- Location:
- /trunk
- Files:
-
- 2 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
/trunk/J_CurrentCostEnviR1.js
r20 r30 2 2 function getChildApplianceName(deviceId, a) 3 3 { 4 var matches = j sonp.ud.devices.findAll(function(d) {4 var matches = jQuery.grep(jsonp.ud.devices, function(d) { 5 5 return d.altid == "Appliance" + a && d.id_parent == deviceId 6 6 } ); … … 9 9 } 10 10 11 function getFormula(deviceId) 12 { 13 var formula = get_device_state(deviceId, "urn:futzle-com:serviceId:CurrentCostEnviR1", "Formula", 0); 14 if (formula == undefined) formula = ""; 15 if (/^[0-9]/.test(formula)) formula = "+" + formula; 16 return formula; 17 } 18 19 function setFormula(deviceId, a, operation) 20 { 21 var formula = getFormula(deviceId); 22 formula = formula.replace("-" + a, "").replace("+" + a, ""); 23 if (operation == "add") 24 { 25 formula += "+" + a; 26 } 27 else if (operation == "subtract") 28 { 29 formula += "-" + a; 30 } 31 set_device_state(deviceId, "urn:futzle-com:serviceId:CurrentCostEnviR1", "Formula", formula, 0); 32 } 33 34 var entityMap = { 35 "&": "&", 36 "<": "<", 37 ">": ">", 38 '"': '"', 39 "'": ''', 40 "/": '/' 41 }; 42 43 function escapeHtml(string) { 44 return String(string).replace(/[&<>"'\/]/g, function (s) { 45 return entityMap[s]; 46 }); 47 } 48 11 49 /* Entry point for "Configuration" tab. 12 50 Provide GUI for editing global and per-appliance settings. */ 13 51 function setup(deviceId) 14 52 { 53 var applianceTypes = [ "Unknown", "Electricity (Power)", "Electricity (Pulse)" ]; 54 15 55 var htmlResult = ""; 16 56 htmlResult += "<div>"; … … 22 62 var childTemperature = get_device_state(deviceId, "urn:futzle-com:serviceId:CurrentCostEnviR1", "ChildTemperature", 0); 23 63 if (childTemperature == undefined) childTemperature = 0; 24 htmlResult += "<td><input type='checkbox' id='childTemperature' " + (childTemperature == "1" ? "checked='checked' " : "") + "onclick='set_device_state(" + deviceId + ", \"urn:futzle-com:serviceId:CurrentCostEnviR1\", \"ChildTemperature\", $F(\"childTemperature\") ? 1 : 0, 0)'/></td>";64 htmlResult += "<td><input type='checkbox' id='childTemperature' " + (childTemperature == "1" ? "checked='checked' " : "") + "onclick='set_device_state(" + deviceId + ", \"urn:futzle-com:serviceId:CurrentCostEnviR1\", \"ChildTemperature\", jQuery(this).is(\":checked\") ? 1 : 0, 0)'/></td>"; 25 65 26 66 htmlResult += "</tr><tr>"; … … 30 70 var applianceDetect = get_device_state(deviceId, "urn:futzle-com:serviceId:CurrentCostEnviR1", "ApplianceAutoDetect", 0); 31 71 if (applianceDetect == undefined) applianceDetect = 1; 32 htmlResult += "<td><input type='checkbox' id='applianceDetect' " + (applianceDetect == "1" ? "checked='checked' " : "") + "onclick='set_device_state(" + deviceId + ", \"urn:futzle-com:serviceId:CurrentCostEnviR1\", \"ApplianceAutoDetect\", $F(\"applianceDetect\") ? 1 : 0, 0)'/></td>";72 htmlResult += "<td><input type='checkbox' id='applianceDetect' " + (applianceDetect == "1" ? "checked='checked' " : "") + "onclick='set_device_state(" + deviceId + ", \"urn:futzle-com:serviceId:CurrentCostEnviR1\", \"ApplianceAutoDetect\", jQuery(this).is(\":checked\") ? 1 : 0, 0)'/></td>"; 33 73 34 74 htmlResult += "</tr>"; … … 38 78 htmlResult += "<table border='0' padding='0' width='100%'>"; 39 79 htmlResult += "<tr>"; 40 htmlResult += "<th>Appliance</th><th> ID</th><th>Name</th><th>Separate Phases</th><th>Main power</th>";80 htmlResult += "<th>Appliance</th><th>Type</th><th>ID</th><th>Name</th><th>Separate Phases</th><th>Main power</th>"; 41 81 htmlResult += "</tr>"; 42 82 43 var formula = get_device_state(deviceId, "urn:futzle-com:serviceId:CurrentCostEnviR1", "Formula", 0); 44 if (formula == undefined) formula = ""; 45 if (/^[0-9]/.test(formula)) formula = "+" + formula; 83 var formula = getFormula(deviceId); 46 84 var a; 47 85 for (a = 0; a < 10; a++) … … 49 87 var applianceId = get_device_state(deviceId, "urn:futzle-com:serviceId:CurrentCostEnviR1", "Appliance" + a, 0); 50 88 if (applianceId == undefined || applianceId == "" || applianceId == "0") continue; 89 var applianceType = get_device_state(deviceId, "urn:futzle-com:serviceId:CurrentCostEnviR1", "Appliance" + a + "Type", 0); 90 if (applianceType == undefined) { applianceType = 1; } 91 applianceType = applianceType - 0; 51 92 htmlResult += "<tr>"; 52 93 // Appliance number 53 94 htmlResult += "<td>" + a + (a == 0 ? " (whole house)" : "") + "</td>"; 95 // Appliance type 96 htmlResult += "<td>" + applianceTypes[applianceType] + "</td>"; 54 97 // Appliance unique identifier 55 htmlResult += "<td>" + applianceId.escapeHTML() + "</td>";98 htmlResult += "<td>" + escapeHtml(applianceId) + "</td>"; 56 99 // Appliance name as set by the user 57 100 var applianceName = getChildApplianceName(deviceId, a); 58 101 htmlResult += "<td>" + applianceName + "</td>"; 59 // Create additional child devices for each phase? 60 var applianceThreePhase = get_device_state(deviceId, "urn:futzle-com:serviceId:CurrentCostEnviR1", "Appliance" + a + "ThreePhase", 0); 61 if (applianceThreePhase == undefined) applianceThreePhase = 0; 62 htmlResult += "<td><input type='checkbox' " + (applianceThreePhase == "1" ? "checked='checked' " : "") + "/></td>"; 63 // How does the child's energy contribute to the main device's energy (+ or -)? 64 htmlResult += "<td>" 65 htmlResult += "<select>"; 66 htmlResult += "<option value='none' " + (formula.indexOf("+" + a) == -1 && formula.indexOf("-" + a) == -1 ? "selected='selected' " : "") + ">None</option>"; 67 htmlResult += "<option value='add' " + (formula.indexOf("+" + a) != -1 ? "selected='selected' " : "") + ">Add</option>"; 68 htmlResult += "<option value='subtract' " + (formula.indexOf("-" + a) != -1 ? "selected='selected' " : "") + ">Subtract</option>"; 69 htmlResult += "</select>"; 70 htmlResult += "</td>"; 71 htmlResult += "</tr>"; 102 if (applianceType == 1) 103 { 104 // Create additional child devices for each phase? 105 var applianceThreePhase = get_device_state(deviceId, "urn:futzle-com:serviceId:CurrentCostEnviR1", "Appliance" + a + "ThreePhase", 0); 106 if (applianceThreePhase == undefined) applianceThreePhase = 0; 107 htmlResult += "<td><input type='checkbox' id='appliance" + a + "ThreePhase' " + (applianceThreePhase == "1" ? "checked='checked' " : "") + "onclick='set_device_state(" + deviceId + ", \"urn:futzle-com:serviceId:CurrentCostEnviR1\", \"Appliance" + a + "ThreePhase\", jQuery(\"#appliance" + a + "ThreePhase\").is(\":checked\") ? 1 : 0, 0)'/></td>"; 108 // How does the child's energy contribute to the main device's energy (+ or -)? 109 htmlResult += "<td>" 110 htmlResult += "<select id='formula" + a + "' onchange='setFormula(" + deviceId + "," + a + ", jQuery(\"#formula" + a + "\").val())'>"; 111 htmlResult += "<option value='none' " + (formula.indexOf("+" + a) == -1 && formula.indexOf("-" + a) == -1 ? "selected='selected' " : "") + ">None</option>"; 112 htmlResult += "<option value='add' " + (formula.indexOf("+" + a) != -1 ? "selected='selected' " : "") + ">Add</option>"; 113 htmlResult += "<option value='subtract' " + (formula.indexOf("-" + a) != -1 ? "selected='selected' " : "") + ">Subtract</option>"; 114 htmlResult += "</select>"; 115 htmlResult += "</td>"; 116 htmlResult += "</tr>"; 117 } 118 else 119 { 120 // No phase or arithmetic for pulse meters. 121 htmlResult += "<td /><td />"; 122 } 72 123 } 73 124 -
/trunk/J_SerialConnection.js
r20 r30 27 27 * If set and of the form "1.1.1.1", this means that the TCP port is a "default" 28 28 * value, which may mean something useful or not, depending on the plugin. 29 * Use luup.io.open() or signal an error. 29 * If your plugin's implementation uses <ioPort> then Luup may open a 30 * connection for you anyway. Use luup.io.open(), do nothing, or signal an error. 30 31 * Other forms are reserved (for IPv6 or named hosts). 31 32 * - If neither is set, return false from the startup to signal an error. … … 43 44 + numberPattern65535 + ")$"); 44 45 46 var entityMap = { 47 "&": "&", 48 "<": "<", 49 ">": ">", 50 '"': '"', 51 "'": ''', 52 "/": '/' 53 }; 54 55 function escapeHtml(string) { 56 return String(string).replace(/[&<>"'\/]/g, function (s) { 57 return entityMap[s]; 58 }); 59 } 60 45 61 function getConnectionType(deviceId) 46 62 { 47 63 var ioDevice = get_device_state(deviceId, "urn:micasaverde-com:serviceId:HaDevice1", "IODevice", 0); 48 var ipDevice = j sonp.get_device_by_id(deviceId);64 var ipDevice = jQuery.grep(jsonp.ud.devices, function(o, i) { return o.id == deviceId; })[0]; 49 65 if (ioDevice != undefined && ioDevice != "") { return "ioDevice"; } 50 66 if (ipDevice != undefined) … … 61 77 function getSerialDevices(deviceId) 62 78 { 63 return j sonp.ud.devices.findAll(function(d) {79 return jQuery.grep(jsonp.ud.devices, function(d) { 64 80 return d.device_type == "urn:micasaverde-org:device:SerialPort:1"; 65 81 } ); … … 71 87 function getDeviceOfSerialDevice(serialDeviceId) 72 88 { 73 var matches = j sonp.ud.devices.findAll(function(d) {74 return d.states.findAll(function(state) {89 var matches = jQuery.grep(jsonp.ud.devices, function(d) { 90 return jQuery.grep(d.states, function(state) { 75 91 return state.service == "urn:micasaverde-com:serviceId:HaDevice1" && 76 92 state.variable == "IODevice" && … … 85 101 function getIpAddress(deviceId) 86 102 { 87 var ipDevice = jsonp.get_device_by_id(deviceId); 103 var ipDevice = jQuery.grep(jsonp.ud.devices, function(o, i) { return o.id == deviceId; })[0]; 104 if (ipDevice == undefined) { return undefined; } 88 105 var ip = ipDevice.ip; 89 if (ip == undefined) { return undefined; }90 106 if (ip == "") { return undefined; } 91 107 if (ipv4Pattern.test(ip)) { return ip; } … … 98 114 function getTcpPort(deviceId) 99 115 { 100 var ipDevice = jsonp.get_device_by_id(deviceId); 116 var ipDevice = jQuery.grep(jsonp.ud.devices, function(o, i) { return o.id == deviceId; })[0]; 117 if (ipDevice == undefined) { return undefined; } 101 118 var ip = ipDevice.ip; 102 if (ip == undefined) { return undefined; }103 119 if (ip == "") { return undefined; } 104 120 if (ipv4Pattern.test(ip)) { return undefined; } … … 109 125 110 126 /* Mess with the DOM to disable parts of the UI. */ 111 function enableSelectedOption(deviceId, currentConnectionType) 112 { 113 $('serialDevice').disable(); 114 $('ipaddress').disable(); 115 $('tcpport').disable(); 127 function enableSelectedOption(deviceId, currentConnectionType, ownedSerialDeviceId) 128 { 129 jQuery('#serialDevice').get(0).disabled = true; 130 jQuery('#serialSpeed').get(0).disabled = true; 131 jQuery('#serialData').get(0).disabled = true; 132 jQuery('#serialParity').get(0).disabled = true; 133 jQuery('#serialStop').get(0).disabled = true; 134 jQuery('#ipaddress').get(0).disabled = true; 135 jQuery('#tcpport').get(0).disabled = true; 116 136 117 137 if (currentConnectionType == "ioDevice") 118 138 { 119 $('serialDevice').enable(); 139 jQuery('#serialDevice').get(0).disabled = false; 140 if (ownedSerialDeviceId != undefined && ownedSerialDeviceId != "") 141 { 142 var serialSpeed = jsonp.get_lu_device_variable_value(ownedSerialDeviceId, "urn:micasaverde-org:serviceId:SerialPort1", "baud", 0); 143 if (serialSpeed == undefined || serialSpeed == "") serialSpeed = "9600"; // Default 144 jQuery('#serialSpeed').val(serialSpeed).get(0).disabled = false; 145 var serialData = jsonp.get_lu_device_variable_value(ownedSerialDeviceId, "urn:micasaverde-org:serviceId:SerialPort1", "databits", 0); 146 if (serialData == undefined || serialData == "") serialData = "8"; // Default 147 jQuery('#serialData').val(serialData).get(0).disabled = false; 148 var serialParity = jsonp.get_lu_device_variable_value(ownedSerialDeviceId, "urn:micasaverde-org:serviceId:SerialPort1", "parity", 0); 149 if (serialParity == undefined || serialParity == "") serialParity = "none"; // Default 150 jQuery('#serialParity').val(serialParity).get(0).disabled = false; 151 var serialStop = jsonp.get_lu_device_variable_value(ownedSerialDeviceId, "urn:micasaverde-org:serviceId:SerialPort1", "stopbits", 0); 152 if (serialStop == undefined || serialStop == "") serialStop = "1"; // Default 153 jQuery('#serialStop').val(serialStop).get(0).disabled = false; 154 } 120 155 } 121 156 if (currentConnectionType == "ip") 122 157 { 123 $('ipaddress').enable();124 $('tcpport').enable();158 jQuery('#ipaddress').get(0).disabled = false; 159 jQuery('#tcpport').get(0).disabled = false; 125 160 } 126 161 } … … 131 166 function setSerialDevice(deviceId, serialDeviceId) 132 167 { 133 enableSelectedOption(deviceId,"ioDevice");134 168 set_device_state(deviceId, "urn:micasaverde-com:serviceId:HaDevice1", "IODevice", serialDeviceId, 0); 135 jsonp.get_device_by_id(deviceId).ip = ""; 169 var ipDevice = jQuery.grep(jsonp.ud.devices, function(o, i) { return o.id == deviceId; })[0]; 170 ipDevice.ip = ""; 171 enableSelectedOption(deviceId, "ioDevice", serialDeviceId); 172 } 173 174 /* Set the IODevice serial properties (speed, parity, etc.). */ 175 function setSerialProperties(deviceId, serialDeviceId) 176 { 177 set_device_state(serialDeviceId, "urn:micasaverde-org:serviceId:SerialPort1", "baud", jQuery('#serialSpeed').val(), 0); 178 set_device_state(serialDeviceId, "urn:micasaverde-org:serviceId:SerialPort1", "databits", jQuery('#serialData').val(), 0); 179 set_device_state(serialDeviceId, "urn:micasaverde-org:serviceId:SerialPort1", "parity", jQuery('#serialParity').val(), 0); 180 set_device_state(serialDeviceId, "urn:micasaverde-org:serviceId:SerialPort1", "stopbits", jQuery('#serialStop').val(), 0); 136 181 } 137 182 … … 141 186 function setIPDevice(deviceId, ipAddress, tcpPort) 142 187 { 143 enableSelectedOption(deviceId,"ip");144 if (tcpPort == undefined || tcpPort == "")145 {146 jsonp.get_device_by_id(deviceId).ip = ipAddress;188 if (jQuery('#tcpport').get(0).disabled || tcpPort == undefined || tcpPort == "") 189 { 190 var ipDevice = jQuery.grep(jsonp.ud.devices, function(o, i) { return o.id == deviceId; })[0]; 191 ipDevice.ip = ""; 147 192 } 148 193 else 149 194 { 150 jsonp.get_device_by_id(deviceId).ip = ipAddress + ":" + tcpPort; 195 var ipDevice = jQuery.grep(jsonp.ud.devices, function(o, i) { return o.id == deviceId; })[0]; 196 ipDevice.ip = ipAddress + ":" + tcpPort; 151 197 } 152 198 set_device_state(deviceId, "urn:micasaverde-com:serviceId:HaDevice1", "IODevice", "", 0); 199 enableSelectedOption(deviceId, "ip", undefined); 200 } 201 202 /* Fetch the named file over Ajax and execute function 203 f() on the resulting XML. */ 204 function withUpnpFileName(deviceId, filename, f) 205 { 206 new Ajax.Request("../port_3480/" + filename, { 207 onSuccess : function(response) { 208 return f(response.responseXML); 209 } 210 } 211 ); 212 } 213 214 /* Fetch the Implementation file (I_*.xml) and 215 execute the function f() on the resulting XML. */ 216 function withImplementationFile(deviceId, f) 217 { 218 var device = jQuery.grep(jsonp.ud.devices, function(o, i) { return o.id == deviceId; })[0]; 219 if (device.impl_file != "") 220 { 221 return withUpnpFileName(deviceId, device.impl_file, f); 222 } 223 else 224 { 225 return withUpnpFileName(deviceId, device.device_file, function(doc) { 226 var implementationElement = doc.querySelector("root > device > implementationList > implementationFile"); 227 if (implementationElement != undefined) 228 { 229 var implementationFile = implementationElement.textContent.trim(); 230 return withUpnpFileName(deviceId, implementationFile, f); 231 } 232 }); 233 } 153 234 } 154 235 … … 165 246 htmlResult += "<p><input type='radio' name='connectionType' value='serial' "; 166 247 if (currentConnectionType == "ioDevice") htmlResult += "checked='checked' "; 167 htmlResult += "onclick='setSerialDevice(" + deviceId + ", $F(serialDevice))'/>Serial port or IPSerial device ";168 htmlResult += "<select id='serialDevice' onchange='setSerialDevice(" + deviceId + ", $F(serialDevice))'>";248 htmlResult += "onclick='setSerialDevice(" + deviceId + ",jQuery(\"#serialDevice\").val())'/>Serial port or IPSerial device "; 249 htmlResult += "<select id='serialDevice' onchange='setSerialDevice(" + deviceId + ",jQuery(\"#serialDevice\").val())'>"; 169 250 htmlResult += "<option value=''>None</option>"; 170 251 var serialDevices = getSerialDevices(deviceId); 171 htmlResult += serialDevices.inject("", function(htmlResult, d) { 252 var ownedSerialDeviceId; 253 jQuery.each(serialDevices, function(i, d) { 172 254 htmlResult += "<option value='" + d.id + "'"; 173 255 var deviceOwner = getDeviceOfSerialDevice(d.id); … … 178 260 // This is my serial device. 179 261 htmlResult += " selected='selected'"; 262 ownedSerialDeviceId = d.id; 180 263 } 181 264 else … … 185 268 } 186 269 } 187 htmlResult += ">" + d.name.escapeHTML();270 htmlResult += ">" + escapeHtml(d.name); 188 271 // Tell user who owns this device (if it's not us). 189 272 if (deviceOwner != undefined && deviceOwner.id != deviceId) 190 273 { 191 htmlResult += " [" + deviceOwner.name.escapeHTML() + "]";274 htmlResult += " [" + escapeHtml(deviceOwner.name) + "]"; 192 275 } 193 276 htmlResult += "</option>"; 194 return htmlResult;195 277 }); 196 278 htmlResult += "</select>"; 197 279 htmlResult += "</p>"; 280 htmlResult += "<p style='margin-left: 4em;'>"; 281 htmlResult += "Speed <select id='serialSpeed' onchange='setSerialProperties(" + deviceId + ",jQuery(\"#serialDevice\").val())'><option value='300'>300</option><option value='1200'>1200</option><option value='2400'>2400</option><option value='4800'>4800</option><option value='9600'>9600</option><option value='19200'>19200</option><option value='38400'>38400</option><option value='57600'>57600</option><option value='115200'>115200</option><option value='230400'>230400</option></select>"; 282 htmlResult += " Data bits <select id='serialData' onchange='setSerialProperties(" + deviceId + ",jQuery(\"#serialDevice\").val())'><option value='7'>7</option><option value='8'>8</option></select>"; 283 htmlResult += " Parity <select id='serialParity' onchange='setSerialProperties(" + deviceId + ",jQuery(\"#serialDevice\").val())'><option value='none'>None</option><option value='even'>Even</option><option value='odd'>Odd</option></select>"; 284 htmlResult += " Stop bits <select id='serialStop' onchange='setSerialProperties(" + deviceId + ",jQuery(\"#serialDevice\").val())'><option value='0'>0</option><option value='1'>1</option><option value='2'>2</option></select>"; 285 htmlResult += "</p>"; 198 286 199 287 /* Serial proxy over Ethernet. */ 200 288 htmlResult += "<p><input type='radio' name='connectionType' value='ip' "; 201 289 if (currentConnectionType == "ip") htmlResult += "checked='checked' "; 202 htmlResult += "onclick='setIPDevice(" + deviceId + ", $F(ipaddress),$F(tcpport))'/>Serial proxy on another machine ";290 htmlResult += "onclick='setIPDevice(" + deviceId + ",jQuery(\"#ipaddress\").val(),jQuery(\"#tcpport\").val())'/>Serial proxy on another machine "; 203 291 var ipAddress = getIpAddress(deviceId); 204 292 if (ipAddress == undefined) { ipAddress = ""; } 205 htmlResult += "<p style='margin-left: 4em;'>IP address <input id='ipaddress' type='text' size='16' value='" + ipAddress.escapeHTML() + "' onchange='setIPDevice(" + deviceId + ",$F(ipaddress),$F(tcpport))' />";293 htmlResult += "<p style='margin-left: 4em;'>IP address <input id='ipaddress' type='text' size='16' value='" + escapeHtml(ipAddress) + "' onchange='setIPDevice(" + deviceId + ",jQuery(\"#ipaddress\").val(),jQuery(\"#tcpport\").val())' />"; 206 294 var tcpPort = getTcpPort(deviceId); 207 295 if (tcpPort == undefined) { tcpPort = ""; } 208 htmlResult += " TCP port <input id='tcpport' type='text' size='6' value='" + tcpPort.escapeHTML() + "' onchange='setIPDevice(" + deviceId + ",$F(ipaddress),$F(tcpport))' /></p> ";296 htmlResult += " TCP port <input id='tcpport' type='text' size='6' value='" + escapeHtml(tcpPort) + "' onchange='setIPDevice(" + deviceId + ",jQuery(\"#ipaddress\").val(),jQuery(\"#tcpport\").val())' /></p> "; 209 297 htmlResult += "</p>"; 210 298 … … 213 301 set_panel_html(htmlResult); 214 302 215 enableSelectedOption(deviceId, currentConnectionType); 216 } 303 enableSelectedOption(deviceId, currentConnectionType, ownedSerialDeviceId); 304 305 /* See if this device has an <ioPort> element. 306 If so, don't let user edit the TCP port. */ 307 withImplementationFile(deviceId, function(doc) { 308 var ioPortElement = doc.querySelector("implementation > settings > ioPort"); 309 if (ioPortElement != undefined) 310 { 311 var ioPortHardcoded = ioPortElement.textContent.trim(); 312 jQuery('#tcpport').val(ioPortHardcoded).get(0).disabled = true; 313 } 314 }); 315 } -
/trunk/L_CurrentCostEnviR1.lua
r20 r30 9 9 -- Cache of child devices, maps appliance number to MiOS device ID. 10 10 CHILD_DEVICE = { } 11 CHILD_DEVICE_TYPE = { } 11 12 CHILD_DEVICE_THREEPHASE = { ["0"] = { }, ["1"] = { }, ["2"] = { }, ["3"] = { }, ["4"] = { }, ["5"] = { }, ["6"] = { }, ["7"] = { }, ["8"] = { }, ["9"] = { } } 12 13 -- Child device for temperature, if configured. … … 60 61 if ((luup.variable_get(SERVICE_ID, "Appliance" .. tostring(child), lul_device) or "0") ~= "0") then 61 62 CHILD_DEVICE_COUNT = CHILD_DEVICE_COUNT + 1 62 luup.chdev.append(lul_device, childDevices, "Appliance" .. tostring(child), 63 "Appliance " .. child, "urn:schemas-futzle-com:device:CurrentCostEnvirAppliance:1", 64 "D_CurrentCostEnviRAppliance1.xml", "", "", false) 63 -- What type of device is it? 64 local deviceType = luup.variable_get(SERVICE_ID, "Appliance" .. tostring(child) .. "Type", lul_device) or "1" 65 if (deviceType == "1") then 66 -- Electricity power (clamp, individual monitor). 67 luup.chdev.append(lul_device, childDevices, "Appliance" .. tostring(child), 68 "Appliance " .. child, "urn:schemas-futzle-com:device:CurrentCostEnviRAppliance:1", 69 "D_CurrentCostEnviRAppliance1.xml", "", "", false) 70 elseif (deviceType == "2") then 71 -- Impulse meter (OptiSmart). 72 luup.chdev.append(lul_device, childDevices, "Appliance" .. tostring(child), 73 "Appliance " .. child .. " (pulse)", "urn:schemas-futzle-com:device:CurrentCostEnviRAppliancePulse:1", 74 "D_CurrentCostEnviRAppliancePulse1.xml", "", "", false) 75 end 65 76 end 66 77 if ((luup.variable_get(SERVICE_ID, "Appliance" .. tostring(child) .. "ThreePhase", lul_device) or "0") ~= "0") then 67 78 for phase = 1, 3 do 68 79 luup.chdev.append(lul_device, childDevices, "Appliance" .. tostring(child) .. "Phase" .. tostring(phase), 69 "Appliance " .. child .. " phase " .. phase, "urn:schemas-futzle-com:device:CurrentCostEnvi rAppliancePhase:1",80 "Appliance " .. child .. " phase " .. phase, "urn:schemas-futzle-com:device:CurrentCostEnviRAppliancePhase:1", 70 81 "D_CurrentCostEnviRAppliancePhase1.xml", "", "", false) 71 82 end … … 106 117 AUTO_DETECT = luup.variable_get(SERVICE_ID, "ApplianceAutoDetect", lul_device) 107 118 if (AUTO_DETECT == nil) then 119 AUTO_DETECT = "1" 108 120 luup.variable_set(SERVICE_ID, "ApplianceAutoDetect", "1", lul_device) 109 121 end 122 123 -- Set the device category. 21 is "power meter". 124 luup.attr_set("category_num", 21, lul_device) 110 125 111 126 -- Cache the child device ids, and populate the history variables. … … 114 129 if (v.device_num_parent == lul_device and v.id == "Appliance" .. sensor) then 115 130 if (DEBUG) then luup.log("Child deviceId for Appliance " .. sensor .. " is " .. k) end 116 CHILD_DEVICE[tostring(sensor)] = k 117 TWOHOURLY_HISTORY[tostring(sensor)] = deserializeHistory(luup.variable_get(SERVICE_ID, "TwoHourlyHistory", k) or "") 118 DAILY_HISTORY[tostring(sensor)] = deserializeHistory(luup.variable_get(SERVICE_ID, "DailyHistory", k) or "") 119 MONTHLY_HISTORY[tostring(sensor)] = deserializeHistory(luup.variable_get(SERVICE_ID, "MonthlyHistory", k) or "") 131 -- What type of device is it? 132 local deviceType = luup.variable_get(SERVICE_ID, "Appliance" .. tostring(child) .. "Type", lul_device) or "1" 133 if (deviceType == "1") then 134 -- Electricity power (clamp, individual monitor). 135 -- Set the device category. 21 is "power meter". 136 luup.attr_set("category_num", 21, k) 137 CHILD_DEVICE[tostring(sensor)] = k 138 CHILD_DEVICE_TYPE[tostring(sensor)] = "1" 139 TWOHOURLY_HISTORY[tostring(sensor)] = deserializeHistory(luup.variable_get(SERVICE_ID, "TwoHourlyHistory", k) or "") 140 DAILY_HISTORY[tostring(sensor)] = deserializeHistory(luup.variable_get(SERVICE_ID, "DailyHistory", k) or "") 141 MONTHLY_HISTORY[tostring(sensor)] = deserializeHistory(luup.variable_get(SERVICE_ID, "MonthlyHistory", k) or "") 142 elseif (deviceType == "2") then 143 -- Impulse meter (OptiSmart). 144 -- Set the device category. 21 is "power meter". 145 luup.attr_set("category_num", 21, k) 146 CHILD_DEVICE[tostring(sensor)] = k 147 CHILD_DEVICE_TYPE[tostring(sensor)] = "2" 148 end 120 149 end 121 150 for phase = 1, 3 do 122 151 if (v.device_num_parent == lul_device and v.id == "Appliance" .. sensor .. "Phase" .. phase) then 123 152 if (DEBUG) then luup.log("Child deviceId for Appliance " .. sensor .. " Phase " .. phase .. " is " .. k) end 153 -- Set the device category. 21 is "power meter". 154 luup.attr_set("category_num", 21, k) 124 155 CHILD_DEVICE_THREEPHASE[tostring(sensor)][tostring(phase)] = k 125 156 end … … 127 158 end 128 159 if (v.device_num_parent == lul_device and v.id == "Temperature") then 160 -- Set the device category. 17 is "temperature". 161 luup.attr_set("category_num", 17, k) 129 162 CHILD_TEMPERATURE_DEVICE = k 130 163 end … … 174 207 end 175 208 209 -- Set a variable only if it is different. 210 function set_if_different(serviceId, variable, value, deviceId) 211 if (luup.variable_get(serviceId, variable, deviceId) ~= tostring(value)) then 212 luup.variable_set(serviceId, variable, value, deviceId) 213 end 214 end 215 176 216 -- 177 217 -- Process elements in the <msg> part of a packet. … … 181 221 function processMsgSrc(context, lul_device, source) 182 222 context.version = source 183 luup.variable_set(SERVICE_ID, "Version", source, lul_device)223 set_if_different(SERVICE_ID, "Version", source, lul_device) 184 224 return context 185 225 end … … 188 228 function processMsgUid(context, lul_device, uid) 189 229 context.uid = uid 190 luup.variable_set(SERVICE_ID, "UID", uid, lul_device)230 set_if_different(SERVICE_ID, "UID", uid, lul_device) 191 231 return context 192 232 end … … 195 235 function processMsgDsb(context, lul_device, dsb) 196 236 context.dsb = dsb 197 luup.variable_set(SERVICE_ID, "DaysSinceBirth", tonumber(dsb), lul_device)237 set_if_different(SERVICE_ID, "DaysSinceBirth", tonumber(dsb), lul_device) 198 238 return context 199 239 end … … 202 242 function processMsgTime(context, lul_device, time) 203 243 context.time = time 204 luup.variable_set(SERVICE_ID, "Time", time, lul_device)244 set_if_different(SERVICE_ID, "Time", time, lul_device) 205 245 return context 206 246 end … … 329 369 local childDevice = CHILD_DEVICE[context.sensor] 330 370 if (childDevice ~= nil) then 331 luup.variable_set(ENERGY_SERVICE_ID, "Watts", context.watts, childDevice)332 luup.variable_set(SERVICE_ID, "DaysSinceBirth", context.dsb, childDevice)333 luup.variable_set(SERVICE_ID, "Time", context.time, childDevice)334 luup.variable_set(TEMPERATURE_SERVICE_ID, "CurrentTemperature", context.tmpr, childDevice)335 if (context.version) then luup.variable_set(SERVICE_ID, "Version", context.version, childDevice) end336 if (context.uid) then luup.variable_set(SERVICE_ID, "UID", context.uid, childDevice) end371 set_if_different(ENERGY_SERVICE_ID, "Watts", context.watts, childDevice) 372 set_if_different(SERVICE_ID, "DaysSinceBirth", context.dsb, childDevice) 373 set_if_different(SERVICE_ID, "Time", context.time, childDevice) 374 set_if_different(TEMPERATURE_SERVICE_ID, "CurrentTemperature", context.tmpr, childDevice) 375 if (context.version) then set_if_different(SERVICE_ID, "Version", context.version, childDevice) end 376 if (context.uid) then set_if_different(SERVICE_ID, "UID", context.uid, childDevice) end 337 377 end 338 378 … … 341 381 local childDevicePhase = CHILD_DEVICE_THREEPHASE[context.sensor][tostring(phase)] 342 382 if (childDevicePhase ~= nil) then 343 luup.variable_set(ENERGY_SERVICE_ID, "Watts", context.phase[tostring(phase)], childDevicePhase) 344 luup.variable_set(SERVICE_ID, "DaysSinceBirth", context.dsb, childDevicePhase) 345 luup.variable_set(SERVICE_ID, "Time", context.time, childDevicePhase) 346 luup.variable_set(TEMPERATURE_SERVICE_ID, "CurrentTemperature", context.tmpr, childDevicePhase) 347 if (context.version) then luup.variable_set(SERVICE_ID, "Version", context.version, childDevicePhase) end 348 if (context.uid) then luup.variable_set(SERVICE_ID, "UID", context.uid, childDevicePhase) end 349 end 350 end 351 352 -- Note this appliance number, if permitted. 353 if (AUTO_DETECT or "0" ~= "0") then 354 local previousId = luup.variable_get(SERVICE_ID, "Appliance" .. context.sensor, lul_device) 355 if (previousId == nil or context.id ~= previousId) then 356 luup.variable_set(SERVICE_ID, "Appliance" .. context.sensor, context.id, lul_device) 357 CHILD_DEVICE_COUNT = CHILD_DEVICE_COUNT + 1 358 -- Did we start with zero appliances? Tell user we found another. 359 if (CHILD_DEVICE_DISCOVERY_HANDLE ~= nil) then 360 luup.task("Discovered " .. CHILD_DEVICE_COUNT .. (CHILD_DEVICE_COUNT == 1 and " appliance" or " appliances") .. ". Reload when all appliances are discovered", 1, string.format("%s[%d]", luup.devices[lul_device].description, lul_device), CHILD_DEVICE_DISCOVERY_HANDLE) 361 end 383 set_if_different(ENERGY_SERVICE_ID, "Watts", context.phase[tostring(phase)], childDevicePhase) 384 set_if_different(SERVICE_ID, "DaysSinceBirth", context.dsb, childDevicePhase) 385 set_if_different(SERVICE_ID, "Time", context.time, childDevicePhase) 386 set_if_different(TEMPERATURE_SERVICE_ID, "CurrentTemperature", context.tmpr, childDevicePhase) 387 if (context.version) then set_if_different(SERVICE_ID, "Version", context.version, childDevicePhase) end 388 if (context.uid) then set_if_different(SERVICE_ID, "UID", context.uid, childDevicePhase) end 362 389 end 363 390 end … … 365 392 -- Compute parent device's reading, using its custom formula. 366 393 APPLIANCE_POWER[context.sensor] = context.watts 367 luup.variable_set(ENERGY_SERVICE_ID, "Watts", calculateFormula(APPLIANCE_POWER), lul_device) 394 set_if_different(ENERGY_SERVICE_ID, "Watts", calculateFormula(APPLIANCE_POWER), lul_device) 395 elseif (context.packetType == "realtime" and context.type == "2") then 396 -- Impulse (OptiSmart) meter data. 397 398 -- Log the child device's impulse (if there is a child device). 399 local childDevice = CHILD_DEVICE[context.sensor] 400 if (childDevice ~= nil) then 401 set_if_different(ENERGY_SERVICE_ID, "Pulse", context.imp, childDevice) 402 local zero = luup.variable_get(SERVICE_ID, "PulseZero", childDevice) or "0" 403 set_if_different(SERVICE_ID, "ImpulsePerUnit", context.ipu, childDevice) 404 set_if_different(ENERGY_SERVICE_ID, "KWH", (tonumber(context.imp) - tonumber(zero))/tonumber(context.ipu), childDevice) 405 set_if_different(SERVICE_ID, "DaysSinceBirth", context.dsb, childDevice) 406 set_if_different(SERVICE_ID, "Time", context.time, childDevice) 407 set_if_different(TEMPERATURE_SERVICE_ID, "CurrentTemperature", context.tmpr, childDevice) 408 if (context.version) then set_if_different(SERVICE_ID, "Version", context.version, childDevice) end 409 if (context.uid) then set_if_different(SERVICE_ID, "UID", context.uid, childDevice) end 410 end 411 end 412 413 -- Note this appliance number, if permitted. 414 if (AUTO_DETECT ~= "0") then 415 local previousId = luup.variable_get(SERVICE_ID, "Appliance" .. context.sensor, lul_device) 416 if (previousId == nil or context.id ~= previousId) then 417 set_if_different(SERVICE_ID, "Appliance" .. context.sensor, context.id, lul_device) 418 set_if_different(SERVICE_ID, "Appliance" .. context.sensor .. "Type", context.type, lul_device) 419 CHILD_DEVICE_COUNT = CHILD_DEVICE_COUNT + 1 420 -- Did we start with zero appliances? Tell user we found another. 421 if (CHILD_DEVICE_DISCOVERY_HANDLE ~= nil) then 422 luup.task("Discovered " .. CHILD_DEVICE_COUNT .. (CHILD_DEVICE_COUNT == 1 and " appliance" or " appliances") .. ". Reload when all appliances are discovered", 1, string.format("%s[%d]", luup.devices[lul_device].description, lul_device), CHILD_DEVICE_DISCOVERY_HANDLE) 423 end 424 end 368 425 end 369 426 370 427 if (context.tmpr) then 371 luup.variable_set(TEMPERATURE_SERVICE_ID, "CurrentTemperature", context.tmpr, lul_device)428 set_if_different(TEMPERATURE_SERVICE_ID, "CurrentTemperature", context.tmpr, lul_device) 372 429 -- Set temperature on the child temperature device (if there is one). 373 430 if (CHILD_TEMPERATURE_DEVICE) then 374 luup.variable_set(TEMPERATURE_SERVICE_ID, "CurrentTemperature", context.tmpr, CHILD_TEMPERATURE_DEVICE)431 set_if_different(TEMPERATURE_SERVICE_ID, "CurrentTemperature", context.tmpr, CHILD_TEMPERATURE_DEVICE) 375 432 end 376 433 end … … 399 456 for sensor = 0, 9 do 400 457 local childDevice = CHILD_DEVICE[tostring(sensor)] 401 if (childDevice ~= nil) then 458 local childDeviceType = CHILD_DEVICE_TYPE[tostring(sensor)] 459 if (childDevice ~= nil and childDeviceType == "1") then 402 460 luup.variable_set(SERVICE_ID, "TwoHourlyHistory", serializeHistory(TWOHOURLY_HISTORY[tostring(sensor)]), childDevice) 403 461 luup.variable_set(SERVICE_ID, "DailyHistory", serializeHistory(DAILY_HISTORY[tostring(sensor)]), childDevice)
Note: See TracChangeset
for help on using the changeset viewer.