Jump to content

Recommended Posts

This is a thread for the fibaroapiHC3.lua sdk that is under development (keeping it separate from the HC3 QuickApps coding - tips and tricks thread)

I've started to run and test HC3 QuickApps offline and have made a fibaroapi.lua file that can be included to emulate the fibaro calls and call out to the HC3.

This means that a whole QA can be developed offline, debugged and verified before deploying to the HC3. Something that significantly reduces the development process.

 

fibaroapiHC3.lua: fibaroapiHC3.lua(v0.145) 

Latest version always here https://raw.githubusercontent.com/jangabrielsson/EventRunner/master/fibaroapiHC3.lua

The code is updated weekly so please make sure you have the latest...

It's similar to the old fibaroapi for the HC2 in a thread started by @riemers but with more extensive support to create a better "offline experience"... in fact, it's really an emulator than just a SDK..

 

(enable English subtitles to see instructions)

(note the nice tooltip and autocompletion of fibaro commands we get with the fibaroapiHC3plugin for ZBS)

 

Some benefits:

  • Use a modern development environment such as ZeroBrane Studio zerobrane-logo.png.6e96ab226afa8e1a54036c331e5169ad.png  (free for Mac/PC/Linux, HC3 plugin here) on your laptop/PC to develop and debug QuickApps and Scenes
  • Step through code, inspect Lua variables, set break-points etc - all that is possible in a good IDE.
  • Faster to pin-point errors as the error messages are better than on the HC3 - stack-traces etc.
  • Use the whole Fibaro API fibaro.call etc and net.HTTPClient(), setTimeout(), json.ecode/decode, QuickApp self:functions like self:getVariable, self:updateView
  • Support for MQTT client and QuickApp child devices
  • Both QuickApps and Scenes are supported. Scenes support most conditions and are triggered by real triggers from the HC3 or simulated triggers.
  • Speed up clock to run faster than real time, to watch a Scene or QuickApp over days/weeks/months in seconds.
  • Start at any given time and date - test if your scene behaves on week-ends ? 
  • Automatically create a proxy QuickApp on the HC3 that sends UI clicks back to the code your are running and displays self:updateView updates. This way you can test the QuickApp UI (buttons etc) and still debug the main code on your PC.
  • Run completely disconnected from the HC3 simulating devices and other resources (now you can take your coding with you on your vacation :-) )
    • There is a possibility to download resource definitions from the HC3 and use them (devices, globals etc) while running disconnected.
  • Move the code as-is over to the HC3 when it runs in the emulator - and it will most likely run on the HC3. Scenes needs to be moved to conditions/actions part on the HC3 - may automat that in the future.
  • Oh, and an emulated Web GUI for the quickApp so you can try out button/slider clicks without connecting to the HC3.
  • And lastly, it makes it fun to develop code for the HC3 :-)

 

 

To get going define

hc3_emulator.credentials = {ip=<HC3_IP>, user=<username>, pwd=<password>} }

and include

dofile("fibaroapiHC3.lua")

An example of a minimal QA can look like

if dofile and not hc3_emulator then
  hc3_emulator = {
    name = "My QA",
    poll=1000,         -- Poll for triggers from the HC3 every 1s
    credentials = {ip="192.168.1.X", user="<user>", pwd="<password>"}
  }
  dofile("fibaroapiHC3.lua")
end

function QuickApp:onInit()
  fibaro.call(88,"turnOn") -- turns on device 88 on your HC3
end

We wrap the emulator specific stuff inside "if dofile and not hc3_emulator then .... end" as the symbol 'dofile' is not defined on the HC3 and will thus be false and not include the code - This means that we can take the code as-is and paste it into the HC3 and it works.

 

Most of the functions are there and will be improved over time.

  • There are support for net.HTTPClient() and setTimeout/clearTimeout and api.*
  • There are support for getting triggers and events from the HC3
    • Support for auto-creating a QuickApp proxy with UI elements that sends events back to the code being debugged.
  • There are support for both QuickApps and Scenes (with conditions)

 

Currently supported (v 0.126)

fibaro.debug(type,str) 
fibaro.warning(type,str) 
fibaro.trace(type,str) 
fibaro.error(type,str)

fibaro.call(deviceID, actionName, ...) 
fibaro.getType(deviceID) 
fibaro.getValue(deviceID, propertyName)
fibaro.getName(deviceID) 
fibaro.get(deviceID,propertyName) 
fibaro.getGlobalVariable(varName)
fibaro.setGlobalVariable(varName ,value) 
fibaro.getRoomName(roomID)
fibaro.getRoomID(deviceID)
fibaro.getRoomNameByDeviceID(deviceID) 
fibaro.getSectionID(deviceID)
fibaro.getIds(devices)
fibaro.getAllDeviceIds()
fibaro.getDevicesID(filter)
fibaro.scene(action, sceneIDs)
fibaro.profile(profile_id, action)
fibaro.callGroupAction(action,args)
fibaro.alert(alert_type, user_ids, notification_content) 
fibaro.alarm(partition_id, action)
fibaro.setTimeout(ms, func)
fibaro.clearTimeout(ref)
fibaro.emitCustomEvent(name)
fibaro.wakeUpDeadDevice(deviceID)
fibaro.sleep(ms)

net.HTTPClient()
net.TCPSocket()
net.UDPSocket()
api.get(call) 
api.put(call <, data>) 
api.post(call <, data>)
api.delete(call <, data>)

setTimeout(func, ms)
clearTimeout(ref)
setInterval(func, ms)
clearInterval(ref)

mqtt.Client.connect(uri, options)
<mqttclient>:addEventListener(message,handler)
<mqttclient>:subscribe(topic, options) 
<mqttclient>:unsubscribe(topics, options) 
<mqttclient>:publish(topic, payload, options) 
<mqttclient>::disconnect(options) 


plugin.mainDeviceId

class QuickAppBase
class QuickApp
class QuickAppChild

QuickApp:onInit() -- called at startup if defined
QuickApp - self:setVariable(name,value) 
QuickApp - self:getVariable(name)
QuickApp - self:debug(...)
QuickApp - self:updateView(elm,type,value)
QuickApp - self:updateProperty()
QuickApp - self:createChildDevice(props,device)
QuickApp - self:initChildDevices(table)

sourceTrigger - scene trigger
Supported scene events:
  {type='device', id=<number>, property=<string>, value=<value>}
  {type='global-variable', property=<string>, value=<value>}
  {type='date', property="cron", value={ <time> }}
  {type='date', property="sunset", value={ <time> }}
  {type='date', property="sunrise", value={ <time> }}
  {type='manual', property='execute'}
  {type='custom-event', name=<string>}
  {type='device' property='centralSceneEvent', id=<number>, value={keyId=<number>, keyAttribute=<string>}}

