Comms with NuVo Essentia using IP2SL

I own an aging NuVo Essentia whole house audio system and a user of another forum indicated they were successful at using The Home Remote to control his system (power on/off of the individual zones and source control), but unfortunately provided no further details. I have a GC IP2SL connected to the controller’s RS232 port and I’ve been trying to gleen information from the YouTube videos on setting up the GC device and from other forum entries on how to program the plugin to work with no luck. I can’t even get the debug function to display an data (despite binding the log output to a label on the remote draft), so I’m guessing that the script I’ve entered isn’t even being executed. I’ve attached a link to the
Manual as a reference. I’m just trying to establish that I can communicate with the controller by turning one of the zones off and on, I feel like I can develop the rest of the code once I get a start. I’d attach the plugin I’m using, but I can’t as a new user.

I wrote a very simple plugin to help get you started. It only has the zone 1 power on/off commands implemented. Just import this into a new project & use the default templates to test. Don’t forget to add the NuvoEssentia device to the HomeGroup so you can test with the defaults.

Also, make sure you open the log so you can track what the plugin is doing. There’s a button to open the log on the bottom left corner of the main window.

NuvoEssentia.plugin (1.4 KB)

plugin.Name = "NuvoEssentia";
plugin.OnChangeRequest = onChangeRequest;
plugin.OnConnect = onConnect;
plugin.OnDisconnect = onDisconnect;
plugin.OnPoll = onPoll;
plugin.OnSynchronizeDevices = onSynchronizeDevices;
plugin.PollingInterval = -1;
plugin.DefaultSettings = { "Host": "" };

var socket = new TCPClient();

var commands = {
    "Zone1PowerOn": "*Z1ON",
    "Zone1PowerOff": "*Z1OFF",

function onChangeRequest(device, attribute, value) {
    if (attribute != "MediaCommand")
        throw "Invalid attribute";

    var command = commands[value];
    if (!command)
        throw "Invalid command";

    console.log("sent command : " + command);

function onConnect() {

    var nuvoDevice = plugin.Devices["1"];
    if (nuvoDevice != null) {
        nuvoDevice.SupportedMediaCommands = Object.keys(commands);

    socket.connect(plugin.Settings["Host"], 4999);


function onDisconnect() {

function onPoll() {

function onSynchronizeDevices() {
    var nuvoDevice = new Device();
    nuvoDevice.Id = "1";
    nuvoDevice.DisplayName = "Nuvo Essentia";
    nuvoDevice.Capabilities = ["MediaControl"];
    nuvoDevice.Attributes = [];
    plugin.Devices[nuvoDevice.Id] = nuvoDevice;

Thank you so much for the assistance, Bill. I followed your directions importing the plugin and ran it. No effect on the controller, and I checked the log to see that the commands were being sent. After realizing how to open the log, I tried my original code with the same results. So the validation that I wasn’t crazy was nice. :slight_smile:

Good news though - I ended up getting the code to work though. after a little trial and error. Section 4 of the manual states "Each Command string is STARTED with an ASCII “*” character and terminated by a < CR > and with this being my first foray into this kind of communication, so I’d been literally following my code with < CR>. In my research, I’d seen people use \n and \r and after trying them out - success.

Thanks so much for taking the time to get me started.

Can’t believe I forgot to include that. Yeah, pretty much all serial commands are usually terminated with a carriage return. The socket.send command should look like this:

socket.send(command + "\r");

Yes, my plugin captures that code, thank you.

One last question to permit me to forge ahead. I’ve tweeked the plugin to parse the controller response when a change occurs to identify the affected zone and the status of power. I’d like to update the remote display based on the response, but I don’t know how to create a binding from the plugin so I can set data triggers for it.

Nevermind. I created added a new Attribute to my NuVo device named Zone so I can now populate that from the script and use it for triggers.

1 Like

Another suggestion would be to consider creating a separate Device object for each zone. Kind of like I did in this Monoprice plugin.

MonopriceMultizoneController.hrp (81.4 KB)

I appreciate the suggestion. Always nice to see alternative ways of doing things. For now, I’ve got what I need keeping it as one device since the type of control I’m looking for across all 6 zones is actually pretty limited.

I have a question though. I have the On Connect function send a message to each zone to get a status to update the display, but anytime the system is changed from anywhere, a message is sent out with the status of that zone. So if someone turns a zone on using the physical control pad, currently the app doesn’t see the message because it isn’t look for it. Is there a way to look for these asynchronous messages from the controller? Or is there a way to run code on an interval to get zone status?

Enable polling. Set the PollingInterval to a value greater than zero. A lot of people get confused about how polling works. If the interval is greater than zero it calls onPoll, waits for number of milliseconds specified by PollingInterval, then repeats the loop. Think of that interval more as a “Delay”. So if your PollingInterval is 250 ms it isn’t guaranteed that onPoll will be called every 250 ms. All receive functions are blocking so your onPoll may only run when something is received. Review that plugin I shared with you earlier, it monitors for status changes so the device is always in sync, regardless of where the change is made.

Awesome. I tried that, but forgot about the PollingInternal setting. I figured it would be something easy.

Bill, I’ve got everything working but there is one lingering issue I cannot seem to resolve.

I have individual volume fields bound to Zone#Vol capabilities for the device. When the zone is off, there is no volume, so the fields are set to “” in the plugin. Once the zone is turned on, the volume level is received from the Essentia and set to the zone’s volume capability.These fields work as expected in the simulator, but when loaded to the app, they appear blank (see photo). If I switch to a different page in the app and then switch back, the field displays properly and will continue to display if I toggle the zone power. Any thoughts about why this is happening?

When it is off, set it to 0 instead of an empty string.