-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f683a5f
commit fb1f4ca
Showing
9 changed files
with
380 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
local List = require('jls.util.List') | ||
local tables = require('jls.util.tables') | ||
|
||
local utils = require('lha.utils') | ||
|
||
-- temp_min temp_max | ||
-- sys.sunrise: 1485720272 | ||
-- sys.sunset: 1485766550 | ||
-- city.name: "Paris" | ||
|
||
local FIELD_MAP = { | ||
temperature = 'main/temp', | ||
humidity = 'main/humidity', | ||
pressure = 'main/pressure', | ||
cloud = 'clouds/all', | ||
windSpeed = 'wind/speed', | ||
windDirection = 'wind/deg', | ||
rain = 'rain/3h', -- Rain volume for last 3 hours | ||
} | ||
|
||
local CUMULATIVE_FIELD_MAP = { | ||
rain = true, | ||
} | ||
|
||
local function adapt(w, d) | ||
local a = {} | ||
for k, p in pairs(FIELD_MAP) do | ||
a[k] = tables.getPath(w, p, d) | ||
end | ||
a.date = utils.timeToString(w.dt) | ||
return a | ||
end | ||
|
||
local function adaptNil(w) | ||
return adapt(w) | ||
end | ||
|
||
local function sumFields(a, w) | ||
for k, v in pairs(w) do | ||
if type(v) == 'number' then | ||
a[k] = (a[k] or 0) + v | ||
else | ||
a[k] = v | ||
end | ||
end | ||
return a | ||
end | ||
|
||
local function range(days, from, to, time) | ||
local t = time or os.time() | ||
local d = os.date('*t', t + 86400 * (days or 0)) | ||
d.min = 15 | ||
d.sec = 0 | ||
d.hour = from or 0 | ||
local ft = os.time(d) | ||
d.hour = to or 23 | ||
local tt = os.time(d) | ||
return function(w) | ||
return w.dt >= t and w.dt >= ft and w.dt < tt | ||
end | ||
end | ||
|
||
local function ranges(from, to, time) | ||
local t = time or os.time() | ||
local r3 = range(2, from, to, t) | ||
local r4 = range(3, from, to, t) | ||
local r5 = range(4, from, to, t) | ||
return function(w) | ||
return r3(w) or r4(w) or r5(w) | ||
end | ||
end | ||
|
||
local function aggregate(list) | ||
local w = List.reduce(List.map(list, adaptNil), sumFields, adapt({}, 0)) | ||
local a, n = {}, #list | ||
for k, v in pairs(w) do | ||
if type(v) == 'number' and not CUMULATIVE_FIELD_MAP[k] then | ||
a[k] = (v * 100 // n) / 100 | ||
else | ||
a[k] = v | ||
end | ||
end | ||
return a | ||
end | ||
|
||
-- 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, range(0, 7, 19, time))) | ||
end, | ||
computeTomorrow = function(forecast, time) | ||
return aggregate(List.filter(forecast.list, range(1, 7, 19, time))) | ||
end, | ||
computeNextDays = function(forecast, time) | ||
return aggregate(List.filter(forecast.list, ranges(7, 19, time))) | ||
end | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
define(['./owm.xml'], function(owmTemplate) { | ||
|
||
var unitAlias = app.getUnitAliases(); | ||
var directionLabels = ['-', 'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']; | ||
var directions = ['\u21BB', '\u2191', '\u2197', '\u2192', '\u2198', '\u2193', '\u2199', '\u2190', '\u2196']; | ||
|
||
function compare(a, b) { | ||
return a === b ? 0 : (a > b ? 1 : -1); | ||
} | ||
function compareTimes(a, b) { | ||
return compare(a.time, b.time); | ||
} | ||
function formatIcon(props) { | ||
if (props.rain) { | ||
if (props.rain > 10) { | ||
return 'cloud-showers-heavy'; | ||
} | ||
return props.cloud < 66 ? 'cloud-sun-rain' : 'cloud-rain'; | ||
} else if (props.cloud > 33) { | ||
return props.cloud < 66 ? 'cloud-sun' : 'cloud'; | ||
} | ||
return 'sun'; | ||
} | ||
function formatDirection(direction, speed, label) { | ||
var i = 0; | ||
if (typeof speed !== 'number' || speed > 0) { | ||
i = Math.round(direction / 45) % 8 + 1; | ||
} | ||
if (label) { | ||
return directionLabels[i]; | ||
} | ||
return directions[i]; | ||
} | ||
|
||
var owmVue = new Vue({ | ||
template: owmTemplate, | ||
data: { | ||
empty: true, | ||
unit: {}, | ||
times: [] | ||
}, | ||
methods: { | ||
onDataChange: function() { | ||
Promise.all([ | ||
app.getThings(), | ||
app.getPropertiesByThingId() | ||
]).then(apply(this, function(things, properties) { | ||
this.refresh(things, properties); | ||
})); | ||
}, | ||
onShow: function() { | ||
this.onDataChange(); | ||
}, | ||
formatDirection: function(d) { | ||
return formatDirection(d); | ||
}, | ||
extractUnits: function(thing) { | ||
for (var name in thing.properties) { | ||
var unit = thing.properties[name].unit; | ||
if (unit) { | ||
this.unit[name] = unitAlias[unit] || unit; | ||
} | ||
} | ||
}, | ||
refresh: function(things, properties) { | ||
var now = Date.now(); | ||
var times = []; | ||
for (var i = 0; i < things.length; i++) { | ||
var thing = things[i]; | ||
if (thing.extensionId === 'owm') { | ||
if (this.empty) { | ||
this.empty = false; | ||
this.extractUnits(thing); | ||
//console.info('units:', this.unit); | ||
} | ||
var props = properties[thing.thingId]; | ||
if (props) { | ||
var t = props.date ? new Date(props.date).getTime() : 0; | ||
var h = t > now ? Math.floor((t - now) / 3600000) : 0; | ||
var item = Object.assign({ | ||
title: thing.title, | ||
label: h < 24 ? (h + 'h'): (Math.floor(h / 24) + 'd'), | ||
time: t, | ||
faIcon: 'fa-' + formatIcon(props) | ||
}, props); | ||
times.push(item); | ||
} | ||
} | ||
} | ||
times.sort(compareTimes); | ||
//console.info('times:', times); | ||
this.times = times; | ||
} | ||
} | ||
}); | ||
|
||
addPageComponent(owmVue, 'fa-umbrella'); | ||
|
||
}); |
Oops, something went wrong.