iobroker.accuweather
Advanced tools
Comparing version 2.0.0 to 2.0.1
/*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": "2.0.0", | ||
"news": { | ||
"2.0.0": { | ||
"en": "Production release", | ||
"de": "Produktionsfreigabe", | ||
"ru": "Первая Версия", | ||
"pt": "Lançamento de produção", | ||
"nl": "Productie release", | ||
"fr": "Production", | ||
"it": "Rilascio di produzione", | ||
"es": "Lanzamiento de la producción", | ||
"pl": "Dopuszczenie do produkcji", | ||
"zh-cn": "生产发布" | ||
}, | ||
"0.1.0": { | ||
"en": "initial release", | ||
"de": "Erstveröffentlichung", | ||
"ru": "Начальная версия", | ||
"pt": "lançamento inicial", | ||
"nl": "Eerste uitgave", | ||
"fr": "Première version", | ||
"it": "Versione iniziale", | ||
"es": "Versión inicial", | ||
"pl": "Pierwsze wydanie", | ||
"zh-cn": "首次出版" | ||
}, | ||
"0.0.1": { | ||
"en": "initial release", | ||
"de": "Erstveröffentlichung", | ||
"ru": "Начальная версия", | ||
"pt": "lançamento inicial", | ||
"nl": "Eerste uitgave", | ||
"fr": "Première version", | ||
"it": "Versione iniziale", | ||
"es": "Versión inicial", | ||
"pl": "Pierwsze wydanie", | ||
"zh-cn": "首次出版" | ||
} | ||
}, | ||
"title": "AccuWeather", | ||
"titleLang": { | ||
"en": "AccuWeather", | ||
"de": "AccuWeather", | ||
"ru": "AccuWeather", | ||
"pt": "AccuWeather", | ||
"nl": "AccuWeather", | ||
"fr": "AccuWeather", | ||
"it": "AccuWeather", | ||
"es": "AccuWeather", | ||
"pl": "AccuWeather", | ||
"zh-cn": "机构AccuWeather" | ||
}, | ||
"desc": { | ||
"en": "Weather forecast using AccuWeather API", | ||
"de": "Wettervorhersage mit AccuWeather API", | ||
"ru": "Прогноз погоды с использованием AccuWeather API", | ||
"pt": "Previsão do tempo usando a API AccuWeather", | ||
"nl": "Weersverwachting met AccuWeather API", | ||
"fr": "Prévisions météorologiques à l'aide de l'API AccuWeather", | ||
"it": "Previsioni del tempo utilizzando l'API AccuWeather", | ||
"es": "Pronóstico del tiempo usando AccuWeather API", | ||
"pl": "Prognoza pogody za pomocą interfejsu API AccuWeather", | ||
"zh-cn": "使用AccuWeather API的天气预报" | ||
}, | ||
"authors": [ | ||
"algar42 <igor.aleschenkov@gmail.com>" | ||
], | ||
"keywords": [ | ||
"Weather", | ||
"AccuWeather", | ||
"Forecast" | ||
], | ||
"license": "MIT", | ||
"platform": "Javascript/Node.js", | ||
"main": "main.js", | ||
"icon": "accuweather.png", | ||
"enabled": true, | ||
"extIcon": "https://raw.githubusercontent.com/algar42/ioBroker.accuweather/master/admin/accuweather.png", | ||
"readme": "https://github.com/algar42/ioBroker.accuweather/blob/master/README.md", | ||
"loglevel": "info", | ||
"mode": "daemon", | ||
"type": "weather", | ||
"compact": true, | ||
"materialize": true, | ||
"dependencies": [ | ||
{ | ||
"js-controller": ">=1.4.2" | ||
} | ||
] | ||
}, | ||
"native": { | ||
"apiKey": "", | ||
"loKey": "", | ||
"language": "en-us" | ||
}, | ||
"objects": [], | ||
"instanceObjects": [] | ||
"common": { | ||
"name": "accuweather", | ||
"version": "2.0.1", | ||
"news": { | ||
"2.0.1": { | ||
"en": "BREAKING: Requires Nodejs 20 or higher\nBREAKING: Command states are now buttons and only respond to ack=false. \nadmin option: No data is updated on adapter startup (default: true). \napikey renamed and encrypted\nDependencies and eslint updated\nAdd nextHour.CloudCover", | ||
"de": "BREAKING: Erfordert Nodejs 20 oder höher\nBREAKING: Befehlszustände sind jetzt Tasten und reagieren nur auf ack=false.\nadmin-Option: Beim Adapter-Startup werden keine Daten aktualisiert (Standard: true).\napikey umbenannt und verschlüsselt\nAbhängigkeiten und eslint aktualisiert\nNextHour.CloudCover hinzufügen", | ||
"ru": "20 или более\nВЫВОДЫ: Командные состояния теперь являются кнопками и отвечают только на ack=false.\nadmin опция: Данные не обновляются о запуске адаптера (по умолчанию: True).\napikey переименован и зашифрован\nЗависимость и уклонение\nДобавить следующийHour.CloudCover", | ||
"pt": "BREAKING: Requer Nodejs 20 ou superior\nBREAKING: Os estados de comando agora são botões e só respondem ao ack=false.\nopção admin: Nenhum dado é atualizado na inicialização do adaptador (padrão: verdadeiro).\napikey renomeado e criptografado\nDependências e eslint atualizado\nAdicionar nextHour.CloudCover", | ||
"nl": "Breaking: Vereist Nodejs 20 of hoger\nOpdrachtstaten zijn nu knoppen en reageren alleen op ack=false.\nadmin optie: Er worden geen gegevens bijgewerkt bij het opstarten van de adapter (standaard: waar).\napikey hernoemd en gecodeerd\nAfhankelijkheden en eslint bijgewerkt\nVoeg volgende uur toe.CloudCover", | ||
"fr": "BREAKING: Nécessite Nodejs 20 ou plus\nLes états de commande sont maintenant des boutons et ne répondent qu'à ack=false.\noption administrateur & #160;: Aucune donnée n'est mise à jour au démarrage de l'adaptateur (par défaut: true).\napikey renommé et chiffré\nDépendances et essence mises à jour\nAjouter heure suivante.CloudCover", | ||
"it": "BREAKING: Richiede Nodejs 20 o più\nBREAKING: Gli stati di comando sono ora pulsanti e rispondono solo a ack=false.\nopzione admin: Nessun dato viene aggiornato sull'avvio dell'adattatore (default: true).\napikey rinominato e crittografato\nDipendenze ed eslint aggiornati\nAggiungi il prossimo.CloudCover", | ||
"es": "Requiere Nodejs 20 o superior\nLos estados de mando son ahora botones y sólo responden a ack=false.\nopción de administración: No se actualizan datos sobre el arranque del adaptador (por defecto: verdadero).\napikey renombrado y cifrado\nDependencias y datos actualizados\nAñade siguienteHour.CloudCover", | ||
"pl": "BREAKING: wymaga Nodejs 20 lub wyższy\nBREAKING: stany poleceń są teraz przyciskami i tylko odpowiadają na ack = false.\nopcja admin: Brak aktualizacji danych przy starcie adaptera (domyślnie: true).\napikey przemianowany i zaszyfrowany\nZaktualizowane zależności i eslint\nDodaj nextHour.CloudCover", | ||
"uk": "BREAKING: Вимагає Nodejs 20 або вище\nBREAKING: Командні стани тепер кнопки і тільки відповідають ack=false.\nопція адміністратора: Немає даних оновлюється на запуску адаптера (за замовчуванням: true).\napikey перейменований і зашифрований\nЗалежність і eslint оновлено\nДодати наступнеHour.CloudCover", | ||
"zh-cn": "需要20个或以上的节点\n命令状态现在是按键,只回应阿克=虚构.\n管理选项 : 没有更新适配器启动数据( 默认: true) .\napikey 重命名并加密\n依赖和Eslint 更新\n添加下一个 Hour. CloudCover" | ||
}, | ||
"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": { | ||
"en": "Adapter requires node.js 18 and js-controller >= 5 now\nDependencies have been updated", | ||
"de": "Adapter benötigt node.js 18 und js-controller >= 5 jetzt\nAbhängigkeiten wurden aktualisiert", | ||
"ru": "Адаптер требует node.js 18 и js-controller >= 5 сейчас\nЗависимость обновлена", | ||
"pt": "Adapter requer node.js 18 e js-controller >= 5 agora\nAs dependências foram atualizadas", | ||
"nl": "Adapter vereist node.js 18 en js-controller Nu 5\nAfhankelijkheden zijn bijgewerkt", | ||
"fr": "Adaptateur nécessite node.js 18 et js-controller >= 5 maintenant\nLes dépendances ont été actualisées", | ||
"it": "Adattatore richiede node.js 18 e js-controller >= 5 ora\nLe dipendenze sono state aggiornate", | ||
"es": "Adaptador requiere node.js 18 y js-controller √= 5 ahora\nSe han actualizado las dependencias", | ||
"pl": "Adapter wymaga node.js 18 i sterownika js- > = 5 teraz\nZaktualizowano zależności", | ||
"uk": "Адаптер вимагає node.js 18 і js-controller >= 5 тепер\nЗалежність було оновлено", | ||
"zh-cn": "适配器需要节点.js 18和js控制器 QQ 现在5号\n依赖关系已更新" | ||
}, | ||
"1.3.2": { | ||
"en": "fixed: dependencies\nfixed: error message [object Object]", | ||
"de": "fest: abhängigkeiten\nbehoben: Fehlermeldung [objekt]", | ||
"ru": "фиксированный: зависимости\nисправлено: сообщение об ошибке [object Object]", | ||
"pt": "corrigido: dependências\ncorrigido: mensagem de erro [objeto]", | ||
"nl": "afhankelijkheid\nvergissing", | ||
"fr": "fixes: dépendances\ncorrigé: message d'erreur [objet]", | ||
"it": "fisso: dipendenze\nfisso: messaggio di errore [oggetto oggetto]", | ||
"es": "fija: dependencias\nfijo: mensaje de error [objeto objeto]", | ||
"pl": "zależność\nuruchomione: błędy wiadomości (pol.)", | ||
"uk": "фіксована: залежності\nвиправлено: повідомлення про помилку [об'єкт]", | ||
"zh-cn": "固定:取决于\n固定:错误信息[目标]" | ||
}, | ||
"1.3.1": { | ||
"en": "added the Wind Direction Text und Cloud Cover\nAdded json config", | ||
"de": "windrichtung Text und Cloud Cover\nHinzugefügt json config", | ||
"ru": "добавлено направление ветра Текст und Облачная крышка\nДобавлено json config", | ||
"pt": "adicionou o texto de direção do vento und Cloud Cover\nAdicionado json config", | ||
"nl": "voegde de Wind Direction Text und Cloud Cover toe\n_", | ||
"fr": "ajouté la fenêtre de direction du vent Text und Cloud Cover\nAjouté json config", | ||
"it": "aggiunto la direzione del vento Testo und Cloud Cover\nAggiunto json config", | ||
"es": "añadido el texto dirección del viento und cubierta de nube\nAñadido json config", | ||
"pl": "wprowadzono dyrekcję Wind Direction Text i Cloud Cover\nAdded json configig", | ||
"uk": "додана хмарна кришка вітру\nДодано json config", | ||
"zh-cn": "添加了Wind Direction案文 und Cloud Cover\n增编" | ||
}, | ||
"1.2.4": { | ||
"en": "dependencies update", | ||
"de": "Abhängigkeiten aktualisieren", | ||
"ru": "обновление зависимостей", | ||
"pt": "atualização de dependências", | ||
"nl": "afhankelijkheden bijwerken", | ||
"fr": "mise à jour des dépendances", | ||
"it": "aggiornamento delle dipendenze", | ||
"es": "actualización de dependencias", | ||
"pl": "aktualizacja zależności", | ||
"zh-cn": "依赖更新", | ||
"uk": "оновлення залежностей" | ||
}, | ||
"1.2.3": { | ||
"en": "HoursOfSun parameter added to Daily forecast", | ||
"de": "HoursOfSun-Parameter zur täglichen Vorhersage hinzugefügt", | ||
"ru": "В суточный прогноз добавлен параметр HoursOfSun", | ||
"pt": "Parâmetro HoursOfSun adicionado à previsão diária", | ||
"nl": "HoursOfSun-parameter toegevoegd aan dagelijkse voorspelling", | ||
"fr": "Paramètre HoursOfSun ajouté aux prévisions quotidiennes", | ||
"it": "Parametro HoursOfSun aggiunto alla previsione giornaliera", | ||
"es": "Parámetro HoursOfSun agregado al pronóstico diario", | ||
"pl": "Dodano parametr HoursOfSun do prognozy dziennej", | ||
"zh-cn": "每日预测中添加了 hoursOfSun 参数", | ||
"uk": "До щоденного прогнозу додано параметр HoursOfSun" | ||
} | ||
}, | ||
"titleLang": { | ||
"en": "AccuWeather", | ||
"de": "AccuWeather", | ||
"ru": "AccuWeather", | ||
"pt": "AccuWeather", | ||
"nl": "AccuWeather", | ||
"fr": "AccuWeather", | ||
"it": "AccuWeather", | ||
"es": "AccuWeather", | ||
"pl": "AccuWeather", | ||
"zh-cn": "机构AccuWeather", | ||
"uk": "AccuWeather" | ||
}, | ||
"desc": { | ||
"en": "Weather forecast using AccuWeather API", | ||
"de": "Wettervorhersage mit AccuWeather API", | ||
"ru": "Прогноз погоды с использованием AccuWeather API", | ||
"pt": "Previsão do tempo usando a API AccuWeather", | ||
"nl": "Weersverwachting met AccuWeather API", | ||
"fr": "Prévisions météorologiques à l'aide de l'API AccuWeather", | ||
"it": "Previsioni del tempo utilizzando l'API AccuWeather", | ||
"es": "Pronóstico del tiempo usando AccuWeather API", | ||
"pl": "Prognoza pogody za pomocą interfejsu API AccuWeather", | ||
"zh-cn": "使用AccuWeather API的天气预报", | ||
"uk": "Прогноз погоди за допомогою AccuWeather API" | ||
}, | ||
"authors": [ | ||
"algar42 <igor.aleschenkov@gmail.com>" | ||
], | ||
"keywords": [ | ||
"Weather", | ||
"AccuWeather", | ||
"Forecast" | ||
], | ||
"licenseInformation": { | ||
"license": "MIT", | ||
"type": "free" | ||
}, | ||
"platform": "Javascript/Node.js", | ||
"icon": "accuweather.png", | ||
"enabled": true, | ||
"extIcon": "https://raw.githubusercontent.com/iobroker-community-adapters/ioBroker.accuweather/master/admin/accuweather.png", | ||
"readme": "https://github.com/iobroker-community-adapters/ioBroker.accuweather/blob/master/README.md", | ||
"loglevel": "info", | ||
"tier": 2, | ||
"mode": "daemon", | ||
"type": "weather", | ||
"compact": true, | ||
"materialize": true, | ||
"adminUI": { | ||
"config": "json" | ||
}, | ||
"connectionType": "cloud", | ||
"dataSource": "poll", | ||
"dependencies": [ | ||
{ | ||
"js-controller": ">=6.0.11" | ||
} | ||
], | ||
"globalDependencies": [ | ||
{ | ||
"admin": ">=6.17.14" | ||
} | ||
] | ||
}, | ||
"native": { | ||
"apiKeyEncrypted": "", | ||
"loKey": "", | ||
"language": "", | ||
"apiCallProtection": true | ||
}, | ||
"protectedNative": [ | ||
"apiKeyEncrypted" | ||
], | ||
"encryptedNative": [ | ||
"apiKeyEncrypted" | ||
], | ||
"objects": [], | ||
"instanceObjects": [] | ||
} |
@@ -1,97 +0,148 @@ | ||
"use strict"; | ||
const req = require("request"); | ||
'use strict'; | ||
const axios = require('axios'); | ||
//const moment = require("moment"); | ||
const queryString = require("query-string"); | ||
const queryString = require('qs'); | ||
/** | ||
* Class representing the AccuWeather API. | ||
*/ | ||
class Accuapi { | ||
constructor(apiKey) { | ||
this.apiKey = apiKey; | ||
this.lokey = 335315; | ||
this.query = {}; | ||
//this.adapter = adapter; | ||
} | ||
/** | ||
* Create an instance of Accuapi. | ||
* | ||
* @param apiKey - The API key for accessing AccuWeather. | ||
*/ | ||
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. | ||
/** | ||
* Set the location key. | ||
* | ||
* @param lkey - The location key. | ||
* @returns The instance of Accuapi. | ||
*/ | ||
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. | ||
/** | ||
* Set the time interval. | ||
* | ||
* @param val - The time interval value. | ||
* @returns Accuapi The instance of Accuapi. | ||
*/ | ||
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. | ||
/** | ||
* Sets the language for the API request. | ||
* | ||
* @param lan - The language code in which to return the resource. | ||
* Refer to http://apidev.accuweather.com/developers/languages for valid language codes. | ||
* If not provided, the default value is 'en-us'. | ||
* @returns The current instance of the API object to allow for method chaining. | ||
*/ | ||
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). | ||
/** | ||
* Set the details flag. | ||
* | ||
* @param bool - Specifies whether or not to include the full object. | ||
* @returns The instance of Accuapi. | ||
*/ | ||
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. | ||
/** | ||
* Set the metric flag. | ||
* | ||
* @param bool - Specifies whether to return the data in metric units. | ||
* @returns The instance of Accuapi. | ||
*/ | ||
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; | ||
} | ||
/** | ||
* Generates the request URL for the AccuWeather API. | ||
* | ||
* @param current - A boolean indicating whether to generate the URL for current conditions or forecasts. | ||
* If true, the URL for current conditions is generated. | ||
*/ | ||
generateReqUrl(current = false) { | ||
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() { | ||
return new Promise((resolve, reject) => { | ||
// | ||
//const body = require("./test-data/daily.json"); | ||
// | ||
this.generateReqUrl(); | ||
req({ url: this.url, json: true }, (err, res, body) => { | ||
err ? reject(`Forecast cannot be retrieved. ERROR: ${err}`) : null; | ||
res.statusCode !== 200 ? reject(`Forecast cannot be retrieved. Response: ${res.statusCode} ${res.statusMessage}`) : null; | ||
resolve(body); | ||
//log.info("response: " + body); | ||
}); | ||
/** | ||
* Retrieves the weather data from the AccuWeather API. | ||
* | ||
* @returns A promise that resolves to the weather data. | ||
* @throws {Error} Throws an error if the forecast cannot be retrieved. | ||
*/ | ||
get() { | ||
this.generateReqUrl(); | ||
return axios | ||
.get(this.url ? 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()}`, | ||
); | ||
}); | ||
} | ||
}); | ||
/** | ||
* Retrieves the current weather data from the AccuWeather API. | ||
* | ||
* @returns A promise that resolves to the current weather data. | ||
* @throws {Error} Throws an error if the forecast cannot be retrieved. | ||
*/ | ||
getCurrent() { | ||
// | ||
//const body = require("./test-data/currentCond.json"); | ||
// | ||
this.generateReqUrl(true); | ||
return axios | ||
.get(this.url ? 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() { | ||
return new Promise((resolve, reject) => { | ||
// | ||
//const body = require("./test-data/currentCond.json"); | ||
// | ||
this.generateReqUrl(true); | ||
req({ url: this.url, json: true }, (err, res, body) => { | ||
err ? reject(`Forecast cannot be retrieved. ERROR: ${err}`) : null; | ||
res.statusCode !== 200 ? reject(`Forecast cannot be retrieved. Response: ${res.statusCode} ${res.statusMessage}`) : null; | ||
resolve(body); | ||
//log.info("response: " + body); | ||
}); | ||
}); | ||
} | ||
} | ||
module.exports = Accuapi; |
{ | ||
"nextHour.LocalObservationDateTime": { | ||
"type": "state", | ||
"common": { | ||
"name": "Forecast date", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value.datetime" | ||
}, | ||
"native": {} | ||
"nextHour.LocalObservationDateTime": { | ||
"type": "state", | ||
"common": { | ||
"name": "Forecast date", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "date" | ||
}, | ||
"nextHour.WeatherIcon": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Icon", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.WeatherIcon": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Icon", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value" | ||
}, | ||
"nextHour.WeatherIconURL": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Icon URL", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "media.url" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.WeatherIconURL": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Icon URL", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "media.url" | ||
}, | ||
"nextHour.WeatherIconURLS": { | ||
"type": "state", | ||
"common": { | ||
"name": "SVG Weather Icon URL", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "media.url" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.WeatherIconURLS": { | ||
"type": "state", | ||
"common": { | ||
"name": "SVG Weather Icon URL", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "weather.icon" | ||
}, | ||
"nextHour.WeatherText": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Description", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.WeatherText": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Description", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "weather.state" | ||
}, | ||
"nextHour.HasPrecipitation": { | ||
"type": "state", | ||
"common": { | ||
"name": "Precipitation", | ||
"type": "boolean", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.HasPrecipitation": { | ||
"type": "state", | ||
"common": { | ||
"name": "Precipitation", | ||
"type": "boolean", | ||
"read": true, | ||
"write": false, | ||
"role": "value" | ||
}, | ||
"nextHour.PrecipitationType": { | ||
"type": "state", | ||
"common": { | ||
"name": "Precipitation Description", | ||
"type": "boolean", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.PrecipitationType": { | ||
"type": "state", | ||
"common": { | ||
"name": "Precipitation Description", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "value" | ||
}, | ||
"nextHour.Temperature": { | ||
"type": "state", | ||
"common": { | ||
"name": "Temperature", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value.temperature", | ||
"unit": "°C" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.Temperature": { | ||
"type": "state", | ||
"common": { | ||
"name": "Temperature", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.temperature", | ||
"unit": "°C" | ||
}, | ||
"nextHour.RealFeelTemperature": { | ||
"type": "state", | ||
"common": { | ||
"name": "Feels Like Temperature", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value.temperature", | ||
"unit": "°C" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.RealFeelTemperature": { | ||
"type": "state", | ||
"common": { | ||
"name": "Feels Like Temperature", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.temperature.feelslike", | ||
"unit": "°C" | ||
}, | ||
"nextHour.RealFeelTemperatureShade": { | ||
"type": "state", | ||
"common": { | ||
"name": "Shadow Temperature", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value.temperature", | ||
"unit": "°C" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.RealFeelTemperatureShade": { | ||
"type": "state", | ||
"common": { | ||
"name": "Shadow Temperature", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.temperature", | ||
"unit": "°C" | ||
}, | ||
"nextHour.DewPoint": { | ||
"type": "state", | ||
"common": { | ||
"name": "Dew Point", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit": "°C" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.DewPoint": { | ||
"type": "state", | ||
"common": { | ||
"name": "Dew Point", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "°C" | ||
}, | ||
"nextHour.WindSpeed":{ | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Speed", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit": "km/h" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.WindSpeed": { | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Speed", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.speed.wind", | ||
"unit": "km/h" | ||
}, | ||
"nextHour.WindDirection": { | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Direction", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit": "°" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.WindDirection": { | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Direction", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.direction.wind", | ||
"unit": "°" | ||
}, | ||
"nextHour.WindGust": { | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Gust", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit": "km/h" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.WindDirectionText": { | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Direction Text", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "value.direction.wind" | ||
}, | ||
"nextHour.RelativeHumidity": { | ||
"type": "state", | ||
"common": { | ||
"name": "Humidity", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value.humidity", | ||
"unit": "%" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.WindGust": { | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Gust", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "km/h" | ||
}, | ||
"nextHour.UVIndex": { | ||
"type": "state", | ||
"common": { | ||
"name": "UV Index", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.RelativeHumidity": { | ||
"type": "state", | ||
"common": { | ||
"name": "Humidity", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.humidity", | ||
"unit": "%" | ||
}, | ||
"nextHour.UVIndexText": { | ||
"type": "state", | ||
"common": { | ||
"name": "UV Index Description", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.CloudCover": { | ||
"type": "state", | ||
"common": { | ||
"name": "Cloud Cover", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "%" | ||
}, | ||
"nextHour.Pressure": { | ||
"type": "state", | ||
"common": { | ||
"name": "Pressure", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value.pressure", | ||
"unit":"mb" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.UVIndex": { | ||
"type": "state", | ||
"common": { | ||
"name": "UV Index", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value" | ||
}, | ||
"nextHour.PressureTendency": { | ||
"type": "state", | ||
"common": { | ||
"name": "Ptressure Tendency", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value" | ||
}, | ||
"native": {} | ||
} | ||
"native": {} | ||
}, | ||
"nextHour.UVIndexText": { | ||
"type": "state", | ||
"common": { | ||
"name": "UV Index Description", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "value" | ||
}, | ||
"native": {} | ||
}, | ||
"nextHour.Pressure": { | ||
"type": "state", | ||
"common": { | ||
"name": "Pressure", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.pressure", | ||
"unit": "mb" | ||
}, | ||
"native": {} | ||
}, | ||
"nextHour.PressureTendency": { | ||
"type": "state", | ||
"common": { | ||
"name": "Pressure Tendency", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "value" | ||
}, | ||
"native": {} | ||
} | ||
} |
{ | ||
"Daily.dayn.Date": { | ||
"type": "state", | ||
"common": { | ||
"name": "Forecast date", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value.datetime" | ||
}, | ||
"native": {} | ||
"Daily.dayn.Date": { | ||
"type": "state", | ||
"common": { | ||
"name": "Forecast date", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "date" | ||
}, | ||
"Daily.dayn.Sunrise": { | ||
"type": "state", | ||
"common": { | ||
"name": "Sunrise datetime", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value.datetime" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.Sunrise": { | ||
"type": "state", | ||
"common": { | ||
"name": "Sunrise datetime", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "date.sunrise" | ||
}, | ||
"Daily.dayn.Sunset": { | ||
"type": "state", | ||
"common": { | ||
"name": "Sunset datetime", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value.datetime" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.Sunset": { | ||
"type": "state", | ||
"common": { | ||
"name": "Sunset datetime", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "date.sunset" | ||
}, | ||
"Daily.dayn.Temperature.Minimum": { | ||
"type": "state", | ||
"common": { | ||
"name": "Temperature Min", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value.temperature", | ||
"unit": "°C" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.HoursOfSun": { | ||
"type": "state", | ||
"common": { | ||
"name": "Hours of Sun", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value" | ||
}, | ||
"Daily.dayn.Temperature.Maximum": { | ||
"type": "state", | ||
"common": { | ||
"name": "Temperature Max", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value.temperature", | ||
"unit": "°C" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.Temperature.Minimum": { | ||
"type": "state", | ||
"common": { | ||
"name": "Temperature Min", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.temperature.min", | ||
"unit": "°C" | ||
}, | ||
"Daily.dayn.RealFeelTemperature.Minimum": { | ||
"type": "state", | ||
"common": { | ||
"name": "Feels Like Temperature Min", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value.temperature", | ||
"unit": "°C" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.Temperature.Maximum": { | ||
"type": "state", | ||
"common": { | ||
"name": "Temperature Max", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.temperature.max", | ||
"unit": "°C" | ||
}, | ||
"Daily.dayn.RealFeelTemperature.Maximum": { | ||
"type": "state", | ||
"common": { | ||
"name": "Feels Like Temperature Max", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value.temperature", | ||
"unit": "°C" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.RealFeelTemperature.Minimum": { | ||
"type": "state", | ||
"common": { | ||
"name": "Feels Like Temperature Min", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.temperature.feelslike.min", | ||
"unit": "°C" | ||
}, | ||
"Daily.dayn.dayPart.Icon": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Icon", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.RealFeelTemperature.Maximum": { | ||
"type": "state", | ||
"common": { | ||
"name": "Feels Like Temperature Max", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.temperature.feelslike.max", | ||
"unit": "°C" | ||
}, | ||
"Daily.dayn.dayPart.IconURL": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Icon URL", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "media.url" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.Icon": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Icon", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value" | ||
}, | ||
"Daily.dayn.dayPart.IconURLS": { | ||
"type": "state", | ||
"common": { | ||
"name": "SVG Weather Icon URL", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "media.url" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.IconURL": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Icon URL", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "media.url" | ||
}, | ||
"Daily.dayn.dayPart.IconPhrase": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Description", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.IconURLS": { | ||
"type": "state", | ||
"common": { | ||
"name": "SVG Weather Icon URL", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "weather.icon" | ||
}, | ||
"Daily.dayn.dayPart.HasPrecipitation": { | ||
"type": "state", | ||
"common": { | ||
"name": "Precipitation", | ||
"type": "boolean", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.IconPhrase": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Description", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "weather.state" | ||
}, | ||
"Daily.dayn.dayPart.ShortPhrase": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Description", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.HasPrecipitation": { | ||
"type": "state", | ||
"common": { | ||
"name": "Precipitation", | ||
"type": "boolean", | ||
"read": true, | ||
"write": false, | ||
"role": "value" | ||
}, | ||
"Daily.dayn.dayPart.LongPhrase": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Description", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.ShortPhrase": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Description", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "weather.state.description" | ||
}, | ||
"Daily.dayn.dayPart.PrecipitationProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Precipitation Probability", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit":"%" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.LongPhrase": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Description", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "value" | ||
}, | ||
"Daily.dayn.dayPart.ThunderstormProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Thunderstorm Probability", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit":"%" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.PrecipitationProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Precipitation Probability", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.precipitation", | ||
"unit": "%" | ||
}, | ||
"Daily.dayn.dayPart.RainProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Rain Probability", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit":"%" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.ThunderstormProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Thunderstorm Probability", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "%" | ||
}, | ||
"Daily.dayn.dayPart.SnowProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Snow Probability", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit":"%" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.RainProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Rain Probability", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "%" | ||
}, | ||
"Daily.dayn.dayPart.IceProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Ice Probability", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit":"%" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.SnowProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Snow Probability", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "%" | ||
}, | ||
"Daily.dayn.dayPart.WindSpeed":{ | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Speed", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit": "km/h" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.IceProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Ice Probability", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "%" | ||
}, | ||
"Daily.dayn.dayPart.WindDirection": { | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Direction", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit": "°" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.WindSpeed": { | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Speed", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.speed.wind", | ||
"unit": "km/h" | ||
}, | ||
"Daily.dayn.dayPart.WindGust": { | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Gust", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit": "km/h" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.WindDirection": { | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Direction", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "value.direction.wind", | ||
"unit": "°" | ||
}, | ||
"Daily.dayn.dayPart.RainVolume":{ | ||
"type": "state", | ||
"common": { | ||
"name": "Rain Amount", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit":"mm" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.WindGust": { | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Gust", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "km/h" | ||
}, | ||
"Daily.dayn.dayPart.SnowVolume":{ | ||
"type": "state", | ||
"common": { | ||
"name": "Snow Amount", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit":"mm" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.RainVolume": { | ||
"type": "state", | ||
"common": { | ||
"name": "Rain Amount", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "mm" | ||
}, | ||
"Daily.dayn.dayPart.IceVolume":{ | ||
"type": "state", | ||
"common": { | ||
"name": "Ice Amount", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit":"mm" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.SnowVolume": { | ||
"type": "state", | ||
"common": { | ||
"name": "Snow Amount", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "mm" | ||
}, | ||
"Daily.dayn.dayPart.TotalLiquidVolume": { | ||
"type": "state", | ||
"common": { | ||
"name": "Total Precipitation Amount", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit":"mm" | ||
}, | ||
"native": {} | ||
} | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.IceVolume": { | ||
"type": "state", | ||
"common": { | ||
"name": "Ice Amount", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "mm" | ||
}, | ||
"native": {} | ||
}, | ||
"Daily.dayn.dayPart.TotalLiquidVolume": { | ||
"type": "state", | ||
"common": { | ||
"name": "Total Precipitation Amount", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.precipitation", | ||
"unit": "mm" | ||
}, | ||
"native": {} | ||
} | ||
} |
@@ -1,66 +0,102 @@ | ||
"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); | ||
for (const key in _obj) { | ||
adapter.setObjectNotExists(key, _obj[key]); | ||
} | ||
} | ||
async function createNextHourForecatObjects(hour, adapter) { | ||
const obj = require("./nextHourObject.json"); | ||
await adapter.setObjectAsync("Hourly.h" + hour, { | ||
type: "channel", | ||
common: { | ||
name: `Hour ${hour} Forecast` | ||
}, | ||
native: {}, | ||
}); | ||
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) { | ||
await adapter.setObjectAsync(key.replace("nextHour", "Hourly.h" + hour), obj[key]); | ||
} | ||
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]); | ||
} | ||
} | ||
async function createCurrentConditionObjects(adapter) { | ||
const obj = require("./currentCondObject.json"); | ||
await adapter.setObjectAsync("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) { | ||
await adapter.setObjectAsync(key.replace("nextHour", "Current"), obj[key]); | ||
} | ||
for (const key in obj) { | ||
adapter.setObjectNotExists(key.replace('nextHour', 'Current'), obj[key]); | ||
} | ||
} | ||
async function createDailyForecastObjects(adapter) { | ||
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.setObjectAsync("Daily.Day" + i, { | ||
type: "channel", | ||
common: { | ||
name: `Day ${i} Forecast` | ||
}, | ||
native: {}, | ||
}); | ||
for (const key in obj) { | ||
if (!key.indexOf("dayPart.")) { await adapter.setObjectAsync(key.replace("dayn.", "Day" + i + "."), obj[key]); } | ||
else { | ||
["Day", "Night"].forEach(async function (dp) { | ||
await adapter.setObjectAsync(key.replace("dayn.", "Day" + i + ".").replace("dayPart.", dp + "."), obj[key]); | ||
}); | ||
} | ||
} | ||
} | ||
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]); | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
function createHourlyForecastObjects(adapter) { | ||
for (let hr = 0; hr < 24; hr++) { | ||
createNextHourForecatObjects(hr, adapter); | ||
} | ||
async function createHourlyForecastObjects(adapter) { | ||
for (let hr = 0; hr < 24; hr++) { | ||
await createNextHourForecatObjects(hr, adapter); | ||
} | ||
} | ||
@@ -71,2 +107,3 @@ | ||
exports.createCurrentConditionObjects = createCurrentConditionObjects; | ||
exports.createDailyForecastObjects = createDailyForecastObjects; | ||
exports.createDailyForecastObjects = createDailyForecastObjects; | ||
exports.createSummaryObjects = createSummaryObjects; |
{ | ||
"nextHour.DateTime": { | ||
"type": "state", | ||
"common": { | ||
"name": "Forecast date", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value.datetime" | ||
}, | ||
"native": {} | ||
"nextHour.DateTime": { | ||
"type": "state", | ||
"common": { | ||
"name": "Forecast date", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "date" | ||
}, | ||
"nextHour.WeatherIcon": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Icon", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.WeatherIcon": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Icon", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value" | ||
}, | ||
"nextHour.WeatherIconURL": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Icon URL", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "media.url" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.CloudCover": { | ||
"type": "state", | ||
"common": { | ||
"name": "CloudCover", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value" | ||
}, | ||
"nextHour.WeatherIconURLS": { | ||
"type": "state", | ||
"common": { | ||
"name": "SVG Weather Icon URL", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "media.url" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.WeatherIconURL": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Icon URL", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "media.url" | ||
}, | ||
"nextHour.IconPhrase": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Description", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.WeatherIconURLS": { | ||
"type": "state", | ||
"common": { | ||
"name": "SVG Weather Icon URL", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "weather.icon" | ||
}, | ||
"nextHour.HasPrecipitation": { | ||
"type": "state", | ||
"common": { | ||
"name": "Precipitation", | ||
"type": "boolean", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.IconPhrase": { | ||
"type": "state", | ||
"common": { | ||
"name": "Weather Description", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "weather.state" | ||
}, | ||
"nextHour.Temperature": { | ||
"type": "state", | ||
"common": { | ||
"name": "Temperature", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value.temperature", | ||
"unit": "°C" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.HasPrecipitation": { | ||
"type": "state", | ||
"common": { | ||
"name": "Precipitation", | ||
"type": "boolean", | ||
"read": true, | ||
"write": false, | ||
"role": "value" | ||
}, | ||
"nextHour.RealFeelTemperature": { | ||
"type": "state", | ||
"common": { | ||
"name": "Feels Like Temperature", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value.temperature", | ||
"unit": "°C" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.Temperature": { | ||
"type": "state", | ||
"common": { | ||
"name": "Temperature", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.temperature", | ||
"unit": "°C" | ||
}, | ||
"nextHour.DewPoint": { | ||
"type": "state", | ||
"common": { | ||
"name": "Dew Point", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit": "°C" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.RealFeelTemperature": { | ||
"type": "state", | ||
"common": { | ||
"name": "Feels Like Temperature", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.temperature.feelslike", | ||
"unit": "°C" | ||
}, | ||
"nextHour.WindSpeed":{ | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Speed", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit": "km/h" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.DewPoint": { | ||
"type": "state", | ||
"common": { | ||
"name": "Dew Point", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "°C" | ||
}, | ||
"nextHour.WindDirection": { | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Direction", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit": "°" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.WindSpeed": { | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Speed", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.speed.wind", | ||
"unit": "km/h" | ||
}, | ||
"nextHour.WindGust": { | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Gust", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit": "km/h" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.WindDirection": { | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Direction", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "value.direction.wind", | ||
"unit": "°" | ||
}, | ||
"nextHour.RelativeHumidity": { | ||
"type": "state", | ||
"common": { | ||
"name": "Humidity", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value.humidity", | ||
"unit": "%" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.WindGust": { | ||
"type": "state", | ||
"common": { | ||
"name": "Wind Gust", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "km/h" | ||
}, | ||
"nextHour.UVIndex": { | ||
"type": "state", | ||
"common": { | ||
"name": "UV Index", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.RelativeHumidity": { | ||
"type": "state", | ||
"common": { | ||
"name": "Humidity", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.humidity", | ||
"unit": "%" | ||
}, | ||
"nextHour.UVIndexText": { | ||
"type": "state", | ||
"common": { | ||
"name": "UV Index Description", | ||
"type": "string", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.UVIndex": { | ||
"type": "state", | ||
"common": { | ||
"name": "UV Index", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value" | ||
}, | ||
"nextHour.PrecipitationProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Precipitation Probability", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit":"%" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.UVIndexText": { | ||
"type": "state", | ||
"common": { | ||
"name": "UV Index Description", | ||
"type": "string", | ||
"read": true, | ||
"write": false, | ||
"role": "value" | ||
}, | ||
"nextHour.RainProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Rain Probability", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit":"%" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.PrecipitationProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Precipitation Probability", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.precipitation", | ||
"unit": "%" | ||
}, | ||
"nextHour.SnowProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Snow Probability", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit":"%" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.RainProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Rain Probability", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "%" | ||
}, | ||
"nextHour.IceProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Ice Probability", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit":"%" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.SnowProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Snow Probability", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "%" | ||
}, | ||
"nextHour.RainVolume":{ | ||
"type": "state", | ||
"common": { | ||
"name": "Rain Amount", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit":"mm" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.IceProbability": { | ||
"type": "state", | ||
"common": { | ||
"name": "Ice Probability", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "%" | ||
}, | ||
"nextHour.SnowVolume":{ | ||
"type": "state", | ||
"common": { | ||
"name": "Snow Amount", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit":"mm" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.RainVolume": { | ||
"type": "state", | ||
"common": { | ||
"name": "Rain Amount", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "mm" | ||
}, | ||
"nextHour.IceVolume":{ | ||
"type": "state", | ||
"common": { | ||
"name": "Ice Amount", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit":"mm" | ||
}, | ||
"native": {} | ||
"native": {} | ||
}, | ||
"nextHour.SnowVolume": { | ||
"type": "state", | ||
"common": { | ||
"name": "Snow Amount", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "mm" | ||
}, | ||
"nextHour.TotalLiquidVolume": { | ||
"type": "state", | ||
"common": { | ||
"name": "Total Precipitation Amount", | ||
"type": "number", | ||
"read": "true", | ||
"write": "false", | ||
"role": "value", | ||
"unit":"mm" | ||
}, | ||
"native": {} | ||
} | ||
"native": {} | ||
}, | ||
"nextHour.IceVolume": { | ||
"type": "state", | ||
"common": { | ||
"name": "Ice Amount", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value", | ||
"unit": "mm" | ||
}, | ||
"native": {} | ||
}, | ||
"nextHour.TotalLiquidVolume": { | ||
"type": "state", | ||
"common": { | ||
"name": "Total Precipitation Amount", | ||
"type": "number", | ||
"read": true, | ||
"write": false, | ||
"role": "value.precipitation", | ||
"unit": "mm" | ||
}, | ||
"native": {} | ||
} | ||
} |
122
lib/tools.js
@@ -1,14 +0,15 @@ | ||
const axios = require("axios"); | ||
const axios = require('axios'); | ||
/** | ||
* Tests whether the given variable is a real object and not an Array | ||
* @param {any} it The variable to test | ||
* @returns {it is Record<string, any>} | ||
* | ||
* @param it The variable to test | ||
* @returns | ||
*/ | ||
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]'; | ||
} | ||
@@ -18,8 +19,11 @@ | ||
* Tests whether the given variable is really an Array | ||
* @param {any} it The variable to test | ||
* @returns {it is any[]} | ||
* | ||
* @param it The variable to test | ||
* @returns | ||
*/ | ||
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]'; | ||
} | ||
@@ -29,16 +33,16 @@ | ||
* Translates text to the target language. Automatically chooses the right translation API. | ||
* @param {string} text The text to translate | ||
* @param {string} targetLang The target languate | ||
* @param {string} [yandexApiKey] The yandex API key. You can create one for free at https://translate.yandex.com/developers | ||
* @returns {Promise<string>} | ||
* | ||
* @param text The text to translate | ||
* @param targetLang The target languate | ||
* @param [yandexApiKey] The yandex API key. You can create one for free at https://translate.yandex.com/developers | ||
* @returns | ||
*/ | ||
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); | ||
} | ||
return await translateGoogle(text, targetLang); | ||
} | ||
@@ -48,21 +52,22 @@ | ||
* Translates text with Yandex API | ||
* @param {string} text The text to translate | ||
* @param {string} targetLang The target languate | ||
* @param {string} [apiKey] The yandex API key. You can create one for free at https://translate.yandex.com/developers | ||
* @returns {Promise<string>} | ||
* | ||
* @param text The text to translate | ||
* @param targetLang The target languate | ||
* @param [apiKey] The yandex API key. You can create one for free at https://translate.yandex.com/developers | ||
* @returns | ||
*/ | ||
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}`); | ||
} | ||
} | ||
@@ -72,24 +77,25 @@ | ||
* Translates text with Google API | ||
* @param {string} text The text to translate | ||
* @param {string} targetLang The target languate | ||
* @returns {Promise<string>} | ||
* | ||
* @param text The text to translate | ||
* @param targetLang The target languate | ||
* @returns | ||
*/ | ||
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, | ||
}; |
994
main.js
@@ -1,2 +0,2 @@ | ||
"use strict"; | ||
'use strict'; | ||
@@ -9,416 +9,642 @@ /* | ||
// 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; | ||
let timeout1 = null; | ||
let timeout2 = null; | ||
// Load your modules here, e.g.: | ||
// const fs = require("fs"); | ||
//let forecast = undefined; | ||
class Accuweather extends utils.Adapter { | ||
/** | ||
* @param [options] - Optional settings for the adapter | ||
*/ | ||
constructor(options = {}) { | ||
super({ | ||
...options, | ||
name: 'accuweather', | ||
strictObjectChecks: false, | ||
}); | ||
this.on('ready', this.onReady.bind(this)); | ||
this.on('stateChange', this.onStateChange.bind(this)); | ||
this.on('unload', this.onUnload.bind(this)); | ||
} | ||
/** | ||
* @param {Partial<ioBroker.AdapterOptions>} [options={}] | ||
*/ | ||
constructor(options) { | ||
super({ | ||
...options, | ||
name: "accuweather", | ||
}); | ||
this.on("ready", this.onReady.bind(this)); | ||
this.on("objectChange", this.onObjectChange.bind(this)); | ||
this.on("stateChange", this.onStateChange.bind(this)); | ||
// this.on("message", this.onMessage.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']; | ||
} | ||
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.setState(`Daily.Day${day}.${key}`, { | ||
val: json[key], | ||
ack: true, | ||
}); | ||
await this.setState(`Summary.DateTime_d${day}`, { | ||
val: json[key], | ||
ack: true, | ||
}); | ||
await this.setState(`Summary.DayOfWeek_d${day}`, { | ||
val: dt.toLocaleString(this.config.language, { | ||
weekday: 'short', | ||
}), | ||
ack: true, | ||
}); | ||
break; | ||
case 'Sun': | ||
await this.setState(`Daily.Day${day}.Sunrise`, { | ||
val: json[key]['Rise'], | ||
ack: true, | ||
}); | ||
await this.setState(`Daily.Day${day}.Sunset`, { | ||
val: json[key]['Set'], | ||
ack: true, | ||
}); | ||
if (day === 1) { | ||
await this.setState('Summary.Sunrise', { | ||
val: json[key]['Rise'], | ||
ack: true, | ||
}); | ||
await this.setState('Summary.Sunset', { | ||
val: json[key]['Set'], | ||
ack: true, | ||
}); | ||
} | ||
break; | ||
case 'HoursOfSun': | ||
await this.setState(`Daily.Day${day}.HoursOfSun`, { | ||
val: json[key], | ||
ack: true, | ||
}); | ||
if (day === 1) { | ||
await this.setState('Summary.HoursOfSun', { | ||
val: json[key], | ||
ack: true, | ||
}); | ||
} | ||
break; | ||
case 'Temperature': | ||
await this.setState(`Daily.Day${day}.Temperature.Minimum`, { | ||
val: json[key]['Minimum'].Value, | ||
ack: true, | ||
}); | ||
await this.setState(`Daily.Day${day}.Temperature.Maximum`, { | ||
val: json[key]['Maximum'].Value, | ||
ack: true, | ||
}); | ||
await this.setState(`Summary.TempMin_d${day}`, { | ||
val: json[key]['Minimum'].Value, | ||
ack: true, | ||
}); | ||
await this.setState(`Summary.TempMax_d${day}`, { | ||
val: json[key]['Maximum'].Value, | ||
ack: true, | ||
}); | ||
break; | ||
case 'RealFeelTemperature': | ||
await this.setState(`Daily.Day${day}.RealFeelTemperature.Minimum`, { | ||
val: json[key]['Minimum'].Value, | ||
ack: true, | ||
}); | ||
await this.setState(`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.setState(`Daily.Day${day}.${key}.${key1}`, { | ||
val: json1[key1], | ||
ack: true, | ||
}); | ||
if (key1 === 'Icon') { | ||
await this.setState(`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.setState(`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.setState(`Summary.WeatherIconURL_d${day}`, { | ||
val: `http://vortex.accuweather.com/adc2010/images/slate/icons/${String(json1[key1]).padStart(2, '0')}.svg`, | ||
ack: true, | ||
}); | ||
await this.setState(`Summary.WeatherIcon_d${day}`, { | ||
val: json1[key1], | ||
ack: true, | ||
}); | ||
} | ||
} else if (key === 'Day') { | ||
if (key1 === 'IconPhrase') { | ||
await this.setState(`Summary.WeatherText_d${day}`, { | ||
val: json1[key1], | ||
ack: true, | ||
}); | ||
} else { | ||
await this.setState(`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.setState(`Daily.Day${day}.${key}.${key1}Volume`, { | ||
val: json1[key1].Value, | ||
ack: true, | ||
}); | ||
if (key === 'Day' && key1 === 'TotalLiquid') { | ||
await this.setState(`Summary.TotalLiquidVolume_d${day}`, { | ||
val: json1[key1].Value, | ||
ack: true, | ||
}); | ||
} | ||
} else { | ||
await this.setState(`Daily.Day${day}.${key}.${key1}`, { | ||
val: json1[key1].Value, | ||
ack: true, | ||
}); | ||
} | ||
} else if (key1 === 'Wind') { | ||
await this.setState(`Daily.Day${day}.${key}.WindSpeed`, { | ||
val: json1[key1].Speed.Value, | ||
ack: true, | ||
}); | ||
await this.setState(`Daily.Day${day}.${key}.WindDirection`, { | ||
val: json1[key1].Direction.Degrees, | ||
ack: true, | ||
}); | ||
if (key === 'Day') { | ||
await this.setState(`Summary.WindSpeed_d${day}`, { | ||
val: json1[key1].Speed.Value, | ||
ack: true, | ||
}); | ||
await this.setState(`Summary.WindDirection_d${day}`, { | ||
val: json1[key1].Direction.Degrees, | ||
ack: true, | ||
}); | ||
await this.setState(`Summary.WindDirectionStr_d${day}`, { | ||
val: this.getCardinalDirection(json1[key1].Direction.Degrees), | ||
ack: true, | ||
}); | ||
} | ||
} else if (key1 === 'WindGust') { | ||
await this.setState(`Daily.Day${day}.${key}.WindGust`, { | ||
val: json1[key1].Speed.Value, | ||
ack: true, | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
} | ||
} catch (err) { | ||
this.log.error(String(err)); | ||
} | ||
} | ||
async setNextHourStates(obj, item, hour) { | ||
const json = obj[item]; | ||
try { | ||
for (const key in json) { | ||
if (typeof json[key] !== 'object') { | ||
await this.setState(`Hourly.h${hour}.${key}`, { | ||
val: json[key], | ||
ack: true, | ||
}); | ||
if (key === 'WeatherIcon') { | ||
await this.setState(`Hourly.h${hour}.WeatherIconURL`, { | ||
val: `https://developer.accuweather.com/sites/default/files/${String(json[key]).padStart(2, '0')}-s.png`, | ||
ack: true, | ||
}); | ||
await this.setState(`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.setState(`Hourly.h${hour}.${key}Volume`, { | ||
val: json[key].Value, | ||
ack: true, | ||
}); | ||
} else { | ||
await this.setState(`Hourly.h${hour}.${key}`, { | ||
val: json[key].Value, | ||
ack: true, | ||
}); | ||
} | ||
} else if (key === 'Wind') { | ||
await this.setState(`Hourly.h${hour}.WindSpeed`, { | ||
val: json[key].Speed.Value, | ||
ack: true, | ||
}); | ||
await this.setState(`Hourly.h${hour}.WindDirection`, { | ||
val: json[key].Direction.Degrees, | ||
ack: true, | ||
}); | ||
await this.setState(`Hourly.h${hour}.WindDirectionText`, { | ||
val: json[key].Direction.Localized, | ||
ack: true, | ||
}); | ||
} else if (key === 'WindGust') { | ||
await this.setState(`Hourly.h${hour}.WindGust`, { | ||
val: json[key].Speed.Value, | ||
ack: true, | ||
}); | ||
} | ||
} | ||
} | ||
} catch (err) { | ||
this.log.error(String(err)); | ||
} | ||
} | ||
/** | ||
* Is called when databases are connected and adapter received configuration. | ||
*/ | ||
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.setState(`Current.${key}`, { val: json[key], ack: true }); | ||
async setDailyStates(obj) { | ||
const days = obj.DailyForecasts; | ||
try { | ||
for (let day = 1; day <= 5; day++) { | ||
let json = days[day - 1]; | ||
for (let key in json) { | ||
switch (key) { | ||
case "Date": | ||
await this.setStateAsync("Daily.Day" + day + "." + key, { val: json[key], 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 }); | ||
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 }); | ||
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": | ||
{ | ||
let json1 = json[key]; | ||
for (let 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 }); | ||
} | ||
//https://developer.accuweather.com/sites/default/files/36-s.png | ||
//http://vortex.accuweather.com/adc2010/images/slate/icons/1.svg | ||
} else | ||
if (typeof json1[key1] == "object") { | ||
if (key === 'WeatherIcon') { | ||
await this.setState('Current.WeatherIconURL', { | ||
val: `https://developer.accuweather.com/sites/default/files/${String(json[key]).padStart(2, '0')}-s.png`, | ||
ack: true, | ||
}); | ||
await this.setState('Current.WeatherIconURLS', { | ||
val: `http://vortex.accuweather.com/adc2010/images/slate/icons/${String(json[key]).padStart(2, '0')}.svg`, | ||
ack: true, | ||
}); | ||
await this.setState('Summary.WeatherIconURL', { | ||
val: `http://vortex.accuweather.com/adc2010/images/slate/icons/${String(json[key]).padStart(2, '0')}.svg`, | ||
ack: true, | ||
}); | ||
await this.setState('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.setState('Summary.CurrentDateTime', { | ||
val: json[key], | ||
ack: true, | ||
}); | ||
await this.setState('Summary.DayOfWeek', { val: dow, ack: true }); | ||
this.log.debug( | ||
`Date ${dt}, dow: ${dt.toLocaleString(this.config.language, { weekday: 'short' })}`, | ||
); | ||
} else { | ||
await this.setState(`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.setState(`Current.${key}`, { | ||
val: json[key].Metric.Value, | ||
ack: true, | ||
}); | ||
await this.setState(`Summary.${key}`, { | ||
val: json[key].Metric.Value, | ||
ack: true, | ||
}); | ||
} else if (key === 'Wind') { | ||
await this.setState('Current.WindSpeed', { | ||
val: json[key].Speed.Metric.Value, | ||
ack: true, | ||
}); | ||
await this.setState('Summary.WindSpeed', { | ||
val: json[key].Speed.Metric.Value, | ||
ack: true, | ||
}); | ||
await this.setState('Current.WindDirection', { | ||
val: json[key].Direction.Degrees, | ||
ack: true, | ||
}); | ||
await this.setState('Current.WindDirectionText', { | ||
val: json[key].Direction.Localized, | ||
ack: true, | ||
}); | ||
await this.setState('Summary.WindDirection', { | ||
val: json[key].Direction.Degrees, | ||
ack: true, | ||
}); | ||
await this.setState('Summary.WindDirectionStr', { | ||
val: this.getCardinalDirection(json[key].Direction.Degrees), | ||
ack: true, | ||
}); | ||
} else if (key === 'WindGust') { | ||
await this.setState('Current.WindGust', { | ||
val: json[key].Speed.Metric.Value, | ||
ack: true, | ||
}); | ||
} else if (key === 'PressureTendency') { | ||
await this.setState('Current.PressureTendency', { | ||
val: json[key].LocalizedText, | ||
ack: true, | ||
}); | ||
} | ||
} | ||
} | ||
} catch (err) { | ||
this.log.error(String(err)); | ||
} | ||
} | ||
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 }); | ||
} 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 }); | ||
} else | ||
if (key1 == "WindGust") { | ||
await this.setStateAsync("Daily.Day" + day + "." + key + ".WindGust", { val: json1[key1].Speed.Value, ack: true }); | ||
} | ||
} | ||
} | ||
} | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
} | ||
} catch (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 setNextHourStates(obj, item, hour) { | ||
const json = obj[item]; | ||
try { | ||
for (let 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") { | ||
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(String(err))); | ||
} | ||
} | ||
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 }); | ||
} else | ||
if (key == "WindGust") { | ||
await this.setStateAsync("Hourly.h" + hour + ".WindGust", { val: json[key].Speed.Value, ack: true }); | ||
} | ||
} | ||
} | ||
} 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)); | ||
} | ||
} | ||
async setCurrentStates(obj) { | ||
const json = obj[0]; | ||
try { | ||
for (let 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 }); | ||
} | ||
} | ||
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 }); | ||
} else | ||
if (key == "Wind") { | ||
await this.setStateAsync("Current.WindSpeed", { val: json[key].Speed.Metric.Value, ack: true }); | ||
await this.setStateAsync("Current.WindDirection", { val: 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 (err) { this.log.error(err); } | ||
} | ||
requestCurrent() { | ||
if (typeof this.forecast !== 'undefined') { | ||
const loc = this.config.loKey; | ||
const lang = this.config.language; | ||
setHourlyStates(obj) { | ||
for (let hr in obj) { | ||
if (typeof obj[hr] == "object" && obj[hr]["DateTime"]) { | ||
const d = new Date(obj[hr]["DateTime"]); | ||
this.setNextHourStates(obj, hr, d.getHours()); | ||
} | ||
} | ||
} | ||
this.forecast | ||
.localkey(loc) | ||
.timeInt() | ||
.language(lang) | ||
.metric(true) | ||
.details(true) | ||
.getCurrent() | ||
.then(res => this.setCurrentStates(res)) | ||
.catch(err => this.log.error(err)); | ||
} | ||
} | ||
requst5Days() { | ||
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.log.debug(JSON.stringify(res)); | ||
this.setDailyStates(res); | ||
}) | ||
.catch(err => { | ||
this.log.error(err); | ||
}); | ||
} | ||
} | ||
async onReady() { | ||
const nameSpaceObj = await this.getForeignObjectAsync(this.namespace); | ||
if (!nameSpaceObj) { | ||
await this.setForeignObject(this.namespace, { | ||
_id: this.namespace, | ||
type: 'meta', | ||
common: { name: 'Accuweather device', type: 'meta.folder' }, | ||
native: {}, | ||
}); | ||
} | ||
const obj = await this.getForeignObjectAsync(`system.adapter.${this.namespace}`); | ||
requst12Hours() { | ||
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.log.debug(JSON.stringify(res)); | ||
this.setHourlyStates(res); | ||
}) | ||
.catch(err => { | ||
this.log.error(err); | ||
}); | ||
} | ||
} | ||
if (obj && obj.native && obj.native.apiKey) { | ||
obj.native.apiKeyEncrypted = this.encrypt(obj.native.apiKey); | ||
this.config.apiKeyEncrypted = obj.native.apiKey; | ||
delete obj.native.apiKey; | ||
await this.setForeignObject(`system.adapter.${this.namespace}`, obj); | ||
} | ||
requstCurrent() { | ||
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.log.debug(JSON.stringify(res)); | ||
this.setCurrentStates(res); | ||
}) | ||
.catch(err => { | ||
this.log.error(err); | ||
}); | ||
} | ||
} | ||
if (!this.config.language) { | ||
const systemConfig = await this.getForeignObjectAsync('system.config'); | ||
if (systemConfig && systemConfig.common && systemConfig.common.language) { | ||
this.config.language = systemConfig.common.language; | ||
} | ||
} | ||
async onReady() { | ||
nextHour.createHourlyForecastObjects(this); | ||
nextHour.createCurrentConditionObjects(this); | ||
nextHour.createDailyForecastObjects(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}`); | ||
this.log.debug(`API: ********; 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.apiKeyEncrypted) { | ||
this.forecast = new AccuAPI(this.config.apiKeyEncrypted); | ||
} else { | ||
this.log.error('API Key is missing. Please enter Accuweather API key'); | ||
} | ||
setInterval(()=>{ | ||
const _this=this; | ||
const cdt=new Date(); | ||
if ((cdt.getHours()===7 || cdt.getHours()===20) && cdt.getMinutes() <=5 ) {setTimeout(()=>{_this.requst5Days();},Math.random()*10000+1);} | ||
if (cdt.getMinutes() <=5 && cdt.getMinutes() > 0) {setTimeout(()=>{_this.requstCurrent();},Math.random()*10000+1);} | ||
if ((cdt.getHours()===6 || cdt.getHours()===12 || cdt.getHours()===18 || cdt.getHours()===0) && cdt.getMinutes() <=5) {setTimeout(()=>{_this.requst12Hours();},Math.random()*10000+1);} | ||
}, 300000); | ||
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 | ||
if (!this.config.apiCallProtection) { | ||
this.request12Hours(); | ||
this.requestCurrent(); | ||
this.request5Days(); | ||
} else { | ||
this.log.info('The data has not been updated. The normal update cycle is running.'); | ||
} | ||
this.requst12Hours(); | ||
this.requstCurrent(); | ||
this.requst5Days(); | ||
/* | ||
setInterval(() => { | ||
this.requst12Hours(); | ||
}, 21600000); | ||
/* | ||
For every state in the system, there has to be also an object of type state | ||
Here a simple template for a boolean variable named "testVariable" | ||
Because every adapter instance uses its own unique namespace variable names can't collide with other adapters variables | ||
*/ | ||
setInterval(() => { | ||
this.requstCurrent(); | ||
}, 3600000); | ||
*/ | ||
//this.log.info(fres); | ||
//accu=require('./lib/accuapi')()('GqmgWXup3W4DSrGoHpGdB32MR9bSAlPI'); | ||
// Initialize your adapter here | ||
await this.extendObject('updateCurrent', { | ||
type: 'state', | ||
common: { | ||
name: 'Update Current Weather', | ||
type: 'boolean', | ||
role: 'button', | ||
read: false, | ||
write: true, | ||
}, | ||
native: {}, | ||
}); | ||
await this.extendObject('updateHourly', { | ||
type: 'state', | ||
common: { | ||
name: 'Update 12 Hours Forecast', | ||
type: 'boolean', | ||
role: 'button', | ||
read: false, | ||
write: true, | ||
}, | ||
native: {}, | ||
}); | ||
await this.extendObject('updateDaily', { | ||
type: 'state', | ||
common: { | ||
name: 'Update 5 Days Forecast', | ||
type: 'boolean', | ||
role: 'button', | ||
read: false, | ||
write: true, | ||
}, | ||
native: {}, | ||
}); | ||
// The adapters config (in the instance object everything under the attribute "native") is accessible via | ||
// this.config: | ||
//this.log.info("config option1: " + this.config.option1); | ||
//this.log.info("config option2: " + this.config.option2); | ||
// 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'); | ||
} | ||
/* | ||
For every state in the system there has to be also an object of type state | ||
Here a simple template for a boolean variable named "testVariable" | ||
Because every adapter instance uses its own unique namespace variable names can't collide with other adapters variables | ||
*/ | ||
/** | ||
* Is called when adapter shuts down - callback has to be called under any circumstances! | ||
* | ||
* @param callback - The callback function to be called when the unload process is complete | ||
*/ | ||
onUnload(callback) { | ||
try { | ||
this.log.info('cleaned everything up...'); | ||
updateInterval && clearInterval(updateInterval); | ||
updateInterval = null; | ||
await this.setObjectAsync("updateCurrent", { | ||
type: "state", | ||
common: { | ||
name: "Update Current Weather", | ||
type: "boolean", | ||
role: "button", | ||
read: true, | ||
write: true | ||
}, | ||
native: {}, | ||
}); | ||
await this.setObjectAsync("updateHourly", { | ||
type: "state", | ||
common: { | ||
name: "Update 12 Hours Forecast", | ||
type: "boolean", | ||
role: "button", | ||
read: true, | ||
write: true, | ||
}, | ||
native: {}, | ||
}); | ||
await this.setObjectAsync("updateDaily", { | ||
type: "state", | ||
common: { | ||
name: "Update 5 Days Forecast", | ||
type: "boolean", | ||
role: "button", | ||
read: true, | ||
write: true, | ||
}, | ||
native: {}, | ||
}); | ||
timeout1 && clearTimeout(timeout1); | ||
timeout1 = null; | ||
timeout2 && clearTimeout(timeout2); | ||
timeout2 = null; | ||
// in this template all states changes inside the adapters namespace are subscribed | ||
this.subscribeStates("update*"); | ||
callback(); | ||
callback = null; | ||
} catch { | ||
callback && callback(); | ||
} | ||
} | ||
/* | ||
setState examples | ||
you will notice that each setState will cause the stateChange event to fire (because of above subscribeStates cmd) | ||
*/ | ||
// the variable testVariable is set to true as command (ack=false) | ||
//await this.setStateAsync("testVariable", true); | ||
// same thing, but the value is flagged "ack" | ||
// ack should be always set to true if the value is received from or acknowledged from the target system | ||
//await this.setStateAsync("testVariable", { val: true, ack: true }); | ||
// same thing, but the state is deleted after 30s (getState will return null afterwards) | ||
//await this.setStateAsync("testVariable", { val: true, ack: true }); | ||
// examples for the checkPassword/checkGroup functions | ||
//let result = await this.checkPasswordAsync("admin", "iobroker"); | ||
//this.log.info("check user admin pw ioboker: " + result); | ||
//result = await this.checkGroupAsync("admin", "admin"); | ||
//this.log.info("check group user admin group admin: " + result); | ||
} | ||
/** | ||
* 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..."); | ||
callback(); | ||
} catch (e) { | ||
callback(); | ||
} | ||
} | ||
/** | ||
* Is called if a subscribed object changes | ||
* @param {string} id | ||
* @param {ioBroker.Object | null | undefined} obj | ||
*/ | ||
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 | ||
* @param {string} id | ||
* @param {ioBroker.State | null | undefined} state | ||
*/ | ||
onStateChange(id, state) { | ||
if (state) { | ||
// The state was changed | ||
if (id.indexOf("updateCurrent")) {this.requstCurrent();} else | ||
if (id.indexOf("updateHourly")) {this.requst12Hours();} else | ||
if (id.indexOf("updateDaily")) {this.requst5Days();} | ||
this.log.debug(`state ${id} changed: ${state.val} (ack = ${state.ack})`); | ||
} else { | ||
// The state was deleted | ||
this.log.debug(`state ${id} deleted`); | ||
} | ||
} | ||
// /** | ||
// * Some message was sent to this instance over message box. Used by email, pushover, text2speech, ... | ||
// * Using this method requires "common.message" property to be set to true in io-package.json | ||
// * @param {ioBroker.Message} obj | ||
// */ | ||
// onMessage(obj) { | ||
// if (typeof obj === "object" && obj.message) { | ||
// if (obj.command === "send") { | ||
// // e.g. send email or pushover or whatever | ||
// this.log.info("send command"); | ||
// // Send response in callback if required | ||
// if (obj.callback) this.sendTo(obj.from, obj.command, "Message received", obj.callback); | ||
// } | ||
// } | ||
// } | ||
/** | ||
* Is called if a subscribed state changes | ||
* | ||
* @param id - The id of the state that changed | ||
* @param state - The state object that changed | ||
*/ | ||
onStateChange(id, state) { | ||
if (state) { | ||
if (!state.ack) { | ||
// 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`); | ||
} | ||
} | ||
} | ||
// @ts-ignore parent is a valid property on module | ||
// @ts-expect-error parent is a valid property on module | ||
if (module.parent) { | ||
// Export the constructor in compact mode | ||
/** | ||
* @param {Partial<ioBroker.AdapterOptions>} [options={}] | ||
*/ | ||
module.exports = (options) => new Accuweather(options); | ||
// Export the constructor in compact mode | ||
/** | ||
* @param [options] - Optional settings for the adapter instance | ||
*/ | ||
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": "2.0.0", | ||
"version": "2.0.1", | ||
"description": "Weather forecast using AccuWeather API", | ||
@@ -9,5 +9,6 @@ "author": { | ||
}, | ||
"homepage": "https://github.com/algar42/ioBroker.accuweather", | ||
"homepage": "https://github.com/iobroker-community-adapters/ioBroker.accuweather", | ||
"license": "MIT", | ||
"keywords": [ | ||
"ioBroker", | ||
"Weather", | ||
@@ -19,47 +20,65 @@ "AccuWeather", | ||
"type": "git", | ||
"url": "https://github.com/algar42/ioBroker.accuweather" | ||
"url": "https://github.com/iobroker-community-adapters/ioBroker.accuweather" | ||
}, | ||
"engines": { | ||
"node": ">=20" | ||
}, | ||
"dependencies": { | ||
"@iobroker/adapter-core": "^1.0.3", | ||
"query-string": "^6.8.3", | ||
"request": "^2.88.0" | ||
"@iobroker/adapter-core": "^3.2.3", | ||
"axios": "^1.7.9", | ||
"qs": "^6.14.0" | ||
}, | ||
"devDependencies": { | ||
"@iobroker/testing": "^1.2.5", | ||
"@types/chai": "^4.2.0", | ||
"@types/chai-as-promised": "^7.1.2", | ||
"@types/gulp": "^4.0.6", | ||
"@types/mocha": "^5.2.7", | ||
"@types/node": "^10.14.17", | ||
"@types/proxyquire": "^1.3.28", | ||
"@types/sinon": "^7.0.13", | ||
"@types/sinon-chai": "^3.2.3", | ||
"axios": "^0.19.0", | ||
"chai": "^4.2.0", | ||
"chai-as-promised": "^7.1.1", | ||
"colors": "^1.3.3", | ||
"eslint": "^6.2.2", | ||
"gulp": "^4.0.2", | ||
"mocha": "^6.2.0", | ||
"@alcalzone/release-script": "^3.8.0", | ||
"@alcalzone/release-script-plugin-iobroker": "^3.7.2", | ||
"@alcalzone/release-script-plugin-license": "^3.7.0", | ||
"@alcalzone/release-script-plugin-manual-review": "^3.7.0", | ||
"@iobroker/adapter-dev": "^1.3.0", | ||
"@iobroker/eslint-config": "^1.0.0", | ||
"@iobroker/testing": "^5.0.0", | ||
"@tsconfig/node20": "^20.1.4", | ||
"@types/axios": "^0.9.36", | ||
"@types/chai": "^4.3.11", | ||
"@types/chai-as-promised": "^8.0.1", | ||
"@types/gulp": "^4.0.17", | ||
"@types/mocha": "^10.0.8", | ||
"@types/node": "^22.10.3", | ||
"@types/proxyquire": "^1.3.31", | ||
"@types/sinon": "^17.0.3", | ||
"@types/sinon-chai": "^3.2.12", | ||
"chai": "^4.5.0", | ||
"chai-as-promised": "^8.0.1", | ||
"colors": "1.4.0", | ||
"mocha": "^11.0.1", | ||
"proxyquire": "^2.1.3", | ||
"sinon": "^7.4.1", | ||
"sinon-chai": "^3.3.0", | ||
"ts-node": "^8.3.0", | ||
"typescript": "^3.6.3" | ||
"sinon": "^19.0.2", | ||
"sinon-chai": "^3.7.0", | ||
"typescript": "^5.7.2" | ||
}, | ||
"main": "main.js", | ||
"files": [ | ||
"admin/", | ||
"lib/", | ||
"main.js", | ||
"io-package.json", | ||
"LICENSE" | ||
], | ||
"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", | ||
"release": "node --require ts-node/register maintenance/release.ts", | ||
"build": "tsc -p tsconfig.build.json", | ||
"lint": "eslint" | ||
"check": "tsc --noEmit -p tsconfig.check.json", | ||
"lint": "eslint -c eslint.config.mjs .", | ||
"translate": "translate-adapter", | ||
"release": "release-script", | ||
"update-packages": "ncu --upgrade" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/algar42/ioBroker.accuweather/issues" | ||
"url": "https://github.com/iobroker-community-adapters/ioBroker.accuweather/issues" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"readmeFilename": "README.md" | ||
} |
100
README.md
![Logo](admin/accuweather.png) | ||
# ioBroker.accuweather | ||
[![NPM version](http://img.shields.io/npm/v/iobroker.accuweather.svg)](https://www.npmjs.com/package/iobroker.accuweather) | ||
![Number of Installations](http://iobroker.live/badges/accuweather-installed.svg) ![Number of Installations](http://iobroker.live/badges/accuweather-stable.svg) [![NPM version](http://img.shields.io/npm/v/iobroker.accuweather.svg)](https://www.npmjs.com/package/iobroker.accuweather) | ||
[![Downloads](https://img.shields.io/npm/dm/iobroker.accuweather.svg)](https://www.npmjs.com/package/iobroker.accuweather) | ||
[![Dependency Status](https://img.shields.io/david/algar42/iobroker.accuweather.svg)](https://david-dm.org/algar42/iobroker.accuweather) | ||
[![Known Vulnerabilities](https://snyk.io/test/github/algar42/ioBroker.accuweather/badge.svg)](https://snyk.io/test/github/algar42/ioBroker.accuweather) | ||
[![NPM](https://nodei.co/npm/iobroker.accuweather.png?downloads=true)](https://nodei.co/npm/iobroker.accuweather/) | ||
**Tests:**: [![Travis-CI](http://img.shields.io/travis/algar42/ioBroker.accuweather/master.svg)](https://travis-ci.org/algar42/ioBroker.accuweather) | ||
## accuweather adapter for ioBroker | ||
Weather forecast using AccuWeather API. | ||
Weather forecast using AccuWeather API | ||
Adapter receives | ||
- Current Conditions (updated every hour), (24 requests) | ||
- 5 Days daily forecast (update daily at approximately 7am and 8pm), (2 requests) | ||
- and 12 hours forecast (updated every six hours at 12am, 6am, 12pm and 6pm). (4 requests) | ||
Adapter receives Current Conditions (updated every hour), 5 Days daily forecast (update once daily at approximately 7am), and 12 hours forecast (updated every six hours at 12am, 6am, 12pm and 6pm). | ||
By default, the adapter does not update any data when restarting. | ||
Please adjust this in the configuration. 50 requests per day are allowed, each restart would require 3 requests to update all data. | ||
@@ -22,24 +23,87 @@ ## Getting started | ||
### Get API Key | ||
To get API Key, register on https://developer.accuweather.com/ and create application in `My Apps` menu. | ||
Once the application is created, you will have an API key generated. | ||
For free use, it is possible to make 50 requests to API per day. | ||
It was noted that to get the API working, the following settings are preferred (please choose your country!): | ||
![settings](admin/image.png) | ||
To get API Key, register on https://developer.accuweather.com/ and create application in \"My Apps\" menu. Once application created you will have API key generated. | ||
For free use it is possible to make 50 requests to API per day. | ||
### Get Location Key | ||
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) as you have them, e.g., in ioBroker settings. | ||
Your location key will be the number at the end of the forecast URL. | ||
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) as you have them e.g. in IoBroker settings. | ||
Your location key wil be the number at the end of URL of forecast. | ||
### Using in Lovelace visualization (starting version 1.1.0) | ||
The summary channel contains a current and by-day forecast with role/types of states supported by type-detector. | ||
New feature can be used in order to show weather forecast in Lovelace UI. | ||
For better view a custom lovelace card is created - see https://github.com/algar42/IoB.lovelace.accuweather-card | ||
## Changelog | ||
### 0.1.0 | ||
* (algar42) First release | ||
<!-- | ||
Placeholder for the next version (at the beginning of the line): | ||
### **WORK IN PROGRESS** | ||
--> | ||
### 2.0.1 (2025-01-18) | ||
* (ticaki) BREAKING: Requires Nodejs 20 or higher | ||
* (ticaki) BREAKING: Command states are now buttons and only respond to ack=false. | ||
* (ticaki) admin option: No data is updated on adapter startup (default: true). | ||
* (ticaki) apikey renamed and encrypted | ||
* (ticaki) Dependencies and eslint updated | ||
* (devtronic) Add nextHour.CloudCover | ||
### 0.0.1 | ||
* (algar42) initial commit | ||
### 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) | ||
* (mcm1957) Adapter requires node.js 18 and js-controller >= 5 now | ||
* (mcm1957) Dependencies have been updated | ||
### 1.3.2 (2023-12-04) | ||
* (ticaki) fixed: dependencies | ||
* (ticaki) fixed: error message [object Object] | ||
### 1.3.1 (2023-08-15) | ||
* (isi07) added the Wind Direction Text und Cloud Cover | ||
* (bluefox) Added json config | ||
### 1.2.4 (2022-02-08) | ||
* (algar42) Depency updates | ||
### 1.2.3 (2021-12-29) | ||
* (algar42) HoursOfSun Parameter added to the Daily forecast | ||
### 1.2.1 (2021-07-22) | ||
* (bluefox) Updated logo | ||
### 1.2.0 (2021-07-03) | ||
* (Garfonso) adjust roles to properly detect weather forecast in Summary folder. (Summary objects need to be deleted and adapter restarted after that) | ||
### 1.1.7 (2021-06-24) | ||
* (bluefox) Create device for device-detector | ||
### v1.1.6 (2021-05-05) | ||
Minor bug fixes to `Object.common` section | ||
### 1.1.5 (2021-01-25) | ||
* (algar42) Resolve log Warning for js-controller 3.2 | ||
### 1.1.4 | ||
* (HGlab01) small bugfix regarding setTimeout range | ||
### 1.1.3 (2020-03-04) | ||
* (algar42) Minor updates for compact mode | ||
### 1.1.0 (2019-11-09) | ||
* (algar42) Summary channel added to support type-detector and automatic weather device creation | ||
### 1.0.2 (2019-09-12) | ||
* (algar42) Production Release | ||
## License | ||
MIT License | ||
Copyright (c) 2019 algar42 <igor.aleschenkov@gmail.com> | ||
Copyright (c) 2024-2025 iobroker-community-adapters <iobroker-community-adapters@gmx.de> | ||
Copyright (c) 2021-2023 algar42 <igor.aleschenkov@gmail.com> | ||
@@ -46,0 +110,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
204099
32
2925
126
25
1
+ Addedaxios@^1.7.9
+ Addedqs@^6.14.0
+ Added@iobroker/adapter-core@3.2.3(transitive)
+ Added@iobroker/types@7.0.6(transitive)
+ Addedaxios@1.7.9(transitive)
+ Addedcall-bind-apply-helpers@1.0.1(transitive)
+ Addedcall-bound@1.0.3(transitive)
+ Addeddunder-proto@1.0.1(transitive)
+ Addedes-define-property@1.0.1(transitive)
+ Addedes-errors@1.3.0(transitive)
+ Addedes-object-atoms@1.1.1(transitive)
+ Addedfollow-redirects@1.15.9(transitive)
+ Addedform-data@4.0.1(transitive)
+ Addedfunction-bind@1.1.2(transitive)
+ Addedget-intrinsic@1.2.7(transitive)
+ Addedget-proto@1.0.1(transitive)
+ Addedgopd@1.2.0(transitive)
+ Addedhas-symbols@1.1.0(transitive)
+ Addedhasown@2.0.2(transitive)
+ Addedmath-intrinsics@1.1.0(transitive)
+ Addedobject-inspect@1.13.4(transitive)
+ Addedproxy-from-env@1.1.0(transitive)
+ Addedqs@6.14.0(transitive)
+ Addedside-channel@1.1.0(transitive)
+ Addedside-channel-list@1.0.0(transitive)
+ Addedside-channel-map@1.0.1(transitive)
+ Addedside-channel-weakmap@1.0.2(transitive)
- Removedquery-string@^6.8.3
- Removedrequest@^2.88.0
- Removed@iobroker/adapter-core@1.0.3(transitive)
- Removed@types/iobroker@1.4.13(transitive)
- Removed@types/node@22.13.1(transitive)
- Removedajv@6.12.6(transitive)
- Removedasn1@0.2.6(transitive)
- Removedassert-plus@1.0.0(transitive)
- Removedaws-sign2@0.7.0(transitive)
- Removedaws4@1.13.2(transitive)
- Removedbcrypt-pbkdf@1.0.2(transitive)
- Removedcaseless@0.12.0(transitive)
- Removedcore-util-is@1.0.2(transitive)
- Removeddashdash@1.14.1(transitive)
- Removeddecode-uri-component@0.2.2(transitive)
- Removedecc-jsbn@0.1.2(transitive)
- Removedextend@3.0.2(transitive)
- Removedextsprintf@1.3.0(transitive)
- Removedfast-deep-equal@3.1.3(transitive)
- Removedfast-json-stable-stringify@2.1.0(transitive)
- Removedfilter-obj@1.1.0(transitive)
- Removedforever-agent@0.6.1(transitive)
- Removedform-data@2.3.3(transitive)
- Removedgetpass@0.1.7(transitive)
- Removedhar-schema@2.0.0(transitive)
- Removedhar-validator@5.1.5(transitive)
- Removedhttp-signature@1.2.0(transitive)
- Removedis-typedarray@1.0.0(transitive)
- Removedisstream@0.1.2(transitive)
- Removedjsbn@0.1.1(transitive)
- Removedjson-schema@0.4.0(transitive)
- Removedjson-schema-traverse@0.4.1(transitive)
- Removedjson-stringify-safe@5.0.1(transitive)
- Removedjsprim@1.4.2(transitive)
- Removedoauth-sign@0.9.0(transitive)
- Removedperformance-now@2.1.0(transitive)
- Removedpsl@1.15.0(transitive)
- Removedpunycode@2.3.1(transitive)
- Removedqs@6.5.3(transitive)
- Removedquery-string@6.14.1(transitive)
- Removedrequest@2.88.2(transitive)
- Removedsafe-buffer@5.2.1(transitive)
- Removedsafer-buffer@2.1.2(transitive)
- Removedsplit-on-first@1.1.0(transitive)
- Removedsshpk@1.18.0(transitive)
- Removedstrict-uri-encode@2.0.0(transitive)
- Removedtough-cookie@2.5.0(transitive)
- Removedtunnel-agent@0.6.0(transitive)
- Removedtweetnacl@0.14.5(transitive)
- Removedundici-types@6.20.0(transitive)
- Removeduri-js@4.4.1(transitive)
- Removeduuid@3.4.0(transitive)
- Removedverror@1.10.0(transitive)