plugin.Name = "Isy994i"; plugin.OnChangeRequest = onChangeRequest; plugin.OnConnect = onConnect; plugin.OnDisconnect = onDisconnect; plugin.OnPoll = onPoll; plugin.OnSynchronizeDevices = onSynchronizeDevices; plugin.PollingInterval = 100; plugin.DefaultSettings = { "HostName": "192.168.1.75", "IsyPort": "80", "EncodedUsernPass": "", "UserName": "", "Password": "", "EnableScenes": "Yes", "EnablePrograms": "No", "EnableIntegerVariables": "No", "EnableStateVariables": "No" }; //IMPORTANT! This is not the HostName used. Value actually used is configured in "Properties" pane. // Ver 8_6 By James Knutson 3/28/2021 var VERSION = "8_6"; var debug = true; var LOG_MAX = 5000; // maximum size of the log in characters; set to 0 for unlimited var LOG_TRIM = 500; // when maximum size reached, trim the log plus this much more so not constantly trimming var socket = new TCPClient(); var http = new HTTPClient(); var LOG_ID = "Log"; var leftover = ""; var firstrun = "Yes"; var needSubscribe = true; function getDevice(id) { return plugin.Devices[id]; } function formatJSDate(dt) { return (dt.toLocaleString('en-US', { hour: 'numeric',minute:'numeric', hour12: true })); } function log(message) { console.log(message); } function fixprogramdate(mydate){ var temphour = mydate.substring(7,9); var tempdaytime ="AM"; if(temphour=="00") { temphour="12";} if(temphour.substring(0,1)=="0") { temphour=" "+temphour.substring(1,2);} if(Number(temphour)>12) { var x=Number(temphour)-12; temphour=x.toString(); tempdaytime="PM"; } var tempdate = "20"+mydate.substring(0,2)+"/"+mydate.substring(2,4)+"/"+mydate.substring(4,7)+temphour+mydate.substring(9,12)+" "+ tempdaytime; return dateToText(tempdate); } function dateToText(mydate){ if(mydate!=""){ var myTime=mydate.substring(mydate.indexOf(" ")+1, mydate.length); var myYear =mydate.substring(0, 4); var tempDate = mydate.substring(5, mydate.length); var myMonth = tempDate.substring(0, tempDate.indexOf("/")); var myDay = tempDate.substring(tempDate.indexOf("/")+1, tempDate.indexOf(" ")); var d = new Date(myYear,myMonth-1,myDay); var weekday = new Array(7); weekday[0] = "Sun"; weekday[1] = "Mon"; weekday[2] = "Tue"; weekday[3] = "Wed"; weekday[4] = "Thu"; weekday[5] = "Fri"; weekday[6] = "Sat"; var month = new Array(); month[0] = "Jan"; month[1] = "Feb"; month[2] = "Mar"; month[3] = "April"; month[4] = "May"; month[5] = "June"; month[6] = "July"; month[7] = "Aug"; month[8] = "Sept"; month[9] = "Oct"; month[10] = "Nov"; month[11] = "Dec"; var myWeekday=weekday[d.getDay()]; var myMonthName=month[d.getMonth()]; //You can use any Format you wish. return myWeekday+" "+myMonthName+" "+myDay+" "+myTime; } else return ""; } function updateProgram(curid, ParentId,PEnabled,PStatus,Running, lastRunTime, lastFinishTime, nextScheduledRunTime) { var curDevice = getDevice(curid); try { //log("id:"+curid+" ParentId:"+ParentId+" Enabled:"+PEnabled+" Status:"+PStatus+" Running:"+Running+" LastRun:"+dateToText(lastRunTime)+" LastFinish:"+dateToText(lastFinishTime)+" NextSchedTime:"+dateToText(nextScheduledRunTime)); if(lastRunTime!=""){ curDevice.lastRunTime = dateToText(lastRunTime);} if(lastFinishTime!=""){ curDevice.lastFinishTime = dateToText(lastFinishTime);} if(nextScheduledRunTime!=""){ curDevice.nextScheduledRunTime = dateToText(nextScheduledRunTime);} if(PEnabled!=""){ curDevice.PEnabled = PEnabled;} if(PStatus!=""){ curDevice.PStatus = PStatus;} if(Running!=""){ curDevice.Running = Running;} if(ParentId!=""){curDevice.ParentId=ParentId;} } catch (err) {} } function updatevalue(node, control, value) { //This is where all the data from ISY994i is used to update the state of all ISY994i devices in app //log(node+" "+control+" "+value); var curDevice = getDevice(node); if (firstrun == "No") {log("UpdateValue "+node+" "+control+" "+value);} try { if (node.substring(0, 1)=="n") { switch(control){ case "ST": curDevice.ST= value; if (value > 0) { curDevice.Switch = "On"; } else { curDevice.Switch = "Off"; } break; case "SVOL": curDevice.SVOL= value; break; case "GV0": curDevice.GV0= value; break; case "GV1": curDevice.GV1= value; break; case "GV2": curDevice.GV2= value; break; case "GV3": curDevice.GV3= value; break; case "GV4": curDevice.GV4= value; break; case "GV5": curDevice.GV5= value; break; case "GV6": curDevice.GV6= value; break; case "GV7": curDevice.GV7= value; break case "GV8": curDevice.GV8= value; break; case "GV9": curDevice.GV9= value; break; case "GV10": curDevice.GV10= value; break; } }else { switch (control) { case "ST": switch (curDevice.DeviceType) { case "Thermostat": // log("Insteon Thermostat "+curDevice.DeviceType+" "+control+" "+value); curDevice.Temperature = Math.round(Number(value) / 2); break; case "ZThermostat": // log("ZWave Thermostat "+curDevice.DeviceType+" "+control+" "+value); curDevice.Temperature = Math.round(Number(value)); break; case "Light": if (value > 0) { curDevice.Switch = "On"; curDevice.Level = Math.round(Number(value) / 2.55); } else { curDevice.Switch = "Off"; curDevice.Level = 0; } break; case "Status": if (value > 0) { curDevice.Switch = "On"; } else { curDevice.Switch = "Off"; } break; case "Outlet": if (value > 0) { curDevice.Switch = "On"; } else { curDevice.Switch = "Off"; } break; case "ContactSensor": if (value == "255") { curDevice.Contact = "Open"; } else { curDevice.Contact = "Closed"; } break; case "MotionSensor": if (value == "255") { curDevice.Motion = "Active"; } else { curDevice.Motion = "Inactive"; } break; case "Battery": if (value == "255") { curDevice.Battery = 100; } else { curDevice.Battery = 0; } break; case "PresenceSensor": curDevice.Presence = "NotPresent"; if (value == "255") { curDevice.Presence = "Present"; } if (value == "0") { curDevice.Presence = "Present"; } break; case "WaterSensor": if (node.substring(node.length - 1, node.length) == "1") { if (value == "255") { curDevice.Water = "Dry"; } else { curDevice.Water = "Wet"; } } if (node.substring(node.length - 1, node.length) == "2") { if (value == "255") { curDevice.Water = "Wet"; } else { curDevice.Water = "Dry"; } } break; } break; case "CLIMD": if (value == "0") { curDevice.ThermostatMode = "Off"; } if (value == "1") { curDevice.ThermostatMode = "Heat"; } if (value == "2") { curDevice.ThermostatMode = "Cool"; } if (value == "3") { curDevice.ThermostatMode = "Auto"; } break; case "BATLVL": curDevice.BatteryLevel=value+"%"; break; case "LUMIN": curDevice.Luminance=value+"%"; break; case "CLITEMP": curDevice.Temperature=value.substring(0,2); break; case "GV1": if (value == "0") { curDevice.BatteryPowered = "False"; } if (value == "1") { curDevice.BatteryPowered = "True"; } break; case "CLIHCS": //log("CLIHCS(Calling for): "+value); // 0 off //1 calling for heat //2 calling for cool if (value == "0") { curDevice.Status = "Idle"; } if (value == "1") { curDevice.Status = "Heating"; } if (value == "2") { curDevice.Status = "Cooling"; } break; case "UOM": // mine is 2 break; case "CLIFS": //log("CLIFS(Fan Mode): "+value); curDevice.SupportedThermostatFanModes = ["Auto", "On"]; if (value == "8") { curDevice.ThermostatFanMode = "Auto"; } if (value == "7") { curDevice.ThermostatFanMode = "On"; } break; case "CLIHUM": curDevice.Humidity = Number(value); break; case "CLISPH": if (curDevice.DeviceType == "ZThermostat"){ curDevice.HeatingSetpoint = Math.round(Number(value)); } else { curDevice.HeatingSetpoint = Math.round(Number(value) / 2); } break; case "CLISPC": if (curDevice.DeviceType == "ZThermostat"){ curDevice.CoolingSetpoint = Math.round(Number(value)); } else { curDevice.CoolingSetpoint = Math.round(Number(value) / 2); } break; case "ISYIntegerValue": curDevice.ISYIntegerValue = value; break; case "ISYStateValue": curDevice.ISYStateValue = value; break; case "timeSet": curDevice.timeSet = value; //log("Updated Variable:"+curDevice.name+" Id:"+curDevice.Id+" timeSet:"+value); break; default: //log(node+" "+control+" "+value); } } } catch (err) {} } function onChangeRequest(device, attribute, value) { //Any changes made by user input are sent here to be interpreted and sent to ISY994i var outputNum = device.Id; var devicenode = encodeURI(outputNum); var config = { auth: { username: plugin.Settings["UserName"], password: plugin.Settings["Password"] } } log("ChangeRequest: "+device.DeviceType+" Node: "+devicenode+" Attribute: "+attribute+" Value: "+value); //Send commands to ISY994i base off attribute(type of command) and value(actual change) // check if device is a ISY Node if (outputNum.substring(0, 1)=="n") { if (attribute =="Switch") { if (value =="Off") { var inputCmd = "/rest/nodes/" + devicenode + "/cmd/DFOF";} if (value == "On"){ var inputCmd = "/rest/nodes/" + devicenode + "/cmd/DFON";} http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + inputCmd, config); } else { var inputCmd = "/rest/nodes/" + devicenode + "/cmd/"+value; log(inputCmd); http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + inputCmd, config); }} else { switch (attribute) { case "Switch": if (devicenode.substring(devicenode.length - 1, devicenode.length) == "1") { //These are all your On/Off devices if (value == "On") { var inputCmd = "/rest/nodes/" + devicenode + "/cmd/DON/255"; } else { var inputCmd = "/rest/nodes/" + devicenode + "/cmd/DOF"; } http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + inputCmd, config); } break; case "Level": //These are your Dimmer Devices if (value == 0) { var inputCmd = "/rest/nodes/" + devicenode + "/cmd/DOF"; } else { var inputCmd = "/rest/nodes/" + devicenode + "/cmd/DON/" + Math.round(Number(value * 2.55)); } http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + inputCmd, config); break; case "HeatingSetpoint": //Thermostat adjustment for heat setpoint //log("set heat to:"+value); if (device.DeviceType =="ZThermostat") { var inputCmd = "/rest/nodes/" + devicenode + "/cmd/CLISPH/" + Number(value); } else { var inputCmd = "/rest/nodes/" + devicenode + "/cmd/CLISPH/" + Number(value) * 2; } http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + inputCmd, config); break; case "CoolingSetpoint": //Thermostat adjustment for cool setpoint //log("set cool to:"+value); if (device.DeviceType =="ZThermostat") { var inputCmd = "/rest/nodes/" + devicenode + "/cmd/CLISPC/" + Number(value); } else { var inputCmd = "/rest/nodes/" + devicenode + "/cmd/CLISPC/" + Number(value) * 2; } http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + inputCmd, config); break; case "ThermostatMode": //Thermostat adjustment for new mode if (value == "Cool") { value = "2"; } if (value == "Heat") { value = "1"; } if (value == "Off") { value = "0"; } if (value == "Auto") { value = "3"; } if (value == "Eco") { value = "5"; } var inputCmd = "/rest/nodes/" + devicenode + "/cmd/CLIMD/" + value; http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + inputCmd, config); break; case "ThermostatFanMode": if (value == "Auto") { value = "8"; } if (value == "On") { value = "7"; } if (value == "7" || value == "8" ) { var inputCmd = "/rest/nodes/" + devicenode + "/cmd/CLIFS/" + value; http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + inputCmd, config); } break; case "Scene": //These are all your ISY scenes if you enabled them if (device.Switch == "On") { var inputCmd = "/rest/nodes/" + devicenode + "/cmd/DOF"; device.Switch = "Off"; } else { var inputCmd = "/rest/nodes/" + devicenode + "/cmd/DON/255"; device.Switch = "On"; } http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + inputCmd, config); break; case "PCommand": //This is for controlling ISY Programs var inputCmd = "/rest/programs/" + outputNum + "/" + value; http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + inputCmd, config); break; case "ISYIntegerValue": //This is for setting ISY Integer variables outputNum = outputNum.substring(10, outputNum.length); var inputCmd = "/rest/vars/set/1/" + outputNum + "/" + value; http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + inputCmd, config); break; case "ISYStateValue": //This is for setting ISY State variables outputNum = outputNum.substring(8, outputNum.length); var inputCmd = "/rest/vars/set/2/" + outputNum + "/" + value; http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + inputCmd, config); break; case "updateVariables": //This is for controlling ISY Programs if (plugin.Settings["EnableIntegerVariables"] == "Yes" || plugin.Settings["EnableIntegerVariables"] == "YES") { updateIntegerVariables(); } if (plugin.Settings["EnableStateVariables"] == "Yes" || plugin.Settings["EnableStateVariables"] == "YES") { updateStateVariables(); } break; case "updatePrograms": updatePrograms(); break; case "updateDevices": updateDevices(); break; case "updateWeather": updateWeather(); break; case "customCommand": //This is for controlling ISY Programs var inputCmd = value; http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + inputCmd, config); break; default: if (attribute == "Log") { if (value == "ClearLog") { var logDevice = getDevice("Log"); logDevice.Log = "Isy Feedback\n"; } } //log("Command:"+attribute+" "+value); }} return; } function fixdate(isydate){ if(isydate!=""){ var isyYear =isydate.substring(0, 4); var isyMonth =isydate.substring(4, 6); var isyDay =isydate.substring(6,8); var isyHour =isydate.substring(9,11); var isyMinutes =isydate.substring(12, 14); var isydaytime="AM"; if(isyHour=="12"){isydaytime="PM";} if(Number(isyHour)>12) { var x=Number(isyHour)-12; isyHour=x.toString(); isydaytime="PM"; } var d = new Date(isyYear,isyMonth-1,isyDay); var weekday = new Array(7); weekday[0] = "Sun"; weekday[1] = "Mon"; weekday[2] = "Tue"; weekday[3] = "Wed"; weekday[4] = "Thu"; weekday[5] = "Fri"; weekday[6] = "Sat"; var month = new Array(); month[0] = "Jan"; month[1] = "Feb"; month[2] = "Mar"; month[3] = "April"; month[4] = "May"; month[5] = "June"; month[6] = "July"; month[7] = "Aug"; month[8] = "Sept"; month[9] = "Oct"; month[10] = "Nov"; month[11] = "Dec"; var isyWeekday=weekday[d.getDay()]; var isyMonthName=month[d.getMonth()]; //You can use any Format you wish. return isyWeekday+" "+isyMonthName+" "+isyDay+" "+isyHour+":"+isyMinutes+" "+isydaytime; } else return ""; } function updateIntegerVariables() { //log("Updating Integer Variables"); var config = { auth: { username: plugin.Settings["UserName"], password: plugin.Settings["Password"] } } var r = http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + "/rest/vars/get/1", config); //get list of all integer variables var data = r.data; //00020190818 10:55:10 try{ var varElement = XML.parse(data); varElement.elements.forEach(function (node) { var varid = node.attributes.id; var varvalue = "", varts = ""; node.elements.forEach(function (element) { switch (element.name) { case "val": varvalue = element.text; break; case "ts": varts = element.text; break; default: } }); //log(" ISYInteger:" + varid+" ISYIntegerValue:"+varvalue+" time set:"+varts); updatevalue("ISYInteger" + varid, "ISYIntegerValue", varvalue); updatevalue("ISYInteger" + varid, "timeSet", fixdate(varts)); }); } catch(err) { log("No Integer Variables!"); } } function updateStateVariables() { //log("Updating State Variables"); var config = { auth: { username: plugin.Settings["UserName"], password: plugin.Settings["Password"] } } //Update State variable value var r = http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + "/rest/vars/get/2", config); //get list of all State variables var data = r.data; //log(data); try{ //00020190818 10:55:10 var varElement = XML.parse(data); varElement.elements.forEach(function (node) { var varid = node.attributes.id; var varvalue = "", varts = ""; node.elements.forEach(function (element) { switch (element.name) { case "val": varvalue = element.text; break; case "ts": varts = element.text; break; default: } }); //log(" ISYState:" + varid+" ISYStateValue:"+varvalue+" time set:"+varts); updatevalue("ISYState" + varid, "ISYStateValue", varvalue); updatevalue("ISYState" + varid, "timeSet", fixdate(varts)); }); } catch(err) { log("No State Variables!"); } } function updatePrograms() { //log("Updating Programs"); var config = { auth: { username: plugin.Settings["UserName"], password: plugin.Settings["Password"] } } var r = http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + "/rest/programs?subfolders=true", config); //get list of all programs var data = r.data; //Outside Lights On2020/01/09 4:36:45 PM2020/01/09 4:36:45 PM2020/01/10 4:37:44 PM var programElement = XML.parse(data); programElement.elements.forEach(function (program) { var PStatus = program.attributes.status; var curid = program.attributes.id; var PEnabled = program.attributes.enabled; var Running = program.attributes.running; var ParentId = program.attributes.parentId; var lastRunTime = "", lastFinishTime = "", nextScheduledRunTime = "",name = ""; program.elements.forEach(function (element) { switch (element.name) { case "name": name = element.text; break; case "lastRunTime": lastRunTime = element.text; break; case "lastFinishTime": lastFinishTime = element.text; break; case "nextScheduledRunTime": nextScheduledRunTime = element.text; break; default: } }); //log("id:"+curid+" ParentId:"+ParentId+" Enabled:"+PEnabled+" Status:"+PStatus+" Running:"+Running+" LastRun:"+dateToText(lastRunTime)+" LastFinish:"+dateToText(lastFinishTime)+" NextSchedTime:"+dateToText(nextScheduledRunTime)); updateProgram(curid, ParentId,PEnabled,PStatus,Running, lastRunTime, lastFinishTime, nextScheduledRunTime); }); } function subscribe(){ //This sends the subscribe command to the ISY994i so any changes are automaticaly sent to this socket socket.send("POST /services HTTP/1.1\r\n"); socket.send("Authorization: Basic " + plugin.Settings["EncodedUsernPass"] + "\r\n"); socket.send("Content-Length: 192\r\n"); socket.send("Content-Type: text/xml; charset=\"utf-8\"\r\n"); socket.send("SOAPACTION:\"urn:udi-com:service:X_Insteon_Lighting_Service:1#Subscribe\"\r\n"); socket.send("\r\n"); socket.send("\r\n"); socket.send("REUSE_SOCKETinfinite\r\n"); needSubscribe = false; } function onConnect() { //log("Connecting!"); firstrun = "Yes"; socket.connect(plugin.Settings["HostName"], plugin.Settings["IsyPort"]); needSubscribe = true; } function onDisconnect() { //log("Disconnecting!"); socket.close(); } function onPoll() { if(needSubscribe){subscribe();} //Get new data from ISY994i var dataReceived = socket.receive(); var data = dataReceived; //log("****************************************************************New Data Received*******************************************************"); //log(data); //log("*****************************************************************End Data Received*******************************************************"); //log(leftover); if (leftover > "") { data = leftover + data; } //Update current values from ISY while (data.length > 1) { if (data.indexOf(" -1 && data.indexOf("") > -1) { leftover = ""; var curevent = data.substring(data.indexOf("")+8); //log(curevent); if (firstrun == "No") { log(curevent);} var xmlObj = XML.parse(curevent); //_160120200118 10:57:51 //_103200118 10:57:52200118 10:57:5231 var seqnum = xmlObj.attributes.seqnum; var control = "", action = "", node = ""; xmlObj.elements.forEach(function (element) { switch (element.name) { case "control": control = element.text; break; case "action": action = element.text; break; case "node": node = element.text; break; case "eventInfo": if(control=="_1"){ if(action=="6"){ varelement=element; } //Save XML for more parsing to get Variable info 0120200118 10:57:51 if(action=="0"){ progelement=element; } // Save XML for more parsing to get Program info 3200118 10:57:52200118 10:57:5231 } break; default: } }); // log("Control:"+control+" Action"+action); if (control == "_0" && action == "120") { var dt = new Date(); var today=formatJSDate(dt); try { var myISY = getDevice("IsyRequest"); myISY.lastPing=today; //log("Ping received: "+today); } catch (err) {} } if ((control == "_23" && action == "1") || (control == "_11" && action == "100")) { if (firstrun == "Yes") { //log(curevent); log("End of Device Update"); if (plugin.Settings["EnableIntegerVariables"] == "Yes" || plugin.Settings["EnableIntegerVariables"] == "YES") { //log("Updating Integer Variables"); updateIntegerVariables(); } if (plugin.Settings["EnableStateVariables"] == "Yes" || plugin.Settings["EnableStateVariables"] == "YES") { //log("Updating State Variables"); updateStateVariables(); } if (plugin.Settings["EnablePrograms"] == "Yes" || plugin.Settings["EnablePrograms"] == "YES") { //log("Updating Programs"); updatePrograms(); } firstrun = "No"; } } if(control=="_1" && action=="6"){ //update Variable //0120200118 10:57:51 if (varelement.elements.length > 0) { varelement.elements.forEach(function (eventinfo) { if(eventinfo.name=="var"){ var curid = eventinfo.attributes.id; var curtype = eventinfo.attributes.type; var curval = "",curts = ""; eventinfo.elements.forEach(function (curvariable) { switch (curvariable.name) { case "val": curval = curvariable.text; break; case "ts": curts = curvariable.text; break; default: } }); // log("Variable ID: "+curid+" Type: "+curtype+" Value: "+curval+" Time Set: "+curts); if(curtype=="2"){ if (plugin.Settings["EnableStateVariables"] == "Yes" || plugin.Settings["EnableStateVariables"] == "YES") { updatevalue("ISYState" + curid, "ISYStateValue",curval); updatevalue("ISYState" + curid, "timeSet", fixdate(curts)); } } if(curtype=="1"){ if (plugin.Settings["EnableIntegerVariables"] == "Yes" || plugin.Settings["EnableIntegerVariables"] == "YES") { updatevalue("ISYInteger" + curid, "ISYIntegerValue", curval); updatevalue("ISYInteger" + curid, "timeSet", fixdate(curts)); } } } }); } } if(control=="_1" && action=="0"){ //update Program //3200118 10:57:52200118 10:57:5231 if (plugin.Settings["EnablePrograms"] == "Yes" || plugin.Settings["EnablePrograms"] == "YES") { if (progelement.elements.length > 0) { var lastRunTime = "",lastFinishTime="",curid="",nextScheduledRunTime="",PEnabled=""; progelement.elements.forEach(function (eventinfo) { switch (eventinfo.name) { case "r": lastRunTime = eventinfo.text; break; case "f": lastFinishTime = eventinfo.text; break; case "on": PEnabled="true"; break; case "off": PEnabled="false"; break; case "id": curid = eventinfo.text; break; case "nsr": nextScheduledRunTime = eventinfo.text; break; default: } }); //log("Program Id: "+curid+" Enabled: "+PEnabled+" R: "+lastRunTime+" F: "+lastFinishTime+" NSR: "+nextScheduledRunTime); updateProgram("00"+curid, "",PEnabled,"","", lastRunTime, lastFinishTime, nextScheduledRunTime); } } } if (node!= "" && control!= "RR" && control!= "OL") { //Take new data from ISY994i and send it to the update function to update app variables updatevalue(node, control, action); } data = data.substring(data.indexOf("/Event>") + 7, data.length); } else { if (data.indexOf(" -1 || data.indexOf("") > -1) { //Valid Leftover data! //log(data); leftover = data; } //Garbage Leftover Data data = ""; } //End of Getting values from ISY } //Update Integer variable value } function onSynchronizeDevices() { //This is ran from in the HomeRemote Designer and used to import all your ISY994i devices var config = { auth: { username: plugin.Settings["UserName"], password: plugin.Settings["Password"] } } // var pluginDevices = []; //this deletes all current devices var pluginDevice = new Device(); pluginDevice.Id = "Log"; pluginDevice.DisplayName = "Log"; pluginDevice.Icon = "PC"; pluginDevice.DeviceType = ""; pluginDevice.TileTemplate = ""; pluginDevice.DetailsTemplate = ""; pluginDevice.Capabilities = [""]; pluginDevice.Attributes = ["Log"]; plugin.Devices[pluginDevice.Id] = pluginDevice; var pluginDevice = new Device(); pluginDevice.Id = "IsyRequest"; pluginDevice.DisplayName = "IsyRequest"; pluginDevice.Icon = "PC"; pluginDevice.DeviceType = ""; pluginDevice.TileTemplate = ""; pluginDevice.DetailsTemplate = ""; pluginDevice.Capabilities = [""]; pluginDevice.Attributes = ["lastPing","updateVariables", "updatePrograms", "updateDevices", "customCommand"]; plugin.Devices[pluginDevice.Id] = pluginDevice; //Finished creating log device for testing var r = http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + "/rest/nodes", config); //get list of all devices var data = r.data; //log(data); var nodesElement = XML.parse(data); try { var curadd = "",nodename= "",nodetype = ""; nodesElement.elements.forEach(function (node) { //log(node.name); if (node.name!="root") { node.elements.forEach(function (element) { switch (element.name) { case "name": nodename = element.text; break; case "address": curadd = element.text; break; case "type": nodetype = element.text; break; default: } }); if (node.name=="group") { if (plugin.Settings["EnableScenes"] == "Yes" || plugin.Settings["EnableScenes"] == "YES") { var pluginDevice = new Device(); pluginDevice.Id = curadd; //pluginDevice.Name = "Scene_" + nodename; pluginDevice.DisplayName = "Scene_" +nodename; pluginDevice.Icon = "Sun"; pluginDevice.DeviceType = "Scene"; pluginDevice.TileTemplate = "SceneTile.xaml"; pluginDevice.DetailsTemplate = ""; pluginDevice.Capabilities = ["Switch"]; pluginDevice.Attributes = ["Scene"]; plugin.Devices[pluginDevice.Id] = pluginDevice; } } else if (curadd.substring(0, 1)=="n") { if (plugin.Settings["EnableNodes"] == "Yes" || plugin.Settings["EnableNodes"] == "YES") { var pluginDevice = new Device(); pluginDevice.Id = curadd; pluginDevice.DisplayName = "Node_" +nodename; pluginDevice.Icon = "Sensor"; pluginDevice.DeviceType = "Node"; pluginDevice.TileTemplate = "ISYNodeTile.xaml"; pluginDevice.DetailsTemplate = "ISYNodeDetails.xaml"; pluginDevice.Capabilities = ["Switch"]; pluginDevice.Attributes = ["NCommand","ST","SVOL","GV0","GV1","GV2","GV3","GV4","GV5","GV6","GV7","GV8","GV9","GV10"]; plugin.Devices[pluginDevice.Id] = pluginDevice; } } else { var basicnodetype = nodetype.substring(0, 2); /* This is a list of all ISY994i device types I have found. Included this incase you want to break down into more specific types for your GUI 1.0. =LampLinc Dimmable 1.14 =Dual Band LampLinc Dimmable 1.1. =SwitchLinc Dimmer 1.12 =KeypadLinc Dimmer 8 Buttons 1.25 =SwitchLinc Dimmer W/Beeper 1.27 =KeypadLinc Dimmer 6 Buttons 1.28 =KeypadLinc Dimmer 8 Buttons 1.32 =Dual Band SwitchLinc Dimmer 1.33 =Insteon OutletLinc Dimmer 1.46 =FanLinc Dimmable Light/Fan (Off/Low/Medium/High) 1.65 =KeypadLinc Dimmer 8 Buttons 1.66 =KeypadLinc Dimmer 5 Buttons 1.9. =KeypadLinc Dimmer 2.13 =ToggleLinc On/Off 2.15 =KeypadLinc Relay On/Off 2.20 =In-LineLinc Relay W/ Sense On/Off 2.22 =Icon Relay Switch On/Off 2.26 =ToggleLinc Relay On/Off 2.28 =SwitchLinc Relay On/Off 2.42 =Dual Band SwitchLinc On/Off 2.44 =Dual Band KeypadLinc Relay On/Off 2.47 =Micro On/Off 2.55 =Plugin On/Off Module 2.57 =Dual OutletLinc Top/Bottom On/Off 2.8. =OutletLinc On/Off 2.9. =ApplianceLinc 4.16 =Power Switch Zwave On/Off 4.17 =Zwave Dimmer 4.64 =Zwave Door Locks 4.7. =Zwave Motion Detector 5.11 =Thermostat 7.0. =I/OLink GarageDoor Sensor Opened/Closed, Contacts Open/Close 7.9. =SynchroLinc Status of PLugged Devices On/Off 15.6 =MorningLinc DoorLock Lock/Unlock 16.1. =Insteon Motion Sensor Status On/Off 16.2 =TriggerLinc Door/Window Sensor Open/Close 16.8 =Water Sensor 16.17 =Hidden Door Sensor 16.22 =Motion Sensor II */ switch (basicnodetype) { case "1.": // All Dimmable Devices // MultiButton Device-Only main button is Controllable, other buttons can only be controlled by scenes! if (curadd.substring(curadd.length - 1, curadd.length) == "1") { pluginDevice = new Device(); pluginDevice.Id = curadd; //pluginDevice.Name = nodename; pluginDevice.DisplayName = nodename; pluginDevice.Icon = "Lightbulb"; pluginDevice.DeviceType = "Light"; pluginDevice.TileTemplate = "LightTile.xaml"; pluginDevice.DetailsTemplate = "LightDetails.xaml"; pluginDevice.Capabilities = ["Switch", "SwitchLevel"]; pluginDevice.Attributes = []; plugin.Devices[pluginDevice.Id] = pluginDevice; } else { // This is the secondary buttons of multi button devices. No commands can be sent only used for status. pluginDevice = new Device(); pluginDevice.Id = curadd; pluginDevice.DisplayName = nodename; pluginDevice.Icon = "Lightbulb"; pluginDevice.DeviceType = "Status"; pluginDevice.TileTemplate = "ISYStatusTile.xaml"; pluginDevice.DetailsTemplate = ""; pluginDevice.Capabilities = ["Switch"]; pluginDevice.Attributes = []; plugin.Devices[pluginDevice.Id] = pluginDevice; } break; case "2.": //All On/Off switch types if (curadd.substring(curadd.length - 1, curadd.length) == "1") { pluginDevice = new Device(); pluginDevice.Id = curadd; //pluginDevice.Name = nodename; pluginDevice.DisplayName = nodename; if (nodetype.substring(0, 3) == "2.5" || nodetype.substring(0, 3) == "2.8") { // This is for switched Outlets pluginDevice.Icon = "Plug"; pluginDevice.DeviceType = "Outlet"; pluginDevice.TileTemplate = "OutletTile.xaml"; pluginDevice.DetailsTemplate = ""; pluginDevice.Capabilities = ["Switch"]; } else { pluginDevice.Icon = "Lightbulb"; pluginDevice.DeviceType = "Light"; pluginDevice.TileTemplate = "LightTile.xaml"; pluginDevice.DetailsTemplate = "LightDetails.xaml"; pluginDevice.Capabilities = ["Switch", "SwitchLevel"]; } pluginDevice.Attributes = []; plugin.Devices[pluginDevice.Id] = pluginDevice; } else { // This is the secondary buttons of multi button devices. No commands can be sent only used for status. pluginDevice = new Device(); pluginDevice.Id = curadd; pluginDevice.DisplayName = nodename; pluginDevice.Icon = "Lightbulb"; pluginDevice.DeviceType = "Status"; pluginDevice.TileTemplate = "ISYStatusTile.xaml"; pluginDevice.DetailsTemplate = ""; pluginDevice.Capabilities = ["Switch"]; pluginDevice.Attributes = []; plugin.Devices[pluginDevice.Id] = pluginDevice; } break; case "4.": //All ZWave //Added by CA to accommodate ZWave T'stat (4.8.x.x) and Motion Detector (4.7.x.x) pluginDevice = new Device(); pluginDevice.Id = curadd; pluginDevice.DisplayName = nodename; if (nodetype.substring(0, 4) == "4.8.") { pluginDevice.Icon = "Thermometer"; pluginDevice.DeviceType = "ZThermostat"; pluginDevice.TileTemplate = "ThermostatTile.xaml"; pluginDevice.DetailsTemplate = ""; pluginDevice.Capabilities = ["TemperatureMeasurement", "ThermostatCoolingSetpoint", "ThermostatFanMode", "ThermostatHeatingSetpoint", "ThermostatMode", "RelativeHumidityMeasurement"]; pluginDevice.Attributes = ["Status"]; } plugin.Devices[pluginDevice.Id] = pluginDevice; if (nodetype.substring(0, 4) == "4.7.") { pluginDevice.Icon = "Sensor"; pluginDevice.TileTemplate = "MotionSensorTile.xaml"; pluginDevice.DetailsTemplate = ""; pluginDevice.DeviceType = "MotionSensor"; pluginDevice.Capabilities = ["MotionSensor"]; pluginDevice.Attributes = ["Status"]; } break; case "5.": //Thermostats //var nodeflag = nodeinfo.substring(nodeinfo.indexOf("")); // if (nodeflag != "0") { pluginDevice = new Device(); pluginDevice.Id = curadd; //pluginDevice.Name = nodename; pluginDevice.DisplayName = nodename; pluginDevice.Icon = "Thermometer"; pluginDevice.DeviceType = "Thermostat"; pluginDevice.TileTemplate = "ThermostatTile.xaml"; pluginDevice.DetailsTemplate = "ThermostatDetails.xaml"; pluginDevice.Capabilities = ["TemperatureMeasurement", "ThermostatCoolingSetpoint", "ThermostatFanMode", "ThermostatHeatingSetpoint", "ThermostatMode", "RelativeHumidityMeasurement"]; pluginDevice.Attributes = ["Status"]; plugin.Devices[pluginDevice.Id] = pluginDevice; //} break; case "7.": //Sensor status of Plug Device if (nodetype.substring(0, 4) == "7.9.") { pluginDevice = new Device(); pluginDevice.Id = curadd; //pluginDevice.Name = nodetype + nodename; pluginDevice.DisplayName = nodename; pluginDevice.Icon = "Sensor"; pluginDevice.DeviceType = "ContactSensor"; pluginDevice.TileTemplate = "ContactSensorTile.xaml"; pluginDevice.DetailsTemplate = ""; pluginDevice.Capabilities = ["ContactSensor"]; pluginDevice.Attributes = []; plugin.Devices[pluginDevice.Id] = pluginDevice; } //Sensor status with Controll On/Off Garage control device------Work in Progress if (nodetype.substring(0, 4) == "7.0.") { pluginDevice = new Device(); pluginDevice.Id = curadd; //pluginDevice.Name = nodetype + nodename; pluginDevice.DisplayName = nodename; pluginDevice.Icon = "Home"; pluginDevice.DeviceType = "GarageDoor"; pluginDevice.TileTemplate = "GarageDoorTile.xaml"; pluginDevice.DetailsTemplate = "GarageDoorDetails.xaml"; pluginDevice.Capabilities = ["DoorControl"]; pluginDevice.Attributes = ["Status"]; plugin.Devices[pluginDevice.Id] = pluginDevice; } break; case "16": //All Sensors //Node ends in 1-Main Sensor, 2-Secodary(wet), 3-Low battery, 4-Heartbeat pluginDevice = new Device(); pluginDevice.TileTemplate = "ContactSensorTile.xaml"; pluginDevice.DeviceType = "ContactSensor"; pluginDevice.Icon = "Sensor"; pluginDevice.Capabilities = ["ContactSensor"]; pluginDevice.Attributes = []; if (nodetype.substring(0, 4) == "16.8") { pluginDevice.TileTemplate = "WaterSensorTile.xaml"; pluginDevice.DeviceType = "WaterSensor"; pluginDevice.Icon = "Drop"; pluginDevice.Capabilities = ["WaterSensor"]; } if (nodetype.substring(0, 5) == "16.1.") { pluginDevice.TileTemplate = "MotionSensorTile.xaml"; pluginDevice.DeviceType = "MotionSensor"; pluginDevice.Icon = "Sensor"; pluginDevice.Capabilities = ["MotionSensor"]; pluginDevice.Attributes = ["Status"]; } if (nodetype.substring(0, 5) == "16.22") { pluginDevice.TileTemplate = "MotionSensorTile.xaml"; pluginDevice.DeviceType = "MotionSensor"; pluginDevice.Icon = "Sensor"; pluginDevice.Capabilities = ["MotionSensor"]; pluginDevice.Attributes = ["Status", "BatteryPowered", "BatteryLevel", "Temperature", "Luminance"]; } pluginDevice.Id = curadd; //pluginDevice.Name = nodename; pluginDevice.DisplayName = nodename; pluginDevice.Icon = "Sensor"; pluginDevice.DetailsTemplate = ""; if (curadd.substring(curadd.length - 1, curadd.length) == "3") { pluginDevice.TileTemplate = ""; pluginDevice.DeviceType = "LowBattery"; pluginDevice.Icon = "BatteryUnknown"; pluginDevice.Capabilities = ["Battery"]; } if (curadd.substring(curadd.length - 1, curadd.length) == "4") { pluginDevice.TileTemplate = ""; pluginDevice.DeviceType = "Heartbeat"; pluginDevice.Icon = "Heart"; pluginDevice.Capabilities = ["PresenceSensor"]; } plugin.Devices[pluginDevice.Id] = pluginDevice; break; default: var pluginDevice = new Device(); pluginDevice.Id = curadd; pluginDevice.DisplayName = "Unknown_" +nodename; pluginDevice.Icon = "More"; pluginDevice.DeviceType = ""; pluginDevice.TileTemplate = ""; pluginDevice.DetailsTemplate = ""; pluginDevice.Capabilities = ["Switch"]; pluginDevice.Attributes = []; plugin.Devices[pluginDevice.Id] = pluginDevice; } } } }); } catch (err) { var pluginDevice = new Device(); pluginDevice.Id = curadd; pluginDevice.DisplayName = "Error_" +nodename; pluginDevice.Icon = "More"; pluginDevice.DeviceType = ""; pluginDevice.TileTemplate = ""; pluginDevice.DetailsTemplate = ""; pluginDevice.Capabilities = ["Switch"]; pluginDevice.Attributes = []; plugin.Devices[pluginDevice.Id] = pluginDevice; } //Check if Programs are enabled if so begin importing if (plugin.Settings["EnablePrograms"] == "Yes" || plugin.Settings["EnablePrograms"] == "YES") { var r = http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + "/rest/programs?subfolders=true", config); //get list of all scenes var data = r.data; var r = http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + "/rest/programs?subfolders=true", config); //get list of all scenes var data = r.data; var programElement = XML.parse(data); programElement.elements.forEach(function (program) { var curid = program.attributes.id; var IsFolder = program.attributes.folder; var programname = ""; program.elements.forEach(function (element) { switch (element.name) { case "name": programname = element.text; break; default: } }); var pluginDevice = new Device(); pluginDevice.Id = curid; //pluginDevice.Name = "Program_" + programname; if (IsFolder== "true") { pluginDevice.DisplayName = "ProgramFolder_" +programname; pluginDevice.Icon = "PC"; pluginDevice.DeviceType = "ISYProgramFolder"; pluginDevice.TileTemplate = "ISYProgramFolderTile.xaml"; pluginDevice.DetailsTemplate = ""; pluginDevice.Capabilities = []; pluginDevice.Attributes = ["PCommand","PStatus","ParentId","PFolder", "PEnabled","Running", "lastRunTime", "lastFinishTime", "nextScheduledRunTime"]; // Set this to any of these options run, runThen, runElse, stop, enable, disable, enableRunAtStartup, disableRunAtStartup } else { pluginDevice.DisplayName = "Program_" +programname; pluginDevice.Icon = "PC"; pluginDevice.DeviceType = "ISYProgram"; pluginDevice.TileTemplate = "ISYProgramTile.xaml"; pluginDevice.DetailsTemplate = ""; pluginDevice.Capabilities = []; pluginDevice.Attributes = ["PCommand","PStatus","ParentId","PFolder", "PEnabled","Running", "lastRunTime", "lastFinishTime", "nextScheduledRunTime"]; // Set this to any of these options run, runThen, runElse, stop, enable, disable, enableRunAtStartup, disableRunAtStartup } plugin.Devices[pluginDevice.Id] = pluginDevice; }); } /* var r = http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + "/rest/nodes/folders", config); //get list of all Lighting Folders //get list of all folders var data = r.data; while (data.length > 1) { if (data.indexOf(" -1 && data.indexOf("/folder>") > -1) { var curfolder = data.substring(data.indexOf("") + 8); var curfoladd = curfolder.substring(curfolder.indexOf("
") + 9, curfolder.indexOf("
")); var foldername = curfolder.substring(curfolder.indexOf("") + 6, curfolder.indexOf("")); var pluginDevice = new Device(); pluginDevice.Id = curfoladd; //pluginDevice.Name = "Folder_" + foldername; pluginDevice.DisplayName = "Folder_" + foldername; pluginDevice.Icon = "folder"; pluginDevice.DeviceType = "Folder"; pluginDevice.TileTemplate = "FolderTile.xaml"; pluginDevice.DetailsTemplate = "FolderDetailsTile.xaml"; pluginDevice.Capabilities = []; pluginDevice.Attributes = [""]; plugin.Devices[pluginDevice.Id] = pluginDevice; data = data.substring(data.indexOf("/folder>") + 8, data.length); } else { data = ""; } } */ //Check if Variables are enabled if so begin importing integer variables if (plugin.Settings["EnableIntegerVariables"] == "Yes" || plugin.Settings["EnableIntegerVariables"] == "YES") { var r = http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + "/rest/vars/definitions/1", config); //get list of all integer variables var data = r.data; var varElement = XML.parse(data); if (varElement.elements!=null) { varElement.elements.forEach(function (node) { var curid = node.attributes.id; var varname = node.attributes.name; var pluginDevice = new Device(); pluginDevice.Id = "ISYInteger" + curid; //pluginDevice.Name = "ISYInteger_" + varname; pluginDevice.DisplayName = "ISYInteger_" +varname; pluginDevice.Icon = "Globe"; pluginDevice.DeviceType = "ISYIntegerVariable"; pluginDevice.TileTemplate = "ISYIntegerVariableTile.xaml"; pluginDevice.DetailsTemplate = ""; pluginDevice.Capabilities = []; pluginDevice.Attributes = ["ISYIntegerValue", "timeSet"]; plugin.Devices[pluginDevice.Id] = pluginDevice; }); } else {log("No Integer Variables!");} } if (plugin.Settings["EnableStateVariables"] == "Yes" || plugin.Settings["EnableStateVariables"] == "YES") { var r = http.get("http://" + plugin.Settings["HostName"] + ":" + plugin.Settings["IsyPort"] + "/rest/vars/definitions/2", config); //get list of all state(0 or 1) variables var data = r.data; var varElement = XML.parse(data); if (varElement.elements!=null) { varElement.elements.forEach(function (node) { var curid = node.attributes.id; var varname = node.attributes.name; var pluginDevice = new Device(); pluginDevice.Id = "ISYState" + curid; //pluginDevice.Name = "ISYState_" + varname; pluginDevice.DisplayName = "ISYState_" + varname; pluginDevice.Icon = "Globe"; pluginDevice.DeviceType = "ISYStateVariable"; pluginDevice.TileTemplate = "ISYStateVariableTile.xaml"; pluginDevice.DetailsTemplate = ""; pluginDevice.Capabilities = []; pluginDevice.Attributes = ["ISYStateValue", "timeSet"]; plugin.Devices[pluginDevice.Id] = pluginDevice; }); } else {log("No State Variables!");} } // plugin.Devices = pluginDevices; //add all new devices to the plugin }