We have moved at community.getvera.com

Author Topic: openLuup: Asynchronous I/O  (Read 358 times)

Offline akbooer

  • Moderator
  • Master Member
  • *****
  • Posts: 6387
  • Karma: +292/-70
  • "Less is more"
openLuup: Asynchronous I/O
« on: March 14, 2019, 04:52:39 pm »
I have successfully been testing a version of the asynchronous I/O, in general, and specifically for VeraBridge.  As hoped for, the latency is much lower, and there is somewhat less polling activity.  I've tested common error conditions, including Luup reloads and Vera reboots.

The latest development release 2019.03.14 on GitHub is available for download.  By default, the asynchronous VeraBridge is not enabled, but there is a device variable AsyncPoll which, if set to "true", will enable it after a reload.

At the moment there are some additional log messages to check the behaviour, but overall, the only difference you should see is improved response times to Vera variable changes, and an additional socket named VERA async-tcp on the Console > Scheduler > Sockets page.

The bridge uses a new form of the http.request() which provides an asynchronous callback to the user when the response is received.  In theory, this could be available to openLuup plugin developers to handle things like SOAP / AJAX calls, but that's yet to be tested*.

If you care to try it, I'd welcome feedback.


* as discussed here: Using Soap onvif to listen for camera motion detection
« Last Edit: March 14, 2019, 05:57:11 pm by akbooer »
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline a-lurker

  • Hero Member
  • *****
  • Posts: 872
  • Karma: +66/-8
Re: openLuup: Asynchronous I/O
« Reply #1 on: March 14, 2019, 11:51:21 pm »
Ok - had a go at this, on a PI pcb, by updating my existing very well functioning set up (thanks for that):

openLuup & bridge now both show as version 19.13.14 as expected.
AsyncPoll set to "true" and restarted openLuup
http://ip_address:3480/console?page=sockets makes no mention of "VERA async-tcp"

console log shows:
Code: [Select]
2019-03-15 14:26:29.566   luup_log:5: VeraBridge ASYNC callback status code: ?, data length: 4
2019-03-15 14:26:29.567   openLuup.context_switch::  ERROR: ./openLuup/http.lua:547: attempt to call method 'sendrequestline' (a nil value)
2019-03-15 14:26:29.567   openLuup.scheduler:: job aborted : ./openLuup/http.lua:547: attempt to call method 'sendrequestline' (a nil value)

Suspect I have the wrong socket library as sendrequestline is not found in openLuup in GitHub?? If so, what to do?

I set AsyncPoll back to "false" and restarted openLuup in the hope that this will revert back to the method previously used?

Offline Buxton

  • Full Member
  • ***
  • Posts: 209
  • Karma: +12/-0
Re: openLuup: Asynchronous I/O
« Reply #2 on: March 15, 2019, 12:36:11 am »

Offline a-lurker

  • Hero Member
  • *****
  • Posts: 872
  • Karma: +66/-8
Re: openLuup: Asynchronous I/O
« Reply #3 on: March 15, 2019, 03:58:32 am »
@Buxton yes - that's the problem. I modified http.lua as per the file here:
http://forum.micasaverde.com/index.php/topic,48982.msg321683.html#msg321683

It no longer had sendrequestline() and also had a modified sendheaders(). So something fixed two years ago caused the the problem described above. So I rehashed that code to resurrect these two functions.

So setting AsyncPoll set to "true" and restarting openLuup now results in being shown in "VERA async-tcp" in http://ip_address:3480/console?page=sockets

The log file now shows lots of these - so looks like it's working:

Code: [Select]
VeraBridge ASYNC callback status code: 200, data length: xyz
Some initial confusion in that there are now two http.lua files. One being in the socket lib and one in openLuup. Does the latter also need to be called http.lua? Also can the functions sendrequestline() & sendheaders() be duplicated in the openLuup http.lua file or is that too hard? I don't quiet understand the interactions between the two http.lua files.

Have attached my updated http.lua socket version for reference.

Offline akbooer

  • Moderator
  • Master Member
  • *****
  • Posts: 6387
  • Karma: +292/-70
  • "Less is more"
Re: openLuup: Asynchronous I/O
« Reply #4 on: March 15, 2019, 07:10:47 am »
@a-lurker, great to see a response from you.  Thanks for trying it and finding a problem (albeit, of your own making, in the end?!)

@Buxton, great detective work.  I had not seen that post previously.

Karma to you both for that.

It's been my philosophy never to alter a 'system' library, for just these reasons, except through the usual GitHub pull request mechanism, and even then you'll run into installed version incompatibilties.  For this reason, I've been putting off (for years) delving into the LuaSocket library to see how I could do asynchronous I/O.  However, it turns out that there is a legitimate, although undocumented, way of doing this, and the low-level library itself provides almost all the tools you need.

Regarding the confusion of file naming, it isn't really a problem because one is socket.http and the other openLuup.http and, in truth, you shouldn't need to touch either.  However, I have been through this quandary before: the original file was called this, but then changed to openLuup.server but changed back per the comment in its header, when the server functionality became more general.  I'll consider another name change.  Ideas?

@amg0 has asked me whether this code will run on Vera, and I believe that with one small utility function to replace an openLuup scheduler call, then it could do just that.  The technique is not limited to HTTP,  since all the magic is actually happening at the TCP/socket level, but the code itself would need to be generalised a bit.

I just want this to get fully shaken down in VeraBridge before I try to widen its application.

Thanks both for your invaluable help.



PS: I've split this into a separate topic, since I think there may just be further discussion.

