Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

iobroker.accuweather

Package Overview
Dependencies
Maintainers
0
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

iobroker.accuweather - npm Package Compare versions

Comparing version 1.4.0 to 1.5.0

admin/i18n/de/translations.json

99

admin/words.js
/*global systemDictionary:true */
"use strict";
/*
+===================== DO NOT MODIFY ======================+
| This file was generated by translate-adapter, please use |
| `translate-adapter adminLanguages2words` to update it. |
+===================== DO NOT MODIFY ======================+
*/
'use strict';
systemDictionary = {
"accuweather adapter settings": {
"en": "Adapter settings for accuweather",
"de": "Adaptereinstellungen für accuweather",
"ru": "Настройки адаптера для accuweather",
"pt": "Configurações do adaptador para accuweather",
"nl": "Adapterinstellingen voor accuweather",
"fr": "Paramètres d'adaptateur pour accuweather",
"it": "Impostazioni dell'adattatore per accuweather",
"es": "Ajustes del adaptador para accuweather",
"pl": "Ustawienia adaptera dla accuweather",
"zh-cn": "accuweather的适配器设置"
},
"apiKey": {
"en": "API Key",
"de": "API-Schlüssel",
"ru": "Ключ API",
"pt": "Chave API",
"nl": "API sleutel",
"fr": "clé API",
"it": "Chiave API",
"es": "Clave API",
"pl": "Klucz API",
"zh-cn": "API密钥"
},
"loKey": {
"en": "Location Key",
"de": "Standortschlüssel",
"ru": "Ключ местоположения",
"pt": "Chave de localização",
"nl": "Locatiesleutel",
"fr": "Clé de localisation",
"it": "Chiave di posizione",
"es": "Clave de ubicación",
"pl": "Klucz lokalizacji",
"zh-cn": "位置键"
},
"language": {
"en": "Language",
"de": "Sprache",
"ru": "Язык",
"pt": "Língua",
"nl": "Taal",
"fr": "La langue",
"it": "linguaggio",
"es": "Idioma",
"pl": "Język",
"zh-cn": "语言"
},
"api_help": {
"en": "To get API Key, register on https://developer.accuweather.com/ and create application in \"My Apps\" menu",
"de": "Um einen API-Schlüssel zu erhalten, registrieren Sie sich unter https://developer.accuweather.com/ und erstellen Sie eine Anwendung im Menü \"Meine Apps\"",
"ru": "Чтобы получить API Key, зарегистрируйтесь на https://developer.accuweather.com/ и создайте приложение в меню «Мои приложения»",
"pt": "Para obter a chave da API, registre-se em https://developer.accuweather.com/ e crie um aplicativo no menu \"Meus aplicativos\"",
"nl": "Registreer de API Key op https://developer.accuweather.com/ en maak een applicatie in het menu \"Mijn apps\"",
"fr": "Pour obtenir la clé API, inscrivez-vous sur https://developer.accuweather.com/ et créez une application dans le menu \"Mes applications\".",
"it": "Per ottenere la chiave API, registrati su https://developer.accuweather.com/ e crea un'applicazione nel menu \"Le mie app\"",
"es": "Para obtener la clave API, regístrese en https://developer.accuweather.com/ y cree una aplicación en el menú \"Mis aplicaciones\"",
"pl": "Aby uzyskać klucz API, zarejestruj się na https://developer.accuweather.com/ i utwórz aplikację w menu „Moje aplikacje”",
"zh-cn": "要获取API密钥,请在https://developer.accuweather.com/上注册,然后在“我的应用程序”菜单中创建应用程序"
},
"REGISTER": {
"en": "REGISTER",
"de": "REGISTRIEREN",
"ru": "ЗАРЕГИСТРИРОВАТЬСЯ",
"pt": "REGISTO",
"nl": "REGISTREREN",
"fr": "REGISTRE",
"it": "REGISTRARE",
"es": "REGISTRO",
"pl": "ZAREJESTROWAĆ",
"zh-cn": "寄存器"
},
"lo_help": {
"en": "In order to get location key, go to https://www.accuweather.com/ and enter your city name, or try to enter your coordinates (latitude, longitude). Your location key wil be the number at the end of URL.",
"de": "Um den Standortschlüssel zu erhalten, gehen Sie zu https://www.accuweather.com/ und geben Sie Ihren Städtenamen ein oder versuchen Sie, Ihre Koordinaten (Breitengrad, Längengrad) einzugeben. Ihr Standortschlüssel ist die Nummer am Ende der URL.",
"ru": "Чтобы получить ключ местоположения, перейдите по адресу https://www.accuweather.com/ и введите название своего города или попробуйте ввести свои координаты (широта, долгота). Ваш ключ местоположения будет номером в конце URL.",
"pt": "Para obter a chave de localização, vá para https://www.accuweather.com/ e insira o nome da sua cidade ou tente inserir suas coordenadas (latitude, longitude). A sua chave de localização será o número no final do URL.",
"nl": "Om de locatiesleutel te krijgen, ga naar https://www.accuweather.com/ en voer je plaatsnaam in, of probeer je coördinaten in te voeren (lengte- en breedtegraad). Uw locatiesleutel is het nummer aan het einde van de URL.",
"fr": "Pour obtenir la clé de localisation, accédez à la page https://www.accuweather.com/ et entrez le nom de votre ville ou essayez d'entrer vos coordonnées (latitude, longitude). Votre clé de localisation sera le numéro à la fin de l'URL.",
"it": "Per ottenere la chiave di posizione, vai su https://www.accuweather.com/ e inserisci il nome della tua città, oppure prova a inserire le tue coordinate (latitudine, longitudine). La chiave di posizione sarà il numero alla fine dell'URL.",
"es": "Para obtener la clave de ubicación, vaya a https://www.accuweather.com/ e ingrese el nombre de su ciudad, o intente ingresar sus coordenadas (latitud, longitud). Su clave de ubicación será el número al final de la URL.",
"pl": "Aby uzyskać klucz lokalizacji, przejdź na stronę https://www.accuweather.com/ i wprowadź nazwę swojego miasta lub spróbuj wpisać współrzędne (szerokość, długość). Twój klucz lokalizacji będzie liczbą na końcu adresu URL.",
"zh-cn": "要获取位置密钥,请访问https://www.accuweather.com/并输入您的城市名称,或尝试输入您的坐标(纬度,经度)。您的位置键将是URL末尾的数字。"
}
"REGISTER": { "en": "REGISTER", "de": "REGISTRIEREN", "ru": "ЗАРЕГИСТРИРОВАТЬСЯ", "pt": "REGISTO", "nl": "REGISTREREN", "fr": "REGISTRE", "it": "REGISTRARE", "es": "REGISTRO", "pl": "ZAREJESTROWAĆ", "uk": "ЗАРЕЄСТРУВАТИСЯ", "zh-cn": "寄存器"},
"accuweather adapter settings": { "en": "Adapter settings for accuweather", "de": "Adaptereinstellungen für accuweather", "ru": "Настройки адаптера для accuweather", "pt": "Configurações do adaptador para accuweather", "nl": "Adapterinstellingen voor accuweather", "fr": "Paramètres d'adaptateur pour accuweather", "it": "Impostazioni dell'adattatore per accuweather", "es": "Ajustes del adaptador para accuweather", "pl": "Ustawienia adaptera dla accuweather", "uk": "Налаштування адаптера для accuweather", "zh-cn": "accuweather的适配器设置"},
"apiKey": { "en": "API Key", "de": "API-Schlüssel", "ru": "Ключ API", "pt": "Chave API", "nl": "API sleutel", "fr": "clé API", "it": "Chiave API", "es": "Clave API", "pl": "Klucz API", "uk": "Ключ API", "zh-cn": "API密钥"},
"api_help": { "en": "To get API Key, register on https://developer.accuweather.com/ and create application in \"My Apps\" menu", "de": "Um einen API-Schlüssel zu erhalten, registrieren Sie sich unter https://developer.accuweather.com/ und erstellen Sie eine Anwendung im Menü \"Meine Apps\"", "ru": "Чтобы получить API Key, зарегистрируйтесь на https://developer.accuweather.com/ и создайте приложение в меню «Мои приложения»", "pt": "Para obter a chave da API, registre-se em https://developer.accuweather.com/ e crie um aplicativo no menu \"Meus aplicativos\"", "nl": "Registreer de API Key op https://developer.accuweather.com/ en maak een applicatie in het menu \"Mijn apps\"", "fr": "Pour obtenir la clé API, inscrivez-vous sur https://developer.accuweather.com/ et créez une application dans le menu \"Mes applications\".", "it": "Per ottenere la chiave API, registrati su https://developer.accuweather.com/ e crea un'applicazione nel menu \"Le mie app\"", "es": "Para obtener la clave API, regístrese en https://developer.accuweather.com/ y cree una aplicación en el menú \"Mis aplicaciones\"", "pl": "Aby uzyskać klucz API, zarejestruj się na https://developer.accuweather.com/ i utwórz aplikację w menu „Moje aplikacje”", "uk": "Щоб отримати ключ API, зареєструйтеся на сайті https://developer.accuweather.com/ і створіть програму в меню «Мої програми».", "zh-cn": "要获取API密钥,请在https://developer.accuweather.com/上注册,然后在“我的应用程序”菜单中创建应用程序"},
"language": { "en": "Language", "de": "Sprache", "ru": "Язык", "pt": "Língua", "nl": "Taal", "fr": "La langue", "it": "linguaggio", "es": "Idioma", "pl": "Język", "uk": "Мова", "zh-cn": "语言"},
"loKey": { "en": "Location Key", "de": "Standortschlüssel", "ru": "Ключ местоположения", "pt": "Chave de localização", "nl": "Locatiesleutel", "fr": "Clé de localisation", "it": "Chiave di posizione", "es": "Clave de ubicación", "pl": "Klucz lokalizacji", "uk": "Ключ розташування", "zh-cn": "位置键"},
"lo_help": { "en": "In order to get location key, go to https://www.accuweather.com/ and enter your city name, or try to enter your coordinates (latitude, longitude). Your location key wil be the number at the end of URL.", "de": "Um den Standortschlüssel zu erhalten, gehen Sie zu https://www.accuweather.com/ und geben Sie Ihren Städtenamen ein oder versuchen Sie, Ihre Koordinaten (Breitengrad, Längengrad) einzugeben. Ihr Standortschlüssel ist die Nummer am Ende der URL.", "ru": "Чтобы получить ключ местоположения, перейдите по адресу https://www.accuweather.com/ и введите название своего города или попробуйте ввести свои координаты (широта, долгота). Ваш ключ местоположения будет номером в конце URL.", "pt": "Para obter a chave de localização, vá para https://www.accuweather.com/ e insira o nome da sua cidade ou tente inserir suas coordenadas (latitude, longitude). A sua chave de localização será o número no final do URL.", "nl": "Om de locatiesleutel te krijgen, ga naar https://www.accuweather.com/ en voer je plaatsnaam in, of probeer je coördinaten in te voeren (lengte- en breedtegraad). Uw locatiesleutel is het nummer aan het einde van de URL.", "fr": "Pour obtenir la clé de localisation, accédez à la page https://www.accuweather.com/ et entrez le nom de votre ville ou essayez d'entrer vos coordonnées (latitude, longitude). Votre clé de localisation sera le numéro à la fin de l'URL.", "it": "Per ottenere la chiave di posizione, vai su https://www.accuweather.com/ e inserisci il nome della tua città, oppure prova a inserire le tue coordinate (latitudine, longitudine). La chiave di posizione sarà il numero alla fine dell'URL.", "es": "Para obtener la clave de ubicación, vaya a https://www.accuweather.com/ e ingrese el nombre de su ciudad, o intente ingresar sus coordenadas (latitud, longitud). Su clave de ubicación será el número al final de la URL.", "pl": "Aby uzyskać klucz lokalizacji, przejdź na stronę https://www.accuweather.com/ i wprowadź nazwę swojego miasta lub spróbuj wpisać współrzędne (szerokość, długość). Twój klucz lokalizacji będzie liczbą na końcu adresu URL.", "uk": "Щоб отримати ключ розташування, перейдіть на сторінку https://www.accuweather.com/ і введіть назву свого міста або спробуйте ввести свої координати (широта, довгота). Ваш ключ місцезнаходження буде числом у кінці URL-адреси.", "zh-cn": "要获取位置密钥,请访问https://www.accuweather.com/并输入您的城市名称,或尝试输入您的坐标(纬度,经度)。您的位置键将是URL末尾的数字。"},
};
{
"common": {
"name": "accuweather",
"version": "1.4.0",
"version": "1.5.0",
"news": {
"1.5.0": {
"en": "limit updates to once an hour, this fixes part of issue #273.\nAdapter requires js-controller >= 5 and admin >= 6 now\nNode 22 support has been added to testing\nDependencies have been updated",
"de": "Updates auf einmal pro Stunde limitiert, dies repariert einen Teil der Fehlermeldung #273.\nAdapter benötigt js-controller >= 5 und admin >= 6 jetzt\nNode 22 Unterstützung wurde zur Prüfung hinzugefügt\nAbhängigkeiten wurden aktualisiert",
"ru": "ограничить обновления раз в час, это исправляет часть выпуска #273.\nАдаптер требует js-контроллер >= 5 и admin >= 6 сейчас\nПоддержка Node 22 была добавлена к тестированию\nЗависимость обновлена",
"pt": "limite atualizações para uma vez por hora, isso corrige parte do problema #273.\nAdapter requer js-controller >= 5 e admin >= 6 agora\nNode 22 suporte foi adicionado ao teste\nAs dependências foram atualizadas",
"nl": "limiet updates tot eenmaal per uur, dit lost deel van probleem #273.\nJs-controller vereist 5 en admin 6 nu\nNode 22 ondersteuning is toegevoegd aan het testen\nAfhankelijkheden zijn bijgewerkt",
"fr": "limiter les mises à jour à une fois par heure, cela corrige une partie du numéro 273.\nAdaptateur nécessite js-controller >= 5 et administrateur >= 6 maintenant\nLe support Node 22 a été ajouté au test\nLes dépendances ont été actualisées",
"it": "limitare gli aggiornamenti di una volta all'ora, questo risolve parte del problema #273.\nAdattatore richiede js-controller >= 5 e admin >= 6 ora\nIl supporto Node 22 è stato aggiunto ai test\nLe dipendenze sono state aggiornate",
"es": "limitar las actualizaciones una vez por hora, esto fija parte del número #273.\nAdaptador requiere js-controller 5 y admin= 6 ahora\nSe ha añadido apoyo Nodo 22 a las pruebas\nSe han actualizado las dependencias",
"pl": "limit aktualizacje raz na godzinę, to naprawia część wydania # 273.\nAdapter wymaga sterownika js- > = 5 i admin > = 6 teraz\nDo testowania dodano wsparcie węzła 22\nZaktualizowano zależności",
"uk": "обмежити оновлення один раз на годину, це фіксує частину випуску #273.\nАдаптер вимагає js-controller >= 5 і admin >= 6 тепер\nДодано підтримку Node 22 для тестування\nЗалежність було оновлено",
"zh-cn": "将更新限制在每小时一次,这可以修复第273期的部分内容.\n适配器需要js控制器 QQ 第5条 行政 现在6个\n测试中增加了22号节点支持\n依赖关系已更新"
},
"1.4.0": {

@@ -55,3 +68,4 @@ "en": "Adapter requires node.js 18 and js-controller >= 5 now\nDependencies have been updated",

"pl": "aktualizacja zależności",
"zh-cn": "依赖更新"
"zh-cn": "依赖更新",
"uk": "оновлення залежностей"
},

@@ -68,3 +82,4 @@ "1.2.3": {

"pl": "Dodano parametr HoursOfSun do prognozy dziennej",
"zh-cn": "每日预测中添加了 hoursOfSun 参数"
"zh-cn": "每日预测中添加了 hoursOfSun 参数",
"uk": "До щоденного прогнозу додано параметр HoursOfSun"
},

@@ -81,15 +96,4 @@ "1.2.1": {

"pl": "Zaktualizowane logo",
"zh-cn": "更新标志"
},
"1.2.0": {
"en": "adjust roles to properly detect weather forecast in Summary folder. (Summary objects need to be deleted and adapter restarted after that)",
"de": "Passen Sie die Rollen an, um die Wettervorhersage im Ordner \"Zusammenfassung\" richtig zu erkennen. (Zusammenfassungsobjekte müssen danach gelöscht und der Adapter neu gestartet werden)",
"ru": "Изменены роли для правильного определения устройства Погода. (Объекты Summary необходимо удалить и после этого перезапустить адаптер)",
"pt": "ajuste as funções para detectar adequadamente a previsão do tempo na pasta Resumo. (Objetos de resumo precisam ser excluídos e o adaptador reiniciado depois disso)",
"nl": "pas rollen aan om de weersvoorspelling correct te detecteren in de map Samenvatting. (Samenvattingsobjecten moeten daarna worden verwijderd en de adapter moet opnieuw worden opgestart)",
"fr": "ajustez les rôles pour détecter correctement les prévisions météorologiques dans le dossier Résumé. (Les objets de résumé doivent être supprimés et l'adaptateur redémarré après cela)",
"it": "regolare i ruoli per rilevare correttamente le previsioni del tempo nella cartella Riepilogo. (Gli oggetti di riepilogo devono essere eliminati e l'adattatore riavviato successivamente)",
"es": "ajuste los roles para detectar correctamente el pronóstico del tiempo en la carpeta Resumen. (Los objetos de resumen deben eliminarse y el adaptador debe reiniciarse después de eso)",
"pl": "dostosuj role, aby poprawnie wykryć prognozę pogody w folderze Podsumowanie. (Obiekty podsumowania należy usunąć, a następnie ponownie uruchomić adapter)",
"zh-cn": "调整角色以正确检测摘要文件夹中的天气预报。 (之后需要删除摘要对象并重新启动适配器)"
"zh-cn": "更新标志",
"uk": "Оновлений логотип"
}

@@ -107,3 +111,4 @@ },

"pl": "AccuWeather",
"zh-cn": "机构AccuWeather"
"zh-cn": "机构AccuWeather",
"uk": "AccuWeather"
},

@@ -120,3 +125,4 @@ "desc": {

"pl": "Prognoza pogody za pomocą interfejsu API AccuWeather",
"zh-cn": "使用AccuWeather API的天气预报"
"zh-cn": "使用AccuWeather API的天气预报",
"uk": "Прогноз погоди за допомогою AccuWeather API"
},

@@ -153,3 +159,3 @@ "authors": [

{
"js-controller": ">=5.0.0"
"js-controller": ">=5.0.19"
}

@@ -159,3 +165,3 @@ ],

{
"admin": ">=5.1.13"
"admin": ">=6.13.16"
}

@@ -162,0 +168,0 @@ ]

