Add-on - Aviosys IPPower 9258
-
Hi
Picking up from another thread this is to focus on the creation of the 4 key elements of a new Plugin for my Aviosys IPPower 9258, which are quite old, and I don’t believe are made anymore, but they seem to have a simple http api interface to cut my teeth on with a plugin.
First the device file, which is to support the creation/set up of the device, and here I explain what it is, tell Vera what the implementation file and .json file is, and also leverage the pre-existing Switch and HA capabilities..
Device File -
D_IPPower.xml
<?xml version="1.0"?> <root xmlns="urn:schemas-upnp-org:device-1-0"> <specVersion> <major>1</major> <minor>0</minor> </specVersion> <device> <deviceType>urn:nodecentral-net:device:IPPower:1</deviceType> <staticJson>D_IPPower1.json</staticJson> <manufacturer>Aviosys</manufacturer> <modelDescription>IPPowerSwitch</modelDescription> <modelName>IPPower9258</modelName> <handleChildren>1</handleChildren> <implementationList> <implementationFile>I_IPPower1.xml</implementationFile> </implementationList> <serviceList> <service> <serviceType>urn:schemas-upnp-org:service:SwitchPower:1</serviceType> <serviceId>urn:upnp-org:serviceId:SwitchPower1</serviceId> <SCPDURL>S_SwitchPower1.xml</SCPDURL> </service> <service> <serviceType>urn:schemas-micasaverde-com:service:HaDevice:1</serviceType> <serviceId>urn:micasaverde-com:serviceId:HaDevice1</serviceId> <SCPDURL>S_HaDevice1.xml</SCPDURL> </service> </serviceList> </device> </root>
Next it is the Implementation file, which thanks to the feedback on this forum, will focus on a specific Lua file, where all the code will be, the only thing I need to add here are the Actions (what do I want it to be able to do etc.)
Implementation file -
I_IPPower.xml
<?xml version="1.0"?> <!-- I_IPPower.xml; Vera/openLuup "IPPower 9258" Plug-in V1.1 Nov 2021 --> <implementation> <settings> <protocol>crlf</protocol> </settings> <files>L_IPPower1.lua</files> <startup>IPPowerStartup</startup> <actionList> <action> <serviceId>urn:upnp-org:serviceId:SwitchPower1</serviceId> <name>SetTarget</name> <job> local url = "http://" .. ipAddress .. "/set.cmd?user=admin+pass=12345678+cmd=setpower+" .. luup.devices[lul_device].id .. "=" .. lul_settings.newTargetValue luup.log("Sending command " .. url) local status, data = luup.inet.wget(url) if (data) then debug("Data received = " .. data) else log("No Data received !! ") end local value = string.match(data, luup.devices[lul_device].id.."=(%d)") if (value) then luup.variable_set("urn:upnp-org:serviceId:SwitchPower1", "Status", value, lul_device) else log("Value returned is empty") end </job> </action> </actionList> </implementation>
The other two files
D_IPPower.json
, andL_IPPower.lua
are still being worked on so i will add later …If anyone notices any improvement
-
ISSUE : Current status is if I go to Create Device, it will not appear on the UI, however I can see what I think it is via an all devices look up, but it has very few attributes. It does not look like the L_IPPower.lua file is being called ??
Here is the latest L_IPPower1.lua, I can only assume for now it’s not being called, or requirements such as lul_device are not being passed to it.. What’s strange is that there is nothing in the logs, so I can only assume the latter ? I’ve tried the Lua file with and without the package_seeall declaration..
Lua file =
L_IPPower1.lua
module("L_IPPower1", package.seeall) local POLLING_INTERVAL = 30 local OUTLET_START = 61 -- API returns the first socket as P61 local OUTLET_END = 68 -- depending on your device, it can be a 4 or 8 port, so 64 or 68 local DEBUG_MODE = true -- turn on debugging local PV = "1.1" -- plugin version number local ipAddress local childDeviceIndex = {} local function log(text, level) luup.log("IPPower: " .. text, (level or 1)) end local function debug(text) if (DEBUG_MODE == true) then log("debug: " .. text, 50) end end function IPPowerPoller() -- Call IPPower to return state of each outlet local user = "admin" local pass = "12345678" debug("Polling IPPower Device") local url = "http://" .. ipAddress .. "/set.cmd?user=".. user .. "+pass=" .. pass .. "+cmd=getpower" luup.call_timer("IPPowerPoller", 1, POLLING_INTERVAL, "", "") debug("Calling status " .. url) local status, data = luup.inet.wget(url) if (data) then debug("Response received " .. data) -- Example response is "P61=0,P62=1,P63=0,P64=0,P65=1,P66=0,P67=0,P68=0" else log("Empty response returned") end for v = OUTLET_START,OUTLET_END do local value = string.match(data, "P"..v.."=(%d)") if (value) then luup.variable_set("urn:upnp-org:serviceId:SwitchPower1", "Status", value, childDeviceIndex["P"..v]) else log("Empty value returned") end end end local function checkIPPowerSetUp(lul_device) log("Checking if parent device is configured correctly...") ipAddress = luup.devices[lul_device].ip -- check if parent device has an ip address assigned if ipAddress == nil or ipAddress == "" then -- if not stop and present error message luup.task('ERROR: IP Address is missing',2,'IPPower',-1) debug("ERROR: IP Address is missing " ..ipAddress.. " unable to progress") --return false luup.set_failure(1,lul_device) else -- if one is provided, present success message luup.task('IP Address for IPPower 9258 present, setup continues',4,'IPPower',-1) debug("IPPower StartUp activated - Device #" .. lul_device .. " now creating children") --luup.call_delay("IPPowerPoller", 5) --return true end end -- Initialize plug-in function IPPowerStartup(lul_device) -- set attributes for parent device luup.attr_set( "name", "IPPower 9258", lul_device) luup.attr_set( "category_num", "3", lul_device) luup.attr_set( "subcategory_num", "1", lul_device) luup.variable_set("urn:nodecentral-net:serviceId:IPPower1", "Icon", 1, lul_device) luup.variable_set("urn:nodecentral-net:serviceId:IPPower1", "PluginVersion", PV, lul_device) log("Start up, Parent device created...") child_devices = luup.chdev.start(lul_device) -- Tells Luup to start enumerating children for this device based on its dev_id for v = OUTLET_START,OUTLET_END do luup.chdev.append(lul_device,child_devices, "P" .. v, " Outlet " .. v, "urn:nodecentral-net:device:IPPower:1", "D_IPPower1.xml", "", "", false) debug("Child device created with id = P" .. v, " and description = Switch" .. v) end luup.chdev.sync(lul_device, child_devices) for k, v in pairs(luup.devices) do if (v.device_num_parent == lul_device) then -- populate child device table childDeviceIndex[v.id]=k end end checkIPPowerSetUp(lul_device) end
-
This is not required as you are not making a library/module component:
module("L_IPPower1", package.seeall)
Your implementation file says:
<startup>IPPowerStartup</startup>
yet your Lua code does not contain that function. So there's nothing to call. For testing, that function, could just write to the log and do nothing else. Don't forget every-time you change something you have to restart the Luup engine. This the slow apporach. Typically you would write and test your code first using some sort of test environment and then link it all into the implementation file.
After making any changes to your xml files with, you should check them for errors with a xml validator.
-
Thanks @a-lurker
Good to know, as I only added
module("L_IPPower1", package.seeall)
at the last minute, as I thought that might be the cause, and could see other like @toggledbits had itAs for the
IPPowerStartup
function, I do have that in there, it’s on line 66 in theL_IPPower1
file, shared above..What am I missing, I must be missing something ?
I’ll try variations, I assume it must be something like this
<startup>L_IPPower1.IPPowerStartup(lul_device)</startup>
instead then ?@a-lurker said in Add-on - Aviosys IPPower 9258:
Typically you would write and test your code first using some sort of test environment and then link it all into the implementation file.
After making any changes to your xml files with, you should check them for errors with a xml validator.
Yep, totally agree and that exactly what I’ve been doing, all the functions seem to check out fine in isolation - I’m just struggling to pull them all together into a stand-alone plugin.
As for the validators, totally agree, I’m a big user of the json one, and all my xml ones - all check out too.
-
I structure my implementation in modules, and load it in my startup section, not using
<files>
. This is an important distinction. You cannot mix and match styles. You have to go one way or the other. -
Ok, thanks @toggledbits , that makes sense, I’d like to get the
<files>
approach working at some point, but let’s try one with modules too.. Which means myI_IPPower.xml
will now be something like this..? With theL_IPPower.lua
having the seeall declaration this time..?<?xml version="1.0"?> <!-- I_IPPower.xml; Vera/openLuup "IPPower 9258" Plug-in V1.1 Nov 2021 --> <implementation> <functions> function initialiseIPPowerPlugin(lul_device) luup.log("IPPower Plugin START-UP!") IPPower = require("L_IPPower1") return IPPower.IPPowerStartup(lul_device) end </functions> <startup>initialiseIPPowerPlugin</startup> <actionList>
-
Oh no., somethings gone wrong, it’s now finding the start up but it’s going into some sort of loop of child device creations - and continual luup.reloads !!??
The function called by the implementation file is still this..
-- Initialize plug-in function IPPowerStartup(lul_device) -- set attributes for parent device luup.attr_set( "name", "IPPower 9258", lul_device) luup.attr_set( "category_num", "3", lul_device) luup.attr_set( "subcategory_num", "1", lul_device) luup.variable_set("urn:nodecentral-net:serviceId:IPPower1", "Icon", 1, lul_device) luup.variable_set("urn:nodecentral-net:serviceId:IPPower1", "PluginVersion", PV, lul_device) log("Start up, Parent device created...") child_devices = luup.chdev.start(lul_device) -- Tells Luup to start enumerating children for this device based on it's dev_id for v = OUTLET_START,OUTLET_END do luup.chdev.append(lul_device,child_devices, "P" .. v, " Outlet " .. v, "urn:nodecentral-net:device:IPPower:1", "D_IPPower1.xml", "", "", false) debug("Child device created with id = P" .. v, " and description = Switch" .. v) end luup.chdev.sync(lul_device, child_devices) for k, v in pairs(luup.devices) do if (v.device_num_parent == lul_device) then -- populate child device table childDeviceIndex[v.id]=k end end checkIPPowerSetUp(lul_device) end
-
From what I can see for the Log file extract, it seems to keep incrementing (deleting and creating) the child devices ?
50 11/14/21 21:06:20.986 luup_log:600: IPPower Plugin START-UP! <0x76db4520> 06 11/14/21 21:06:20.990 Device_Variable::m_szValue_set device: 600 service: urn:nodecentral-net:serviceId:IPPower1 variable: Icon was: 1 now: 1 #hooks: 0 upnp: 0 skip: 0 v:(nil)/NONE duplicate:1 <0x76db4520> 06 11/14/21 21:06:20.990 Device_Variable::m_szValue_set device: 600 service: urn:nodecentral-net:serviceId:IPPower1 variable: PluginVersion was: 1.1 now: 1.1 #hooks: 0 upnp: 0 skip: 0 v:(nil)/NONE duplicate:1 <0x76db4520> 01 11/14/21 21:06:20.990 luup_log:600: IPPower: Start up, Parent device created... <0x76db4520> 50 11/14/21 21:06:20.991 luup_log:600: IPPower: debug: Child device created with id = P61 <0x76db4520> 50 11/14/21 21:06:20.991 luup_log:600: IPPower: debug: Child device created with id = P62 <0x76db4520> 50 11/14/21 21:06:20.992 luup_log:600: IPPower: debug: Child device created with id = P63 <0x76db4520> 50 11/14/21 21:06:20.992 luup_log:600: IPPower: debug: Child device created with id = P64 <0x76db4520> 50 11/14/21 21:06:20.992 luup_log:600: IPPower: debug: Child device created with id = P65 <0x76db4520> 50 11/14/21 21:06:20.992 luup_log:600: IPPower: debug: Child device created with id = P66 <0x76db4520> 50 11/14/21 21:06:20.993 luup_log:600: IPPower: debug: Child device created with id = P67 <0x76db4520> 50 11/14/21 21:06:20.993 luup_log:600: IPPower: debug: Child device created with id = P68 <0x76db4520> 09 11/14/21 21:06:20.993 Child_Devices::ProcessChildDevice deleting device 889 id P61 room 0 desc Outlet 61 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 under 600 topmost parent 600 because type o:urn:schemas-micasaverde-com:device:GenericIO:1!=n:urn:nodecentral-net:device:IPPower:1 or file o:D_IPPower1.xml!=n:D_IPPower1.xml embedded o:0!=n:0 ok:0/1 <0x76db4520> 02 11/14/21 21:06:21.011 UserData::CommitToDatabase data size 86066 86066 <0x76db4520> 02 11/14/21 21:06:21.107 Device_Basic::m_sDescription_set device 897. description: Outlet 61 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 exist already, new Description: Outlet 61 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 <0x76db4520> 09 11/14/21 21:06:21.109 Child_Devices::ProcessChildDevice created device 897 id P61 under 600 topmost parent 600 <0x76db4520> 09 11/14/21 21:06:21.110 Child_Devices::ProcessChildDevice deleting device 890 id P62 room 0 desc Outlet 62 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 under 600 topmost parent 600 because type o:urn:schemas-micasaverde-com:device:GenericIO:1!=n:urn:nodecentral-net:device:IPPower:1 or file o:D_IPPower1.xml!=n:D_IPPower1.xml embedded o:0!=n:0 ok:0/1 <0x76db4520> 02 11/14/21 21:06:21.234 UserData::CommitToDatabase data size 85500 85500 <0x76db4520> 02 11/14/21 21:06:21.240 Device_Basic::m_sDescription_set device 898. description: Outlet 62 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 exist already, new Description: Outlet 62 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 <0x76db4520> 09 11/14/21 21:06:21.244 Child_Devices::ProcessChildDevice created device 898 id P62 under 600 topmost parent 600 <0x76db4520> 09 11/14/21 21:06:21.244 Child_Devices::ProcessChildDevice deleting device 891 id P63 room 0 desc Outlet 63 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 under 600 topmost parent 600 because type o:urn:schemas-micasaverde-com:device:GenericIO:1!=n:urn:nodecentral-net:device:IPPower:1 or file o:D_IPPower1.xml!=n:D_IPPower1.xml embedded o:0!=n:0 ok:0/1 <0x76db4520> 02 11/14/21 21:06:21.376 UserData::CommitToDatabase data size 84934 84934 <0x76db4520> 02 11/14/21 21:06:21.381 Device_Basic::m_sDescription_set device 899. description: Outlet 63 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 exist already, new Description: Outlet 63 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 <0x76db4520> 09 11/14/21 21:06:21.386 Child_Devices::ProcessChildDevice created device 899 id P63 under 600 topmost parent 600 <0x76db4520> 09 11/14/21 21:06:21.386 Child_Devices::ProcessChildDevice deleting device 892 id P64 room 0 desc Outlet 64 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 under 600 topmost parent 600 because type o:urn:schemas-micasaverde-com:device:GenericIO:1!=n:urn:nodecentral-net:device:IPPower:1 or file o:D_IPPower1.xml!=n:D_IPPower1.xml embedded o:0!=n:0 ok:0/1 <0x76db4520> 02 11/14/21 21:06:21.491 UserData::CommitToDatabase data size 84368 84368 <0x76db4520> 02 11/14/21 21:06:21.494 Device_Basic::m_sDescription_set device 900. description: Outlet 64 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 exist already, new Description: Outlet 64 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 <0x76db4520> 09 11/14/21 21:06:21.497 Child_Devices::ProcessChildDevice created device 900 id P64 under 600 topmost parent 600 <0x76db4520> 09 11/14/21 21:06:21.497 Child_Devices::ProcessChildDevice deleting device 893 id P65 room 0 desc Outlet 65 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 under 600 topmost parent 600 because type o:urn:schemas-micasaverde-com:device:GenericIO:1!=n:urn:nodecentral-net:device:IPPower:1 or file o:D_IPPower1.xml!=n:D_IPPower1.xml embedded o:0!=n:0 ok:0/1 <0x76db4520> 02 11/14/21 21:06:21.568 UserData::CommitToDatabase data size 83802 83802 <0x76db4520> 02 11/14/21 21:06:21.572 Device_Basic::m_sDescription_set device 901. description: Outlet 65 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 exist already, new Description: Outlet 65 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 <0x76db4520> 09 11/14/21 21:06:21.575 Child_Devices::ProcessChildDevice created device 901 id P65 under 600 topmost parent 600 <0x76db4520> 09 11/14/21 21:06:21.575 Child_Devices::ProcessChildDevice deleting device 894 id P66 room 0 desc Outlet 66 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 under 600 topmost parent 600 because type o:urn:schemas-micasaverde-com:device:GenericIO:1!=n:urn:nodecentral-net:device:IPPower:1 or file o:D_IPPower1.xml!=n:D_IPPower1.xml embedded o:0!=n:0 ok:0/1 <0x76db4520> 02 11/14/21 21:06:21.645 UserData::CommitToDatabase data size 83236 83236 <0x76db4520> 02 11/14/21 21:06:21.649 Device_Basic::m_sDescription_set device 902. description: Outlet 66 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 exist already, new Description: Outlet 66 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 <0x76db4520> 09 11/14/21 21:06:21.652 Child_Devices::ProcessChildDevice created device 902 id P66 under 600 topmost parent 600 <0x76db4520> 09 11/14/21 21:06:21.652 Child_Devices::ProcessChildDevice deleting device 895 id P67 room 0 desc Outlet 67 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 under 600 topmost parent 600 because type o:urn:schemas-micasaverde-com:device:GenericIO:1!=n:urn:nodecentral-net:device:IPPower:1 or file o:D_IPPower1.xml!=n:D_IPPower1.xml embedded o:0!=n:0 ok:0/1 <0x76db4520> 02 11/14/21 21:06:21.722 UserData::CommitToDatabase data size 82670 82670 <0x76db4520> 02 11/14/21 21:06:21.726 Device_Basic::m_sDescription_set device 903. description: Outlet 67 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 exist already, new Description: Outlet 67 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 <0x76db4520> 09 11/14/21 21:06:21.728 Child_Devices::ProcessChildDevice created device 903 id P67 under 600 topmost parent 600 <0x76db4520> 09 11/14/21 21:06:21.729 Child_Devices::ProcessChildDevice deleting device 896 id P68 room 0 desc Outlet 68 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 under 600 topmost parent 600 because type o:urn:schemas-micasaverde-com:device:GenericIO:1!=n:urn:nodecentral-net:device:IPPower:1 or file o:D_IPPower1.xml!=n:D_IPPower1.xml embedded o:0!=n:0 ok:0/1 <0x76db4520> 02 11/14/21 21:06:21.798 UserData::CommitToDatabase data size 82104 82104 <0x76db4520> 02 11/14/21 21:06:21.802 Device_Basic::m_sDescription_set device 904. description: Outlet 68 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 exist already, new Description: Outlet 68 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 <0x76db4520> 09 11/14/21 21:06:21.805 Child_Devices::ProcessChildDevice created device 904 id P68 under 600 topmost parent 600 <0x76db4520> 06 11/14/21 21:06:21.805 Device_Variable::m_szValue_set device: 1 service: urn:micasaverde-com:serviceId:ZWaveNetwork1 variable: LastDongleBackup was: now: #hooks: 0 upnp: 0 skip: 0 v:(nil)/NONE duplicate:1 <0x76db4520> 01 11/14/21 21:06:21.830 UserData::WriteUserData saved--before move File Size: 22154 save size 22154 <0x76bb4520> 02 11/14/21 21:06:21.831 UserData::TempLogFileSystemFailure start 0 <0x76bb4520> 02 11/14/21 21:06:21.847 UserData::TempLogFileSystemFailure (not failure, only WriteUserData) 0 <0x76bb4520> 02 11/14/21 21:06:21.848 UserData::TempLogFileSystemFailure 699 res:1
-
You have to be super-careful with how you structure your luup.chdev work. If the loop creates or deletes any child, then the
sync()
will cause a restart, so it's very easy to get reload loops. -
parkercreplied to toggledbits on Nov 14, 2021, 10:26 PM last edited by parkerc Nov 14, 2021, 5:27 PM
@toggledbits said in Add-on - Aviosys IPPower 9258:
You have to be super-careful with how you structure your luup.chdev work. If the loop creates or deletes any child, then the
sync()
will cause a restart, so it's very easy to get reload loops.Agreed, and it’s my first attempt at doing this, and i even remember making a note of the warning on the wiki - http://wiki.micasaverde.com/index.php/Luup_Lua_extensions#Module:_luup.chdev .
When the final luup.chdev.sync is executed the children are checked. Any additions, changes or deletions will result in a Luup engine restart. Any incorrect coding of luup.chdev.append may result in a situation where the engine goes into a loop and continually restarts. As an example, if two children are added with the same id parameter, this will occur. To recover, you need to quickly upload a new file that has the faulty "append" code commented out. In the interim the engine will be incrementing the device ID numbers with no end in sight.
I can’t work out why the chdev is doing that , can you see any issue with my chdev.start and append that would cause the sync to do that ?
local OUTLET_START = 61 -- API returns the first socket as P61 local OUTLET_END = 68 -- depending on your device, it can be a 4 or 8 port, so 64 or 68 child_devices = luup.chdev.start(lul_device) -- Tells Luup to start enumerating children for this device based on it's dev_id , this returns: ptr (binary object) which is used in the cheer.append. for v = OUTLET_START,OUTLET_END do luup.chdev.append(lul_device,child_devices, "P" .. v, " Outlet " .. v, "urn:nodecentral-net:device:IPPower:1", "D_IPPower1.xml", "", "", false) debug("Child device created with id = P" .. v, " and description = Switch" .. v) end luup.chdev.sync(lul_device, child_devices) for k, v in pairs(luup.devices) do if (v.device_num_parent == lul_device) then -- populate child device table childDeviceIndex[v.id]=k end end
-
I’ve discovered that if I change the chdev.append so it creates a different device (see below), i don’t seem to get the loop issue.
I assume this is likely due to the previous set up had the append calling the same implementation file as the parent, which looks to create children - thus triggers a loop ?
for v = OUTLET_START,OUTLET_END do luup.chdev.append(lul_device,child_devices, "P" .. v, " Outlet " .. v, "urn:schemas-upnp-org:device:BinaryLight:1", "D_BinaryLight1.xml", "", "", false) end
-
toggledbitswrote on Nov 14, 2021, 11:19 PM last edited by toggledbits Nov 14, 2021, 6:19 PM
Since you have
handleChildren
set to 1 in the D_.xml (device) file, the children should not receive an implementation file at all (it should be blank/empty string inappend()
). And it seems right that the children also should not have the same device type as the parent. -
Agreed, many thanks .
Well it looks like I’m almost there now, the only thing left to fix is the the luup.call_timer I have on the main polling function in L_IPPower1.lua file .
Here’s the function..
function IPPowerPoller() -- Call IPPower to return state of each outlet local user = "admin" local pass = "12345678" debug("Started Polling IPPower Device") local url = "http://" .. ipAddress .. "/set.cmd?user=".. user .. "+pass=" .. pass .. "+cmd=getpower" debug("Calling URL " .. url) local status, data = luup.inet.wget(url) if (data) then debug("Response received " .. data) -- Example response is "P61=0,P62=1,P63=0,P64=0,P65=1,P66=0,P67=0,P68=0" else log("Empty response returned") end for v = OUTLET_START,OUTLET_END do local value = string.match(data, "P"..v.."=(%d)") if (value) then luup.variable_set("urn:upnp-org:serviceId:SwitchPower1", "Status", value, childDeviceIndex["P"..v]) else log("Empty value returned") end end debug("Finished Polling IPPower Device") luup.call_timer("IPPowerPoller", 1, 30, "", "") end
Which returns this..
01 11/15/21 0:00:58.100 LuaInterface::CallFunction_Timer-5 function IPPowerPoller failed attempt to call a nil value <0x74e48520>
I might just be tired, but I can’t work out the cause here, any ideas?
I’ve made it a local and a global function, called it with and without the module name, all return the same nil value error?
-
toggledbitsreplied to parkerc on Nov 15, 2021, 1:10 AM last edited by toggledbits Nov 14, 2021, 8:11 PM
@parkerc said in Add-on - Aviosys IPPower 9258:
I might just be tired, but I can’t work out the cause here, any ideas?
I’ve made it a local and a global function, called it with and without the module name, all return the same nil value error?If you're getting the same
nil
error, you're somehow not making a global, or making it with the correct name/using the correct name. In order to help there, I'd need to see the current I_ and L_ files in their entirety.But before you do that, I think you said you were looking at the SiteSensor code as an example, and you invoked the "module" word, so... in the I_SiteSensor file, look at how I create a global called
siteSensorWatch
that is an alias for the module's function. This creates a global, which must be done in the scope of the implementation (I_) file if the L_ file is a module. Then in my L_SiteSensor module, you can see in theluup.variable_watch
statements where I'm using that name -- the function name parameter for that works the same as it does forcall_delay
andcall_timer
. Check that out, and see if you can work out what you didn't get to there. -
@toggledbits said in Add-on - Aviosys IPPower 9258:
…… in the I_SiteSensor file, look at how I create a global called
siteSensorWatch
that is an alias for the module's function. This creates a global, which must be done in the scope of the implementation (I_) file if the L_ file is a module.I had a look in your Implementation file , but could not see anything called
siteSensorWatch
listed?Here is the opening of my a I_IPPower.xml` Implementation file..
<?xml version="1.0"?> <!-- I_IPPower.xml; Vera/openLuup "IPPower 9258" Plug-in V1.1 Nov 2021 --> <implementation> <functions> function initialiseIPPowerPlugin(lul_device) luup.log("IPPower: IPPower Plugin STARTING-UP!") IPPower = require("L_IPPower1") return IPPower.IPPowerStartup(lul_device) end </functions> <startup>initialiseIPPowerPlugin</startup> <actionList> <action>
@toggledbits said in Add-on - Aviosys IPPower 9258:
Then in my L_SiteSensor module, you can see in the
luup.variable_watch
statements where I'm using that name -- the function name parameter for that works the same as it does forcall_delay
andcall_timer
. Check that out, and see if you can work out what you didn't get to there.Right, I’m on it, I couldn’t find any luup.variable_watch calls, but I did find a
luup.call_delay
in yourL_SiteSensor
luup.call_delay("siteSensorRunQuery", delay, string.format("%d:%d", stamp, dev))
Which links to the following assocation in your siteSensor Implementation file
siteSensorRunQuery = SiteSensor.runQuery
So that’s where I’ll focus..
-
Sorry, I'm always looking at the development version, but you've followed the right trail.
runQuery
works the same way. -
Thanks @toggledbits - it’s all working now !!
My last piece is back to my other post around error handling, and how I can present that better to the user, and so for that topic, I;ll revert back to that thread.. - > https://smarthome.community/topic/777/luup-error-handling/9
8/17