Jump to content

Welcome to Smart Home Forum by FIBARO

Dear Guest,

 

as you can notice parts of Smart Home Forum by FIBARO is not available for you. You have to register in order to view all content and post in our community. Don't worry! Registration is a simple free process that requires minimal information for you to sign up. Become a part of of Smart Home Forum by FIBARO by creating an account.

 

As a member you can:

  •     Start new topics and reply to others
  •     Follow topics and users to get email updates
  •     Get your own profile page and make new friends
  •     Send personal messages
  •     ... and learn a lot about our system!

 

Regards,

Smart Home Forum by FIBARO Team


HC3 QuickApps coding - tips and tricks


jgab

Recommended Posts

  • Topic Author
  • 8 minutes ago, Sjakie said:

    Jan,

    FindMy should be in the foreground, I don't see option run in back ground, all option are on in iPhone and Macbook.

    Screensaver is on 20 min will set it off, yesterday I left my computer and house on the same time in both cases.

    I noticed that if I switch off Macbook I have option to steer Terminal it comes up after restart

     

    "background" I mean running behind other windows.

    Link to comment
    Share on other sites

  • Topic Author
  • On 7/13/2022 at 1:52 PM, Sjakie said:

    Zerobrane installed and save  did the trick, chapeau!

    Now I feel myself obliged to start also with ZB to test QA's>> will become a long way.

    In terminal I get this, must I do something more because its a list:

    If you install TQAE for ZB I have added some instructions in the thread for how to set it up using git

     

    I really recommend using git as it makes it easy to update the TQAE code.

    Link to comment
    Share on other sites

    Okay Jan here I am again, hehehe

    from GitHub>>git clone............

    Followed your instructions

    Stuck on open 192.168.11.36:8976/web/main

    Zerobrane is open and TQAE_QA.lua is on screen

    Browser>>>> error can't find page

    disabled firewall same result

    Link to comment
    Share on other sites

  • Topic Author
  • Posted (edited)
    4 minutes ago, Sjakie said:

    Okay Jan here I am again, hehehe

    from GitHub>>git clone............

    Followed your instructions

    Stuck on open 192.168.11.36:8976/web/main

    Zerobrane is open and TQAE_QA.lua is on screen

    Browser>>>> error can't find page

    disabled firewall same result

    Your QA/code must be running in ZB for you to be able to open the page.

    because the web server serving the web page is running in the emulator together with your code

    If you go deep into TQAE, move the discussion to the TQAE forum.

    Edited by jgab
    Link to comment
    Share on other sites

  • Topic Author
  • Posted (edited)

    So, I'm a big fan of event style programming because it fits so well with the asynchronous nature of programming home automation. It's asynchronous because things can happen at any time in any order and our code needs to be able to handle it without blocking events.

     

    Event style programming means that we think about all our functions/actions as "event handlers". Functions that get triggered when an event happens. An event handler (handler for short) can also trigger or post another event wich then trigger other handlers etc, kicking of a chain of events and handlers.

     

    HandlerA -> Event1 -> HandlerB -> Event2 -> HandlerC -> Event3 ->HandlerD -> Event4 -> ....

     

    Because your handler decides what event to post next it decides what handler should be invoked next, thus you create "threads" of handlers to solve tasks. Ex.

     

    HandlerA:Start -> Event:Login -> HandlerB:Login -> Event:SuccessLogin -> HandlerC:LoginSuccess-> HandlerD:FetchData

                                                                                   |

                                                                                   +-> Event:FailedLogin -> HandlerC:FailedLogin

    Here we start by posting a login event with a handler that logs in to a server. Depending if we succeed with that, we post a success or failure event. The success event triggers a handler that can then fetch a value from the server. A failure posts an event that we take care of the error in another handler.

     

    So, the logical flow in your program becomes the event threads that you "weave" together.

     

    There are 2 major advantages structuring your program this way.

    1. It integrates well with the asynchronous nature of some of the HC3 APIs, in particular the net.HTTPClient. In our example above, the HandlerB that does the login can in its success and error callbacks do post the Event:SuccessLogin event or the Event:FailedLogin event to drive the "event thread" forward.
    2. Secondly, it lends itself easily to run several event threads in parallel. We could have started 2 logins above and each thread could have run in alternating steps. Lua is not actually running anything in parallel, but code takes turn running. So when a Handler has executed and makes a post, another Handler that wants to execute (because it's been triggered by an event) can then run.

     

    Ok, enough with the theory. Let's see some code.

    The examples here make use of a really small "event library"

    Please login or register to see this spoiler.

    Please login or register to see this code.

    It produces the output

    Please login or register to see this code.

    Handlers are defined on EVENT:, very much like we define functions for QuickApp:

    However, here the name of the function is important as it is the name of the event that the handler/function should trigger on.

    Also, inside handlers we use self:post() to post an event. Not LE:post() as it's only used to start a new event thread.

     

    We post 3 events in :onInit and we see that they run in "parallel" (or takes turn in their steps). This is just a thread of 3 handlers, but part of the event is a key 'a' that is incremented by each handler and then printed out in the last handler. It's also pretty quick, you see all logging within the same second.

     

    We could post an event in the future by giving a time in seconds as a delay.

    LE:post and self:post can take a second optional argument that is the delay in seconds. 

    Please login or register to see this code.

    Here we use the 'a' value of the event as the time to delay next post, and it becomes incremental longer as we see in the log times below.

    Please login or register to see this code.

     

    This is useful to make event loops that execute their handlers at specific intervals.

     

    Besides the events that are sent through the "event thread" of handlers, you would sometimes like to bring with you values that can be used in each handler, much like local variables, but local to the event thread. Ex passwords etc. We can't store them in global Lua variables as we may want to run several event threads to login to several servers in parallel. We could put them in the event itself but then all handlers in the thread must know how to carry that value forward when it posts the next event.

    We can solve this by providing a context that becomes the 'self' variable in the handlers.

    A context is just a Lua table with key/values that are the values we would like to carry with us. The context is an optional 3rd argument of LE:post(), and if we provide that we also need to include the second, delay argument, but we can set it to 0.

    Please login or register to see this code.

    Please login or register to see this code.

    Here we provide a context {b=8, _tag='A1"} and in handlers we can access b as self.b.

    We increment b also and print out event.a and self.b in the final handler. 

    Another feature of the framework is that if the context has a '_tag' value it is used as a prefix for the debug loggings. This requires that we use self:print(), self:debug(), self:trace(), or self:error() to do our logging.

    In the case above we see the threads more easily as the first is prefixed with "A1", the second with "A2" and the third with "A3".

     

    So, events integrate well with http requests.

    Please login or register to see this code.

    self:http takes the event that triggered the handler, the HTTP method (GET/PUT/POST/DELETE) and a url path as argument (also the data if we do a post/put)

    In our first handler, 'getValue', we call self:http with the path "valueGet&name=X". That path will be appended to whatever baseURL we have in the context. When we do LE:post in :onInit we provide a context with baseURL=="http:// ...." that is used.

    If we don't provide a baseURL we would need to provide the full URL in the handler when calling self:http

     

    The magic with self:http is that when it gets its result (remember it's asynchronous), it will call an event that has the name of the previous event but with "_success" or "_error" appended. (that's why we need to put the event as first argument to self:http, it needs the type of the event)

    In our case it will post the result to either 'getValue_success' or 'getValue_error' with the result in event.data or error in event.error.

    In the example we print out the .enable value we get back in the result from the server.

     

    Ok, this is simple and we probably didn't need some complicated events for that. We could have printed out .enable in the http request's success callback.

     

    But assume that we need to login to retrieve a token before we can fetch the value with another request. Then it becomes a bit more cumbersome. Well with events that easy.

    Please login or register to see this code.

    In our getValue handler we check if the context has the token, if not it calls the login handler. We also set the context variable 'nextStep' to our handlers name, so that the login handler knows where it should post its event, e.g. to continue where we left off.

     

    Our login handler puts the token in the context (if it succeeds) and post an event of type specified in .nextStep, so we come back to our getValue handler. Now the token is in the context and we proceed to retrieve the .enable value.

    Please login or register to see this code.

    Any handler that needs to be logged in before retrieving a value can use the same login handler, just setting .nextStep to refer back to itself. The error handler for retrieving a value could detect "token expire" and automatically do a login and re-run the handler that retrieved the value. The opportunities are limitless...

     

    So, this was a long preach about event based programming. Something that we, the disciples of the event programming church, are expected to deliver on a regular basis :-) 

    (also, I think the fibaro.lightEvents() event framework is pretty cool, a refinement of a number of previously event frameworks attempts over the years)

    Edited by jgab
    Link to comment
    Share on other sites

    Jan, I do something wrong but don't know what.

    If --function ....... is active QA runs well

    If I reverse with function QuicApp:turnOn() is active QA goes in loop on/off

    Please login or register to see this code.

     

    Link to comment
    Share on other sites

  • Topic Author
  • Can you show log from it starts, self:debug("onInit"), to when it alternates on/off?

    btw, this is probably wrong

    Please login or register to see this code.

     

    Link to comment
    Share on other sites

    Please login or register to see this code.

    Sorry I think I found something:

    iOS_allHome or iOS_somehome will disable arming

    arming will put $beveiliging==' Uit'

    We are home so iOS == all home

    If I switch on beveiliging your excellent ER4 will do what was given switch beveiliging Off

    How it is switching on again I need to track down so first part is solved!

    Second art:

    If iOS == all_home or some_home and $Status == ' Sleep' will set beveiliging = ' Aan'

    The ERROR is $Status == ' Sleep' hangs and I don't understand it did't change, should been  changed already 5 times.

    Edited by Sjakie
    wrong way
    Link to comment
    Share on other sites

  • Topic Author
  • Please login or register to see this code.

    Please login or register to see this code.

    'onActions' means that there are some other QA calling your QA 1793's 'turnOn' and 'turnOff' function (or 'toggle'?).

    Some rule running amok?

     

     

    Please login or register to see this code.

    Please login or register to see this code.

    'UIEvent' is you pressing the buttons in the GUI.

    Link to comment
    Share on other sites

    Jan,

    Please login or register to see this code.

    QA xx has inside the rule if $Sec_Beveiligen == 'Aan'  =>1793:btn=1

    This is done to have the right state on QA 1793, or is this wrong? Or shall I use a time delay?

    QA1793 replace a relay what I used before to operate from Yubii.

    To operate in Yubii I only use/need for incase something goes wrong:

    $Sec_Beveiligen Aan/Uit  & $Sec_Alarm Uit >>arm or disarm 

    $Bezetting_Appartement >>>> for in case $iOS is missing

    One or two others for temporary as Plan B must see first HC3 running with all devices, keep in mind HC3 is without any device at this moment.

     

    Link to comment
    Share on other sites

    On 2/3/2022 at 4:45 PM, jgab said:

    So I have lua code  that takes a directory with tile .pngs and create a QuickApp file that can be included in the QA

    Please login or register to see this spoiler.

    Hi @jgab

     

    Line 33+34 - what should 😎 be replaced with ?

    I tried 8) - guess that is right?

     

      local width = (buf[1] << 24) + (buf[2] << 16) + (buf[3] << 😎 + (buf[4] << 0)
      local height = (buf[5] << 24) + (buf[6] << 16) + (buf[7] << 😎 + (buf[8] << 0);

     

    to

     

      local width = (buf[1] << 24) + (buf[2] << 16) + (buf[3] << 8 ) + (buf[4] << 0)
      local height = (buf[5] << 24) + (buf[6] << 16) + (buf[7] << 8 ) + (buf[8] << 0);

     

    But i get this error on the MAC? - is this for windows computers?

     

     

    Please login or register to see this code.

     

    Edited by ChristianSogaard
    P
    Link to comment
    Share on other sites

  • Topic Author
  • Posted (edited)

    I didn't understand what you meant but then I looked back at the code and it has the emoji there!!! It seems like that when I typed 8 with closing parenthesis "8)" it was autocompleted to the emoji....

     

    Anyway, the problem with the code is that probably 

    local outputFile = "test/map/imageFile.lua"

    is set to something that doesn't work. I see in the code that I expect the filename to be split in a directory and a file so there need to be at least one "/" in the name.

     

    If you run in TQAE you should always set the working directory to TQAE/, even if you run programs in subdirectories. That is so that the included libraries will be found (all are addressed relative the TQAE/ directory)

    Also, it looks like you put your code in the examples/ directory in TQAE?

    Try to avoid it as when you update the TQAE/ directory (git fetch) it will remove your files

    In TQAE/ you can create 2 directories 

    TQAE/dev/... and TQAE/test/... that will not be touched when doing git fetch. They are included in the .gitignore file (you can add other directories there if you want)

    I do all my testing myself in TQAE/test/...

     

    Btw, I have also a Mac M1 for my daily development and it works very well.

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

    6 hours ago, jgab said:

    I didn't understand what you meant but then I looked back at the code and it has the emoji there!!! It seems like that when I typed 8 with closing parenthesis "8)" it was autocompleted to the emoji....

     

    Anyway, the problem with the code is that probably 

    local outputFile = "test/map/imageFile.lua"

    is set to something that doesn't work. I see in the code that I expect the filename to be split in a directory and a file so there need to be at least one "/" in the name.

     

    If you run in TQAE you should always set the working directory to TQAE/, even if you run programs in subdirectories. That is so that the included libraries will be found (all are addressed relative the TQAE/ directory)

    Also, it looks like you put your code in the examples/ directory in TQAE?

    Try to avoid it as when you update the TQAE/ directory (git fetch) it will remove your files

    In TQAE/ you can create 2 directories 

    TQAE/dev/... and TQAE/test/... that will not be touched when doing git fetch. They are included in the .gitignore file (you can add other directories there if you want)

    I do all my testing myself in TQAE/test/...

     

    Btw, I have also a Mac M1 for my daily development and it works very well.

     

    Hi Jan

     

    Thank you for this explanation.

    I changed the ... local outputFile = "dev/HouseMap/map/imageFile.lua" - this seems to bring me further :-)

    working directory to TQAE is set the working directory to TQAE/, (/Users/christian_soegaard/TQAE)

     

    I created the TQAE/dev/ and moved housemap.lua into there.

     

    Now the HouseMap.Lua runs with no errors in the output window,

     

    I was expecting the imageFile to contain the images in base64 encode, but it seems that i might did something wrong, because it more or less seems to copy the HouseMap into imagefile.lua

     

    Please login or register to see this attachment.

     

     

    here is my structure for a 3x8 map

     

    Please login or register to see this attachment.

     

     

    Link to comment
    Share on other sites

  • Topic Author
  • I think your image files need to be in dev/housemap/map

    same as the directory of the outputfile 

    • Thanks 1
    Link to comment
    Share on other sites

    21 minutes ago, jgab said:

    I think your image files need to be in dev/housemap/map

    same as the directory of the outputfile 

    Thank you again 🤩- You where right as always

    File is now updated 

    Link to comment
    Share on other sites

    5 hours ago, ChristianSogaard said:

     

    Hi Jan

     

    Thank you for this explanation.

    I changed the ... local outputFile = "dev/HouseMap/map/imageFile.lua" - this seems to bring me further :-)

    working directory to TQAE is set the working directory to TQAE/, (/Users/christian_soegaard/TQAE)

     

    I created the TQAE/dev/ and moved housemap.lua into there.

     

    Now the HouseMap.Lua runs with no errors in the output window,

     

    I was expecting the imageFile to contain the images in base64 encode, but it seems that i might did something wrong, because it more or less seems to copy the HouseMap into imagefile.lua

     

     

    Please login or register to see this attachment.

     

     

    here is my structure for a 3x8 map

     

    Please login or register to see this attachment.

     

     

    Hi Jan

     

    What is the trigger to show the map ?

     

    i just inserted

    Please login or register to see this code.

     

    I am getting 

    [27.07.2022] [18:38:00] [DEBUG] [QUICKAPP44]: HouseMap 44
    [27.07.2022] [18:38:00] [ERROR] [QUICKAPP44]: QuickApp crashed
    [27.07.2022] [18:38:00] [ERROR] [QUICKAPP44]: main.lua:46: Rows must have same number of columns

     

    I have 3x8 - so not sure why i get Rows must have same number of columns

    Please login or register to see this spoiler.

     

    Link to comment
    Share on other sites

  • Topic Author
  • Your indexes are wrong. Ive updated the original post with some better explanation 

    You need something like

    Slice_[1-24]_[0-1].png

    Assuming you have 3x8 (= 24) tiles per layer, and 2 layers (0 and 1)'

     

    You seem to have only one layer (24 images) so then you can't turn on/off any tiles. The idea is that one can select any layer for a tile to be the visible layer...

     

    Then you need to set 

    Please login or register to see this code.

    if you have 3 columns and 8 rows

     

     

    Anyway, if was a hack at the time and I have not evolved it any further. I just tried it in the web GUI and in the app and it seems like the picture is not immediately updated anymore, but I need to close and open the tab for the image to update (seems like Fibaro is a bit more aggressive in caching UI updates in the latest fws...)

    • Thanks 1
    Link to comment
    Share on other sites

  • Topic Author
  • So, I have a Hue V2 API engine in Lua that works on the HC3. It's using the event stream so it's pretty snappy compared to the old V2 where we needed to poll (and of course less cpu hungry).

    I even have a decent hsv<->rgb<->xy conversion routines (will never be perfect).

    So, Hue sensors and power plugs and white ambient lamps works nice... but color lights are killing me.

    It seems impossible to create a decent QA with color (hue+saturation or RGB), brightness and temperature.

    • Type com.fibaro.philipsHueLight gives the hue+saturation and brightness but lack temperature. Adding a 'warmWhite' component with colorComponents  makes it look very ugly.
    • Making a basic colorController and adding colorComponents R,G,B,warmWhite kind of makes it work but somehow the Brightness controller doesn't work (produces no onAction/UIEvent whatsoever...)

    I could build the UI from scratch based on multilevelSwitch using a hue, saturation and hue slider, but I would really like it to have the color and other properties etc that makes it a color light...  and also adding custom UIs to child QAs also doesn't look nice as the custom elements don't blend well with the native elements...

     

    a bit frustrating how it can be so hard to get anything that looks decent...?

     

    Has anyone in the forum managed to make anything that looks good in the Yubii app? supporting color/brightness/color_temperature ?

     

    I've looked at @petrkl12 color light child QA and I suppose it works but it's also an example of how the native and custom elements don't blend well (I don't know how it looks on a mobile).

     

    What I probably do is release a Hue QA that can be used from something like EventRunner but don't expose any UI (don't create any child QAs).

    Controlling Hue lights works really well from the Hue app and that's what my family uses anyway, and I only need to automate stuff in the background using ER.

     

    ...just blowing off some frustration ;-) 

    Link to comment
    Share on other sites

    Jan as fervent ER user:

    HUE settings are in your QA

    Operating HUE lights in HA>>ER

    ER is thanks to you very well operating and sometimes I need to adjust manual>>HUE  App

    Ybii App I don't want to use I only need to use in emergency cases

    Still a happy camper it will not remove your frustration but I hope it will take off the sharp edges.

     

    Link to comment
    Share on other sites

    5 hours ago, jgab said:

    So, I have a Hue V2 API engine in Lua that works on the HC3. It's using the event stream so it's pretty snappy compared to the old V2 where we needed to poll (and of course less cpu hungry).

    I even have a decent hsv<->rgb<->xy conversion routines (will never be perfect).

    So, Hue sensors and power plugs and white ambient lamps works nice... but color lights are killing me.

    It seems impossible to create a decent QA with color (hue+saturation or RGB), brightness and temperature.

    • Type com.fibaro.philipsHueLight gives the hue+saturation and brightness but lack temperature. Adding a 'warmWhite' component with colorComponents  makes it look very ugly.
    • Making a basic colorController and adding colorComponents R,G,B,warmWhite kind of makes it work but somehow the Brightness controller doesn't work (produces no onAction/UIEvent whatsoever...)

    I could build the UI from scratch based on multilevelSwitch using a hue, saturation and hue slider, but I would really like it to have the color and other properties etc that makes it a color light...  and also adding custom UIs to child QAs also doesn't look nice as the custom elements don't blend well with the native elements...

     

    a bit frustrating how it can be so hard to get anything that looks decent...?

     

    Has anyone in the forum managed to make anything that looks good in the Yubii app? supporting color/brightness/color_temperature ?

     

    I've looked at @petrkl12 color light child QA and I suppose it works but it's also an example of how the native and custom elements don't blend well (I don't know how it looks on a mobile).

     

    What I probably do is release a Hue QA that can be used from something like EventRunner but don't expose any UI (don't create any child QAs).

    Controlling Hue lights works really well from the Hue app and that's what my family uses anyway, and I only need to automate stuff in the background using ER.

     

    ...just blowing off some frustration ;-) 

     

    Hi Jan...

     

    We are using COH at home - but only for mapping/controlling HUE lights from 

    Please login or register to see this link.

     and using EV4 for the mapping.

    No need at all for any GUI from our site.

     

    I only use the Yubii app to set the house Alarm

    Link to comment
    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...