Mulitple Devices in Plugin

Hi -
I’m trying my hand at writting my first plugin, but need some help. I have a single device working properly, however when I have mulitple devices and do something on one device, the same action occurs on the other. If someone can provide some quidance for me, that would be great.

Plugin attached. Many Thanks.

RGB_Controller.plugin (4.2 KB)

Are they all failing or is it just Level/Brightness?

I see your URL is incorrect for Level. You are passing in device.DeviceType where you should be using device.Id. That one definitely is not going to work as you expect it will. Your other calls look good.

I would also recommend adding some console.log calls to your onChangeRequest method. They will help you troubleshoot.

Thanks, Bill…I will do some work as you recommended. I had the console.logs in there, but took them out once I got things working…I’ll add back in. One more question: When I add a device, a box pops up asking for device info, but it’s empty. My thoughts were that by putting the params in the onSynchronizeDevices() function, a new device would be populated with those values. The other thing is that if I do Synchronize Devices…a new device is create with all the info in it. I’m probably not understanding the process. Thanks, man.

The 2 are completely unrelated. Right-clicking and selecting “Add Device” is a manual process & you have to type all of the required data. Right-clicking & selecting “Synchronize Devices” calls your “onSyncronizeDevices” function which is an automated process to generate new device objects.

Makes complete sense to me now. Thanks. So, when I’m running HR on my Android device, if I go away from the app then resume, my color wheel value changes to white (center of color wheel). Is there a way to remedy this. I’ve attached the current version of the plugin in case you need to have a look at it.

Thanks again for your help.

RGB_Controller.plugin (6.4 KB)

Device states reset when you resume the app. You need to look at the value you are assigning to the attribute in your onPoll function. You probably aren’t assigning it the correct value there.

I’ve got everything functioning properly thanks to your help. However, when the plugin starts, I will occassionally get “Object reference not set to an instance of an object”…sometime once, sometimes twice. It appears to depend on if the http calls for DevDim and DevColor return in time. After the first onPoll, I don’t get it again, unless I resume the app. Is this an asynchronous behavior? If so, what is best practice for dealing with it? Thanks again.

plugin.Name = "RGB_Controller";
plugin.OnChangeRequest = onChangeRequest;
plugin.OnConnect = onConnect;
plugin.OnDisconnect = onDisconnect;
plugin.OnPoll = onPoll;
plugin.OnSynchronizeDevices = onSynchronizeDevices;
plugin.PollingInterval = 5000;
plugin.DefaultSettings = {
    "Host"  : "",    // this needs to be an IP address and not a hostname or the Roku won't respond
};

var VERSION = "2022-02-13";
var http = new HTTPClient();
var host = plugin.Settings["Host"];
var count = "1";
var ColorTemp = "";
var DeviceSwitchLevel ="";
var DeviceColor = "";
var DevState = "";
var DevDim = "";
var DevColor = "";
var DeviceId = "";
var MyDevice = "";

function onChangeRequest(device, attribute, value) {
	console.log("Change Request......");

	DeviceSwitchLevel = device.Id.slice(-3);
	DeviceColor = device.Id.substring(0, 3);
	console.log("Switch: " + DeviceSwitchLevel + "/ Color: " + DeviceColor);
	device.HoldValue = (value + "00FF");
//	console.log("HoldValue: " + device.HoldValue);

	//GET VERA DEVICE STATES
	//Status
	DevState = (http.get("http://" + host + "/data_request?id=variableget&DeviceNum=" + DeviceColor + "&serviceId=urn:upnp-org:serviceId:SwitchPower1&Variable=Status").data);
//	console.log("Switch Sate Start: " + DevState);
	if (DevState == "1"){
		device.Switch = "On";
	}
	if (DevState == "0"){	
		device.Switch = "Off";
	}
	//Dim Level
	DevDim = (http.get("http://" + host + "/data_request?id=variableget&DeviceNum=" + DeviceSwitchLevel + "&serviceId=urn:upnp-org:serviceId:Dimming1&Variable=LoadLevelStatus").data);	
//	console.log("Dim Level Start: " + DevDim);
	device.Level = DevDim;
	//Color
	DevColor =( http.get("http://" + host + "/data_request?id=variableget&DeviceNum=" +DeviceColor + "&serviceId=urn:upnp-org:serviceId:RGBController1&Variable=Color").data);
//	console.log("Color Start: " + DevColor);
	//SEND COMMANDS TO VERA & HR DEVICES 
	switch(attribute){
	case "Switch":
		switch (value) {
 		    	case "On":
 		             http.post("http://" + host + "/data_request?id=lu_action&output_format=json&DeviceNum=" + DeviceColor + "&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1");
				device.Switch = "On";
			break;
			case "Off":
				http.post("http://" + host + "/data_request?id=lu_action&output_format=json&DeviceNum="+ DeviceColor +"&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=0");
				device.Switch = "Off";
			break;
		}
		break;
	case "Level":
             http.post("http://" + host + "/data_request?id=lu_action&output_format=json&DeviceNum="+ DeviceSwitchLevel +"&serviceId=urn:upnp-org:serviceId:Dimming1&action=SetLoadLevelTarget&newLoadlevelTarget=" + value );
             device.Level = value;
             break;
	case "Color":
		//
		if (count == "1"){
			count ="2";
		} else {
//			console.log("HoldValue before Send: " + device.HoldValue);
			if (device.Switch == "On"){
				device.Color = device.HoldValue.slice(1, -4);;
				http.post("http://" + host + "/data_request?id=lu_action&output_format=json&DeviceNum=" + DeviceColor + "&serviceId=urn:upnp-org:serviceId:RGBController1&action=SetColorTarget&newColorTargetValue=" + device.Color);
			}
		}
		break;
	//NOT FUNCTIONAL
	case  "ColorTemperature":
		device.ColorTemperature = value;
//		console.log("ColorTemperatureVal:  " + value);
		break;
	}
}

