UNPKG

homebridge-ecowitt-weather-sensors

Version:

Homebridge support for your Fine Offset weather station (Ecowitt, Ambient, Froggit, GoGen, and more)

793 lines 36.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.v2ConfigKeys = exports.v1ConfigKeys = exports.UNKNOWN = exports.UNDERGROUND = exports.AMBIENT = exports.ECOWITT = exports.CHAR_INTENSITY_UUID = exports.CHAR_INTENSITY_NAME = exports.CHAR_TIME_UUID = exports.CHAR_TIME_NAME = exports.CHAR_VALUE_UUID = exports.CHAR_VALUE_NAME = exports.MIGRATION_GUIDE_LINK = exports.GATEWAY_SETUP_LINK = exports.FEATURE_REQ_LINK = exports.BUG_REPORT_LINK = void 0; exports.boundRange = boundRange; exports.truthy = truthy; exports.falsy = falsy; exports.lookup = lookup; exports.includesAll = includesAll; exports.includesAny = includesAny; exports.toCelcius = toCelcius; exports.toFahrenheit = toFahrenheit; exports.tohPa = tohPa; exports.toMile = toMile; exports.toKts = toKts; exports.toKph = toKph; exports.toMps = toMps; exports.toBeafort = toBeafort; exports.toWindSector = toWindSector; exports.toRainIntensity = toRainIntensity; exports.toAirQuality = toAirQuality; exports.toUVRiskLevel = toUVRiskLevel; exports.v1ConfigTest = v1ConfigTest; exports.dataReportTranslator = dataReportTranslator; exports.baseStationRemapper = baseStationRemapper; exports.v1ConfigRemapper = v1ConfigRemapper; // eslint-disable-next-line @typescript-eslint/no-var-requires const merge = require('deepmerge'); // external help links exports.BUG_REPORT_LINK = 'https://bit.ly/3yklrWZ'; exports.FEATURE_REQ_LINK = 'https://bit.ly/4fzeAtj'; exports.GATEWAY_SETUP_LINK = 'https://bit.ly/3YGnYVU'; exports.MIGRATION_GUIDE_LINK = 'https://bit.ly/4d4K8oh'; //------------------------------------------------------------------------------ // custom characteristics name and uuid exports.CHAR_VALUE_NAME = 'Value'; exports.CHAR_VALUE_UUID = 'dc87b6c3-84ab-41a6-ae13-69fea759ee39'; exports.CHAR_TIME_NAME = 'Last Updated'; exports.CHAR_TIME_UUID = 'd1130039-59df-4b0e-a8ba-8527c854e3fa'; exports.CHAR_INTENSITY_NAME = 'Intensity'; exports.CHAR_INTENSITY_UUID = 'fdd76937-37bb-49f2-b1a0-0705fe548782'; //------------------------------------------------------------------------------ // protocol types exports.ECOWITT = 'Ecowitt'; exports.AMBIENT = 'Ambient'; exports.UNDERGROUND = 'Underground'; //------------------------------------------------------------------------------ exports.UNKNOWN = 'Unknown'; //------------------------------------------------------------------------------ // config keys exports.v1ConfigKeys = ['mac', 'port', 'path', 'unregister', 'ws', 'thbin', 'th', 'tf', 'soil', 'leak', 'pm25', 'lightning']; exports.v2ConfigKeys = ['baseStation', 'nameOverrides', 'additional', 'thresholds', 'hidden', 'units']; //------------------------------------------------------------------------------ function boundRange(percent, lowerBound = 0, upperBound = 100) { return Math.max(lowerBound, Math.min(upperBound, percent)); } //------------------------------------------------------------------------------ function truthy(val) { if (typeof val === 'undefined') { return false; } return String(val).toLowerCase() === 'true' || String(val).toLowerCase() === '1'; } //------------------------------------------------------------------------------ function falsy(val) { if (typeof val === 'undefined') { return true; } return String(val).toLowerCase() === 'false' || String(val).toLowerCase() === '0'; } //------------------------------------------------------------------------------ // eslint-disable-next-line @typescript-eslint/no-explicit-any function lookup(object, key) { if (typeof object === 'undefined' || typeof key === 'undefined') { return undefined; } let obj = {}; if (Array.isArray(object)) { object.forEach(x => obj[x.key] = x.value); } else { obj = object; } const lowKey = key.toLowerCase(); const index = Object.keys(obj).find(k => k.toLowerCase() === lowKey); if (typeof index === 'undefined') { return undefined; } else { return obj[index]; } } //------------------------------------------------------------------------------ function includesAll(arr, values) { const lowArr = arr.map(name => name.toLowerCase()); const lowVal = values.map(name => name.toLowerCase()); return lowVal.every(k => lowArr.includes(k)); } //------------------------------------------------------------------------------ function includesAny(arr, values) { const lowArr = arr.map(name => name.toLowerCase()); const lowVal = values.map(name => name.toLowerCase()); return lowVal.some(k => lowArr.includes(k)); } //------------------------------------------------------------------------------ function toCelcius(fahrenheit) { return ((parseFloat(fahrenheit) - 32.0) * 5.0) / 9.0; } //------------------------------------------------------------------------------ function toFahrenheit(celcius) { return ((9.0 / 5.0) * parseFloat(celcius)) + 32.0; } //------------------------------------------------------------------------------ function tohPa(inHg) { return parseFloat(inHg) * 33.8638; } //------------------------------------------------------------------------------ function toMile(km) { return parseFloat(km) * 0.6214; } //------------------------------------------------------------------------------ const kWindSectors = [ 'N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW', ]; // upper limits for each scale threshold const kBeaufortScale = [ { force: 0, description: 'Calm', kts: 1, mph: 1, kph: 2, mps: 0.5, }, { force: 1, description: 'Light Air', kts: 3, mph: 3, kph: 5, mps: 1.5, }, { force: 2, description: 'Light Breeze', kts: 6, mph: 7, kph: 11, mps: 3.3, }, { force: 3, description: 'Gentle Breeze', kts: 10, mph: 12, kph: 19, mps: 5.5, }, { force: 4, description: 'Moderate Breeze', kts: 16, mph: 18, kph: 28, mps: 7.9, }, { force: 5, description: 'Fresh Breeze', kts: 21, mph: 24, kph: 38, mps: 10.7, }, { force: 6, description: 'Strong Breeze', kts: 27, mph: 31, kph: 49, mps: 13.8, }, { force: 7, description: 'Near Gale', kts: 33, mph: 38, kph: 61, mps: 17.1, }, { force: 8, description: 'Gale', kts: 40, mph: 46, kph: 74, mps: 20.7, }, { force: 9, description: 'Strong Gale', kts: 47, mph: 54, kph: 88, mps: 24.4, }, { force: 10, description: 'Storm', kts: 55, mph: 63, kph: 102, mps: 28.4, }, { force: 11, description: 'Violent Storm', kts: 63, mph: 72, kph: 117, mps: 32.6, }, { force: 12, description: 'Hurricane', kts: Number.POSITIVE_INFINITY, mph: Number.POSITIVE_INFINITY, kph: Number.POSITIVE_INFINITY, mps: Number.POSITIVE_INFINITY, }, ]; //------------------------------------------------------------------------------ function toKts(mph) { return parseFloat(mph) * 0.86897624; } //------------------------------------------------------------------------------ function toKph(mph) { return parseFloat(mph) * 1.609344; } //------------------------------------------------------------------------------ function toMps(mph) { return parseFloat(mph) * 0.44704; } //------------------------------------------------------------------------------ function toBeafort(mph) { let beaufort = kBeaufortScale.find((scale) => mph <= scale.mph); if (!beaufort) { beaufort = kBeaufortScale[kBeaufortScale.length - 1]; } return beaufort; } //------------------------------------------------------------------------------ function toWindSector(degrees) { if (typeof degrees !== 'number' || isNaN(degrees)) { return 'NaN'; } const index = Math.round((degrees % 360) / 24.0); let sectorName = kWindSectors[index]; if (!sectorName) { sectorName = 'None'; } return sectorName; } //------------------------------------------------------------------------------ // classifcations from MANOBS (Manual of Surface Weather Observations) function toRainIntensity(ratemm) { if (ratemm <= 0) { return 'None'; } else if (ratemm <= 2.5) { return 'Light'; } else if (ratemm <= 7.5) { return 'Moderate'; } else if (ratemm <= 50.0) { return 'Heavy'; } else { return 'Violent'; } } // european air quality index - https://ecmwf-projects.github.io/copernicus-training-cams/proc-aq-index.html const airQualityScale = [ { scale: 1, description: 'Excellent', pm10: 20, pm25: 10, }, { scale: 2, description: 'Good', pm10: 40, pm25: 20, }, { scale: 3, description: 'Fair', pm10: 50, pm25: 25, }, { scale: 4, description: 'Inferior', pm10: 100, pm25: 50, }, { scale: 5, description: 'Poor', pm10: Number.POSITIVE_INFINITY, pm25: Number.POSITIVE_INFINITY, }, ]; //------------------------------------------------------------------------------ function toAirQuality(pm, pmType) { let airQuality = airQualityScale.find((scale) => pm <= scale[pmType]); if (!airQuality) { airQuality = airQualityScale[airQualityScale.length - 1]; } return airQuality; } // https://en.wikipedia.org/wiki/Ultraviolet_index const uvIndexScale = [ { level: 2, risk: 'Low', }, { level: 5, risk: 'Moderate', }, { level: 7, risk: 'High', }, { level: 10, risk: 'Very High', }, { level: Number.POSITIVE_INFINITY, risk: 'Extreme', }, ]; //------------------------------------------------------------------------------ function toUVRiskLevel(index) { let uvRating = uvIndexScale.find((scale) => index <= scale.level); if (!uvRating) { uvRating = uvIndexScale[uvIndexScale.length - 1]; } return uvRating; } //------------------------------------------------------------------------------ function v1ConfigTest(v1Config) { if (includesAny(Object.keys(v1Config), exports.v1ConfigKeys)) { return true; } return false; } //------------------------------------------------------------------------------ // convert ambient data report to ecowitt data report // eslint-disable-next-line @typescript-eslint/no-explicit-any function dataReportTranslator(ambDataReport) { const ecoDataReport = JSON.parse(JSON.stringify(ambDataReport)); let key, value; const wh65Prop = ['tempf', 'humidity', 'solarradiation', 'uv', 'winddir', 'windspeedmph', 'windgustmph', 'maxdailygust', 'eventrainin', 'hourlyrainin', 'dailyrainin', 'weeklyrainin', 'monthlyrainin']; // omit 'yearlyrainin' const wh67Prop = ['tempf', 'humidity', 'winddir', 'windspeedmph', 'windgustmph', 'maxdailygust', 'eventrainin', 'hourlyrainin', 'dailyrainin', 'weeklyrainin', 'monthlyrainin']; // omit 'yearlyrainin' const wh80Prop = ['tempf', 'humidity', 'solarradiation', 'uv', 'winddir', 'windspeedmph', 'windgustmph', 'maxdailygust']; const wh90Prop = ['tempf', 'humidity', 'solarradiation', 'uv', 'winddir', 'windspeedmph', 'windgustmph', 'maxdailygust', 'rrain_piezo', 'erain_piezo', 'hrain_piezo', 'drain_piezo', 'wrain_piezo', 'mrain_piezo', 'yrain_piezo']; for (const entry of Object.entries(ambDataReport)) { key = entry[0]; value = entry[1]; // battout maps to the sensor array battery which depends on the product bundle if (key === 'battout') { if (ambDataReport.stationtype === undefined) { ecoDataReport.stationtype = 'AMBWeather'; } // wh40 and wh80/wh90 can look like wh65/wh67 const wh40Exists = ambDataReport.battrain !== undefined; if (!wh40Exists && includesAll(Object.keys(ecoDataReport), wh65Prop)) { // must be WS2000, or WS2902 ecoDataReport.wh65batt = value; // wh65 default if (ambDataReport.battin !== undefined) { // WS2000 comes with WH25 for indoor ecoDataReport.model = 'HP2550'; // WS2000 } else { ecoDataReport.model = 'WS2900'; // WS2902 } delete ecoDataReport.battout; continue; } if (!wh40Exists && includesAll(Object.keys(ecoDataReport), wh67Prop)) { // must be WS1965 ecoDataReport.wh65batt = value; // wh67 default ecoDataReport.model = 'WN1920'; delete ecoDataReport.battout; continue; } if (includesAll(Object.keys(ecoDataReport), wh90Prop)) { // must be WS4000 ecoDataReport.wh90batt = value; // wh90 default ecoDataReport.model = 'HP2550'; delete ecoDataReport.battout; continue; } if (includesAll(Object.keys(ecoDataReport), wh80Prop)) { // must be WS5000 ecoDataReport.wh80batt = value; // wh80 default ecoDataReport.model = 'HP2550'; delete ecoDataReport.battout; continue; } // if no sensor array matched, then assume outdoor TH sensor if (ecoDataReport.battout !== undefined) { delete ecoDataReport.battout; ecoDataReport.wh26batt = value; ecoDataReport.model = exports.UNKNOWN; } } // indoor temp/humdity sensor - wh25 if (key === 'battin') { delete ecoDataReport.battin; ecoDataReport.wh25batt = value; } // rain detector - wh40 if (key === 'battrain') { delete ecoDataReport.battrain; ecoDataReport.wh40batt = value; } // pm25 outdoor sensor - wh41, ch1 if (key === 'batt_25') { delete ecoDataReport[key]; ecoDataReport.pm25batt1 = value; } if (key === 'pm25') { delete ecoDataReport[key]; ecoDataReport.pm25_ch1 = value; } if (key === 'pm25_24hr') { delete ecoDataReport[key]; ecoDataReport.pm25_avg_24h_ch1 = value; } // pm25 indoor sensor - wh43, ch2 if (key === 'batt_25in') { delete ecoDataReport[key]; ecoDataReport.pm25batt2 = value; } if (key === 'pm25_in') { delete ecoDataReport[key]; ecoDataReport.pm25_ch2 = value; } if (key === 'pm25_in_24hr') { delete ecoDataReport[key]; ecoDataReport.pm25_avg_24h_ch2 = value; } // air quality sensor - wh45 if (key.startsWith('batt_co2')) { delete ecoDataReport[key]; ecoDataReport[key.replace('batt_co2', 'co2_batt')] = value; } if (key === 'pm_in_temp_aqin') { delete ecoDataReport[key]; ecoDataReport.tf_co2 = value; } if (key === 'pm_in_humidity_aqin') { delete ecoDataReport[key]; ecoDataReport.humi_co2 = value; } if (key === 'pm10_in_aqin') { delete ecoDataReport[key]; ecoDataReport.pm10_co2 = value; } if (key === 'pm10_in_24h_aqin') { delete ecoDataReport[key]; ecoDataReport.pm10_24h_co2 = value; } if (key === 'pm25_in_aqin') { delete ecoDataReport[key]; ecoDataReport.pm25_co2 = value; } if (key === 'pm25_in_24h_aqin') { delete ecoDataReport[key]; ecoDataReport.pm25_24h_co2 = value; } if (key === 'co2_in_aqin') { delete ecoDataReport[key]; ecoDataReport.co2 = value; } if (key === 'co2_in_24h_aqin') { delete ecoDataReport[key]; ecoDataReport.co2_24h = value; } // soil moisture sensor - wh51 if (key.startsWith('battsm')) { delete ecoDataReport[key]; ecoDataReport[key.replace('battsm', 'soilbatt')] = value; } if (key.startsWith('soilhum')) { delete ecoDataReport[key]; ecoDataReport[key.replace('soilhum', 'soilmoisture')] = value; } // leak sensor - wh55 if (key.startsWith('batleak')) { delete ecoDataReport[key]; ecoDataReport[key.replace('batleak', 'leakbatt')] = value; } if (key.startsWith('leak')) { delete ecoDataReport[key]; ecoDataReport[key.replace('leak', 'leak_ch')] = value; } // lightning sensor - wh57 if (key === 'batt_lightning') { delete ecoDataReport.batt_lightning; ecoDataReport.wh57batt = value; } if (key === 'lightning_distance') { delete ecoDataReport.lightning_distance; ecoDataReport.lightning = value; } if (key === 'lightning_day') { delete ecoDataReport.lightning_day; ecoDataReport.lightning_num = value; } if (key === 'lightning_hour' && ambDataReport.lightning_day === undefined) { delete ecoDataReport.lightning_hour; ecoDataReport.lightning_num = value; } // leaf wetness sensor - wn35 if (key.startsWith('batt_lw')) { delete ecoDataReport[key]; ecoDataReport[key.replace('batt_lw', 'leaf_batt')] = value; } if (key.startsWith('leafwetness')) { delete ecoDataReport[key]; ecoDataReport[key.replace('leafwetness', 'leafwetness_ch')] = value; } } // set model if not detected if (ecoDataReport.model === undefined) { ecoDataReport.model = exports.UNKNOWN; } return ecoDataReport; } //------------------------------------------------------------------------------ // eslint-disable-next-line @typescript-eslint/no-explicit-any function baseStationRemapper(config) { const remappedConfig = JSON.parse(JSON.stringify(config)); let key, value; // hidden if (config.hidden !== undefined) { for (const entry of Object.entries(config.hidden)) { key = entry[0]; value = entry[1]; if (key === 'GW1000' || key === 'GW2000' || key === 'GW3000' || key === 'HP2560') { delete remappedConfig.hidden[key]; remappedConfig.hidden.BASE = value; } } } // nameoverride if (config.nameOverrides !== undefined) { for (let i = 0; i < config.nameOverrides.length; i++) { key = config.nameOverrides[i].key.split(':'); value = config.nameOverrides[i].value; if (key[0] === 'GW1000' || key[0] === 'GW2000' || key[0] === 'GW3000' || key[0] === 'HP2560') { remappedConfig.nameOverrides[i].key = `BASE:${key[1]}`; } } } return remappedConfig; } //------------------------------------------------------------------------------ // eslint-disable-next-line @typescript-eslint/no-explicit-any function v1ConfigRemapper(v1Config) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75; // eslint-disable-next-line @typescript-eslint/no-explicit-any const v2Config = { 'baseStation': {}, 'nameOverrides': [], 'additional': {}, 'thresholds': {}, 'hidden': {}, 'customHidden': [], 'units': {}, 'platform': 'Ecowitt', }; // base station if (v1Config === null || v1Config === void 0 ? void 0 : v1Config.mac) { v2Config.baseStation.mac = v1Config.mac; } if (v1Config === null || v1Config === void 0 ? void 0 : v1Config.port) { v2Config.baseStation.port = v1Config.port; } if (v1Config === null || v1Config === void 0 ? void 0 : v1Config.path) { v2Config.baseStation.path = v1Config.path; } // units if ((_b = (_a = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _a === void 0 ? void 0 : _a.wind) === null || _b === void 0 ? void 0 : _b.units) { v2Config.units.wind = (_d = (_c = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _c === void 0 ? void 0 : _c.wind) === null || _d === void 0 ? void 0 : _d.units; } if ((_f = (_e = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _e === void 0 ? void 0 : _e.rain) === null || _f === void 0 ? void 0 : _f.units) { v2Config.units.rain = (_h = (_g = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _g === void 0 ? void 0 : _g.rain) === null || _h === void 0 ? void 0 : _h.units; } if ((_j = v1Config === null || v1Config === void 0 ? void 0 : v1Config.lightning) === null || _j === void 0 ? void 0 : _j.units) { v2Config.units.distance = (_k = v1Config === null || v1Config === void 0 ? void 0 : v1Config.lightning) === null || _k === void 0 ? void 0 : _k.units; } v2Config.units.temperature = 'fh'; // hidden if (truthy((_l = v1Config === null || v1Config === void 0 ? void 0 : v1Config.thbin) === null || _l === void 0 ? void 0 : _l.hide)) { v2Config.hidden['GW1000'] = true; v2Config.hidden['GW2000'] = true; v2Config.hidden['HP2560'] = true; } if (truthy((_m = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _m === void 0 ? void 0 : _m.hide)) { v2Config.hidden['WS85'] = true; v2Config.hidden['WH65'] = true; } if (truthy((_o = v1Config === null || v1Config === void 0 ? void 0 : v1Config.th) === null || _o === void 0 ? void 0 : _o.hide)) { v2Config.hidden['WN31'] = true; } if (truthy((_p = v1Config === null || v1Config === void 0 ? void 0 : v1Config.tf) === null || _p === void 0 ? void 0 : _p.hide)) { v2Config.hidden['WN34'] = true; } if (truthy((_q = v1Config === null || v1Config === void 0 ? void 0 : v1Config.soil) === null || _q === void 0 ? void 0 : _q.hide)) { v2Config.hidden['WH51'] = true; } if (truthy((_r = v1Config === null || v1Config === void 0 ? void 0 : v1Config.leak) === null || _r === void 0 ? void 0 : _r.hide)) { v2Config.hidden['WH55'] = true; } if (truthy((_s = v1Config === null || v1Config === void 0 ? void 0 : v1Config.pm25) === null || _s === void 0 ? void 0 : _s.hide)) { v2Config.hidden['WH41'] = true; } if (truthy((_t = v1Config === null || v1Config === void 0 ? void 0 : v1Config.lightning) === null || _t === void 0 ? void 0 : _t.hide)) { v2Config.hidden['WH57'] = true; } if (truthy((_v = (_u = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _u === void 0 ? void 0 : _u.uv) === null || _v === void 0 ? void 0 : _v.hide)) { v2Config.hidden.uvIndex = true; } if (truthy((_x = (_w = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _w === void 0 ? void 0 : _w.solarradiation) === null || _x === void 0 ? void 0 : _x.hide)) { v2Config.hidden.solarRadiation = true; } const rainHide = (_z = (_y = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _y === void 0 ? void 0 : _y.rain) === null || _z === void 0 ? void 0 : _z.hide; if (Array.isArray(rainHide)) { if (rainHide.includes('Rate')) { v2Config.hidden.rainRate = true; } if (rainHide.includes('Event')) { v2Config.hidden.rainEventTotal = true; } if (rainHide.includes('Hourly')) { v2Config.hidden.rainHourlyTotal = true; } if (rainHide.includes('Daily')) { v2Config.hidden.rainDailyTotal = true; } if (rainHide.includes('Weekly')) { v2Config.hidden.rainWeeklyTotal = true; } if (rainHide.includes('Monthly')) { v2Config.hidden.rainMonthlyTotal = true; } if (rainHide.includes('Yearly')) { v2Config.hidden.rainYearlyTotal = true; } } const windHide = (_1 = (_0 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _0 === void 0 ? void 0 : _0.wind) === null || _1 === void 0 ? void 0 : _1.hide; if (Array.isArray(windHide)) { if (windHide.includes('Direction')) { v2Config.hidden.windDirection = true; } if (windHide.includes('Speed')) { v2Config.hidden.windSpeed = true; } if (windHide.includes('Gust')) { v2Config.hidden.windGustSpeed = true; } if (windHide.includes('MaxDailyGust')) { v2Config.hidden.windMaxDailySpeed = true; } } // thresholds if ((_3 = (_2 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _2 === void 0 ? void 0 : _2.uv) === null || _3 === void 0 ? void 0 : _3.threshold) { v2Config.thresholds.uvIndex = (_5 = (_4 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _4 === void 0 ? void 0 : _4.uv) === null || _5 === void 0 ? void 0 : _5.threshold; } const windUnits = v2Config.units.wind; if ((_7 = (_6 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _6 === void 0 ? void 0 : _6.wind) === null || _7 === void 0 ? void 0 : _7.speedThreshold) { const threshold = boundRange((_9 = (_8 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _8 === void 0 ? void 0 : _8.wind) === null || _9 === void 0 ? void 0 : _9.speedThreshold, 0, 11); v2Config.thresholds.windSpeed = kBeaufortScale[threshold][windUnits]; } if ((_11 = (_10 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _10 === void 0 ? void 0 : _10.wind) === null || _11 === void 0 ? void 0 : _11.gustThreshold) { const threshold = boundRange((_13 = (_12 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _12 === void 0 ? void 0 : _12.wind) === null || _13 === void 0 ? void 0 : _13.gustThreshold, 0, 11); v2Config.thresholds.windGustSpeed = kBeaufortScale[threshold][windUnits]; } if ((_15 = (_14 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _14 === void 0 ? void 0 : _14.wind) === null || _15 === void 0 ? void 0 : _15.maxDailyGustThreshold) { const threshold = boundRange((_17 = (_16 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _16 === void 0 ? void 0 : _16.wind) === null || _17 === void 0 ? void 0 : _17.maxDailyGustThreshold, 0, 11); v2Config.thresholds.windMaxDailySpeed = kBeaufortScale[threshold][windUnits]; } const rainUnits = v2Config.units.rain; if ((_19 = (_18 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _18 === void 0 ? void 0 : _18.rain) === null || _19 === void 0 ? void 0 : _19.rateThreshold) { v2Config.thresholds.rainRate = rainUnits === 'mm' ? (_21 = (_20 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _20 === void 0 ? void 0 : _20.rain) === null || _21 === void 0 ? void 0 : _21.rateThreshold : parseFloat((((_23 = (_22 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _22 === void 0 ? void 0 : _22.rain) === null || _23 === void 0 ? void 0 : _23.rateThreshold) / 25.4).toFixed(3)); } if ((_25 = (_24 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _24 === void 0 ? void 0 : _24.rain) === null || _25 === void 0 ? void 0 : _25.eventThreshold) { v2Config.thresholds.rainEventTotal = rainUnits === 'mm' ? (_27 = (_26 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _26 === void 0 ? void 0 : _26.rain) === null || _27 === void 0 ? void 0 : _27.eventThreshold : parseFloat((((_29 = (_28 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _28 === void 0 ? void 0 : _28.rain) === null || _29 === void 0 ? void 0 : _29.eventThreshold) / 25.4).toFixed(3)); } if ((_31 = (_30 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _30 === void 0 ? void 0 : _30.rain) === null || _31 === void 0 ? void 0 : _31.hourlyThreshold) { v2Config.thresholds.rainHourlyTotal = rainUnits === 'mm' ? (_33 = (_32 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _32 === void 0 ? void 0 : _32.rain) === null || _33 === void 0 ? void 0 : _33.hourlyThreshold : parseFloat((((_35 = (_34 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _34 === void 0 ? void 0 : _34.rain) === null || _35 === void 0 ? void 0 : _35.hourlyThreshold) / 25.4).toFixed(3)); } if ((_37 = (_36 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _36 === void 0 ? void 0 : _36.rain) === null || _37 === void 0 ? void 0 : _37.dailyThreshold) { v2Config.thresholds.rainDailyTotal = rainUnits === 'mm' ? (_39 = (_38 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _38 === void 0 ? void 0 : _38.rain) === null || _39 === void 0 ? void 0 : _39.dailyThreshold : parseFloat((((_41 = (_40 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _40 === void 0 ? void 0 : _40.rain) === null || _41 === void 0 ? void 0 : _41.dailyThreshold) / 25.4).toFixed(3)); } if ((_43 = (_42 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _42 === void 0 ? void 0 : _42.rain) === null || _43 === void 0 ? void 0 : _43.weeklyThreshold) { v2Config.thresholds.rainWeeklyTotal = rainUnits === 'mm' ? (_45 = (_44 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _44 === void 0 ? void 0 : _44.rain) === null || _45 === void 0 ? void 0 : _45.weeklyThreshold : parseFloat((((_47 = (_46 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _46 === void 0 ? void 0 : _46.rain) === null || _47 === void 0 ? void 0 : _47.weeklyThreshold) / 25.4).toFixed(3)); } if ((_49 = (_48 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _48 === void 0 ? void 0 : _48.rain) === null || _49 === void 0 ? void 0 : _49.monthlyThreshold) { v2Config.thresholds.rainMonthlyTotal = rainUnits === 'mm' ? (_51 = (_50 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _50 === void 0 ? void 0 : _50.rain) === null || _51 === void 0 ? void 0 : _51.monthlyThreshold : parseFloat((((_53 = (_52 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _52 === void 0 ? void 0 : _52.rain) === null || _53 === void 0 ? void 0 : _53.monthlyThreshold) / 25.4).toFixed(3)); } if ((_55 = (_54 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _54 === void 0 ? void 0 : _54.rain) === null || _55 === void 0 ? void 0 : _55.yearlyThreshold) { v2Config.thresholds.rainYearlyTotal = rainUnits === 'mm' ? (_57 = (_56 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _56 === void 0 ? void 0 : _56.rain) === null || _57 === void 0 ? void 0 : _57.yearlyThreshold : parseFloat((((_59 = (_58 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _58 === void 0 ? void 0 : _58.rain) === null || _59 === void 0 ? void 0 : _59.yearlyThreshold) / 25.4).toFixed(3)); } // name overrides for (let channel = 1; channel <= 8; channel++) { if ((_60 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.th) === null || _60 === void 0 ? void 0 : _60[`name${channel}`]) { v2Config.nameOverrides.push({ 'key': `WN31CH${channel}:temperature`, 'value': (_61 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.th) === null || _61 === void 0 ? void 0 : _61[`name${channel}`] }); v2Config.nameOverrides.push({ 'key': `WN31CH${channel}:humidity`, 'value': (_62 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.th) === null || _62 === void 0 ? void 0 : _62[`name${channel}`] }); } } for (let channel = 1; channel <= 8; channel++) { if ((_63 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.tf) === null || _63 === void 0 ? void 0 : _63[`name${channel}`]) { v2Config.nameOverrides.push({ 'key': `WN34CH${channel}:temperature`, 'value': (_64 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.tf) === null || _64 === void 0 ? void 0 : _64[`name${channel}`] }); } } for (let channel = 1; channel <= 4; channel++) { if ((_65 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.pm25) === null || _65 === void 0 ? void 0 : _65[`name${channel}`]) { v2Config.nameOverrides.push({ 'key': `WH41CH${channel}:airQualityPM25`, 'value': (_66 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.pm25) === null || _66 === void 0 ? void 0 : _66[`name${channel}`] }); v2Config.nameOverrides.push({ 'key': `WH41CH${channel}:airQualityPM25Avg`, 'value': (_67 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.pm25) === null || _67 === void 0 ? void 0 : _67[`name${channel}`] }); } } for (let channel = 1; channel <= 8; channel++) { if ((_68 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.soil) === null || _68 === void 0 ? void 0 : _68[`name${channel}`]) { v2Config.nameOverrides.push({ 'key': `WH51CH${channel}:soilMoisture`, 'value': (_69 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.soil) === null || _69 === void 0 ? void 0 : _69[`name${channel}`] }); } } for (let channel = 1; channel <= 4; channel++) { if ((_70 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.leak) === null || _70 === void 0 ? void 0 : _70[`name${channel}`]) { v2Config.nameOverrides.push({ 'key': `WH55CH${channel}:waterLeak`, 'value': (_71 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.leak) === null || _71 === void 0 ? void 0 : _71[`name${channel}`] }); } } // advanced if ((_73 = (_72 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _72 === void 0 ? void 0 : _72.solarradiation) === null || _73 === void 0 ? void 0 : _73.luxFactor) { v2Config.additional.luxFactor = ((_75 = (_74 = v1Config === null || v1Config === void 0 ? void 0 : v1Config.ws) === null || _74 === void 0 ? void 0 : _74.solarradiation) === null || _75 === void 0 ? void 0 : _75.luxFactor) || 126.7; } v2Config.additional.staticNames = 'false'; v2Config.additional.validateMac = 'true'; v2Config.additional.acceptAnyPath = 'false'; v2Config.additional.validateTimestamp = 'true'; v2Config.additional.removeStaleDevices = 'true'; // ensure nameOverrides is array so v1 v2 merge concats overrides if (!Array.isArray(v1Config === null || v1Config === void 0 ? void 0 : v1Config.nameOverrides)) { v1Config.nameOverrides = []; } // v1config may be partially or fully migrated to v2 exports.v1ConfigKeys.forEach(v => delete v1Config[v]); // remove all migrated keys from v1 let mergedConfig = merge(v2Config, v1Config); // merge, v1 wins conflicts mergedConfig = Object.fromEntries(exports.v2ConfigKeys.map(key => [key, mergedConfig[key]])); // retain only valid v2 keys return mergedConfig; } //# sourceMappingURL=Utils.js.map