The updated version of weather script.
1.) Added possibility to read coordinates (latitude and longitude) from system.
2.) Changed data types of objects:
a.) for humidity dt.scale
b.) for uv_index dt.uint8
c.) for pressure dt.uint16
4. How often we can start this script?
You can run the script every four hours, should work fine.
1.) Added possibility to read coordinates (latitude and longitude) from system.
2.) Changed data types of objects:
a.) for humidity dt.scale
b.) for uv_index dt.uint8
c.) for pressure dt.uint16
Code:
-- Please comment objects which you are not using, comment also grp.write() at the bottom of script
--[[
-- You can set latitude and longitude in "Date time" option
-- go to LogicMachine->Utilities->Date and time
require('uci')
latitude = uci.get('genohm-scada.core.latitude') -- read latitude from system
latitude = tonumber(latitude) or 0
longitude = uci.get('genohm-scada.core.longitude') -- read longitude from system
longitude = tonumber(longitude) or 0
if(latitude == 0 and longitude == 0) then -- if cooridinates were not set in the system
latitude = 51.5072 -- London
longitude = 0.1276 -- London
end
--]]
-- you can set latitude and longitude manualy
-- (if you set coordinates using "Date time" do not forget to comment these two lines
latitude = 56.9496 -- Riga
longitude = 24.1052 -- Riga
--log('latitude = ' .. latitude)
--log('longitude = ' .. longitude)
--[[
status_temp = '32/1/13' -- group address of temperature, should be float
status_pressure = '32/1/14' -- air pressure, should be float
status_humidity = '32/1/15' -- relative humidity, should be float
status_wind_direction = '32/1/16' -- wind direction, should be float
status_wind_speed = '32/1/17' -- wind speed, should be float
status_uv_index = '32/2/4' -- UV index, should be float
status_feelslike_temp = '32/2/3' -- feels like temperature, should be float
status_rain_today = '32/1/11' -- today's rain object, should be boolean
status_snow_today = '32/1/12' -- today's snow object, should be boolean
status_min_temp_today = '32/1/20' -- today's minimum air temperature, float
status_max_temp_today = '32/1/21' -- today's maximum air temperature, float
status_min_pressure_today = '32/1/22' -- minimum air pressure, float
status_max_pressure_today = '32/1/23' -- maximum air pressure, float
status_min_wind_speed_today = '32/1/24' -- minimum wind speed, float
status_max_wind_speed_today = '32/1/25' -- maximum wind speed, float
status_min_uv_today = '32/2/5' -- minimum UV today, float
status_max_uv_today = '32/2/6' -- maximum UV today, float
status_rain_tomor = '32/1/9' -- tomorrow's rain object
status_snow_tomor = '32/1/10' -- tomorrow's snow object
status_min_temp_tomor = '32/1/26'
status_max_temp_tomor = '32/1/27'
status_min_pressure_tomor = '32/1/28'
status_max_pressure_tomor = '32/1/29'
status_min_wind_speed_tomor = '32/1/30'
status_max_wind_speed_tomor = '32/1/31'
status_min_uv_tomor = '32/2/7'
status_max_uv_tomor = '32/2/8'
--]]
--[[]]
status_temp = grp.create({ datatype = dt.float16, address = '33/1/1', name = 'current_temp',})
status_pressure = grp.create({ datatype = dt.uint16, address = '33/1/2', name = 'current_press',})
status_humidity = grp.create({ datatype = dt.scale, address = '33/1/3', name = 'current_humid',})
status_wind_direction = grp.create({ datatype = dt.float16, address = '33/1/4', name = 'current_wind_dir',})
status_wind_speed = grp.create({ datatype = dt.float16, address = '33/1/5', name = 'current_wind_sp',})
status_uv_index = grp.create({ datatype = dt.uint8, address = '33/1/6', name = 'current_uv_index',})
status_feelslike_temp = grp.create({ datatype = dt.float16, address = '33/1/7', name = 'current_feels_temp',})
status_rain_today = grp.create({ datatype = dt.bool, address = '33/1/8', name = 'rain_today',})
status_snow_today = grp.create({ datatype = dt.bool, address = '33/1/9', name = 'snow_today',})
status_min_temp_today = grp.create({ datatype = dt.float16, address = '33/1/10', name = 'today_temp_min',})
status_max_temp_today = grp.create({ datatype = dt.float16, address = '33/1/11', name = 'today_temp_max',})
status_min_pressure_today = grp.create({ datatype = dt.uint16, address = '33/1/12', name = 'today_press_min',})
status_max_pressure_today = grp.create({ datatype = dt.uint16, address = '33/1/13', name = 'today_press_max',})
status_min_wind_speed_today = grp.create({ datatype = dt.float16, address = '33/1/14', name = 'today_wind_min',})
status_max_wind_speed_today = grp.create({ datatype = dt.float16, address = '33/1/15', name = 'today_wind_max',})
status_min_uv_today = grp.create({ datatype = dt.uint8, address = '33/1/16', name = 'today_uv_min',})
status_max_uv_today = grp.create({ datatype = dt.uint8, address = '33/1/17', name = 'today_uv_max',})
status_rain_tomor = grp.create({ datatype = dt.bool, address = '33/1/18', name = 'rain_tomor',})
status_snow_tomor = grp.create({ datatype = dt.bool, address = '33/1/19', name = 'snow_tomor',})
status_min_temp_tomor = grp.create({ datatype = dt.float16, address = '33/1/20', name = 'tomor_temp_min',})
status_max_temp_tomor = grp.create({ datatype = dt.float16, address = '33/1/21', name = 'tomor_temp_max',})
status_min_pressure_tomor = grp.create({ datatype = dt.uint16, address = '33/1/22', name = 'tomor_press_min',})
status_max_pressure_tomor = grp.create({ datatype = dt.uint16, address = '33/1/23', name = 'tomor_press_max',})
status_min_wind_speed_tomor = grp.create({ datatype = dt.float16, address = '33/1/24', name = 'tomor_wind_min',})
status_max_wind_speed_tomor = grp.create({ datatype = dt.float16, address = '33/1/25', name = 'tomor_wind_max',})
status_min_uv_tomor = grp.create({ datatype = dt.uint8, address = '33/1/26', name = 'tomor_uv_min',})
status_max_uv_tomor = grp.create({ datatype = dt.uint8, address = '33/1/27', name = 'tomor_uv_max',})
--]]
rain_tod_YR = false -- is rainy or not (for today)
snow_tod_YR = false -- is snowy or not (for today)
rain_tom_YR = false -- is rainy or not (for tomorrow)
snow_tom_YR = false -- is snowy or not (for tomorrow)
-- current temperature, air pressure, humidity, wind direction and speed
temperature_YR = -273 -- temperature in degree Celsius
air_pressure_YR = -1 -- air pressure in hPa
humidity_YR = -1 -- air humidity in %
wind_direction_YR = -1 -- wind direction in degrees [0; 360)
wind_speed_YR = -1 -- wind speed in m/s
uv_index_YR = -1 -- UV index
feelslike_temp_YR = -273 -- feels like temperature in degree Celsius
function init_min_max_table() -- initialize table for minimum, maximum temperature, pressure, windspeed
local min_max = {}
min_max.min_t = 8000 -- minimum temperature for today
min_max.max_t = -273 -- maximum temperature for today
min_max.min_p = 8000 -- minimum pressure for today
min_max.max_p = -1 -- maximum pressure for today
min_max.min_w = 8000 -- minimum wind speed for today
min_max.max_w = -1 -- maximum wind speed for today
min_max.min_uv = 8000 -- minimum UV index
min_max.max_uv = -1 -- maximum UV index
return min_max
end
function set_timestamp(day) -- if day = 0 today; if day = 1 tomorrow, if day = 2 day after tomorrow
local date = os.date('*t')
date.day = date.day + day
local time = os.time(date)
return os.date('%Y-%m-%d', time), date.hour -- timestamp and current hour
end
-- minimum maximum values of temperature, pressure and windspeed
function min_max_temp_press_wind(dat_tab, min_max_tab)
min_max_tab.min_t = math.min(min_max_tab.min_t, dat_tab.air_temperature or 8000)
min_max_tab.max_t = math.max(min_max_tab.max_t, dat_tab.air_temperature or -273)
min_max_tab.min_p = math.min(min_max_tab.min_p, dat_tab.air_pressure_at_sea_level or 8000)
min_max_tab.max_p = math.max(min_max_tab.max_p, dat_tab.air_pressure_at_sea_level or -1)
min_max_tab.min_w = math.min(min_max_tab.min_w, dat_tab.wind_speed or 8000)
min_max_tab.max_w = math.max(min_max_tab.max_w, dat_tab.wind_speed or -1)
min_max_tab.min_uv = math.min(min_max_tab.min_uv, dat_tab.ultraviolet_index_clear_sky or 8000)
min_max_tab.max_uv = math.max(min_max_tab.max_uv, dat_tab.ultraviolet_index_clear_sky or -1)
return min_max_tab
end
function check_for_rain(next1h)
local is_rainy = false
local code = ''
if type(next1h) == 'table' and type(next1h.summary) == 'table' then
code = next1h.summary.symbol_code or ''
end
if code:find('rain') then
is_rainy = true
end
return is_rainy
end
function check_for_snow(next1h)
local is_snowy = false
local code = ''
if type(next1h) == 'table' and type(next1h.summary) == 'table' then
code = next1h.summary.symbol_code or ''
end
if code:find('snow') then
is_snowy = true
end
return is_snowy
end
function calc_heat_index(temperature, humidity)
if temperature < 26.7 then
log('for heat_index calculation temperature should be higher than +26.7 Celsius degree')
return -273
end
if humidity < 0 or humidity > 100 then
log('humidity should be in a range from 0 ... 100%')
return -273
end
local T = temperature
local H = humidity
local c_1 = -8.785
local c_2 = 1.611
local c_3 = 2.339
local c_4 = -0.146
local c_5 = -0.0123
local c_6 = -0.0164
local c_7 = 0.00221
local c_8 = 0.000725
local c_9 = -0.00000358
local heat_index = c_1+c_2*T+c_3*H+c_4*T*H+c_5*T*T+c_6*H*H+c_7*T*T*H+c_8*T*H*H+c_9*T*T*H*H
return heat_index
end
function calc_wind_chill(temperature, wind_speed)
if temperature > 10 then
log('temperature should be less than +10.0 Celsius degree')
return -273
end
if wind_speed < 0 or wind_speed > 49.2 then
log('wind speed should be in a range 0 ... 49.2 m/s')
return -273
end
local T_air = temperature -- air temperature Celsius degree
local a = 0.62 -- coef
local b = 0.51 -- coef
local T_1 = 13.1 -- Celsius degree
local T_2 = 14.6 -- Celsius degree
local M_0 = 1.3333 -- m/s
local M = wind_speed -- m/s
local T_wind_chill
if M > M_0 then
T_wind_chill = (a*T_air + T_1) + (b*T_air - T_2)*(M/M_0)^0.16
else
T_wind_chill = T_air
end
return T_wind_chill
end
function calc_feelslike(temperature, wind_speed, humidity)
local T_feelslike
if temperature <= 10.0 then -- if less than 10.0 Celsius degree (or equal) then wind chill
T_feelslike = calc_wind_chill(temperature, wind_speed)
elseif temperature >= 26.7 then -- if more than 26.7 Celsius degree (or equal) then heat index
T_feelslike = calc_heat_index(temperature, humidity)
else -- other cases just return temperature
T_feelslike = temperature
end
return T_feelslike
end
min_max_today = init_min_max_table() -- table for minimum maximum temperature, air pressure, wind direction
min_max_tomor = init_min_max_table() -- table for minimum maximum temperature, air pressure, wind direction
json = require('json')
http = require('socket.http')
args = 'lat=' .. latitude .. '&lon=' .. longitude
--url = 'https://api.met.no/weatherapi/locationforecast/2.0/compact?' .. args
url = 'https://api.met.no/weatherapi/locationforecast/2.0/complete?' .. args
mac = 0
io.readfile('/sys/class/net/eth0/address'):gsub('%x%x', function(v)
mac = mac * 256 + tonumber(v, 16)
end)
http.USERAGENT = 'LM ' .. mac
res, err = http.request(url)
data = json.pdecode(res)
if type(data) == 'table' then
timestamp, hour = set_timestamp(0) -- current day
if hour < 10 then
timestamp_current_hour = timestamp .. 'T0' .. hour .. ':00:00Z' -- time stamp for current hour
else
timestamp_current_hour = timestamp .. 'T' .. hour .. ':00:00Z' -- time stamp for current hour
end
--log('timestamp = ' .. timestamp)
timestamp_next = set_timestamp(1) -- timestamp for tomorrow
--log('timestamp_next = ' .. timestamp_next)
--timestamp_after_next = set_timestamp(2) -- timestamp for day after tomorrow
--log('timestamp_after_next = ' .. timestamp_after_next)
--timestamp_after_after = set_timestamp(3) -- timestamp for day after day after tomorrow
--log('timestamp_after_after = ' .. timestamp_after_after)
for i, entry in ipairs(data.properties.timeseries) do
-- for weather now
if entry.time == timestamp_current_hour then -- get data only for one hour (current hour)
current_data = entry.data.instant.details
if type(current_data) == 'table' then
temperature_YR = current_data.air_temperature or -273 -- temperature in Celsius degree
air_pressure_YR = current_data.air_pressure_at_sea_level or -1 -- air pressure in hPa
humidity_YR = current_data.relative_humidity or -1 -- air humidity in %
wind_direction_YR = current_data.wind_from_direction or -1 -- wind direction in degrees [0;360)
wind_speed_YR = current_data.wind_speed or -1 -- wind speed in m/s
uv_index_YR = current_data.ultraviolet_index_clear_sky or -1 -- uv index
feelslike_temp_YR = calc_feelslike(temperature_YR, wind_speed_YR, humidity_YR) -- feels like temperature in Celsius degree
end
end
if entry.time:sub(1, #timestamp) == timestamp then -- checks remaining hours + 3 previous hours of current day
current_data = entry.data.instant.details
if type(current_data) == 'table' then
min_max_today = min_max_temp_press_wind(current_data, min_max_today)
end
if rain_tod_YR == false then -- if detected rain does not check for rain
rain_tod_YR = check_for_rain(entry.data.next_1_hours)
end
if snow_tod_YR == false then -- if detected snow does not check for snow
snow_tod_YR = check_for_snow(entry.data.next_1_hours)
end
end
if entry.time:sub(1, #timestamp_next) == timestamp_next then -- checks 24 hours of next day
tomor_data = entry.data.instant.details
if type(tomor_data) == 'table' then
min_max_tomor = min_max_temp_press_wind(tomor_data, min_max_tomor)
end
if rain_tom_YR == false then -- if detected rain does not check for rain
rain_tom_YR = check_for_rain(entry.data.next_1_hours)
end
if snow_tom_YR == false then -- if detected snow does not check for snow
snow_tom_YR = check_for_snow(entry.data.next_1_hours)
end
end
end
-- data for current hour
grp.write(status_temp, temperature_YR)
grp.write(status_pressure, air_pressure_YR)
grp.write(status_humidity, humidity_YR)
grp.write(status_wind_direction, wind_direction_YR)
grp.write(status_wind_speed, wind_speed_YR)
grp.write(status_uv_index, uv_index_YR)
grp.write(status_feelslike_temp, feelslike_temp_YR)
-- data for today: rain, snow; min and max for temperature, pressure, wind
grp.write(status_rain_today, rain_tod_YR)
grp.write(status_snow_today, snow_tod_YR)
grp.write(status_min_temp_today, min_max_today.min_t)
grp.write(status_max_temp_today, min_max_today.max_t)
grp.write(status_min_pressure_today, min_max_today.min_p)
grp.write(status_max_pressure_today, min_max_today.max_p)
grp.write(status_min_wind_speed_today, min_max_today.min_w)
grp.write(status_max_wind_speed_today, min_max_today.max_w)
grp.write(status_min_uv_today, min_max_today.min_uv)
grp.write(status_max_uv_today, min_max_today.max_uv)
-- data for tomorrow: rain, snow; min and max for temperature, pressure, wind
grp.write(status_rain_tomor, rain_tom_YR)
grp.write(status_snow_tomor, snow_tom_YR)
grp.write(status_min_temp_tomor, min_max_tomor.min_t)
grp.write(status_max_temp_tomor, min_max_tomor.max_t)
grp.write(status_min_pressure_tomor, min_max_tomor.min_p)
grp.write(status_max_pressure_tomor, min_max_tomor.max_p)
grp.write(status_min_wind_speed_tomor, min_max_tomor.min_w)
grp.write(status_max_wind_speed_tomor, min_max_tomor.max_w)
grp.write(status_min_uv_tomor, min_max_tomor.min_uv)
grp.write(status_max_uv_tomor, min_max_tomor.max_uv)
end
4. How often we can start this script?
You can run the script every four hours, should work fine.