Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
976c611f97 | ||
|
|
3887500a62 | ||
|
|
62ef7cabf8 | ||
|
|
8fc6f4ac01 | ||
|
|
649bdfce2f | ||
|
|
e0fcc28746 | ||
|
|
71813c2df9 | ||
|
|
ac8d3617b0 | ||
|
|
2986071d2e | ||
|
|
56a9cbbb1c | ||
|
|
5a8e22b408 | ||
|
|
1c46a7772f | ||
|
|
659152be2e | ||
|
|
ad8f360c17 | ||
|
|
88d027d575 | ||
|
|
9727116d46 | ||
|
|
03fba79027 | ||
|
|
50fd571f0b | ||
|
|
39bd989a41 | ||
|
|
407b5bfb07 | ||
|
|
cdc3aba0b2 | ||
|
|
8a2933411f | ||
|
|
68c6bd989f | ||
|
|
e03a2cfc80 | ||
|
|
9558c39deb | ||
|
|
2956ee506a | ||
|
|
62ce173d22 | ||
|
|
45b0550e0c | ||
|
|
0ac6c66aaf |
@@ -12,5 +12,5 @@ updates:
|
|||||||
interval: monthly
|
interval: monthly
|
||||||
time: "04:00"
|
time: "04:00"
|
||||||
timezone: Europe/Berlin
|
timezone: Europe/Berlin
|
||||||
open-pull-requests-limit: 20
|
open-pull-requests-limit: 5
|
||||||
versioning-strategy: increase
|
versioning-strategy: increase
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
name: "CodeQL"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "master" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "master" ]
|
||||||
|
schedule:
|
||||||
|
- cron: "4 5 * * 5"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: [ javascript ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
queries: +security-and-quality
|
||||||
|
|
||||||
|
- name: Autobuild
|
||||||
|
uses: github/codeql-action/autobuild@v2
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v2
|
||||||
|
with:
|
||||||
|
category: "/language:${{ matrix.language }}"
|
||||||
@@ -16,6 +16,10 @@ on:
|
|||||||
- "v?[0-9]+.[0-9]+.[0-9]+-**"
|
- "v?[0-9]+.[0-9]+.[0-9]+-**"
|
||||||
pull_request: {}
|
pull_request: {}
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Performs quick checks before the expensive test runs
|
# Performs quick checks before the expensive test runs
|
||||||
check-and-lint:
|
check-and-lint:
|
||||||
@@ -25,7 +29,7 @@ jobs:
|
|||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [12.x]
|
node-version: [16.x]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -36,7 +40,7 @@ jobs:
|
|||||||
|
|
||||||
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm install
|
run: npm ci
|
||||||
|
|
||||||
# - name: Perform a type check
|
# - name: Perform a type check
|
||||||
# run: npm run check:ts
|
# run: npm run check:ts
|
||||||
@@ -67,7 +71,7 @@ jobs:
|
|||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm install
|
run: npm ci
|
||||||
|
|
||||||
- name: Run local tests
|
- name: Run local tests
|
||||||
run: npm test
|
run: npm test
|
||||||
@@ -92,7 +96,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [12.x]
|
node-version: [16.x]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -118,7 +122,7 @@ jobs:
|
|||||||
echo "::set-output name=BODY::$BODY"
|
echo "::set-output name=BODY::$BODY"
|
||||||
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm install
|
run: npm ci
|
||||||
|
|
||||||
# - name: Create a clean build
|
# - name: Create a clean build
|
||||||
# run: npm run build
|
# run: npm run build
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
/**/*
|
/**/*
|
||||||
/gulpfile.js
|
|
||||||
gulpfile.js
|
|
||||||
!/admin/**/*
|
!/admin/**/*
|
||||||
!/admin/*
|
!/admin/*
|
||||||
!/lib/**/*
|
!/lib/**/*
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2018-2022 bluefox <dogafox@gmail.com>
|
Copyright (c) 2018-2023 bluefox <dogafox@gmail.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -18,10 +18,19 @@ This adapter allows the connecting of Home Assistant to ioBroker.
|
|||||||
Create a long term token in HASS and use it as PW (copy it also in the repeat field).
|
Create a long term token in HASS and use it as PW (copy it also in the repeat field).
|
||||||
|
|
||||||
Then it should read out all attributes for all devices. Services might be controllable (e.g. "turn_on"). To control services you have two options:
|
Then it should read out all attributes for all devices. Services might be controllable (e.g. "turn_on"). To control services you have two options:
|
||||||
* Set the state with an ack=false value which is not a string (e.g. Boolean true) then it will be triggered also in HASS without additional service data
|
|
||||||
* Set the state with an ack=false String value which is a stringified JSON object to call the service and use the JSON object as service data
|
|
||||||
|
|
||||||
For the last option on a light.turn_off with e.g. `{"transition":10,"flash":"short"}` these two service data details are sent with the call to HASS. The available fields with their data definition can be seen in the JSON definition of the ioBroker object in the native.fields section and would look like the following in the above example:
|
### Set a direct value
|
||||||
|
Set the state with an ack=false value which is not a string (e.g. Boolean true) then it will be triggered also in HASS without additional service data. This will only work if the service has one field to be sent - then the value is sent as this field! If the service has more than one field you will find a warning in the log that provides more details about the fields taht are possible to be sent, e.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
Please make sure to provide a stringified JSON as value to set relevant fields! Please refer to the Readme for details!
|
||||||
|
Allowed field keys are: temperature, target_temp_high, target_temp_low, hvac_mode
|
||||||
|
```
|
||||||
|
|
||||||
|
### Set a stringified JSON to provide one or multiple fields
|
||||||
|
Set the state with an ack=false String value which is a stringified JSON object to call the service and use the JSON object as service data
|
||||||
|
|
||||||
|
For the last option on a light.turn_off with e.g. `{"transition":10,"flash":"short"}` these two service data details are sent with the call to HASS. The available fields with their exact data definition can be seen in the JSON definition of the ioBroker object in the native.fields section and would look like the following in the above example:
|
||||||
|
|
||||||
`
|
`
|
||||||
...
|
...
|
||||||
@@ -93,6 +102,14 @@ Please check it https://www.smarthomejetzt.de/mit-iobroker-auf-eine-home-assista
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
### 1.4.0 (2023-01-03)
|
||||||
|
* (Apollon77) Added more guidance logging when setting services incorrectly
|
||||||
|
* (Apollon77) Prevent crashes when attributes contain "." at the end of their names
|
||||||
|
* (Apollon77) Added logging for state updates for unknown objects
|
||||||
|
|
||||||
|
### 1.3.0 (2022-07-01)
|
||||||
|
* (Apollon77) Further optimize sending data to HASS and allow to set values like numbers as normal states if the service has one attribute and it can be mapped
|
||||||
|
|
||||||
### 1.2.0 (2022-06-17)
|
### 1.2.0 (2022-06-17)
|
||||||
* (Apollon77) IMPORTANT: Replace special characters in entity attribute names with an underscore! Object IDs might change!
|
* (Apollon77) IMPORTANT: Replace special characters in entity attribute names with an underscore! Object IDs might change!
|
||||||
* (Apollon77) make sure a "null" value in state changes is not crashing
|
* (Apollon77) make sure a "null" value in state changes is not crashing
|
||||||
@@ -123,7 +140,7 @@ Please check it https://www.smarthomejetzt.de/mit-iobroker-auf-eine-home-assista
|
|||||||
## License
|
## License
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2018-2022 bluefox <dogafox@gmail.com>
|
Copyright (c) 2018-2023 bluefox <dogafox@gmail.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -5,4 +5,4 @@
|
|||||||
"Password:": "Clave:",
|
"Password:": "Clave:",
|
||||||
"Passwords missmatch!": "¡Las contraseñas no coinciden!",
|
"Passwords missmatch!": "¡Las contraseñas no coinciden!",
|
||||||
"Secure:": "¿HTTPS?:"
|
"Secure:": "¿HTTPS?:"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Home assistant IP:": "Домашній помічник IP:",
|
||||||
|
"Home assistant WS Port:": "Домашній помічник WS Порт:",
|
||||||
|
"Password repeat:": "Повторення пароля:",
|
||||||
|
"Password:": "Пароль:",
|
||||||
|
"Passwords missmatch!": "Паролі не збігаються!",
|
||||||
|
"Secure:": "HTTPS?"
|
||||||
|
}
|
||||||
+13
-7
@@ -1,11 +1,17 @@
|
|||||||
/*global systemDictionary:true */
|
/*global systemDictionary:true */
|
||||||
|
/*
|
||||||
|
+===================== DO NOT MODIFY ======================+
|
||||||
|
| This file was generated by translate-adapter, please use |
|
||||||
|
| `translate-adapter adminLanguages2words` to update it. |
|
||||||
|
+===================== DO NOT MODIFY ======================+
|
||||||
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
systemDictionary = {
|
systemDictionary = {
|
||||||
"Home assistant IP:": { "en": "Home assistant IP:", "de": "IP-Adresse des Heimassistenten:", "ru": "Домашний помощник IP:", "pt": "IP do assistente doméstico:", "nl": "Thuisassistent IP:", "fr": "IP de l'assistant à domicile :", "it": "IP assistente domestico:", "es": "IP del asistente de hogar:", "pl": "Adres IP asystenta domowego:", "zh-cn": "家庭助理IP:"},
|
"Home assistant IP:": { "en": "Home assistant IP:", "de": "IP-Adresse des Heimassistenten:", "ru": "Домашний помощник IP:", "pt": "IP do assistente doméstico:", "nl": "Thuisassistent IP:", "fr": "IP de l'assistant à domicile :", "it": "IP assistente domestico:", "es": "IP del asistente de hogar:", "pl": "Adres IP asystenta domowego:", "uk": "Домашній помічник IP:", "zh-cn": "家庭助理IP:"},
|
||||||
"Home assistant WS Port:": { "en": "Home assistant WS Port:", "de": "Home Assistant WS-Port:", "ru": "Домашний помощник WS Порт:", "pt": "Assistente doméstico Porta WS:", "nl": "Thuisassistent WS Poort:", "fr": "Port WS de l'assistant domestique :", "it": "Porta WS dell'assistente domestico:", "es": "Asistente doméstico Puerto WS:", "pl": "Asystent domowy Port WS:", "zh-cn": "家庭助理 WS 端口:"},
|
"Home assistant WS Port:": { "en": "Home assistant WS Port:", "de": "Home Assistant WS-Port:", "ru": "Домашний помощник WS Порт:", "pt": "Assistente doméstico Porta WS:", "nl": "Thuisassistent WS Poort:", "fr": "Port WS de l'assistant domestique :", "it": "Porta WS dell'assistente domestico:", "es": "Asistente doméstico Puerto WS:", "pl": "Asystent domowy Port WS:", "uk": "Домашній помічник WS Порт:", "zh-cn": "家庭助理 WS 端口:"},
|
||||||
"Password repeat:": { "en": "Password repeat:", "de": "Passwort wiederholen:", "ru": "Повтор пароля:", "pt": "Repetição de senha:", "nl": "Wachtwoord herhalen:", "fr": "Répéter le mot de passe :", "it": "Ripeti password:", "es": "Repite la contraseña:", "pl": "Powtórz hasło:", "zh-cn": "密码重复:"},
|
"Password repeat:": { "en": "Password repeat:", "de": "Passwort wiederholen:", "ru": "Повтор пароля:", "pt": "Repetição de senha:", "nl": "Wachtwoord herhalen:", "fr": "Répéter le mot de passe :", "it": "Ripeti password:", "es": "Repite la contraseña:", "pl": "Powtórz hasło:", "uk": "Повторення пароля:", "zh-cn": "密码重复:"},
|
||||||
"Password:": { "en": "Password:", "de": "Passwort:", "ru": "Пароль:", "pt": "Senha:", "nl": "Wachtwoord:", "fr": "Mot de passe:", "it": "Parola d'ordine:", "es": "Clave:", "pl": "Hasło:", "zh-cn": "密码:"},
|
"Password:": { "en": "Password:", "de": "Passwort:", "ru": "Пароль:", "pt": "Senha:", "nl": "Wachtwoord:", "fr": "Mot de passe:", "it": "Parola d'ordine:", "es": "Clave:", "pl": "Hasło:", "uk": "Пароль:", "zh-cn": "密码:"},
|
||||||
"Passwords missmatch!": { "en": "Passwords missmatch!", "de": "Passwörter stimmen nicht überein!", "ru": "Пароли не совпадают!", "pt": "As senhas não correspondem!", "nl": "Wachtwoorden komen niet overeen!", "fr": "Les mots de passe ne correspondent pas !", "it": "Le password non corrispondono!", "es": "¡Las contraseñas no coinciden!", "pl": "Niezgodność haseł!", "zh-cn": "密码不匹配!"},
|
"Passwords missmatch!": { "en": "Passwords missmatch!", "de": "Passwörter stimmen nicht überein!", "ru": "Пароли не совпадают!", "pt": "As senhas não correspondem!", "nl": "Wachtwoorden komen niet overeen!", "fr": "Les mots de passe ne correspondent pas !", "it": "Le password non corrispondono!", "es": "¡Las contraseñas no coinciden!", "pl": "Niezgodność haseł!", "uk": "Паролі не збігаються!", "zh-cn": "密码不匹配!"},
|
||||||
"Secure:": { "en": "HTTPS?", "de": "HTTPS?", "ru": "HTTPS?", "pt": "HTTPS?", "nl": "HTTPS?", "fr": "HTTPS ?", "it": "HTTPS?", "es": "¿HTTPS?", "pl": "HTTPS?", "zh-cn": "HTTPS?"},
|
"Secure:": { "en": "HTTPS?", "de": "HTTPS?", "ru": "HTTPS?", "pt": "HTTPS?", "nl": "HTTPS?", "fr": "HTTPS ?", "it": "HTTPS?", "es": "¿HTTPS?:", "pl": "HTTPS?", "uk": "HTTPS?", "zh-cn": "HTTPS?"},
|
||||||
};
|
};
|
||||||
-337
@@ -1,337 +0,0 @@
|
|||||||
/*!
|
|
||||||
* ioBroker gulpfile
|
|
||||||
* Date: 2019-01-28
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const gulp = require('gulp');
|
|
||||||
const fs = require('fs');
|
|
||||||
const pkg = require('./package.json');
|
|
||||||
const iopackage = require('./io-package.json');
|
|
||||||
const version = (pkg && pkg.version) ? pkg.version : iopackage.common.version;
|
|
||||||
const fileName = 'words.js';
|
|
||||||
const EMPTY = '';
|
|
||||||
const translate = require('./lib/tools').translateText;
|
|
||||||
const languages = {
|
|
||||||
en: {},
|
|
||||||
de: {},
|
|
||||||
ru: {},
|
|
||||||
pt: {},
|
|
||||||
nl: {},
|
|
||||||
fr: {},
|
|
||||||
it: {},
|
|
||||||
es: {},
|
|
||||||
pl: {},
|
|
||||||
'zh-cn': {}
|
|
||||||
};
|
|
||||||
|
|
||||||
function lang2data(lang) {
|
|
||||||
let str ='{\n';
|
|
||||||
let count = 0;
|
|
||||||
for (const w in lang) {
|
|
||||||
if (lang.hasOwnProperty(w)) {
|
|
||||||
count++;
|
|
||||||
const key = ' "' + w.replace(/"/g, '\\"') + '": ';
|
|
||||||
str += key + '"' + lang[w].replace(/"/g, '\\"') + '",\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!count) {
|
|
||||||
return '{\n}';
|
|
||||||
} else {
|
|
||||||
return str.substring(0, str.length - 2) + '\n}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function readWordJs(src) {
|
|
||||||
try {
|
|
||||||
let words;
|
|
||||||
if (fs.existsSync(src + 'js/' + fileName)) {
|
|
||||||
words = fs.readFileSync(src + 'js/' + fileName).toString();
|
|
||||||
} else {
|
|
||||||
words = fs.readFileSync(src + fileName).toString();
|
|
||||||
}
|
|
||||||
words = words.substring(words.indexOf('{'), words.length);
|
|
||||||
words = words.substring(0, words.lastIndexOf(';'));
|
|
||||||
|
|
||||||
const resultFunc = new Function('return ' + words + ';');
|
|
||||||
|
|
||||||
return resultFunc();
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function padRight(text, totalLength) {
|
|
||||||
return text + (text.length < totalLength ? new Array(totalLength - text.length).join(' ') : '');
|
|
||||||
}
|
|
||||||
|
|
||||||
function writeWordJs(data, src) {
|
|
||||||
let text = '';
|
|
||||||
text += '/*global systemDictionary:true */\n';
|
|
||||||
text += "'use strict';\n\n";
|
|
||||||
text += 'systemDictionary = {\n';
|
|
||||||
for (const word in data) {
|
|
||||||
if (data.hasOwnProperty(word)) {
|
|
||||||
text += ' ' + padRight('"' + word.replace(/"/g, '\\"') + '": {', 50);
|
|
||||||
let line = '';
|
|
||||||
for (const lang in data[word]) {
|
|
||||||
if (data[word].hasOwnProperty(lang)) {
|
|
||||||
line += '"' + lang + '": "' + padRight(data[word][lang].replace(/"/g, '\\"') + '",', 50) + ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (line) {
|
|
||||||
line = line.trim();
|
|
||||||
line = line.substring(0, line.length - 1);
|
|
||||||
}
|
|
||||||
text += line + '},\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
text += '};';
|
|
||||||
if (fs.existsSync(src + 'js/' + fileName)) {
|
|
||||||
fs.writeFileSync(src + 'js/' + fileName, text);
|
|
||||||
} else {
|
|
||||||
fs.writeFileSync(src + '' + fileName, text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function words2languages(src) {
|
|
||||||
const langs = Object.assign({}, languages);
|
|
||||||
const data = readWordJs(src);
|
|
||||||
if (data) {
|
|
||||||
for (const word in data) {
|
|
||||||
if (data.hasOwnProperty(word)) {
|
|
||||||
for (const lang in data[word]) {
|
|
||||||
if (data[word].hasOwnProperty(lang)) {
|
|
||||||
langs[lang][word] = data[word][lang];
|
|
||||||
// pre-fill all other languages
|
|
||||||
for (const j in langs) {
|
|
||||||
if (langs.hasOwnProperty(j)) {
|
|
||||||
langs[j][word] = langs[j][word] || EMPTY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!fs.existsSync(src + 'i18n/')) {
|
|
||||||
fs.mkdirSync(src + 'i18n/');
|
|
||||||
}
|
|
||||||
for (const l in langs) {
|
|
||||||
if (!langs.hasOwnProperty(l))
|
|
||||||
continue;
|
|
||||||
const keys = Object.keys(langs[l]);
|
|
||||||
keys.sort();
|
|
||||||
const obj = {};
|
|
||||||
for (let k = 0; k < keys.length; k++) {
|
|
||||||
obj[keys[k]] = langs[l][keys[k]];
|
|
||||||
}
|
|
||||||
if (!fs.existsSync(src + 'i18n/' + l)) {
|
|
||||||
fs.mkdirSync(src + 'i18n/' + l);
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.writeFileSync(src + 'i18n/' + l + '/translations.json', lang2data(obj));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.error('Cannot read or parse ' + fileName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function languages2words(src) {
|
|
||||||
const dirs = fs.readdirSync(src + 'i18n/');
|
|
||||||
const langs = {};
|
|
||||||
const bigOne = {};
|
|
||||||
const order = Object.keys(languages);
|
|
||||||
dirs.sort(function (a, b) {
|
|
||||||
const posA = order.indexOf(a);
|
|
||||||
const posB = order.indexOf(b);
|
|
||||||
if (posA === -1 && posB === -1) {
|
|
||||||
if (a > b)
|
|
||||||
return 1;
|
|
||||||
if (a < b)
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
} else if (posA === -1) {
|
|
||||||
return -1;
|
|
||||||
} else if (posB === -1) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
if (posA > posB)
|
|
||||||
return 1;
|
|
||||||
if (posA < posB)
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
for (const lang of dirs) {
|
|
||||||
if (lang === 'flat.txt')
|
|
||||||
continue;
|
|
||||||
langs[lang] = fs.readFileSync(src + 'i18n/' + lang + '/translations.json').toString();
|
|
||||||
langs[lang] = JSON.parse(langs[lang]);
|
|
||||||
const words = langs[lang];
|
|
||||||
for (const word in words) {
|
|
||||||
if (words.hasOwnProperty(word)) {
|
|
||||||
bigOne[word] = bigOne[word] || {};
|
|
||||||
if (words[word] !== EMPTY) {
|
|
||||||
bigOne[word][lang] = words[word];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// read actual words.js
|
|
||||||
const aWords = readWordJs();
|
|
||||||
|
|
||||||
const temporaryIgnore = ['flat.txt'];
|
|
||||||
if (aWords) {
|
|
||||||
// Merge words together
|
|
||||||
for (const w in aWords) {
|
|
||||||
if (aWords.hasOwnProperty(w)) {
|
|
||||||
if (!bigOne[w]) {
|
|
||||||
console.warn('Take from actual words.js: ' + w);
|
|
||||||
bigOne[w] = aWords[w];
|
|
||||||
}
|
|
||||||
dirs.forEach(function (lang) {
|
|
||||||
if (temporaryIgnore.indexOf(lang) !== -1)
|
|
||||||
return;
|
|
||||||
if (!bigOne[w][lang]) {
|
|
||||||
console.warn('Missing "' + lang + '": ' + w);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
writeWordJs(bigOne, src);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function translateNotExisting(obj, baseText, yandex) {
|
|
||||||
let t = obj['en'];
|
|
||||||
if (!t) {
|
|
||||||
t = baseText;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t) {
|
|
||||||
for (let l in languages) {
|
|
||||||
if (!obj[l]) {
|
|
||||||
const time = new Date().getTime();
|
|
||||||
obj[l] = await translate(t, l, yandex);
|
|
||||||
console.log('en -> ' + l + ' ' + (new Date().getTime() - time) + ' ms');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//TASKS
|
|
||||||
|
|
||||||
gulp.task('adminWords2languages', function (done) {
|
|
||||||
words2languages('./admin/');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('adminLanguages2words', function (done) {
|
|
||||||
languages2words('./admin/');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('updatePackages', function (done) {
|
|
||||||
iopackage.common.version = pkg.version;
|
|
||||||
iopackage.common.news = iopackage.common.news || {};
|
|
||||||
if (!iopackage.common.news[pkg.version]) {
|
|
||||||
const news = iopackage.common.news;
|
|
||||||
const newNews = {};
|
|
||||||
|
|
||||||
newNews[pkg.version] = {
|
|
||||||
en: 'news',
|
|
||||||
de: 'neues',
|
|
||||||
ru: 'новое',
|
|
||||||
pt: 'novidades',
|
|
||||||
nl: 'nieuws',
|
|
||||||
fr: 'nouvelles',
|
|
||||||
it: 'notizie',
|
|
||||||
es: 'noticias',
|
|
||||||
pl: 'nowości',
|
|
||||||
'zh-cn': '新'
|
|
||||||
};
|
|
||||||
iopackage.common.news = Object.assign(newNews, news);
|
|
||||||
}
|
|
||||||
fs.writeFileSync('io-package.json', JSON.stringify(iopackage, null, 4));
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('updateReadme', function (done) {
|
|
||||||
const readme = fs.readFileSync('README.md').toString();
|
|
||||||
const pos = readme.indexOf('## Changelog\n');
|
|
||||||
if (pos !== -1) {
|
|
||||||
const readmeStart = readme.substring(0, pos + '## Changelog\n'.length);
|
|
||||||
const readmeEnd = readme.substring(pos + '## Changelog\n'.length);
|
|
||||||
|
|
||||||
if (readme.indexOf(version) === -1) {
|
|
||||||
const timestamp = new Date();
|
|
||||||
const date = timestamp.getFullYear() + '-' +
|
|
||||||
('0' + (timestamp.getMonth() + 1).toString(10)).slice(-2) + '-' +
|
|
||||||
('0' + (timestamp.getDate()).toString(10)).slice(-2);
|
|
||||||
|
|
||||||
let news = '';
|
|
||||||
if (iopackage.common.news && iopackage.common.news[pkg.version]) {
|
|
||||||
news += '* ' + iopackage.common.news[pkg.version].en;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.writeFileSync('README.md', readmeStart + '### ' + version + ' (' + date + ')\n' + (news ? news + '\n\n' : '\n') + readmeEnd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('translate', async function (done) {
|
|
||||||
|
|
||||||
let yandex;
|
|
||||||
const i = process.argv.indexOf('--yandex');
|
|
||||||
if (i > -1) {
|
|
||||||
yandex = process.argv[i + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iopackage && iopackage.common) {
|
|
||||||
if (iopackage.common.news) {
|
|
||||||
console.log('Translate News');
|
|
||||||
for (let k in iopackage.common.news) {
|
|
||||||
console.log('News: ' + k);
|
|
||||||
let nw = iopackage.common.news[k];
|
|
||||||
await translateNotExisting(nw, null, yandex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (iopackage.common.titleLang) {
|
|
||||||
console.log('Translate Title');
|
|
||||||
await translateNotExisting(iopackage.common.titleLang, iopackage.common.title, yandex);
|
|
||||||
}
|
|
||||||
if (iopackage.common.desc) {
|
|
||||||
console.log('Translate Description');
|
|
||||||
await translateNotExisting(iopackage.common.desc, null, yandex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fs.existsSync('./admin/i18n/en/translations.json')) {
|
|
||||||
let enTranslations = require('./admin/i18n/en/translations.json');
|
|
||||||
for (let l in languages) {
|
|
||||||
console.log('Translate Text: ' + l);
|
|
||||||
let existing = {};
|
|
||||||
if (fs.existsSync('./admin/i18n/' + l + '/translations.json')) {
|
|
||||||
existing = require('./admin/i18n/' + l + '/translations.json');
|
|
||||||
}
|
|
||||||
for (let t in enTranslations) {
|
|
||||||
if (!existing[t]) {
|
|
||||||
existing[t] = await translate(enTranslations[t], l, yandex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!fs.existsSync('./admin/i18n/' + l + '/')) {
|
|
||||||
fs.mkdirSync('./admin/i18n/' + l + '/');
|
|
||||||
}
|
|
||||||
fs.writeFileSync('./admin/i18n/' + l + '/translations.json', JSON.stringify(existing, null, 4));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
fs.writeFileSync('io-package.json', JSON.stringify(iopackage, null, 4));
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('translateAndUpdateWordsJS', gulp.series('translate', 'adminLanguages2words', 'adminWords2languages'));
|
|
||||||
|
|
||||||
gulp.task('default', gulp.series('updatePackages', 'updateReadme'));
|
|
||||||
+49
-36
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"common": {
|
"common": {
|
||||||
"name": "hass",
|
"name": "hass",
|
||||||
"version": "1.2.0",
|
"version": "1.4.0",
|
||||||
"title": "Home Assistant",
|
"title": "Home Assistant",
|
||||||
"titleLang": {
|
"titleLang": {
|
||||||
"en": "Home Assistant",
|
"en": "Home Assistant",
|
||||||
@@ -13,7 +13,8 @@
|
|||||||
"it": "Assistente domiciliare",
|
"it": "Assistente domiciliare",
|
||||||
"es": "Asistente de hogar",
|
"es": "Asistente de hogar",
|
||||||
"pl": "Asystent domowy",
|
"pl": "Asystent domowy",
|
||||||
"zh-cn": "家庭助理"
|
"zh-cn": "家庭助理",
|
||||||
|
"uk": "Домашній помічник"
|
||||||
},
|
},
|
||||||
"desc": {
|
"desc": {
|
||||||
"en": "Home Assistant connection for ioBroker",
|
"en": "Home Assistant connection for ioBroker",
|
||||||
@@ -25,9 +26,36 @@
|
|||||||
"it": "Connessione Home Assistant per ioBroker",
|
"it": "Connessione Home Assistant per ioBroker",
|
||||||
"es": "Conexión de Home Assistant para ioBroker",
|
"es": "Conexión de Home Assistant para ioBroker",
|
||||||
"pl": "Połączenie Home Assistant dla ioBroker",
|
"pl": "Połączenie Home Assistant dla ioBroker",
|
||||||
"zh-cn": "ioBroker 的家庭助理连接"
|
"zh-cn": "ioBroker 的家庭助理连接",
|
||||||
|
"uk": "Підключення Home Assistant для ioBroker"
|
||||||
},
|
},
|
||||||
"news": {
|
"news": {
|
||||||
|
"1.4.0": {
|
||||||
|
"en": "Added more guidance logging when setting services incorrectly\nPrevent crashes when attributes contain \".\" at the end of their names\nAdded logging for state updates for unknown objects",
|
||||||
|
"de": "Mehr Anleitungsprotokollierung hinzugefügt, wenn Dienste falsch eingestellt werden\nVerhindern Sie Abstürzen, wenn Attribute \" enthalten.\" am Ende ihrer Namen\nHinzugefügt Protokollierung für Zustandsaktualisierungen für unbekannte Objekte",
|
||||||
|
"ru": "Добавили больше руководства, когда установка услуг неправильно\nПредотвратить сбои, когда атрибуты содержат \".\" в конце их имен\nДобавлен вход для государственных обновлений для неизвестных объектов",
|
||||||
|
"pt": "Adicionado mais registro de orientação ao definir serviços incorretamente\nImpedir falhas quando os atributos contêm \". no final de seus nomes\nRegisto adicionado para atualizações de estado para objetos desconhecidos",
|
||||||
|
"nl": "Voeg meer begeleiding toe als ze onjuiste diensten indienen\nVertaling:\nVermeld inloggen op staatsinformatie voor onbekende objecten",
|
||||||
|
"fr": "Ajout d'autres lignes directrices lorsqu'on établit des services incorrectement\nPrévenir les crashes lorsque les attributs contiennent \".\" à la fin de leurs noms\nAjout de logging pour les mises à jour de l'état des objets inconnus",
|
||||||
|
"it": "Aggiunto più guida logging quando imposta i servizi in modo errato\nPrevenire crash quando gli attributi contengono \". alla fine dei loro nomi\nAggiunto logging per aggiornamenti di stato per oggetti sconosciuti",
|
||||||
|
"es": "Se agregó más registro de guía cuando se establecen los servicios incorrectamente\nEvitar fallos cuando los atributos contienen \".\" al final de sus nombres\nRegistro añadido para actualizaciones estatales para objetos desconocidos",
|
||||||
|
"pl": "Wprowadzone są bardziej wytyczne, gdy ustawienie usług nieprawidłowo błędnie\nPrevent rozbija się, gdy atrybuty zawierają „”\nWprowadzone logowanie dla aktualizacji stanów nieznanych obiektów",
|
||||||
|
"uk": "Додайте більше звітів при установці послуг неправильно\nПрофілактика аварійних випадків, коли атрибути містять \".\" в кінці їх імен\nДодана записка для державних оновлень для невідомих об'єктів",
|
||||||
|
"zh-cn": "在不正确地建立服务时增加指导标志\n在名称末尾含有“第2款”的预防事故\n增加用于不明物品的国家更新的伐木"
|
||||||
|
},
|
||||||
|
"1.3.0": {
|
||||||
|
"en": "Further optimize sending data to HASS and allow to set values like numbers as normal states if the service has one attribute and it can be mapped",
|
||||||
|
"de": "Weitere optimieren Sie das Senden von Daten an HASS und ermöglichen es, Werte wie Zahlen als normale Zustände festzulegen, wenn der Dienst ein Attribut hat und es abgebildet werden kann",
|
||||||
|
"ru": "Далее оптимизируйте отправку данных в HASS и позвольте установить значения, такие как цифры, как нормальные состояния, если услуга имеет один атрибут, и она может быть загружена",
|
||||||
|
"pt": "Além disso otimizar o envio de dados para HASS e permitir definir valores como números como estados normais se o serviço tem um atributo e pode ser mapeado",
|
||||||
|
"nl": "Verder optimiliseer het sturen van gegevens naar HASS en sta toe om waarden als normale staten te plaatsen als de dienst een Attribuut heeft en het kan worden in kaart gebracht",
|
||||||
|
"fr": "Optimiser l'envoi de données à HASS et permettre de définir des valeurs comme des nombres comme des états normaux si le service a un attribut et il peut être mappé",
|
||||||
|
"it": "Ottimizzare ulteriormente l'invio di dati a HASS e consentire di impostare valori come numeri come stati normali se il servizio ha un attributo e può essere mappato",
|
||||||
|
"es": "Optimizar aún más el envío de datos a HASS y permitir establecer valores como números como estados normales si el servicio tiene un atributo y puede ser mapeado",
|
||||||
|
"pl": "Dalsze optymalizowanie danych do HASS i umożliwienie ustalenie wartości takich jak stany normalne, jeśli usługa ma jeden atrybut i może być zmapowana",
|
||||||
|
"zh-cn": "进一步优化向人道协调厅系统传送数据,如果该服务具有属性,它可以绘制图表,从而能够将数字象正常国家一样。",
|
||||||
|
"uk": "Додатково оптимізуйте надсилання даних до HASS і дозвольте встановлювати такі значення, як числа, як звичайні стани, якщо служба має один атрибут і його можна зіставити"
|
||||||
|
},
|
||||||
"1.2.0": {
|
"1.2.0": {
|
||||||
"en": "IMPORTANT: Replace special characters in entity attribute names with an underscore! Object IDs might change!\nmake sure a \"null\" value in state changes is not crashing",
|
"en": "IMPORTANT: Replace special characters in entity attribute names with an underscore! Object IDs might change!\nmake sure a \"null\" value in state changes is not crashing",
|
||||||
"de": "WICHTIG: Ersetzen Sie Sonderzeichen in Namen des Attributes der Einheit mit einem Unterpunkt! Objekt-IDs können sich ändern!\nsicherstellen, dass ein nullwert bei zustandsänderungen nicht abstürzt",
|
"de": "WICHTIG: Ersetzen Sie Sonderzeichen in Namen des Attributes der Einheit mit einem Unterpunkt! Objekt-IDs können sich ändern!\nsicherstellen, dass ein nullwert bei zustandsänderungen nicht abstürzt",
|
||||||
@@ -38,7 +66,8 @@
|
|||||||
"it": "IMPORTANTE: Sostituisci caratteri speciali in nomi attributo entità con un underscore! Gli ID degli Oggetti potrebbero cambiare!\nassicurarsi che un valore nullo nei cambiamenti di stato non è crash",
|
"it": "IMPORTANTE: Sostituisci caratteri speciali in nomi attributo entità con un underscore! Gli ID degli Oggetti potrebbero cambiare!\nassicurarsi che un valore nullo nei cambiamenti di stato non è crash",
|
||||||
"es": "IMPORTANTE: Reemplazar caracteres especiales en nombres de atributos de entidad con un subrayado! ¡Las identificaciones de objetos pueden cambiar!\nasegúrese de que un valor nulo en los cambios estatales no se estrella",
|
"es": "IMPORTANTE: Reemplazar caracteres especiales en nombres de atributos de entidad con un subrayado! ¡Las identificaciones de objetos pueden cambiar!\nasegúrese de que un valor nulo en los cambios estatales no se estrella",
|
||||||
"pl": "IMPORTANT: Replace special characters in identity attribution names with an underscore! (ang.). Zmiany obiektów mogą się zmieniać!\nniewątpliwą wartością w zmianach stanowych nie jest rozbicie się",
|
"pl": "IMPORTANT: Replace special characters in identity attribution names with an underscore! (ang.). Zmiany obiektów mogą się zmieniać!\nniewątpliwą wartością w zmianach stanowych nie jest rozbicie się",
|
||||||
"zh-cn": "IMPORTANT:将实体的特色性改为强调的! 目标国际组织可能改变!\n确保在国家变化中确保无效不失"
|
"zh-cn": "IMPORTANT:将实体的特色性改为强调的! 目标国际组织可能改变!\n确保在国家变化中确保无效不失",
|
||||||
|
"uk": "ВАЖЛИВО: Замініть спеціальні символи в іменах атрибутів сутності на підкреслення! Ідентифікатори об'єктів можуть змінитися!\nпереконайтеся, що \"нульове\" значення в змінах стану не аварійно завершує роботу"
|
||||||
},
|
},
|
||||||
"1.1.2": {
|
"1.1.2": {
|
||||||
"en": "Fix crash cases reported by Sentry",
|
"en": "Fix crash cases reported by Sentry",
|
||||||
@@ -50,7 +79,8 @@
|
|||||||
"it": "Risolvi i casi di crash segnalati da Sentry",
|
"it": "Risolvi i casi di crash segnalati da Sentry",
|
||||||
"es": "Solucionar casos de fallas informados por Sentry",
|
"es": "Solucionar casos de fallas informados por Sentry",
|
||||||
"pl": "Napraw przypadki awarii zgłoszone przez Sentry",
|
"pl": "Napraw przypadki awarii zgłoszone przez Sentry",
|
||||||
"zh-cn": "修复 Sentry 报告的崩溃案例"
|
"zh-cn": "修复 Sentry 报告的崩溃案例",
|
||||||
|
"uk": "Виправте випадки збоїв, про які повідомляє Sentry"
|
||||||
},
|
},
|
||||||
"1.1.1": {
|
"1.1.1": {
|
||||||
"en": "Show password fields masked again in config",
|
"en": "Show password fields masked again in config",
|
||||||
@@ -62,7 +92,8 @@
|
|||||||
"it": "Mostra i campi password mascherati di nuovo in config",
|
"it": "Mostra i campi password mascherati di nuovo in config",
|
||||||
"es": "Mostrar campos de contraseña enmascarados nuevamente en la configuración",
|
"es": "Mostrar campos de contraseña enmascarados nuevamente en la configuración",
|
||||||
"pl": "Pokaż ponownie zamaskowane pola haseł w konfiguracji",
|
"pl": "Pokaż ponownie zamaskowane pola haseł w konfiguracji",
|
||||||
"zh-cn": "在配置中再次显示被屏蔽的密码字段"
|
"zh-cn": "在配置中再次显示被屏蔽的密码字段",
|
||||||
|
"uk": "Знову показати замасковані поля пароля в конфігурації"
|
||||||
},
|
},
|
||||||
"1.1.0": {
|
"1.1.0": {
|
||||||
"en": "IMPORTANT: You need to re-enter the password once after installing this version!\nImplement Service triggers to use any value to trigger or stringified JSON to call with fields\nOptimize unload handling\nAdd Sentry for crash reporting",
|
"en": "IMPORTANT: You need to re-enter the password once after installing this version!\nImplement Service triggers to use any value to trigger or stringified JSON to call with fields\nOptimize unload handling\nAdd Sentry for crash reporting",
|
||||||
@@ -74,7 +105,8 @@
|
|||||||
"it": "IMPORTANTE: è necessario reinserire la password una volta dopo aver installato questa versione!\nImplementa i trigger del servizio per utilizzare qualsiasi valore per attivare o JSON in formato stringa per chiamare con i campi\nOttimizza la gestione dello scarico\nAggiungi Sentinella per la segnalazione degli arresti anomali",
|
"it": "IMPORTANTE: è necessario reinserire la password una volta dopo aver installato questa versione!\nImplementa i trigger del servizio per utilizzare qualsiasi valore per attivare o JSON in formato stringa per chiamare con i campi\nOttimizza la gestione dello scarico\nAggiungi Sentinella per la segnalazione degli arresti anomali",
|
||||||
"es": "IMPORTANTE: ¡Debe volver a ingresar la contraseña una vez después de instalar esta versión!\nImplementar disparadores de servicio para usar cualquier valor para disparar o JSON en cadena para llamar con campos\nOptimizar el manejo de descarga\nAgregar Sentry para informes de fallas",
|
"es": "IMPORTANTE: ¡Debe volver a ingresar la contraseña una vez después de instalar esta versión!\nImplementar disparadores de servicio para usar cualquier valor para disparar o JSON en cadena para llamar con campos\nOptimizar el manejo de descarga\nAgregar Sentry para informes de fallas",
|
||||||
"pl": "WAŻNE: Po zainstalowaniu tej wersji należy raz ponownie wprowadzić hasło!\nZaimplementuj wyzwalacze usługi, aby używać dowolnej wartości do wyzwalania lub skróconego JSON do wywołania z polami\nZoptymalizuj obsługę rozładunku\nDodaj Sentry do zgłaszania awarii",
|
"pl": "WAŻNE: Po zainstalowaniu tej wersji należy raz ponownie wprowadzić hasło!\nZaimplementuj wyzwalacze usługi, aby używać dowolnej wartości do wyzwalania lub skróconego JSON do wywołania z polami\nZoptymalizuj obsługę rozładunku\nDodaj Sentry do zgłaszania awarii",
|
||||||
"zh-cn": "重要提示:安装此版本后需要重新输入一次密码!\n实现服务触发器以使用任何值触发或字符串化 JSON 以使用字段调用\n优化卸载处理\n添加 Sentry 以进行崩溃报告"
|
"zh-cn": "重要提示:安装此版本后需要重新输入一次密码!\n实现服务触发器以使用任何值触发或字符串化 JSON 以使用字段调用\n优化卸载处理\n添加 Sentry 以进行崩溃报告",
|
||||||
|
"uk": "ВАЖЛИВО: після встановлення цієї версії потрібно повторно ввести пароль!\nРеалізуйте тригери служби, щоб використовувати будь-яке значення для запуску або рядковий JSON для виклику з полями\nОптимізуйте роботу з розвантаженням\nДодайте Sentry для звітування про збої"
|
||||||
},
|
},
|
||||||
"1.0.1": {
|
"1.0.1": {
|
||||||
"en": "IMPORTANT: js-controller 2.0 is needed st least!\nFix start issue\n(Apollon77/Garfonso) Fix issue where value could not be set in hass",
|
"en": "IMPORTANT: js-controller 2.0 is needed st least!\nFix start issue\n(Apollon77/Garfonso) Fix issue where value could not be set in hass",
|
||||||
@@ -86,31 +118,8 @@
|
|||||||
"it": "IMPORTANTE: come minimo è necessario js-controller 2.0!\nRisolvi il problema di avvio\n(Apollon77/Garfonso) Risolto il problema per cui il valore non poteva essere impostato in hass",
|
"it": "IMPORTANTE: come minimo è necessario js-controller 2.0!\nRisolvi il problema di avvio\n(Apollon77/Garfonso) Risolto il problema per cui il valore non poteva essere impostato in hass",
|
||||||
"es": "IMPORTANTE: ¡js-controller 2.0 es lo menos necesario!\nSolucionar problema de inicio\n(Apollon77 / Garfonso) Se solucionó el problema por el cual no se podía establecer el valor en hass",
|
"es": "IMPORTANTE: ¡js-controller 2.0 es lo menos necesario!\nSolucionar problema de inicio\n(Apollon77 / Garfonso) Se solucionó el problema por el cual no se podía establecer el valor en hass",
|
||||||
"pl": "WAŻNE: js-controller 2.0 jest potrzebny przynajmniej!\nNapraw problem z uruchomieniem\n(Apollon77/Garfonso) Napraw problem, w którym nie można było ustawić wartości w hass",
|
"pl": "WAŻNE: js-controller 2.0 jest potrzebny przynajmniej!\nNapraw problem z uruchomieniem\n(Apollon77/Garfonso) Napraw problem, w którym nie można było ustawić wartości w hass",
|
||||||
"zh-cn": "重要提示:至少需要 js-controller 2.0!\n修复启动问题\n(Apollon77/Garfonso) 修复无法在 hass 中设置值的问题"
|
"zh-cn": "重要提示:至少需要 js-controller 2.0!\n修复启动问题\n(Apollon77/Garfonso) 修复无法在 hass 中设置值的问题",
|
||||||
},
|
"uk": "ВАЖЛИВО: як мінімум потрібен js-контроллер 2.0!\nВиправити проблему запуску\n(Apollon77/Garfonso) Виправлено проблему, через яку значення не можна було встановити в hass"
|
||||||
"1.0.0": {
|
|
||||||
"en": "added the support of compact mode",
|
|
||||||
"de": "fügte die Unterstützung des Kompaktmodus hinzu",
|
|
||||||
"ru": "добавлена поддержка компактного режима",
|
|
||||||
"pt": "adicionado o suporte do modo compacto",
|
|
||||||
"nl": "de ondersteuning van de compacte modus toegevoegd",
|
|
||||||
"fr": "ajouté le support du mode compact",
|
|
||||||
"it": "aggiunto il supporto della modalità compatta",
|
|
||||||
"es": "agregó el soporte del modo compacto",
|
|
||||||
"pl": "dodano obsługę trybu kompaktowego",
|
|
||||||
"zh-cn": "增加了对紧凑模式的支持"
|
|
||||||
},
|
|
||||||
"0.1.0": {
|
|
||||||
"en": "initial version",
|
|
||||||
"de": "erste Version",
|
|
||||||
"ru": "Первоначальная версия",
|
|
||||||
"pt": "versão inicial",
|
|
||||||
"nl": "eerste versie",
|
|
||||||
"fr": "version initiale",
|
|
||||||
"it": "versione iniziale",
|
|
||||||
"es": "versión inicial",
|
|
||||||
"pl": "początkowa wersja",
|
|
||||||
"zh-cn": "初始版本"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"localLink": "http://%host%:8123",
|
"localLink": "http://%host%:8123",
|
||||||
@@ -170,7 +179,8 @@
|
|||||||
"it": "Reinserire la password dopo l'aggiornamento!",
|
"it": "Reinserire la password dopo l'aggiornamento!",
|
||||||
"es": "Vuelva a ingresar la contraseña después de ¡Actualizar!",
|
"es": "Vuelva a ingresar la contraseña después de ¡Actualizar!",
|
||||||
"pl": "Wprowadź hasło ponownie po aktualizacji!",
|
"pl": "Wprowadź hasło ponownie po aktualizacji!",
|
||||||
"zh-cn": "更新后重新输入密码!"
|
"zh-cn": "更新后重新输入密码!",
|
||||||
|
"uk": "Повторно введіть пароль після оновлення!"
|
||||||
},
|
},
|
||||||
"text": {
|
"text": {
|
||||||
"en": "After installing this update the password/token used to access the HASS installation needs to be re-entered in the Instance-Settings!",
|
"en": "After installing this update the password/token used to access the HASS installation needs to be re-entered in the Instance-Settings!",
|
||||||
@@ -182,7 +192,8 @@
|
|||||||
"it": "Dopo aver installato questo aggiornamento, la password/token utilizzato per accedere all'installazione HASS deve essere reinserito nelle impostazioni dell'istanza!",
|
"it": "Dopo aver installato questo aggiornamento, la password/token utilizzato per accedere all'installazione HASS deve essere reinserito nelle impostazioni dell'istanza!",
|
||||||
"es": "¡Después de instalar esta actualización, la contraseña/token utilizada para acceder a la instalación de HASS debe volver a ingresarse en la configuración de la instancia!",
|
"es": "¡Después de instalar esta actualización, la contraseña/token utilizada para acceder a la instalación de HASS debe volver a ingresarse en la configuración de la instancia!",
|
||||||
"pl": "Po zainstalowaniu tej aktualizacji hasło/token używane do uzyskania dostępu do instalacji HASS należy ponownie wprowadzić w ustawieniach instancji!",
|
"pl": "Po zainstalowaniu tej aktualizacji hasło/token używane do uzyskania dostępu do instalacji HASS należy ponownie wprowadzić w ustawieniach instancji!",
|
||||||
"zh-cn": "安装此更新后,用于访问 HASS 安装的密码/令牌需要在实例设置中重新输入!"
|
"zh-cn": "安装此更新后,用于访问 HASS 安装的密码/令牌需要在实例设置中重新输入!",
|
||||||
|
"uk": "Після встановлення цього оновлення пароль/токен, який використовується для доступу до встановлення HASS, потрібно повторно ввести в налаштуваннях екземпляра!"
|
||||||
},
|
},
|
||||||
"level": "warn",
|
"level": "warn",
|
||||||
"buttons": [
|
"buttons": [
|
||||||
@@ -208,7 +219,8 @@
|
|||||||
"it": "Avviso IMPORTANTE!",
|
"it": "Avviso IMPORTANTE!",
|
||||||
"es": "Noticia importante!",
|
"es": "Noticia importante!",
|
||||||
"pl": "Ważna uwaga!",
|
"pl": "Ważna uwaga!",
|
||||||
"zh-cn": "重要通知!"
|
"zh-cn": "重要通知!",
|
||||||
|
"uk": "Важливе повідомлення!"
|
||||||
},
|
},
|
||||||
"text": {
|
"text": {
|
||||||
"en": "The new version 1.2.x will potentially change the Names of Objects when special characters like \".\", \"-\" or spaces were used in entity attributes! Please delete the old objects manually if needed.",
|
"en": "The new version 1.2.x will potentially change the Names of Objects when special characters like \".\", \"-\" or spaces were used in entity attributes! Please delete the old objects manually if needed.",
|
||||||
@@ -220,7 +232,8 @@
|
|||||||
"it": "La nuova versione 1.2.x cambierà potenzialmente i nomi degli oggetti quando caratteri speciali come \".\", \"-\" o spazi sono stati utilizzati negli attributi dell'entità! Si prega di eliminare i vecchi oggetti manualmente se necessario.",
|
"it": "La nuova versione 1.2.x cambierà potenzialmente i nomi degli oggetti quando caratteri speciali come \".\", \"-\" o spazi sono stati utilizzati negli attributi dell'entità! Si prega di eliminare i vecchi oggetti manualmente se necessario.",
|
||||||
"es": "La nueva versión 1.2.x potencialmente cambiará los Nombres de Objetos cuando caracteres especiales como \"., \"-\" o espacios fueron utilizados en atributos de entidad! Por favor, borre los viejos objetos manualmente si es necesario.",
|
"es": "La nueva versión 1.2.x potencialmente cambiará los Nombres de Objetos cuando caracteres especiales como \"., \"-\" o espacios fueron utilizados en atributos de entidad! Por favor, borre los viejos objetos manualmente si es necesario.",
|
||||||
"pl": "Nowa wersja 1.2.x będzie potencjalnie zmieniać nazwy obiektów, kiedy szczególne postacie takie jak „.”, „-” lub przestrzenie były używane w atrybutach. Okazuje się, że stare obiekty ręcznie będą potrzebne.",
|
"pl": "Nowa wersja 1.2.x będzie potencjalnie zmieniać nazwy obiektów, kiedy szczególne postacie takie jak „.”, „-” lub przestrzenie były używane w atrybutach. Okazuje się, że stare obiekty ręcznie będą potrzebne.",
|
||||||
"zh-cn": "新版本1.2.x将可能改变物体的名称,如“......”、“-”或空间在实体的属性中使用。 请在必要时删除旧物体。."
|
"zh-cn": "新版本1.2.x将可能改变物体的名称,如“......”、“-”或空间在实体的属性中使用。 请在必要时删除旧物体。.",
|
||||||
|
"uk": "Нова версія 1.2.x потенційно змінить назви об’єктів, якщо в атрибутах об’єктів використовувалися спеціальні символи, такі як «.», «-» або пробіли! За потреби видаліть старі об’єкти вручну."
|
||||||
},
|
},
|
||||||
"level": "warn",
|
"level": "warn",
|
||||||
"buttons": [
|
"buttons": [
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
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>}
|
|
||||||
*/
|
|
||||||
function isObject(it) {
|
|
||||||
// This is necessary because:
|
|
||||||
// typeof null === 'object'
|
|
||||||
// typeof [] === 'object'
|
|
||||||
// [] instanceof Object === true
|
|
||||||
return Object.prototype.toString.call(it) === "[object Object]";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests whether the given variable is really an Array
|
|
||||||
* @param {any} it The variable to test
|
|
||||||
* @returns {it is any[]}
|
|
||||||
*/
|
|
||||||
function isArray(it) {
|
|
||||||
if (Array.isArray != null)
|
|
||||||
return Array.isArray(it);
|
|
||||||
return Object.prototype.toString.call(it) === "[object Array]";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Choose the right tranalation API
|
|
||||||
* @param {string} text The text to translate
|
|
||||||
* @param {string} targetLang The target languate
|
|
||||||
* @param {string} yandex api key
|
|
||||||
* @returns {Promise<string>}
|
|
||||||
*/
|
|
||||||
async function translateText(text, targetLang, yandex) {
|
|
||||||
if (targetLang === "en") {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
if (yandex) {
|
|
||||||
return await translateYandex(text, targetLang, yandex);
|
|
||||||
} else {
|
|
||||||
return await translateGoogle(text, targetLang);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates text with Yandex API
|
|
||||||
* @param {string} text The text to translate
|
|
||||||
* @param {string} targetLang The target languate
|
|
||||||
* @param {string} yandex api key
|
|
||||||
* @returns {Promise<string>}
|
|
||||||
*/
|
|
||||||
async function translateYandex(text, targetLang, yandex) {
|
|
||||||
if (targetLang === "zh-cn") {
|
|
||||||
targetLang = "zh";
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const url = `https://translate.yandex.net/api/v1.5/tr.json/translate?key=${yandex}&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}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates text with Google API
|
|
||||||
* @param {string} text The text to translate
|
|
||||||
* @param {string} targetLang The target languate
|
|
||||||
* @returns {Promise<string>}
|
|
||||||
*/
|
|
||||||
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}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
isArray,
|
|
||||||
isObject,
|
|
||||||
translateText
|
|
||||||
};
|
|
||||||
@@ -25,7 +25,7 @@ function startAdapter(options) {
|
|||||||
// you can use the ack flag to detect if it is status (true) or command (false)
|
// you can use the ack flag to detect if it is status (true) or command (false)
|
||||||
if (state && !state.ack) {
|
if (state && !state.ack) {
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
return adapter.log.warn('Cannot send command to "' + id + '", because not connected');
|
return adapter.log.warn(`Cannot send command to "${id}", because not connected`);
|
||||||
}
|
}
|
||||||
/*if (id === adapter.namespace + '.' + '.info.resync') {
|
/*if (id === adapter.namespace + '.' + '.info.resync') {
|
||||||
queue.push({command: 'resync'});
|
queue.push({command: 'resync'});
|
||||||
@@ -33,7 +33,7 @@ function startAdapter(options) {
|
|||||||
} else */
|
} else */
|
||||||
if (hassObjects[id]) {
|
if (hassObjects[id]) {
|
||||||
if (!hassObjects[id].common.write) {
|
if (!hassObjects[id].common.write) {
|
||||||
adapter.log.warn('Object ' + id + ' is not writable!');
|
adapter.log.warn(`Object ${id} is not writable!`);
|
||||||
} else {
|
} else {
|
||||||
const serviceData = {};
|
const serviceData = {};
|
||||||
const fields = hassObjects[id].native.fields;
|
const fields = hassObjects[id].native.fields;
|
||||||
@@ -41,30 +41,52 @@ function startAdapter(options) {
|
|||||||
|
|
||||||
let requestFields = {};
|
let requestFields = {};
|
||||||
if (typeof state.val === 'string') {
|
if (typeof state.val === 'string') {
|
||||||
try {
|
state.val = state.val.trim();
|
||||||
requestFields = JSON.parse(state.val) || {};
|
if (state.val.startsWith('{') && state.val.endsWith('}')) {
|
||||||
} catch (err) {
|
try {
|
||||||
adapter.log.info(`Ignore data for service call ${id} is no valid JSON: ${err.message}`);
|
requestFields = JSON.parse(state.val) || {};
|
||||||
requestFields = {};
|
} catch (err) {
|
||||||
|
adapter.log.info(`Ignore data for service call ${id} is no valid JSON: ${err.message}`);
|
||||||
|
requestFields = {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const field in fields) {
|
// If a non-JSON value was set, and we only have one relevant field, use this field as value
|
||||||
if (!fields.hasOwnProperty(field)) {
|
if (fields && Object.keys(requestFields).length === 0) {
|
||||||
continue;
|
const fieldList = Object.keys(fields);
|
||||||
}
|
if (fieldList.length === 1 && fieldList[0] !== 'entity_id') {
|
||||||
|
requestFields[fieldList[0]] = state.val;
|
||||||
if (field === 'entity_id') {
|
} else if (fieldList.length === 2 && fields.entity_id) {
|
||||||
target.entity_id = hassObjects[id].native.entity_id
|
requestFields[fieldList[1 - fields.indexOf('entity_id')]] = state.val;
|
||||||
} else if (requestFields[field] !== undefined) {
|
|
||||||
serviceData[field] = requestFields[field];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
adapter.log.debug(`Prepare service call for ${id} with (mapped) request parameters ${JSON.stringify(requestFields)} from value: ${JSON.stringify(state.val)}`);
|
||||||
|
if (fields) {
|
||||||
|
for (const field in fields) {
|
||||||
|
if (!fields.hasOwnProperty(field)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field === 'entity_id') {
|
||||||
|
target.entity_id = hassObjects[id].native.entity_id
|
||||||
|
} else if (requestFields[field] !== undefined) {
|
||||||
|
serviceData[field] = requestFields[field];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const noFields = Object.keys(serviceData).length === 0;
|
||||||
serviceData.entity_id = hassObjects[id].native.entity_id
|
serviceData.entity_id = hassObjects[id].native.entity_id
|
||||||
|
|
||||||
adapter.log.debug(`Send to HASS for service ${hassObjects[id].native.attr} with ${hassObjects[id].native.domain || hassObjects[id].native.type} and data ${JSON.stringify(serviceData)}`)
|
adapter.log.debug(`Send to HASS for service ${hassObjects[id].native.attr} with ${hassObjects[id].native.domain || hassObjects[id].native.type} and data ${JSON.stringify(serviceData)}`)
|
||||||
hass.callService(hassObjects[id].native.attr, hassObjects[id].native.domain || hassObjects[id].native.type, serviceData, target, err =>
|
hass.callService(hassObjects[id].native.attr, hassObjects[id].native.domain || hassObjects[id].native.type, serviceData, target, err => {
|
||||||
err && adapter.log.error('Cannot control ' + id + ': ' + err));
|
err && adapter.log.error(`Cannot control ${id}: ${err}`);
|
||||||
|
if (err && fields && noFields) {
|
||||||
|
adapter.log.warn(`Please make sure to provide a stringified JSON as value to set relevant fields! Please refer to the Readme for details!`);
|
||||||
|
adapter.log.warn(`Allowed field keys are: ${Object.keys(fields).join(', ')}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,7 +148,7 @@ function syncObjects(objects, cb) {
|
|||||||
err && adapter.log.error(err);
|
err && adapter.log.error(err);
|
||||||
|
|
||||||
if (!oldObj) {
|
if (!oldObj) {
|
||||||
adapter.log.debug('Create "' + obj._id + '": ' + JSON.stringify(obj.common));
|
adapter.log.debug(`Create "${obj._id}": ${JSON.stringify(obj.common)}`);
|
||||||
hassObjects[obj._id] = obj;
|
hassObjects[obj._id] = obj;
|
||||||
adapter.setForeignObject(obj._id, obj, err => {
|
adapter.setForeignObject(obj._id, obj, err => {
|
||||||
err && adapter.log.error(err);
|
err && adapter.log.error(err);
|
||||||
@@ -137,7 +159,7 @@ function syncObjects(objects, cb) {
|
|||||||
if (JSON.stringify(obj.native) !== JSON.stringify(oldObj.native)) {
|
if (JSON.stringify(obj.native) !== JSON.stringify(oldObj.native)) {
|
||||||
oldObj.native = obj.native;
|
oldObj.native = obj.native;
|
||||||
|
|
||||||
adapter.log.debug('Update "' + obj._id + '": ' + JSON.stringify(obj.common));
|
adapter.log.debug(`Update "${obj._id}": ${JSON.stringify(obj.common)}`);
|
||||||
adapter.setForeignObject(obj._id, oldObj, err => {
|
adapter.setForeignObject(obj._id, oldObj, err => {
|
||||||
err => adapter.log.error(err);
|
err => adapter.log.error(err);
|
||||||
setImmediate(syncObjects, objects, cb);
|
setImmediate(syncObjects, objects, cb);
|
||||||
@@ -150,10 +172,10 @@ function syncObjects(objects, cb) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function syncRoom(room, members, cb) {
|
function syncRoom(room, members, cb) {
|
||||||
adapter.getForeignObject('enum.rooms.' + room, (err, obj) => {
|
adapter.getForeignObject(`enum.rooms.${room}`, (err, obj) => {
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
obj = {
|
obj = {
|
||||||
_id: 'enum.rooms.' + room,
|
_id: `enum.rooms.${room}`,
|
||||||
type: 'enum',
|
type: 'enum',
|
||||||
common: {
|
common: {
|
||||||
name: room,
|
name: room,
|
||||||
@@ -161,7 +183,7 @@ function syncRoom(room, members, cb) {
|
|||||||
},
|
},
|
||||||
native: {}
|
native: {}
|
||||||
};
|
};
|
||||||
adapter.log.debug('Update "' + obj._id + '"');
|
adapter.log.debug(`Update "${obj._id}"`);
|
||||||
adapter.setForeignObject(obj._id, obj, err => {
|
adapter.setForeignObject(obj._id, obj, err => {
|
||||||
err && adapter.log.error(err);
|
err && adapter.log.error(err);
|
||||||
cb();
|
cb();
|
||||||
@@ -177,7 +199,7 @@ function syncRoom(room, members, cb) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (changed) {
|
if (changed) {
|
||||||
adapter.log.debug('Update "' + obj._id + '"');
|
adapter.log.debug(`Update "${obj._id}"`);
|
||||||
adapter.setForeignObject(obj._id, obj, err => {
|
adapter.setForeignObject(obj._id, obj, err => {
|
||||||
err && adapter.log.error(err);
|
err && adapter.log.error(err);
|
||||||
cb();
|
cb();
|
||||||
@@ -283,8 +305,9 @@ function parseStates(entities, services, callback) {
|
|||||||
common = {};
|
common = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const attrId = attr.replace(adapter.FORBIDDEN_CHARS, '_').replace(/\.+$/, '_');
|
||||||
obj = {
|
obj = {
|
||||||
_id: `${adapter.namespace}.entities.${entity.entity_id}.${attr.replace(adapter.FORBIDDEN_CHARS, '_')}`,
|
_id: `${adapter.namespace}.entities.${entity.entity_id}.${attrId}`,
|
||||||
type: 'state',
|
type: 'state',
|
||||||
common: common,
|
common: common,
|
||||||
native: {
|
native: {
|
||||||
@@ -295,7 +318,7 @@ function parseStates(entities, services, callback) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (!common.name) {
|
if (!common.name) {
|
||||||
common.name = name + ' ' + attr.replace(/_/g, ' ');
|
common.name = `${name} ${attr.replace(/_/g, ' ')}`;
|
||||||
}
|
}
|
||||||
if (common.read === undefined) {
|
if (common.read === undefined) {
|
||||||
common.read = true;
|
common.read = true;
|
||||||
@@ -375,11 +398,15 @@ function main() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = adapter.namespace + '.entities.' + entity.entity_id + '.';
|
const id = `entities.${entity.entity_id}.`;
|
||||||
const lc = entity.last_changed ? new Date(entity.last_changed).getTime() : undefined;
|
const lc = entity.last_changed ? new Date(entity.last_changed).getTime() : undefined;
|
||||||
const ts = entity.last_updated ? new Date(entity.last_updated).getTime() : undefined;
|
const ts = entity.last_updated ? new Date(entity.last_updated).getTime() : undefined;
|
||||||
if (entity.state !== undefined) {
|
if (entity.state !== undefined) {
|
||||||
adapter.setForeignState(id + 'state', {val: entity.state, ack: true, lc: lc, ts: ts});
|
if (hassObjects[`${adapter.namespace}.${id}state`]) {
|
||||||
|
adapter.setState(`${id}state`, {val: entity.state, ack: true, lc: lc, ts: ts});
|
||||||
|
} else {
|
||||||
|
adapter.log.info(`State changed for unknown object ${`${id}state`}. Please restart the adapter to resync the objects.`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (entity.attributes) {
|
if (entity.attributes) {
|
||||||
for (const attr in entity.attributes) {
|
for (const attr in entity.attributes) {
|
||||||
@@ -390,7 +417,12 @@ function main() {
|
|||||||
if ((typeof val === 'object' && val !== null) || Array.isArray(val)) {
|
if ((typeof val === 'object' && val !== null) || Array.isArray(val)) {
|
||||||
val = JSON.stringify(val);
|
val = JSON.stringify(val);
|
||||||
}
|
}
|
||||||
adapter.setForeignState(id + attr.replace(adapter.FORBIDDEN_CHARS, '_'), {val, ack: true, lc, ts});
|
const attrId = attr.replace(adapter.FORBIDDEN_CHARS, '_').replace(/\.+$/, '_');
|
||||||
|
if (hassObjects[`${adapter.namespace}.${id}state`]) {
|
||||||
|
adapter.setState(id + attrId, {val, ack: true, lc, ts});
|
||||||
|
} else {
|
||||||
|
adapter.log.info(`State changed for unknown object ${id + attrId}. Please restart the adapter to resync the objects.`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -402,7 +434,7 @@ function main() {
|
|||||||
adapter.setState('info.connection', true, true);
|
adapter.setState('info.connection', true, true);
|
||||||
hass.getConfig((err, config) => {
|
hass.getConfig((err, config) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
adapter.log.error('Cannot read config: ' + err);
|
adapter.log.error(`Cannot read config: ${err}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//adapter.log.debug(JSON.stringify(config));
|
//adapter.log.debug(JSON.stringify(config));
|
||||||
@@ -413,7 +445,7 @@ function main() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
return adapter.log.error('Cannot read states: ' + err);
|
return adapter.log.error(`Cannot read states: ${err}`);
|
||||||
}
|
}
|
||||||
//adapter.log.debug(JSON.stringify(states));
|
//adapter.log.debug(JSON.stringify(states));
|
||||||
delayTimeout = setTimeout(() => {
|
delayTimeout = setTimeout(() => {
|
||||||
@@ -423,7 +455,7 @@ function main() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
adapter.log.error('Cannot read states: ' + err);
|
adapter.log.error(`Cannot read states: ${err}`);
|
||||||
} else {
|
} else {
|
||||||
//adapter.log.debug(JSON.stringify(services));
|
//adapter.log.debug(JSON.stringify(services));
|
||||||
parseStates(states, services, () => {
|
parseStates(states, services, () => {
|
||||||
|
|||||||
Generated
+6381
File diff suppressed because it is too large
Load Diff
+8
-8
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "iobroker.hass",
|
"name": "iobroker.hass",
|
||||||
"version": "1.2.0",
|
"version": "1.4.0",
|
||||||
"description": "Home Assistant",
|
"description": "Home Assistant",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "bluefox",
|
"name": "bluefox",
|
||||||
@@ -26,17 +26,16 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"websocket": "^1.0.34",
|
"websocket": "^1.0.34",
|
||||||
"ws": "^8.8.0",
|
"ws": "^8.11.0",
|
||||||
"@iobroker/adapter-core": "^2.6.0"
|
"@iobroker/adapter-core": "^2.6.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@alcalzone/release-script": "^3.5.9",
|
"@alcalzone/release-script": "^3.5.9",
|
||||||
"@alcalzone/release-script-plugin-iobroker": "^3.5.9",
|
"@alcalzone/release-script-plugin-iobroker": "^3.5.9",
|
||||||
"@alcalzone/release-script-plugin-license": "^3.5.9",
|
"@alcalzone/release-script-plugin-license": "^3.5.9",
|
||||||
"axios": "^0.27.2",
|
"@iobroker/adapter-dev": "^1.2.0",
|
||||||
"gulp": "^4.0.2",
|
"mocha": "^10.2.0",
|
||||||
"mocha": "^10.0.0",
|
"chai": "^4.3.7"
|
||||||
"chai": "^4.3.6"
|
|
||||||
},
|
},
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -44,7 +43,8 @@
|
|||||||
"release": "release-script",
|
"release": "release-script",
|
||||||
"release-patch": "release-script patch --yes",
|
"release-patch": "release-script patch --yes",
|
||||||
"release-minor": "release-script minor --yes",
|
"release-minor": "release-script minor --yes",
|
||||||
"release-major": "release-script major --yes"
|
"release-major": "release-script major --yes",
|
||||||
|
"translate": "translate-adapter"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/ioBroker/ioBroker.hass/issues"
|
"url": "https://github.com/ioBroker/ioBroker.hass/issues"
|
||||||
|
|||||||
Reference in New Issue
Block a user