Lua Examples of accessing API's for Fronius, Sonos and Tech sterowniki

Discussion in 'C-Bus Automation Controllers' started by gte242, Oct 17, 2021.

  1. gte242

    gte242

    Joined:
    Apr 7, 2017
    Messages:
    6
    Likes Received:
    3
    Location:
    Poland
    Hi

    After a fun couple of days I thought I would share my Lua code for accessing Fronius Solar Inverters through the API and Tech Sterowniki (underfloor heating controllers. Both use request http command and return a json file which then can be queried and read the relevant values. I have included both API manuals as I have used only the data I need in the examples.

    Sonos - I converted the code from the other forum which used Wiser 2.

    First one below is for Fronius.

    Code:
    -- importing HTTP and json packages
    local http = require'ssl.https'
    local json = require('json')
    local ltn12 = require("ltn12")
    
    -- Create table, request json file and store (sink)
    local data = {}
    local r, c , h, s  = http.request {
          url = 'http://<your local IP>/solar_api/v1/GetInverterRealtimeData.cgi?Scope=Device&DataCollection=CommonInverterData&DeviceId=1',
          method = 'GET',
          headers = {
            ["Content-Type"] = "application/json"
                  },
                  sink = ltn12.sink.table(data)
                }
    
    --combine table and decode json data.
    local response = table.concat(data)
    local data2 = json.decode(response)
    
    --Select data
    totalenergy = data2.Body.Data.TOTAL_ENERGY.Value
    yearenergy = data2.Body.Data.YEAR_ENERGY.Value
    dayenergy = data2.Body.Data.DAY_ENERGY.Value
    
    --Write to user parameter
    SetUserParam(0, 20, totalenergy)
    SetUserParam(0, 21, yearenergy)
    SetUserParam(0, 22, dayenergy)
    The second is for Tech Sterowniki. This is done through quering the emodul.pl API interface. Please note obvious for secuity reasons <userID>, <module no> and <authorisation code> have been removed. These can be generated by using postman application and following the API guide attached...

    Code:
    -- importing HTTP and json packages
    local http = require'ssl.https'
    local json = require('json')
    local ltn12 = require("ltn12")
    
    -- Create table, request http, authorisation code in header and sink into table.
    
    local data = {}
    local r, c , h, s  = http.request {
          url = 'https://emodul.eu/api/v1/users/<userID>/modules/<module no>',
          method = 'GET',
          headers = {
            ["Authorization"] = "Bearer <Authorisation code>",
                     ["Content-Type"] = "application/json"
                  },
                  sink = ltn12.sink.table(data)
                 }
    
    --combine table and decode json data.
    local response = table.concat(data)
    local data3 = json.decode(response)
    
    --Transfer data to Cbus User parameter - Salon[1}, Kuchnia[2], Wiatrołap[3], Pokój Dół[4], Korytarz Dół[5], Toleta[6], Pomp. Gosp[7], Garaż[8]
    --Create decimal by divide by ten as number comes without it.
    
    salontemp = data3.zones.elements[1].zone.currentTemperature / 10
    kuchniatemp = data3.zones.elements[2].zone.currentTemperature /10
    wiatrolaptemp = data3.zones.elements[3].zone.currentTemperature /10
    pokojdoltemp = data3.zones.elements[4].zone.currentTemperature /10
    korytarztemp = data3.zones.elements[5].zone.currentTemperature /10
    toletatemp = data3.zones.elements[6].zone.currentTemperature /10
    pompgosptemp = data3.zones.elements[7].zone.currentTemperature /10
    garaztemp = data3.zones.elements[8].zone.currentTemperature /10
    
    --Transfer data to Cbus User parameter - Sypalnia[9], Łazienka Z&G[10], Pokój Gier[11], Spare[12], Korytarz Gora[13], Łazienka[14],  Pokój Oskar[15], Pokój Daniel [16]
    
    sypalniatemp = data3.zones.elements[9].zone.currentTemperature /10
    lazienkazgtemp = data3.zones.elements[10].zone.currentTemperature /10
    pokojgiertemp = data3.zones.elements[11].zone.currentTemperature /10
    --Sparetemp = data3.zones.elements[12].zone.currentTemperature /10
    korytarzgoratemp = data3.zones.elements[13].zone.currentTemperature /10
    lazienkatemp = data3.zones.elements[14].zone.currentTemperature /10
    pokojoskartemp = data3.zones.elements[15].zone.currentTemperature /10
    pokojdanieltemp = data3.zones.elements[16].zone.currentTemperature /10
    
    -- send to userparameter
    SetUserParam(0, 4, salontemp)
    SetUserParam(0, 5, kuchniatemp)
    SetUserParam(0, 6, wiatrolaptemp)
    SetUserParam(0, 7, pokojdoltemp)
    SetUserParam(0, 8, korytarztemp)
    SetUserParam(0, 9, toletatemp)
    SetUserParam(0, 10, pompgosptemp)
    SetUserParam(0, 11, garaztemp)
    SetUserParam(0, 19, sypalniatemp)
    SetUserParam(0, 12, lazienkazgtemp)
    SetUserParam(0, 13, pokojgiertemp)
    SetUserParam(0, 14, Sparetemp)
    SetUserParam(0, 15, korytarzgoratemp)
    SetUserParam(0, 16, lazienkatemp)
    SetUserParam(0, 17, pokojoskartemp)
    SetUserParam(0, 18, pokojdanieltemp)
    
    An finally SONOS. Once again I used node js on windows setup and run the following code to give me the API.
    https://github.com/jishi/node-sonos-http-api

    Then on the SHAC side I have the following code examples. I use an EDLT to trigger the code.

    Play/Pause
    Code:
    playpause = event.getvalue()
    if (playpause == 255) then
      http = require'socket.http'
      body = http.request("http://<Windows PC IP>:5005/Bedroom/play")
    else
      http = require'socket.http'
      body = http.request("http://<Windows PC IP>:5005/Bedroom/pause")
    end
    
    -- Read state of amp, extract volume level, convert to number and send to cbus state
    http = require'socket.http'
    body = http.request("http://<Windows PC IP>:5005/Bedroom/state")
    volumestring = string.match(body,'volume":(%d+)')
    volumenumber = tonumber(volumestring)
    volumelevel = CBusPctToLevel(volumenumber)
    SetCBusLevel(0, 56, 134, volumelevel,0)
    Volume Control

    Code:
    --send volume level
    sendvolumenum = event.getvalue()
    sendvolumep = CBusLevelToPct(sendvolumenum)
    sendvolumestring = tostring(sendvolumep)
    http = require'socket.http'
    body = http.request("http://<Windows PC IP>:5005/Bedroom/volume/"..sendvolumestring)
    log(body)
    Start radio, update volume state and play if stopped.

    Code:
    --change to magic
    http = require'socket.http'
    body = http.request("http://<Windows PC IP>:5005/ Bedroom/Favourite/Magic")
    
    -- Read state of amp, extract volume elevel, convert to number and send to cbus state
    http = require'socket.http'
    body = http.request("http://<Windows PC IP>:5005/Bedroom/state")
    volumestring = string.match(body,'volume":(%d+)')
    volumenumber = tonumber(volumestring)
    volumelevel = CBusPctToLevel(volumenumber)
    SetCBusLevel(0, 56, 134, volumelevel,0)
    
    -- Read state of amp, extract play state and set to correct state
    playstate = string.match(body,'playbackState":"(%u%u%u%u%u%u%u)')
    if  ('STOPPED' == playstate) then
        SetCBusState(0, 56, 133, false)
    elseif ('PLAYING' == playstate) then
      SetCBusState(0, 56, 133, true)
    end
    Hoping this will help someone. Happy Lua coding.
     

    Attached Files:

    gte242, Oct 17, 2021
    #1
    Shiney2512 likes this.
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.