function onConnect() {
console.log("Connecting.....");
}

function onDisconnect() {
console.log("Disconnecing.....");
}

function onPoll() {
	console.log("Polling......");
	for (DeviceId in plugin.Devices) {
		MyDevice = plugin.Devices[DeviceId];
//		console.log("Device: " + MyDevice.Name);
 		//PARSE THE 2 DEVICES FROM DEVICE ID
		DeviceSwitchLevel = (MyDevice.Id).slice(-3);
		DeviceColor = (MyDevice.Id).substring(0, 3);
//		console.log("Light & Dim Device:  " + DeviceSwitchLevel + " / Color Device: "+ DeviceColor);

		//GET VERA DEVICE STATES
		//Status
		DevState = (http.get("http://" + host + "/data_request?id=variableget&DeviceNum=" + DeviceColor + "&serviceId=urn:upnp-org:serviceId:SwitchPower1&Variable=Status").data);
		if (DevState == "1"){
			DevState = "On";
		} else {
			DevState = "Off";
		}
		console.log("DevState: " + DevState);
////  BILL - SEEMS THESE 2 HTTP CALLS END UP ASYNC
		//Dim Level
		DevDim = (http.get("http://" + host + "/data_request?id=variableget&DeviceNum=" + DeviceSwitchLevel + "&serviceId=urn:upnp-org:serviceId:Dimming1&Variable=LoadLevelStatus").data);	
		console.log("DevDim: " + DevDim);
		//Color
		DevColor = (http.get("http://" + host + "/data_request?id=variableget&DeviceNum=" +DeviceColor + "&serviceId=urn:upnp-org:serviceId:RGBController1&Variable=Color").data);
		console.log("DevColor: " + DevColor);

		//SET HR DEVICE TO THE CURRENT VERA SETTING
//		console.log("State: " + DevState);
		if (DevState == "On"){ 
		    	MyDevice.Switch = "On";
		    	MyDevice.Level = DevDim;
			MyDevice.Color = DevColor.slice(1, -4);
			MyDevice.HoldValue = MyDevice.Color;
//			console.log("HoldValue on Poll: " + MyDevice.HoldValue);
		}
		if (DevState == "Off") {
			MyDevice.Switch = "Off";
			MyDevice.Color = DevColor.slice(1, -4);
			MyDevice.HoldValue = MyDevice.Color;
//			console.log("HoldValue on Poll: " + MyDevice.HoldValue);
		}	
	}
	console.log("End Polling......");
}

function onSynchronizeDevices() {
	console.log("onSynchronizeDevices called...");

	var newDevice = new Device();

    	newDevice.Id = plugin.Name;
    	newDevice.Name = "New Device";
    	newDevice.DeviceType = "RGB_Controller";
    	newDevice.DisplayName = "RGB_Controller";
    	newDevice.Icon = "Dimmer";
    	newDevice.TileTemplate = "RGBPluginTile.xaml";
    	newDevice.DetailsTemplate = "RGBPluginDetails.xaml";
    	newDevice.Capabilities = [ "Switch", "SwitchLevel", "ColorControl", "ColorTemperature" ];
    	newDevice.Attributes = [HoldValue];

    	plugin.Devices[plugin.Name] = newDevice;

    	console.log("  done syncing");
}

I don’t know. The error might not even be where you think it is. Could be something else entirely. You can try wrapping those calls in a try-catch to verify.

Perhaps the more important question, Vera already has a service for color control that’s supported by Home Remote. You may not even need this custom plugin. Does your device not support the service urn:micasaverde-com:serviceId:Color1?
http://wiki.micasaverde.com/index.php/Luup_UPnP_Variables_and_Actions#Color1

Here’s the thing…On Vera, I’m using the Fibaro RGB Controller V2. When installed on Vera, the Fibaro creates separate devices for State, Dim, Red, Green, Blue & White channels. There is a way on Vera to merge them into one device, but that only works for Fibaro RGB Controller V1. So, the only option for me is to utilize a plugin called RGB Controller which utilizes the following services:

urn:upnp-org:serviceId:RGBController1
urn:upnp-org:serviceId:SwitchPower1
urn:micasaverde-com:serviceId:HaDevice1

This plugin, however, does not have a Dim function builit in.

What my plugin is attempting to do is manage this problem. What I’ve done is make a plugin with 2 Vera device #'s per HR plugin device. To accomplish this, the Id property of each device looks like 466:455 where the 1st number is for the State & Color device and the 2nd is for the Dim device. At the top of onChangeRequest and onPoll, I take the device.Id and parse it out to create the 2 devices with:

DeviceSwitchLevel = device.Id.slice(-3);
DeviceColor = device.Id.substring(0, 3);

I then have to manage those 2 devices throughout the code to get everything working. I know it’s convoluted, but hope it makes sense. If there’s another way, I’m open to it. I didn’t want to ask you to incorporate support for this into the software…you probably have more important things to work on. Thanks.