UNPKG

homebridge-weather-plus-with-pws-sync

Version:

A comprehensive weather plugin for homekit with current observations, forecasts and history.

297 lines (279 loc) 12.4 kB
/*jshint esversion: 6,node: true,-W041: false */ /*To use this API Use with weewx add the weewx extension weewx-json (https://github.com/teeks99/weewx-json) and create a formatted JSON response template as below { "observations":[ { "stationID": "$station.location", "softwareType": "weewx $station.version", "realtimeFrequency": "$current.interval", #if $current.radiation.has_data "solarRadiation": $current.radiation.raw, #end if #if $current.rain.raw > 0 "rainbool": true, #else "rainbool": false, #end if "lon": $station.stn_info.longitude_f, "epoch": $current.dateTime.raw, "lat": $station.stn_info.latitude_f, #if $current.UV.has_data "uv": $current.UV, #end if #if $current.windDir.has_data "winddir": $current.windDir.raw, #end if #if $current.outHumidity.has_data "humidity": $current.outHumidity.raw, #end if #if $current.o3.has_data "o3": $current.o3.raw #end if "imperial": { #if $current.outTemp.has_data "temp": $current.outTemp.degree_F.raw, #end if #if $day.outTemp.has_data "maxtemp": $day.outTemp.max.degree_F.raw, "mintemp": $day.outTemp.min.degree_F.raw, #end if #if $current.appTemp.has_data "apptemp": $current.appTemp.degree_F.raw, #end if #if $current.dewpoint.has_data "dewpt": $current.dewpoint.degree_F.raw, #end if #if $current.windSpeed.has_data "windSpeed": $current.windSpeed.mile_per_hour.raw, #end if #if $current.windGust.has_data "windGust": $current.windGust.mile_per_hour.raw, #end if #if $current.barometer.has_data "pressure": $current.barometer.inHg.raw, #end if #if $hour.rain.has_data "precip1h": $hour($hours_ago=1).rain.sum.inch.raw, #end if #if $current.rainRate.has_data "precipRate": $current.rainRate.inch_per_hour.raw, #end if #if $day.rain.has_data "rainday": $day.rain.sum.inch.raw #end if }, "metric": { #if $current.outTemp.has_data "temp": $current.outTemp.degree_C.raw, #end if #if $day.outTemp.has_data "maxtemp": $day.outTemp.max.degree_C.raw, "mintemp": $day.outTemp.min.degree_C.raw, #end if #if $current.appTemp.has_data "apptemp": $current.appTemp.degree_C.raw, #end if #if $current.dewpoint.has_data "dewpt": $current.dewpoint.degree_C.raw, #end if #if $current.windSpeed.has_data "windSpeed": $current.windSpeed.km_per_hour.raw, #end if #if $current.windGust.has_data "windGust": $current.windGust.km_per_hour.raw, #end if #if $current.barometer.has_data "pressure": $current.barometer.mbar.raw, #end if #if $hour.rain.has_data "precip1h": $hour($hours_ago=1).rain.sum.mm.raw, #end if #if $current.rainRate.has_data "precipRate": $current.rainRate.mm_per_hour.raw, #end if #if $day.rain.has_data "rainday": $day.rain.sum.mm.raw #end if }, "metric_si": { #if $current.outTemp.has_data "temp": $current.outTemp.degree_C.raw, #end if #if $day.outTemp.has_data "maxtemp": $day.outTemp.max.degree_C.raw, "mintemp": $day.outTemp.min.degree_C.raw, #end if #if $current.appTemp.has_data "apptemp": $current.appTemp.degree_C.raw, #end if #if $current.dewpoint.has_data "dewpt": $current.dewpoint.degree_C.raw, #end if #if $current.windSpeed.has_data "windSpeed": $current.windSpeed.meter_per_second.raw, #end if #if $current.windGust.has_data "windGust": $current.windGust.meter_per_second.raw, #end if #if $current.barometer.has_data "pressure": $current.barometer.mbar.raw, #end if #if $hour.rain.has_data "precip1h": $hour($hours_ago=1).rain.sum.mm.raw, #end if #if $current.rainRate.has_data "precipRate": $current.rainRate.mm_per_hour.raw, #end if #if $day.rain.has_data "rainday": $day.rain.sum.mm.raw #end if }, "uk_hybrid": { #if $current.outTemp.has_data "temp": $current.outTemp.degree_C.raw, #end if #if $day.outTemp.has_data "maxtemp": $day.outTemp.max.degree_C.raw, "mintemp": $day.outTemp.min.degree_C.raw, #end if #if $current.appTemp.has_data "apptemp": $current.appTemp.degree_C.raw, #end if #if $current.dewpoint.has_data "dewpt": $current.dewpoint.degree_C.raw, #end if #if $current.windSpeed.has_data "windSpeed": $current.windSpeed.mile_per_hour.raw, #end if #if $current.windGust.has_data "windGust": $current.windGust.mile_per_hour.raw, #end if #if $current.barometer.has_data "pressure": $current.barometer.mbar.raw, #end if #if $hour.rain.has_data "precip1h": $hour($hours_ago=1).rain.sum.mm.raw, #end if #if $current.rainRate.has_data "precipRate": $current.rainRate.mm_per_hour.raw, #end if #if $day.rain.has_data "rainday": $day.rain.sum.mm.raw #end if } } ] } */ "use strict"; const request = require('request'), converter = require('../util/converter'), geoTz = require('geo-tz'), moment = require('moment-timezone'), debug = require('debug')('homebridge-weather-plus'); class WeewxAPI { constructor(apiKey, log) { this.attribution = 'Powered by Weewx'; this.reportCharacteristics = [ 'ObservationStation', 'SolarRadiation', 'RainBool', 'ObservationTime', 'UVIndex', 'WindDirection', 'Humidity', 'Ozone', 'Temperature', 'TemperatureApparent', 'DewPoint', 'WindSpeed', 'WindSpeedMax', 'AirPressure', 'Rain1h', 'RainDay' ]; this.log = log; //this.location = location; this.apiKey = apiKey; // Get observation values only in si 's' for now. this.units = 's'; } update(forecastDays, callback) { debug("Updating weather with weewx"); let weather = {}; let that = this; //formatting url as http://site/file.json (using apikey for URL) const queryUri = this.apiKey; request(encodeURI(queryUri), function (err, response, body) { if (!err) { // Current weather report try { const jsonObj = JSON.parse(body); if (jsonObj.errors === undefined || jsonObj.errors.length === 0) { debug(JSON.stringify(jsonObj, null, 2)); weather.report = that.parseReport(jsonObj); callback(null, weather); } else { throw new Error(JSON.stringify(jsonObj.errors, null, 2)); } } catch (e) { that.log.error("Error retrieving weather report and forecast"); that.log.error("Error Message: " + e); callback(e); } } else { that.log.error("Error retrieving weather report and forecast"); that.log.error("Error Message: " + err); callback(err); } }.bind(this)); } parseReport(json) { let that = this; let report = {}; try { let observation = json.observations[0]; let values; debug("Units: " + this.units); // Get values depending on chosen unit in request if (this.units === 's') { values = observation.metric_si; } else if (this.units === 'm') { values = observation.metric; } else if (this.units === 'e') { values = observation.imperial; } else { // 'h' values = observation.uk_hybrid; } const timezone = String(geoTz(parseFloat(observation.lat), parseFloat(observation.lon))); report.ObservationStation = observation.stationID; report.RainBool = observation.rainbool; report.ObservationTime = moment.unix(observation.epoch).tz(timezone).format('HH:mm:ss'); report.WindDirection = converter.getWindDirection(isNaN(parseInt(observation.winddir)) ? 0 : parseInt(observation.winddir)); report.WindBearing = observation.winddir; report.Humidity = isNaN(observation.humidity) ? 0 : observation.humidity; report.SolarRadiation = isNaN(observation.solarRadiation) ? 0 : observation.solarRadiation; report.UVIndex = isNaN(observation.uv) ? 0 : observation.uv; report.Ozone = isNaN(observation.ozone) ? 0 : observation.ozone; report.Temperature = isNaN(values.temp) ? 0 : values.temp; report.DewPoint = isNaN(values.dewpt) ? 0 : values.dewpt; report.AirPressure = isNaN(values.pressure) ? 0 : values.pressure; report.TemperatureApparent = isNaN(values.apptemp) ? 0 : values.apptemp; report.WindSpeed = isNaN(values.windSpeed) ? 0 : values.windSpeed; report.WindSpeedMax = isNaN(values.windGust) ? 0 : values.windGust; report.Rain1h = isNaN(values.rain1h) ? 0 : values.rain1h; report.RainDay = isNaN(values.rainday) ? 0 : values.rainday; } catch (error) { that.log.error("Error parsing weather report for Weewx"); that.log.error("Error Message: " + error); } return report; } parseForecasts(forecastObjs, timezone) { /* NO FORECAST DATA FROM API */ return []; } } module.exports = { WeewxAPI: WeewxAPI };