Page 1 of 1

Access to current data (not documented?)

Posted: Thu 03 Jan 2019 5:40 pm
by GSV3MiaC
A wrinkle I discovered while looking for a way to access my Cumulus/Davis weather station data, now that WU is pretty much defunct (I was sending it up to WU and then API-ing it back) .. if you access:

http://192.168.1.21:8998/api/data/currentdata

(replace the URL with your own IP address for the MX server)

you can download a .json response with everything you might want to know neatly encoded in it (firefox has the facility to display it nicely formatted, if you tell it that you want to see json, rather than plaintext). This makes it a (relative) doddle to suck the currents station data into whatever app you want to use it with (assuming a modicum of programming skill) .. I've been using LUA to get it into Domoticz, and VBA to get it into Excel.

If this is in the wiki/documentation I failed to find it. I was looking at using WXNOW.txt, but that has several issues. You can try to read the data files directly, but that is a PITA across a mixed network (some Windoze, some Raspberry Pi, some Synology) and you have to be careful that data files are not locked when Cumulus wants them.

Re: Access to current data (not documented?)

Posted: Sat 05 Jan 2019 4:55 pm
by laulau
GSV3MiaC wrote: Thu 03 Jan 2019 5:40 pm .. I've been using LUA to get it into Domoticz,
Hi,
I'm also a Domoticz user, is it possible for you to share the lua script ?
Thanks

Re: Access to current data (not documented?)

Posted: Sun 06 Jan 2019 3:20 pm
by mcrossley
GSV3MiaC wrote: Thu 03 Jan 2019 5:40 pm If this is in the wiki/documentation I failed to find it.
It isn't formally documented, same with the other API data streams that the management interface uses, and of course it can only be accessed on your local LAN.

Re: Access to current data (not documented?)

Posted: Sun 06 Jan 2019 4:35 pm
by freddie
mcrossley wrote: Sun 06 Jan 2019 3:20 pm it can only be accessed on your local LAN.
You can access from outside your LAN if you set up a reverse proxy. I do this with my trends page. Saves having loads of FTP traffic, but is probably only advisable on a relatively low traffic site.

Re: Access to current data (not documented?)

Posted: Sun 06 Jan 2019 5:24 pm
by mcrossley
True, and if utilising the API for your website I'd recommend...
a. Only allowing access from web server processes.
b. Looking into a short term caching scheme if you expect multiple concurrent visitors.

I experimented with setting up a MQTT service on my server (and using a commercial service) and feeding the data into that. Has the advantage of only a single update process and supports n number of clients. It worked rather well.

Re: Access to current data (not documented?)

Posted: Mon 07 Jan 2019 10:14 am
by GSV3MiaC
laulau wrote: Sat 05 Jan 2019 4:55 pm
GSV3MiaC wrote: Thu 03 Jan 2019 5:40 pm .. I've been using LUA to get it into Domoticz,
Hi,
I'm also a Domoticz user, is it possible for you to share the lua script ?
Thanks
Hmm, OK, but this is very much work-in-progress and my LUA coding level is definitely 'newbie'. 8>. Also note that I run in Metric, so I have not coded MPH to M/sec, or Pressure from InHg to mb, or anything else (but how to do it should be obvious). I'm also still waiting for some rain to see if I need a multiplier or whatever ..

--
-- Script to read current weather data from CumulusMX, in JSON format,
-- and stick it into dummy/virtual sensors on Domoticz system.
--
-- Since we can't assume that the web server will respond immediately, we actually
-- run one minute behind - i.e. this script accesses a temporary file which was built
-- by a CURL call in the previous minute. If your CumulusMX server is blindingly fast and on
-- your own local LAN, you could risk reading/parsing the JSON in the same timed call.
--
-- CumulusMX presents more 'now' data than you probably need, and more than I care to document,
-- but if you navigate to '/api/data/currentdata' on your Cumulus server with something like Firefox,
-- you can display the returned page as parsed json, and most of the values are obvious.
--


function MakeTimeStamp(dateString)
-- Jan 01 2019 20:55
local pattern = "(%a+)%s(%d+)%s(%d+)%s(%d+):(%d+)"
local months = { jan=1, feb=2, mar=3, apr=4, may=5, jun=6, jul=7, aug=8, sep=9, oct=10, nov=11, dec=12 }
local xmonth, xday, xyear, xhour, xminute = dateString:match(pattern)
local convertedTimestamp = os.time({year = xyear, month = months[string.lower((xmonth))],
day = xday, hour = xhour, min = xminute})
return convertedTimestamp
end

-- round a number to numDecimalPlaces (not a build in math function in most cases)
function round(num, numDecimalPlaces)
local mult = 10^(numDecimalPlaces or 0)
return math.floor(num * mult + 0.5) / mult
end


---loads a json file with the provided name and returns it as a table (if it exists)
local function readLuaFromJsonFile(fileName)
local file = io.open(fileName, 'r')
if file then
package.path = './scripts/lua/?.lua;'..package.path
local jsonParser = require('JSON')
local _json = file:read('*a')
local json = jsonParser:decode(_json)
io.close(file)
return json
end
return nil
end

