Skip to content

Commit

Permalink
Split weather and forecast
Browse files Browse the repository at this point in the history
  • Loading branch information
javalikescript committed Dec 6, 2024
1 parent 5646f10 commit cf386b7
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 29 deletions.
41 changes: 33 additions & 8 deletions extensions/owm/adapter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ local CUMULATIVE_FIELD_MAP = {
rain = true,
}

local HOUR_SEC = 3600
local DAY_SEC = 86400

local function adapt(w, d)
local a = {}
for k, p in pairs(FIELD_MAP) do
Expand All @@ -46,17 +49,28 @@ local function sumFields(a, w)
return a
end

local function rangeHours(hours, time)
local t = time or os.time()
local tt = t + hours * 3600
local function between(from, to)
return function(w)
return w.dt >= t and w.dt < tt
return w.dt >= from and w.dt < to
end
end

local function tomorrow(time)
local d = os.date('*t', time + DAY_SEC)
d.hour = 0
d.min = 15
d.sec = 0
return os.time(d)
end

local function hour(time)
local d = os.date('*t', time + DAY_SEC)
return d.hour
end

local function range(days, from, to, time)
local t = time or os.time()
local d = os.date('*t', t + 86400 * (days or 0))
local d = os.date('*t', t + DAY_SEC * (days or 0))
d.min = 15
d.sec = 0
d.hour = from or 0
Expand Down Expand Up @@ -98,19 +112,30 @@ local function aggregate(list)
return a
end

local DAY_MORNING = 7
local DAY_EVENING = 19

-- 5 day forecast includes weather forecast data with 3-hour step

