diff --git a/.npmignore b/.npmignore deleted file mode 100644 index ea86115..0000000 --- a/.npmignore +++ /dev/null @@ -1,13 +0,0 @@ -gulpfile.js -tasks -tmp -test -.github -.idea -node_modules -.travis.yml -appveyor.yml -admin/i18n -iob_npm.done -package-lock.json -.releaseconfig.json diff --git a/LICENSE b/LICENSE index 8da1927..5e581b4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015-2022, bluefox +Copyright (c) 2015-2024, bluefox Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 4221bb4..4b90723 100644 --- a/README.md +++ b/README.md @@ -19,25 +19,22 @@ This adapter uses the owfs library from https://www.npmjs.com/package/owjs and a ## Install OWFS Linux -```sudo apt-get install owfs``` +`sudo apt-get install owfs` -Sometimes you need write following steps: -- To start the the server to communicate over serial interface with 1wire sensors +Sometimes you need to write the following steps: +- To start the server to communicate over serial interface with 1wire sensors -``` -owserver -d "/dev/ttyUSB0" --nozero -``` +`owserver -d "/dev/ttyUSB0" --nozero` -*/dev/ttyUSB0* is the name of your serial device. Here was USB stick used for that. +`/dev/ttyUSB0` is the name of your serial device. Here was a USB stick used for that. This command starts the 1wire server on local port 4304. -- To show the data from the local 1wire server in the file system call following command: +- To show the data from the local 1wire server in the file system, call the following command: -``` -owfs -C -m /mnt/1wire --allow_other -``` -Before you must create the directroy */mnt/1wire* with command `mkdir /mnt/1wire` +`owfs -C -m /mnt/1wire --allow_other` + +Before you must create the directory */mnt/1wire* with command `mkdir /mnt/1wire` ## Install OWFS windows http://sourceforge.net/projects/owfs/ @@ -55,12 +52,12 @@ http://sourceforge.net/projects/owfs/ * (INgo Rah) Added the alarm state handling ### 0.6.2 (2019-10-29) -* (RustyThePropellerHead) Improved data integrity when reading from local OWFS via file system +* (RustyThePropellerHead) Improved data integrity when reading from local OWFS via a file system ### 0.6.1 (2018-07-11) * (bluefox) compact mode supported * (lvogt) Added data points counter.A/.B/.ALL from DS2423 to config page -* (lvogt) Add option to not log faulty readouts +* (lvogt) Added option to not log faulty readouts ### 0.5.0 (2018-03-16) * (bluefox) Ready for Admin3 @@ -78,17 +75,17 @@ http://sourceforge.net/projects/owfs/ * (bluefox) custom poll interval for every sensor ### 0.3.2 (2016-08-24) -* (bluefox) support of local OWFS via file system +* (bluefox) support of local OWFS via a file system ### 0.2.2 (2016-07-29) -* (bluefox) add new datapoints: pressure, volts, ... +* (bluefox) add new data points: pressure, volts, ... ### 0.2.1 (2016-07-28) -* (bluefox) fixes of write +* (bluefox) fixes of writing ### 0.2.0 (2016-07-27) * (bluefox) discover sensors -* (bluefox) use other npm library to fix write +* (bluefox) used another npm library to fix writing ### 0.1.1 (2016-07-25) * (bluefox) check configuration @@ -102,17 +99,11 @@ http://sourceforge.net/projects/owfs/ ### 0.0.1 (2014-11-02) * (bluefox) support of server (actual no authentication) -## Install - -```node iobroker.js add owfs``` - -## Configuration - ## License The MIT License (MIT) -Copyright (c) 2015-2022, bluefox +Copyright (c) 2015-2024, bluefox Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/admin/index_m.html b/admin/index_m.html index 0374380..ce79348 100644 --- a/admin/index_m.html +++ b/admin/index_m.html @@ -291,7 +291,7 @@
- +
diff --git a/admin/jsonConfig.json b/admin/jsonConfig.json new file mode 100644 index 0000000..6583b84 --- /dev/null +++ b/admin/jsonConfig.json @@ -0,0 +1,123 @@ +{ + "type": "tabs", + "i18n": true, + "items": { + "_main": { + "type": "panel", + "label": "OWFS server settings", + "items": { + "local": { + "type": "checkbox", + "label": "Use local OWFS", + "sm": 12, + "md": 4 + }, + "path": { + "newLine": true, + "type": "text", + "label": "Path to OWFS mount", + "sm": 12, + "md": 4 + }, + "ip": { + "newLine": true, + "type": "text", + "label": "IP Address of OWFS Server", + "sm": 12, + "md": 4 + }, + "port": { + "type": "number", + "min": 1, + "max": 65535, + "label": "Port of OWFS Server", + "sm": 12, + "md": 4 + }, + "interval": { + "newLine": true, + "type": "number", + "min": 0, + "max": 100000, + "label": "Poll interval", + "help": "seconds", + "sm": 12, + "md": 4 + }, + "alarmInterval": { + "type": "number", + "min": 0, + "max": 100000, + "label": "Alarm poll interval", + "help": "milliseconds, 0 = off", + "sm": 12, + "md": 4 + }, + "noStateChangeOnError": { + "newLine": true, + "type": "checkbox", + "label": "No state change on error", + "sm": 12, + "md": 4 + }, + "noStateChangeOn85C": { + "type": "checkbox", + "label": "No state change on 85°C reading", + "help": "Initial state of DS18B20 in case of power failure", + "sm": 12, + "md": 4 + } + } + }, + "_addresses": { + "type": "panel", + "label": "Wires addresses", + "items": { + "_readAddresses": { + "type": "sendTo", + "command": "readdir", + "label": "refresh", + "jsonData": "{ \"local\": ${!!data.local}, \"path\": \"${data.path}\", \"ip\": \"${data.ip}\", \"port\": ${data.port} }" + }, + "wires": { + "type": "table", + "showSecondAddAt": 10, + "export": true, + "import": true, + "items": [ + { + "type": "text", + "attr": "name", + "label": "Name" + }, + { + "type": "text", + "attr": "id", + "label": "ID", + "width": "20%" + }, + { + "type": "text", + "attr": "property", + "label": "Property", + "width": 120 + }, + { + "type": "checkbox", + "attr": "iButton", + "label": "iButton", + "width": 60 + }, + { + "type": "number", + "attr": "interval", + "label": "Interval (sec)", + "title": "in seconds", + "width": 80 + } + ] + } + } + } + } +} diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index a5d5acf..0000000 --- a/gulpfile.js +++ /dev/null @@ -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')); \ No newline at end of file diff --git a/io-package.json b/io-package.json index ac5682f..9396741 100644 --- a/io-package.json +++ b/io-package.json @@ -88,7 +88,6 @@ "zh-cn": "修复翻译" } }, - "title": "1Wire OWFS", "titleLang": { "en": "1Wire OWFS", "de": "1Wire-OWFS", @@ -116,7 +115,10 @@ "authors": [ "bluefox " ], - "license": "MIT", + "licenseInformation": { + "type": "free", + "license": "MIT" + }, "platform": "Javascript/Node.js", "mode": "daemon", "availableModes": [ @@ -127,8 +129,10 @@ "icon": "owfs.png", "compact": true, "messagebox": true, - "subscribe": "messagebox", "materialize": true, + "adminUI": { + "config": "materialize" + }, "keywords": [ "owfs", "one wire", diff --git a/main.js b/main.js index ad97c5a..fae63ed 100644 --- a/main.js +++ b/main.js @@ -2,15 +2,11 @@ * * ioBroker OWFS Adapter * - * Copyright (c) 2015-2020 bluefox + * Copyright (c) 2015-2024 bluefox * * MIT License * */ -/* jshint -W097 */ -/* jshint strict: false */ -/* jslint node: true */ -'use strict'; const utils = require('@iobroker/adapter-core'); // Get common adapter utils const adapterName = require('./package.json').name.split('.').pop(); let OWJS = null; @@ -48,20 +44,23 @@ function startAdapter(options) { }); adapter.on('stateChange', (id, state) => { - if (!id || !state || state.ack) return; - if (!adapter.config.wires) return; + if (!id || !state || state.ack) { + return; + } + if (!adapter.config.wires) { + return; + } - if (id === adapter.namespace + '.alarm') { + if (id === `${adapter.namespace}.alarm`) { activeAlarm = !(state.val === false || state.val === 0 || state.val === '0' || state.val === 'false'); return; } let wire; for (let i = 0; i < adapter.config.wires.length; i++) { - if (adapter.config.wires[i] && id === adapter.namespace + '.wires.' + adapter.config.wires[i]._name) { + if (adapter.config.wires[i] && id === `${adapter.namespace}.wires.${adapter.config.wires[i]._name}`) { if (state.val === true || state.val === 'true') { state.val = 1; - } else - if (state.val === false || state.val === 'false') { + } else if (state.val === false || state.val === 'false') { state.val = 0; } wire = adapter.config.wires[i]; @@ -77,20 +76,20 @@ function startAdapter(options) { adapter.getForeignObject(id, (err, obj) => { objects[id] = obj; if (obj && obj.common && !obj.common.write) { - adapter.log.debug('Cannot write read only "' + id + '"'); + adapter.log.debug(`Cannot write read only "${id}"`); } else { writeWire(wire, state.val); } }); } else { if (objects[id] && objects[id].common && !objects[id].common.write) { - adapter.log.debug('Cannot write read only "' + id + '"'); + adapter.log.debug(`Cannot write read only "${id}"`); } else { writeWire(wire, state.val); } } } else { - adapter.log.warn('Wire "' + id + '" not found'); + adapter.log.warn(`Wire "${id}" not found`); } }); @@ -105,22 +104,22 @@ function readSensors(oClientOrPath, sensors, result, cb) { const sensor = sensors.shift(); if (typeof oClientOrPath === 'object') { - oClientOrPath.list('/' + sensor, (err, dirs) => { + oClientOrPath.list(`/${sensor}`, (err, dirs) => { result[sensor] = dirs; if (dirs) { for (let d = 0; d < dirs.length; d++) { - if (dirs[d].substring(0, sensor.length + 2) === '/' + sensor + '/') { + if (dirs[d].substring(0, sensor.length + 2) === `/${sensor}/`) { dirs[d] = dirs[d].substring(sensor.length + 2); } - if (possibleSubTrees.indexOf(dirs[d]) !== -1) { - sensors.push(sensor + '/' + dirs[d]); + if (possibleSubTrees.includes(dirs[d])) { + sensors.push(`${sensor}/${dirs[d]}`); } } } setImmediate(() => readSensors(oClientOrPath, sensors, result, cb)); }); } else { - fs.readdir(oClientOrPath + '/' + sensor, (err, dirs) => { + fs.readdir(`${oClientOrPath}/${sensor}`, (err, dirs) => { result[sensor] = dirs; dirs && dirs.forEach(dir => possibleSubTrees.includes(dir) && sensors.push(sensor + '/' + dir)); @@ -133,7 +132,7 @@ function readSensors(oClientOrPath, sensors, result, cb) { const possibleSubTrees = [ 'LED', 'relay', - 'set_alarm' + 'set_alarm', ]; const ignoreDevices = [ @@ -143,7 +142,7 @@ const ignoreDevices = [ 'settings', 'uncached', 'simultaneous', - 'statistics' + 'statistics', ]; function processMessage(msg) { @@ -156,7 +155,7 @@ function processMessage(msg) { if (msg.callback) { let _client = null; if (msg.message.config && msg.message.config.ip) { - adapter.log.debug('Connect to ' + msg.message.config.ip + ':' + msg.message.config.port); + adapter.log.debug(`Connect to ${msg.message.config.ip}:${msg.message.config.port}`); _client = getOWFSClient({host: msg.message.config.ip, port: msg.message.config.port}); } else if (msg.message.config && !msg.message.config.path) { _client = client; @@ -165,11 +164,11 @@ function processMessage(msg) { if (_client) { _client.list('/', (err, dirs) => { if (err) { - adapter.log.error('Cannot read dir: ' + err); + adapter.log.error(`Cannot read dir: ${err}`); adapter.sendTo(msg.from, msg.command, {error: err.toString()}, msg.callback); _client = null; } else { - adapter.log.debug('Result for list: ' + JSON.stringify(dirs)); + adapter.log.debug(`Result for list: ${JSON.stringify(dirs)}`); for (let d = dirs.length - 1; d >= 0; d--) { if (!dirs[d] || dirs[d][0] !== '/') { dirs.splice(d, 1); @@ -177,32 +176,34 @@ function processMessage(msg) { dirs[d] = dirs[d].substring(1); } // remove some constant entries - if (ignoreDevices.indexOf(dirs[d]) !== -1 || dirs[d].match(/^bus\./)) dirs.splice(d, 1); + if (ignoreDevices.includes(dirs[d]) || dirs[d].match(/^bus\./)) { + dirs.splice(d, 1); + } } - adapter.log.debug('Result for list_: ' + JSON.stringify(dirs)); + adapter.log.debug(`Result for list_: ${JSON.stringify(dirs)}`); // read all sensors readSensors(_client, dirs, null, result => { - adapter.log.debug('Result for dir: ' + JSON.stringify(result)); + adapter.log.debug(`Result for dir: ${JSON.stringify(result)}`); adapter.sendTo(msg.from, msg.command, {sensors: result}, msg.callback); _client = null; }); } }); } else { - fs = fs || require('fs'); + fs = fs || require('node:fs'); let _path1wire = msg.message.config ? msg.message.config.path || '/mnt/1wire' : '/mnt/1wire'; if (_path1wire[_path1wire.length - 1] === '/') { _path1wire = _path1wire.substring(0, _path1wire.length - 1); } fs.readdir(_path1wire, (err, dirs) => { if (err) { - adapter.log.error('Cannot read dir: ' + err); + adapter.log.error(`Cannot read dir: ${err}`); adapter.sendTo(msg.from, msg.command, {error: err.toString()}, msg.callback); } else { for (let d = dirs.length - 1; d >= 0; d--) { // remove some constant entries - if (!dirs[d] || ignoreDevices.indexOf(dirs[d]) !== -1 || dirs[d].match(/^bus\./)) { + if (!dirs[d] || ignoreDevices.includes(dirs[d]) || dirs[d].match(/^bus\./)) { dirs.splice(d, 1); } } @@ -230,60 +231,60 @@ function writeWire(wire, value) { } let val; - if (property.indexOf('.ALL') !== -1) { + if (property.includes('.ALL')) { val = value; } else - if (property.indexOf('PIO') !== -1 && property.indexOf('.BYTE') === -1) { + if (property.includes('PIO') && !property.includes('.BYTE')) { val = (value === '0' || value === 0 || value === 'false' || value === false) ? 0 : 1; } else { val = parseFloat(value) || 0; } - adapter.log.debug('Write /' + wire.id + '/' + (wire.property || 'temperature') + ' with "' + val + '"'); + adapter.log.debug(`Write /${wire.id}/${wire.property || 'temperature'} with "${val}"`); if (client) { - client.write('/' + wire.id + '/' + property, val, (err, message) => { + client.write(`/${wire.id}/${property}`, val, (err, message) => { if (message !== undefined) { - adapter.log.debug('Response for write /' + wire.name + '/' + property + ': ' + message); + adapter.log.debug(`Response for write /${wire.name}/${property}: ${message}`); } // no idea what is received here if (err) { - adapter.log.warn('Cannot write value of /' + wire.id + '/' + property + ': ' + JSON.stringify(err)); - adapter.setState('wires.' + wire._name, {val: 0, ack: true, q: 0x84}); + adapter.log.warn(`Cannot write value of /${wire.id}/${property}: ${JSON.stringify(err)}`); + adapter.setState(`wires.${wire._name}`, {val: 0, ack: true, q: 0x84}); } else { // ALL is like "0,1" - if (property.indexOf('.ALL') !== -1) { - adapter.setState('wires.' + wire._name, value || '', true); + if (property.includes('.ALL')) { + adapter.setState(`wires.${wire._name}`, value || '', true); } else // PIO.0, PIO.1, PIO.A are boolean - if (property.indexOf('PIO') !== -1 && property.indexOf('.BYTE') === -1) { - adapter.setState('wires.' + wire._name, !(value === '0' || value === 0 || value === 'false' || value === false), true); + if (property.includes('PIO') && !property.includes('.BYTE')) { + adapter.setState(`wires.${wire._name}`, !(value === '0' || value === 0 || value === 'false' || value === false), true); } else { - // alse some float value, e.g. temperature - adapter.setState('wires.' + wire._name, parseFloat(value) || 0, true); + // else some float value, e.g. temperature + adapter.setState(`wires.${wire._name}`, parseFloat(value) || 0, true); } } }); } else { - const pathFile = path1wire + '/' + wire.id + '/' + property; + const pathFile = `${path1wire}/${wire.id}/${property}`; - adapter.log.debug(pathFile + ' with "' + val + '"'); + adapter.log.debug(`${pathFile} with "${val}"`); // Write to file fs.writeFile(pathFile, val, (err/*, written*/) => { if (err) { // Write error - adapter.log.warn('Cannot write value of ' + pathFile + ': ' + JSON.stringify(err)); - adapter.setState('wires.' + wire._name, {val: 0, ack: true, q: 0x84}); + adapter.log.warn(`Cannot write value of ${pathFile}: ${JSON.stringify(err)}`); + adapter.setState(`wires.${wire._name}`, {val: 0, ack: true, q: 0x84}); } else { // ALL is like "0,1" - if (property.indexOf('.ALL') !== -1) { - adapter.setState('wires.' + wire._name, value || '', true); + if (property.includes('.ALL')) { + adapter.setState(`wires.${wire._name}`, value || '', true); } else // PIO.0, PIO.1, PIO.A are boolean - if (property.indexOf('PIO') !== -1 && property.indexOf('.BYTE') === -1) { - adapter.setState('wires.' + wire._name, !(value === '0' || value === 0 || value === 'false' || value === false), true); + if (property.includes('PIO') && !property.includes('.BYTE')) { + adapter.setState(`wires.${wire._name}`, !(value === '0' || value === 0 || value === 'false' || value === false), true); } else { - // alse some float value, e.g. temperature - adapter.setState('wires.' + wire._name, parseFloat(value) || 0, true); + // else some float value, e.g. temperature + adapter.setState(`wires.${wire._name}`, parseFloat(value) || 0, true); } } }); @@ -307,12 +308,12 @@ function getOWFSClient(settings) { } } if (ret < 0) { - adapter.log.warn('Invalid response for list: ' + ret); + adapter.log.warn(`Invalid response for list: ${ret}`); callback('Invalid response'); return; } if (!str) { - adapter.log.warn('Invalid response for list [empty answer]: ' + JSON.stringify(messages)); + adapter.log.warn(`Invalid response for list [empty answer]: ${JSON.stringify(messages)}`); callback('Invalid response for list [empty answer]'); return; } @@ -335,96 +336,96 @@ function readWire(wire) { if (wire.iButton && !wire.property) wire.property = 'r_address'; if (wire) { if (client) { - adapter.log.debug('Reading ' + '/' + wire.id + '/' + (wire.property || 'temperature')); - client.read('/' + wire.id + '/' + (wire.property || 'temperature'), (err, result) => { + adapter.log.debug(`Reading /${wire.id}/${wire.property || 'temperature'}`); + client.read(`/${wire.id}/${wire.property || 'temperature'}`, (err, result) => { if (result) { result.value = result.value || '0'; result.value = result.value.trim(); - adapter.log.debug('Read result ' + result.path + ':' + result.value); + adapter.log.debug(`Read result ${result.path}:${result.value}`); } if (!err && result) { if (wire.iButton) { - adapter.setState('wires.' + wire._name, {val: true, ack: true, q: 0}); // sensor reports OK + adapter.setState(`wires.${wire._name}`, {val: true, ack: true, q: 0}); // sensor reports OK } else { // ALL is like "0,1" - if (wire.property.indexOf('.ALL') !== -1) { - adapter.setState('wires.' + wire._name, {val: result.value || '', ack: true, q: 0}); + if (wire.property.includes('.ALL')) { + adapter.setState(`wires.${wire._name}`, {val: result.value || '', ack: true, q: 0}); } else // PIO.0, PIO.1, PIO.A are boolean - if (wire.property.indexOf('PIO') !== -1 && wire.property.indexOf('.BYTE') === -1) { - adapter.setState('wires.' + wire._name, {val: result.value === '1' || result.value === 1, ack: true, q: 0}); + if (wire.property.includes('PIO') && !wire.property.includes('.BYTE')) { + adapter.setState(`wires.${wire._name}`, {val: result.value === '1' || result.value === 1, ack: true, q: 0}); } else { // else some float value, e.g. temperature let val = owfsParseFloat(result.value); if (!isNaN(val)) { if (adapter.config.noStateChangeOn85C && val >= 84.999 && val <= 85.001) { - adapter.log.info('Ignoring 85.0°C value of /' + wire.id + '/' + (wire.property || 'temperature') + ': ' + result.value); + adapter.log.info(`Ignoring 85.0°C value of /${wire.id}/${wire.property || 'temperature'}: ${result.value}`); } else { - adapter.setState('wires.' + wire._name, {val: val, ack: true, q: 0}); + adapter.setState(`wires.${wire._name}`, {val: val, ack: true, q: 0}); } } else { - adapter.log.info('Cannot parse value of /' + wire.id + '/' + (wire.property || 'temperature') + ': ' + result.value); + adapter.log.info(`Cannot parse value of /${wire.id}/${wire.property || 'temperature'}: ${result.value}`); if (!adapter.config.noStateChangeOnError) { - adapter.setState('wires.' + wire._name, {val: 0, ack: true, q: 0x42}); // sensor reports nonsense + adapter.setState(`wires.${wire._name}`, {val: 0, ack: true, q: 0x42}); // sensor reports nonsense } } } } } else { if (wire.iButton) { - adapter.setState('wires.' + wire._name, {val: false, ack: true, q: 0}); // sensor reports error + adapter.setState(`wires.${wire._name}`, {val: false, ack: true, q: 0}); // sensor reports error } else { if (!adapter.config.noStateChangeOnError) { - adapter.setState('wires.' + wire._name, {val: 0, ack: true, q: 0x84}); // sensor reports error + adapter.setState(`wires.${wire._name}`, {val: 0, ack: true, q: 0x84}); // sensor reports error } - adapter.log.info('Cannot read value of /' + wire.id + '/' + (wire.property || 'temperature') + ': ' + err); + adapter.log.info(`Cannot read value of /${wire.id}/${wire.property || 'temperature'}: ${err}`); } } }); } else { - const pathFile = path1wire + '/' + wire.id + '/' + (wire.property || 'temperature'); - // Read from file - adapter.log.debug('Reading ' + pathFile); + const pathFile = `${path1wire}/${wire.id}/${wire.property || 'temperature'}`; + // Read from a file + adapter.log.debug(`Reading ${pathFile}`); try { const result = fs.readFileSync(pathFile, 'utf8').toString(); - adapter.log.debug('Read result ' + pathFile + ': ' + result); + adapter.log.debug(`Read result ${pathFile}: ${result}`); if (wire.iButton) { - adapter.setState('wires.' + wire._name, {val: true, ack: true, q: 0}); // sensor reports OK + adapter.setState(`wires.${wire._name}`, {val: true, ack: true, q: 0}); // sensor reports OK } else { // ALL is like "0,1" - if (wire.property.indexOf('.ALL') !== -1) { - adapter.setState('wires.' + wire._name, {val: result || '', ack: true, q: 0}); + if (wire.property.includes('.ALL')) { + adapter.setState(`wires.${wire._name}`, {val: result || '', ack: true, q: 0}); } else // PIO.0, PIO.1, PIO.A are boolean - if (wire.property.indexOf('PIO') !== -1 && wire.property.indexOf('.BYTE') === -1) { - adapter.setState('wires.' + wire._name, {val: result === '1', ack: true, q: 0}); + if (wire.property.includes('PIO') && !wire.property.includes('.BYTE')) { + adapter.setState(`wires.${wire._name}`, { val: result === '1', ack: true, q: 0 }); } else { // else some float value, e.g. temperature let val = owfsParseFloat(result); if (!isNaN(val)) { if (adapter.config.noStateChangeOn85C && val >= 84.999 && val <= 85.001) { - adapter.log.info('Ignoring 85.0°C value of /' + wire.id + '/' + (wire.property || 'temperature') + ': ' + result.value); + adapter.log.info(`Ignoring 85.0°C value of /${wire.id}/${wire.property || 'temperature'}: ${result.value}`); } else { - adapter.setState('wires.' + wire._name, {val: val, ack: true, q: 0}); + adapter.setState(`wires.${wire._name}`, {val: val, ack: true, q: 0}); } } else { - adapter.log.info('Cannot parse value of ' + pathFile + ': ' + result); + adapter.log.info(`Cannot parse value of ${pathFile}: ${result}`); if (!adapter.config.noStateChangeOnError) { - adapter.setState('wires.' + wire._name, {val: 0, ack: true, q: 0x42}); // sensor reports nonsense + adapter.setState(`wires.${wire._name}`, {val: 0, ack: true, q: 0x42}); // sensor reports nonsense } } } } } catch (err) { if (wire.iButton) { - adapter.setState('wires.' + wire._name, {val: false, ack: true, q: 0}); // sensor reports error + adapter.setState(`wires.${wire._name}`, {val: false, ack: true, q: 0}); // sensor reports error } else { if (!adapter.config.noStateChangeOnError) { - adapter.setState('wires.' + wire._name, {val: 0, ack: true, q: 0x84}); // sensor reports error + adapter.setState(`wires.${wire._name}`, {val: 0, ack: true, q: 0x84}); // sensor reports error } - adapter.log.info('Cannot read value of ' + pathFile + ': ' + err); + adapter.log.info(`Cannot read value of ${pathFile}: ${err}`); } } } @@ -455,16 +456,16 @@ function pollAlarm() { return; } - fs = fs || require('fs'); - fs.readdir(path1wire + '/alarm', (err, dirs) => { + fs = fs || require('node:fs'); + fs.readdir(`${path1wire}/alarm`, (err, dirs) => { if (err || !dirs.length) { return; } activeAlarm = true; - adapter.setState(adapter.namespace + '.alarm', true); + adapter.setState(`${adapter.namespace}.alarm`, true); dirs.forEach(dir => { - adapter.log.info('Alarm on ' + dir); + adapter.log.info(`Alarm on ${dir}`); adapter.config.wires.forEach(wire => wire && wire.id === dir && readWire(wire)); }); @@ -477,7 +478,7 @@ function createState(wire, callback) { type: 'number', read: true, write: true, - role: 'value.' + (wire.property || 'temperature'), + role: `value.${wire.property || 'temperature'}`, desc: '1wire sensor' }; if (wire.iButton) { @@ -500,7 +501,7 @@ function createState(wire, callback) { obj.write = false; } - if (wire.property.indexOf('PIO') !== -1) { + if (wire.property.includes('PIO')) { obj.type = 'boolean'; obj.role = 'switch'; } @@ -515,7 +516,7 @@ function createState(wire, callback) { function addState(wire, callback) { adapter.getObject('wires', (err, obj) => { if (err || !obj) { - // if root does not exist, channel will not be created + // if root does not exist, a channel will not be created adapter.createChannel('', 'wires', [], () => createState(wire, callback)); } else { createState(wire, callback); @@ -532,12 +533,12 @@ function syncConfig(cb) { if (adapter.config.wires) { for (k = 0; k < adapter.config.wires.length; k++) { if (!adapter.config.wires[k] || (!adapter.config.wires[k].name && !adapter.config.wires[k].id)) { - adapter.log.error('Invalid config for wire with index ' + k); + adapter.log.error(`Invalid config for wire with index ${k}`); continue; } adapter.config.wires[k]._name = (adapter.config.wires[k].name || adapter.config.wires[k].id).replace(/[.\s\/]+/g, '_'); - configToAdd.push(adapter.namespace + '.wires.' + adapter.config.wires[k]._name); + configToAdd.push(`${adapter.namespace}.wires.${adapter.config.wires[k]._name}`); } } @@ -551,19 +552,21 @@ function syncConfig(cb) { if (adapter.config.wires) { // Check room, id and property for (let u = 0; u < adapter.config.wires.length; u++) { - if (!adapter.config.wires[u] || !adapter.config.wires[u]._name) continue; + if (!adapter.config.wires[u] || !adapter.config.wires[u]._name) { + continue; + } - if (adapter.namespace + '.wires.' + adapter.config.wires[u]._name === _states[j]._id) { + if (`${adapter.namespace}.wires.${adapter.config.wires[u]._name}` === _states[j]._id) { if (_states[j].common.name !== (adapter.config.wires[u].name || adapter.config.wires[u].id) || _states[j].native.id !== adapter.config.wires[u].id || _states[j].native.property !== adapter.config.wires[u].property) { adapter.extendObject(_states[j]._id, { common: { - name: (adapter.config.wires[u].name || adapter.config.wires[u].id) + name: adapter.config.wires[u].name || adapter.config.wires[u].id, }, native: { - id: adapter.config.wires[u].id, - property: adapter.config.wires[u].property + id: adapter.config.wires[u].id, + property: adapter.config.wires[u].property, } }); } @@ -578,8 +581,10 @@ function syncConfig(cb) { if (configToAdd.length && adapter.config.wires) { for (let r = 0; r < adapter.config.wires.length; r++) { - if (!adapter.config.wires[r] || !adapter.config.wires[r]._name) continue; - if (configToAdd.indexOf(adapter.namespace + '.wires.' + adapter.config.wires[r]._name) !== -1) { + if (!adapter.config.wires[r] || !adapter.config.wires[r]._name) { + continue; + } + if (configToAdd.includes(`${adapter.namespace}.wires.${adapter.config.wires[r]._name}`)) { count++; addState(adapter.config.wires[r], () => !--count && cb && cb()); @@ -594,7 +599,9 @@ function syncConfig(cb) { } } - if (!count && cb) cb(); + if (!count && cb) { + cb(); + } }); } @@ -606,7 +613,7 @@ function main() { if (!adapter.config.local) { client = getOWFSClient({host: adapter.config.ip, port: adapter.config.port}); } else { - fs = require('fs'); + fs = require('node:fs'); path1wire = adapter.config.path || '/mnt/1wire'; if (path1wire[path1wire.length - 1] === '/') { path1wire = path1wire.substring(0, path1wire.length - 1); @@ -621,22 +628,26 @@ function main() { pollAll(); for (let i = 0; i < adapter.config.wires.length; i++) { - if (!adapter.config.wires[i]) continue; + if (!adapter.config.wires[i]) { + continue; + } if (!adapter.config.wires[i].interval) { adapter.config.wires[i].interval = adapter.config.interval * 1000; } else { adapter.config.wires[i].interval *= 1000; - if (!adapter.config.wires[i].interval) adapter.config.wires[i].interval = adapter.config.interval * 1000; + if (!adapter.config.wires[i].interval) { + adapter.config.wires[i].interval = adapter.config.interval * 1000; + } } - // If interval yet exists, just add to list + // If an interval yet exists, just add to the list if (timers[adapter.config.wires[i].interval]) { timers[adapter.config.wires[i].interval].ports.push(i); continue; } - // start new interval + // start a new interval timers[adapter.config.wires[i].interval] = { timer: setInterval(pollAll, adapter.config.wires[i].interval, adapter.config.wires[i].interval), - ports: [i] + ports: [i], }; } @@ -651,12 +662,12 @@ function main() { activeAlarm = false; adapter.getObject('states.alarm', (err, obj) => { !obj && adapter.createState('', 'states', 'alarm', false, { - read: true, - write: false, - desc: '1wire alarm indication', - type: 'boolean', - def: false, - role: 'state' + read: true, + write: false, + desc: '1wire alarm indication', + type: 'boolean', + def: false, + role: 'state', }); }); alarmPollingTimer = setInterval(pollAlarm, adapter.config.alarmInterval); diff --git a/package.json b/package.json index 4ad06a9..afd9714 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ "@alcalzone/release-script-plugin-iobroker": "^3.5.9", "@alcalzone/release-script-plugin-license": "^3.7.0", "@iobroker/testing": "^4.1.0", - "gulp": "^4.0.2", "mocha": "^10.2.0", "chai": "^4.3.7", "axios": "^1.7.5" @@ -37,6 +36,13 @@ "url": "https://github.com/ioBroker/ioBroker.owfs/issues" }, "main": "main.js", + "files": [ + "admin/", + "lib/", + "main.js", + "io-package.json", + "LICENSE" + ], "scripts": { "test": "npm run test:package && npm run test:unit", "test:package": "mocha test/package --exit",