@@ -1,85 +0,85 @@

"use strict";
const axios = require("axios");
'use strict';
const axios = require('axios');
//const moment = require("moment");
const queryString = require("qs");
const queryString = require('qs');
class Accuapi {
constructor(apiKey) {
this.apiKey = apiKey;
this.lokey = 335315;
this.query = {};
//this.adapter = adapter;
}
constructor(apiKey) {
this.apiKey = apiKey;
this.lokey = 335315;
this.query = {};
//this.adapter = adapter;
}
localkey(lkey) {
// Unique ID that can be used to search for a specific location.
localkey(lkey) {
// Unique ID that can be used to search for a specific location.
!lkey ? null : this.lokey = lkey;
return this;
}
!lkey ? null : this.lokey = lkey;
return this;
}
timeInt(val) {
// Unique ID that can be used to search for a specific location.
timeInt(val) {
// Unique ID that can be used to search for a specific location.
!val ? this.time = "hourly/1hour" : this.time = val;
return this;
}
!val ? this.time = 'hourly/1hour' : this.time = val;
return this;
}
language(lan) {
// http://apidev.accuweather.com/developers/languages
// String indicating the language in which to return the resource.
// Default value set to en-us.
language(lan) {
// http://apidev.accuweather.com/developers/languages
// String indicating the language in which to return the resource.
// Default value set to en-us.
!lan ? null : this.query.language = lan;
return this;
}
!lan ? null : this.query.language = lan;
return this;
}
details(bool) {
// Boolean value (true or false) specifies whether or not to include the full object.
//Default value set to false.
//(For location searches, details = true will return AccuWeather related details).
details(bool) {
// Boolean value (true or false) specifies whether or not to include the full object.
//Default value set to false.
//(For location searches, details = true will return AccuWeather related details).
!bool ? null : this.query.details = bool;
return this;
}
!bool ? null : this.query.details = bool;
return this;
}
metric(bool) {
// Boolean value (true or false) that specifies to return the data in either metric (=true) or imperial units.
metric(bool) {
// Boolean value (true or false) that specifies to return the data in either metric (=true) or imperial units.
!bool ? null : this.query.metric = bool;
return this;
}
!bool ? null : this.query.metric = bool;
return this;
}
generateReqUrl(current) {
if (current) {
this.url = `http://dataservice.accuweather.com/currentconditions/v1/${this.lokey}?apikey=${this.apiKey}`;
}
else {
this.url = `http://dataservice.accuweather.com/forecasts/v1/${this.time}/${this.lokey}?apikey=${this.apiKey}`;
}
this.query ? this.url += `&${queryString.stringify(this.query)}` : this.url;
}
generateReqUrl(current) {
if (current) {
this.url = `http://dataservice.accuweather.com/currentconditions/v1/${this.lokey}?apikey=${this.apiKey}`;
}
else {
this.url = `http://dataservice.accuweather.com/forecasts/v1/${this.time}/${this.lokey}?apikey=${this.apiKey}`;
}
this.query ? this.url += `&${queryString.stringify(this.query)}` : this.url;
}
get() {
this.generateReqUrl();
return axios(this.url)
.then(response => response.data)
.catch(error => {
throw new Error(`Forecast cannot be retrieved. ERROR: ${error.response && JSON.stringify(error.response.data) || error.toString()}`);
});
}
get() {
this.generateReqUrl();
return axios(this.url)
.then(response => response.data)
.catch(error => {
throw new Error(`Forecast cannot be retrieved. ERROR: ${error.response && JSON.stringify(error.response.data) || error.toString()}`);
});
}
getCurrent() {
//
//const body = require("./test-data/currentCond.json");
//
this.generateReqUrl(true);
return axios(this.url)
.then(response => response.data)
.catch(error => {
throw new Error(`Forecast cannot be retrieved. ERROR: ${error.response && JSON.stringify(error.response.data) || error.toString()}`);
});
}
getCurrent() {
//
//const body = require("./test-data/currentCond.json");
//
this.generateReqUrl(true);
return axios(this.url)
.then(response => response.data)
.catch(error => {
throw new Error(`Forecast cannot be retrieved. ERROR: ${error.response && JSON.stringify(error.response.data) || error.toString()}`);
});
}
}
module.exports = Accuapi;

