Weather based device control JSON API Example

Hi All, just wanted to post the results of my vera LUUP/LUA testing
to make a snow melt or simliar type of system trigger under certain weather conditions.
What It shows is how to use an API with a JSON reply and apply it in vera.

We were always able to get the snow melt device to trigger when the hard-wired, physical sensor detected snow but it would run on and on. A whiff of snow from a tree and boom another 4 hours. Very inefficient. I already had vera on site so…
I tried to use dark sky app but it just wasn’t matching my weather conditions. Weatherstack seems much more accurate for some reason. It is the api that vera is using in the top right corner when you login. The key is now turning it off and running it the minimum amount needed to do the job.

I have changed out my api access key to xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
and the zip I used to 12345 for the US there are other ways to look up the location data
refer to the api documents for specifics of this or any api you are using in your function

I do not profess to have the cleanest code but it works and it is well commented. feel free to refactor and show me how.

In our setup we are using a Remotec ZFM-80 that we control via scenes rather than directly
so that the system sends out notifications. I know you can do it many other ways, but this
is how I do it, so far. We do poll the device directly for status of course.

I set the scene to run every 30 mins and for our device we have a min run time of 2 hours
or there is no effect. I have included that logic in there as well using a fun system variable of

os.time()

Returns how many seconds since the epoch (1 January 1970, 00:00:00), under UTC time.

You get a nice number for time calculation and time based event triggering and handling.

The setVCvar and getVCvar work with a vera app called “Variable Container”
It displays the values nicely on the dashboard. So that I can see them in runtime.

Most of the debugging was done onsite with my laptop connected to Vera via ssh. Like this:

Connect to your vera unit via putty or the terminal:

ssh 192.168.0.100 or whatever your vera IP address is.

Login with “root” and the password printed on the bottom of the unit and issue the following commands:

cd /var/log/cmh

tail -f LuaUPnP.log | grep ‘^01|^5’

now you only see a certain kind of log, luup.log()

Ctrl+C - ends the debug log

the when you run your scene use a lot of luup.log(currcond) or whatever variable
you need to see in runtime. Make sure you hand in a string!

as per:

http://wiki.micasaverde.com/index.php/Luup_Debugging

This program is working well and I am happy with it so far. But I am already working on improvments.
I am working on a log. A file “snow.txt” that will basically show line after line of what
occured at those 30 min intervals.

CurrTime - CurrCond - BoilerOn - message

Something like that. Then build a little report from that data? And on it goes…

Another idea for improvement would be to include the amount of times that the api returned
“snow” needs to be 2 in a row before the system would turn on for the alotted 2 hours.
That way if it only snows for 20 mins we dont bother even firing the system for another 2 hours.

Really that is what vera is doing in this scenario is bringing smart effeciency to the situation.
It is worth the time we spent on it as from the first month of operation we see a massive
reduction in running costs as a result when its a snowy month.

I also use a nice vera app called “LuaView” It really helps with editing
luup code directly on the vera and greatly speeds up the iterative process of debugging etc.

I have attached the code as snowpost.lua inside snowpost.zip
tried to upload the lua directly but “computer says no”

snowpost.zip|attachment](upload://7HF1tKQcAVZxtQ88gu26aoSPlju.zip) (1.1 KB)

-- import required libraries
local json = require ("dkjson")
local http = require("socket.http")
-- Read in the weather json data from weatherstack
local status, result = luup.inet.wget("http://api.weatherstack.com/current?access_key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&query=12345", 5)
-- create "obj" the json object
local obj, pos, err = json.decode (result, 1, nil)
-- pull out the piece of data we need from the json object "Weather Descriptions"
CurrCond = (obj.current.weather_descriptions[1])
-- A nice readable time and date format
CurrTime = os.date()
-- number of seconds since midnight jan 1 1970
TriggerTime = os.time ()
-- Boiler current status
BoilerOn = luup.variable_get("urn:upnp-org:serviceId:SwitchPower1","Status", 65)
-- write out the conditions and time
setVCvar(16,1,CurrCond)
setVCvar(16,2,CurrTime)
-- if the "Weather Descriptions" contains "snow"
if string.match(CurrCond, "snow") then
    -- if the boiler is off
  if (BoilerOn == "0") then
    -- write out to the variable container
    setVCvar(16,3,"Boiler On")
    setVCvar(16,4,CurrTime)
    setVCvar(16,2,CurrCond)
    setVCvar(16,5,CurrCond)
    -- Record seconds since 1970 as a string in Variable 6
    local firetime = os.time()
    tostring(firetime)
    setVCvar(16,6,firetime)
    -- turn on the boiler
    luup.call_action("urn:micasaverde-com:serviceId:HomeAutomationGateway1", "RunScene", {SceneNum = "16"}, 0)
    return true
  end
else
  if (BoilerOn == "1") then
   -- Read in the timefired value from var6 in var container
   local firetime getVCvar(16,6)
   tonumber(firetime)
   -- compare the times and see if 2 hours less 10 seconds minimum (7190 seconds) have occured. No point in running the boiler for less than 2 hours.
   local timediff = os.difftime (TriggerTime, firetime)
   if (timediff < 7190) then
    luup.log("Not time to turn off the boiler yet")
   else
    luup.log("It's Time to turn off the boiler Now")
    --Turn off the boiler. I use a scene so that it triggers the notification
    luup.call_action("urn:micasaverde-com:serviceId:HomeAutomationGateway1", "RunScene", {SceneNum = "15"}, 0)
    setVCvar(16,3,"Boiler Off")
   end
  end
end