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
  • 40 minutes ago, marius de jong said:

    i am trying to press a button in a quickapp from a scene but i do not know the action to use.
    in the quickapp it is self:button2Clicked() but i cant seem to get it working from a lua scene to the quickapp

    Do you have a function in the QuickApp that looks like

    Please login or register to see this code.

    then this should work

    Please login or register to see this code.

    or do you have code inside the button that you need to run?

    Link to comment
    Share on other sites

  • Topic Author
  • On 3/28/2020 at 8:09 PM, Krikroff said:

    If it can help...

    Use:

    Please login or register to see this code.

     

     

    It's funny that the quickAppVariables panel allows for adding two variables with the same name. I wonder what the thinking behind that was...

    The other thing that's kind of surprising is that they implement it as a list(!). The more variables you have the longer access time. Lua supports key-value association, seems natural for a variable store.

    Also, when a quickAppVariable is changed with self:setVariable a 'DevicePropertyUpdatedEvent' with property = ''quickAppVariables' is thrown with ALL the variables in the data part... not very efficient.

    So, all in all, it feels like performance is not high on the priorities...

    Link to comment
    Share on other sites

  • Topic Author
  • 7 hours ago, petergebruers said:

    Thanks for sharing. Your code inspired me to turn that into a "Binary Sensor" quick app and apply a few "optimisations". Well, I think they are optimisations... Please tell me if you do not agree. Firstly I've moved the http client to "self" and create it in "onInit" only once. Because you only need one of those, per app, and it can handle all your requests. No need to create and destroy that HTTPClient each time. Also moved the "header" with authentication because that one also does not change and makes it easier to see where you define the password (if you has multiple http requests, in this example there is only one so not a good example). Actually, you could take it a bit further and store the options or the complete request, because it uses always the same options and url.

     

    So, I have to throw in my "coding style" too :-)

    I like the "event" model to structure all the callbacks, and I also don't like putting "local" functions on QuickApp as they become the "external" API of the QuickApp.  ( I'm starting to use my own QuickApp helper class that encapsulate some of the standard QuickApp code that's always needed - more on that in another post)

    Please login or register to see this code.

     

    • Thanks 1
    Link to comment
    Share on other sites

    10 hours ago, marius de jong said:

    i am trying to press a button in a quickapp from a scene but i do not know the action to use.
    in the quickapp it is self:button2Clicked() but i cant seem to get it working from a lua scene to the quickapp

    You can use API also without crateting endless QuickApp functions.

    api.get("/plugins/callUIEvent?deviceID="..<ID>.."&elementName="..<button ID name>.."&eventType=onPressed&value=null")

    Edited by cag014
    Link to comment
    Share on other sites

    I decided to turn my "refreshStates" example (a few posts back) with pseudocode into a working quickapp. What this will to is "listen" to events while at the same time "ticking" a clock every 2 seconds, to demonstrate both are working at the same time. The clock ticks every 2 seconds.

     

    Please login or register to see this code.

     

    I also decided to make it compatible with @jgab's HC3 emulator so you'll see a bit of extra code not required on your HC3. You can remove the parts between "if require then" and the next block if you don't need that.

     

    @jgab would you consider adding b64enc to your emulator? From emulator 0.75 onwards, encoded credentials are available as hc3_emulator.BasicAuthorization

     

    At the moment, running under emulation version 0.75, the clock tick has a 1 second resolution, thanks to a new feature introduced in that version (hc3_emulator.asyncHTTP=true) by @jgab

     

    Please login or register to see this code.

    I failed to come up with a good name for the variable "req". If someone has a better idea...

     

    Just to be clear... I am not suggestion people should use tick() as a clock (unless you make it really slow eg one tick per minute). The idea is that production code acts upon the state updates (eg motion sensor breached, now printed merely as "got state update") then decides if something needs to be done after a certain time (eg turn of the light) and uses fibaro.setTimeout to schedule that. I don't have a working example of that, because until now I've use the blocking "api.get" and relied on its (undocumented) 30 s timeout to do time related calculations.

    Edited by petergebruers
    • Like 1
    Link to comment
    Share on other sites

    Nice example.

    I have solved that by Quick:App which updates random value every 3 seconds. In this case refreshState doesn't stuck anymore.

    Link to comment
    Share on other sites

  • Topic Author
  • 32 minutes ago, petergebruers said:

    I decided to turn my "refreshStates" example (a few posts back) with pseudocode into a working quickapp. What this will to is "listen" to events while at the same time "ticking" a clock every 2 seconds, to demonstrate both are working at the same time. The clock ticks every 2 seconds.

    I also decided to make it compatible with @jgab's HC3 emulator so you'll see a bit of extra code not required on your HC3. You can remove the parts between "if require then" and the next block if you don't need that.

     

    @jgab would you consider adding b64enc to your emulator? Or a function or a (table) variable to retrieve the "basic auth string" in some way?

    Yes, I will do that. I will provide a variable in hc3_emulator with  the basic auth string to the HC3. However, it's purely for offline testing as code moving to the HC3 will not have access to. it.

     

    32 minutes ago, petergebruers said:

     

    At the moment, running under emulation, the clock does not tick, I have not investigated this yet.

     

    When I run your code in the emulator the clock ticks. Would be interesting to know what's different (I took away your includes/requires and use my own - are you doing something strange in CheckGlobalLeakage? )

     

    32 minutes ago, petergebruers said:

     

    I failed to come up with a good name for the variable "req". If someone has a better idea...

    'req' is as good as any. I guess there are more local variables needed in a full app and maybe scope them all in a local table name "App" ?

    I'm doing my own "App" class where I can store nice to have data and add local functions without polluting QuickApp. 

     

    Link to comment
    Share on other sites

  • Topic Author
  • 5 minutes ago, jgab said:

    When I run your code in the emulator the clock ticks. Would be interesting to know what's different (I took away your includes/requires and use my own - are you doing something strange in CheckGlobalLeakage? )

     

    Mine works with CheckGlobalLeakage too, so that's not it - what do you have in HC3settings? :-)

    Btw, I get an read exception for 'PROXY' deep inside http.lua

    ...dio.app/Contents/ZeroBraneStudio/lualibs/socket/http.lua:189: attempt to read undeclared variable PROXY

     

    Link to comment
    Share on other sites

    15 minutes ago, jgab said:

    When I run your code in the emulator the clock ticks.

    Thanks, maybe my comment was imprecise... It does tick, but ticks only after refreshStates reports an event. So it does not tick every 2 seconds as it does on HC3. I can investigate this later.

    Link to comment
    Share on other sites

  • Topic Author
  • 1 minute ago, petergebruers said:

    Thanks, maybe my comment was imprecise... It does tick, but ticks only after refreshStates reports an event. So it does not tick every 2 seconds as it does on HC3. I can investigate this later.

    Ah, I didn't see it because I have too frequent events.

    Ok, emulated net.HTTPClient() is not asynchronous. That's the way luasocket is implemented. To take in a non-blocking socket lib will create platform dependencies - or at least a more advanced configuration of fibaroapiHC3. Let me think about it.

    Link to comment
    Share on other sites

    11 minutes ago, jgab said:

    To take in a non-blocking socket lib will create platform dependencies - or at least a more advanced configuration of fibaroapiHC3. Let me think about it.

    Ah yes "socket" is blocking. Don't worry too much about it. At least not for my specific case, it is not important. To test "offline" and get things right I guess I will have to 'inject' fake data anyway. Debugging with time is always a bit tricky. I know you have provided things like "speedup" of the clock but I haven't used that trick yet.

     

    34 minutes ago, jgab said:

    Btw, I get an read exception for 'PROXY' deep inside http.lua

    Yeah, it seems you can set a global to force a proxy. I think by modern standards that is considered a bit ugly, but once an API is public it is probably hard to revert stuff users (might) rely on.

    Link to comment
    Share on other sites

  • Topic Author
  • 1 minute ago, petergebruers said:

    Ah yes "socket" is blocking. Don't worry too much about it. At least not for my specific case, it is not important. To test "offline" and get things right I guess I will have to 'inject' fake data anyway. Debugging with time is always a bit tricky. I know you have provided things like "speedup" of the clock but I haven't used that trick yet.

     

    Yeah, it seems you can set a global to force a proxy. I think by modern standards that is considered a bit ugly, but once an API is public it is probably hard to revert stuff users (might) rely on.

    You have an updated version of CheckGlobalLeakage.lua ? 

    Link to comment
    Share on other sites

    4 minutes ago, jgab said:

    You have an updated version of CheckGlobalLeakage.lua ? 

    Please login or register to see this attachment.

    • Like 1
    Link to comment
    Share on other sites

    15 hours ago, jgab said:

    It's funny that the quickAppVariables panel allows for adding two variables with the same name. I wonder what the thinking behind that was...

     

     

    I don't think it works, When adding a variable with the same name the value is simply overwritten ...

    Link to comment
    Share on other sites

  • Topic Author
  • 6 minutes ago, Krikroff said:

     

     

    I don't think it works, When adding a variable with the same name the value is simply overwritten ...

    If you use the web tab to add variables manually, you can add multiple with same name. (5.021.38)

    Edited by jgab
    Link to comment
    Share on other sites

    I have updated my refreshStates example... New code after @jgab released a new version of his HC3 emulator. Clock now ticks offline and code can be simplified because we no longer need base 64 encoder.

     

     

    Link to comment
    Share on other sites

    52 minutes ago, jgab said:

    If you use the web tab to add variables manually, you can add multiple with same name. (5.021.38)

     

    You are right ?

     

    Please login or register to see this image.

    /monthly_2020_03/QA_Vars_bugs.PNG.07dbde9b73675d99eccbe4ec39d03b79.PNG" />

    • Like 1
    Link to comment
    Share on other sites

    • 2 weeks later...
  • Topic Author
  • Question:

    In the debug we see "onAction" and "onUIEvent" traces and debugs...

    Ex.

    [13.04.2020] [18:17:18] [DEBUG] [QUICKAPP263]: onAction: {"args":[513],"deviceId":263,"actionName":"removeChildDevice"}

     

    Is there a way to intercept these actions?

    It would be nice if defining QuickApp:onAction(deviceId,actionName,args) I would get the action.... but that doesn't work.

    At the moment I have a device with many children and when I remove a child device with the web UI trashcan I'm unaware of it - I can scan the childDevices list all the time but it feels a bit unnecessary.

    Anyone with some insights?

     

    Btw. more questions:

    'core.EventTarget' and 'Device' are classes. What's their purposes?

    Edited by jgab
    Link to comment
    Share on other sites

    21 minutes ago, jgab said:

    It would be nice if defining QuickApp:onAction(deviceId,actionName,args) I would get the action.... but that doesn't work.

     

    ;) by design i also expected that!  but you must declare the name of the event handler directly in the control

     

    image.png.1f19bc147ac8ca504480a860cc2b90bd.png

     

    What is interesting is to be able to manage several buttons with the same method, for example: a QA with 10 buttons btnRadio1, btnRadio2, btnRadio3 ...

     

    Please login or register to see this code.

     

    30 minutes ago, jgab said:

    At the moment I have a device with many children and when I remove a child device with the web UI trashcan I'm unaware of it

     

    it would be nice to be able to subscribe to an event for that ;)

     

    31 minutes ago, jgab said:

    'core.EventTarget' and 'Device' are classes. What's their purposes?

     

    I saw that too, for me, 'Device' hum ... i suspect :

    Please login or register to see this code.

     

    Link to comment
    Share on other sites

  • Topic Author
  • 43 minutes ago, Krikroff said:

     

    ;) by design i also expected that!  but you must declare the name of the event handler directly in the control

     

    Please login or register to see this link.

     

    Yes, for the onUIEvent I get it, but what about the 'onAction' event?

    Please login or register to see this code.

    Th 'onAction' is logged when QuickApp:<functions> are called among other things - so it seems like it is some kind of callback "inside" the QuickApp class.

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