@@ -1,42 +0,42 @@

"use strict";
'use strict';
async function createSummaryObjects(adapter) {
const obj = require("./summaryObject.json");
await adapter.setObjectNotExistsAsync("Summary", {
type: "channel",
common: {
name: "Weather Summary",
},
native: {},
});
const _obj = Object.assign({}, obj);
const obj = require('./summaryObject.json');
await adapter.setObjectNotExistsAsync('Summary', {
type: 'channel',
common: {
name: 'Weather Summary',
},
native: {},
});
const _obj = Object.assign({}, obj);
for (const key in _obj) {
adapter.setObjectNotExists(key, _obj[key]);
}
for (const key in _obj) {
adapter.setObjectNotExists(key, _obj[key]);
}
}
async function createNextHourForecatObjects(hour, adapter) {
const obj = require("./nextHourObject.json");
await adapter.setObjectNotExistsAsync(`Hourly.h${hour}`, {
type: "channel",
common: {
name: `Hour ${hour} Forecast`,
},
native: {},
});
const _obj = Object.assign({}, obj);
const obj = require('./nextHourObject.json');
await adapter.setObjectNotExistsAsync(`Hourly.h${hour}`, {
type: 'channel',
common: {
name: `Hour ${hour} Forecast`,
},
native: {},
});
const _obj = Object.assign({}, obj);
for (const key in _obj) {
const measure = {};
const nkey = key.replace("nextHour", `Hourly.h${hour}`);
const role = _obj[key].common.role;
measure[nkey] = Object.assign({}, _obj[key]);
measure[nkey].common = Object.assign({}, _obj[key].common);
if (measure[nkey].common.role) {
measure[nkey].common.role = `${role}.forecast.${hour}`;
}
adapter.log.debug(`key: ${nkey}, role:${JSON.stringify(measure[nkey].common.role)}, base: ${role}`);
adapter.setObjectNotExists(nkey, measure[nkey]);
}
for (const key in _obj) {
const measure = {};
const nkey = key.replace('nextHour', `Hourly.h${hour}`);
const role = _obj[key].common.role;
measure[nkey] = Object.assign({}, _obj[key]);
measure[nkey].common = Object.assign({}, _obj[key].common);
if (measure[nkey].common.role) {
measure[nkey].common.role = `${role}.forecast.${hour}`;
}
adapter.log.debug(`key: ${nkey}, role:${JSON.stringify(measure[nkey].common.role)}, base: ${role}`);
adapter.setObjectNotExists(nkey, measure[nkey]);
}
}

@@ -46,14 +46,14 @@

async function createCurrentConditionObjects(adapter) {
const obj = require("./currentCondObject.json");
await adapter.setObjectNotExistsAsync("Current", {
type: "channel",
common: {
name: "Current Conditions",
},
native: {},
});
const obj = require('./currentCondObject.json');
await adapter.setObjectNotExistsAsync('Current', {
type: 'channel',
common: {
name: 'Current Conditions',
},
native: {},
});
for (const key in obj) {
adapter.setObjectNotExists(key.replace("nextHour", "Current"), obj[key]);
}
for (const key in obj) {
adapter.setObjectNotExists(key.replace('nextHour', 'Current'), obj[key]);
}
}

