iobroker.wifilight
Advanced tools
Comparing version 1.2.2 to 1.3.0
@@ -0,45 +1,47 @@ | ||
const RGB_MAX = 255; | ||
const HUE_MAX = 360; | ||
const SV_MAX = 100; | ||
const FLOAT_RGB_MAX = 255.0; | ||
const FLOAT_HUE_MAX = 360.0; | ||
const FLOAT_SV_MAX = 100.0; | ||
//"use strict"; | ||
// ohne const und use strict sind C_ global | ||
const | ||
RGB_MAX = 255, | ||
HUE_MAX = 360, | ||
SV_MAX = 100, | ||
FLOAT_RGB_MAX = 255.0, | ||
FLOAT_HUE_MAX = 360.0, | ||
FLOAT_SV_MAX = 100.0; | ||
exports.minmax = function (v, min, max) { | ||
if(v < min) return min; | ||
if(v > max) return max; | ||
function minmax(v, min, max) { | ||
if (v < min) { | ||
return min; | ||
} | ||
if (v > max) { | ||
return max; | ||
} | ||
return v; | ||
}; | ||
} | ||
exports.mmrgb = function (v) { | ||
return (minmax(v, 0, 255)); | ||
}; | ||
function mmrgb(v) { | ||
return minmax(v, 0, 255); | ||
} | ||
exports.checkRGB = function (co) { | ||
//for (var i in co) { | ||
// co[i] = mmrgb(parseInt(co[i])); | ||
//} | ||
co.r = mmrgb(parseInt(co.r)); | ||
co.g = mmrgb(parseInt(co.g)); | ||
co.b = mmrgb(parseInt(co.b)); | ||
if (co.w != undefined) co.w = mmrgb(parseInt(co.w)); | ||
//return co; | ||
}; | ||
// function checkRGB(co) { | ||
// // for (const i in co) { | ||
// // co[i] = mmrgb(parseInt(co[i])); | ||
// // } | ||
// co.r = mmrgb(parseInt(co.r)); | ||
// co.g = mmrgb(parseInt(co.g)); | ||
// co.b = mmrgb(parseInt(co.b)); | ||
// if (co.w !== undefined) { | ||
// co.w = mmrgb(parseInt(co.w)); | ||
// } | ||
// //return co; | ||
// } | ||
exports.roundRGB = function (co, copy) { | ||
function roundRGB(co, copy) { | ||
if (copy) { | ||
var c = {}; | ||
//for (var i in co) { | ||
const c = {}; | ||
// for (const i in co) { | ||
// c[i] = mmrgb(Math.round(co[i])); | ||
//} | ||
// } | ||
c.r = mmrgb(Math.round(co.r)); | ||
c.g = mmrgb(Math.round(co.g)); | ||
c.b = mmrgb(Math.round(co.b)); | ||
if(co.w != undefined) c.w = mmrgb(Math.round(co.w)); | ||
if (co.w !== undefined) { | ||
c.w = mmrgb(Math.round(co.w)); | ||
} | ||
//checkRGB(c); | ||
@@ -51,34 +53,36 @@ return c; | ||
co.b = mmrgb(Math.round(co.b)); | ||
if(co.w != undefined) co.w = mmrgb(Math.round(co.w)); | ||
if (co.w !== undefined) { | ||
co.w = mmrgb(Math.round(co.w)); | ||
} | ||
//checkRGB(co); | ||
}; | ||
} | ||
exports.xct2rgb = function (kelvin){ | ||
var temp = (kelvin * (40000-1000) / 5000 + 1000) / 100; | ||
var co = { r: 255, g: 0, b: 255 }; | ||
if( temp <= 66 ){ | ||
co.r = 255; | ||
co.g = temp; | ||
co.g = 99.4708025861 * Math.log(co.g) - 161.1195681661; | ||
if( temp <= 19){ | ||
co.b = 0; | ||
} else { | ||
co.b = temp-10; | ||
co.b = 138.5177312231 * Math.log(co.b) - 305.0447927307; | ||
} | ||
} else { | ||
co.r = temp - 60; | ||
co.r = 329.698727446 * Math.pow(co.r, -0.1332047592); | ||
co.g = temp - 60; | ||
co.g = 288.1221695283 * Math.pow(co.g, -0.0755148492 ); | ||
co.b = 255; | ||
} | ||
checkRGB(co); | ||
return co; | ||
}; | ||
// function xct2rgb(kelvin){ | ||
// const temp = (kelvin * (40000 - 1000) / 5000 + 1000) / 100; | ||
// const co = { r: 255, g: 0, b: 255 }; | ||
// if (temp <= 66) { | ||
// co.r = 255; | ||
// co.g = temp; | ||
// co.g = 99.4708025861 * Math.log(co.g) - 161.1195681661; | ||
// if( temp <= 19){ | ||
// co.b = 0; | ||
// } else { | ||
// co.b = temp-10; | ||
// co.b = 138.5177312231 * Math.log(co.b) - 305.0447927307; | ||
// } | ||
// } else { | ||
// co.r = temp - 60; | ||
// co.r = 329.698727446 * Math.pow(co.r, -0.1332047592); | ||
// co.g = temp - 60; | ||
// co.g = 288.1221695283 * Math.pow(co.g, -0.0755148492); | ||
// co.b = 255; | ||
// } | ||
// checkRGB(co); | ||
// return co; | ||
// } | ||
exports.ct2rgb = function (kelvin) { | ||
var temperature = (kelvin * (40000-1000) / 5000 + 1000) / 100; | ||
//var temperature = kelvin / 100; | ||
var co = {r: 255, g: 0, b: 255 }; | ||
function ct2rgb(kelvin) { | ||
const temperature = (kelvin * (40000-1000) / 5000 + 1000) / 100; | ||
// const temperature = kelvin / 100; | ||
const co = {r: 255, g: 0, b: 255 }; | ||
@@ -103,5 +107,5 @@ if (temperature < 66.0) { | ||
roundRGB(co); | ||
//checkRGB(co); | ||
// checkRGB(co); | ||
return co; | ||
}; | ||
} | ||
@@ -111,16 +115,19 @@ //////////////////////////////////////////////////////////////////// | ||
exports.rgb2hsv = function (r, g, b) { | ||
function rgb2hsv(r, g, b) { | ||
if (typeof r === 'object') { | ||
g = r.g; b = r.b; r = r.r; | ||
g = r.g; | ||
b = r.b; | ||
r = r.r; | ||
} | ||
r = (r === RGB_MAX) ? 1 : (r % RGB_MAX / FLOAT_RGB_MAX); | ||
g = (g === RGB_MAX) ? 1 : (g % RGB_MAX / FLOAT_RGB_MAX); | ||
b = (b === RGB_MAX) ? 1 : (b % RGB_MAX / FLOAT_RGB_MAX); | ||
r = r === RGB_MAX ? 1 : (r % RGB_MAX / FLOAT_RGB_MAX); | ||
g = g === RGB_MAX ? 1 : (g % RGB_MAX / FLOAT_RGB_MAX); | ||
b = b === RGB_MAX ? 1 : (b % RGB_MAX / FLOAT_RGB_MAX); | ||
var max = Math.max(r, g, b); | ||
var min = Math.min(r, g, b); | ||
var h, s, v = max; | ||
var d = max - min; | ||
const max = Math.max(r, g, b); | ||
const min = Math.min(r, g, b); | ||
let h; | ||
const v = max; | ||
const d = max - min; | ||
s = max === 0 ? 0 : d / max; | ||
const s = max === 0 ? 0 : d / max; | ||
@@ -139,13 +146,16 @@ if (max === min) { | ||
h = (r - g) / d + 4; | ||
break | ||
break; | ||
} | ||
h /= 6; | ||
} | ||
return { h: Math.floor(h * HUE_MAX), s: Math.floor(s * SV_MAX), v: Math.floor(v * SV_MAX) }; | ||
}; | ||
return { | ||
h: Math.floor(h * HUE_MAX), | ||
s: Math.floor(s * SV_MAX), | ||
v: Math.floor(v * SV_MAX), | ||
}; | ||
} | ||
//////////////////////////////////////////////////////////////////// | ||
//based on colorsys, https://github.com/netbeast/colorsys | ||
exports.hsv2rgb = function (h, s, v) { | ||
// based on colorsys, https://github.com/netbeast/colorsys | ||
function hsv2rgb(h, s, v) { | ||
if (typeof h === 'object') { | ||
@@ -155,22 +165,28 @@ s = h.s; v = h.v; h = h.h; | ||
h = (h === HUE_MAX) ? 1 : (h % HUE_MAX / FLOAT_HUE_MAX * 6); | ||
s = (s === SV_MAX) ? 1 : (s % SV_MAX / FLOAT_SV_MAX); | ||
v = (v === SV_MAX) ? 1 : (v % SV_MAX / FLOAT_SV_MAX); | ||
h = h === HUE_MAX ? 1 : (h % HUE_MAX / FLOAT_HUE_MAX * 6); | ||
s = s === SV_MAX ? 1 : (s % SV_MAX / FLOAT_SV_MAX); | ||
v = v === SV_MAX ? 1 : (v % SV_MAX / FLOAT_SV_MAX); | ||
var i = Math.floor(h); | ||
var f = h - i; | ||
var p = v * (1 - s); | ||
var q = v * (1 - f * s); | ||
var t = v * (1 - (1 - f) * s); | ||
var mod = i % 6; | ||
var r = [v, q, p, p, t, v][mod]; | ||
var g = [t, v, v, q, p, p][mod]; | ||
var b = [p, p, t, v, v, q][mod]; | ||
const i = Math.floor(h); | ||
const f = h - i; | ||
const p = v * (1 - s); | ||
const q = v * (1 - f * s); | ||
const t = v * (1 - (1 - f) * s); | ||
const mod = i % 6; | ||
const r = [v, q, p, p, t, v][mod]; | ||
const g = [t, v, v, q, p, p][mod]; | ||
const b = [p, p, t, v, v, q][mod]; | ||
return { r: Math.round(r * RGB_MAX), g: Math.round(g * RGB_MAX), b: Math.round(b * RGB_MAX) }; | ||
return { | ||
r: Math.round(r * RGB_MAX), | ||
g: Math.round(g * RGB_MAX), | ||
b: Math.round(b * RGB_MAX), | ||
}; | ||
} | ||
exports = { | ||
hsv2rgb, | ||
rgb2hsv, | ||
ct2rgb, | ||
roundRGB, | ||
}; | ||
for (var i in exports) { | ||
global[i] = exports[i]; | ||
} |
@@ -1,65 +0,60 @@ | ||
"use strict"; | ||
const dgram = require('node:dgram'); | ||
const os = require('node:os'); | ||
const Netmask = require('netmask').Netmask; | ||
var dgram = require('dgram'), | ||
os = require('os'), | ||
Netmask = require('netmask').Netmask; | ||
const BROADCAST_PORT = 48899; | ||
var BROADCAST_PORT = 48899; | ||
exports.scanForDevices = function (checkCb, cb) { | ||
var BC_ID = "HF-A11ASSISTHREAD"; //V6 API | ||
var msg = new Buffer(BC_ID); | ||
var boradcasts = []; | ||
var ifaces = os.networkInterfaces(); | ||
const BC_ID = 'HF-A11ASSISTHREAD'; //V6 API | ||
const msg = new Buffer(BC_ID); | ||
const broadcasts = []; | ||
const ifaces = os.networkInterfaces(); | ||
for (var name in ifaces) { | ||
ifaces[name].forEach(function (iface) { | ||
for (const name in ifaces) { | ||
ifaces[name].forEach((iface) => { | ||
if ('IPv4' !== iface.family || iface.internal) { | ||
return; | ||
} | ||
var netmask = new Netmask(iface.address, iface.netmask); | ||
boradcasts.push(netmask.broadcast); | ||
}) | ||
const netmask = new Netmask(iface.address, iface.netmask); | ||
broadcasts.push(netmask.broadcast); | ||
}); | ||
} | ||
var result = []; | ||
var client = dgram.createSocket("udp4"); | ||
const result = []; | ||
const client = dgram.createSocket('udp4'); | ||
client.bind(BROADCAST_PORT); | ||
client.on('listening', function () { | ||
client.setBroadcast(true); | ||
}); | ||
client.on('message', function (message, rinfo) { | ||
var s = message.toString(); | ||
client.on('listening', () => client.setBroadcast(true)); | ||
client.on('message', (message, rinfo) => { | ||
const s = message.toString(); | ||
if (rinfo.port !== BROADCAST_PORT || s === BC_ID || s.indexOf('+ERR') === 0) { | ||
return; | ||
} | ||
if (result.indexOf(s) > -1) return; | ||
if (result.include(s)) { | ||
return; | ||
} | ||
result.push(s); | ||
}); | ||
var interval = setInterval(function () { | ||
boradcasts.forEach(function (ip) { | ||
client.send(msg, 0, msg.length, BROADCAST_PORT, ip); | ||
}); | ||
const interval = setInterval(() => { | ||
broadcasts.forEach(ip => client.send(msg, 0, msg.length, BROADCAST_PORT, ip)); | ||
}, 300); | ||
setTimeout(function() { | ||
setTimeout(() => { | ||
clearInterval(interval); | ||
client.close(); | ||
for (var i=0; i<result.length; i++) { | ||
var ar = result[i].split(','); | ||
for (let i=0; i<result.length; i++) { | ||
const ar = result[i].split(','); | ||
result[i] = { | ||
name: ar[2], | ||
mac: ar[1], | ||
ip: ar[0] | ||
//type: '', | ||
//port: 5577, | ||
//pollIntervall: 30 | ||
ip: ar[0], | ||
// type: '', | ||
// port: 5577, | ||
// pollIntervall: 30 | ||
}; | ||
if (checkCb && !checkCb(result[i])) { | ||
result.splice(i--, 1); | ||
continue; | ||
// continue; | ||
} | ||
//switch(result [i].name) { | ||
// switch(result [i].name) { | ||
// case 'HF-LPB100-ZJ200': | ||
@@ -71,53 +66,55 @@ // result[i].type = 'LD382A'; | ||
// break; | ||
//} | ||
//console.log('found: ' + JSON.stringify(result[i])); | ||
// } | ||
// console.log('found: ' + JSON.stringify(result[i])); | ||
} | ||
if(cb) cb(result); | ||
if (cb) { | ||
cb(result); | ||
} | ||
}, 2500); | ||
}; | ||
exports.scanForMiLightDevices = function scanForMiLightDevices (checkCb, cb) { | ||
const port = 48899; | ||
const ip = '255.255.255.255'; | ||
const result = []; | ||
exports.scanForMiLightDevices = function scanForMiLightDevices (checkCb, cb) { | ||
var port = 48899; | ||
var ip = '255.255.255.255'; | ||
var result = []; | ||
var socket = dgram.createSocket( {type: 'udp4', reuseAddr: true} ); | ||
//var socket = dgram.createSocket('udp4'); | ||
socket.on('error', function (err) { | ||
}); | ||
socket.on("listening", function (error) { | ||
if (error) return cb && cb(error); | ||
const socket = dgram.createSocket({ type: 'udp4', reuseAddr: true }); | ||
//const socket = dgram.createSocket('udp4'); | ||
socket.on('error', (/* err */) => {}); | ||
socket.on('listening', error => { | ||
if (error) { | ||
return cb && cb(error); | ||
} | ||
socket.setBroadcast(true); | ||
}); | ||
socket.on('message', function(msg, rinfo) { | ||
//console.log(rinfo.address); | ||
socket.on('message', (msg /* , rinfo */) => { | ||
// console.log(rinfo.address); | ||
msg = msg.toString(); | ||
if (result.indexOf(msg) > -1) return; | ||
if (result.includes(msg)) { | ||
return; | ||
} | ||
result.push(msg); | ||
}); | ||
var search = function search() { | ||
var pkt = new Buffer('Link_Wi-Fi'); | ||
socket.send(pkt, 0, pkt.length, port, ip, function(err,data) { | ||
}); | ||
}; | ||
search(); | ||
setTimeout(function() { | ||
// send search command | ||
const pkt = Buffer.from('Link_Wi-Fi'); | ||
socket.send(pkt, 0, pkt.length, port, ip, (/* err, data */) => {}); | ||
setTimeout(() => { | ||
socket.close(); | ||
for (var i=0; i<result.length; i++) { | ||
var ar = result[i].split(','); | ||
for (let i = 0; i < result.length; i++) { | ||
const ar = result[i].split(','); | ||
result[i] = { | ||
name: 'Mi-Light', | ||
mac: ar[1], | ||
ip: ar[0] | ||
//type: 'MiLight' | ||
ip: ar[0], | ||
// type: 'MiLight' | ||
}; | ||
if (checkCb && !checkCb(result[i])) { | ||
result.splice(i--, 1); | ||
continue; | ||
}; | ||
} | ||
} | ||
if(cb) cb(result); | ||
if (cb) { | ||
cb(result); | ||
} | ||
}, 2000); | ||
@@ -128,7 +125,9 @@ | ||
exports.scanForAllDevices = function scanForAllDevices(checkCb, cb) { | ||
exports.scanForDevices(checkCb, function(result) { | ||
exports.scanForMiLightDevices(checkCb, function(result2) { | ||
if (cb) cb (result.concat(result2)); | ||
exports.scanForDevices(checkCb, function (result) { | ||
exports.scanForMiLightDevices(checkCb, function (result2) { | ||
if (cb) { | ||
cb(result.concat(result2)); | ||
} | ||
}); | ||
}); | ||
}; |
680
main.js
@@ -1,12 +0,10 @@ | ||
"use strict"; | ||
const net = require('node:net'); | ||
const discovery = require('./lib/discovery'); | ||
const Colors = require('./lib/colors'); | ||
const soef = require('./lib/dontBeSoSoef'); | ||
var discovery = require(__dirname + '/lib/discovery'), | ||
colors = require(__dirname + '/lib/colors'), | ||
soef = require(`${__dirname}/lib/dontBeSoSoef`), | ||
net = require('net'); | ||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
var wifi = {}; | ||
var debug = false; | ||
const wifi = {}; | ||
const debug = false; | ||
@@ -16,7 +14,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
soef.extendAll(); | ||
var hex = soef.arrayToHex; | ||
const hex = soef.arrayToHex; | ||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
var adapter = soef.Adapter ( | ||
const adapter = soef.Adapter ( | ||
main, | ||
@@ -26,3 +24,3 @@ onStateChange, | ||
onUnload, | ||
{ name: 'wifilight' } | ||
{ name: 'wifilight' }, | ||
); | ||
@@ -37,3 +35,5 @@ | ||
function onMessage (obj) { | ||
if (!obj) return; | ||
if (!obj) { | ||
return; | ||
} | ||
switch (obj.command) { | ||
@@ -43,7 +43,5 @@ case 'discovery': | ||
function(entry) { | ||
var ret = !adapter.config.devices.some(function(e,i) { | ||
return e.ip === entry.ip; | ||
}); | ||
const ret = !adapter.config.devices.some(e => e.ip === entry.ip); | ||
if (ret) { | ||
var dev = fromDeviceName(entry.name); | ||
const dev = fromDeviceName(entry.name); | ||
entry.type = dev ? dev.type : ''; | ||
@@ -63,16 +61,16 @@ entry.port = dev && dev.port ? dev.port : 5577; | ||
default: | ||
adapter.log.warn("Unknown command: " + obj.command); | ||
adapter.log.warn(`Unknown command: ${obj.command}`); | ||
break; | ||
} | ||
if (obj.callback) adapter.sendTo (obj.from, obj.command, obj.message, obj.callback); | ||
if (obj.callback) { | ||
adapter.sendTo (obj.from, obj.command, obj.message, obj.callback); | ||
} | ||
return true; | ||
} | ||
function onUnload(callback) { | ||
Object.keys(wifi).forEach(function(v) { | ||
Object.keys(wifi).forEach(v => { | ||
wifi[v].close(); | ||
delete wifi[v]; | ||
adapter.log.debug('unload: ' + v); | ||
adapter.log.debug(`unload: ${v}`); | ||
}); | ||
@@ -89,22 +87,22 @@ callback && callback(); | ||
var cmds = require(__dirname + '/devices'); | ||
const cmds = require('./lib/devices'); | ||
var usedStateNames = { | ||
online: { n: 'reachable', g:1, val: 0, common: { write: false, type: "boolean", role: "indicator.reachable"}}, | ||
on: { n: 'on', g:3, val: false, common: { type: "boolean", role: "switch" }}, | ||
bri: { n: 'bri', g:3, val: 100, common: { type: "number", min: 0, max: 100, unit: '%', desc: '0..100%', role: "level.dimmer" }}, | ||
ct: { n: 'ct', g:1, val: 0, common: { type: "number", min: 0, max: 5000, unit: '°K', desc: 'temperature in °Kelvin 0..5000', role: "level.color.temperature" }}, | ||
red: { n: 'r', g:3, val: 0, common: { type: "number", min: 0, max: 255, desc: '0..255 or #rrggbb[ww] (hex)', role: "level.color.red" }}, | ||
green: { n: 'g', g:3, val: 0, common: { type: "number", min: 0, max: 255, desc: '0..255 or #rrggbb[ww] (hex)', role: "level.color.green" }}, | ||
blue: { n: 'b', g:3, val: 0, common: { type: "number", min: 0, max: 255, desc: '0..255 or #rrggbb[ww] (hex)', role: "level.color.blue" }}, | ||
white: { n: 'w', g:3, val: 0, common: { type: "number", min: 0, max: 255, desc: '0..255 or #rrggbb[ww] (hex)', role: "level.color.white" }}, | ||
disco: { n: 'disco', g:2, val: 1, common: { type: "number", min: 1, max: 9, desc: '1..9' }}, | ||
progNo: { n: 'progNo', g:1, val: 38, common: { type: "number", min: 35, max: 56, desc: '37..56, 97=none' }}, | ||
progOn: { n: 'progOn', g:1, val: false, common: { type: "boolean", desc: 'program on/off' }}, | ||
progSpeed: { n: 'progSpeed', g:3, val: 10, common: { type: "number", min: 0, max: 255 }, desc: 'speed for preogram'}, | ||
refresh: { n: 'refresh', g:1, val: false, common: { type: "boolean", desc: 'read states from device' }}, | ||
transition: { n: 'trans', g:1, val: 30, common: { type: "number", unit: '\u2152 s', desc: 'in 10th seconds'} }, | ||
command: { n: 'command', g:3, val: 'r:0, g:0, b:0, on:true, transition:30', desc: 'r:0, g:0, b:0, on:true, transition:2' }, | ||
rgb: { n: 'rgb', g:3, val: '', common: { type: "text", desc: '000000..ffffff' , role: "level.color.rgb"}}, | ||
onTime: { n: 'onTime', g:3, val: '', common: {}} | ||
const usedStateNames = { | ||
online: { n: 'reachable', g: 1, val: 0, common: { write: false, type: 'boolean', role: 'indicator.reachable'}}, | ||
on: { n: 'on', g: 3, val: false, common: { type: 'boolean', role: 'switch' }}, | ||
bri: { n: 'bri', g: 3, val: 100, common: { type: 'number', min: 0, max: 100, unit: '%', desc: '0..100%', role: 'level.dimmer' }}, | ||
ct: { n: 'ct', g: 1, val: 0, common: { type: 'number', min: 0, max: 5000, unit: '°K', desc: 'temperature in °Kelvin 0..5000', role: 'level.color.temperature' }}, | ||
red: { n: 'r', g: 3, val: 0, common: { type: 'number', min: 0, max: 255, desc: '0..255 or #rrggbb[ww] (hex)', role: 'level.color.red' }}, | ||
green: { n: 'g', g: 3, val: 0, common: { type: 'number', min: 0, max: 255, desc: '0..255 or #rrggbb[ww] (hex)', role: 'level.color.green' }}, | ||
blue: { n: 'b', g: 3, val: 0, common: { type: 'number', min: 0, max: 255, desc: '0..255 or #rrggbb[ww] (hex)', role: 'level.color.blue' }}, | ||
white: { n: 'w', g: 3, val: 0, common: { type: 'number', min: 0, max: 255, desc: '0..255 or #rrggbb[ww] (hex)', role: 'level.color.white' }}, | ||
disco: { n: 'disco', g: 2, val: 1, common: { type: 'number', min: 1, max: 9, desc: '1..9' }}, | ||
progNo: { n: 'progNo', g: 1, val: 38, common: { type: 'number', min: 35, max: 56, desc: '37..56, 97=none' }}, | ||
progOn: { n: 'progOn', g: 1, val: false, common: { type: 'boolean', desc: 'program on/off' }}, | ||
progSpeed: { n: 'progSpeed', g: 3, val: 10, common: { type: 'number', min: 0, max: 255 }, desc: 'speed for program'}, | ||
refresh: { n: 'refresh', g: 1, val: false, common: { type: 'boolean', desc: 'read states from device' }}, | ||
transition: { n: 'trans', g: 1, val: 30, common: { type: 'number', unit: '\u2152 s', desc: 'in 10th seconds'} }, | ||
command: { n: 'command', g: 3, val: 'r:0, g:0, b:0, on:true, transition:30', desc: 'r:0, g:0, b:0, on:true, transition:2' }, | ||
rgb: { n: 'rgb', g: 3, val: '', common: { type: 'text', desc: '000000..ffffff' , role: 'level.color.rgb'}}, | ||
onTime: { n: 'onTime', g: 3, val: '', common: {}} | ||
}; | ||
@@ -116,6 +114,8 @@ | ||
val = val.toString(); | ||
var ar = val.split('.'); | ||
const ar = val.split('.'); | ||
if (ar && ar.length > 1) val = ar[0]; | ||
if (val[0] === '#') val = val.substr(1); | ||
var co = { | ||
if (val[0] === '#') { | ||
val = val.substr(1); | ||
} | ||
const co = { | ||
r: parseInt(val.substr(0, 2), 16), | ||
@@ -129,7 +129,7 @@ g: parseInt(val.substr(2, 2), 16) || 0, | ||
if (ar && ar.length > 1) { | ||
var m = Number('.' + ar[1]); | ||
for (var i in co) { | ||
const m = Number(`.${ar[1]}`); | ||
for (const i in co) { | ||
co[i] *= m; | ||
} | ||
roundRGB(co); | ||
Colors.roundRGB(co); | ||
} | ||
@@ -141,13 +141,18 @@ return co; | ||
function onStateChange(id, state) { | ||
var ar = id.split('.'); | ||
//var dcs = adapter.idToDCS(id); | ||
var deviceName = ar[2], channelName = ''; | ||
const ar = id.split('.'); | ||
//const dcs = adapter.idToDCS(id); | ||
let deviceName = ar[2]; | ||
let channelName = ''; | ||
if (ar.length > 4) { | ||
channelName = ar.splice(3, 1)[0]; | ||
deviceName += '.' + channelName; | ||
deviceName += `.${channelName}`; | ||
} | ||
var stateName = ar[3]; | ||
var device = wifi[deviceName]; | ||
if (device == undefined || !device.isOnline || !state || state.val === null || state.ack) return; | ||
if (device.cmds.decodeResponse) devices.invalidate(id); | ||
const stateName = ar[3]; | ||
const device = wifi[deviceName]; | ||
if (device === undefined || !device.isOnline || !state || state.val === null || state.ack) { | ||
return; | ||
} | ||
if (device.cmds.decodeResponse) { | ||
devices.invalidate(id); | ||
} | ||
device.stopRunningProgram(); | ||
@@ -159,7 +164,9 @@ device.onStateChange(channelName, stateName, state.val); | ||
var WifiLight = function (config, zone, cb) { | ||
const WifiLight = function (config, zone, cb) { | ||
if (!(this instanceof WifiLight)) { | ||
return new WifiLight(config, zone, cb); | ||
} | ||
if (!config) return this; | ||
if (!config) { | ||
return this; | ||
} | ||
this.config = config; | ||
@@ -173,10 +180,14 @@ this.isOnline = false; | ||
if (!this.cmds) { | ||
adapter.log.error('wrong device type. ' + this.config.type + ' not yet supported!'); | ||
if (cb) cb(-1); | ||
adapter.log.error(`wrong device type. ${this.config.type} not yet supported!`); | ||
if (cb) { | ||
cb(-1); | ||
} | ||
return null; | ||
} | ||
if (this.cmds.vmax === undefined) this.cmds.vmax = 255; | ||
if (this.cmds.vmax === undefined) { | ||
this.cmds.vmax = 255; | ||
} | ||
this.cmds.g = this.cmds.g || 1; | ||
this.createDevice(function(err) { | ||
this.createDevice(function (/* err */) { | ||
this.setOnline(false); | ||
@@ -188,3 +199,2 @@ | ||
} | ||
this.locked = 0; | ||
this.queue = []; | ||
@@ -200,3 +210,3 @@ this.dataBuffer = new Uint8Array(200); | ||
WifiLight.prototype.log = function (msg) { | ||
adapter.log.debug('[' + this.config.ip + '] ' + msg); | ||
adapter.log.debug(`[${this.config.ip}] ${msg}`); | ||
}; | ||
@@ -206,11 +216,26 @@ | ||
this.dev = new devices.CDevice(0, ''); | ||
this.dev.setDevice(this.config.ip, {common: {name: this.config.name, role: 'device'}, native: { type: this.config.type, intervall: this.config.pollIntervall } }); | ||
this.dev.setDevice(this.config.ip, { | ||
common: { | ||
name: this.config.name, | ||
role: 'device', | ||
}, | ||
native: { | ||
type: this.config.type, | ||
intervall: this.config.pollIntervall, | ||
}, | ||
}); | ||
if (this.zone !== undefined) { | ||
this.dev.setChannel(this.zone.toString(), ['All Zones', 'Zone 1', 'Zone 2', 'Zone 3', 'Zone 4'][this.zone]); | ||
} | ||
wifi[this.dev.getFullId()] = this; | ||
for (var j in usedStateNames) { | ||
if (j === 'white' && this.cmds.rgbw === undefined) continue; | ||
var st = Object.assign({}, usedStateNames[j]); | ||
if ((j === 'progNo' || j==='disco') && this.cmds.programNames) st.common.states = this.cmds.programNames; | ||
for (const j in usedStateNames) { | ||
if (j === 'white' && this.cmds.rgbw === undefined) { | ||
continue; | ||
} | ||
const st = Object.assign({}, usedStateNames[j]); | ||
if ((j === 'progNo' || j === 'disco') && this.cmds.programNames) { | ||
st.common.states = this.cmds.programNames; | ||
} | ||
if (st.g & this.cmds.g) { | ||
@@ -224,5 +249,5 @@ this.dev.createNew(st.n, st); | ||
WifiLight.prototype.onStateChange = function (channel, stateName, val) { | ||
var transitionTime = this.getval(channel, usedStateNames.transition.n, 0); | ||
let transitionTime = this.getval(channel, usedStateNames.transition.n, 0); | ||
this.clearQueue(); | ||
let co; | ||
switch (stateName) { | ||
@@ -240,3 +265,3 @@ case usedStateNames.transition.n: | ||
case 'rgb': | ||
var co = parseHexColors(val); | ||
co = parseHexColors(val); | ||
this.color(channel, co); | ||
@@ -249,3 +274,2 @@ break; | ||
case 'sat': | ||
var co; | ||
if (typeof val === 'string' && val[0] === '#') { | ||
@@ -270,11 +294,14 @@ co = parseHexColors(val); | ||
break; | ||
case usedStateNames.progSpeed.n: | ||
var progNo = this.get(channel, usedStateNames.progNo.n).val; | ||
case usedStateNames.progSpeed.n: { | ||
const progNo = this.get(channel, usedStateNames.progNo.n).val; | ||
this.addToQueue(channel, this.cmds.progNo, progNo, val); | ||
break; | ||
case usedStateNames.progNo.n: | ||
var speed; | ||
} | ||
case usedStateNames.progNo.n: { | ||
let speed; | ||
if (typeof val === 'string') { | ||
var ar = val.split(' '); | ||
if (!ar || ar.lengt < 2) ar = val.split(','); | ||
let ar = val.split(' '); | ||
if (!ar || ar.lengt < 2) { | ||
ar = val.split(','); | ||
} | ||
if (ar && ar.length >= 2) { | ||
@@ -287,15 +314,39 @@ speed = parseInt(ar[1]); | ||
} | ||
//if (this.cmds._setProgNo) _setProgNo(this, channel, val >> 0); else | ||
// if (this.cmds._setProgNo) _setProgNo(this, channel, val >> 0); else | ||
this.addToQueue(channel, this.cmds.progNo, val >> 0, speed); | ||
break; | ||
} | ||
case usedStateNames.progOn.n: | ||
this.addToQueue(channel, val ? this.cmds.progOn : this.cmds.progOff); | ||
break; | ||
case usedStateNames.command.n: | ||
var v = val.replace(/(^on$|red|green|blue|transition|bri|off)/g, function(match, p) { return { '#': '#', off:'off:1', on:'on:1', red:'r', green:'g', blue:'b', white: 'w', transition:'x', bri:'l'/*, off:'on:0'*/} [match] }); | ||
v = v.replace(/\s|\"|;$|,$/g, '').replace(/=/g, ':').replace(/;/g, ',').replace(/true/g, 1).replace(/((on|off),{1})/g, '$2:1,').replace(/#((\d|[a-f]|[A-F]|[.])*)/g, 'h:"$1"').replace(/(r|g|b|w|x|l|sat|off|on|ct|h|p)/g, '"$1"').replace(/^\{?(.*?)\}?$/, '{$1}'); | ||
case usedStateNames.command.n: { | ||
let v = val.replace(/(^on$|red|green|blue|transition|bri|off)/g, match => { | ||
return { | ||
'#': '#', | ||
off: 'off:1', | ||
on: 'on:1', | ||
red: 'r', | ||
green: 'g', | ||
blue: 'b', | ||
white: 'w', | ||
transition: 'x', | ||
bri: 'l' | ||
//, off: 'on:0' | ||
}[match]; | ||
}); | ||
v = v | ||
.replace(/\s|"|;$|,$/g, '') | ||
.replace(/=/g, ':') | ||
.replace(/;/g, ',') | ||
.replace(/true/g, 1) | ||
.replace(/((on|off),{1})/g, '$2:1,') | ||
.replace(/#((\d|[a-f]|[A-F]|[.])*)/g, 'h:"$1"') | ||
.replace(/(r|g|b|w|x|l|sat|off|on|ct|h|p)/g, '"$1"') | ||
.replace(/^\{?(.*?)}?$/, '{$1}'); | ||
let colors; | ||
try { | ||
var colors = JSON.parse(v); | ||
colors = JSON.parse(v); | ||
} catch (e) { | ||
adapter.log.error("on Command: " + e.message + ': state.val="' + val + '"'); | ||
adapter.log.error(`on Command: ${e.message}: state.val="${val}"`); | ||
return; | ||
@@ -311,8 +362,13 @@ } | ||
} | ||
if (!colors || typeof colors !== 'object') return; | ||
if(colors.off !== undefined) { | ||
this.color(channel, {r:0, g:0, b:0, w: colors.w !== undefined ? 0 : undefined}); | ||
this.states.red = 0; this.states.green = 0; this.states.blue = 0; if (this.states.white !== undefined) this.states.white = 0; | ||
if (!colors || typeof colors !== 'object') { | ||
return; | ||
} | ||
var o = fullExtend(this.getRGBStates(channel), colors); | ||
if (colors.off !== undefined) { | ||
this.color(channel, {r: 0, g: 0, b: 0, w: colors.w !== undefined ? 0 : undefined}); | ||
this.states.red = 0; | ||
this.states.green = 0; | ||
this.states.blue = 0; | ||
if (this.states.white !== undefined) this.states.white = 0; | ||
} | ||
const o = fullExtend(this.getRGBStates(channel), colors); | ||
adapter.log.debug(JSON.stringify(o)); | ||
@@ -325,3 +381,3 @@ if (o.x !== undefined) { | ||
} | ||
if (colors.r!==undefined || colors.g!==undefined || colors.b!==undefined || colors.w!==undefined || colors.sat!==undefined) { | ||
if (colors.r !== undefined || colors.g !== undefined || colors.b !== undefined || colors.w !== undefined || colors.sat !== undefined) { | ||
this.fade(channel, o, transitionTime); | ||
@@ -336,4 +392,5 @@ } | ||
break; | ||
} | ||
default: | ||
return | ||
return; | ||
} | ||
@@ -349,5 +406,5 @@ }; | ||
WifiLight.prototype.runJsonProgram = function (channel, cmds) { | ||
var i = -1, self = this; | ||
var delay = 30; | ||
var lastCo = { red: self.states.red, green: self.states.green, blue: self.states.blue}; | ||
let i = -1; | ||
const self = this; | ||
const lastCo = { red: self.states.red, green: self.states.green, blue: self.states.blue}; | ||
this.prgTimer.clear(); | ||
@@ -361,12 +418,20 @@ self.clearQueue(); | ||
} | ||
if (++i >= cmds.length) i = 0; | ||
var cmd = cmds[i]; | ||
if (cmd.x === undefined) cmd.x = 0; | ||
var delay = Math.abs(cmd.x); | ||
if (++i >= cmds.length) { | ||
i = 0; | ||
} | ||
const cmd = cmds[i]; | ||
if (cmd.x === undefined) { | ||
cmd.x = 0; | ||
} | ||
const delay = Math.abs(cmd.x); | ||
if (cmd.r !== undefined) { | ||
Object.assign(self.states, lastCo); | ||
self.fade(channel, cmd, delay); | ||
lastCo.red = cmd.r; lastCo.green = cmd.g; lastCo.blue = cmd.b; | ||
lastCo.red = cmd.r; | ||
lastCo.green = cmd.g; | ||
lastCo.blue = cmd.b; | ||
} | ||
if (cmd.x < 0) return; | ||
if (cmd.x < 0) { | ||
return; | ||
} | ||
self.prgTimer.set(doIt, 10 + delay * 10); | ||
@@ -389,3 +454,3 @@ } | ||
this.destroyClient(); | ||
setTimeout(this.start.bind(this, cb), timeout == undefined ? 5000 : timeout); | ||
setTimeout(() => this.start(cb), timeout === undefined ? 5000 : timeout); | ||
} | ||
@@ -399,3 +464,2 @@ }; | ||
WifiLight.prototype.start = function (cb) { | ||
if (this.USE_SOCKET_ONCE) { | ||
@@ -408,19 +472,17 @@ if (this.__proto__._write === WifiLight.prototype._write) { | ||
var self = this; | ||
const self = this; | ||
self.destroyClient(); | ||
if (debug) { | ||
this.ts = new Date().getTime(); | ||
this.ts = Date.now(); | ||
} | ||
self.client = new net.Socket(); | ||
self.client.on('data', function(data) { | ||
self.onData(data); | ||
}); | ||
self.client.on('close', function(hasError) { | ||
self.client.on('data', data => self.onData(data)); | ||
self.client.on('close', function (hasError) { | ||
self.setOnline(false); | ||
var ts = debug ? '(' + parseInt((new Date().getTime() - self.ts) / 1000) + ' sec) ' : ""; | ||
self.log('onClose ' + ts + 'hasError=' + hasError + ' client=' + self.client); | ||
const ts = debug ? `(${parseInt((Date.now() - self.ts) / 1000)} sec) ` : ''; | ||
self.log(`onClose ${ts}hasError=${hasError} client=${self.client}`); | ||
}); | ||
self.client.on('error', function(error) { | ||
var ts = debug ? '(' + parseInt((new Date().getTime() - self.ts) / 1000) + ' sec) ' : ""; | ||
self.log('onError: ' + ts + (error.code != undefined ? error.code : "") + ' ' + error.message); | ||
self.client.on('error', function (error) { | ||
const ts = debug ? `(${parseInt((Date.now() - self.ts) / 1000)} sec) ` : ''; | ||
self.log(`onError: ${ts}${error.code !== undefined ? error.code : ''} ${error.message}`); | ||
switch (error.errno) { //error.code | ||
@@ -435,8 +497,10 @@ case 'ECONNRESET': | ||
}); | ||
self.client.connect(self.config.port, self.config.ip, function() { | ||
self.log(self.config.ip + ' connected'); | ||
self.client.connect(self.config.port, self.config.ip, function () { | ||
self.log(`${self.config.ip} connected`); | ||
self.setOnline(true); | ||
self.runUpdateTimer(); | ||
adapter.log.debug('self.client.connect: connected'); | ||
if (cb && typeof cb == 'function') cb(); | ||
if (typeof cb == 'function') { | ||
cb(); | ||
} | ||
}); | ||
@@ -457,3 +521,2 @@ }; | ||
WifiLight.prototype.writeOnce = function(data, cb) { | ||
if (this.client) { | ||
@@ -465,4 +528,4 @@ this.client.write(data, cb); | ||
var self = this; | ||
this.client.on('data', function(data) { | ||
const self = this; | ||
this.client.on('data', function (data) { | ||
self.onData(data); | ||
@@ -472,7 +535,7 @@ self.client.end(); | ||
}); | ||
this.client.on('error', function(error) { | ||
this.client.on('error', function (/* error */) { | ||
self.destroyClient(); | ||
}); | ||
this.client.connect(this.config.port, this.config.ip, function() { | ||
this.client.connect(this.config.port, this.config.ip, function () { | ||
self.client.write(data, cb); | ||
@@ -485,4 +548,5 @@ }); | ||
}; | ||
WifiLight.prototype.getval = function (channel, state, def) { | ||
var o = this.dev.get(channel, state); | ||
const o = this.dev.get(channel, state); | ||
if (o && o.val !== undefined) return o.val; | ||
@@ -492,9 +556,2 @@ return def; | ||
WifiLight.prototype.unlock = function () { | ||
this.addToQueue({unlock: true}); | ||
}; | ||
WifiLight.prototype.lock = function () { | ||
this.locked += 1; | ||
}; | ||
WifiLight.prototype.close = function() { | ||
@@ -515,3 +572,5 @@ this.clearQueue(); | ||
WifiLight.prototype.runUpdateTimer = function () { | ||
if (!this.cmds.decodeResponse) return; | ||
if (!this.cmds.decodeResponse) { | ||
return; | ||
} | ||
this.refresh(); | ||
@@ -525,3 +584,5 @@ if (this.config.pollIntervall > 0) { | ||
this.isOnline = val; | ||
if ((this.cmds.g & usedStateNames.online.g) === 0) return; | ||
if ((this.cmds.g & usedStateNames.online.g) === 0) { | ||
return; | ||
} | ||
this.dev.set(usedStateNames.online.n, val); | ||
@@ -531,4 +592,6 @@ devices.update(); | ||
WifiLight.prototype.directRefresh = function(channel) { | ||
if (!this.cmds.statusRequest || this.refreshPaused) return; | ||
WifiLight.prototype.directRefresh = function (channel) { | ||
if (!this.cmds.statusRequest || this.refreshPaused) { | ||
return; | ||
} | ||
this.log('sending refresh...'); | ||
@@ -539,12 +602,14 @@ this.write(channel, this.cmds.statusRequest); | ||
WifiLight.prototype.refresh = function(channel, ctrl) { | ||
if (!this.cmds.statusRequest || this.refreshPaused) return; | ||
this.addToQueue(channel, this.cmds.statusRequest, { ctrl: ctrl|true }); | ||
if (!this.cmds.statusRequest || this.refreshPaused) { | ||
return; | ||
} | ||
this.addToQueue(channel, this.cmds.statusRequest, { ctrl: ctrl === undefined ? true : ctrl }); | ||
}; | ||
WifiLight.prototype.write = function(channel, cmd, cb) { | ||
var varArgs = arguments, buf; | ||
WifiLight.prototype.write = function (channel, cmd, cb) { | ||
let buf; | ||
if (this.cmds.useCheckSum) { | ||
buf = new Buffer(cmd.length + 1); | ||
var sum = 0; | ||
for (var i = 0; i < cmd.length; i++) { | ||
buf = Buffer.alloc(cmd.length + 1); | ||
let sum = 0; | ||
for (let i = 0; i < cmd.length; i++) { | ||
buf[i] = cmd[i]; | ||
@@ -555,11 +620,9 @@ sum += buf[i]; | ||
} else { | ||
buf = new Buffer(cmd); | ||
buf = Buffer.from(cmd); | ||
} | ||
//var s = buf.inspect(); | ||
//const s = buf.inspect(); | ||
//this.log('writing: ' + buf.toString('hex').match(/.{2}/g).join(' ')); | ||
this.log('write: ' + hex(buf)); | ||
this.log(`write: ${hex(buf)}`); | ||
if (!this.isOnline /*&& !this.USE_SOCKET_ONCE*/) { | ||
this.reconnect(function() { | ||
this._write(buf, cb); | ||
}.bind(this), 0); | ||
this.reconnect(() => this._write(buf, cb), 0); | ||
return; | ||
@@ -574,31 +637,31 @@ } | ||
WifiLight.prototype.addToQueue = function (varArgArray) { | ||
var varArgs = arguments, | ||
channel = "", | ||
idx = 0, | ||
cmd = []; | ||
if (!(varArgs[0] instanceof Array)) { | ||
channel = varArgs[0]; | ||
WifiLight.prototype.addToQueue = function (...args) { | ||
let channel = ''; | ||
let idx = 0; | ||
let cmd = []; | ||
if (!(args[0] instanceof Array)) { | ||
channel = args[0]; | ||
idx = 1; | ||
} | ||
if (!(varArgs[idx] instanceof Array)) { | ||
if (!(args[idx] instanceof Array)) { | ||
return; | ||
} | ||
if (varArgs.length > idx+1) { | ||
for (var i = 0, j=idx+1; i < varArgs[idx].length; i++) { | ||
cmd[i] = varArgs[idx][i] < 0 && varArgs[idx][i] !== cmds.VARS.separator && varArgs[idx][i] !== cmds.VARS.sepNoDelay ? varArgs[j++] : varArgs[idx][i]; | ||
let j = idx + 1; | ||
if (args.length > j) { | ||
for (let i = 0; i < args[idx].length; i++) { | ||
cmd[i] = args[idx][i] < 0 && args[idx][i] !== cmds.VARS.separator && args[idx][i] !== cmds.VARS.sepNoDelay ? args[j++] : args[idx][i]; | ||
} | ||
} else { | ||
cmd = varArgs[idx]; | ||
cmd = args[idx]; | ||
} | ||
var opt = undefined; | ||
if (varArgs.length >= j && typeof varArgs[j] == 'object') { | ||
opt = varArgs[j]; | ||
let opt; | ||
if (args.length >= j && typeof args[j] == 'object') { | ||
opt = args[j]; | ||
} | ||
var _cmd = []; | ||
var last = cmd.length - 1; | ||
cmd.forEach(function(c, i) { | ||
var sep = 0; | ||
let _cmd = []; | ||
const last = cmd.length - 1; | ||
cmd.forEach((c, i) => { | ||
let sep = 0; | ||
switch(c) { | ||
@@ -612,15 +675,16 @@ case cmds.VARS.separator: sep = 1; break; | ||
cmd: _cmd, | ||
ctrl: opt && opt.ctrl ? true : false, | ||
ctrl: !!opt?.ctrl, | ||
channel: channel, | ||
delay: sep & 2 ? 0 : opt && opt.delay !== undefined ? opt.delay : this.cmds.delay != undefined ? this.cmds.delay : 10, | ||
delay: sep & 2 ? 0 : opt && opt.delay !== undefined ? opt.delay : this.cmds.delay !== undefined ? this.cmds.delay : 10, | ||
ts: 0, | ||
inProcess: 0, | ||
unlock: 0 | ||
}); | ||
_cmd = []; | ||
} | ||
}.bind(this)); | ||
}); | ||
if (this.queue.length && this.queue[0].inProcess === 1) { | ||
return; | ||
} | ||
this.exec(); | ||
@@ -630,4 +694,4 @@ }; | ||
WifiLight.prototype.exec = function () { | ||
var akt; | ||
while(true) { | ||
let akt; | ||
while (true) { | ||
if (this.queue.length <= 0) { | ||
@@ -637,3 +701,3 @@ return; | ||
akt = this.queue[0]; | ||
if (!(akt.inProcess || (!akt.ctrl && akt.ts != 0 && akt.ts < new Date().getTime()))) { | ||
if (!(akt.inProcess || (!akt.ctrl && akt.ts && akt.ts < new Date().getTime()))) { | ||
break; | ||
@@ -646,13 +710,9 @@ } | ||
} | ||
if (akt.unlock) { | ||
this.unlock(); | ||
if (!akt.cmd) return; | ||
} | ||
this.write (akt.channel, akt.cmd, function() { | ||
this.writeTimeout = setTimeout(this.exec.bind(this), akt.delay); | ||
}.bind(this)); | ||
this.write(akt.channel, akt.cmd, () => | ||
this.writeTimeout = setTimeout(() => this.exec(), akt.delay)); | ||
akt.inProcess = 1; | ||
}; | ||
WifiLight.prototype.on_off = function (channel, state) { | ||
@@ -667,9 +727,20 @@ this.addToQueue(channel, state ? this.cmds.on : this.cmds.off); | ||
} | ||
var co = { r: this.states.red, g: this.states.green, b: this.states.blue, w: this.states.white}; | ||
var dif= { r: rgbw.r - co.r, g: rgbw.g - co.g, b: rgbw.b - co.b}; | ||
dif.w = (rgbw.w != undefined && co.w != undefined) ? rgbw.w - co.w : 0; | ||
var maxSteps = Math.max(Math.abs(dif.r), Math.abs(dif.g), Math.abs(dif.b), Math.abs(dif.w), 1); | ||
const co = { | ||
r: this.states.red, | ||
g: this.states.green, | ||
b: this.states.blue, | ||
w: this.states.white, | ||
}; | ||
const dif= { | ||
r: rgbw.r - co.r, | ||
g: rgbw.g - co.g, | ||
b: rgbw.b - co.b, | ||
}; | ||
maxSteps = Math.min ((transitionTime*100) / this.cmds.delay, maxSteps); | ||
dif.w = rgbw.w !== undefined && co.w !== undefined ? rgbw.w - co.w : 0; | ||
let maxSteps = Math.max(Math.abs(dif.r), Math.abs(dif.g), Math.abs(dif.b), Math.abs(dif.w), 1); | ||
maxSteps = Math.min((transitionTime * 100) / this.cmds.delay, maxSteps); | ||
dif.r /= maxSteps; | ||
@@ -680,11 +751,13 @@ dif.g /= maxSteps; | ||
var steps = maxSteps; | ||
var delay = parseInt(transitionTime*100 / maxSteps); | ||
const steps = maxSteps; | ||
const delay = parseInt(transitionTime * 100 / maxSteps); | ||
for (var i = 0; i<steps; i++) { | ||
for (let i = 0; i < steps; i++) { | ||
co.r += dif.r; | ||
co.g += dif.g; | ||
co.b += dif.b; | ||
if (co.w != undefined) co.w += dif.w; | ||
this.color(channel, roundRGB(co, true), { delay:delay }); | ||
if (co.w !== undefined) { | ||
co.w += dif.w; | ||
} | ||
this.color(channel, Colors.roundRGB(co, true), { delay }); | ||
} | ||
@@ -694,3 +767,3 @@ }; | ||
WifiLight.prototype.color = function (channel, rgbw, opt) { | ||
rgbw.w == undefined ? | ||
rgbw.w === undefined ? | ||
this.addToQueue(channel, this.cmds.rgb, rgbw.r, rgbw.g, rgbw.b, opt) : | ||
@@ -701,8 +774,10 @@ this.addToQueue(channel, this.cmds.rgbw, rgbw.r, rgbw.g, rgbw.b, rgbw.w, opt); | ||
WifiLight.prototype.ct = function (channel, temp, transitionTime) { | ||
var co = ct2rgb(temp); | ||
var hsv = rgb2hsv(co); | ||
//hsv.v = this.get(channel, 'bri').val; | ||
var v = this.get(channel, 'bri').val; | ||
if (v) hsv.v = v; | ||
co = hsv2rgb(hsv); | ||
let co = Colors.ct2rgb(temp); | ||
const hsv = Colors.rgb2hsv(co); | ||
// hsv.v = this.get(channel, 'bri').val; | ||
const v = this.get(channel, 'bri').val; | ||
if (v) { | ||
hsv.v = v; | ||
} | ||
co = Colors.hsv2rgb(hsv); | ||
this.fade(channel, co, transitionTime); | ||
@@ -712,3 +787,3 @@ }; | ||
WifiLight.prototype.getRGBStates = function (channel) { | ||
WifiLight.prototype.getRGBStates = function (/* channel */) { | ||
return { | ||
@@ -718,3 +793,3 @@ r: this.states.red, | ||
b: this.states.blue, | ||
w: this.states.white | ||
w: this.states.white, | ||
}; | ||
@@ -724,6 +799,6 @@ }; | ||
WifiLight.prototype.bri = function (channel, bri, transitionTime) { | ||
var co = this.getRGBStates(channel); | ||
var hsv = rgb2hsv(co); | ||
hsv.v = Math.max (Math.min(bri, 100), 0); | ||
co = hsv2rgb(hsv); | ||
let co = this.getRGBStates(channel); | ||
const hsv = Colors.rgb2hsv(co); | ||
hsv.v = Math.max(Math.min(bri, 100), 0); | ||
co = Colors.hsv2rgb(hsv); | ||
this.fade(channel, co, transitionTime); | ||
@@ -737,6 +812,6 @@ }; | ||
} | ||
var timeout = val >> 0, | ||
cmd = '#00000000;x10'; | ||
let timeout = val >> 0; | ||
let cmd = '#00000000;x10'; | ||
if (typeof val == 'string') { | ||
var ar = val.split(';'); | ||
const ar = val.split(';'); | ||
timeout = parseInt(ar.shift()); | ||
@@ -746,3 +821,3 @@ cmd = ar.join(';'); | ||
if (timeout && timeout > 0) { | ||
this.onTimerObject = setTimeout(this.onStateChange.bind(this), timeout*100, channel, 'command', cmd); | ||
this.onTimerObject = setTimeout(this.onStateChange.bind(this), timeout * 100, channel, 'command', cmd); | ||
} | ||
@@ -752,12 +827,11 @@ }; | ||
WifiLight.prototype.onData = function (data) { | ||
if (adapter.common.loglevel == 'debug') { | ||
adapter.log.debug('raw data length: ' + data.length); | ||
adapter.log.debug('raw data: ' + hex(data)); | ||
if (adapter.common.loglevel === 'debug') { | ||
adapter.log.debug(`raw data length: ${data.length}`); | ||
adapter.log.debug(`raw data: ${hex(data)}`); | ||
} | ||
var newPos = this.dataBuffer.pos + data.length; | ||
const newPos = this.dataBuffer.pos + data.length; | ||
if (newPos > this.dataBuffer.length) { | ||
var b = new Uint8Array(newPos + 200); | ||
//var b = new Buffer(newPos + 200); | ||
for (var i=0; i<this.dataBuffer.pos; i++) { | ||
const b = new Uint8Array(newPos + 200); | ||
//const b = new Buffer(newPos + 200); | ||
for (let i=0; i<this.dataBuffer.pos; i++) { | ||
b [i] = this.dataBuffer[i]; | ||
@@ -772,11 +846,12 @@ } | ||
while (this.dataBuffer.pos >= this.cmds.responseLen) | ||
{ | ||
var states = this.cmds.decodeResponse(this.dataBuffer); | ||
this.log('onData: raw: ' + hex(this.dataBuffer, this.cmds.responseLen)); | ||
this.dataBuffer.copyWithin(0, this.cmds.responseLen, this.dataBuffer.pos); | ||
this.dataBuffer.pos -= this.cmds.responseLen; | ||
if (!states) break; | ||
while (this.dataBuffer.pos >= this.cmds.responseLen || this.dataBuffer.pos >= this.cmds.responseLen2) { | ||
const [lengthRead, states] = this.cmds.decodeResponse(this.dataBuffer); | ||
this.log(`onData: raw: ${hex(this.dataBuffer, lengthRead)}`); | ||
this.dataBuffer.copyWithin(0, lengthRead, this.dataBuffer.pos); | ||
this.dataBuffer.pos -= lengthRead; | ||
if (!states) { | ||
break; | ||
} | ||
this.states = states; | ||
this.log('onData: ' + JSON.stringify(this.states)); | ||
this.log(`onData: ${JSON.stringify(this.states)}`); | ||
if (this.states) { | ||
@@ -792,4 +867,6 @@ //set(usedStateNames.status.n, this.states.power); | ||
this.dev.set(usedStateNames.white.n, this.states.white); | ||
var rgb = '#' + this.states.red.toHex() + this.states.green.toHex() + this.states.blue.toHex(); | ||
if (this.states.white != undefined) rgb += this.states.white.toHex(); | ||
let rgb = `#${this.states.red.toHex()}${this.states.green.toHex()}${this.states.blue.toHex()}`; | ||
if (this.states.white !== undefined) { | ||
rgb += this.states.white.toHex(); | ||
} | ||
this.dev.set(usedStateNames.rgb.n, rgb); | ||
@@ -805,5 +882,7 @@ devices.update(); | ||
var MiLight = function MiLight (config, zone, cb) { | ||
const MiLight = function MiLight (config, zone /* , cb */) { | ||
WifiLight.call(this, config); | ||
if (!this.cmds) return; | ||
if (!this.cmds) { | ||
return; | ||
} | ||
this.zone = zone; | ||
@@ -821,19 +900,17 @@ this.cmds = clone(this.cmds); | ||
MiLight.prototype._write = function writeUdp (data, cb) { | ||
var self = this; | ||
if (!this.client) { | ||
var dgram = require('dgram'); | ||
self.client = dgram.createSocket('udp4'); | ||
self.client.on("listening", function (error) { | ||
if (error) return cb && cb(error); | ||
if (self.config.ip === '255.255.255.255') { | ||
self.client.setBroadcast(true); | ||
const dgram = require('node:dgram'); | ||
this.client = dgram.createSocket('udp4'); | ||
this.client.on('listening', (error) => { | ||
if (error) { | ||
return cb && cb(error); | ||
} | ||
if (this.config.ip === '255.255.255.255') { | ||
this.client.setBroadcast(true); | ||
} | ||
}); | ||
self.client.on('message', function (data, rinfo) { | ||
}); | ||
this.client.on('error', function (error) { | ||
}); | ||
this.client.on('close', function (error) { | ||
self.client = null; | ||
this.client.on('message', (/* data, rinfo */) => {}); | ||
this.client.on('error', (/* error */) => {}); | ||
this.client.on('close', (/* error */) => { | ||
this.client = null; | ||
adapter.log.debug('udp socked closed'); | ||
@@ -843,5 +920,7 @@ }); | ||
self.client.send(data, 0, data.length, self.config.port, self.config.ip, function(error, bytes) { | ||
self.writeTimer.set(function() { | ||
if (self && self.client) self.client.close(); | ||
this.client.send(data, 0, data.length, this.config.port, this.config.ip, (/* error, bytes */) => { | ||
this.writeTimer.set(() => { | ||
if (this && this.client) { | ||
this.client.close(); | ||
} | ||
}, 2000); | ||
@@ -852,8 +931,7 @@ cb && cb(); | ||
MiLight.prototype.bri = function (channel, bri, transitionTime) { | ||
MiLight.prototype.bri = function (channel, bri /* , transitionTime */) { | ||
this.addToQueue(channel, this.cmds._bri(bri)); | ||
}; | ||
MiLight.prototype.color = function (channel, rgbw, opt) { | ||
MiLight.prototype.color = function (channel, rgbw /* , opt */) { | ||
if (rgbw.w !== undefined) { | ||
@@ -863,3 +941,3 @@ this.addToQueue(channel, this.cmds._white((rgbw.w * 100 / 255) >> 0)); | ||
} | ||
var hsv = rgb2hsv(rgbw); | ||
const hsv = Colors.rgb2hsv(rgbw); | ||
if (hsv.h === 0 && hsv.v === 0) { | ||
@@ -869,3 +947,3 @@ this.on_off(channel, false); | ||
} | ||
var color = (256 + 176 - Math.floor(Number(hsv.h) / 360.0 * 255.0)) % 256; | ||
const color = (256 + 176 - Math.floor(Number(hsv.h) / 360.0 * 255.0)) % 256; | ||
this.addToQueue(channel, this.cmds.on); | ||
@@ -876,9 +954,9 @@ this.addToQueue(channel, this.cmds._color(color)); | ||
MiLight.prototype.pair = function pair() { | ||
for (var i=0; i<3; i++) { | ||
MiLight.prototype.pair = function (channel) { | ||
for (let i = 0; i < 3; i++) { | ||
this.addToQueue(channel, this.pair, { delay: 1000 }); | ||
} | ||
}; | ||
MiLight.prototype.unPair = function pair() { | ||
for (var i=0; i<15; i++) { | ||
MiLight.prototype.unPair = function (channel) { | ||
for (let i = 0; i < 15; i++) { | ||
this.addToQueue(channel, this.unPair, { delay: 200 }); | ||
@@ -890,3 +968,3 @@ } | ||
switch (stateName) { | ||
case 'disco': | ||
case 'disco': { | ||
val = val >> 0; | ||
@@ -897,11 +975,13 @@ if (val === 0) { | ||
} | ||
var bri = this.getval(channel, 'bri'); | ||
var cmd = this.cmds._white(10).cc(this.cmds.on); | ||
// const bri = this.getval(channel, 'bri'); | ||
let cmd = this.cmds._white(10).cc(this.cmds.on); | ||
while (val--) { | ||
cmd = cmd.cc(this.cmds.discoMode); | ||
} | ||
this.addToQueue(channel, cmd/*, {delay: 50}*/ ); | ||
this.addToQueue(channel, cmd /*, {delay: 50}*/); | ||
break; | ||
} | ||
default: | ||
WifiLight.prototype.onStateChange.call(this, channel, stateName, val); | ||
break; | ||
} | ||
@@ -912,11 +992,11 @@ }; | ||
adapter.getDevices(function(err, res) { | ||
if (err || !res || res.length <= 0) return cb && cb(); | ||
var reIp = /[^0-9]/g; | ||
var toDelete = []; | ||
if (err || !res || res.length <= 0) { | ||
return cb && cb(); | ||
} | ||
const reIp = /[^0-9]/g; | ||
const toDelete = []; | ||
res.forEach(function(obj) { | ||
var ar = obj._id.split('.'); | ||
var ip = ar[2].replace(reIp, '.'); | ||
var found = adapter.config.devices.find(function(v) { //xxxx | ||
return v.ip === ip; | ||
}); | ||
const ar = obj._id.split('.'); | ||
const ip = ar[2].replace(reIp, '.'); | ||
const found = adapter.config.devices.find(v => v.ip === ip); // xxxx | ||
if (!found) { | ||
@@ -926,6 +1006,3 @@ toDelete.push(obj._id); | ||
}); | ||
toDelete.forEachCallback(function(next, id) { | ||
dcs.del(id, next); | ||
}, | ||
cb); | ||
toDelete.forEachCallback((next, id) => dcs.del(id, next), cb); | ||
}); | ||
@@ -937,16 +1014,20 @@ } | ||
function normalizeConfig (config) { | ||
let changed = false; | ||
const types = []; | ||
config.devices.forEach(d => { | ||
const old = Object.assign({}, d); | ||
const dev = fromDeviceName(d.name); | ||
var changed = false; | ||
var types = []; | ||
config.devices.forEach(function (d, i) { | ||
var c, old = Object.assign({}, d); | ||
var dev = fromDeviceName(d.name); | ||
if (d.type === undefined) d.type = dev ? dev.type : ''; | ||
if (!(c = cmds[d.type])) { | ||
var err = 'config.device.type "' + d.type + '" (' + d.name + ') is not a known device type. Skipping this device!'; | ||
if (d.type === undefined) { | ||
d.type = dev ? dev.type : ''; | ||
} | ||
const c = cmds[d.type]; | ||
if (!c) { | ||
let err = `config.device.type "${d.type}" (${d.name}) is not a known device type. Skipping this device!`; | ||
if (!types.length) Object.keys(cmds).forEach(function(n) { | ||
if (typeof cmds[n] === 'object' && cmds[n].on) types.push(n); | ||
if (typeof cmds[n] === 'object' && cmds[n].on) { | ||
types.push(n); | ||
} | ||
}); | ||
err += '\nKnown types are: ' + types.join(', '); | ||
err += `\nKnown types are: ${types.join(', ')}`; | ||
adapter.log.error(err); | ||
@@ -956,5 +1037,9 @@ return; | ||
if (d.pollIntervall === undefined) d.pollIntervall = 30; | ||
d.pollIntervall = parseInt(d.pollIntervall) | 0; | ||
if (d.pollIntervall && d.pollIntervall < 5) d.pollIntervall = 5; | ||
if (d.pollIntervall === undefined) { | ||
d.pollIntervall = 30; | ||
} | ||
d.pollIntervall = parseInt(d.pollIntervall, 10) || 0; | ||
if (d.pollIntervall && d.pollIntervall < 5) { | ||
d.pollIntervall = 5; | ||
} | ||
@@ -967,5 +1052,3 @@ d.port = parseInt(d.port) || (c && c.port ? c.port : dev && dev.port ? dev.port : 5577); | ||
if (changed) { | ||
soef.changeAdapterConfig (adapter, function(conf) { | ||
conf.devices = config.devices; | ||
}); | ||
soef.changeAdapterConfig (adapter, conf => conf.devices = config.devices); | ||
} | ||
@@ -975,22 +1058,21 @@ } | ||
function main() { | ||
if (!adapter.config.devices) return; | ||
checkDeletedDevices(function(err) { | ||
}); | ||
if (!adapter.config.devices) { | ||
return; | ||
} | ||
checkDeletedDevices((/* err */) => {}); | ||
normalizeConfig(adapter.config); | ||
for (var i=0; i<adapter.config.devices.length; i++) { | ||
for (let i = 0; i < adapter.config.devices.length; i++) { | ||
if (adapter.config.devices[i].type === 'MiLight') { | ||
for (var zone=0; zone<=4; zone++) { | ||
new MiLight(adapter.config.devices[i], zone).run(function() { | ||
}); | ||
for (let zone = 0; zone <= 4; zone++) { | ||
new MiLight(adapter.config.devices[i], zone) | ||
.run(() => {}); | ||
} | ||
} else | ||
new WifiLight(adapter.config.devices[i]).run(function() { | ||
}); | ||
new WifiLight(adapter.config.devices[i]) | ||
.run(() => {}); | ||
} | ||
devices.update(); | ||
adapter.subscribeStates('*'); | ||
adapter.subscribeObjects('*'); | ||
} | ||
{ | ||
"name": "iobroker.wifilight", | ||
"version": "1.2.2", | ||
"version": "1.3.0", | ||
"description": "WiFi Light Adapter", | ||
@@ -34,3 +34,3 @@ "author": { | ||
"netmask": "^2.0.2", | ||
"@iobroker/adapter-core": "^3.0.6", | ||
"@iobroker/adapter-core": "^3.1.6", | ||
"sprintf-js": "^1.1.3", | ||
@@ -40,29 +40,35 @@ "array-ext": "^0.1.5" | ||
"devDependencies": { | ||
"@alcalzone/release-script": "^3.7.0", | ||
"@alcalzone/release-script-plugin-iobroker": "^3.7.0", | ||
"@alcalzone/release-script": "^3.8.0", | ||
"@alcalzone/release-script-plugin-iobroker": "^3.7.2", | ||
"@alcalzone/release-script-plugin-license": "^3.7.0", | ||
"@alcalzone/release-script-plugin-manual-review": "^3.7.0", | ||
"@iobroker/adapter-dev": "^1.3.0", | ||
"@iobroker/testing": "^4.1.1", | ||
"@iobroker/testing": "^4.1.3", | ||
"@tsconfig/node14": "^14.1.2", | ||
"@types/chai": "^4.3.5", | ||
"@types/chai": "^4.3.17", | ||
"@types/chai-as-promised": "^7.1.8", | ||
"@types/mocha": "^10.0.6", | ||
"@types/node": "^20.12.2", | ||
"@types/mocha": "^10.0.7", | ||
"@types/node": "^22.2.0", | ||
"@types/proxyquire": "^1.3.31", | ||
"@types/sinon": "^17.0.3", | ||
"@types/sinon-chai": "^3.2.12", | ||
"chai": "^4.4.1", | ||
"chai-as-promised": "^7.1.1", | ||
"chai": "^4.5.0", | ||
"chai-as-promised": "^7.1.2", | ||
"eslint": "^8.57.0", | ||
"eslint-config-prettier": "^9.1.0", | ||
"eslint-plugin-prettier": "^5.1.3", | ||
"mocha": "^10.4.0", | ||
"prettier": "^3.2.5", | ||
"eslint-plugin-prettier": "^5.2.1", | ||
"mocha": "^10.7.3", | ||
"prettier": "^3.3.3", | ||
"proxyquire": "^2.1.3", | ||
"sinon": "^17.0.1", | ||
"sinon": "^18.0.0", | ||
"sinon-chai": "^3.7.0", | ||
"typescript": "~5.4.3" | ||
"typescript": "~5.5.4" | ||
}, | ||
"main": "main.js", | ||
"files": [ | ||
"main.js", | ||
"admin/", | ||
"lib/", | ||
"LICENSE" | ||
], | ||
"scripts": { | ||
@@ -69,0 +75,0 @@ "test:js": "mocha --config test/mocharc.custom.json \"{!(node_modules|test)/**/*.test.js,*.test.js,test/**/test!(PackageFiles|Startup).js}\"", |
@@ -23,3 +23,3 @@ ![Logo](admin/wifilight.png) | ||
## Initial Creation | ||
This adapter was initialy created by @soef at https://github.com/soef/ioBroker.wifilight but not maintained any more, so we moved it to iobroker-community so that bugs could be fixed. thanks @soef for his work. | ||
This adapter was initially created by @soef at https://github.com/soef/ioBroker.wifilight but not maintained anymore, so we moved it to iobroker-community so that bugs could be fixed. Thanks @soef for his work. | ||
@@ -30,4 +30,4 @@ ### How to use the command state: | ||
+ You can also assign a value by = | ||
+ Range of colors: ```0..255``` | ||
+ Range of bri: ``0..100`` | ||
+ Range of colors: `0..255` | ||
+ Range of bri: `0..100` | ||
@@ -44,4 +44,4 @@ Some Examples: | ||
``` | ||
To change the color you do not have to use all three vallues. | ||
For example, ``` red = 0 ```, blue and green will stay unchanged. | ||
To change the color, you do not have to use all three values. | ||
For example, `red = 0`, blue and green will stay unchanged. | ||
@@ -52,17 +52,2 @@ ### r, g, b, w States: | ||
## Installation | ||
Use the Adapter panel in iobroker to add an instance. | ||
If not exists execute the following command in the iobroker root directory (e.g. in /opt/iobroker). | ||
``` | ||
npm install iobroker.wifilight | ||
``` | ||
### Error fixing | ||
In case of not working try to install the soef npm package | ||
``` | ||
cd /opt/iobroker/node_modules/iobroker.wifilight | ||
sudo npm install soef | ||
``` | ||
## Changelog | ||
@@ -73,2 +58,6 @@ <!-- | ||
--> | ||
### 1.3.0 (2024-08-12) | ||
* (p-kehling) Added ignorance of acknowledgement messages for on/off commands | ||
* (bluefox) refactoring | ||
### 1.2.2 (2024-04-15) | ||
@@ -85,6 +74,6 @@ * (mcm1957) Fix js-controller dependency | ||
### 1.1.4 (2022-06-17) | ||
* (Apollon77) Prevent crash case reported by sentry | ||
* (Apollon77) Prevent a crash case reported by sentry | ||
### 1.1.3 (2022-04-27) | ||
* (Apollon77) Prevent crash case reported by sentry | ||
* (Apollon77) Prevent a crash case reported by sentry | ||
@@ -91,0 +80,0 @@ ### 1.1.2 (2022-04-19) |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
5
2
141434
21
3164
110