### 1.0.0 (2020-12-13)
* (bluefox) added the support of compact mode
This commit is contained in:
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Something is not working as it should
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '...'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots & Logfiles**
|
||||||
|
If applicable, add screenshots and logfiles to help explain your problem.
|
||||||
|
|
||||||
|
**Versions:**
|
||||||
|
- Adapter version: <adapter-version>
|
||||||
|
- JS-Controller version: <js-controller-version> <!-- determine this with `iobroker -v` on the console -->
|
||||||
|
- Node version: <node-version> <!-- determine this with `node -v` on the console -->
|
||||||
|
- Operating system: <os-name>
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
# Configuration for probot-stale - https://github.com/probot/stale
|
||||||
|
|
||||||
|
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
||||||
|
daysUntilStale: 90
|
||||||
|
|
||||||
|
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
|
||||||
|
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
|
||||||
|
daysUntilClose: 7
|
||||||
|
|
||||||
|
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
|
||||||
|
onlyLabels: []
|
||||||
|
|
||||||
|
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
|
||||||
|
exemptLabels:
|
||||||
|
- enhancement
|
||||||
|
- security
|
||||||
|
|
||||||
|
# Set to true to ignore issues in a project (defaults to false)
|
||||||
|
exemptProjects: true
|
||||||
|
|
||||||
|
# Set to true to ignore issues in a milestone (defaults to false)
|
||||||
|
exemptMilestones: true
|
||||||
|
|
||||||
|
# Set to true to ignore issues with an assignee (defaults to false)
|
||||||
|
exemptAssignees: false
|
||||||
|
|
||||||
|
# Label to use when marking as stale
|
||||||
|
staleLabel: wontfix
|
||||||
|
|
||||||
|
# Comment to post when marking as stale. Set to `false` to disable
|
||||||
|
markComment: >
|
||||||
|
This issue has been automatically marked as stale because it has not had
|
||||||
|
recent activity. It will be closed if no further activity occurs within the next 7 days.
|
||||||
|
Please check if the issue is still relevant in the most current version of the adapter
|
||||||
|
and tell us. Also check that all relevant details, logs and reproduction steps
|
||||||
|
are included and update them if needed.
|
||||||
|
Thank you for your contributions.
|
||||||
|
|
||||||
|
Dieses Problem wurde automatisch als veraltet markiert, da es in letzter Zeit keine Aktivitäten gab.
|
||||||
|
Es wird geschlossen, wenn nicht innerhalb der nächsten 7 Tage weitere Aktivitäten stattfinden.
|
||||||
|
Bitte überprüft, ob das Problem auch in der aktuellsten Version des Adapters noch relevant ist,
|
||||||
|
und teilt uns dies mit. Überprüft auch, ob alle relevanten Details, Logs und Reproduktionsschritte
|
||||||
|
enthalten sind bzw. aktualisiert diese.
|
||||||
|
Vielen Dank für Eure Unterstützung.
|
||||||
|
|
||||||
|
# Comment to post when removing the stale label.
|
||||||
|
# unmarkComment: >
|
||||||
|
# Your comment here.
|
||||||
|
|
||||||
|
# Comment to post when closing a stale Issue or Pull Request.
|
||||||
|
closeComment: >
|
||||||
|
This issue has been automatically closed because of inactivity. Please open a new
|
||||||
|
issue if still relevant and make sure to include all relevant details, logs and
|
||||||
|
reproduction steps.
|
||||||
|
Thank you for your contributions.
|
||||||
|
|
||||||
|
Dieses Problem wurde aufgrund von Inaktivität automatisch geschlossen. Bitte öffnet ein
|
||||||
|
neues Issue, falls dies noch relevant ist und stellt sicher das alle relevanten Details,
|
||||||
|
Logs und Reproduktionsschritte enthalten sind.
|
||||||
|
Vielen Dank für Eure Unterstützung.
|
||||||
|
|
||||||
|
# Limit the number of actions per hour, from 1-30. Default is 30
|
||||||
|
limitPerRun: 30
|
||||||
|
|
||||||
|
# Limit to only `issues` or `pulls`
|
||||||
|
only: issues
|
||||||
|
|
||||||
|
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
|
||||||
|
# pulls:
|
||||||
|
# daysUntilStale: 30
|
||||||
|
# markComment: >
|
||||||
|
# This pull request has been automatically marked as stale because it has not had
|
||||||
|
# recent activity. It will be closed if no further activity occurs. Thank you
|
||||||
|
# for your contributions.
|
||||||
|
|
||||||
|
# issues:
|
||||||
|
# exemptLabels:
|
||||||
|
# - confirmed
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
# This is a composition of lint and test scripts
|
||||||
|
# Make sure to update this file along with the others
|
||||||
|
|
||||||
|
name: Test and Release
|
||||||
|
|
||||||
|
# Run this job on all pushes and pull requests
|
||||||
|
# as well as tags with a semantic version
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '*'
|
||||||
|
tags:
|
||||||
|
# normal versions
|
||||||
|
- "v?[0-9]+.[0-9]+.[0-9]+"
|
||||||
|
# pre-releases
|
||||||
|
- "v?[0-9]+.[0-9]+.[0-9]+-**"
|
||||||
|
pull_request: {}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Performs quick checks before the expensive test runs
|
||||||
|
check-and-lint:
|
||||||
|
if: contains(github.event.head_commit.message, '[skip ci]') == false
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [12.x]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
# - name: Perform a type check
|
||||||
|
# run: npm run check:ts
|
||||||
|
# env:
|
||||||
|
# CI: true
|
||||||
|
# - name: Lint TypeScript code
|
||||||
|
# run: npm run lint
|
||||||
|
# - name: Test package files
|
||||||
|
# run: npm run test:package
|
||||||
|
|
||||||
|
# Runs adapter tests on all supported node versions and OSes
|
||||||
|
adapter-tests:
|
||||||
|
if: contains(github.event.head_commit.message, '[skip ci]') == false
|
||||||
|
|
||||||
|
needs: [check-and-lint]
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [10.x, 12.x, 14.x]
|
||||||
|
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Run local tests
|
||||||
|
run: npm test
|
||||||
|
# - name: Run unit tests
|
||||||
|
# run: npm run test:unit
|
||||||
|
# - name: Run integration tests # (linux/osx)
|
||||||
|
# if: startsWith(runner.OS, 'windows') == false
|
||||||
|
# run: DEBUG=testing:* npm run test:integration
|
||||||
|
# - name: Run integration tests # (windows)
|
||||||
|
# if: startsWith(runner.OS, 'windows')
|
||||||
|
# run: set DEBUG=testing:* & npm run test:integration
|
||||||
|
|
||||||
|
# Deploys the final package to NPM
|
||||||
|
deploy:
|
||||||
|
needs: [adapter-tests]
|
||||||
|
|
||||||
|
# Trigger this step only when a commit on master is tagged with a version number
|
||||||
|
if: |
|
||||||
|
contains(github.event.head_commit.message, '[skip ci]') == false &&
|
||||||
|
github.event_name == 'push' &&
|
||||||
|
github.event.base_ref == 'refs/heads/master' &&
|
||||||
|
startsWith(github.ref, 'refs/tags/')
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [12.x]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
|
- name: Extract the version and commit body from the tag
|
||||||
|
id: extract_release
|
||||||
|
# The body may be multiline, therefore we need to escape some characters
|
||||||
|
run: |
|
||||||
|
VERSION="${{ github.ref }}"
|
||||||
|
VERSION=${VERSION##*/}
|
||||||
|
VERSION=${VERSION##*v}
|
||||||
|
echo "::set-output name=VERSION::$VERSION"
|
||||||
|
BODY=$(git show -s --format=%b)
|
||||||
|
BODY="${BODY//'%'/'%25'}"
|
||||||
|
BODY="${BODY//$'\n'/'%0A'}"
|
||||||
|
BODY="${BODY//$'\r'/'%0D'}"
|
||||||
|
echo "::set-output name=BODY::$BODY"
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
# - name: Create a clean build
|
||||||
|
# run: npm run build
|
||||||
|
- name: Publish package to npm
|
||||||
|
run: |
|
||||||
|
npm config set //registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}
|
||||||
|
npm whoami
|
||||||
|
npm publish
|
||||||
|
|
||||||
|
- name: Create Github Release
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
tag_name: ${{ github.ref }}
|
||||||
|
release_name: Release v${{ steps.extract_release.outputs.VERSION }}
|
||||||
|
draft: false
|
||||||
|
# Prerelease versions create prereleases on Github
|
||||||
|
prerelease: ${{ contains(steps.extract_release.outputs.VERSION, '-') }}
|
||||||
|
body: ${{ steps.extract_release.outputs.BODY }}
|
||||||
|
|
||||||
|
#- name: Notify Sentry.io about the release
|
||||||
|
# run: |
|
||||||
|
# npm i -g @sentry/cli
|
||||||
|
# export SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
|
# export SENTRY_URL=https://sentry.iobroker.net
|
||||||
|
# export SENTRY_ORG=iobroker
|
||||||
|
# export SENTRY_PROJECT=iobroker-hass
|
||||||
|
# export SENTRY_VERSION=iobroker.hass@${{ steps.extract_release.outputs.VERSION }}
|
||||||
|
# sentry-cli releases new $SENTRY_VERSION
|
||||||
|
# sentry-cli releases finalize $SENTRY_VERSION
|
||||||
|
|
||||||
|
# Add the following line BEFORE finalize if repositories are connected in Sentry
|
||||||
|
# sentry-cli releases set-commits $SENTRY_VERSION --auto
|
||||||
|
|
||||||
|
# Add the following line BEFORE finalize if sourcemap uploads are needed
|
||||||
|
# sentry-cli releases files $SENTRY_VERSION upload-sourcemaps build/
|
||||||
+11
-8
@@ -1,9 +1,12 @@
|
|||||||
|
/**/*
|
||||||
|
/gulpfile.js
|
||||||
gulpfile.js
|
gulpfile.js
|
||||||
tasks
|
!/admin/**/*
|
||||||
tmp
|
!/admin/*
|
||||||
test
|
!/lib/**/*
|
||||||
.travis.yml
|
!/lib/*
|
||||||
appveyor.yml
|
!/io-package.json
|
||||||
admin/i18n
|
!/package.json
|
||||||
iob_npm.done
|
!/LICENSE
|
||||||
package-lock.json
|
!/main.js
|
||||||
|
!/README.md
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2018 bluefox <dogafox@gmail.com>
|
Copyright (c) 2018-2020 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
|
||||||
|
|||||||
@@ -1,23 +1,38 @@
|
|||||||

|

|
||||||
# ioBroker.hass
|
# ioBroker.hass
|
||||||
=================
|
|
||||||
|
|
||||||
[](https://www.npmjs.com/package/iobroker.hass)
|
[](https://www.npmjs.com/package/iobroker.hass)
|
||||||
[](https://www.npmjs.com/package/iobroker.hass)
|
[](https://www.npmjs.com/package/iobroker.hass)
|
||||||
|
|
||||||
[](https://nodei.co/npm/iobroker.hass/)
|
|
||||||
|
|
||||||
|
This adapter allows the connecting of Home Assistant to ioBroker.
|
||||||
|
|
||||||
This adapter allows connect Home Assistant to ioBroker.
|
## Usage
|
||||||
|
Create a long term token in HASS and use it as PW (copy it also in the repeat field).
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
There is a good article about connection.
|
||||||
|
|
||||||
|
Please check it https://www.smarthomejetzt.de/mit-iobroker-auf-eine-home-assistant-hass-io-installation-und-die-geraete-zugreifen/
|
||||||
|
|
||||||
|
**Unfortunately only in german, but the [google translate works rather good](https://translate.google.com/translate?hl=en&sl=de&tl=en&u=https%3A%2F%2Fwww.smarthomejetzt.de%2Fmit-iobroker-auf-eine-home-assistant-hass-io-installation-und-die-geraete-zugreifen%2F)**
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Placeholder for the next version (at the beginning of the line):
|
||||||
|
### __WORK IN PROGRESS__
|
||||||
|
-->
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
#### 0.1.0
|
### 1.0.0 (2020-12-13)
|
||||||
|
* (bluefox) added the support of compact mode
|
||||||
|
|
||||||
|
### 0.1.0
|
||||||
* (bluefox) initial release
|
* (bluefox) initial release
|
||||||
|
|
||||||
## License
|
## License
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2018 bluefox <dogafox@gmail.com>
|
Copyright (c) 2018-2020 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
|
||||||
|
|||||||
+1
-2
@@ -56,12 +56,11 @@
|
|||||||
callback(obj);
|
callback(obj);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="adapter-container">
|
<div id="adapter-container">
|
||||||
<table><tr>
|
<table><tr>
|
||||||
<td><img src="hass.png"/></td>
|
<td><img src="hass.png" alt="logo"/></td>
|
||||||
<td><h3 class="translate">Home assistant adapter settings</h3></td>
|
<td><h3 class="translate">Home assistant adapter settings</h3></td>
|
||||||
</tr></table>
|
</tr></table>
|
||||||
<table>
|
<table>
|
||||||
|
|||||||
+88
-86
@@ -1,10 +1,10 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var gulp = require('gulp');
|
const gulp = require('gulp');
|
||||||
var fs = require('fs');
|
const fs = require('fs');
|
||||||
var pkg = require('./package.json');
|
const pkg = require('./package.json');
|
||||||
var iopackage = require('./io-package.json');
|
const iopackage = require('./io-package.json');
|
||||||
var version = (pkg && pkg.version) ? pkg.version : iopackage.common.version;
|
const version = (pkg && pkg.version) ? pkg.version : iopackage.common.version;
|
||||||
/*var appName = getAppName();
|
/*var appName = getAppName();
|
||||||
|
|
||||||
function getAppName() {
|
function getAppName() {
|
||||||
@@ -13,7 +13,7 @@ function getAppName() {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
const fileName = 'words.js';
|
const fileName = 'words.js';
|
||||||
var languages = {
|
let languages = {
|
||||||
en: {},
|
en: {},
|
||||||
de: {},
|
de: {},
|
||||||
ru: {},
|
ru: {},
|
||||||
@@ -22,24 +22,27 @@ var languages = {
|
|||||||
fr: {},
|
fr: {},
|
||||||
it: {},
|
it: {},
|
||||||
es: {},
|
es: {},
|
||||||
pl: {}
|
pl: {},
|
||||||
|
'zh-cn': {}
|
||||||
};
|
};
|
||||||
|
|
||||||
function lang2data(lang, isFlat) {
|
function lang2data(lang, isFlat) {
|
||||||
var str = isFlat ? '' : '{\n';
|
let str = isFlat ? '' : '{\n';
|
||||||
var count = 0;
|
let count = 0;
|
||||||
for (var w in lang) {
|
for (const w in lang) {
|
||||||
if (lang.hasOwnProperty(w)) {
|
if (lang.hasOwnProperty(w)) {
|
||||||
count++;
|
count++;
|
||||||
if (isFlat) {
|
if (isFlat) {
|
||||||
str += (lang[w] === '' ? (isFlat[w] || w) : lang[w]) + '\n';
|
str += (lang[w] === '' ? (isFlat[w] || w) : lang[w]) + '\n';
|
||||||
} else {
|
} else {
|
||||||
var key = ' "' + w.replace(/"/g, '\\"') + '": ';
|
const key = ' "' + w.replace(/"/g, '\\"') + '": ';
|
||||||
str += key + '"' + lang[w].replace(/"/g, '\\"') + '",\n';
|
str += key + '"' + lang[w].replace(/"/g, '\\"') + '",\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!count) return isFlat ? '' : '{\n}';
|
if (!count) {
|
||||||
|
return isFlat ? '' : '{\n}';
|
||||||
|
}
|
||||||
if (isFlat) {
|
if (isFlat) {
|
||||||
return str;
|
return str;
|
||||||
} else {
|
} else {
|
||||||
@@ -49,15 +52,15 @@ function lang2data(lang, isFlat) {
|
|||||||
|
|
||||||
function readWordJs(src) {
|
function readWordJs(src) {
|
||||||
try {
|
try {
|
||||||
var words;
|
let words;
|
||||||
if (fs.existsSync(src + 'js/' + fileName)) {
|
if (fs.existsSync(src + 'js/' + fileName)) {
|
||||||
words = fs.readFileSync(src + 'js/' + fileName).toString();
|
words = fs.readFileSync(src + 'js/' + fileName).toString();
|
||||||
} else {
|
} else {
|
||||||
words = fs.readFileSync(src + fileName).toString();
|
words = fs.readFileSync(src + fileName).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
var lines = words.split(/\r\n|\r|\n/g);
|
const lines = words.split(/\r\n|\r|\n/g);
|
||||||
var i = 0;
|
let i = 0;
|
||||||
while (!lines[i].match(/^systemDictionary = {/)) {
|
while (!lines[i].match(/^systemDictionary = {/)) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -75,7 +78,7 @@ function readWordJs(src) {
|
|||||||
lines[0] = lines[0].replace('systemDictionary = ', '');
|
lines[0] = lines[0].replace('systemDictionary = ', '');
|
||||||
lines[lines.length - 1] = lines[lines.length - 1].trim().replace(/};$/, '}');
|
lines[lines.length - 1] = lines[lines.length - 1].trim().replace(/};$/, '}');
|
||||||
words = lines.join('\n');
|
words = lines.join('\n');
|
||||||
var resultFunc = new Function('return ' + words + ';');
|
const resultFunc = new Function('return ' + words + ';');
|
||||||
|
|
||||||
return resultFunc();
|
return resultFunc();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -86,16 +89,16 @@ function padRight(text, totalLength) {
|
|||||||
return text + (text.length < totalLength ? new Array(totalLength - text.length).join(' ') : '');
|
return text + (text.length < totalLength ? new Array(totalLength - text.length).join(' ') : '');
|
||||||
}
|
}
|
||||||
function writeWordJs(data, src) {
|
function writeWordJs(data, src) {
|
||||||
var text = '// DO NOT EDIT THIS FILE!!! IT WILL BE AUTOMATICALLY GENERATED FROM src/i18n\n';
|
let text = '// DO NOT EDIT THIS FILE!!! IT WILL BE AUTOMATICALLY GENERATED FROM src/i18n\n';
|
||||||
text += '/*global systemDictionary:true */\n';
|
text += '/*global systemDictionary:true */\n';
|
||||||
text += '\'use strict\';\n\n';
|
text += '\'use strict\';\n\n';
|
||||||
|
|
||||||
text += 'systemDictionary = {\n';
|
text += 'systemDictionary = {\n';
|
||||||
for (var word in data) {
|
for (const word in data) {
|
||||||
if (data.hasOwnProperty(word)) {
|
if (data.hasOwnProperty(word)) {
|
||||||
text += ' ' + padRight('"' + word.replace(/"/g, '\\"') + '": {', 50);
|
text += ' ' + padRight('"' + word.replace(/"/g, '\\"') + '": {', 50);
|
||||||
var line = '';
|
let line = '';
|
||||||
for (var lang in data[word]) {
|
for (const lang in data[word]) {
|
||||||
if (data[word].hasOwnProperty(lang)) {
|
if (data[word].hasOwnProperty(lang)) {
|
||||||
line += '"' + lang + '": "' + padRight(data[word][lang].replace(/"/g, '\\"') + '",', 50) + ' ';
|
line += '"' + lang + '": "' + padRight(data[word][lang].replace(/"/g, '\\"') + '",', 50) + ' ';
|
||||||
}
|
}
|
||||||
@@ -120,16 +123,16 @@ function writeWordJs(data, src) {
|
|||||||
const EMPTY = '';
|
const EMPTY = '';
|
||||||
|
|
||||||
function words2languages(src) {
|
function words2languages(src) {
|
||||||
var langs = Object.assign({}, languages);
|
const langs = Object.assign({}, languages);
|
||||||
var data = readWordJs(src);
|
const data = readWordJs(src);
|
||||||
if (data) {
|
if (data) {
|
||||||
for (var word in data) {
|
for (const word in data) {
|
||||||
if (data.hasOwnProperty(word)) {
|
if (data.hasOwnProperty(word)) {
|
||||||
for (var lang in data[word]) {
|
for (const lang in data[word]) {
|
||||||
if (data[word].hasOwnProperty(lang)) {
|
if (data[word].hasOwnProperty(lang)) {
|
||||||
langs[lang][word] = data[word][lang];
|
langs[lang][word] = data[word][lang];
|
||||||
// pre-fill all other languages
|
// pre-fill all other languages
|
||||||
for (var j in langs) {
|
for (const j in langs) {
|
||||||
if (langs.hasOwnProperty(j)) {
|
if (langs.hasOwnProperty(j)) {
|
||||||
langs[j][word] = langs[j][word] || EMPTY;
|
langs[j][word] = langs[j][word] || EMPTY;
|
||||||
}
|
}
|
||||||
@@ -141,12 +144,12 @@ function words2languages(src) {
|
|||||||
if (!fs.existsSync(src + 'i18n/')) {
|
if (!fs.existsSync(src + 'i18n/')) {
|
||||||
fs.mkdirSync(src + 'i18n/');
|
fs.mkdirSync(src + 'i18n/');
|
||||||
}
|
}
|
||||||
for (var l in langs) {
|
for (const l in langs) {
|
||||||
if (!langs.hasOwnProperty(l)) continue;
|
if (!langs.hasOwnProperty(l)) continue;
|
||||||
var keys = Object.keys(langs[l]);
|
const keys = Object.keys(langs[l]);
|
||||||
//keys.sort();
|
//keys.sort();
|
||||||
var obj = {};
|
let obj = {};
|
||||||
for (var k = 0; k < keys.length; k++) {
|
for (let k = 0; k < keys.length; k++) {
|
||||||
obj[keys[k]] = langs[l][keys[k]];
|
obj[keys[k]] = langs[l][keys[k]];
|
||||||
}
|
}
|
||||||
if (!fs.existsSync(src + 'i18n/' + l)) {
|
if (!fs.existsSync(src + 'i18n/' + l)) {
|
||||||
@@ -160,16 +163,16 @@ function words2languages(src) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
function words2languagesFlat(src) {
|
function words2languagesFlat(src) {
|
||||||
var langs = Object.assign({}, languages);
|
let langs = Object.assign({}, languages);
|
||||||
var data = readWordJs(src);
|
const data = readWordJs(src);
|
||||||
if (data) {
|
if (data) {
|
||||||
for (var word in data) {
|
for (const word in data) {
|
||||||
if (data.hasOwnProperty(word)) {
|
if (data.hasOwnProperty(word)) {
|
||||||
for (var lang in data[word]) {
|
for (const lang in data[word]) {
|
||||||
if (data[word].hasOwnProperty(lang)) {
|
if (data[word].hasOwnProperty(lang)) {
|
||||||
langs[lang][word] = data[word][lang];
|
langs[lang][word] = data[word][lang];
|
||||||
// pre-fill all other languages
|
// pre-fill all other languages
|
||||||
for (var j in langs) {
|
for (const j in langs) {
|
||||||
if (langs.hasOwnProperty(j)) {
|
if (langs.hasOwnProperty(j)) {
|
||||||
langs[j][word] = langs[j][word] || EMPTY;
|
langs[j][word] = langs[j][word] || EMPTY;
|
||||||
}
|
}
|
||||||
@@ -178,12 +181,12 @@ function words2languagesFlat(src) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var keys = Object.keys(langs.en);
|
const keys = Object.keys(langs.en);
|
||||||
//keys.sort();
|
//keys.sort();
|
||||||
for (var l in langs) {
|
for (const l in langs) {
|
||||||
if (!langs.hasOwnProperty(l)) continue;
|
if (!langs.hasOwnProperty(l)) continue;
|
||||||
var obj = {};
|
let obj = {};
|
||||||
for (var k = 0; k < keys.length; k++) {
|
for (let k = 0; k < keys.length; k++) {
|
||||||
obj[keys[k]] = langs[l][keys[k]];
|
obj[keys[k]] = langs[l][keys[k]];
|
||||||
}
|
}
|
||||||
langs[l] = obj;
|
langs[l] = obj;
|
||||||
@@ -191,7 +194,7 @@ function words2languagesFlat(src) {
|
|||||||
if (!fs.existsSync(src + 'i18n/')) {
|
if (!fs.existsSync(src + 'i18n/')) {
|
||||||
fs.mkdirSync(src + 'i18n/');
|
fs.mkdirSync(src + 'i18n/');
|
||||||
}
|
}
|
||||||
for (var ll in langs) {
|
for (const ll in langs) {
|
||||||
if (!langs.hasOwnProperty(ll)) continue;
|
if (!langs.hasOwnProperty(ll)) continue;
|
||||||
if (!fs.existsSync(src + 'i18n/' + ll)) {
|
if (!fs.existsSync(src + 'i18n/' + ll)) {
|
||||||
fs.mkdirSync(src + 'i18n/' + ll);
|
fs.mkdirSync(src + 'i18n/' + ll);
|
||||||
@@ -205,13 +208,13 @@ function words2languagesFlat(src) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
function languagesFlat2words(src) {
|
function languagesFlat2words(src) {
|
||||||
var dirs = fs.readdirSync(src + 'i18n/');
|
const dirs = fs.readdirSync(src + 'i18n/');
|
||||||
var langs = {};
|
let langs = {};
|
||||||
var bigOne = {};
|
let bigOne = {};
|
||||||
var order = Object.keys(languages);
|
const order = Object.keys(languages);
|
||||||
dirs.sort(function (a, b) {
|
dirs.sort((a, b) => {
|
||||||
var posA = order.indexOf(a);
|
const posA = order.indexOf(a);
|
||||||
var posB = order.indexOf(b);
|
const posB = order.indexOf(b);
|
||||||
if (posA === -1 && posB === -1) {
|
if (posA === -1 && posB === -1) {
|
||||||
if (a > b) return 1;
|
if (a > b) return 1;
|
||||||
if (a < b) return -1;
|
if (a < b) return -1;
|
||||||
@@ -226,19 +229,19 @@ function languagesFlat2words(src) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var keys = fs.readFileSync(src + 'i18n/flat.txt').toString().split('\n');
|
const keys = fs.readFileSync(src + 'i18n/flat.txt').toString().split('\n');
|
||||||
|
|
||||||
for (var l = 0; l < dirs.length; l++) {
|
for (let l = 0; l < dirs.length; l++) {
|
||||||
if (dirs[l] === 'flat.txt') continue;
|
if (dirs[l] === 'flat.txt') continue;
|
||||||
var lang = dirs[l];
|
let lang = dirs[l];
|
||||||
var values = fs.readFileSync(src + 'i18n/' + lang + '/flat.txt').toString().split('\n');
|
const values = fs.readFileSync(src + 'i18n/' + lang + '/flat.txt').toString().split('\n');
|
||||||
langs[lang] = {};
|
langs[lang] = {};
|
||||||
keys.forEach(function (word, i) {
|
keys.forEach(function (word, i) {
|
||||||
langs[lang][word] = values[i].replace(/<\/ i>/g, '</i>').replace(/<\/ b>/g, '</b>').replace(/<\/ span>/g, '</span>').replace(/% s/g, ' %s');
|
langs[lang][word] = values[i].replace(/<\/ i>/g, '</i>').replace(/<\/ b>/g, '</b>').replace(/<\/ span>/g, '</span>').replace(/% s/g, ' %s');
|
||||||
});
|
});
|
||||||
|
|
||||||
var words = langs[lang];
|
const words = langs[lang];
|
||||||
for (var word in words) {
|
for (const word in words) {
|
||||||
if (words.hasOwnProperty(word)) {
|
if (words.hasOwnProperty(word)) {
|
||||||
bigOne[word] = bigOne[word] || {};
|
bigOne[word] = bigOne[word] || {};
|
||||||
if (words[word] !== EMPTY) {
|
if (words[word] !== EMPTY) {
|
||||||
@@ -248,12 +251,12 @@ function languagesFlat2words(src) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// read actual words.js
|
// read actual words.js
|
||||||
var aWords = readWordJs();
|
const aWords = readWordJs();
|
||||||
|
|
||||||
var temporaryIgnore = ['pt', 'fr', 'nl', 'flat.txt'];
|
const temporaryIgnore = ['pt', 'fr', 'nl', 'flat.txt'];
|
||||||
if (aWords) {
|
if (aWords) {
|
||||||
// Merge words together
|
// Merge words together
|
||||||
for (var w in aWords) {
|
for (const w in aWords) {
|
||||||
if (aWords.hasOwnProperty(w)) {
|
if (aWords.hasOwnProperty(w)) {
|
||||||
if (!bigOne[w]) {
|
if (!bigOne[w]) {
|
||||||
console.warn('Take from actual words.js: ' + w);
|
console.warn('Take from actual words.js: ' + w);
|
||||||
@@ -273,13 +276,13 @@ function languagesFlat2words(src) {
|
|||||||
writeWordJs(bigOne, src);
|
writeWordJs(bigOne, src);
|
||||||
}
|
}
|
||||||
function languages2words(src) {
|
function languages2words(src) {
|
||||||
var dirs = fs.readdirSync(src + 'i18n/');
|
const dirs = fs.readdirSync(src + 'i18n/');
|
||||||
var langs = {};
|
let langs = {};
|
||||||
var bigOne = {};
|
let bigOne = {};
|
||||||
var order = Object.keys(languages);
|
const order = Object.keys(languages);
|
||||||
dirs.sort(function (a, b) {
|
dirs.sort((a, b) => {
|
||||||
var posA = order.indexOf(a);
|
const posA = order.indexOf(a);
|
||||||
var posB = order.indexOf(b);
|
const posB = order.indexOf(b);
|
||||||
if (posA === -1 && posB === -1) {
|
if (posA === -1 && posB === -1) {
|
||||||
if (a > b) return 1;
|
if (a > b) return 1;
|
||||||
if (a < b) return -1;
|
if (a < b) return -1;
|
||||||
@@ -294,13 +297,13 @@ function languages2words(src) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
for (var l = 0; l < dirs.length; l++) {
|
for (let l = 0; l < dirs.length; l++) {
|
||||||
if (dirs[l] === 'flat.txt') continue;
|
if (dirs[l] === 'flat.txt') continue;
|
||||||
var lang = dirs[l];
|
const lang = dirs[l];
|
||||||
langs[lang] = fs.readFileSync(src + 'i18n/' + lang + '/translations.json').toString();
|
langs[lang] = fs.readFileSync(src + 'i18n/' + lang + '/translations.json').toString();
|
||||||
langs[lang] = JSON.parse(langs[lang]);
|
langs[lang] = JSON.parse(langs[lang]);
|
||||||
var words = langs[lang];
|
const words = langs[lang];
|
||||||
for (var word in words) {
|
for (const word in words) {
|
||||||
if (words.hasOwnProperty(word)) {
|
if (words.hasOwnProperty(word)) {
|
||||||
bigOne[word] = bigOne[word] || {};
|
bigOne[word] = bigOne[word] || {};
|
||||||
if (words[word] !== EMPTY) {
|
if (words[word] !== EMPTY) {
|
||||||
@@ -310,12 +313,12 @@ function languages2words(src) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// read actual words.js
|
// read actual words.js
|
||||||
var aWords = readWordJs();
|
const aWords = readWordJs();
|
||||||
|
|
||||||
var temporaryIgnore = ['pt', 'fr', 'nl', 'it'];
|
const temporaryIgnore = ['pt', 'fr', 'nl', 'it'];
|
||||||
if (aWords) {
|
if (aWords) {
|
||||||
// Merge words together
|
// Merge words together
|
||||||
for (var w in aWords) {
|
for (const w in aWords) {
|
||||||
if (aWords.hasOwnProperty(w)) {
|
if (aWords.hasOwnProperty(w)) {
|
||||||
if (!bigOne[w]) {
|
if (!bigOne[w]) {
|
||||||
console.warn('Take from actual words.js: ' + w);
|
console.warn('Take from actual words.js: ' + w);
|
||||||
@@ -335,33 +338,32 @@ function languages2words(src) {
|
|||||||
writeWordJs(bigOne, src);
|
writeWordJs(bigOne, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
gulp.task('adminWords2languages', function (done) {
|
gulp.task('admin (words.js => json)', done => {
|
||||||
words2languages('./admin/');
|
words2languages('./admin/');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('adminWords2languagesFlat', function (done) {
|
gulp.task('admin (words.js => flat)', done => {
|
||||||
words2languagesFlat('./admin/');
|
words2languagesFlat('./admin/');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('adminLanguagesFlat2words', function (done) {
|
gulp.task('admin (flat => words.js)', done => {
|
||||||
languagesFlat2words('./admin/');
|
languagesFlat2words('./admin/');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('adminLanguages2words', function (done) {
|
gulp.task('admin (json => words.js)', done => {
|
||||||
languages2words('./admin/');
|
languages2words('./admin/');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
gulp.task('updatePackages', done => {
|
||||||
gulp.task('updatePackages', function (done) {
|
|
||||||
iopackage.common.version = pkg.version;
|
iopackage.common.version = pkg.version;
|
||||||
iopackage.common.news = iopackage.common.news || {};
|
iopackage.common.news = iopackage.common.news || {};
|
||||||
if (!iopackage.common.news[pkg.version]) {
|
if (!iopackage.common.news[pkg.version]) {
|
||||||
var news = iopackage.common.news;
|
const news = iopackage.common.news;
|
||||||
var newNews = {};
|
let newNews = {};
|
||||||
|
|
||||||
newNews[pkg.version] = {
|
newNews[pkg.version] = {
|
||||||
en: 'news',
|
en: 'news',
|
||||||
@@ -374,20 +376,20 @@ gulp.task('updatePackages', function (done) {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('updateReadme', function (done) {
|
gulp.task('updateReadme', done => {
|
||||||
var readme = fs.readFileSync('README.md').toString();
|
const readme = fs.readFileSync('README.md').toString();
|
||||||
var pos = readme.indexOf('## Changelog\n');
|
const pos = readme.indexOf('## Changelog\n');
|
||||||
if (pos !== -1) {
|
if (pos !== -1) {
|
||||||
var readmeStart = readme.substring(0, pos + '## Changelog\n'.length);
|
let readmeStart = readme.substring(0, pos + '## Changelog\n'.length);
|
||||||
var readmeEnd = readme.substring(pos + '## Changelog\n'.length);
|
let readmeEnd = readme.substring(pos + '## Changelog\n'.length);
|
||||||
|
|
||||||
if (readme.indexOf(version) === -1) {
|
if (readme.indexOf(version) === -1) {
|
||||||
var timestamp = new Date();
|
const timestamp = new Date();
|
||||||
var date = timestamp.getFullYear() + '-' +
|
const date = timestamp.getFullYear() + '-' +
|
||||||
('0' + (timestamp.getMonth() + 1).toString(10)).slice(-2) + '-' +
|
('0' + (timestamp.getMonth() + 1).toString(10)).slice(-2) + '-' +
|
||||||
('0' + (timestamp.getDate()).toString(10)).slice(-2);
|
('0' + (timestamp.getDate()).toString(10)).slice(-2);
|
||||||
|
|
||||||
var news = '';
|
let news = '';
|
||||||
if (iopackage.common.news && iopackage.common.news[pkg.version]) {
|
if (iopackage.common.news && iopackage.common.news[pkg.version]) {
|
||||||
news += '* ' + iopackage.common.news[pkg.version].en;
|
news += '* ' + iopackage.common.news[pkg.version].en;
|
||||||
}
|
}
|
||||||
@@ -398,4 +400,4 @@ gulp.task('updateReadme', function (done) {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('default', ['updatePackages', 'updateReadme']);
|
gulp.task('default', gulp.series('updatePackages', 'updateReadme'));
|
||||||
+74
-56
@@ -1,58 +1,76 @@
|
|||||||
{
|
{
|
||||||
"common": {
|
"common": {
|
||||||
"name": "hass",
|
"name": "hass",
|
||||||
"version": "0.1.0",
|
"version": "1.0.0",
|
||||||
"title": "Home Assistant",
|
"title": "Home Assistant",
|
||||||
"desc": {
|
"desc": {
|
||||||
"en": "Home Assistant connection for ioBroker",
|
"en": "Home Assistant connection for ioBroker",
|
||||||
"de": "Home Assistant Verbindung für ioBroker",
|
"de": "Home Assistant Verbindung für ioBroker",
|
||||||
"ru": "Подключение Home Assistant для ioBroker",
|
"ru": "Подключение Home Assistant для ioBroker",
|
||||||
"pt": "Conexão do Home Assistant para ioBroker",
|
"pt": "Conexão do Home Assistant para ioBroker",
|
||||||
"nl": "Home Assistant-verbinding voor ioBroker",
|
"nl": "Home Assistant-verbinding voor ioBroker",
|
||||||
"fr": "Connexion Home Assistant pour ioBroker",
|
"fr": "Connexion Home Assistant pour ioBroker",
|
||||||
"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"
|
||||||
},
|
|
||||||
"news": {
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"localLink": "http://%host%:8123",
|
|
||||||
"platform": "Javascript/Node.js",
|
|
||||||
"mode": "daemon",
|
|
||||||
"icon": "hass.png",
|
|
||||||
"enabled": true,
|
|
||||||
"extIcon": "https://raw.githubusercontent.com/ioBroker/ioBroker.hass/master/admin/hass.png",
|
|
||||||
"keywords": ["HASS", "Home", "assistant"],
|
|
||||||
"readme": "https://github.com/ioBroker/ioBroker.hass/blob/master/README.md",
|
|
||||||
"loglevel": "info",
|
|
||||||
"type": "iot-systems",
|
|
||||||
"authors": [
|
|
||||||
"bluefox <dogafox@gmail.com>"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"native": {
|
"news": {
|
||||||
"host": "127.0.0.1",
|
"1.0.0": {
|
||||||
"port": 8123,
|
"en": "added the support of compact mode",
|
||||||
"password": "",
|
"de": "fügte die Unterstützung des Kompaktmodus hinzu",
|
||||||
"secure": false
|
"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"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"objects": [
|
"localLink": "http://%host%:8123",
|
||||||
|
"platform": "Javascript/Node.js",
|
||||||
|
"mode": "daemon",
|
||||||
|
"icon": "hass.png",
|
||||||
|
"enabled": true,
|
||||||
|
"compact": true,
|
||||||
|
"materialize": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"extIcon": "https://raw.githubusercontent.com/ioBroker/ioBroker.hass/master/admin/hass.png",
|
||||||
|
"keywords": [
|
||||||
|
"HASS",
|
||||||
|
"Home",
|
||||||
|
"assistant"
|
||||||
],
|
],
|
||||||
|
"readme": "https://github.com/ioBroker/ioBroker.hass/blob/master/README.md",
|
||||||
|
"loglevel": "info",
|
||||||
|
"type": "iot-systems",
|
||||||
|
"authors": [
|
||||||
|
"bluefox <dogafox@gmail.com>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"native": {
|
||||||
|
"host": "127.0.0.1",
|
||||||
|
"port": 8123,
|
||||||
|
"password": "",
|
||||||
|
"secure": false
|
||||||
|
},
|
||||||
|
"objects": [
|
||||||
|
],
|
||||||
"instanceObjects": [
|
"instanceObjects": [
|
||||||
{
|
{
|
||||||
"_id": "info",
|
"_id": "info",
|
||||||
"type": "channel",
|
"type": "channel",
|
||||||
"common": {
|
"common": {
|
||||||
"name": "Information"
|
"name": "Information"
|
||||||
@@ -60,20 +78,20 @@
|
|||||||
"native": {}
|
"native": {}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"_id": "info.connection",
|
"_id": "info.connection",
|
||||||
"type": "state",
|
"type": "state",
|
||||||
"common": {
|
"common": {
|
||||||
"role": "indicator.connected",
|
"role": "indicator.connected",
|
||||||
"name": "If connected to HASS server",
|
"name": "If connected to HASS server",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"read": true,
|
"read": true,
|
||||||
"write": false,
|
"write": false,
|
||||||
"def": false
|
"def": false
|
||||||
},
|
},
|
||||||
"native": {}
|
"native": {}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"_id": "entities",
|
"_id": "entities",
|
||||||
"type": "channel",
|
"type": "channel",
|
||||||
"common": {
|
"common": {
|
||||||
"name": "HASS entities"
|
"name": "HASS entities"
|
||||||
|
|||||||
+37
-50
@@ -1,30 +1,32 @@
|
|||||||
var util = require('util');
|
const util = require('util');
|
||||||
var EventEmitter = require('events').EventEmitter;
|
const EventEmitter = require('events').EventEmitter;
|
||||||
var WebSocket = require('ws');
|
const WebSocket = require('ws');
|
||||||
|
|
||||||
function HASS(options, log) {
|
function HASS(options, log) {
|
||||||
if (!(this instanceof HASS)) return new HASS(options);
|
if (!(this instanceof HASS)) {
|
||||||
|
return new HASS(options);
|
||||||
|
}
|
||||||
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
options.host = options.host || '127.0.0.1';
|
options.host = options.host || '127.0.0.1';
|
||||||
options.port = parseInt(options.port, 10) || 8123;
|
options.port = parseInt(options.port, 10) || 8123;
|
||||||
|
|
||||||
var ERRORS = {
|
const ERRORS = {
|
||||||
1: 'ERR_CANNOT_CONNECT',
|
1: 'ERR_CANNOT_CONNECT',
|
||||||
2: 'ERR_INVALID_AUTH',
|
2: 'ERR_INVALID_AUTH',
|
||||||
3: 'ERR_CONNECTION_LOST'
|
3: 'ERR_CONNECTION_LOST'
|
||||||
};
|
};
|
||||||
|
|
||||||
this.socket = null;
|
this.socket = null;
|
||||||
var that = this;
|
const that = this;
|
||||||
var currentId = 1;
|
let currentId = 1;
|
||||||
var requests = {};
|
const requests = {};
|
||||||
var connected;
|
let connected;
|
||||||
var connectTimeout = null;
|
let connectTimeout = null;
|
||||||
|
|
||||||
function subscribeEvents(socket, callback) {
|
function subscribeEvents(socket, callback) {
|
||||||
if (socket && typeof socket.send === 'function') {
|
if (socket && typeof socket.send === 'function') {
|
||||||
var id = currentId++;
|
const id = currentId++;
|
||||||
requests[id] = {type: 'subscribe_events', ts: Date.now(), cb: callback};
|
requests[id] = {type: 'subscribe_events', ts: Date.now(), cb: callback};
|
||||||
|
|
||||||
socket.send(JSON.stringify({
|
socket.send(JSON.stringify({
|
||||||
@@ -39,7 +41,7 @@ function HASS(options, log) {
|
|||||||
|
|
||||||
function getConfig(socket, callback) {
|
function getConfig(socket, callback) {
|
||||||
if (socket && typeof socket.send === 'function') {
|
if (socket && typeof socket.send === 'function') {
|
||||||
var id = currentId++;
|
const id = currentId++;
|
||||||
requests[id] = {type: 'get_config', cb: callback, ts: Date.now()};
|
requests[id] = {type: 'get_config', cb: callback, ts: Date.now()};
|
||||||
socket.send(JSON.stringify({
|
socket.send(JSON.stringify({
|
||||||
id: id,
|
id: id,
|
||||||
@@ -52,7 +54,7 @@ function HASS(options, log) {
|
|||||||
|
|
||||||
function getStates(socket, callback) {
|
function getStates(socket, callback) {
|
||||||
if (socket && typeof socket.send === 'function') {
|
if (socket && typeof socket.send === 'function') {
|
||||||
var id = currentId++;
|
const id = currentId++;
|
||||||
requests[id] = {type: 'get_states', cb: callback, ts: Date.now()};
|
requests[id] = {type: 'get_states', cb: callback, ts: Date.now()};
|
||||||
socket.send(JSON.stringify({
|
socket.send(JSON.stringify({
|
||||||
id: id,
|
id: id,
|
||||||
@@ -65,7 +67,7 @@ function HASS(options, log) {
|
|||||||
|
|
||||||
function getPanels(socket, callback) {
|
function getPanels(socket, callback) {
|
||||||
if (socket && typeof socket.send === 'function') {
|
if (socket && typeof socket.send === 'function') {
|
||||||
var id = currentId++;
|
const id = currentId++;
|
||||||
requests[id] = {type: 'get_panels', cb: callback, ts: Date.now()};
|
requests[id] = {type: 'get_panels', cb: callback, ts: Date.now()};
|
||||||
socket.send(JSON.stringify({
|
socket.send(JSON.stringify({
|
||||||
id: id,
|
id: id,
|
||||||
@@ -78,7 +80,7 @@ function HASS(options, log) {
|
|||||||
|
|
||||||
function getServices(socket, callback) {
|
function getServices(socket, callback) {
|
||||||
if (socket && typeof socket.send === 'function') {
|
if (socket && typeof socket.send === 'function') {
|
||||||
var id = currentId++;
|
const id = currentId++;
|
||||||
requests[id] = {type: 'get_services', cb: callback, ts: Date.now()};
|
requests[id] = {type: 'get_services', cb: callback, ts: Date.now()};
|
||||||
socket.send(JSON.stringify({
|
socket.send(JSON.stringify({
|
||||||
id: id,
|
id: id,
|
||||||
@@ -91,7 +93,7 @@ function HASS(options, log) {
|
|||||||
|
|
||||||
function callService(socket, service, domain, serviceData, callback) {
|
function callService(socket, service, domain, serviceData, callback) {
|
||||||
if (socket && typeof socket.send === 'function') {
|
if (socket && typeof socket.send === 'function') {
|
||||||
var id = currentId++;
|
const id = currentId++;
|
||||||
requests[id] = {type: 'call_service', cb: callback, ts: Date.now()};
|
requests[id] = {type: 'call_service', cb: callback, ts: Date.now()};
|
||||||
socket.send(JSON.stringify({
|
socket.send(JSON.stringify({
|
||||||
id: id,
|
id: id,
|
||||||
@@ -115,10 +117,10 @@ function HASS(options, log) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function initSocket(socket) {
|
function initSocket(socket) {
|
||||||
socket.on('message', function (msg) {
|
socket.on('message', msg => {
|
||||||
log.silly(msg);
|
log.silly(msg);
|
||||||
|
|
||||||
var response = JSON.parse(msg);
|
const response = JSON.parse(msg);
|
||||||
if (response.type === 'event') {
|
if (response.type === 'event') {
|
||||||
if (response.event.data && response.event.event_type === 'system_log_event') {
|
if (response.event.data && response.event.event_type === 'system_log_event') {
|
||||||
if (response.event.data.level === 'WARNING') {
|
if (response.event.data.level === 'WARNING') {
|
||||||
@@ -138,25 +140,22 @@ function HASS(options, log) {
|
|||||||
that.emit('error', 'Password required. Connection closed');
|
that.emit('error', 'Password required. Connection closed');
|
||||||
socket.terminate();
|
socket.terminate();
|
||||||
} else {
|
} else {
|
||||||
setTimeout(function () {
|
setTimeout(() => sendAuth(socket, options.password), 50);
|
||||||
sendAuth(socket, options.password);
|
|
||||||
}, 50);
|
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
if (response.type === 'auth_ok') {
|
if (response.type === 'auth_ok') {
|
||||||
setImmediate(function () {
|
setImmediate(() =>
|
||||||
subscribeEvents(socket, function (err) {
|
subscribeEvents(socket, err => {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
connected = true;
|
connected = true;
|
||||||
that.emit('connected');
|
that.emit('connected');
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
});
|
|
||||||
} else if (response.id === undefined) {
|
} else if (response.id === undefined) {
|
||||||
log.error('Invalid answer: ' + msg);
|
log.error(`Invalid answer: ${msg}`);
|
||||||
} else {
|
} else {
|
||||||
if (response.type === 'result' && requests[response.id]) {
|
if (response.type === 'result' && requests[response.id]) {
|
||||||
log.debug('got answer for ' + requests[response.id].type);
|
log.debug(`got answer for ${requests[response.id].type}`);
|
||||||
if (typeof requests[response.id].cb === 'function') {
|
if (typeof requests[response.id].cb === 'function') {
|
||||||
requests[response.id].cb(!response.success, response.result);
|
requests[response.id].cb(!response.success, response.result);
|
||||||
delete requests[response.id];
|
delete requests[response.id];
|
||||||
@@ -165,7 +164,7 @@ function HASS(options, log) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('error', function (err) {
|
socket.on('error', err => {
|
||||||
socket = null;
|
socket = null;
|
||||||
if (err && err.message.indexOf('RSV2 and RSV3 must be clear') !== -1) {
|
if (err && err.message.indexOf('RSV2 and RSV3 must be clear') !== -1) {
|
||||||
// ignore deflate error
|
// ignore deflate error
|
||||||
@@ -173,12 +172,12 @@ function HASS(options, log) {
|
|||||||
log.error(err);
|
log.error(err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
socket.on('open', function () {
|
socket.on('open', () => {
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
socket.on('close', function () {
|
socket.on('close', () => {
|
||||||
that.socket = null;
|
that.socket = null;
|
||||||
if (connected) {
|
if (connected) {
|
||||||
connected = false;
|
connected = false;
|
||||||
@@ -186,7 +185,7 @@ function HASS(options, log) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
if (!connectTimeout) {
|
if (!connectTimeout) {
|
||||||
setTimeout(function () {
|
setTimeout(() => {
|
||||||
connectTimeout = null;
|
connectTimeout = null;
|
||||||
that.connect();
|
that.connect();
|
||||||
}, 3000);
|
}, 3000);
|
||||||
@@ -194,15 +193,11 @@ function HASS(options, log) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isConnected = function () {
|
this.isConnected = () => connected;
|
||||||
return connected;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.getConfig = function (callback) {
|
this.getConfig = function (callback) {
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
if (typeof callback === 'function') {
|
typeof callback === 'function' && callback('not connected');
|
||||||
callback('not connected');
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
getConfig(this.socket, callback);
|
getConfig(this.socket, callback);
|
||||||
}
|
}
|
||||||
@@ -210,9 +205,7 @@ function HASS(options, log) {
|
|||||||
|
|
||||||
this.getStates = function (callback) {
|
this.getStates = function (callback) {
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
if (typeof callback === 'function') {
|
typeof callback === 'function' && callback('not connected');
|
||||||
callback('not connected');
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
getStates(this.socket, callback);
|
getStates(this.socket, callback);
|
||||||
}
|
}
|
||||||
@@ -220,9 +213,7 @@ function HASS(options, log) {
|
|||||||
|
|
||||||
this.getServices = function (callback) {
|
this.getServices = function (callback) {
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
if (typeof callback === 'function') {
|
typeof callback === 'function' && callback('not connected');
|
||||||
callback('not connected');
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
getServices(this.socket, callback);
|
getServices(this.socket, callback);
|
||||||
}
|
}
|
||||||
@@ -230,9 +221,7 @@ function HASS(options, log) {
|
|||||||
|
|
||||||
this.getPanels = function (callback) {
|
this.getPanels = function (callback) {
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
if (typeof callback === 'function') {
|
typeof callback === 'function' && callback('not connected');
|
||||||
callback('not connected');
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
getPanels(this.socket, callback);
|
getPanels(this.socket, callback);
|
||||||
}
|
}
|
||||||
@@ -240,9 +229,7 @@ function HASS(options, log) {
|
|||||||
|
|
||||||
this.callService = function (service, domain, serviceData, callback) {
|
this.callService = function (service, domain, serviceData, callback) {
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
if (typeof callback === 'function') {
|
typeof callback === 'function' && callback('not connected');
|
||||||
callback('not connected');
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
callService(this.socket, service, domain, serviceData, callback);
|
callService(this.socket, service, domain, serviceData, callback);
|
||||||
}
|
}
|
||||||
@@ -254,7 +241,7 @@ function HASS(options, log) {
|
|||||||
connectTimeout = null;
|
connectTimeout = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.socket = new WebSocket('ws' + (options.secure ? 's' : '') + '://' + options.host + ':' + options.port + '/api/websocket', {
|
this.socket = new WebSocket(`ws${options.secure ? 's' : ''}://${options.host}:${options.port}/api/websocket`, {
|
||||||
perMessageDeflate: false
|
perMessageDeflate: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
var controllerDir;
|
|
||||||
var appName;
|
|
||||||
|
|
||||||
function getAppName() {
|
|
||||||
var parts = __dirname.replace(/\\/g, '/').split('/');
|
|
||||||
return parts[parts.length - 2].split('.')[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get js-controller directory to load libs
|
|
||||||
function getControllerDir(isInstall) {
|
|
||||||
var fs = require('fs');
|
|
||||||
// Find the js-controller location
|
|
||||||
var controllerDir = __dirname.replace(/\\/g, '/');
|
|
||||||
controllerDir = controllerDir.split('/');
|
|
||||||
if (controllerDir[controllerDir.length - 3] === 'adapter') {
|
|
||||||
controllerDir.splice(controllerDir.length - 3, 3);
|
|
||||||
controllerDir = controllerDir.join('/');
|
|
||||||
} else if (controllerDir[controllerDir.length - 3] === 'node_modules') {
|
|
||||||
controllerDir.splice(controllerDir.length - 3, 3);
|
|
||||||
controllerDir = controllerDir.join('/');
|
|
||||||
if (fs.existsSync(controllerDir + '/node_modules/' + appName + '.js-controller')) {
|
|
||||||
controllerDir += '/node_modules/' + appName + '.js-controller';
|
|
||||||
} else if (fs.existsSync(controllerDir + '/node_modules/' + appName.toLowerCase() + '.js-controller')) {
|
|
||||||
controllerDir += '/node_modules/' + appName.toLowerCase() + '.js-controller';
|
|
||||||
} else if (!fs.existsSync(controllerDir + '/controller.js')) {
|
|
||||||
if (!isInstall) {
|
|
||||||
console.log('Cannot find js-controller');
|
|
||||||
process.exit(10);
|
|
||||||
} else {
|
|
||||||
process.exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (fs.existsSync(__dirname + '/../../node_modules/' + appName.toLowerCase() + '.js-controller')) {
|
|
||||||
controllerDir.splice(controllerDir.length - 2, 2);
|
|
||||||
return controllerDir.join('/') + '/node_modules/' + appName.toLowerCase() + '.js-controller';
|
|
||||||
} else {
|
|
||||||
if (!isInstall) {
|
|
||||||
console.log('Cannot find js-controller');
|
|
||||||
process.exit(10);
|
|
||||||
} else {
|
|
||||||
process.exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return controllerDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read controller configuration file
|
|
||||||
function getConfig() {
|
|
||||||
var fs = require('fs');
|
|
||||||
if (fs.existsSync(controllerDir + '/conf/' + appName + '.json')) {
|
|
||||||
return JSON.parse(fs.readFileSync(controllerDir + '/conf/' + appName + '.json'));
|
|
||||||
} else if (fs.existsSync(controllerDir + '/conf/' + appName.toLowerCase() + '.json')) {
|
|
||||||
return JSON.parse(fs.readFileSync(controllerDir + '/conf/' + appName.toLowerCase() + '.json'));
|
|
||||||
} else {
|
|
||||||
throw new Error('Cannot find ' + controllerDir + '/conf/' + appName + '.json');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
appName = getAppName();
|
|
||||||
controllerDir = getControllerDir(typeof process !== 'undefined' && process.argv && process.argv.indexOf('--install') !== -1);
|
|
||||||
|
|
||||||
exports.controllerDir = controllerDir;
|
|
||||||
exports.getConfig = getConfig;
|
|
||||||
exports.Adapter = require(controllerDir + '/lib/adapter.js');
|
|
||||||
exports.appName = appName;
|
|
||||||
@@ -1,73 +1,66 @@
|
|||||||
/* jshint -W097 */
|
/* jshint -W097 */
|
||||||
/* jshint strict:false */
|
/* jshint strict: false */
|
||||||
/* jslint node: true */
|
/* jslint node: true */
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var utils = require(__dirname + '/lib/utils');
|
const utils = require('@iobroker/adapter-core');
|
||||||
var HASS = require(__dirname + '/lib/hass');
|
const HASS = require('./lib/hass');
|
||||||
|
const adapterName = require('./package.json').name.split('.').pop();
|
||||||
|
|
||||||
var adapter = utils.Adapter('hass');
|
let connected = false;
|
||||||
|
let hass;
|
||||||
|
let adapter;
|
||||||
|
const hassObjects = {};
|
||||||
|
|
||||||
var connected = false;
|
function startAdapter(options) {
|
||||||
var hass;
|
options = options || {};
|
||||||
var hassObjects = {};
|
Object.assign(options, {name: adapterName, unload: stop});
|
||||||
|
adapter = new utils.Adapter(options);
|
||||||
|
|
||||||
// is called if a subscribed state changes
|
// is called if a subscribed state changes
|
||||||
adapter.on('stateChange', function (id, state) {
|
adapter.on('stateChange', (id, state) => {
|
||||||
// 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) {
|
||||||
adapter.log.warn('Cannot send command to "' + id + '", because not connected');
|
return adapter.log.warn('Cannot send command to "' + id + '", because not connected');
|
||||||
return;
|
}
|
||||||
}
|
/*if (id === adapter.namespace + '.' + '.info.resync') {
|
||||||
/*if (id === adapter.namespace + '.' + '.info.resync') {
|
queue.push({command: 'resync'});
|
||||||
queue.push({command: 'resync'});
|
processQueue();
|
||||||
processQueue();
|
} 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 = {};
|
||||||
var serviceData = {};
|
const fields = hassObjects[id].native.fields;
|
||||||
var fields = hassObjects[id].native.fields;
|
|
||||||
|
|
||||||
for (var field in fields) {
|
for (const field in fields) {
|
||||||
if (!fields.hasOwnProperty(field)) continue;
|
if (!fields.hasOwnProperty(field)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (field === 'entity_id') {
|
if (field === 'entity_id') {
|
||||||
serviceData.entity_id = hassObjects[id].native.entity_id
|
serviceData.entity_id = hassObjects[id].native.entity_id
|
||||||
} else {
|
} else {
|
||||||
serviceData[field] = state.val;
|
serviceData[field] = state.val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hass.callService(hassObjects[id].native.attr, hassObjects[id].native.domain || hassObjects[id].native.type, serviceData, err =>
|
||||||
|
err && adapter.log.error('Cannot control ' + id + ': ' + err));
|
||||||
}
|
}
|
||||||
|
|
||||||
hass.callService(hassObjects[id].native.attr, hassObjects[id].native.domain || hassObjects[id].native.type, serviceData, function (err) {
|
|
||||||
if (err) {
|
|
||||||
adapter.log.error('Cannot control ' + id + ': ' + err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
|
||||||
// Some message was sent to adapter instance over message box. Used by email, pushover, text2speech, ...
|
// is called when databases are connected and adapter received configuration.
|
||||||
adapter.on('message', function (obj) {
|
// start here!
|
||||||
if (typeof obj === 'object' && obj.message) {
|
adapter.on('ready', main);
|
||||||
if (obj.command === 'send') {
|
|
||||||
// e.g. send email or pushover or whatever
|
|
||||||
console.log('send command');
|
|
||||||
|
|
||||||
// Send response in callback if required
|
return adapter;
|
||||||
if (obj.callback) adapter.sendTo(obj.from, obj.command, 'Message received', obj.callback);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// is called when databases are connected and adapter received configuration.
|
|
||||||
// start here!
|
|
||||||
adapter.on('ready', main);
|
|
||||||
|
|
||||||
function getUnit(name) {
|
function getUnit(name) {
|
||||||
name = name.toLowerCase();
|
name = name.toLowerCase();
|
||||||
@@ -87,37 +80,34 @@ function getUnit(name) {
|
|||||||
|
|
||||||
function syncStates(states, cb) {
|
function syncStates(states, cb) {
|
||||||
if (!states || !states.length) {
|
if (!states || !states.length) {
|
||||||
cb();
|
return cb();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
var state = states.shift();
|
const state = states.shift();
|
||||||
var id = state.id;
|
const id = state.id;
|
||||||
delete state.id;
|
delete state.id;
|
||||||
|
|
||||||
adapter.setForeignState(id, state, function (err) {
|
adapter.setForeignState(id, state, err => {
|
||||||
if (err) adapter.log.error(err);
|
err && adapter.log.error(err);
|
||||||
setImmediate(syncStates, states, cb);
|
setImmediate(syncStates, states, cb);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function syncObjects(objects, cb) {
|
function syncObjects(objects, cb) {
|
||||||
if (!objects || !objects.length) {
|
if (!objects || !objects.length) {
|
||||||
cb();
|
return cb();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
var obj = objects.shift();
|
const obj = objects.shift();
|
||||||
hassObjects[obj._id] = obj;
|
hassObjects[obj._id] = obj;
|
||||||
|
|
||||||
adapter.getForeignObject(obj._id, function (err, oldObj) {
|
adapter.getForeignObject(obj._id, (err, oldObj) => {
|
||||||
|
|
||||||
if (err) adapter.log.error(err);
|
err && adapter.log.error(err);
|
||||||
|
|
||||||
if (!oldObj) {
|
if (!oldObj) {
|
||||||
adapter.log.debug('Create "' + obj._id + '"');
|
adapter.log.debug('Create "' + obj._id + '"');
|
||||||
hassObjects[obj._id] = obj;
|
hassObjects[obj._id] = obj;
|
||||||
adapter.setForeignObject(obj._id, obj, function (err) {
|
adapter.setForeignObject(obj._id, obj, err => {
|
||||||
if (err) adapter.log.error(err);
|
err && adapter.log.error(err);
|
||||||
|
|
||||||
setImmediate(syncObjects, objects, cb);
|
setImmediate(syncObjects, objects, cb);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -126,8 +116,8 @@ function syncObjects(objects, cb) {
|
|||||||
oldObj.native = obj.native;
|
oldObj.native = obj.native;
|
||||||
|
|
||||||
adapter.log.debug('Update "' + obj._id + '"');
|
adapter.log.debug('Update "' + obj._id + '"');
|
||||||
adapter.setForeignObject(obj._id, oldObj, function (err) {
|
adapter.setForeignObject(obj._id, oldObj, err => {
|
||||||
if (err) adapter.log.error(err);
|
err => adapter.log.error(err);
|
||||||
setImmediate(syncObjects, objects, cb);
|
setImmediate(syncObjects, objects, cb);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -138,7 +128,7 @@ function syncObjects(objects, cb) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function syncRoom(room, members, cb) {
|
function syncRoom(room, members, cb) {
|
||||||
adapter.getForeignObject('enum.rooms.' + room, function (err, obj) {
|
adapter.getForeignObject('enum.rooms.' + room, (err, obj) => {
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
obj = {
|
obj = {
|
||||||
_id: 'enum.rooms.' + room,
|
_id: 'enum.rooms.' + room,
|
||||||
@@ -150,15 +140,15 @@ function syncRoom(room, members, cb) {
|
|||||||
native: {}
|
native: {}
|
||||||
};
|
};
|
||||||
adapter.log.debug('Update "' + obj._id + '"');
|
adapter.log.debug('Update "' + obj._id + '"');
|
||||||
adapter.setForeignObject(obj._id, obj, function (err) {
|
adapter.setForeignObject(obj._id, obj, err => {
|
||||||
if (err) adapter.log.error(err);
|
err && adapter.log.error(err);
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
obj.common = obj.common || {};
|
obj.common = obj.common || {};
|
||||||
obj.common.members = obj.common.members || [];
|
obj.common.members = obj.common.members || [];
|
||||||
var changed = false;
|
let changed = false;
|
||||||
for (var m = 0; m < members.length; m++) {
|
for (let m = 0; m < members.length; m++) {
|
||||||
if (obj.common.members.indexOf(members[m]) === -1) {
|
if (obj.common.members.indexOf(members[m]) === -1) {
|
||||||
changed = true;
|
changed = true;
|
||||||
obj.common.members.push(members[m]);
|
obj.common.members.push(members[m]);
|
||||||
@@ -166,8 +156,8 @@ 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, function (err) {
|
adapter.setForeignObject(obj._id, obj, err => {
|
||||||
if (err) adapter.log.error(err);
|
err && adapter.log.error(err);
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -177,41 +167,41 @@ function syncRoom(room, members, cb) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var knownAttributes = {
|
const knownAttributes = {
|
||||||
azimuth: {write: false, read: true, unit: '°'},
|
azimuth: {write: false, read: true, unit: '°'},
|
||||||
elevation: {write: false, read: true, unit: '°'}
|
elevation: {write: false, read: true, unit: '°'}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
var ERRORS = {
|
const ERRORS = {
|
||||||
1: 'ERR_CANNOT_CONNECT',
|
1: 'ERR_CANNOT_CONNECT',
|
||||||
2: 'ERR_INVALID_AUTH',
|
2: 'ERR_INVALID_AUTH',
|
||||||
3: 'ERR_CONNECTION_LOST'
|
3: 'ERR_CONNECTION_LOST'
|
||||||
};
|
};
|
||||||
var mapTypes = {
|
const mapTypes = {
|
||||||
'string': 'string',
|
'string': 'string',
|
||||||
'number': 'number',
|
'number': 'number',
|
||||||
'object': 'mixed',
|
'object': 'mixed',
|
||||||
'boolean': 'boolean'
|
'boolean': 'boolean'
|
||||||
};
|
};
|
||||||
var skipServices = [
|
const skipServices = [
|
||||||
'persistent_notification'
|
'persistent_notification'
|
||||||
];
|
];
|
||||||
|
|
||||||
function parseStates(entities, services, callback) {
|
function parseStates(entities, services, callback) {
|
||||||
var objs = [];
|
const objs = [];
|
||||||
var states = [];
|
const states = [];
|
||||||
var obj;
|
let obj;
|
||||||
var channel;
|
let channel;
|
||||||
for (var e = 0; e < entities.length; e++) {
|
for (let e = 0; e < entities.length; e++) {
|
||||||
var entity = entities[e];
|
const entity = entities[e];
|
||||||
if (!entity) continue;
|
if (!entity) continue;
|
||||||
|
|
||||||
var name = entity.name || (entity.attributes && entity.attributes.friendly_name ? entity.attributes.friendly_name : entity.entity_id);
|
const name = entity.name || (entity.attributes && entity.attributes.friendly_name ? entity.attributes.friendly_name : entity.entity_id);
|
||||||
var desc = entity.attributes && entity.attributes.attribution ? entity.attributes.attribution : undefined;
|
const desc = entity.attributes && entity.attributes.attribution ? entity.attributes.attribution : undefined;
|
||||||
|
|
||||||
channel = {
|
channel = {
|
||||||
_id: adapter.namespace + '.entities.' + entity.entity_id,
|
_id: `${adapter.namespace}.entities.${entity.entity_id}`,
|
||||||
common: {
|
common: {
|
||||||
name: name
|
name: name
|
||||||
},
|
},
|
||||||
@@ -224,15 +214,15 @@ function parseStates(entities, services, callback) {
|
|||||||
if (desc) channel.common.desc = desc;
|
if (desc) channel.common.desc = desc;
|
||||||
objs.push(channel);
|
objs.push(channel);
|
||||||
|
|
||||||
var lc = entity.last_changed ? new Date(entity.last_changed).getTime() : undefined;
|
const lc = entity.last_changed ? new Date(entity.last_changed).getTime() : undefined;
|
||||||
var 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) {
|
||||||
obj = {
|
obj = {
|
||||||
_id: adapter.namespace + '.entities.' + entity.entity_id + '.state',
|
_id: `${adapter.namespace}.entities.${entity.entity_id}.state`,
|
||||||
type: 'state',
|
type: 'state',
|
||||||
common: {
|
common: {
|
||||||
name: name + ' STATE',
|
name: `${name} STATE`,
|
||||||
read: true,
|
read: true,
|
||||||
write: false
|
write: false
|
||||||
},
|
},
|
||||||
@@ -250,11 +240,13 @@ function parseStates(entities, services, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (entity.attributes) {
|
if (entity.attributes) {
|
||||||
for (var attr in entity.attributes) {
|
for (const attr in entity.attributes) {
|
||||||
if (entity.attributes.hasOwnProperty(attr)) {
|
if (entity.attributes.hasOwnProperty(attr)) {
|
||||||
if (attr === 'friendly_name' || attr === 'unit_of_measurement' || attr === 'icon') continue;
|
if (attr === 'friendly_name' || attr === 'unit_of_measurement' || attr === 'icon') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var common;
|
let common;
|
||||||
if (knownAttributes[attr]) {
|
if (knownAttributes[attr]) {
|
||||||
common = Object.assign({}, knownAttributes[attr]);
|
common = Object.assign({}, knownAttributes[attr]);
|
||||||
} else {
|
} else {
|
||||||
@@ -262,7 +254,7 @@ function parseStates(entities, services, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
obj = {
|
obj = {
|
||||||
_id: adapter.namespace + '.entities.' + entity.entity_id + '.' + attr,
|
_id: `${adapter.namespace}.entities.${entity.entity_id}.${attr}`,
|
||||||
type: 'state',
|
type: 'state',
|
||||||
common: common,
|
common: common,
|
||||||
native: {
|
native: {
|
||||||
@@ -291,14 +283,14 @@ function parseStates(entities, services, callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var serviceType = entity.entity_id.split('.')[0];
|
const serviceType = entity.entity_id.split('.')[0];
|
||||||
|
|
||||||
if (services[serviceType] && skipServices.indexOf(serviceType) === -1) {
|
if (services[serviceType] && !skipServices.includes(serviceType)) {
|
||||||
var service = services[serviceType];
|
const service = services[serviceType];
|
||||||
for (var s in service) {
|
for (const s in service) {
|
||||||
if (service.hasOwnProperty(s)) {
|
if (service.hasOwnProperty(s)) {
|
||||||
obj = {
|
obj = {
|
||||||
_id: adapter.namespace + '.entities.' + entity.entity_id + '.' + s,
|
_id: `${adapter.namespace}.entities.${entity.entity_id}.${s}`,
|
||||||
type: 'state',
|
type: 'state',
|
||||||
common: {
|
common: {
|
||||||
desc: service[s].description,
|
desc: service[s].description,
|
||||||
@@ -320,9 +312,8 @@ function parseStates(entities, services, callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
syncObjects(objs, function () {
|
syncObjects(objs, () =>
|
||||||
syncStates(states, callback);
|
syncStates(states, callback));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
@@ -336,60 +327,60 @@ function main() {
|
|||||||
|
|
||||||
hass = new HASS(adapter.config, adapter.log);
|
hass = new HASS(adapter.config, adapter.log);
|
||||||
|
|
||||||
hass.on('error', function (err) {
|
hass.on('error', err =>
|
||||||
adapter.log.error(err);
|
adapter.log.error(err));
|
||||||
});
|
|
||||||
hass.on('state_changed', function (entity) {
|
hass.on('state_changed', entity => {
|
||||||
var id = adapter.namespace + '.entities.' + entity.entity_id + '.';
|
const id = adapter.namespace + '.entities.' + entity.entity_id + '.';
|
||||||
var lc = entity.last_changed ? new Date(entity.last_changed).getTime() : undefined;
|
const lc = entity.last_changed ? new Date(entity.last_changed).getTime() : undefined;
|
||||||
var 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});
|
adapter.setForeignState(id + 'state', {val: entity.state, ack: true, lc: lc, ts: ts});
|
||||||
}
|
}
|
||||||
if (entity.attributes) {
|
if (entity.attributes) {
|
||||||
for (var attr in entity.attributes) {
|
for (const attr in entity.attributes) {
|
||||||
if (!entity.attributes.hasOwnProperty(attr) || attr === 'friendly_name' || attr === 'unit_of_measurement' || attr === 'icon') continue;
|
if (!entity.attributes.hasOwnProperty(attr) || attr === 'friendly_name' || attr === 'unit_of_measurement' || attr === 'icon') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
adapter.setForeignState(id + attr, {val: entity.attributes[attr], ack: true, lc: lc, ts: ts});
|
adapter.setForeignState(id + attr, {val: entity.attributes[attr], ack: true, lc: lc, ts: ts});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
hass.on('connected', function () {
|
hass.on('connected', () => {
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
adapter.log.debug('Connected');
|
adapter.log.debug('Connected');
|
||||||
connected = true;
|
connected = true;
|
||||||
adapter.setState('info.connection', true, true);
|
adapter.setState('info.connection', true, true);
|
||||||
hass.getConfig(function (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));
|
||||||
setTimeout(function () {
|
setTimeout(() =>
|
||||||
hass.getStates(function (err, states) {
|
hass.getStates((err, states) => {
|
||||||
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));
|
||||||
setTimeout(function () {
|
setTimeout(() =>
|
||||||
hass.getServices(function (err, services) {
|
hass.getServices((err, services) => {
|
||||||
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, function () {
|
parseStates(states, services, () => {
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
}), 100);
|
||||||
}, 100);
|
}), 100);
|
||||||
});
|
|
||||||
}, 100);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
hass.on('disconnected', function () {
|
hass.on('disconnected', () => {
|
||||||
if (connected) {
|
if (connected) {
|
||||||
adapter.log.debug('Disconnected');
|
adapter.log.debug('Disconnected');
|
||||||
connected = false;
|
connected = false;
|
||||||
@@ -399,3 +390,11 @@ function main() {
|
|||||||
|
|
||||||
hass.connect();
|
hass.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If started as allInOne/compact mode => return function to create instance
|
||||||
|
if (module && module.parent) {
|
||||||
|
module.exports = startAdapter;
|
||||||
|
} else {
|
||||||
|
// or start the instance directly
|
||||||
|
startAdapter();
|
||||||
|
}
|
||||||
|
|||||||
+10
-7
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "iobroker.hass",
|
"name": "iobroker.hass",
|
||||||
"version": "0.1.0",
|
"version": "1.0.0",
|
||||||
"description": "Home Assistant",
|
"description": "Home Assistant",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "bluefox",
|
"name": "bluefox",
|
||||||
@@ -26,17 +26,20 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"home-assistant-js-websocket": "^1.1.4",
|
"home-assistant-js-websocket": "^1.1.4",
|
||||||
"websocket": "^1.0.25",
|
"websocket": "^1.0.33",
|
||||||
"ws": "^5.0.0"
|
"ws": "^5.0.0",
|
||||||
|
"@iobroker/adapter-core": "^2.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"gulp": "^3.9.1",
|
"@alcalzone/release-script": "^1.8.1",
|
||||||
"mocha": "^4.1.0",
|
"gulp": "^4.0.2",
|
||||||
"chai": "^4.1.2"
|
"mocha": "^8.2.1",
|
||||||
|
"chai": "^4.2.0"
|
||||||
},
|
},
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node node_modules/mocha/bin/mocha --exit"
|
"test": "node node_modules/mocha/bin/mocha --exit",
|
||||||
|
"release": "node node_modules/@alcalzone/release-script/bin/release.js"
|
||||||
},
|
},
|
||||||
"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