return {
computeCurrent = function(weather)
return adapt(weather)
end,
computeNextHours = function(forecast, time)
return aggregate(List.filter(forecast.list, rangeHours(8, time)))
local t = time or os.time()
return aggregate(List.filter(forecast.list, between(t, t + 4 * HOUR_SEC)))
end,
computeToday = function(forecast, time)
local t = time or os.time()
if hour(t) <= 12 then
return aggregate(List.filter(forecast.list, range(0, DAY_MORNING, DAY_EVENING, t)))
end
return aggregate(List.filter(forecast.list, between(t, tomorrow(t))))
end,
computeTomorrow = function(forecast, time)
return aggregate(List.filter(forecast.list, range(1, 7, 19, time)))
return aggregate(List.filter(forecast.list, range(1, DAY_MORNING, DAY_EVENING, time)))
end,
computeNextDays = function(forecast, time)
return aggregate(List.filter(forecast.list, ranges(7, 19, time)))
return aggregate(List.filter(forecast.list, ranges(DAY_MORNING, DAY_EVENING, time)))
end
}
3 changes: 1 addition & 2 deletions extensions/owm/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
"cityId": {
"title": "City ID",
"type": "string",
"deprecated": true,
"required": true
"deprecated": true
},
"latitude": {
"title": "Latitude",
Expand Down
2 changes: 1 addition & 1 deletion extensions/owm/owm.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ define(['./owm.xml'], function(owmTemplate) {
//console.info('units:', this.unit);
}
var props = properties[thing.thingId];
if (props) {
if (props && thing.properties.date) {
var t = props.date ? new Date(props.date).getTime() : 0;
var h = t > now ? Math.floor((t - now) / 3600000) : 0;
var item = Object.assign({
Expand Down
39 changes: 23 additions & 16 deletions extensions/owm/owm.lua
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,6 @@ local function createWeatherThing(title, description)
readOnly = true,
unit = 'percent'
})
thing:addProperty('rain', {
['@type'] = 'LevelProperty',
title = 'Rain volume',
type = 'number',
description = 'The rain volume in millimeter',
minimum = 0,
readOnly = true,
unit = 'mm'
})
thing:addProperty('windSpeed', {
['@type'] = 'LevelProperty',
title = 'Wind speed',
Expand All @@ -55,6 +46,20 @@ local function createWeatherThing(title, description)
readOnly = true,
unit = 'degree'
})
return thing
end

local function createForecastThing(title, description)
local thing = createWeatherThing(title or 'Weather', description or 'Weather Data')
thing:addProperty('rain', {
['@type'] = 'LevelProperty',
title = 'Rain volume',
type = 'number',
description = 'The rain volume in millimeter',
minimum = 0,
readOnly = true,
unit = 'mm'
})
thing:addProperty('date', {
['@type'] = "DateTimeProperty",
configuration = true,
Expand All @@ -78,9 +83,10 @@ end

local THINGS_BY_KEY = {
current = createWeatherThing('Weather Now'),
nextHours = createWeatherThing('Weather Next Hours'),
tomorrow = createWeatherThing('Weather Tomorrow'),
nextDays = createWeatherThing('Weather Next Days')
nextHours = createForecastThing('Weather Next Hours'),
today = createForecastThing('Weather Today'),
tomorrow = createForecastThing('Weather Tomorrow'),
nextDays = createForecastThing('Weather Next Days')
}
local thingByKey = {}
local configuration = extension:getConfiguration()
Expand Down Expand Up @@ -114,9 +120,10 @@ extension:subscribeEvent('things', function()
end
end)

local function updateForecastThing(data, time)
updateWeatherThing(thingByKey.tomorrow, adapter.computeTomorrow(data, time))
local function updateForecastThings(data, time)
updateWeatherThing(thingByKey.nextHours, adapter.computeNextHours(data, time))
updateWeatherThing(thingByKey.today, adapter.computeToday(data, time))
updateWeatherThing(thingByKey.tomorrow, adapter.computeTomorrow(data, time))
updateWeatherThing(thingByKey.nextDays, adapter.computeNextDays(data, time))
end

Expand All @@ -129,7 +136,7 @@ if configuration.demo then
updateWeatherThing(thingByKey.current, adapter.computeCurrent(data))
data = json.parse(File:new('work-misc/forecast.json'):readAll())
local time = data.list[1].dt - 3600
updateForecastThing(data, time)
updateForecastThings(data, time)
end)
else
-- Do not send OWM requests more than 1 time per 10 minutes from one device/one API key
Expand All @@ -149,7 +156,7 @@ else
updateWeatherThing(thingByKey.current, adapter.computeCurrent(data))
return client:fetch(path..'forecast'..query)
end):next(utils.rejectIfNotOk):next(utils.getJson):next(function(data)
updateForecastThing(data, os.time())
updateForecastThings(data, os.time())
end):catch(function(reason)
logger:warn('fail to get OWM, due to "%s"', reason)
end):finally(function()
Expand Down
3 changes: 2 additions & 1 deletion extensions/web-base/www/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,8 @@
<select v-if="hasOfSchema" v-model="ofIndex" style="width: unset; border-color: lightgray;">
<option v-for="(name, i) in ofSchemaLabels" :value="i">{{name}}</option>
</select>
<span v-else v-on:click.exact="toggle()" v-on:click.alt.exact="toggleAll()">{{ label }}</span>
<span v-else-if="schema.deprecated"><s>{{ label }}</s></span>
<span v-else v-on:click.exact="toggle()">{{ label }}</span>
<span class="required" v-if="schema.required" title="The value is required">*</span>
</span>
<span class="hover-visible" v-if="isListItem">
Expand Down
6 changes: 5 additions & 1 deletion tools/owm.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ local utils = require('lha.utils')
local adapter = require('extensions.owm.adapter')

local data = json.parse(File:new(arg[1]):readAll())
local time
if arg[2] then
time = utils.timeFromString(arg[2])
end

local function printWeather(w, l)
if l then
Expand All @@ -18,7 +22,7 @@ local function printWeather(w, l)
end

if data.list then
local time = data.list[1].dt - 3600
time = time or (data.list[1].dt - 3600)
print('', 'date', 'temp', 'rain', 'cloud', 'wind')
for i, w in ipairs(data.list) do
local d = utils.timeToString(w.dt)
Expand Down

0 comments on commit cf386b7

Please sign in to comment.