Discussion Forum to share and further the development of home control and automation, independent of platforms.

    SmartHome Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Unsolved
    (Last Updated: 24 December 2021)
    • Embarrassing mind blank

      CatmanV2

      Or course, I should be used to being blank by now.

      Can someone please refresh me how I can have VeraAlexa say the value of a variable? I used to have it, but have deleted it and now failing to find it in the posts 😞

      TIA

      C

      Code/Snippet library
    • Lua - multi-part/form submission (Paperless-ngx API)

      parkerc

      Hi

      I’ve been investing a lot of time recently trying to digitise everything I can, and my current adventure is with all my paper documents.

      My tool of choice is Paperless-ngx, which so far is an amazing open source solution, and highly recommended if you’re interest in such a thing…

      Such a move to Paperless would not be complete without some form of integration into Vera / openLuup, and thankfully it has a nice Rest API (https://paperless-ngx.readthedocs.io/en/latest/api.html) I can use. So far I’ve been able to make use the GET requests, to provide document counts etc., but it’s the mutipart/form data piece where I’m struggling..

      The Curl command to upload a document, is as follows

      curl -H "Authorization: Basic Y2hyaXM62tgbsgjunotmeY2hyaXNob3N0aW5n" -F "title=Companies House File 10" -F "correspondent=12" -F "document=@/mnt/nas/10.pdf" http://192.168.102.134:8777/api/documents/post_document/

      But, I’d like to know how to do this with Lua code, more just to help me in my Lua learning curve, and what I thought would be reasonably straight forward thing to do, has turned out to be quite the opposite 🙂 Sending a multipart form data submission via http.request, is not as straight forward as I hoped. If anyone has any time to help, I’d appreciate some guidance on what I’m missing with the following, as based on the feedback, it looks like it not seeing the file (which I think I’ve confirmed by trying to sending both the curl and Lua commands to httbin.org ) …

      local http = require("socket.http") local ltn12 = require("ltn12") local mime = require("mime") local lfs = require("lfs") local username = "username" local password = "password" local httpendpoint = 'http://httpbin.org/post' local filepath = "/mnt/nas/10.pdf" local file = io.open(filepath, "rb") local contents = file:read( "*a" ) -- https://stackoverflow.com/questions/3508338/what-is-the-boundary-in-multipart-form-data local boundary = "-----BoundaryePkpFF7tjBAqx29L" local send = "--"..boundary.. "\r\nContent-Disposition: form-data; title='Companies House File'\r\n" .."----"..boundary.. "\r\nContent-Disposition: form-data; document="..filepath.. "\r\nContent-type: application/pdf".."\r\n" ..contents.."\r\n" .."------"..boundary.."--\r\n" -- Execute request (returns response body, response code, response header) local resp = {} local body, code, headers, status = http.request { url = httpendpoint, method = 'POST', headers = { ["Authorization"] = "Basic " .. (mime.b64(username ..":" .. password)), ["Content-Length"] = lfs.attributes(filepath, 'size'), ['Content-Type'] = "multipart/form-data; boundary="..boundary, }, -- source = ltn12.source.file( io.open(filepath,"rb") ), source = ltn12.source.file( io.open(send) ), sink = ltn12.sink.table(resp) } print(body, code, headers, status) print(table.concat(resp)) if headers then for k,v in pairs(headers) do print(k,v) end end
      Code/Snippet library
    • Lua : Downloading a file over https

      parkerc

      Hi,

      I’m sure this is not a unique question about Vera (& Lua 5.1) and I’ve seen this reference in place,, but I can’t seem to find a fix to make an https download request work..

      To give you an example, the code below aims to download 2 different files, the http call works fine, returning a 200 code, but the https one doesn’t, it doesn’t return anything ?

      Please could some highlight what I’m missing?

      print("--------DOWNLOAD http---------") local http = require("socket.http") local body, code = http.request("http://pbs.twimg.com/media/CCROQ8vUEAEgFke.jpg") print(code) if not body then error(code) end local f = assert(io.open('mnt/nas/webtest1.jpg', 'wb')) -- open in "binary" mode f:write(body) f:close() print("--------DOWNLOAD https---------") local https = require "ssl.https" --luasec local body, code = https.request("https://u.cubeupload.com/jbcooper/16146313918060.jpg") print(code) if not body then error(code) end local f = assert(io.open('mnt/nas/webtest2.jpg', 'wb')) -- open in "binary" mode f:write(body) f:close()
      Code/Snippet library
    • Luup : Fitbit API

      parkerc

      Hi

      I’m trying out the Fitbit api, not only to extract some activity data for a potential plugin, but also to learn more about OAuth 2.0. More details can be found here..

      Fitbit Development: Getting Started Fitbit Development: Getting Started

      You'll fit in here. Using JavaScript, CSS, and SVG, developers now have a fast, easy way to build apps and clock faces for Fitbit OS.

      In addition to having a fitbit account, to get going with any integration, you need to register your app, via here..

      Login

      With an app registered, I’ve called mine “VERA” , I’ve written chunks of Lua code to support the various steps, (completed manually) my goal now is to try and put them all together into functions to be called in sequence on my Vera and/or OpenLuup.

      Where I’m getting stuck is with the authorisation code step, which Fitbit provides appended to the domain name I registered with them when registered my app ..

      Here’s an example of a redirect URL that Fitbit will redirect the user too, with their associated authorisation code, which I need in the process later on to obtain the required access token. (More specific details are here - https://dev.fitbit.com/build/reference/web-api/developer-guide/authorization/ )

      https://myapp.com/callback?code=d62d6f5bdc13df79d9a5f#_=_

      And it’s the d62d6f5bdc13df79d9a5f part of that new page/URL which I need..

      How best do i capture/process the URL call Fitbit issues?

      I assume this is where a luup.register_handler would come in, and I could register my Vera handle (using https ?, as that’s required by Fitbit) as the redirect domain/url e.g.

      https://veraip:3480/data_request?id=lr_fitbit&

      So Fitbit would redirect to..

      https://veraip:3480/data_request?id=lr_fitbit&/?code=d62d6f5bdc13df79d9a5f#_=_

      But that doesn’t seem to work..

      Any suggestions on how to do this would be appreciated..

      function FitbitRequestHandler(lul_request, lul_parameters, lul_outputformat) for k,v in pairs(lul_parameters) do luup.log ('fitbit_Handler: parameters are: '..tostring(k)..'='..tostring(v)) end if next(lul_parameters) == nil then luup.log("lul_parameters Table is empty") end local html = "</html><head>" .. "</head>" .. "<body>" .. "PRINTING" .. "\n" .. " lul_request: " .. tostring(lul_request) .. "\n" .. " lul_parameters: " .. tostring(lul_parameters) .. "\n" .. " lul_outputformat: " .. tostring(lul_outputformat) .. "\n" .. "</body></html>" return html, "text/html" end luup.register_handler("FitbitRequestHandler", "fitbit")

      Thanks is advance…

      Code/Snippet library
    • Luup : Error Handling

      parkerc

      Hi,

      Please could people share how they are presenting and handling errors in their Vera / OpenLuup plugins, I’ve tried to look through various Implementation files, but very few seem to have anything, other than perhaps a luup.task (which for some reason doesn’t work for me) ?

      Below is the startup and check/validation functions for a plugin I’m working on..

      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 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") createChildIPPowerOutlets(lul_device) luup.call_delay("IPPowerPoller", 5) return true end end 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) checkIPPowerSetUp(lul_device) log("Start up, Parent device created...") end </functions> <startup>IPPowerStartup</startup>

      What’s the best way to present errors to the user, and make iot clear what they need to do ?

      Code/Snippet library
    • Help with luup.chdev.sync

      therealdb

      I'm struggling to fix the code attached here
      https://github.com/dbochicchio/vera/blob/master/OpenSprinkler/L_VeraOpenSprinkler1.lua#L270,L429

      Under certain circumstances (thanks @DesT!) I see that it's causing a luup reload infinite cycle, because child devices are being created, then deleted. Specifically, I see this in the logs:

      2020-06-01 19:35:30.482 luup.chdev.sync:: [102] Open Sprinkler Test, syncing children 2020-06-01 19:35:30.482 openLuup.chdev:: deleting [413] Daily Garden 2020-06-01 19:35:30.482 openLuup.chdev:: deleting [414] Water Level 2020-06-01 19:35:30.482 openLuup.chdev:: deleting [411] Daily Cedars 2020-06-01 19:35:30.482 openLuup.chdev:: deleting [412] St-Eustache Rules AM 2020-06-01 19:35:30.482 openLuup.luup:: device 102 'Open Sprinkler Test' requesting reload

      The devices are created (look at line 357/410), but when I call luup.chdev.sync, they got deleted. Any hints? Thanks

      Code/Snippet library
    • Vera StaticJSON Help - Showing a button’s status/selection (in/out) in the UI ?

      parkerc

      Hi

      I’m putting the finishing touches to a HDMI Matrix plugin, and while I have it working well - I can’t find anything on the Vera/MIOS wikis that tells me how I can show if a UI button is pressed or not (to reflect a input choice that is selected)

      Here’s a screenshot of the child outputs I’ve created for the Matrix switcher. (The plugin creates a parent device and then 4 children to show the Matrix Outputs - parent is not shown - and the idea is that’s you select the input number for the respective output)

      BB5B6001-294E-4AE9-A095-D2E639F56B9C.jpeg

      Here is an extract of the button element in the associated JSON file used for the child devices..

      { "ControlGroup": "1", "ControlType": "button", "top": "0", "left": "0", "Label": { "lang_tag": "Input1", "text": "Input1" }, "Display": { "Top": 60, "Left": 50, "Width": 75, "Height": 20 }, "Command": { "Service": "urn:nodecentral-net:serviceId:SYMatrix1", "Action": "SYCall", "Parameters": [ { "Name": "action", "Value": "I1" } ] } },

      The associated command calls the parent implementation file SYCall - (The value “I1” relates to a element of the URL that needs to be called to select that associated input)

      <action> <serviceId>urn:nodecentral-net:serviceId:SYMatrix1</serviceId> <name>SYCall</name> <run> SYMatrix.SYCall(lul_device, lul_settings.action, lul_settings) </run> </action>

      And then the Lua file (L_****) has holds the SYCall function

      function SYCall (deviceNo, action, settings) ….. end
      Code/Snippet library
    • URL - /data_request?id=lu_action&serviceId=urn:micasaverde-com:serviceId:HomeAutomationGateway1&action=RunLua&Code=

      parkerc

      I’ve just started to have a play with iOS Shortcut and one of my test cases is to see if I can do the following

      select a a file (.lua or .txt) on my iPad extract the entire script/contents encode the data obtained append the encode content to the end of the RunLua action. call the URL http://myIP/data_request?id=lu_action&serviceId=urn:micasaverde-com:serviceId:HomeAutomationGateway1&action=RunLua&Code=

      Below is a screenshot of the workflow I have built in Shortcuts, which seems pretty straight forward, and it does generate a encoded URL, however the actual request itself does not complete. I get an ‘OK’ response back eventually, but the code is not actioned, and the logs don’t seem to tell me anything..

      FAB8DB5F-9003-4624-BCF3-8F536A660D21.jpeg

      The code I’m extracting from the Lua file works fine in the test Lua window, so i’m not sure what’s occurring differently, between the two routes, maybe it’s the encryption being used ?..

      Is anyone able to help me test this, and see if they can generate a long / multi line RunLua encoded URL (if not via Shortcut, then by some that can help me with the root cause to then address that in Shortcut

      Code/Snippet library
    • Lua : http(s) request, works on some URLs, but not all ? But all work via the browser..

      parkerc

      I have a couple of calendar URLs I’m trying to call, and both work when i enter the URL into the browser, however when I try to call them via Lua and http(s).request, only one of them works ? Please could someone help me understand why, and what needs to be done differently to make the other one work ?

      local socket = require 'socket' local http = require "socket.http" local ssl = require 'ssl' local https = require 'ssl.https' local calendarUria = "https://ics.fixtur.es/v2/ipswich-town.ics" local calendarUrib = "https://calendar.google.com/calendar/ical/en-gb.uk%23holiday%40group.v.calendar.google.com/public/basic.ics" print("Fixtur.es Football (URL A) returns the following?") local responseBodya, responseCodea, responseHeadersa = https.request(calendarUria) print(responseBodya, responseCodea, responseHeadersa) print("Google UK Holidays (URL B) returns the following?") local responseBodyb, responseCodeb, responseHeadersb = https.request(calendarUrib) print(responseBodyb, responseCodeb, responseHeadersb)

      If you run the code above, only the second Google (URL `B) returns anything..

      Code/Snippet library
    • Add-on - Aviosys IPPower 9258

      parkerc

      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, and L_IPPower.lua are still being worked on so i will add later …

      If anyone notices any improvement

      Code/Snippet library
    • Lua : storage.set , storage.get

      parkerc

      Hi

      I’ve seen storage.set and storage.get used in some Lua code posted on the internet, where they need to store/retrieve somethings, e.g.

      iv = encdec.base64dec(challenge_Key)     storage.set('IV', iv)

      and then later on within another function I see..

      iv = storage.get('IV')

      It makes sense how this is meant to work, and it seems such a simple/elegant feature - hence I was wondering, is there an equivalent in Vera/OpenLuup? As I’d naturally go to use luup.variable_set and luup.variable_get - but that requires a device to be used etc.

      Code/Snippet library
    • Get your Alexa replies to the device you've asked them to with VeraAlexa plug-in

      therealdb

      So, I was messing with my Alexa routines and ha bridge, and I want to share something very cool you could do with the ability to get the last Alexa that heard your command. I mentioned it a couple of times on the old place, but Vera's OS is missing the jq package, but openLuup could have it installed.

      Basically, just execute -lastalexa with my VeraAlexa plug-in:

      local lastAlexa = luup.call_action("urn:bochicchio-com:serviceId:VeraAlexa1", "RunCommand", {Command="-lastalexa"}, 666)

      Then use it in your scene, to dynamically generate your TTS response with the device you've asked your question seconds before!

      local temperature = 25 -- get it from your sensor luup.call_action("urn:bochicchio-com:serviceId:VeraAlexa1", "Say", {Text="Ok, outise temperature is " .. temperature .. " degree", Volume=50, GroupZones= lastAlexa, Repeat = 2}, 666

      Very cool indeed 🙂

      Code/Snippet library
    • Luup : Hue Energy (watts) Calculator

      parkerc

      Hi all

      I’ve been trying to use the Hue api and some of my Lua knowledge to create an energy calculator based on the brightness and wattage of specific models of hue bulb registered on the hub

      I’ve pretty much got there, the only stumbling block I have is how I total up all the individual bulb wattages. Can anyone help ?

      It’s likely an easy thing for someone more experienced to see, but as I only dip in and dip out now and then, the correct code/syntax does not always come to mind.

      Note : as I’ve tried various routes, I’ve commented some things out, but you should be able to get the idea of what I’m trying to do..

      Create device json from Hue Hub Decode JSON and extract key values to a table Calculate approx watts based on bulb model and/or watts function Total up watts of all bulbs that are switch on.

      Code below...

      local hueBridgeIP = '192.168.1.29' local hueBridgeAPI = "80uCoXjnn2LNLhxEJ9PW6nmt-G5KWQ2uP3oONAvcm0j" function getHueLight() local http = require('socket.http') local ltn12 = require('ltn12') local json = require('dkjson') t = {} local url = string.format("http://%s/api/%s/lights", hueBridgeIP, hueBridgeAPI) b, c, h = http.request{url=url, sink = ltn12.sink.table(t), method='GET'} huestring = tostring(table.concat(t)) local hue, pos, err = json.decode(huestring, 1, nil) huelights = {} for k, v in pairs(hue) do local modelno = string.gsub(hue[k]['modelid'], "%s+", "") table.insert(huelights, {k, hue[k]['state']['on'], hue[k]['name'], hue[k]['state']['bri'], modelno, hue[k]['state']['reachable']}) print(k, hue[k]['state']['on'], hue[k]['name'], hue[k]['state']['bri'], modelno, hue[k]['state']['reachable']) end end local fourpointeightwattTable = { [ 1 ] = 0.6 , [ 2 ] = 0.7 , [ 3 ] = 0.8 , [ 4 ] = 0.9 , [ 5 ] = 1.2 , [ 6 ] = 1.4 , [ 7 ] = 1.7 , [ 8 ] = 2.0 , [ 9 ] = 2.3 , [ 10 ] = 2.6 , [ 11 ] = 2.9 , [ 12 ] = 3.1 , [ 13 ] = 3.5 , [ 14 ] = 4.0 , } local sevenwattTable = { [ 1 ] = 1.6 , [ 2 ] = 1.7 , [ 3 ] = 1.8 , [ 4 ] = 1.9 , [ 5 ] = 2.2 , [ 6 ] = 2.4 , [ 7 ] = 2.7 , [ 8 ] = 3.0 , [ 9 ] = 3.5 , [ 10 ] = 3.9 , [ 11 ] = 4.5 , [ 12 ] = 5.1 , [ 13 ] = 5.5 , [ 14 ] = 6.4 , } local ninewattTable = { [ 1 ] = 1.6 , [ 2 ] = 1.7 , [ 3 ] = 1.8 , [ 4 ] = 1.9 , [ 5 ] = 2.2 , [ 6 ] = 2.5 , [ 7 ] = 2.9 , [ 8 ] = 3.5 , [ 9 ] = 3.8 , [ 10 ] = 4.6 , [ 11 ] = 5.5 , [ 12 ] = 6.5 , [ 13 ] = 7.7 , [ 14 ] = 8.5 , } function fourpointeightgetWattage(hue) local index = math.floor(hue / 16.5) if index <= 0 then return 0.2 elseif index >= 15 then return 4.8 else return fourpointeightwattTable[index] end end function sevengetWattage(hue) local index = math.floor(hue / 16.5) if index <= 0 then return 0.4 elseif index >= 15 then return 7.0 else return sevenwattTable[index] end end function ninegetWattage(hue) local index = math.floor(hue / 16.5) if index <= 0 then return 0.4 elseif index >= 15 then return 9.0 else return ninewattTable[index] end end local total = 0 local Value = 0 local huewatts = {} for k,v in pairs(huelights) do if v[2] == true and v[5] == "RS125" and v[6] == true then local watts = fourpointeightgetWattage(v[4]) local Value = tonumber(watts) local total = total + Value print("four point eight watts") print(v[5], v[4], v[2], v[3], watts) table.insert(huewatts, {v[5], v[4], v[2], v[3], watts}) --print(watts) --print(total) elseif v[2] == true and v[5] == "LWA004" and v[6] == true then local watts = sevengetWattage(v[4]) local Value = tonumber(watts) local total = total + watts print("seven watts") print(v[5], v[4], v[2], v[3], watts) table.insert(huewatts, {v[5], v[4], v[2], v[3], watts}) --print(watts) --print(total) elseif v[2] == true and v[6] == true then local watts = ninegetWattage(v[4]) local Value = tonumber(watts) local total = total + Value print("nine watts") print(v[5], v[4], v[2], v[3], watts) table.insert(huewatts, {v[5], v[4], v[2], v[3], watts}) --print(watts) --print(total) end end print(total) print(huewatts) -- confirm if table it there (TBC)
      Code/Snippet library
    • UDP Datagrams

      therealdb

      I've implemented this:

      https://smarthome.community/topic/20/openluup-version-log/18

      into my own MQTT Server and that's cool, since I'm now pushing every variable via MQTT, originating from the Vera.

      Just a couple of questions for @akbooer

      do I need to check that sock is connected, from time to time? is there anything specifically to retry the command?

      I'm running it in the latest hour, and everything seems OK, but I want to code it for the worst situations. Thanks, always inspiring!

      Code/Snippet library
    • Luup : Whole house energy usage.

      parkerc

      Hi all

      Here’s another snippet of code I like to use, to see what’s going on.
      If anyone has any variations on this, I’d love to see it.

      local variables = {"Watts"} local NRG_SER = "urn:micasaverde-com:serviceId:EnergyMetering1" local total = 0 for lul_device in pairs(luup.devices) do local readings = {} -- create empty array called readings for _, variable in ipairs(variables) do -- using the id and value in variables table above local value = luup.variable_get(NRG_SER, variable, lul_device) local name = luup.attr_get ('name', lul_device) table.insert( readings, { variable, tonumber(value), name}) -- populate readings table end for _, reading in ipairs(readings) do local Variable = reading[1] local Value = reading[2] or 0 local Name = reading[3] or "Unknown" total = total + Value if Value ~= 0 then print(Name, Variable.. " - ".. Value) end end end print("Total watts = " ..total)
      Code/Snippet library
    • Luup : Foscam API

      parkerc

      Sharing the love...

      As I have a number of foscam cameras around the house, using their API I created the following bit of code to set to retrieve any settings across all of them, to keep them in sync.

      This one gets the device name from each of them. If anyone has any variations or ways to improve the bit of code please let me know..

      local url = require("socket.url") local URL = "http://" local username = "admin" local password = "password" local cmd = "getDevName" -- /cgi-bin/CGIProxy.fcgi?cmd=getDevName&usr=admin&pwd= local foscamsIPs = { { NO=1, IP="192.168.102.165:88", LOCATION="conservatory"}, { NO=2, IP="192.168.102.38:80", LOCATION="boiler room"}, { NO=3, IP="192.168.102.223:88", LOCATION="Living room"}, { NO=4, IP="192.168.102.245:88", LOCATION="front room"}, { NO=5, IP="192.168.102.104:88", LOCATION="kitchen"}, } for k,v in pairs(foscamsIPs) do -- Read each value. local update = URL .. v["IP"] .. "/cgi-bin/CGIProxy.fcgi?cmd="..cmd.."&usr="..username.."&pwd="..password -- do this for each reading. local status, result = luup.inet.wget(update) print(v["LOCATION"].. " status is " ..status.. " : result is " ..result) end````
      Code/Snippet library
    • Help with luup.call_delay()

      T

      I have this block of lua and I am using luup.call_delay to delay the sending of IR codes. it works as intended but I am trying to eliminate the use of luup.sleep for the delay before the tcp:close() as well. i cant figure out how to implement luup.call_delay() for the tcp:close() and keep the luup.call_delay intact for the delay between the IR codes.

      Thanks in advance.

      function Delay1() --[[HDMI Matrix B1--]] local socket = require("socket") tcp = assert(socket.connect("192.168.255.204", 4998)) tcp:send("sendir,1:3,1,38000,1,69,341,171,22,21,22,21,22,21,22,21,22,21,22,21,22,21,22,21,22,64,22,64,22,64,22,64,22,64,22,64,22,64,22,64,22,21,22,21,22,64,22,21,22,64,22,21,22,21,22,21,22,64,22,64,22,21,22,64,22,21,22,64,22,64,22,64,22,1493,341,85,22,3669" .. "\r\n") luup.sleep(1050) tcp:close() end luup.call_delay("Delay1", 1) function Delay2() --[[HDMI Matrix B2--]] local socket = require("socket") tcp = assert(socket.connect("192.168.255.204", 4998)) tcp:send("sendir,1:3,1,38000,1,69,343,171,21,21,22,21,22,21,22,21,21,21,22,21,22,21,21,21,22,63,22,63,22,63,22,63,22,63,22,63,22,63,22,63,22,63,22,63,22,63,22,21,22,63,22,21,21,21,22,21,22,21,21,22,21,21,22,63,22,21,22,63,22,63,22,63,22,1528,342,85,22,1528" .. "\r\n") luup.sleep(1050) tcp:close() end luup.call_delay("Delay2", 5)
      Code/Snippet library
    For those who registered but didn't received the confirmation email, please send an email to support@smarthome.community with the email you used

    Help with luup.chdev.sync

    Code/Snippet library
    4
    14
    237
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • therealdb
      therealdb last edited by

      I'm struggling to fix the code attached here
      https://github.com/dbochicchio/vera/blob/master/OpenSprinkler/L_VeraOpenSprinkler1.lua#L270,L429

      Under certain circumstances (thanks @DesT!) I see that it's causing a luup reload infinite cycle, because child devices are being created, then deleted. Specifically, I see this in the logs:

      2020-06-01 19:35:30.482   luup.chdev.sync:: [102] Open Sprinkler Test, syncing children
      2020-06-01 19:35:30.482   openLuup.chdev:: deleting [413] Daily Garden
      2020-06-01 19:35:30.482   openLuup.chdev:: deleting [414] Water Level
      2020-06-01 19:35:30.482   openLuup.chdev:: deleting [411] Daily Cedars
      2020-06-01 19:35:30.482   openLuup.chdev:: deleting [412] St-Eustache Rules AM
      2020-06-01 19:35:30.482   openLuup.luup:: device 102 'Open Sprinkler Test' requesting reload
      

      The devices are created (look at line 357/410), but when I call luup.chdev.sync, they got deleted. Any hints? Thanks

      --
      On a mission to automate everything.

      My MS Reactor contrib
      My Luup Plug-ins

      1 Reply Last reply Reply Quote 1
      • therealdb
        therealdb last edited by

        oh boy, I had an epiphany! I was calling append only on new devices, instead of every device! If omitted, the existing devices are removed!

        --
        On a mission to automate everything.

        My MS Reactor contrib
        My Luup Plug-ins

        1 Reply Last reply Reply Quote 1
        • akbooer
          akbooer last edited by

          Yes, indeed. It's a curious construct, but we have learned to live with it.

          My particular frustration is that some of the other parameters, which are standard in the call to create new devices, are not available here. I think that the whole chdev module is only there to avoid Vera's standard reload for every new device created.

          1 Reply Last reply Reply Quote 1
          • parkerc
            parkerc last edited by parkerc

            Hi,

            I have a similar luup.chdev.sync issue, where the sync removes the previously created child, when it should be creating a new child device..

            Example in the logs.

            09	12/23/21 22:26:45.239	Child_Devices::ProcessChildDevice created device 1159 id JohnDevice under 1152 topmost parent 1152 <0x71eb6520>
            09	12/23/21 22:26:45.240	Child_Devices::Synchronize removing 1158 from parent 1152 <0x71eb6520>
            

            My code has a handler that receives a json file, which it processes, and if it doesn’t find an existing entry to update, it will call this code to create a child device ..

            local childDeviceIndex = {}
            
            child_devices = luup.chdev.start(ParentDevice) 
            		-- Tells Luup to start enumerating children for this device based on it's dev_id
            		debug("RoomMe parent lul_device  = " ..ParentDevice)
            		
            		luup.chdev.append(ParentDevice,child_devices, j.id, j.userName.."'s Device", "urn:schemas-nodecentral-net:device:RoomMe:1", "D_RoomMeDevice1.xml", "", "urn:nodecentral-net:serviceId:RoomMeDevice1,Icon=".. iconCalc .."\nurn:nodecentral-net:serviceId:RoomMeDevice1,uiLabel=TBC\nurn:nodecentral-net:serviceId:RoomMeDevice1,userId=".. j.userId .."\nurn:nodecentral-net:serviceId:RoomMeDevice1,id=".. j.id .."\nurn:nodecentral-net:serviceId:RoomMeDevice1,userName="..j.userName.."\nurn:nodecentral-net:serviceId:RoomMeDevice1,roomName="..j.roomName.."\nurn:nodecentral-net:serviceId:RoomMeDevice1,eventType="..j.type.."\nurn:nodecentral-net:serviceId:RoomMeDevice1,eventTime="..j.eventTime.."\nurn:nodecentral-net:serviceId:RoomMeDevice1,sensorId="..j.sensorId.."\nurn:nodecentral-net:serviceId:RoomMeDevice1,eventName="..j.event.name.."", false)
            		
            		debug("New RoomMe device created id = " .. j.id .. " for ".. j.userName)
            	
            		luup.chdev.sync(ParentDevice, child_devices)
            	
            		for k, v in pairs(luup.devices) do
            			if (v.device_num_parent == ParentDevice) then -- populate child device table
            				childDeviceIndex[v.id]=k
            			end
            

            What am I missing in the above that causes it to not append, but replace ?

            1 Reply Last reply Reply Quote 0
            • akbooer
              akbooer last edited by

              @parkerc …

              @therealdb said in Help with luup.chdev.sync:

              I was calling append only on new devices, instead of every device! If omitted, the existing devices are removed!

              …does this not describe your situation?

              parkerc 1 Reply Last reply Reply Quote 0
              • parkerc
                parkerc @akbooer last edited by parkerc

                @akbooer said in Help with luup.chdev.sync:

                @parkerc …

                @therealdb said in Help with luup.chdev.sync:

                I was calling append only on new devices, instead of every device! If omitted, the existing devices are removed!

                …does this not describe your situation?

                Hi, I did read that, but i wasn’t sure if it was related or not, as I didn’t quite understand it..

                All my previous use of creating child devices, was done during the initial set up, as i had everything discovered/defined upfront.

                This time around it’s different, as devices need to be created on the fly, whenever something calls the handler..

                Re-reading the thread again..

                Do I have to retrieve all the attributes/variable of any pre-existing child device that’s associated with that same parent, and recreate them too as part of the ‘append’ process for a new child device that needs to be added?

                therealdb 1 Reply Last reply Reply Quote 0
                • therealdb
                  therealdb @parkerc last edited by

                  @parkerc said in Help with luup.chdev.sync:

                  Do I have to retrieve all the attributes/variable of any pre-existing child device that’s associated with that same parent, and recreate them too as part of the ‘append’ process for a new child device that needs to be added?

                  Yes, you’ll need to append every child decide that must be present. So, both existing and new ones.

                  --
                  On a mission to automate everything.

                  My MS Reactor contrib
                  My Luup Plug-ins

                  1 Reply Last reply Reply Quote 0
                  • parkerc
                    parkerc last edited by parkerc

                    Thanks @therealdb

                    That was what I was afraid of 😞

                    What is the best way to do that?

                    How are you retrieving all the variables of any pre-existing child devices and then recreating them ?

                    Do I just loop through everything that has the parent device ID associated and recreate ?

                    -- Create new one first then through existing ?
                    
                    for k, v in pairs(luup.devices) do
                    	if (v.device_num_parent == ParentDevice) then 
                               << luup.chdev_append - CODE HERE >>
                    end
                    

                    If I append all existing ones first, before creating the new one, I assume that will duplicate them and increment the device numbers before registering the new one?

                    If so, that suggests, I need to append the new one first, and then append the existing ones ? But again won’t that increment the device numbers 🤯

                    There must be an order to which you do this?

                    1 Reply Last reply Reply Quote 0
                    • parkerc
                      parkerc last edited by

                      OK, looking at how others have done it, I can see the following in @toggledbits Switchboard plugin, so this gives me something to work with….

                      --[[ Prep for adding new children via the luup.chdev mechanism. The existingChildren
                      	 table (array) should contain device IDs of existing children that will be
                      	 preserved. Any existing child not listed will be dropped. If the table is nil,
                      	 all existing children in luup.devices will be preserved.
                      --]]
                      local function prepForNewChildren( )
                      	D("prepForNewChildren()")
                      	local existingChildren = {}
                      	for k,v in pairs( luup.devices ) do
                      		if v.device_num_parent == pluginDevice then
                      			local d = {}
                      			d.devnum = k
                      			d.device = v
                      			d.device_file = luup.attr_get( "device_file", k ) or ""
                      			d.device_json = luup.attr_get( "device_json", k ) or "D_BinarySwitch1.json"
                      			d.behavior = getVar( "Behavior", "Binary", k, MYSID )
                      			if d.device_file ~= "" then
                      				table.insert( existingChildren, d )
                      			end
                      		end
                      	end
                      	local ptr = luup.chdev.start( pluginDevice )
                      	for _,d in ipairs( existingChildren ) do
                      		local v = d.device
                      		D("prepForNewChildren() appending existing child %1 (%2/%3)", v.description, d.devnum, v.id)
                      		luup.chdev.append( pluginDevice, ptr, v.id, v.description, "",
                      			d.device_file, "", "", false )
                      	end
                      	return ptr, existingChildren
                      end
                      

                      And then the add child code is here..

                      function jobAddChild( ctype, cname, count, pdev )
                      	assert(luup.devices[pdev].device_type == MYTYPE)
                      	assert(dfMap[ctype])
                      	local df = dfMap[ctype]
                      	count = math.min( 16, math.max( 1, tonumber(count) or 1 ) )
                      	L("Adding %1 children %2 (type %2)", count, df.name, ctype)
                      	gatewayStatus( "Creating child. Please hard-refresh your browser!" )
                      	local ptr,children = prepForNewChildren()
                      	local id = 0
                      	for _,d in ipairs( children ) do
                      		local did = tonumber(d.device.id) or 0
                      		if did > id then id = did end
                      	end
                      	for _=1,count do
                      		id = id + 1
                      		local vv = { MYSID .. ",Behavior=" .. ctype }
                      		table.insert( vv, ",device_json=" .. df.device_json )
                      		table.insert( vv, ",category_num=" .. df.category or 3 )
                      		table.insert( vv, ",manufacturer=" .. DEV_MFG )
                      		table.insert( vv, ",model=Switchboard Virtual " .. df.name )
                      		if df.subcategory then
                      			table.insert( vv, ",subcategory_num=" .. df.subcategory )
                      		end
                      		local nn = cname == nil and ( "Virtual " .. df.name .. " " .. id ) or
                      			( tostring(cname) .. ( count > 1 and tostring(id) or "" ) )
                      		luup.chdev.append( pdev, ptr, id, nn, "",
                      			df.device_file,
                      			"",
                      			table.concat( vv, "\n" ),
                      			false )
                      	end
                      	luup.chdev.sync( pdev, ptr )
                      	return 4,0
                      end
                      
                      1 Reply Last reply Reply Quote 0
                      • parkerc
                        parkerc last edited by

                        Ok, think I’ve got it working now.. FYI for anyone who comes across this.. (thanks to @toggledbits code as the guide.)

                        First off , seems obvious, but prepare for any new devices, but creating a table of what’s there already..

                        local function prepForNewChildren(ParentDevice)
                        	-- Create table of existing child devices associated with the parent device
                        	local existingChildren = {}
                        	for k,v in pairs( luup.devices ) do
                        		if v.device_num_parent == ParentDevice then
                        			local d = {}
                        			d.devnum = k
                        			d.device = v
                        			d.device_file = luup.attr_get( "device_file", k ) or ""
                        			d.device_json = luup.attr_get( "device_json", k ) or ""
                        			if d.device_file ~= "" then
                        				table.insert( existingChildren, d )
                        			end
                        		end
                        	end
                        	
                        	-- Start enumerating children based on the parent's device_id
                        	local ptr = luup.chdev.start( ParentDevice )
                        	for _,d in ipairs( existingChildren ) do
                        		local v = d.device
                        		luup.chdev.append( pluginDevice, ptr, v.id, v.description, "",
                        			d.device_file, "", "", false )
                        	end
                        	return ptr, existingChildren
                        end
                        

                        Then utilise your create child code/function, that calls the what children are already there function first 🙂

                        local function createNewRoomMeChildDevice(j, ParentDevice)
                        	-- j is the decoded json provided by the handlers which has the new child device info
                        	debug("Creating child device for lul_device  = " ..ParentDevice)
                        	
                        	-- prepare for the addition of new child devices
                        	local ptr,children = prepForNewChildren(ParentDevice)
                        	-- Create and append new child device to the existing parent device
                        	luup.chdev.append(ParentDevice,ptr, j.id, j.userName.."'s Device", "urn:schemas-nodecentral-net:device:RoomMe:1", "D_RoomMeDevice1.xml", "", "urn:nodecentral-net:serviceId:RoomMeDevice1,Icon=".. iconCalc .."\nurn:nodecentral-net:serviceId:RoomMeDevice1,uiLabel=TBC\nurn:nodecentral-net:serviceId:RoomMeDevice1,userId=".. j.userId .."\nurn:nodecentral-net:serviceId:RoomMeDevice1,id=".. j.id .."\nurn:nodecentral-net:serviceId:RoomMeDevice1,userName="..j.userName.."\nurn:nodecentral-net:serviceId:RoomMeDevice1,roomName="..j.roomName.."\nurn:nodecentral-net:serviceId:RoomMeDevice1,eventType="..j.type.."\nurn:nodecentral-net:serviceId:RoomMeDevice1,eventTime="..j.eventTime.."\nurn:nodecentral-net:serviceId:RoomMeDevice1,sensorId="..j.sensorId.."\nurn:nodecentral-net:serviceId:RoomMeDevice1,eventName="..j.event.name.."", false)
                        		
                        	debug("New RoomMe device created id = " .. j.id .. " for ".. j.userName)
                        	
                        	-- Sync all child devices
                        	luup.chdev.sync(ParentDevice, ptr)
                        end
                        
                        1 Reply Last reply Reply Quote 0
                        • toggledbits
                          toggledbits last edited by

                          In your case, you likely have no need of a separate object to hold the child data in the pre-scan, you can just use existingChildren as an array of device numbers (from k in the first/pre-scan loop) and then use it to index into luup.devices in the chdev.appends later.

                          You probably don't even need the pre-scan at all in most cases, you can just iterate over luup.devices inside the open chdev and add the existing devices directly, without creating existingChildren and a second loop.

                          Author of Multi-system Reactor and Reactor, DelayLight, Switchboard, and about a dozen other plugins that run on Vera and openLuup.

                          1 Reply Last reply Reply Quote 1
                          • parkerc
                            parkerc last edited by

                            Hi @toggledbits

                            Do you mean something like this..

                            local function createChildDevices(ParentDevice, decodedJSON)
                            	-- build table of any existing child devices
                            	local existingChildren = {}
                            	for k,v in pairs( luup.devices ) do
                            		if v.device_num_parent == ParentDevice then
                            			local d = {}
                            			d.devnum = k
                            			d.device = v
                            			d.device_file = luup.attr_get( "device_file", k ) or ""
                            			d.device_json = luup.attr_get( "device_json", k ) or ""
                            			if d.device_file ~= "" then
                            				table.insert( existingChildren, d )
                            			end
                            		end
                            	end
                            	
                            	-- Start enumerating children based on the parent device_id
                            	local ptr = luup.chdev.start( ParentDevice )
                            		for _,d in ipairs( existingChildren ) do
                            			local v = d.device
                            			luup.chdev.append( pluginDevice, ptr, v.id, v.description, "",
                            			d.device_file, "", "", false )
                            		end
                            		
                            	-- Create and append new child device to the existing parent device
                            	luup.chdev.append(ParentDevice,ptr, decodedJSON.id, decodedJSON.userName.."’s Device", "urn:schemas-nodecentral-net:device:RoomMe:1", "D_RoomMeDevice1.xml", "", "urn:nodecentral-net:serviceId:RoomMeDevice1,Icon=".. iconCalc .."\nurn:nodecentral-net:serviceId:RoomMeDevice1,uiLabel=TBC\nurn:nodecentral-net:serviceId:RoomMeDevice1,DeviceName="..decodedJSON.device.name.."", false)
                            	
                            	-- Sync all child devices
                            	luup.chdev.sync(ParentDevice, ptr)
                            end
                            
                            1 Reply Last reply Reply Quote 0
                            • toggledbits
                              toggledbits last edited by

                              That's what I mean you don't need to do... is that what you meant?

                              Author of Multi-system Reactor and Reactor, DelayLight, Switchboard, and about a dozen other plugins that run on Vera and openLuup.

                              1 Reply Last reply Reply Quote 0
                              • parkerc
                                parkerc last edited by

                                No, sorry - that was my altered version 🙂

                                • I had changed it from using two separate functions to just the one. I tried to do as you said, but I couldn’t see what else I could remove without breaking it ?
                                1 Reply Last reply Reply Quote 0
                                • First post
                                  Last post

                                Welcome. If you’d like to participate in the discussion, rather than just read, then you can join the forum. As a member, you can interact with others here to share your experience and ask the questions you need answered.

                                Powered by NodeBB | Contributors
                                Hosted freely by PointPub Media Communications Inc. | Contact us