@@ -63,44 +63,44 @@

const obj = require("./DailyObject.json");
for (let i = 1; i <= 5; i++) {
await adapter.setObjectNotExistsAsync(`Daily.Day${i}`, {
type: "channel",
common: {
name: `Day ${i} Forecast`
},
native: {},
});
const _obj = Object.assign({}, obj);
const obj = require('./DailyObject.json');
for (let i = 1; i <= 5; i++) {
await adapter.setObjectNotExistsAsync(`Daily.Day${i}`, {
type: 'channel',
common: {
name: `Day ${i} Forecast`
},
native: {},
});
const _obj = Object.assign({}, obj);
for (const key in _obj) {
const measure = {};
let nkey = "";
const role = _obj[key].common.role;
if (!key.indexOf("dayPart.")) {
nkey = key.replace("dayn.", `Day${i}.`);
measure[nkey] = Object.assign({}, _obj[key]);
measure[nkey].common = Object.assign({}, _obj[key].common);
if (measure[nkey].common.role) {
measure[nkey].common.role = `${role}.forecast.${i - 1}`;
}
adapter.setObjectNotExists(nkey, measure[nkey]);
} else {
["Day", "Night"].forEach(dp => {
nkey = key.replace("dayn.", `Day${i}.`).replace("dayPart.", `${dp}.`);
measure[nkey] = Object.assign({}, _obj[key]);
measure[nkey].common = Object.assign({}, _obj[key].common);
if (measure[nkey].common.role) {
measure[nkey].common.role = `${role}.forecast.${i - 1}`;
}
adapter.setObjectNotExists(nkey, measure[nkey]);
});
}
}
}
for (const key in _obj) {
const measure = {};
let nkey = '';
const role = _obj[key].common.role;
if (!key.indexOf('dayPart.')) {
nkey = key.replace('dayn.', `Day${i}.`);
measure[nkey] = Object.assign({}, _obj[key]);
measure[nkey].common = Object.assign({}, _obj[key].common);
if (measure[nkey].common.role) {
measure[nkey].common.role = `${role}.forecast.${i - 1}`;
}
adapter.setObjectNotExists(nkey, measure[nkey]);
} else {
['Day', 'Night'].forEach(dp => {
nkey = key.replace('dayn.', `Day${i}.`).replace('dayPart.', `${dp}.`);
measure[nkey] = Object.assign({}, _obj[key]);
measure[nkey].common = Object.assign({}, _obj[key].common);
if (measure[nkey].common.role) {
measure[nkey].common.role = `${role}.forecast.${i - 1}`;
}
adapter.setObjectNotExists(nkey, measure[nkey]);
});
}
}
}
}
async function createHourlyForecastObjects(adapter) {
for (let hr = 0; hr < 24; hr++) {
await createNextHourForecatObjects(hr, adapter);
}
for (let hr = 0; hr < 24; hr++) {
await createNextHourForecatObjects(hr, adapter);
}
}

@@ -107,0 +107,0 @@

@@ -1,2 +0,2 @@

const axios = require("axios");
const axios = require('axios');