-- get device name from idx number .. returns 0 if there is none
function getdevname4idx(deviceIDX)
for i, v in pairs(otherdevices_idx) do
if v == deviceIDX then
return i
end
end
return 0
end

-- And finally the actual LUA code
commandArray = {}
local jsonResultFile = '/tmp/tmpJson.json' -- Temporary file to store the servers response
local url = 'http://192.168.1.21:8998/api/data/currentdata'
local THB_device = 281
local Wind_device = 282
local Rain_device = 283
local Forecast_device = 284

local CumulusData = readLuaFromJsonFile(jsonResultFile)
if not CumulusData then
print('Could not read Cumulus Data from file: '.. jsonResultFile)
goto DoRead
end

debug = false
if debug then
print('json data file has been read')
print("OutdoorTemp = "..CumulusData.OutdoorTemp..CumulusData.TempUnit)
print("OutdoorHum = "..CumulusData.OutdoorHum.."%")
print("Pressure = "..CumulusData.Pressure .. CumulusData.PressUnit)
print("RainLastHour = "..CumulusData.RainLastHour..CumulusData.RainUnit)
print("RainToday = "..CumulusData.RainToday..CumulusData.RainUnit)
print("WindLatest = "..CumulusData.WindLatest..CumulusData.WindUnit)
print("Recentmaxgust = "..CumulusData.Recentmaxgust..CumulusData.WindUnit)
print("Avgbearing = "..CumulusData.Avgbearing)
print("DominantWindDirection = "..CumulusData.DominantWindDirection)
print("Forecast = "..CumulusData.Forecast)
end

temp = CumulusData.OutdoorTemp
humidity = CumulusData.OutdoorHum
pressure = CumulusData.Pressure
wind_dir = CumulusData.Avgbearing
wind_dir_name = CumulusData.DominantWindDirection
wind_speed = CumulusData.WindLatest
wind_gust =CumulusData.Recentmaxgust
rain_in_hour = CumulusData.RainLastHour
rain_today = CumulusData.RainToday

if CumulusData.TempUnit == "°F" then
temp = tostring(round((tonumber(temp)-32)*5/9,1))
end

if CumulusData.WindUnit == "km/h" then
wind_speed = tostring(round(tonumber(wind_speed)/.36,1)) -- convert mph to m/s, 10ths
wind_gust = tostring(round(tonumber(wind_gust)/.36,1)) -- convert mph to m/s, 10ths
end

if CumulusData.RainUnit == "in" then
rain_in_hour = tostring(round(tonumber(rain_in_hour)*25.4,1))
rain_today = tostring(round(tonumber(rain_today)*25.4,1))
end

pressure = tostring(tonumber(pressure)) -- Domoticz guage wants mb
fore = CumulusData.Forecast

hum_num = tonumber(humidity)
if ((hum_num >= 46) and (hum_num <= 70)) then humidity_status = "1" -- comfortable
elseif (hum_num < 46) then humidity_status = "2" -- dry
elseif (hum_num > 70) then humidity_status = "3" -- wet
else humidity_status = "0"
end

commandArray[#commandArray+1]={['UpdateDevice'] = THB_device .. "|0|".. temp..";"..humidity..";"..humidity_status..";"..pressure.. ";0"}
commandArray[#commandArray+1]={['UpdateDevice'] = Wind_device .. "|0|".. wind_dir ..";"..wind_dir_name..";"..wind_speed..";"..wind_gust.. ";0;0"}
commandArray[#commandArray+1]={['UpdateDevice'] = Rain_device .. "|0|".. rain_in_hour ..";"..rain_today}
-- print(rain_in_hour.." "..rain_today)
if otherdevices_svalues[getdevname4idx(Forecast_device)] ~= fore then
if debug then
print("New Forecast")
print("/"..fore.."/")
print("/"..tostring(otherdevices_svalues[Forecast_device]).."/")
end
commandArray[#commandArray+1]={['UpdateDevice'] = Forecast_device .. "|0|".. fore}
end

-- Now queue up the next read

::DoRead::
if debug then
print('Requesting data from the Cumulus server...')
print('URL used: '..url)
end
os.execute('curl -s "'..url..'" > '..jsonResultFile..'&')

return commandArray



p.s. updated 22/1/19 to fix Forecast text device updating. Will adjust further if I find more problems...

Re: Access to current data (not documented?)

Posted: Tue 08 Jan 2019 4:42 pm
by GSV3MiaC
Oops, those km/h to m/sec conversions were off by 10x (now fixed)

Re: Access to current data (not documented?)

Posted: Tue 08 Jan 2019 8:31 pm
by BCJKiwi
Just an alternative suggestion;

Not sure what your total setup is, but you could easily construct a template file with whatever format you want, in the CumulsMX/web folder and configure extra web files to generate a corresponding data file at the "realtime" interval you have configured in MX.
Extra web files will then deliver it to a local folder and/or a website (local and/or remote) at the realtime interval which could be anything above the 2 and bit seconds interval of the internal cycle of CumulusMX.
No conflict with CumulusMX's internal files and no extra temporary file!