3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline akbooer

  • Moderator
  • Master Member
  • *****
  • Posts: 6387
  • Karma: +292/-70
  • "Less is more"
Re: openLuup: Asynchronous I/O
« Reply #5 on: March 16, 2019, 11:45:58 am »
The asynchronous HTTP request routine is accessible for anyone who wants to try this in a plugin.

The call parameters are exactly the same as http.request(), as documented here: LuaSocket http.request() but with an additional one for the callback routine:

Code: [Select]
-- "simple" GET request
local ok, err = luup.openLuup.async_request ("simple URL", myCallback)

-- "simple" POST request
local ok, err = luup.openLuup.async_request ("simple URL", "body of POST", myCallback)

-- "generic" request
local ok, err = luup.openLuup.async_request ({table with url, headers, sources, sinks, etc...}, myCallback)

Return code is non-nil for success when sending the request, nil followed by an error string if failure (including "closed" and "timeout").  In the event of failure, the callback routine will never be called.  If successful, the callback receives parameters which are exactly the same as the returns defined for the normal http.request() routine:

Code: [Select]
function myCallback (response, code, headers, statusline)
...
end

If the request was with a string URL, then the response is a string.  If it was of the generic form, then the response is 1 and actually ends up wherever you specified the ltn12 sink.

Note that the callback is specified as a normal function, not as a global string name, as in standard luup requests.  So if you wanted to ignore the response entirely, you could write:

Code: [Select]
local ok, err = luup.openLuup.async_request ("url goes here", function () end)

giving you a non-blocking send, although that could hang for a while if the socket open or send request times out.

This asynchronous request could be useful for getting images, or other large data, from cameras and suchlike, and certainly works well in VeraBridge for status data requests.
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline akbooer

  • Moderator
  • Master Member
  • *****
  • Posts: 6387
  • Karma: +292/-70
  • "Less is more"
Re: openLuup: Asynchronous I/O
« Reply #6 on: March 19, 2019, 06:35:45 am »
A somewhat unexpected side-effect of switching my main openLuup system to using asynchonous I/O for the currently two bridged Veras that it oversees was a dramatic drop in CPU usage.

Well, I say dramatic, it did halve, but since it's dropped from just 4% to 2% it may hardly matter.  What does matter, though, is the reduced latency in response times.

I'm left with wondering, once again, just where all the CPU goes in a Vera?  The current trend in HA (at least, as read here) is the move to very capable machines, but really the majority of HA automation actually needs nothing like that level of computing power.
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline Don Phillips

  • Hero Member
  • *****
  • Posts: 1464
  • Karma: +41/-36
Re: openLuup: Asynchronous I/O
« Reply #7 on: March 19, 2019, 07:39:18 pm »
I think that is what Melih was saying last fall.
Vera 3, 1.7.1040, CT101, Everspring Motion, GE/Jasco Switch/Dimmer, Leviton outlet, AeonLabs sensor, NuTone garage door, Blue Iris, Sricam SP011, iPhone locator, APCUPSD, VeraMate, VeraAlerts, PLEG, House Modes, Countdown Timer, DVR, Virtual/Multi Switch, LB60Z-1 bulb, Hue, Alexa, Zooz 4-1

Offline rafale77

  • Community Beta
  • Hero Member
  • ******
  • Posts: 1749
  • Karma: +101/-27
  • HA ≠ IoT as a blue sky is cloudless.
Re: openLuup: Asynchronous I/O
« Reply #8 on: March 19, 2019, 08:14:24 pm »
The misleading part of looking at CPU utilization is to focus not on the average or the idle rate but on the spikes. This is when you actually see the CPU constrained and potentially crash. Yeah sure most of the time it will be at 2-5% but if the cpu processing queue is overwhelmed... then we run into potential issues even if it is for a very short time.
openLuup (79 devices, 141 scenes, 19 apps) master to VeraPlus (142 zwave nodes, 8 Zigbee nodes, 221 devices,  20 scenes , 2 apps) +  Hubitat (15 Zigbee nodes) + Home-Assistant (API Integrations). Bridged to Siri and Alexa. Homewave. VeraPlus ExtRooted and mios server independent.

Offline akbooer

  • Moderator
  • Master Member
  • *****
  • Posts: 6387
  • Karma: +292/-70
  • "Less is more"
Re: openLuup: Asynchronous I/O
« Reply #9 on: March 20, 2019, 07:08:36 am »
The misleading part of looking at CPU utilization is to focus not on the average or the idle rate but on the spikes.

Undoubtedly true, and these plotted values are already averages, so the peaks are likely to hit 100% at times.

Quote
This is when you actually see the CPU constrained and potentially crash.

However, a well-written system should degrade gracefully, and certainly not crash.  Clearly you could bring it to its knees with multiple video streams, or such like, but I think that's just inappropriate use of an HA controller.
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline rafale77

  • Community Beta
  • Hero Member
  • ******
  • Posts: 1749
  • Karma: +101/-27
  • HA ≠ IoT as a blue sky is cloudless.
Re: openLuup: Asynchronous I/O
« Reply #10 on: March 20, 2019, 01:33:19 pm »
Completely agree. I was thinking more of the vera UI7 rather than openLuup here... I have yet to get openLuup to crash due to cpu useage.
openLuup (79 devices, 141 scenes, 19 apps) master to VeraPlus (142 zwave nodes, 8 Zigbee nodes, 221 devices,  20 scenes , 2 apps) +  Hubitat (15 Zigbee nodes) + Home-Assistant (API Integrations). Bridged to Siri and Alexa. Homewave. VeraPlus ExtRooted and mios server independent.