@@ -9,7 +9,7 @@ /**

function isObject(it) {
// This is necessary because:
// typeof null === 'object'
// typeof [] === 'object'
// [] instanceof Object === true
return Object.prototype.toString.call(it) === "[object Object]";
// This is necessary because:
// typeof null === 'object'
// typeof [] === 'object'
// [] instanceof Object === true
return Object.prototype.toString.call(it) === '[object Object]';
}

@@ -23,4 +23,4 @@

function isArray(it) {
if (typeof Array.isArray === "function") return Array.isArray(it);
return Object.prototype.toString.call(it) === "[object Array]";
if (typeof Array.isArray === 'function') return Array.isArray(it);
return Object.prototype.toString.call(it) === '[object Array]';
}

@@ -36,10 +36,10 @@

async function translateText(text, targetLang, yandexApiKey) {
if (targetLang === "en") {
return text;
}
if (yandexApiKey) {
return await translateYandex(text, targetLang, yandexApiKey);
} else {
return await translateGoogle(text, targetLang);
}
if (targetLang === 'en') {
return text;
}
if (yandexApiKey) {
return await translateYandex(text, targetLang, yandexApiKey);
} else {
return await translateGoogle(text, targetLang);
}
}

@@ -55,15 +55,15 @@

async function translateYandex(text, targetLang, apiKey) {
if (targetLang === "zh-cn") {
targetLang = "zh";
}
try {
const url = `https://translate.yandex.net/api/v1.5/tr.json/translate?key=${apiKey}&text=${encodeURIComponent(text)}&lang=en-${targetLang}`;
const response = await axios({url, timeout: 15000});
if (response.data && response.data["text"]) {
return response.data["text"][0];
}
throw new Error("Invalid response for translate request");
} catch (e) {
throw new Error(`Could not translate to "${targetLang}": ${e}`);
}
if (targetLang === 'zh-cn') {
targetLang = 'zh';
}
try {
const url = `https://translate.yandex.net/api/v1.5/tr.json/translate?key=${apiKey}&text=${encodeURIComponent(text)}&lang=en-${targetLang}`;
const response = await axios({url, timeout: 15000});
if (response.data && response.data['text']) {
return response.data['text'][0];
}
throw new Error('Invalid response for translate request');
} catch (e) {
throw new Error(`Could not translate to "${targetLang}": ${e}`);
}
}

@@ -78,19 +78,19 @@

async function translateGoogle(text, targetLang) {
try {
const url = `http://translate.googleapis.com/translate_a/single?client=gtx&sl=en&tl=${targetLang}&dt=t&q=${encodeURIComponent(text)}&ie=UTF-8&oe=UTF-8`;
const response = await axios({url, timeout: 15000});
if (isArray(response.data)) {
// we got a valid response
return response.data[0][0][0];
}
throw new Error("Invalid response for translate request");
} catch (e) {
throw new Error(`Could not translate to "${targetLang}": ${e}`);
}
try {
const url = `http://translate.googleapis.com/translate_a/single?client=gtx&sl=en&tl=${targetLang}&dt=t&q=${encodeURIComponent(text)}&ie=UTF-8&oe=UTF-8`;
const response = await axios({url, timeout: 15000});
if (isArray(response.data)) {
// we got a valid response
return response.data[0][0][0];
}
throw new Error('Invalid response for translate request');
} catch (e) {
throw new Error(`Could not translate to "${targetLang}": ${e}`);
}
}
module.exports = {
isArray,
isObject,
translateText
isArray,
isObject,
translateText
};

@@ -1,2 +0,2 @@

"use strict";
'use strict';

@@ -9,5 +9,5 @@ /*

// you need to create an adapter
const utils = require("@iobroker/adapter-core");
const AccuAPI = require("./lib/accuapi");
const nextHour = require("./lib/nexthour-obj");
const utils = require('@iobroker/adapter-core');
const AccuAPI = require('./lib/accuapi');
const nextHour = require('./lib/nexthour-obj');
let updateInterval = null;

@@ -18,323 +18,323 @@ let timeout1 = null;

class Accuweather extends utils.Adapter {
/**
/**
* @param {Partial<utils.AdapterOptions>} [options={}]
*/
constructor(options = {}) {
super({
...options,
name: "accuweather",
strictObjectChecks: false
});
this.on("ready", this.onReady.bind(this));
this.on("objectChange", this.onObjectChange.bind(this));
this.on("stateChange", this.onStateChange.bind(this));
this.on("unload", this.onUnload.bind(this));
}
constructor(options = {}) {
super({
...options,
name: 'accuweather',
strictObjectChecks: false
});
this.on('ready', this.onReady.bind(this));
this.on('objectChange', this.onObjectChange.bind(this));
this.on('stateChange', this.onStateChange.bind(this));
this.on('unload', this.onUnload.bind(this));
}
getCardinalDirection(angle) {
if (typeof angle === "string") {
angle = parseInt(angle);
}
if (angle <= 0 || angle > 360 || typeof angle === "undefined") {
return "☈";
}
const arrows = { north: "↑N", north_east: "↗NE", east: "→E", south_east: "↘SE", south: "↓S", south_west: "↙SW", west: "←W", north_west: "↖NW" };
const directions = Object.keys(arrows);
const degree = 360 / directions.length;
angle = angle + degree / 4;
for (let i = 0; i < directions.length; i++) {
if (angle >= (i * degree) && angle < (i + 1) * degree) return arrows[directions[i]];
}
return arrows["north"];
}
getCardinalDirection(angle) {
if (typeof angle === 'string') {
angle = parseInt(angle);
}
if (angle <= 0 || angle > 360 || typeof angle === 'undefined') {
return '☈';
}
const arrows = { north: '↑N', north_east: '↗NE', east: '→E', south_east: '↘SE', south: '↓S', south_west: '↙SW', west: '←W', north_west: '↖NW' };
const directions = Object.keys(arrows);
const degree = 360 / directions.length;
angle = angle + degree / 4;
for (let i = 0; i < directions.length; i++) {
if (angle >= (i * degree) && angle < (i + 1) * degree) return arrows[directions[i]];
}
return arrows['north'];
}
async setDailyStates(obj) {
const days = obj.DailyForecasts;
try {
for (let day = 1; day <= 5; day++) {
const json = days[day - 1];
for (const key in json) {
let dt = null;
switch (key) {
case "Date":
dt = new Date(json[key]);
await this.setStateAsync(`Daily.Day${day}.${key}`, { val: json[key], ack: true });
await this.setStateAsync(`Summary.DateTime_d${day}`, { val: json[key], ack: true });
await this.setStateAsync(`Summary.DayOfWeek_d${day}`, { val: dt.toLocaleString(this.config.language, {weekday: "short"}), ack: true });
break;
case "Sun":
await this.setStateAsync(`Daily.Day${day}.Sunrise`, { val: json[key]["Rise"], ack: true });
await this.setStateAsync(`Daily.Day${day}.Sunset`, { val: json[key]["Set"], ack: true });
if (day === 1) {
await this.setStateAsync("Summary.Sunrise", { val: json[key]["Rise"], ack: true });
await this.setStateAsync("Summary.Sunset", { val: json[key]["Set"], ack: true });
}
break;
case "HoursOfSun":
await this.setStateAsync(`Daily.Day${day}.HoursOfSun`, { val: json[key], ack: true });
if (day === 1) {
await this.setStateAsync("Summary.HoursOfSun", { val: json[key], ack: true });
}
break;
case "Temperature":
await this.setStateAsync(`Daily.Day${day}.Temperature.Minimum`, { val: json[key]["Minimum"].Value, ack: true });
await this.setStateAsync(`Daily.Day${day}.Temperature.Maximum`, { val: json[key]["Maximum"].Value, ack: true });
await this.setStateAsync(`Summary.TempMin_d${day}`, { val: json[key]["Minimum"].Value, ack: true });
await this.setStateAsync(`Summary.TempMax_d${day}`, { val: json[key]["Maximum"].Value, ack: true });
break;
case "RealFeelTemperature":
await this.setStateAsync(`Daily.Day${day}.RealFeelTemperature.Minimum`, { val: json[key]["Minimum"].Value, ack: true });
await this.setStateAsync(`Daily.Day${day}.RealFeelTemperature.Maximum`, { val: json[key]["Maximum"].Value, ack: true });
break;
case "Day":
case "Night":
{
const json1 = json[key];
for (const key1 in json1) {
if (typeof json1[key1] !== "object") {
await this.setStateAsync(`Daily.Day${day}.${key}.${key1}`, { val: json1[key1], ack: true });
if (key1 === "Icon") {
await this.setStateAsync(`Daily.Day${day}.${key}.IconURL`, { val: `https://developer.accuweather.com/sites/default/files/${String(json1[key1]).padStart(2, "0")}-s.png`, ack: true });
await this.setStateAsync(`Daily.Day${day}.${key}.IconURLS`, { val: `http://vortex.accuweather.com/adc2010/images/slate/icons/${String(json1[key1]).padStart(2, "0")}.svg`, ack: true });
if (key === "Day") {
await this.setStateAsync(`Summary.WeatherIconURL_d${day}`, { val: `http://vortex.accuweather.com/adc2010/images/slate/icons/${String(json1[key1]).padStart(2, "0")}.svg`, ack: true });
await this.setStateAsync(`Summary.WeatherIcon_d${day}`, { val: json1[key1], ack: true });
}
} else if (key === "Day") {
if (key1 === "IconPhrase") {
await this.setStateAsync(`Summary.WeatherText_d${day}`, { val: json1[key1], ack: true });
} else {
await this.setStateAsync(`Summary.${key1}_d${day}`, { val: json1[key1], ack: true });
}
}
} else if (typeof json1[key1] == "object") {
if (json1[key1]["Value"] !== undefined) {
if (["TotalLiquid", "Rain", "Snow", "Ice"].includes(key1)) {
await this.setStateAsync(`Daily.Day${day}.${key}.${key1}Volume`, { val: json1[key1].Value, ack: true });
if (key === "Day" && key1 === "TotalLiquid") {
await this.setStateAsync(`Summary.TotalLiquidVolume_d${day}`, { val: json1[key1].Value, ack: true });
}
} else {
await this.setStateAsync(`Daily.Day${day}.${key}.${key1}`, { val: json1[key1].Value, ack: true });
}
} else if (key1 === "Wind") {
await this.setStateAsync(`Daily.Day${day}.${key}.WindSpeed`, { val: json1[key1].Speed.Value, ack: true });
await this.setStateAsync(`Daily.Day${day}.${key}.WindDirection`, { val: json1[key1].Direction.Degrees, ack: true });
if (key === "Day") {
await this.setStateAsync(`Summary.WindSpeed_d${day}`, { val: json1[key1].Speed.Value, ack: true });
await this.setStateAsync(`Summary.WindDirection_d${day}`, { val: json1[key1].Direction.Degrees, ack: true });
await this.setStateAsync(`Summary.WindDirectionStr_d${day}`, { val: this.getCardinalDirection(json1[key1].Direction.Degrees), ack: true });
}
} else if (key1 === "WindGust") {
await this.setStateAsync(`Daily.Day${day}.${key}.WindGust`, { val: json1[key1].Speed.Value, ack: true });
}
}
}
}
break;
default:
break;
}
}
}
} catch (/** @type any */ err) {
this.log.error(err);
}
}
async setDailyStates(obj) {
const days = obj.DailyForecasts;
try {
for (let day = 1; day <= 5; day++) {
const json = days[day - 1];
for (const key in json) {
let dt = null;
switch (key) {
case 'Date':
dt = new Date(json[key]);
await this.setStateAsync(`Daily.Day${day}.${key}`, { val: json[key], ack: true });
await this.setStateAsync(`Summary.DateTime_d${day}`, { val: json[key], ack: true });
await this.setStateAsync(`Summary.DayOfWeek_d${day}`, { val: dt.toLocaleString(this.config.language, {weekday: 'short'}), ack: true });
break;
case 'Sun':
await this.setStateAsync(`Daily.Day${day}.Sunrise`, { val: json[key]['Rise'], ack: true });
await this.setStateAsync(`Daily.Day${day}.Sunset`, { val: json[key]['Set'], ack: true });
if (day === 1) {
await this.setStateAsync('Summary.Sunrise', { val: json[key]['Rise'], ack: true });
await this.setStateAsync('Summary.Sunset', { val: json[key]['Set'], ack: true });
}
break;
case 'HoursOfSun':
await this.setStateAsync(`Daily.Day${day}.HoursOfSun`, { val: json[key], ack: true });
if (day === 1) {
await this.setStateAsync('Summary.HoursOfSun', { val: json[key], ack: true });
}
break;
case 'Temperature':
await this.setStateAsync(`Daily.Day${day}.Temperature.Minimum`, { val: json[key]['Minimum'].Value, ack: true });
await this.setStateAsync(`Daily.Day${day}.Temperature.Maximum`, { val: json[key]['Maximum'].Value, ack: true });
await this.setStateAsync(`Summary.TempMin_d${day}`, { val: json[key]['Minimum'].Value, ack: true });
await this.setStateAsync(`Summary.TempMax_d${day}`, { val: json[key]['Maximum'].Value, ack: true });
break;
case 'RealFeelTemperature':
await this.setStateAsync(`Daily.Day${day}.RealFeelTemperature.Minimum`, { val: json[key]['Minimum'].Value, ack: true });
await this.setStateAsync(`Daily.Day${day}.RealFeelTemperature.Maximum`, { val: json[key]['Maximum'].Value, ack: true });
break;
case 'Day':
case 'Night':
{
const json1 = json[key];
for (const key1 in json1) {
if (typeof json1[key1] !== 'object') {
await this.setStateAsync(`Daily.Day${day}.${key}.${key1}`, { val: json1[key1], ack: true });
if (key1 === 'Icon') {
await this.setStateAsync(`Daily.Day${day}.${key}.IconURL`, { val: `https://developer.accuweather.com/sites/default/files/${String(json1[key1]).padStart(2, '0')}-s.png`, ack: true });
await this.setStateAsync(`Daily.Day${day}.${key}.IconURLS`, { val: `http://vortex.accuweather.com/adc2010/images/slate/icons/${String(json1[key1]).padStart(2, '0')}.svg`, ack: true });
if (key === 'Day') {
await this.setStateAsync(`Summary.WeatherIconURL_d${day}`, { val: `http://vortex.accuweather.com/adc2010/images/slate/icons/${String(json1[key1]).padStart(2, '0')}.svg`, ack: true });
await this.setStateAsync(`Summary.WeatherIcon_d${day}`, { val: json1[key1], ack: true });
}
} else if (key === 'Day') {
if (key1 === 'IconPhrase') {
await this.setStateAsync(`Summary.WeatherText_d${day}`, { val: json1[key1], ack: true });
} else {
await this.setStateAsync(`Summary.${key1}_d${day}`, { val: json1[key1], ack: true });
}
}
} else if (typeof json1[key1] == 'object') {
if (json1[key1]['Value'] !== undefined) {
if (['TotalLiquid', 'Rain', 'Snow', 'Ice'].includes(key1)) {
await this.setStateAsync(`Daily.Day${day}.${key}.${key1}Volume`, { val: json1[key1].Value, ack: true });
if (key === 'Day' && key1 === 'TotalLiquid') {
await this.setStateAsync(`Summary.TotalLiquidVolume_d${day}`, { val: json1[key1].Value, ack: true });
}
} else {
await this.setStateAsync(`Daily.Day${day}.${key}.${key1}`, { val: json1[key1].Value, ack: true });
}
} else if (key1 === 'Wind') {
await this.setStateAsync(`Daily.Day${day}.${key}.WindSpeed`, { val: json1[key1].Speed.Value, ack: true });
await this.setStateAsync(`Daily.Day${day}.${key}.WindDirection`, { val: json1[key1].Direction.Degrees, ack: true });
if (key === 'Day') {
await this.setStateAsync(`Summary.WindSpeed_d${day}`, { val: json1[key1].Speed.Value, ack: true });
await this.setStateAsync(`Summary.WindDirection_d${day}`, { val: json1[key1].Direction.Degrees, ack: true });
await this.setStateAsync(`Summary.WindDirectionStr_d${day}`, { val: this.getCardinalDirection(json1[key1].Direction.Degrees), ack: true });
}
} else if (key1 === 'WindGust') {
await this.setStateAsync(`Daily.Day${day}.${key}.WindGust`, { val: json1[key1].Speed.Value, ack: true });
}
}
}
}
break;
default:
break;
}
}
}
} catch (/** @type any */ err) {
this.log.error(err);
}
}
async setNextHourStates(obj, item, hour) {
const json = obj[item];
try {
for (const key in json) {
if (typeof json[key] !== "object") {
await this.setStateAsync(`Hourly.h${hour}.${key}`, { val: json[key], ack: true });
if (key === "WeatherIcon") {
await this.setStateAsync(`Hourly.h${hour}.WeatherIconURL`, { val: `https://developer.accuweather.com/sites/default/files/${String(json[key]).padStart(2, "0")}-s.png`, ack: true });
await this.setStateAsync(`Hourly.h${hour}.WeatherIconURLS`, { val: `http://vortex.accuweather.com/adc2010/images/slate/icons/${String(json[key]).padStart(2, "0")}.svg`, ack: true });
}
} else if (typeof json[key] == "object") {
if (json[key]["Value"] !== undefined) {
if (["TotalLiquid", "Rain", "Snow", "Ice"].includes(key)) {
await this.setStateAsync(`Hourly.h${hour}.${key}Volume`, { val: json[key].Value, ack: true });
} else {
await this.setStateAsync(`Hourly.h${hour}.${key}`, { val: json[key].Value, ack: true });
}
} else if (key === "Wind") {
await this.setStateAsync(`Hourly.h${hour}.WindSpeed`, { val: json[key].Speed.Value, ack: true });
await this.setStateAsync(`Hourly.h${hour}.WindDirection`, { val: json[key].Direction.Degrees, ack: true });
await this.setStateAsync(`Hourly.h${hour}.WindDirectionText`, { val: json[key].Direction.Localized , ack: true });
} else if (key === "WindGust") {
await this.setStateAsync(`Hourly.h${hour}.WindGust`, { val: json[key].Speed.Value, ack: true });
}
}
}
} catch (/** @type any */err) {
this.log.error(err);
}
}
async setNextHourStates(obj, item, hour) {
const json = obj[item];
try {
for (const key in json) {
if (typeof json[key] !== 'object') {
await this.setStateAsync(`Hourly.h${hour}.${key}`, { val: json[key], ack: true });
if (key === 'WeatherIcon') {
await this.setStateAsync(`Hourly.h${hour}.WeatherIconURL`, { val: `https://developer.accuweather.com/sites/default/files/${String(json[key]).padStart(2, '0')}-s.png`, ack: true });
await this.setStateAsync(`Hourly.h${hour}.WeatherIconURLS`, { val: `http://vortex.accuweather.com/adc2010/images/slate/icons/${String(json[key]).padStart(2, '0')}.svg`, ack: true });
}
} else if (typeof json[key] == 'object') {
if (json[key]['Value'] !== undefined) {
if (['TotalLiquid', 'Rain', 'Snow', 'Ice'].includes(key)) {
await this.setStateAsync(`Hourly.h${hour}.${key}Volume`, { val: json[key].Value, ack: true });
} else {
await this.setStateAsync(`Hourly.h${hour}.${key}`, { val: json[key].Value, ack: true });
}
} else if (key === 'Wind') {
await this.setStateAsync(`Hourly.h${hour}.WindSpeed`, { val: json[key].Speed.Value, ack: true });
await this.setStateAsync(`Hourly.h${hour}.WindDirection`, { val: json[key].Direction.Degrees, ack: true });
await this.setStateAsync(`Hourly.h${hour}.WindDirectionText`, { val: json[key].Direction.Localized , ack: true });
} else if (key === 'WindGust') {
await this.setStateAsync(`Hourly.h${hour}.WindGust`, { val: json[key].Speed.Value, ack: true });
}
}
}
} catch (/** @type any */err) {
this.log.error(err);
}
}
async setCurrentStates(obj) {
const json = obj[0];
try {
for (const key in json) {
//this.log.debug("Current: " + key + ": " + typeof json[key]);
if (typeof json[key] !== "object" || json[key] == null) {
await this.setStateAsync(`Current.${key}`, { val: json[key], ack: true });
async setCurrentStates(obj) {
const json = obj[0];
try {
for (const key in json) {
//this.log.debug("Current: " + key + ": " + typeof json[key]);
if (typeof json[key] !== 'object' || json[key] == null) {
await this.setStateAsync(`Current.${key}`, { val: json[key], ack: true });
if (key === "WeatherIcon") {
await this.setStateAsync("Current.WeatherIconURL", { val: `https://developer.accuweather.com/sites/default/files/${String(json[key]).padStart(2, "0")}-s.png`, ack: true });
await this.setStateAsync("Current.WeatherIconURLS", { val: `http://vortex.accuweather.com/adc2010/images/slate/icons/${String(json[key]).padStart(2, "0")}.svg`, ack: true });
await this.setStateAsync("Summary.WeatherIconURL", { val: `http://vortex.accuweather.com/adc2010/images/slate/icons/${String(json[key]).padStart(2, "0")}.svg`, ack: true });
await this.setStateAsync("Summary.WeatherIcon", { val: json[key], ack: true });
} else if (key === "LocalObservationDateTime") {
const dt = new Date(json[key]);
const dow = dt.toLocaleString(this.config.language, {weekday: "short"});
await this.setStateAsync("Summary.CurrentDateTime", { val: json[key], ack: true });
await this.setStateAsync("Summary.DayOfWeek", { val: dow, ack: true });
this.log.debug(`Date ${dt}, dow: ${dt.toLocaleString(this.config.language, {weekday: "short"})}`);
} else {
await this.setStateAsync(`Summary.${key}`, { val: json[key], ack: true });
}
} else if (json[key] !== null) {
if (json[key].Metric !== undefined) {
//this.log.debug(key + ": " + json[key].Metric.Value);
await this.setStateAsync(`Current.${key}`, { val: json[key].Metric.Value, ack: true });
await this.setStateAsync(`Summary.${key}`, { val: json[key].Metric.Value, ack: true });
} else if (key === "Wind") {
await this.setStateAsync("Current.WindSpeed", { val: json[key].Speed.Metric.Value, ack: true });
await this.setStateAsync("Summary.WindSpeed", { val: json[key].Speed.Metric.Value, ack: true });
await this.setStateAsync("Current.WindDirection", { val: json[key].Direction.Degrees, ack: true });
await this.setStateAsync("Current.WindDirectionText", { val: json[key].Direction.Localized, ack: true });
await this.setStateAsync("Summary.WindDirection", { val: json[key].Direction.Degrees, ack: true });
await this.setStateAsync("Summary.WindDirectionStr", { val: this.getCardinalDirection(json[key].Direction.Degrees), ack: true });
} else if (key === "WindGust") {
await this.setStateAsync("Current.WindGust", { val: json[key].Speed.Metric.Value, ack: true });
} else if (key === "PressureTendency") {
await this.setStateAsync("Current.PressureTendency", { val: json[key].LocalizedText, ack: true });
}
}
}
} catch (/** @type any */err) {
this.log.error(err);
}
}
if (key === 'WeatherIcon') {
await this.setStateAsync('Current.WeatherIconURL', { val: `https://developer.accuweather.com/sites/default/files/${String(json[key]).padStart(2, '0')}-s.png`, ack: true });
await this.setStateAsync('Current.WeatherIconURLS', { val: `http://vortex.accuweather.com/adc2010/images/slate/icons/${String(json[key]).padStart(2, '0')}.svg`, ack: true });
await this.setStateAsync('Summary.WeatherIconURL', { val: `http://vortex.accuweather.com/adc2010/images/slate/icons/${String(json[key]).padStart(2, '0')}.svg`, ack: true });
await this.setStateAsync('Summary.WeatherIcon', { val: json[key], ack: true });
} else if (key === 'LocalObservationDateTime') {
const dt = new Date(json[key]);
const dow = dt.toLocaleString(this.config.language, {weekday: 'short'});
await this.setStateAsync('Summary.CurrentDateTime', { val: json[key], ack: true });
await this.setStateAsync('Summary.DayOfWeek', { val: dow, ack: true });
this.log.debug(`Date ${dt}, dow: ${dt.toLocaleString(this.config.language, {weekday: 'short'})}`);
} else {
await this.setStateAsync(`Summary.${key}`, { val: json[key], ack: true });
}
} else if (json[key] !== null) {
if (json[key].Metric !== undefined) {
//this.log.debug(key + ": " + json[key].Metric.Value);
await this.setStateAsync(`Current.${key}`, { val: json[key].Metric.Value, ack: true });
await this.setStateAsync(`Summary.${key}`, { val: json[key].Metric.Value, ack: true });
} else if (key === 'Wind') {
await this.setStateAsync('Current.WindSpeed', { val: json[key].Speed.Metric.Value, ack: true });
await this.setStateAsync('Summary.WindSpeed', { val: json[key].Speed.Metric.Value, ack: true });
await this.setStateAsync('Current.WindDirection', { val: json[key].Direction.Degrees, ack: true });
await this.setStateAsync('Current.WindDirectionText', { val: json[key].Direction.Localized, ack: true });
await this.setStateAsync('Summary.WindDirection', { val: json[key].Direction.Degrees, ack: true });
await this.setStateAsync('Summary.WindDirectionStr', { val: this.getCardinalDirection(json[key].Direction.Degrees), ack: true });
} else if (key === 'WindGust') {
await this.setStateAsync('Current.WindGust', { val: json[key].Speed.Metric.Value, ack: true });
} else if (key === 'PressureTendency') {
await this.setStateAsync('Current.PressureTendency', { val: json[key].LocalizedText, ack: true });
}
}
}
} catch (/** @type any */err) {
this.log.error(err);
}
}
async setHourlyStates(obj) {
for (const hr in obj) {
if (typeof obj[hr] === "object" && obj[hr]["DateTime"]) {
const d = new Date(obj[hr]["DateTime"]);
await this.setNextHourStates(obj, hr, d.getHours());
}
}
}
async setHourlyStates(obj) {
for (const hr in obj) {
if (typeof obj[hr] === 'object' && obj[hr]['DateTime']) {
const d = new Date(obj[hr]['DateTime']);
await this.setNextHourStates(obj, hr, d.getHours());
}
}
}
request5Days() {
if (typeof this.forecast !== "undefined") {
const loc = this.config.loKey;
const lang = this.config.language;
this.forecast
.localkey(loc)
.timeInt("daily/5day")
.language(lang)
.metric(true)
.details(true)
.get()
.then(res => this.setDailyStates(res))
.catch(err => this.log.error(err));
}
}
request5Days() {
if (typeof this.forecast !== 'undefined') {
const loc = this.config.loKey;
const lang = this.config.language;
this.forecast
.localkey(loc)
.timeInt('daily/5day')
.language(lang)
.metric(true)
.details(true)
.get()
.then(res => this.setDailyStates(res))
.catch(err => this.log.error(err));
}
}
request12Hours() {
if (typeof this.forecast !== "undefined") {
const loc = this.config.loKey;
const lang = this.config.language;
this.forecast
.localkey(loc)
.timeInt("hourly/12hour")
.language(lang)
.metric(true)
.details(true)
.get()
.then(res => this.setHourlyStates(res))
.catch(err => this.log.error(err));
}
}
request12Hours() {
if (typeof this.forecast !== 'undefined') {
const loc = this.config.loKey;
const lang = this.config.language;
this.forecast
.localkey(loc)
.timeInt('hourly/12hour')
.language(lang)
.metric(true)
.details(true)
.get()
.then(res => this.setHourlyStates(res))
.catch(err => this.log.error(err));
}
}
requestCurrent() {
if (typeof this.forecast !== "undefined") {
const loc = this.config.loKey;
const lang = this.config.language;
requestCurrent() {
if (typeof this.forecast !== 'undefined') {
const loc = this.config.loKey;
const lang = this.config.language;
this.forecast
.localkey(loc)
.timeInt()
.language(lang)
.metric(true)
.details(true)
.getCurrent()
.then(res => this.setCurrentStates(res))
.catch(err => this.log.error(err));
}
}
this.forecast
.localkey(loc)
.timeInt()
.language(lang)
.metric(true)
.details(true)
.getCurrent()
.then(res => this.setCurrentStates(res))
.catch(err => this.log.error(err));
}
}
async onReady() {
let obj;
try {
obj = await this.getForeignObjectAsync(this.namespace);
} catch (e) {
// ignore
}
if (!obj) {
//@ts-ignore
await this.setForeignObjectAsync(this.namespace, { type: "device", common: { name: "Accuweather device" }, native: {} });
}
async onReady() {
let obj;
try {
obj = await this.getForeignObjectAsync(this.namespace);
} catch (e) {
// ignore
}
if (!obj) {
//@ts-ignore
await this.setForeignObjectAsync(this.namespace, { type: 'device', common: { name: 'Accuweather device' }, native: {} });
}
if (!this.config.language) {
const systemConfig = await this.getForeignObjectAsync("system.config");
if (systemConfig && systemConfig.common && systemConfig.common.language) {
this.config.language = systemConfig.common.language;
}
}
if (!this.config.language) {
const systemConfig = await this.getForeignObjectAsync('system.config');
if (systemConfig && systemConfig.common && systemConfig.common.language) {
this.config.language = systemConfig.common.language;
}
}
await nextHour.createHourlyForecastObjects(this);
await nextHour.createCurrentConditionObjects(this);
await nextHour.createDailyForecastObjects(this);
await nextHour.createSummaryObjects(this);
await nextHour.createHourlyForecastObjects(this);
await nextHour.createCurrentConditionObjects(this);
await nextHour.createDailyForecastObjects(this);
await nextHour.createSummaryObjects(this);
this.log.debug(`API: ${this.config.apiKey}; Loc: ${this.config.loKey} Lang: ${this.config.language}`);
this.log.debug(`API: ${this.config.apiKey}; Loc: ${this.config.loKey} Lang: ${this.config.language}`);
if (this.config.apiKey) {
this.forecast = new AccuAPI(this.config.apiKey);
} else {
this.log.error("API Key is missing. Please enter Accuweather API key");
}
if (this.config.apiKey) {
this.forecast = new AccuAPI(this.config.apiKey);
} else {
this.log.error('API Key is missing. Please enter Accuweather API key');
}
updateInterval = setInterval(() => {
const now = new Date();
if ((now.getHours() === 7 || now.getHours() === 20) && now.getMinutes() < 5) {
timeout1 = setTimeout(() => {
timeout1 = null;
this.request5Days();
}, Math.random() * 10000 + 1);
}
if (now.getMinutes() <= 5) {
timeout2 = setTimeout(() => {
timeout2 = null;
this.requestCurrent();
}, Math.random() * 10000 + 1);
}
if ((now.getHours() === 6 || now.getHours() === 12 || now.getHours() === 18 || now.getHours() === 0) && now.getMinutes() <= 5) {
timeout1 = setTimeout(() => {
timeout1 = null;
this.request12Hours();
}, Math.random() * 10000 + 1);
}
}, 300000); // 5 minutes
updateInterval = setInterval(() => {
const now = new Date();
if ((now.getHours() === 7 || now.getHours() === 20) && now.getMinutes() < 5) {
timeout1 = setTimeout(() => {
timeout1 = null;
this.request5Days();
}, Math.random() * 10000 + 1);
}
if (now.getMinutes() < 5) {
timeout2 = setTimeout(() => {
timeout2 = null;
this.requestCurrent();
}, Math.random() * 10000 + 1);
}
if ((now.getHours() === 6 || now.getHours() === 12 || now.getHours() === 18 || now.getHours() === 0) && now.getMinutes() < 5) {
timeout1 = setTimeout(() => {
timeout1 = null;
this.request12Hours();
}, Math.random() * 10000 + 1);
}
}, 300000); // 5 minutes
this.request12Hours();
this.requestCurrent();
this.request5Days();
this.request12Hours();
this.requestCurrent();
this.request5Days();
/*
/*
For every state in the system, there has to be also an object of type state

@@ -345,67 +345,67 @@ Here a simple template for a boolean variable named "testVariable"

await this.setObjectNotExistsAsync("updateCurrent", {
type: "state",
common: {
name: "Update Current Weather",
type: "boolean",
role: "button",
read: true,
write: true
},
native: {},
});
await this.setObjectNotExistsAsync("updateHourly", {
type: "state",
common: {
name: "Update 12 Hours Forecast",
type: "boolean",
role: "button",
read: true,
write: true,
},
native: {},
});
await this.setObjectNotExistsAsync("updateDaily", {
type: "state",
common: {
name: "Update 5 Days Forecast",
type: "boolean",
role: "button",
read: true,
write: true,
},
native: {},
});
await this.setObjectNotExistsAsync('updateCurrent', {
type: 'state',
common: {
name: 'Update Current Weather',
type: 'boolean',
role: 'button',
read: true,
write: true
},
native: {},
});
await this.setObjectNotExistsAsync('updateHourly', {
type: 'state',
common: {
name: 'Update 12 Hours Forecast',
type: 'boolean',
role: 'button',
read: true,
write: true,
},
native: {},
});
await this.setObjectNotExistsAsync('updateDaily', {
type: 'state',
common: {
name: 'Update 5 Days Forecast',
type: 'boolean',
role: 'button',
read: true,
write: true,
},
native: {},
});
// in this template, all states changes inside the adapter's namespace are subscribed
await this.subscribeStatesAsync("updateCurrent");
await this.subscribeStatesAsync("updateHourly");
await this.subscribeStatesAsync("updateDaily");
}
// in this template, all states changes inside the adapter's namespace are subscribed
await this.subscribeStatesAsync('updateCurrent');
await this.subscribeStatesAsync('updateHourly');
await this.subscribeStatesAsync('updateDaily');
}
/**
/**
* Is called when adapter shuts down - callback has to be called under any circumstances!
* @param {() => void} callback
*/
onUnload(callback) {
try {
this.log.info("cleaned everything up...");
updateInterval && clearInterval(updateInterval);
updateInterval = null;
onUnload(callback) {
try {
this.log.info('cleaned everything up...');
updateInterval && clearInterval(updateInterval);
updateInterval = null;
timeout1 && clearTimeout(timeout1);
timeout1 = null;
timeout1 && clearTimeout(timeout1);
timeout1 = null;
timeout2 && clearTimeout(timeout2);
timeout2 = null;
timeout2 && clearTimeout(timeout2);
timeout2 = null;
callback();
// @ts-ignore
callback = null;
} catch (e) {
callback && callback();
}
}
callback();
// @ts-ignore
callback = null;
} catch (e) {
callback && callback();
}
}
/**
/**
* Is called if a subscribed object changes

@@ -415,12 +415,12 @@ * @param {string} id

*/
onObjectChange(id, obj) {
if (obj) {
this.log.debug(`object ${id} changed: ${JSON.stringify(obj)}`);
} else {
// The object was deleted
this.log.debug(`object ${id} deleted`);
}
}
onObjectChange(id, obj) {
if (obj) {
this.log.debug(`object ${id} changed: ${JSON.stringify(obj)}`);
} else {
// The object was deleted
this.log.debug(`object ${id} deleted`);
}
}
/**
/**
* Is called if a subscribed state changes

@@ -430,18 +430,18 @@ * @param {string} id

*/
onStateChange(id, state) {
if (state) {
// The state was changed
if (id === `${this.namespace}.updateCurrent`) {
this.requestCurrent();
} else if (id === `${this.namespace}.updateHourly`) {
this.request12Hours();
} else if (id === `${this.namespace}.updateDaily`) {
this.request5Days();
}
this.log.debug(`state ${id} changed: ${state.val} (ack = ${state.ack})`);
} else {
// The state was deleted
this.log.debug(`state ${id} deleted`);
}
}
onStateChange(id, state) {
if (state) {
// The state was changed
if (id === `${this.namespace}.updateCurrent`) {
this.requestCurrent();
} else if (id === `${this.namespace}.updateHourly`) {
this.request12Hours();
} else if (id === `${this.namespace}.updateDaily`) {
this.request5Days();
}
this.log.debug(`state ${id} changed: ${state.val} (ack = ${state.ack})`);
} else {
// The state was deleted
this.log.debug(`state ${id} deleted`);
}
}
}

@@ -451,12 +451,12 @@

if (module.parent) {
// Export the constructor in compact mode
/**
// Export the constructor in compact mode
/**
* @param {Partial<utils.AdapterOptions>} [options={}]
*/
module.exports = (options) => new Accuweather(options);
module.exports = (options) => new Accuweather(options);
} else {
// otherwise start the instance directly
new Accuweather();
// otherwise start the instance directly
new Accuweather();
}
{
"name": "iobroker.accuweather",
"version": "1.4.0",
"version": "1.5.0",
"description": "Weather forecast using AccuWeather API",

@@ -24,5 +24,5 @@ "author": {

"dependencies": {
"@iobroker/adapter-core": "^3.0.6",
"axios": "^1.6.8",
"qs": "^6.12.0"
"@iobroker/adapter-core": "^3.1.6",
"axios": "^1.7.2",
"qs": "^6.12.1"
},

@@ -35,3 +35,3 @@ "devDependencies": {

"@iobroker/adapter-dev": "^1.3.0",
"@iobroker/testing": "^4.1.1",
"@iobroker/testing": "^4.1.3",
"@tsconfig/node18": "^18.2.4",

@@ -41,4 +41,4 @@ "@types/chai": "^4.3.11",

"@types/gulp": "^4.0.17",
"@types/mocha": "^10.0.6",
"@types/node": "^20.12.2",
"@types/mocha": "^10.0.7",
"@types/node": "^20.14.8",
"@types/proxyquire": "^1.3.31",

@@ -48,11 +48,10 @@ "@types/sinon": "^17.0.3",

"chai": "^4.4.1",
"chai-as-promised": "^7.1.1",
"chai-as-promised": "^7.1.2",
"colors": "1.4.0",
"eslint": "^8.57.0",
"gulp": "^4.0.2",
"mocha": "^10.4.0",
"proxyquire": "^2.1.3",
"sinon": "^17.0.1",
"sinon": "^18.0.0",
"sinon-chai": "^3.7.0",
"typescript": "^5.4.3"
"typescript": "^5.5.2"
},

@@ -68,12 +67,10 @@ "main": "main.js",

"scripts": {
"test:js": "mocha --opts test/mocha.custom.opts",
"test:js": "mocha --config test/mocharc.custom.json \"{!(node_modules|test)/**/*.test.js,*.test.js,test/**/test!(PackageFiles|Startup).js}\"",
"test:package": "mocha test/package --exit",
"test:unit": "mocha test/unit --exit",
"test:integration": "mocha test/integration --exit",
"test": "npm run test:js && npm run test:package",
"lint": "eslint",
"check": "tsc --noEmit -p tsconfig.check.json",
"lint": "eslint .",
"translate": "translate-adapter",
"release": "release-script",
"release-patch": "release-script patch --yes --no-update-lockfile",
"release-minor": "release-script minor --yes --no-update-lockfile",
"release-major": "release-script major --yes --no-update-lockfile",
"update-packages": "ncu --upgrade"

@@ -80,0 +77,0 @@ },

@@ -39,2 +39,8 @@ ![Logo](admin/accuweather.png)

-->
### 1.5.0 (2024-06-23)
* (xdaamg) limit updates to once an hour, this fixes part of issue #273.
* (mcm1957) Adapter requires js-controller >= 5 and admin >= 6 now
* (mcm1957) Node 22 support has been added to testing
* (mcm1957) Dependencies have been updated
### 1.4.0 (2024-04-02)

@@ -41,0 +47,0 @@ * (mcm1957) Adapter requires node.js 18 and js-controller >= 5 now

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc