Jump to content

HC3 QuickApps coding - tips and tricks


Recommended Posts

12 minutes ago, jgab said:

Yes, but it doesn't cancel the timer - wait for 0.13 with a fix...

Ok, v0.14 with the real fix for clearTimeout.

Link to post
Share on other sites
  • Replies 876
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

This thread is most about QuickApp tricks and usually requires some deeper understanding of Lua. I'm going to make an attempt to do something more tutorial wise that could work for newcomers to Lua. I

The anatomy of QuickApps – Part 2 (Part 1)   Disclaimer1: We are now venturing into undocumented land. That means that Fibaro is free to change how things work at any time. Well, Fibaro

A thread to share some coding techniques for QuickApps?  Because QAs are "long running scenes" (they don't have to be loaded and restarted for every event) - it is actually worthwhile to build up

Posted Images

So, I'm a Mac person and only using ZeroBrane studio. In theory fibaroapiHC3.lua should work in Visual Studio on a PC (or Mac?). The problem is that some libraries needs to be available

http = require("socket.http")
socket = require("socket")

They are pretty standard in the Lua world and comes with Luasocket (-- LuaSocket helper module -- Author: Diego Nehab )

Would be interested to hear if someone with Visual Studio manage to make it work?

Link to post
Share on other sites

@jgab [L] Unhandled event:{"data":{"id":32,"roomId":237,"previousRoomId":219},"type":"DeviceChangedRoomEvent"} -- please report

Link to post
Share on other sites
6 minutes ago, petrkl12 said:

@jgab [L] Unhandled event:{"data":{"id":32,"roomId":237,"previousRoomId":219},"type":"DeviceChangedRoomEvent"} -- please report

 

Thanks, the HC3 reports all kind of events - the only question is what we do with them? How often do your code need to react to a device changing room? Well, it can be useful.

I'll add it. (it will be in next version - for now you can just ignore the log msg.)

Edited by jgab
Link to post
Share on other sites
Just now, petrkl12 said:

OK, you have in your code "please report" - so I do it 😀

Yes, I'm happy for all reports - keep them coming :-)

 

Link to post
Share on other sites
Just now, petrkl12 said:

@jgab How to read variables from another QA device?

 

api.get("/devices/"..<deviceID>).properties.quickAppVariables[<variableName>]

Link to post
Share on other sites

There are some simple support for scenes - I'm still not secure how I would like it to work.

if dofile and not hc3_emulator then
  hc3_emulator = {credentials = {ip="192.168.1.X", user="<user>", pwd="<password>"}}
  dofile("fibaroapiHC3.lua")
end

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

function hc3_emulator.actions()
  fibaro.debug("","Hello I was triggered by device 32")

  
end

if dofile then hc3_emulator.start{poll=2000} end

if there is a CONDITIONS and a SCENE we assume the code is a scene. The above will call the SCENE function every time the condition is true. It can only handle devices at the moment, but I have code for cron...  I will change name from SCENE to ACTIONS in next version.

 

 

Edited by jgab
Link to post
Share on other sites

@jgab maybe bug  in getting QA variables

LanguageVD = QuickApp:getVariable("Language") returns nil everytime in fibaroapiHC3.lua

 

(return d.properties.quickAppVariables[name])

Link to post
Share on other sites
On 2/16/2020 at 7:49 PM, petrkl12 said:

@jgab maybe bug  in getting QA variables

LanguageVD = QuickApp:getVariable("Language") returns nil everytime in fibaroapiHC3.lua

 

(return d.properties.quickAppVariables[name])

 

Be careful, api.get("/devices/"..deviceID).properties.quickAppVariables[name] access the quick variables of the device residing on the HC3.

To get the quick variables of the device in the "emulator" you use self:getVariable(<name>)

 

If you have given an deviceID as the first argument to

Ex. hc3_emulator.start{id=21,poll=2000}

then self:getVariable and self:setVariable will access the quick variables on the deviceID 21 on the HC3.

if not set it will access the ones in the "emulated" version you run offline...

 

 

 

...and you can only do QuickApp:getVariable("Language") in the "emulator"

so its best to wrap it in "if dofile then QuickApp:getVariable("Language") end"

Otherwise you need to use self:getVariable("Language") in the QuickApp. i.e  'self' not 'QuickApp' - self is the instance, QuickApp is the class..

Edited by jgab
Link to post
Share on other sites

I have

fibaro._start(32,1000)

 

still nil in both cases:

LanguageVD = QuickApp:getVariable("Language")
LanguageVD = self:getVariable("Language")

 

from HC3 it returns {name = "Language", value = "cz"}

but this return d.properties.quickAppVariables[name] doesn't work

 

Edited by petrkl12
Link to post
Share on other sites

try something else, get values via their index

 

-- api.get("/devices/"..deviceID).properties.quickAppVariables[indexofthevariable].value
api.get("/devices/"..deviceID).properties.quickAppVariables[1].value

 

Link to post
Share on other sites
On 2/16/2020 at 8:00 PM, petrkl12 said:

I have

hc3_emulator.start(32,1000)

 

still nil in both cases:

LanguageVD = QuickApp:getVariable("Language")
LanguageVD = self:getVariable("Language")

 

 

 and if you go the the HC3 and look at the quickvars of deviceID 32 is there a variable with name "Language" that has a value?

 

On 2/16/2020 at 8:04 PM, tinman said:

try something else, get values via their index

 

-- api.get("/devices/"..deviceID).properties.quickAppVariables[indexofthevariable].value
api.get("/devices/"..deviceID).properties.quickAppVariables[1].value

 

Yes, it's not a hashtable, its a list - not very efficient...? - I will patch fibaroapiHC3.lua

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

 and if you go the the HC3 and look at the quickvars of deviceID 32 is there a variable with name "Language" that has a value?

 

Yes, it's not a hashtable, its a list - not very efficient...? - I will patch fibaroapiHC3.lua

Ok, v 0.16 with a fix for the getVariable is linked in the fibaroapiHC3 post.

Thanks @petrkl12 for using the code and finding bugs! 

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

 Yes, it's not a hashtable, its a list - not very efficient...? - I will patch fibaroapiHC3.lua

Why on earth do they implement it as a list? It's not like you can have two variables with the same name, is it? .... yes it turns out that you can 🤪 🤪🤔

And every time you change a single quick variable they post the whole list as an internal event (visible on /refreshState...) 😳

Edited by jgab
Link to post
Share on other sites

New version of fibaroapiHC3.lua (v 0.18)

Besides some bug fixes the new feature is to auto-create a QuickApp proxy on the HC3...

Ex.

if dofile then
  dofile("fibaroapiHC3.lua")
  local cr = loadfile("credentials.lua"); if cr then cr() end
end

function QuickApp:turnOn() 
  self:debug("ON") 
  self:updateProperty("value",true)
end
function QuickApp:turnOff() 
  self:debug("OFF") 
  self:updateProperty("value",false)
end
function QuickApp:b1Clicked() self:debug("Test1 clicked") end
function QuickApp:b2Clicked() self:debug("Test2 clicked") end
function QuickApp:b3Clicked() self:debug("Test3 clicked") end
function QuickApp:s1Clicked(val) self:debug("Slider",val) end

function QuickApp:onInit()
  self:debug("onInit")
end

if dofile then -- only when running offline...
  hc3_emulator.start{
    name="My First QD",
    type = ...,
    poll=1500,
    UI = {
     {button='b1', text='Test1'},
     {{button='b2', text='Test2'},{button='b3', text='Test3'}},
     {slider='s1', max=100,min=0,text='Slider'},
     {label='l1', text='ABC'},
    },
    quickvars=...,
  }
end

If you run this it will create a proxy QuickApp on your HC3 with the name "Proxy My First QD" - it always add "Proxy " infront of the name you give it.

If the proxy already exists it will reuse the one that is installed.

If you callback functions have changed it will also recreate the device. (unfortunately I don't reuse the deviceID for now...)

 

When the buttons are pressed on the WebUI on the HC3 for the device, your "Clicked" methods will be called in the IDE. It takes a second but it's ok.

If someone calls tunrOn/turnOff the method will also be called in the IDE.

 

device type defaults to "com.fibaro.binarySwitch"

 

The difficulty when creating the proxy is to define the UI elements.

The UI table should look like

{

 <row 1>

<row 2>

  :

<row n>

}

Each row is either a list of 2-5 buttons or a single element.

Elements can be of type:

{button=<name>,text=<text>}

{slider=<name>,text=<text>,min=<min>,max=<max>}

{label=<name>,text=<text>}

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

Here is another hack.

This is a QuickApp called 'Library' that reads a json manifest from a directory on the web. I have a manifest that looks like

{"name":"jgab's Lib",
  "version":"1.0",
  "description":"Library with scenes and device for HC3",
  "root":"https://raw.githubusercontent.com/jangabrielsson/EventRunner/master/Lib3.0/",
  "scenes":[
    {"name":"Wait for sensor",
    "uid":"77trfbjasf723fbf873fjakf59",
    "version":"v0.1",
    "url":"WaitForSensor_v1.lua",
    "description":"Example of how to wait for a sensor to be safe for a specified time before turning off a light"
    },
  ],
  "devices":[
    {"name":"Crash notifier",
    "uid":"77trfbjasf723fbf873fjakf60",
    "version":"v0.1",
    "url":"CrashNotifier_v1.lua",
    "description":"Logs all QuickApps that crashes. Optionally pushes a message to the phone"
    },
    {"name":"Profiler scheduler",
    "uid":"77trfbjasf723fbf873fjakf61",
    "version":"v0.1",
    "url":"ProfSched_v1.lua",
    "description":"A simple app to schedule profiles during the day"
    }
  ]
}

...and in the directory I have

'CrashNotifier_v1.lua' and 'ProfSched_v1.lua' etc.

The Library app will read the manifest and allow the user to browse the files and install them. It can handle both QuickApps and Scenes.

I mostly developed this for myself to quickly be able to download and install stuff I do.

The "interesting" feature is that the file formats for the files are "flat" - meaning that they can be downloaded and run in the offline IDE - no encoded json format.

A device file can look like:

--[[
%%LibDevice
properties: {
"name": "Test device1",
"type":"com.fibaro.binarySensor",
"variables":{
   "myVar":"This is a test"
   },
"UI":[
  {"button":"button1","text":"B1"},
  [{"button":"button2","text":"B2"},{"button":"button3","text":"B3"}],
  {"slider":"slider1","text":"","min":0,"max":100},
  {"label":"label1","text":"L1"}
  ]
}
--]]

if dofile then
  dofile("fibaroapiHC3.lua")
  local cr = loadfile("credentials.lua"); if cr then cr() end
  QuickApp:setVariable("IP",_HueIP)
  QuickApp:setVariable("User",_HueUserName)
end

function QuickApp:onInit()
   self:debug("Device1")
end
 

So one declares the QuickApp properties like type and name, and quickVariables and the UI - buttons and sliders and labels. When downloaded by the Library app it will build a QuickApp according to the spec including the main code. Pretty useful.

I include the Library app here if you want to test it - it is configured to fetch apps from my GitHub repository - but can be pointed to another manifest file if you want to build your own library.

Disclaimer: I have only used it for a short time so there could be bugs...

Library-2.fqa

 

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

hehe very nice hack! Btw, one can as well define not yet implemented device types, by editing the .fqa file, e.g. Keyfob:

 

{"name":"keyfob QA","type":"com.fibaro.FGKF601","apiVersion":"1.0"

 

Currently available types for QA are defined her:

 

/api/quickApp/availableTypes

 

but of course all the generally supported could be used:

 

/api/devices/hierarchy

 

It is maybe important to know, that Fibaro is using internally so called Mockup Plugin, which does emulate every supported device,
but it is not just device type Definition, but as well set of lua files for specific types (like e.g. keyfob), where others are just Sub definition.

 

That means, even if i created fqa with keyfob as device type, it does not completelly act as such, so i had to code some Events to emulate buttons by myself. 

This hack might be useful to have a specific kind of device to group it with others, it should not harm anything - i hope :) 

Link to post
Share on other sites
  • jgab changed the title to SDK for remote and offline HC3 development.

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...