json.encode(expr)
json.decode(string)

---------------------------------------
-- Emulator properties/functions
---------------------------------------
hc3_emulator properties             
hc3_emulator.id=<QuickApp ID>,       -- default 999
hc3_emulator.poll=<poll intervall>,  -- default false. Interval i ms to poll for new rigger from the HC3. 1000-2000 is reasonable...
hc3_emulator.type=<type>,            -- default "com.fibaro.binarySwitch"
hc3_emulator.speed=<speedtime>,      -- default false
hc3_emulator.proxy=<boolean>         -- default false. Creates a proxy on the HC3, ignore id.
hc3_emulator.quickApp=<boolean>      -- default false. Connects to an existing quickapp on the HC3 with given id
hc3_emulator.UI=<UI table>,          -- default {}
hc3_emulator.quickvars=<table>,      -- default {}
hc3_emulator.loadDB=<boolean>        -- If true tries to load resource database (only if offline==true)
   
hc3_emulator.createQuickApp{               -- creates and deploys QuickApp on HC3
              name=<string>,            
              type=<string>,
              code=<string>,
              UI=<table>,
              quickvars=<table>,
              dryrun=<boolean>
              } 
hc3_emulator.createProxy(<name>,<type>,<UI>,<quickVars>)  -- create QuickApp proxy on HC3 (usually called with fibaro._start)
hc3_emulator.post(ev,t)                                   -- post event/sourceTrigger 
hc3_emulator.offline = <boolean>                          -- Set to true in beginning of file if running simulated devices..
hc3_emulator.createDevice(deviceID,deviceType)            -- Create an offline device of a given type. When offline device are also autocreated of type binarySwitch. More doc on this is coming
hc3_emulator.copyFromHC3()                                -- Downloads resources from HC3 and stores in HC3sdk.db

If someone wants to try this in another IDE than Zerobrane that I use (like Visual Studio) the only thing that could be an issue is to have access to the Lua libraries

require ("ssl.https") 
require("socket.http")
require("socket")
require("ltn12")

They are pretty standard lua libraries - based on LuaSocket. @10der has managed to run it under Visual Studio on Windows.

 

Any improvements are happily received (in code) and credits will be due granted.

 

Links to notable post

 

Changelog:

v 0.67 - numerous bug fixes caused by the restructuring. hc3_emulator.start{startTime="07:00 4/5/2000"} - will start the simulation at the given time. 

v 0.68 - fibaro.debug behaves more like original.

v 0.70 - better offline support and speeding.

v 0.72 - More offline and support for downloading HC3 resources to be used while running disconnected from the HC3

v 0.73 - Various speed-time related bugs

v 0.75 - Better http sync behaviour. Set hc3_emulator.asyncHTTP=true to get some pseudo asynchronous behaviour

v 0.77 - Support for 5.030.45. Initial support for childDevices and fixes for the changed handling of UI events

v 0.78 - UI fix. Name of callbacks defaults to button.."Clicked", unless you have a onReleased=name or onChanged=name in the UI table struct.

v 0.80 - Fixed bug in self:getVariable and self:setVariable

v 0.81 - Better quickVariables handling for proxies, and self.childDevices list updated when children are deleted.

v 0.83 - self:getVariable returns the empty string "" if the variable does not exists according to the latest behaviour on the HC3... 'class' is not redefined if available from Luabind... However, I've not had a chance to test if it's 100% compatible yet...

v 0.84 - Initial support for mqtt. You need to have installed https://github.com/xHasKx/luamqtt so that require("mqtt") works from fibaroapiHC3.lua. I have tried to mimic the HC3 mqtt api but I have not really used mqtt that much so if someone uses it with fibaroapiHC3.lua and discovers if stuff is not compatible with the HC3 implementation please let me know and we fix it.

v 0.85 - Compatibility fix for function 'class' to adhere more closely to the HC3/luabind version

v 0.90 - Cleanup of code, Better handling of children and QuickApps, ZBS color output with ansi escapes; hc3_emulator.colorDebug=true

v 0.93 - New model for QuickApp proxies. Better child device compatibility.

v 0.95 - Various bug fixes - log prints more in line with HC3 log console. fibaro.emitCustomEvent bug fix.

v 0.98 - First support for backup/download/upload with the ZeroBrane plugin (another post here

v 0.99 - Better trigger handling and new way to include SDK in your QA/scene code. No hc3_emulator.start at the end.

v 0.100 - Web GUI emulator for QuickApps. New format for using credentials.lua. Bug fixes...

v 0.102 - Better handling of children and their quickAppVariables

v 0.104 - Rewrite of offline mode. Better web UI support.

v 0.105 - Support for new QA file format (proxies work again)

v 0.106 - Added support for net.UDPSocket()

v 0.109 - UDPSocket bug fix. ( @10der), property() support for class() - much harder than it looks...

v 0.110 - Oops, serious bug in 'class' affecting ...everything. Hopefully fixed.

v 0.111 - Removed unnecessary os.exit(). urlencode api calls ( @10der)

v 0.112 - UDP fixes. ( @10der)

v 0.114 - Bug fix (global 'self' escaped)

v 0.115 - Bug in url encode for api calls. UDPSocket :bind(ip,port) function added.

v 0.116 - :bind(ip,port) really fixed....

v 0.117 - startup fix

v 0.119 - "Softer os.exit()" - better compatibility with Visual Studio (thanks @10der)

v 0.120 - Debugger friendly QuickApp class (no __index). First version of file/backup

v 0.121 - api.get bug fix. Faster proxy/deploy.

v 0.123 - QuickApp:setVariable bug (thanks  @10der)

v 0.124 - fibaro.clearTimeout added, MQTT fixes.

v 0.125 - fibaro.alarm() was buggy - fixed. Set self.USERPIN to pincode to allow fibaro.alarm("disarm") to be allowed from emulator.

v 0.126 - fix __fibaro_get_device() ( @10der)

v 0.128 - fix sort order of triggers. Default room in offline mode ( @10der)

v 0.130 - fix UI handling ( @rangee. More UI options.

v 0.131 - fix uiCallbacks not always updating when updating proxy

v 0.135 - fixes...

v 0.137 - TCPSocket fixes

v 0.138 - setTimeout for negative times are inserted in the queue.... i.e. will execute as soon as possible.

v 0.140 - fixed bug with setInterval (clearInterval within a setInterval function didn't work...)

v 0.141 - fix bug in net.TCPClient()

v 0.145 - bug in printout of sockets... stricter class constructor requirements

Edited by jgab
  • Like 1
  • Thanks 3
Link to post
Share on other sites
  • Replies 113
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

This is a thread for the fibaroapiHC3.lua sdk that is under development (keeping it separate from the HC3 QuickApps coding - tips and tricks thread) I've started to run and test HC3 QuickApps off

The SDK can be useful for coding and debugging large projects with a lot of moving parts. Zerobrane studio allows for setting conditional breakpoints and live variables watches which is real time save

New version v0.120. Hopefully this version is usable in Visual Studio (Windows) thanks to debugging effort from @10der.    Besides being an emulator for the HC3, fibaroapiHC3.lua is als

Posted Images

Posted (edited)

Here is a post with some notes on the implementation of the SDK.

 

The overall components looks like this

mainarch.thumb.png.914fa8f632f4876af992cb7ef01e0528.png

From a scene or a quickapp you interact with the HC3 using the fibaro.*() functions, like fibaro.call(id,action), or directly using the api.*() calls, like api.get("/devices/88")

If you run remotely towards the HC3 the api.*() commands are translated to http REST commands to the HC3.

That's pretty straightforward.

 

The SDK supports to automatically install a proxy QA for the QA you are developing with the SDK. That proxy traps all the UI events, when you press a button or drag a slider, and call backs to the SDK. The SDK starts a WebAPI server on port 6872 when you run the code that listens for incoming requests from the HC3, requests with UI triggers. The WebAPI then looks up the corresponding QuickApp:function in the QA you are developing and calls it. In this way your QA can react to UI clicks and you can debug it.

All the QuickApp functions available from self:*, like self:updateView() or self:getVariable() are just translated to api.*() calls so they go to the HC3.

 

There is also a remote event loop that continuously polls the HC3 for new events using the /refresStates REST api. New events can cause triggers to start your scene if you are developing a scene. Scenes have a "conditions" part that is compiled and filters the triggers to decide if a trigger should start the scene.

If you run a QuickApp, the remote event loop doesn't do that much for you, but behind the scenes we cache events that we get so that remote calls like fibaro.getValue don't have to make a remote calls every time.

 

If you set 'hc3_emulator.offline=true", the api.*() commands sends their requests to a local api handler with a database with the resources, like devices, globalVariables etc. Remember that the api.*() calls do REST get/post/put/delete operations.

The database checks if the actions changes a value and in that case emits a trigger that scenes can trigger on.

 

That's more or less it.

 

The actual code when folded looks like this:

code.thumb.png.64c0439963ed7d578621c7f5b097f98e.png

It's one big honking  file with everything included. Part of the philosophy is that it should be easy to setup. Now it's just one file in the same folder as the code you are working on. The non-standard Lua dependencies that exists is on the included libraries for socket and http - but they are included with Zerobrane, and should be available for most other environments (they seem to be based on Luasocket)

 

So, first in the file is the version - always use the latest.

Then some libraries that is needed for socket and http functions - they come bundled with ZeroBrane Studio but may need to be added for other environments.

Local variables that are important. We create our own versions of os.time() and os.date() so we can speed up the time if wanted.

Then the 9 modules that make up the SDK.

  • FibaroAPI - all the fibaro.*() and api.*() functions are defined here
  • Timer - The important implementation of setTimeout resides here. That is the heart or engine of the SDK that drives all the other parts. It can also do tricks like speeding up the time.
  • QuickApp - the definition of QuickApp.* and some extra functions for creating proxies etc.
  • Scene - compiler for "conditions" that filter triggers.
  • Trigger - the remote event loop that polls the HC3 for events
  • Utilities - common code used by the other modules
  • Json - a open source json library from Rix
  • WebAPI - the web server for remote calls from the HC3. In the future it could also serve up som GUI - maybe simulate QuickApp GUI too?
  • Offline - the offline database and the simulated rest APIs used when you have set hc3_emulator.offline=true

at the bottom we load the module in the right order needed, and add some functions to the hc3_emulator that is good to have.

...and then we define the hc3_emulator.start{} function used to start the emulator and that is called from the user's code. It's decides if the code is a QA or a Scene and calls runQA or runScene from respective module.  The last thing that the hc3_emulator.start{} does is to do Timer.start() that runs and schedules all the timers that drive the emulator in a tight loop. Every piece of code that gets called after that somehow originates from a timer/setTimout (polling the HC3, the WebAPI, users own timers etc)

 

Despite the ~3000 lines of code there are still things that are incomplete:

  • Scene handling could be better. Some conditions like cron-intervals are not yet supported (mostly because I think the semantic is iffy). Regular cron with "match" works + sunset/sunrise
  • Offline handling only deals with basic resources like devices, globals, and customEvents at the moment.
  • Better error checks...
  • More support for tracing...
  • Would like to have an interpreter plugin for ZBS so that the header and start can be omitted from the code.
  • ...and of course - bugs bugs bugs...

 

You are all welcome to improve the code if you find it useful.

Edited by jgab
  • Thanks 1
Link to post
Share on other sites

Here's error report.

When trigger incoming,  if value contains "%" char then  it return's error.

fibaroapiHC3.lua:1490: bad argument #2 to 'format' (no value)

line1490 : local str = format(table.unpack(args))

Link to post
Share on other sites
Posted (edited)
1 hour ago, rangee said:

Here's error report.

When trigger incoming,  if value contains "%" char then  it return's error.

fibaroapiHC3.lua:1490: bad argument #2 to 'format' (no value)

line1490 : local str = format(table.unpack(args))

Thanks for the report, a classic bug that I accidentally have done many times - will fix asap.

Edited by jgab
Link to post
Share on other sites
48 minutes ago, rangee said:

Here's error report.

When trigger incoming,  if value contains "%" char then  it return's error.

fibaroapiHC3.lua:1490: bad argument #2 to 'format' (no value)

line1490 : local str = format(table.unpack(args))

 

Fixed bug in format. v0.66

Link to post
Share on other sites
Posted (edited)

Here is an example running a scene.

The HC3 scene code is from 

that @robw et.al has been testing out.

 

I make no claims about the correctness of the code, but that's not the purpose of this post. Instead, let's try to run it offline, without using the HC3 at all, simulating the devices involved.

We use the fibaroapiHC3.lua code and Zerobrane.

Because scenes are divided up in a 'conditions' section and an 'actions' sections we need to put those parts in

hc3_emulator.conditions = { }

and

function hc3_emulator.actions()
   ... action code
end

The first being a Lua table and the second being a Lua function, because we need to call it when the scene is triggered.

Because we are running offline we need to define the devices involved (type of devices) and their initial states.

We do that inside a "preamble" function

function hc3_emulator.preamble()
   ... initialisation code
end

The complete "simulated" scene code looks like

if dofile and not hc3_emulator then
  hc3_emulator = {
     poll=1000,
     traceFibaro=true,
  --speed=true,
  --runSceneAtStart=true,
  --startTime = "07:00 3/2"
  
  dofile("fibaroapiHC3.lua")
end

function hc3_emulator.preamble() -- This runs before the scene starts up - place to do initializations for offline execution.
  hc3_emulator.offline = true
  -- api.post("/globalVariables/",{name="HomeTable",value=""}) -- create if not exist
  local jt = { Bathroom={ bathroomlight=21, motion=37, lux=23}}
  fibaro.setGlobalVariable("HomeTable", json.encode(jt))
  local motion = hc3_emulator.create.motionSensor(37)   -- Create devices
  local lux = hc3_emulator.create.luxSensor(23)
  local dimmer = hc3_emulator.create.dimmer(21)
  lux.setValue('value',100)      -- Initiate values
  dimmer.turnOff()               -- start with dimmer off (default)
  motion.turnOff()               -- start with sensor off (default)
  motion.delay(5).breach(20)      -- Wait 5s, breach and restore after 20s
end

hc3_emulator.conditions = {
  conditions = { {
      id = 37,
      isTrigger = true,
      operator = "==",
      property = "value",
      type = "device",
      value = true
      } },
  operator = "all"
}

function hc3_emulator.actions()
  local hc = fibaro
  jT = json.decode(hc.getGlobalVariable("HomeTable")) 

  local light = {jT.Bathroom.bathroomlight}
  local motion = jT.Bathroom.motion
  local lux = tonumber(hc.getValue(jT.Bathroom.lux, "value"))
  local luxmin = 500

  count = 0
  function checkLights()
    if #light > 0 then
      for i = 1, #light
      do
        if hc.getValue(light[i], "state") then count = count+1 end
      end
    end
  end

  function turnon()
    if #light > 0 then
      for i = 1, #light
      do
        hc.call(light[i],"turnOn");
        hc.debug("","Turning on");
        hc.sleep(100)
      end
    end
  end

  function turnoff()
    if #light > 0 then
      for i = 1, #light
      do
        hc.call(light[i],"turnOff");
        hc.debug("","Turning off");
        hc.sleep(100)
      end
    end
  end

  checkLights()
  if count >0 then state = "On" else state = "Off" end

  hc.debug("","Current lux: ",lux)
  hc.debug("","minlux: ",luxmin)
  if state == "Off" then
    if luxmin < lux then hc.debug("","room to light to turn on  lights")
    else
      local maxTime = 3*60  -- max time the sensor should be safe before turning off
      local sleepTime = 3   -- time in seconds between each check of the sensor

      turnon()

      local safeTime = 0
      while safeTime < maxTime do
        hc.sleep(sleepTime*1000)                 
        safeTime=safeTime+sleepTime                   -- count up safeTime
        hc.debug("","Counting up safeTime ",safeTime,maxTime)  

        count = 0 
        checkLights()
        if count >0 then state = "On" else state = "Off" end
        if state == "Off" then hc.debug("","Light(s) turned off manual");
          break 
        end

        if hc.getValue(motion,"value") then -- motion breached
          safeTime=0                                 -- reset safeTime
          hc.debug("","Reset")
        end
      end 

      turnoff()
    end
  else hc.debug("","Light manual turned on")
  end
  hc.debug("","Scene ended")
end

In the preamble, we create the devices involved, dimmer, motion sensor and lux sensor. We initiate them to the values they should have when we start up.

Then we end by breaching the motion sensor after 5 seconds, and then we set it back to safe after another 20s.

The scene ’condition’ is defined so that the scene should be triggered when the motion sensor is set to safe.

Running the code produces.

|SYS  | 13.03.2020 12:05:18: HC3 SDK v0.70
|SYS  | 13.03.2020 12:05:18: Speeding 48 hours
|SYS  | 13.03.2020 12:05:18: Created Event server at 192.168.1.184:6872
|SDBG | 13.03.2020 12:05:23: Incoming trigger:{"value":"{\"Bathroom\":{\"motion\":37,\"bathroomlight\":21,\"lux\":23}}","property":"HomeTable","type":"global-variable"}
|SDBG | 13.03.2020 12:05:23: DeviceId:37 (com.fibaro.motionSensor) created
|SDBG | 13.03.2020 12:05:23: DeviceId:23 (com.fibaro.lightSensor) created
|SDBG | 13.03.2020 12:05:23: DeviceId:21 (com.fibaro.multilevelSwitch) created
|SDBG | 13.03.2020 12:05:23: Incoming trigger:{"id":23,"old":0,"type":"device","value":100,"property":"value"}
---------------------------- Scene started at Fri Mar 13 12:05:23 2020  ----------------------------
|SDBG | 13.03.2020 12:05:28: Scene trigger:{"id":37,"old":false,"type":"device","value":true,"property":"value"}
|SDBG | 13.03.2020 12:05:48: Scene trigger:{"id":37,"old":true,"type":"device","value":false,"property":"value"}
[DEBUG] 13.03.2020 12:05:53: Current lux:  100
[DEBUG] 13.03.2020 12:05:53: minlux:  500
|LOG  | 13.03.2020 12:05:53: fibaro.call(21,"turnOn") => nil
[DEBUG] 13.03.2020 12:05:53: Turning on
[DEBUG] 13.03.2020 12:05:56: Counting up safeTime  3 180
[DEBUG] 13.03.2020 12:05:59: Counting up safeTime  6 180
[DEBUG] 13.03.2020 12:06:02: Counting up safeTime  9 180
[DEBUG] 13.03.2020 12:06:05: Counting up safeTime  12 180
[DEBUG] 13.03.2020 12:06:08: Counting up safeTime  15 180
[DEBUG] 13.03.2020 12:06:11: Counting up safeTime  18 180
[DEBUG] 13.03.2020 12:06:14: Counting up safeTime  21 180
[DEBUG] 13.03.2020 12:06:17: Counting up safeTime  24 180
[DEBUG] 13.03.2020 12:06:20: Counting up safeTime  27 180
[DEBUG] 13.03.2020 12:06:23: Counting up safeTime  30 180
[DEBUG] 13.03.2020 12:06:26: Counting up safeTime  33 180
[DEBUG] 13.03.2020 12:06:29: Counting up safeTime  36 180
....... removed for brevity...
[DEBUG] 13.03.2020 12:08:29: Counting up safeTime  156 180
[DEBUG] 13.03.2020 12:08:32: Counting up safeTime  159 180
[DEBUG] 13.03.2020 12:08:35: Counting up safeTime  162 180
[DEBUG] 13.03.2020 12:08:38: Counting up safeTime  165 180
[DEBUG] 13.03.2020 12:08:41: Counting up safeTime  168 180
[DEBUG] 13.03.2020 12:08:44: Counting up safeTime  171 180
[DEBUG] 13.03.2020 12:08:47: Counting up safeTime  174 180
[DEBUG] 13.03.2020 12:08:50: Counting up safeTime  177 180
[DEBUG] 13.03.2020 12:08:53: Counting up safeTime  180 180
|LOG  | 13.03.2020 12:08:53: fibaro.call(21,"turnOff") => nil
[DEBUG] 13.03.2020 12:08:53: Turning off
[DEBUG] 13.03.2020 12:08:53: Scene ended
|SYS  | 15.03.2020 12:05:14: Max time - exit
Program completed in 1.64 seconds (pid: 14844).
Debugging session completed (traced 0 instructions).

We can see at the logged times that things happens when we expect them. We can also set breakpoints and inspect Lua variables etc.

The scene turns off the light after 180s of motion sensor being safe. It can be a bit boring waiting for that when coding/debugging.

Setting 'speed' to true in hc3_emulator.start{...} at the end will run the scene faster than real time - but the logged times will still be correct.

We can also set the time we want to start at (maybe Xmas next year?) by setting 'startTime' to another time in hc3_emulator.start{}.

 

Well, it's a start and I will improve the code to cater for more "features" and less bugs :-) 

 

 

 

Edited by jgab
  • Like 1
Link to post
Share on other sites

Thank you! Looking forward to new smart light code :)

 

I tried your code like below, but got "[ERROR] 2020-03-14 14:00:28: (load):78: <eof> expected near 'end'". If I delete the last "end" it runs and turns on the light for about 2-3 seconds then turns it off. I've set luxmin very high just for the tests. It was about 733 lux when I tested.

 

 

local hc = fibaro
jT = json.decode(hc.getGlobalVariable("HomeTable")) 
 
local light = {jT.Bathroom.bathroomlamp}
local motion = jT.Bathroom.motion
local lux = tonumber(hc.getValue(jT.Bathroom.lux, "value"))
local luxmin = 800
 
  count = 0
  function checkLights()
    if #light > 0 then
      for i = 1, #light
      do
        if hc.getValue(light"state"then count = count+1 end
      end
    end
  end
 
  function turnon()
    if #light > 0 then
      for i = 1, #light
      do
        hc.call(light,"turnOn");
        hc.debug("","Turning on");
        hc.sleep(100)
      end
    end
  end
 
  function turnoff()
    if #light > 0 then
      for i = 1, #light
      do
        hc.call(light,"turnOff");
        hc.debug("","Turning off");
        hc.sleep(100)
      end
    end
  end
 
  checkLights()
  if count >0 then state = "On" else state = "Off" end
 
  hc.debug("","Current lux: ",lux)
  hc.debug("","minlux: ",luxmin)
  if state == "Off" then
    if luxmin < lux then hc.debug("","room to light to turn on  lights")
    else
      local maxTime = 1*60  -- max time the sensor should be safe before turning off
      local sleepTime = 3   -- time in seconds between each check of the sensor
 
      turnon()
 
      local safeTime = 0
      while safeTime < maxTime do
        hc.sleep(sleepTime*1000)                 
        safeTime=safeTime+sleepTime                   -- count up safeTime
        hc.debug("","Counting up safeTime ",safeTime,maxTime)  
 
        count = 0 
        checkLights()
        if count >0 then state = "On" else state = "Off" end
        if state == "Off" then hc.debug("","Light(s) turned off manual");
          break 
        end
 
        if hc.getValue(motion,"value"then -- motion breached
          safeTime=0                                 -- reset safeTime
          hc.debug("","Reset")
        end
      end 
 
      turnoff()
   end
  else hc.debug("","Light manual turned on")
  end
  hc.debug("","Scene ended")
  end
Link to post
Share on other sites
Posted (edited)

 Here is a plugin for ZeroBrane studio. fibaroapiHC3plug.lua

Put it in the zerobrane folder, in ZBS/packages/ or HOME/.zbstudio/packages folder (where ZBS is the path to ZeroBrane Studio location and HOME is the path specified by the HOME environment variable)

Plugin: 

It's not fully developed yet but has a few features.

  • In ZBS 'Help' menu there are links to this thread, the Fibaro QuickApp manual, and Fibaro Lua Scene manual.
  • Under 'File' menu there is a "Create HC3sdk database" command that copies some of the most common resources from the HC3 and stores it in a file in the current working directory. File is named "HC3sdk.db". That file can then be loaded into the emulator when you run a scene/QA by adding the option hc3_emulator.start{loadDB=true}. This only works when running offline, but is a convenient way to have access to "existing" devices and globals in offline testing
  • Under 'File' there is a "Create HC3 backup" that downloads QuickApps, Scenes, Global variables, Locations, and Custom Events to a backup directory - more below.
  • Under 'File' there is a "Download select(ed) resource" that downloads the selected resource path in the current editor buffer - more below.
  • Under 'File' there is a "Upload HC3 resource" that uploads the current buffer as a resource (QuickApp, Scene etc) if the format is valid - more below.
  • Under "Edit" there is a menu that inserts in the current window a template for a QuickApp and a Scene with the added hc3_emulator commands needed.
  • There is also under "View" a "HC3 Emulator" command that opens a web page available while a QA/Scene is running. In the future we could add UI and other info there...

Future add-on that would be nice...

  • Upload of QA/Scene to the HC3
  • ...

 

backup.thumb.png.f9a2f2176df1a1c0aee98666f5422bde.png

"Copy HC3 data..." copies resource info from the HC3 and stores it in "HC3sdk.db". Can be used in offline-offline mode.

"Download fibaroapiHC3.lua" downloads the latest version from my Github into the current directory. Requires HC3 credentials to have been setup. Bu default I try to load "credentials.lua" from current directory to get the credentials.

 

plug4.png.5f5e4d89ea1c1858694545297c938561.png

"HC3 SDK templates..." insert a Scene or QuickApp code skeleton in the current buffer to be used with the emulator.

 

plug5.png.a437e22a4f53029f7e19dabbb4e36e8e.png

Practical browser links to this thread and Fibaro's Scene and QuickApp documentation.

 

plug3.png.81904e873f706a6f0fb488687da11d88.png

 

Autocompletion for HC3 Lua commands, fibaro.* etc.

plug1.png.ea6bd4af45c047c42bdb4c314fc7438a.png

..with arguments

plug2.thumb.png.1b679060f4fd49bd953fefdc935d7339.png

...and tooltip

 

The backup command downloads the resources to HC3Files/backup in the current working directory

The layout is

dir.thumb.png.c6f6d5f2eaf7d79db36120835a093e2c.png

and the file format is a format working with the "Upload HC3 resource" many command under file

 

 

200331 - auto completion and tooltips added for HC3 functions.

200405 - download option for latest fibaroapiHC3.lua

200512 - resource management

 

 

Edited by jgab
Link to post
Share on other sites
  • 2 weeks later...

I was testing 

    net.HTTPClient({ timeout = 5000 })

 

And noticed the emulator stayed at 60 seconds timeout

If you change this:

      options = options or {}

      for k,v in pairs(moptions or {}) do options[k]=v end

      local req = options.options or {}

 

To this:

      options = options or {}
      for k,v in pairs(moptions or {}) do options.options[k]=v end
      local req = options.options or {}
 

It seems to work. I don't know if you can pass other arguments than "timeout" to net.HTTPClient.

Link to post
Share on other sites
Posted (edited)
4 hours ago, petergebruers said:

I was testing 

    net.HTTPClient({ timeout = 5000 })

 

And noticed the emulator stayed at 60 seconds timeout

If you change this:

      options = options or {}

      for k,v in pairs(moptions or {}) do options[k]=v end

      local req = options.options or {}

 

To this:

      options = options or {}
      for k,v in pairs(moptions or {}) do options.options[k]=v end
      local req = options.options or {}
 

It seems to work. I don't know if you can pass other arguments than "timeout" to net.HTTPClient.

 

Thanks, old bug - never use the init arg to HTTPClient...

I also added hc3_emulator.asyncHTTP=true to enable pseudo asynchronous behaviour. (your test case with the tick loop works more "realistic"). I timeout every second to let other setTimeout get time to run. It's a not enabled by default as it is very special cases I guess this is needed - e.g. refreshStates....

Also, in hc3_emulator.BasicAuthentication is the base64 encoded credentials. "Basic ...."

v 0.75.

Edited by jgab
  • Thanks 1
Link to post
Share on other sites

Updates of the Zerobrane plugin with autocompletions, tooltips and other practical stuff.

 

Link to post
Share on other sites
Posted (edited)

New version 0.77.

Support for childDevices and fixes for the changed handling of UI events

The example in the Fibaro QuickApp child documentation works.

The requirement is to enable proxy on the HC3. (hc3_emulator.start{proxy=true}

They are surprisingly fun to play with :-)

 

Btw, it was also fun and challenging to get to the bottom with the class structure they use QuickAppBase -> QuickApp, QuickAppBase -> QuickAppChild and all the intrinsics of getting a proxy run with self:createChildDevice, self:initChildDevices... but I think I have figured it out.

So childDevices are cool and have nice GUIs but can we add a custom GUI to them?

Ex. I have this "com.fibaro.colorController" child device and I get on/off buttons and 2 sliders for color and brightness automatically. Can I add more custom UI elements to it?

 

Anyway, here is an example using this QuickApp code in the SDK emulator

if dofile and not hc3_emulator then
  hc3_emulator = {
    name = "My Test",
    type = "com.fibaro.deviceController",
    poll = 2000,
    proxy = true,
    UI = {{button='b1', text="B1"},{slider='s1', text='S1'}}
  }
  dofile("fibaroapiHC3.lua") 
end

function QuickApp:b1Clicked() -- Our main device has a button and a slider, just for show...
  self:debug("Test")
end
function QuickApp:s1Clicked(val) 
  self:debug("Slider",val.values[1])
end

class 'MyBinarySwitch'(QuickAppChild)
function MyBinarySwitch:__init(device)
  QuickAppChild.__init(self,device) 
  self:debug("MyBinarySwitch init")   
end

function MyBinarySwitch:turnOn()
  self:debug("child:", self.id, " turned on")
  self:updateProperty("value", true)
  self:updateProperty("state", true)
end

function MyBinarySwitch:turnOff()
  self:debug("child:", self.id, " turned off")
  self:updateProperty("value", false)
  self:updateProperty("state", false)
end

function MyBinarySwitch:toggle()
  self:debug("child:", self.id, " toggle")
  if fibaro.getValue(self.id,"value") then self:turnOff() else self:turnOn() end
end

function QuickApp:createChild()
  local child = self:createChildDevice({
      name = "myChild",
      type = "com.fibaro.binarySwitch",
      }, MyBinarySwitch)
end

function QuickApp:onInit()
  self:debug("onInit")
  self:debug("ID: ",plugin.mainDeviceId)
  self:createChild()
  self:initChildDevices({
      ["com.fibaro.binarySwitch"] = MyBinarySwitch
      })
  self:debug("Child devices:")
  for id,device in pairs(self.childDevices) do
    self:debug("[", id, "]", device.name, ", type of: ", device.type)
  end
end

Create the following on the HC3 (316 - the 'main' device should be com.fibaro.deviceController, but I changed before I took the screenshot)

children.thumb.png.b14e53d16e9f0e5c0bd612f5ec1f1a88.png

..and you can set breakpoints in the SDK emulator and debug your child devices :-)

There are a number of child devices in the screenshot (7 to be precise) because the example creates a new child every time it starts. A real example would save away already created devices like in Fibaro's own example doc.

 

The log in ZeroBrane then look like:

|SYS  | 10.04.2020 21:36:58: HC3 SDK v0.77
|SYS  | 10.04.2020 21:36:58: Created Event server at 192.168.1.18:6872
|SYS  | 10.04.2020 21:36:58: Proxy: Looking for QuickApp on HC3...
|SYS  | 10.04.2020 21:36:59: Proxy: Found ID:316
|SYS  | 10.04.2020 21:36:59: Proxy: Not changed, reusing QuickApp proxy
--------------- QuickApp 'My Test', deviceID:316 started at Fri Apr 10 21:36:59 2020 ---------------
[DEBUG] 10.04.2020 21:36:59: onInit
[DEBUG] 10.04.2020 21:36:59: ID: 316
[DEBUG] 10.04.2020 21:37:00: MyBinarySwitch init
[DEBUG] 10.04.2020 21:37:00: MyBinarySwitch init
[DEBUG] 10.04.2020 21:37:00: MyBinarySwitch init
[DEBUG] 10.04.2020 21:37:00: MyBinarySwitch init
[DEBUG] 10.04.2020 21:37:00: MyBinarySwitch init
[DEBUG] 10.04.2020 21:37:00: MyBinarySwitch init
[DEBUG] 10.04.2020 21:37:00: MyBinarySwitch init
[DEBUG] 10.04.2020 21:37:00: MyBinarySwitch init
[DEBUG] 10.04.2020 21:37:00: Child devices:
[DEBUG] 10.04.2020 21:37:00: [320]myChild, type of: com.fibaro.binarySwitch
[DEBUG] 10.04.2020 21:37:00: [321]myChild, type of: com.fibaro.binarySwitch
[DEBUG] 10.04.2020 21:37:00: [322]myChild, type of: com.fibaro.binarySwitch
[DEBUG] 10.04.2020 21:37:00: [323]myChild, type of: com.fibaro.binarySwitch
[DEBUG] 10.04.2020 21:37:00: [324]myChild, type of: com.fibaro.binarySwitch
[DEBUG] 10.04.2020 21:37:00: [317]myChild, type of: com.fibaro.binarySwitch
[DEBUG] 10.04.2020 21:37:00: [318]myChild, type of: com.fibaro.binarySwitch
[DEBUG] 10.04.2020 21:37:00: [319]myChild, type of: com.fibaro.binarySwitch
Program stopped (pid: 30546).
Debugging session completed (traced 0 instructions).
Program completed in 13.05 seconds (pid: 30546).

 

 

Edited by jgab
Link to post
Share on other sites

Thanks for the update v0.81. I am not 100% sure but I think your definition of "class" might clash if this was general purpose Lua. But it is not general purpose, it is HC3 specific so I doubt it is significant. But I changed this, to be in line with other functions in your code... to see what it would look like. Feel free to implement or ignore...

 

So line 812

class 'QuickAppBase'()

becomes

Util.class 'QuickAppBase'()

 

Same change line 861 Util.class 'QuickApp'(QuickAppBase) and 897 Util.class 'QuickAppChild'(QuickAppBase)

 

Then line 1732

function class(name)

 

becomes

self.class = function (name)

 

Haven't had a chance to play with "child devices" yet... Looks promising.

Link to post
Share on other sites
Posted (edited)
5 hours ago, petergebruers said:

Thanks for the update v0.81. I am not 100% sure but I think your definition of "class" might clash if this was general purpose Lua. But it is not general purpose, it is HC3 specific so I doubt it is significant. But I changed this, to be in line with other functions in your code... to see what it would look like. Feel free to implement or ignore...

 

So line 812

class 'QuickAppBase'()

becomes

Util.class 'QuickAppBase'()

 

Same change line 861 Util.class 'QuickApp'(QuickAppBase) and 897 Util.class 'QuickAppChild'(QuickAppBase)

 

Then line 1732

function class(name)

 

becomes

self.class = function (name)

 

Haven't had a chance to play with "child devices" yet... Looks promising.

Thanks.

 'class' is a global function on the HC3, and so is 'QuickAppBase' and 'QuickAppChild' (actually, the latter are "classes"). With HC3 global functions I'm a bit sloppy and declare them a bit here and there.

'class' is defined in Util. but not scoped with Util because it's supposed to be a global function anyway. I could do

self.class = function(name)

but I would need to do

class = Util.class

anyway to export it as a global.

'class' does not exist in standard Lua so my version is a variant that tries to mimic the one in HC3 by allowing the syntax

class 'ClassName'(ParentClass)

 

 

Edited by jgab
Link to post
Share on other sites
12 hours ago, jgab said:

 'class' is a global function on the HC3

Yes. It is not documented but it is used in "plugins" so also HC2 has it. Not sure why it is not documented.

 

12 hours ago, jgab said:

'class' does not exist in standard Lua so my version is a variant that tries to mimic the one in HC3 by allowing the syntax

Sure, mimicking this is a good thing as long as class does not get defined elsewhere, and I am totally fine with the way you do it now. I assume it would conflict if you had eg luabind on your pc, I did not try... Thinking out loud, you could define global 'class' only if it does not already exist.

Link to post
Share on other sites
49 minutes ago, petergebruers said:

Yes. It is not documented but it is used in "plugins" so also HC2 has it. Not sure why it is not documented.

 

Sure, mimicking this is a good thing as long as class does not get defined elsewhere, and I am totally fine with the way you do it now. I assume it would conflict if you had eg luabind on your pc, I did not try... Thinking out loud, you could define global 'class' only if it does not already exist.

Ok I understand what you mean. I will look at it.

Link to post
Share on other sites
16 minutes ago, jgab said:

Ok I understand what you mean. I will look at it.

Ok, I don't redefine 'class' if it's already available. A bit worried if I'm 100% compatible though.. Could be that I'm doing something with class that's not allowed by Luabind's version... Well, we will find out :-)

 

  • Thanks 1
Link to post
Share on other sites
Posted (edited)

Initial support for mqtt.

if dofile and not hc3_emulator then
  hc3_emulator = {
    name="MQTT test",
    proxy=false,
    poll=2000,
  }
  dofile("fibaroapiHC3.lua")
end

function QuickApp:onInit()
  self:debug("onInit")
  local function handleConnect(event)
    self:debug("connected: "..json.encode(event))
    self.client:subscribe("test/#")
    self.client:publish("test/blah", "test".. os.time())
  end
  self.client = mqtt.Client.connect('192.168.1.50', {clientId="HC3"})
  self.client._debug = true
  self.client:addEventListener('published', function(event) self:debug("published: "..json.encode(event)) end)  
  self.client:addEventListener('message', function(event) self:debug("message: "..json.encode(event)) end)
  self.client:addEventListener('connected', handleConnect)
end

prints the log

Program starting as '"/Applications/ZeroBraneStudio.app/Contents/ZeroBraneStudio/bin/lua.app/Contents/MacOS/lua53" -e "io.stdout:setvbuf('no')" "/var/folders/tv/2v395_bn1zs17v02gqhbkh2c0000gn/T/.Z92JoT"'.
Program 'lua53' started in '/Users/jangabrielsson/Dropbox/LUA/EventRunner/EventRunner' (pid: 16226).
Debugging session started in '/Users/jangabrielsson/Dropbox/LUA/EventRunner/EventRunner/'.
|SYS  | 18.04.2020 11:43:25: HC3 SDK v0.84
|SYS  | 18.04.2020 11:43:25: Created Event server at 192.168.1.18:6872
-------------- QuickApp 'MQTT test', deviceID:999 started at Sat Apr 18 11:43:25 2020 --------------
[DEBUG] 18.04.2020 11:43:26: onInit
|SDBG | 18.04.2020 11:43:28: MQTT connect:{"rc":0,"type":2,"sp":false}
[DEBUG] 18.04.2020 11:43:28: connected: {"sessionPresent":false,"returnCode":0}
|SDBG | 18.04.2020 11:43:29: MQTT subscribe:{"packet_id":1,"type":9,"rc":[0]}
|SDBG | 18.04.2020 11:43:30: MQTT message:{"payload":"test1587203008","type":3,"dup":false,"retain":false,"qos":0,"topic":"test/blah"}
[DEBUG] 18.04.2020 11:43:30: message: {"payload":"test1587203008","type":3,"dup":false,"retain":false,"qos":0,"topic":"test/blah"}
|SDBG | 18.04.2020 11:43:31: Incoming trigger:{"type":"device","id":21,"value":false,"property":"value","old":true}
|SDBG | 18.04.2020 11:43:35: Incoming trigger:{"type":"device","id":21,"value":1587203015,"property":"lastBreached","old":1587202989}
|SDBG | 18.04.2020 11:43:35: Incoming trigger:{"type":"device","id":21,"value":true,"property":"value","old":false}
Program stopped (pid: 16226).
Debugging session completed (traced 0 instructions).
Program completed in 15.31 seconds (pid: 16226).

If you find discrepancies with the HC3 api let me know..

You need to have installed https://github.com/xHasKx/luamqtt so that require("mqtt") works from fibaroapiHC3.lua

Edited by jgab
Link to post
Share on other sites
Posted (edited)

The SDK can be useful for coding and debugging large projects with a lot of moving parts. Zerobrane studio allows for setting conditional breakpoints and live variables watches which is real time savers compared to a myriad of debug printouts.

Have my own little project with 3000+ lines of code but lets take another example how to setup a project.

A recent great QA from @Krikroff for controlling a Sonos players is advanced enough to exercise most corners of the SDK/emulator.

 

Normally we setup  a QA post- and preamble that includes the SDK/emulator into the QA you are developing.

Another approach is to have a skeleton/template and include the QA code:

if dofile and not hc3_emulator then
   hc3_emulator = {
    name="QA Sonos ZC 1.0.3",
    poll=1000,
    proxy=true,
    quickVars = {["ipAddress"]="192.168.1.208"}
    UI = {
      {label='labelZone',text="Zone: ---"},
      {label='labelTrack',text=""},
      {
        {button='btnPrev', text='< Prev'},{button='btnPlay', text='► Play'},
        {button='btnStop', text='■ Stop'},{button='btnNext', text='Next >'}
      },
      {label='labelOptions', text='Mute: enabled'},
      {slider='sliderVolume', text=""},
      {{button='bntVolumeDown', text='Volume -10'},{button='bntVolumeUp', text='Volume +10'},{button='btnMute', text='Mute'}},
      {{button='btnCrossfade', text='Crossfade'},{button='btnShuffle', text='Shuffle'},{button='btnLoudness', text='Loudness'}},
      {label='labelZpInfos', text=''},
      {label='labelQuickAppVersion', text='Version: 1.0.0'},
      {label='lblQuickAppLog', text=''},
    }
  }
  dofile("fibaroapiHC3.lua")
end

dofile("SonosKrikroff.lua")

We could have included the code, but its many lines of code and we don't want to make any accidental changes to the code. Instead we do a Lua 'dofile' to insert the code.

The QA also have a GUI with buttons. we declare them also so that the proxy on the HC3 will get the same buttons. 

(I'm working on a method to automatically import and export QAs to Zerobrane so this would be autogenerated)

Anyway, we set proxy=true which means that when we run the code it creates a proxy on the HC3 with buttons that send requests back to the QA you run in Zerobrane.

sonos.thumb.png.a259d450baaac968d25b1beb6872be31.png

 

In  ZeroBrane studio we get the log:

Program starting as '"/Applications/ZeroBraneStudio.app/Contents/ZeroBraneStudio/bin/lua.app/Contents/MacOS/lua53" -e "io.stdout:setvbuf('no')" "/var/folders/tv/2v395_bn1zs17v02gqhbkh2c0000gn/T/.dPIpkA"'.
Program 'lua53' started in '/Users/jangabrielsson/Dropbox/LUA/EventRunner/EventRunner' (pid: 50408).
Debugging session started in '/Users/jangabrielsson/Dropbox/LUA/EventRunner/EventRunner/'.
[24.04.2020] [17:19:41] |SYS  |: HC3 SDK v0.85
[24.04.2020] [17:19:41] |SYS  |: Created Event server at 192.168.1.18:6872
[24.04.2020] [17:19:41] |SYS  |: Proxy: Looking for QuickApp on HC3...
[24.04.2020] [17:19:42] |SYS  |: Proxy: Found ID:717
[24.04.2020] [17:19:42] |SYS  |: Proxy: Not changed, reusing QuickApp proxy
---------- QuickApp 'QA Sonos ZC 1.0.3', deviceID:717 started at Fri Apr 24 17:19:42 2020 ----------
debug mode:	false
componentUpdate_footerLabel
[24.04.2020] [17:19:58] [DEBUG]: XmlSoap class initialized!
Sonos class initialized!
[24.04.2020] [17:19:58] [TRACE]: [[GetZoneGroupAttributes:GetZoneGroupAttributes]
[24.04.2020] [17:19:58] [TRACE]: [ZoneGroupTopology:GetZoneGroupState]
[24.04.2020] [17:19:58] [TRACE]: [GetZpStatus]

...and we can open the file ""SonosKrikroff.lua"" in another window in Zerobrane and set breakpoints and step through the code... Zerobrane understands files included with dofile.

We can also click on buttons on the HC3 QA UI and get triggers back into the button handlers in Zerobrane.

 

In Zerobrane it is also possible to set the template/skeleton file as start file, meaning that when you press run it will always run that file.

That mean that you can have the real file you work on open and when you press run, it runs the right file first.

 

So at the moment its a little bit of setup needed for a project but its usually worth it in the development speed gained - compared to run and debug on the HC3...

 

Edited by jgab
  • Like 2
Link to post
Share on other sites

@jgab thanks for your advices and framework! 
Without your fibaroapiHC3.lua, I would not be able to create my QAs.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...