beetle-ii / lumi Goto Github PK
View Code? Open in Web Editor NEWMQTT агент для шлюза Xiaomi DGNWG05LM
License: MIT License
MQTT агент для шлюза Xiaomi DGNWG05LM
License: MIT License
Hello,
When music is playing it's impossible to stop it with lumi/audio/play/set "STOP"
Thanks for your great work!
Regards,
Miguel
OpenWrt for Lumi gateway will migrate to new drivers of LED lights soon.
https://github.com/devbis/openwrt/commit/1a3adc95ccee91cad8766e413cc038cd5fb1b778
The new device paths will be:
/sys/class/leds/red/brightness
/sys/class/leds/green/brightness
/sys/class/leds/blue/brightness
And range 0-255 instead of 0-100.
Do you plan to add support for this schema in your application?
Proposal: you can check for the new paths and fallback to the old ones if they are missing
Я добавил поддержку множественных нажатий кнопки на устройстве, автоматическое добавление кнопки в Home Assistant
Из обнаруженных проблем:
`const fs = require('fs');
const os = require('os');
const cp = require('child_process');
const crypto = require('crypto');
const https = require('https');
const urlParse = require('url').parse;
const googleTTS = require('google-tts-api');
module.exports = {
getState,
getIlluminance,
getLamp,
setLamp,
getPlay,
setPlay,
getVolume,
setVolume,
setSay,
setAlarm
}
const common = require('./common');
const mqtt = require('./mqtt_client');
let clicks = 1;
let threshold = 300;
let t0 = new Date();
let t1 = new Date();
let timerId = 0;
//////////////////
let device = {
identifiers: ['xiaomi_gateway' + common.mac],
name: 'Xiaomi_Gateway' + common.mac,
sw_version: '1.0',
model: 'Xiaomi Gateway',
manufacturer: 'Xiaomi'
}
let state = {
state_topic: common.config.mqtt_topic + '/state',
value: 'online'
}
// Начальные параметры лампы
let lamp = {
state_topic: common.config.mqtt_topic + '/light',
value: {
color: {
r: 30,
g: 30,
b: 30
},
brightness: 0,
state: 'OFF'
},
real_color: {
r: 0,
g: 0,
b: 0
},
path: {
r: '/sys/class/leds/red/brightness',
g: '/sys/class/leds/green/brightness',
b: '/sys/class/leds/blue/brightness'
},
config_topic: 'homeassistant/light/lumi' + common.mac + '_light/config',
homeassistant: {
name: 'Lumi Light',
uniq_id: 'lumi' + common.mac + '_light',
schema: 'json',
rgb: true,
brightness: true,
stat_t: common.config.mqtt_topic + '/light',
cmd_t: common.config.mqtt_topic + '/light/set',
device: device
}
}
let illuminance = {
state_topic: common.config.mqtt_topic + '/illuminance',
value: 0,
config_topic: 'homeassistant/sensor/lumi' + common.mac + '_illuminance/config',
homeassistant: {
name: 'Lumi Illuminance',
uniq_id: 'lumi' + common.mac + '_illuminance',
dev_cla: 'illuminance',
unit_of_meas: 'lx',
stat_t: common.config.mqtt_topic + '/illuminance',
device: device
}
}
let button = {
state_topic: common.config.mqtt_topic + '/button/action',
value: 0,
device: '/dev/input/event0',
options: {
flags: 'r',
encoding: null,
fd: null,
autoClose: true
}
}
let audio = {
play: {
state_topic: common.config.mqtt_topic + '/audio/play',
value: {
url: 'STOP',
name: ''
}
},
volume: {
state_topic: common.config.mqtt_topic + '/audio/volume',
value: 0
}
}
let timer_alarm;
///////////////
// Публикуем в MQTT данные для кнопки в HA AutoDiscovery
function publishButtonCfg() {
if (common.config.homeassistant) {
let button_cfg = {
config_topic: 'homeassistant/device_automation/lumi' + common.mac + '_button/action_single/config',
homeassistant: {
automation_type: 'trigger',
device: device,
payload: 'single',
subtype: 'single',
topic: common.config.mqtt_topic + '/button/action',
type: 'action'
}
}
mqtt.publish_homeassistant(button_cfg);
button_cfg = {
config_topic: 'homeassistant/device_automation/lumi' + common.mac + '_button/action_double/config',
homeassistant: {
automation_type: 'trigger',
device: device,
payload: 'double',
subtype: 'double',
topic: common.config.mqtt_topic + '/button/action',
type: 'action'
}
}
mqtt.publish_homeassistant(button_cfg);
button_cfg = {
config_topic: 'homeassistant/device_automation/lumi' + common.mac + '_button/action_triple/config',
homeassistant: {
automation_type: 'trigger',
device: device,
payload: 'triple',
subtype: 'triple',
topic: common.config.mqtt_topic + '/button/action',
type: 'action'
}
}
mqtt.publish_homeassistant(button_cfg);
button_cfg = {
config_topic: 'homeassistant/device_automation/lumi' + common.mac + '_button/action_quadruple/config',
homeassistant: {
automation_type: 'trigger',
device: device,
payload: 'quadruple',
subtype: 'quadruple',
topic: common.config.mqtt_topic + '/button/action',
type: 'action'
}
}
mqtt.publish_homeassistant(button_cfg);
button_cfg = {
config_topic: 'homeassistant/device_automation/lumi' + common.mac + '_button/action_many/config',
homeassistant: {
automation_type: 'trigger',
device: device,
payload: 'many',
subtype: 'many',
topic: common.config.mqtt_topic + '/button/action',
type: 'action'
}
}
mqtt.publish_homeassistant(button_cfg);
button_cfg = {
config_topic: 'homeassistant/sensor/lumi' + common.mac + '_button/action/config',
homeassistant: {
device: device,
icon: 'mdi:gesture-double-tap',
json_attributes_topic: common.config.mqtt_topic + '/button/action',
name: 'Lumi action',
state_topic: common.config.mqtt_topic + '/button/action',
unique_id: 'button'+common.mac+"_action"
//value_template: '{{ value_json.action}}'
}
}
mqtt.publish_homeassistant(button_cfg);
}
}
// Отправляем данные о статусе шлюза
function getState() {
mqtt.publish(state);
getIlluminance();
getLamp();
getPlay();
getVolume();
if (common.config.homeassistant) {
mqtt.publish_homeassistant(lamp);
mqtt.publish_homeassistant(illuminance);
publishButtonCfg();
}
}
// Отправляем данные датчика освещенности
function getIlluminance(treshhold = 0) {
let ill_prev = illuminance.value;
illuminance.value = parseInt(fs.readFileSync('/sys/bus/iio/devices/iio:device0/in_voltage5_raw'));
if (Math.abs(illuminance.value - ill_prev) > treshhold) {
mqtt.publish(illuminance);
}
}
// Получаем текущее состояние лампы
function getLamp() {
lamp.real_color.r = parseInt(fs.readFileSync(lamp.path.r).toString());
lamp.real_color.g = parseInt(fs.readFileSync(lamp.path.g).toString());
lamp.real_color.b = parseInt(fs.readFileSync(lamp.path.b).toString());
lamp.value.brightness = Math.round(0.2126 * lamp.real_color.r + 0.7152 * lamp.real_color.g + 0.0722 * lamp.real_color.b);
if (lamp.real_color.r + lamp.real_color.g + lamp.real_color.b > 0) {
lamp.value.state = 'ON';
mqtt.publish(lamp);
} else {
lamp.value.state = 'OFF';
// Публикуем только состояние, чтобы не потерять последний заданный цвет
mqtt.publish({state_topic: lamp.state_topic, value: {state: lamp.value.state}});
}
}
// Меняем состояние лампы в зависимости от полученных данных
function setLamp(message) {
try {
let state;
let msg = JSON.parse(message);
if (msg.state) {
state = msg.state.toUpperCase();
} else {
state = msg.toUpperCase();
}
if (state === 'OFF') {
fs.writeFileSync(lamp.path.r, 0);
fs.writeFileSync(lamp.path.g, 0);
fs.writeFileSync(lamp.path.b, 0);
}
if (state === 'ON') {
if (msg.color) {
lamp.value.color.r = msg.color.r;
lamp.value.color.g = msg.color.g;
lamp.value.color.b = msg.color.b;
}
if (msg.brightness) {
lamp.value.brightness = Math.round(0.2126 * lamp.value.color.r + 0.7152 * lamp.value.color.g + 0.0722 * lamp.value.color.b);
let k = (msg.brightness / lamp.value.brightness);
lamp.value.color.r = Math.round(k * lamp.value.color.r);
lamp.value.color.g = Math.round(k * lamp.value.color.g);
lamp.value.color.b = Math.round(k * lamp.value.color.b);
}
fs.writeFileSync(lamp.path.r, lamp.value.color.r);
fs.writeFileSync(lamp.path.g, lamp.value.color.g);
fs.writeFileSync(lamp.path.b, lamp.value.color.b);
}
} catch (e) {
common.myLog(e, common.colors.red);
}
getLamp();
}
// Получаем состояние проигрывателя
function getPlay() {
audio.play.value.name = cp.execSync("mpc current --format '%name% - %artist% - %title%'").toString().replace(/ - -/g, ' -').replace('\n', '');
if (audio.play.value.name.length < 5) {
audio.play.value.name = audio.play.value.url;
}
mqtt.publish(audio.play);
}
// Включаем/выключаем проигрыватель
function setPlay(message) {
try {
let msg = JSON.parse(message);
if (msg.volume) {
setVolume(msg.volume);
} else {
setVolume(msg);
}
let url;
if (msg.url) {
url = msg.url.toLowerCase();
} else {
url = msg.toLowerCase();
}
if (url.length < 5) {
audio.play.value.url = 'STOP';
cp.execSync('mpc stop');
} else {
audio.play.value.url = url;
if (url.substring(0, 4) == 'http') {
cp.execSync('mpc clear && mpc add ' + audio.play.value.url + ' && mpc play');
} else {
cp.execSync('mpg123 ' + url);
}
}
setTimeout(() => {
getPlay();
}, 1 * 1000);
} catch (e) {
common.myLog(e, common.colors.red);
sayText('Произошла ошибка!', 'ru');
}
}
// Получаем состояние о громкости
function getVolume() {
audio.volume.value = cp.execSync("amixer get Master | awk '$0~/%/{print $4}' | tr -d '[]%'").toString().split(os.EOL)[0];
mqtt.publish(audio.volume);
return audio.volume.value;
}
// Устанавливаем громкость
function setVolume(volume) {
cp.execSync('amixer sset Master ' + volume + '%');
getVolume();
}
// Произнести указанный текст
function setSay(message) {
try {
let msg = JSON.parse(message);
/*
try {
if (msg.toLowerCase() === 'stop') {
cp.execSync('killall mpg123');
return;
}
} finally {
}
*/
if (msg.volume) {
setVolume(msg.volume);
}
let lang = 'ru';
if (msg.lang) {
lang = msg.lang;
}
let text = 'Ошибка';
if (msg.text) {
text = msg.text;
} else {
text = msg;
}
if (audio.play.value.url !== 'STOP') {
cp.execSync('mpc pause');
}
let vol = getVolume();
if (msg.volume) {
setVolume(msg.volume);
}
sayText(text, lang);
if (msg.volume) {
setVolume(vol);
}
if (audio.play.value.url !== 'STOP') {
cp.execSync('mpc play');
}
} catch (e) {
common.myLog(e, common.colors.red);
sayText('Произошла ошибка!', 'ru');
}
}
// Устанавливаем громкость
function setAlarm(message) {
try {
let msg = JSON.parse(message);
if (msg.state) {
state = msg.state.toUpperCase();
} else {
state = msg.toUpperCase();
}
if (state === 'OFF') {
if (typeof timer_alarm !== 'undefined') {
clearTimeout(timer_alarm);
setLamp('{"state":"OFF"}');
}
}
if (state === 'ON') {
if (msg.color) {
setLamp(message);
}
// Запускаем таймер мигания лампой
timer_alarm = setTimeout(function tick() {
if (lamp.value.state === 'ON') {
setLamp('{"state":"OFF"}');
} else {
setLamp('{"state":"ON"}');
}
timer_alarm = setTimeout(tick, 2000);
}, 2000);
}
} catch (e) {
common.myLog(e, common.colors.red);
}
}
function sayText(text, lang) {
if (text.length > 3) {
let md5sum = crypto.createHash('md5');
md5sum.update(text);
const file = '/tmp/' + md5sum.digest('hex');
if (fs.existsSync(file)) {
cp.execSync('mpg123 ' + file);
} else {
googleTTS(text, lang)
.then((url) => {
return downloadFile(url, file);
})
.then(() => {
//console.log('Download success');
cp.execSync('mpg123 ' + file);
//fs.unlinkSync(file);
})
.catch((err) => {
console.error(err.stack);
});
}
}
}
function downloadFile(url, dest) {
return new Promise((resolve, reject) => {
const info = urlParse(url);
const httpClient = info.protocol === 'https:' ? https : http;
const options = {
host: info.host,
path: info.path,
headers: {
'user-agent': 'WHAT_EVER',
},
};
httpClient
.get(options, (res) => {
// check status code
if (res.statusCode !== 200) {
const msg = `request to ${url} failed, status code = ${res.statusCode} (${res.statusMessage})`;
reject(new Error(msg));
return;
}
const file = fs.createWriteStream(dest);
file.on('finish', function () {
// close() is async, call resolve after close completes.
file.close(resolve);
});
file.on('error', function (err) {
// Delete the file async. (But we don't check the result)
fs.unlink(dest);
reject(err);
});
res.pipe(file);
})
.on('error', reject)
.end();
});
}
function publishMQTTbutton() {
console.log('',button.value,'click detected');
mqtt.publish(button);
button.value= '';
mqtt.publish(button);
}
// Получаем данные о кнопке
fd = fs.createReadStream(button.device, button.options);
fd.on('data', function (buf) {
let i, j, chunk = 16;
for (i = 0, j = buf.length; i < j; i += chunk) {
let event = {
tssec: buf.readUInt32LE(i),
tsusec: buf.readUInt32LE(i + 4),
type: buf.readUInt16LE(i + 8),
code: buf.readUInt16LE(i + 10),
value: buf.readUInt32LE(i + 12)
};
if (event.type == 1 && event.code == 256) {
t1 = new Date();
if (event.value==1) {
if (t1 - t0 < threshold) {
clearTimeout(timerId);
clicks++;
t0 = t1;
timerId = setTimeout (publishMQTTbutton, threshold);
} else {
clearTimeout(timerId);
clicks= 1;
t0 = t1;
timerId = setTimeout (publishMQTTbutton, threshold);
}
switch (clicks) {
case 1:
button.value = 'single';
break;
case 2:
button.value = 'double';
break;
case 3:
button.value = 'triple';
break;
case 4:
button.value = 'quadruple';
break;
default:
button.value = 'many';
}
}
}
}
});
fd.on('error', function (e) {
console.error(e);
});`
Обнаружил неприятные моменты при включении BLE:
UPD: После отключения БТ спам пошел от датчика освещенности
I wanted to check the code, but there is no license in here. I see you use MIT license on nginx-boilerplate
repo, is it fine if I create a PR with MIT license in this project?
Добавьте, пожалуйста, поддержку сторонней прошивки датчиков LYWSD03MMC и MHO-C401 https://github.com/pvvx/ATC_MiThermometer
Can somebody help mi with this problem?
I've got >ERR_INVALID_ARG_TYPE with alarm/light/say, but the lumi/audio/play command work correctly.
Sat Oct 30 18:17:04 2021 daemon.info node[4149]: �[33m Получен topic= lumi/light/set �[0m
Sat Oct 30 18:17:04 2021 daemon.info node[4149]: �[37m message = {"state":"ON", "color":{"r":50,"g":50,"b":50}} �[0m
Sat Oct 30 18:17:04 2021 daemon.info node[4149]: �[37m setLamp. lamp={"state":"ON", "color":{"r":50,"g":50,"b":50}} �[0m
Sat Oct 30 18:17:04 2021 daemon.info node[4149]: �[31m TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received type number (50)
Sat Oct 30 18:17:04 2021 daemon.info node[4149]: at Object.writeFileSync (fs.js:1521:5)
Sat Oct 30 18:17:04 2021 daemon.info node[4149]: at Object.setLamp (/opt/lumi/gateway.js:266:16)
Sat Oct 30 18:17:04 2021 daemon.info node[4149]: at MqttClient.<anonymous> (/opt/lumi/mqtt_client.js:28:25)
Sat Oct 30 18:17:04 2021 daemon.info node[4149]: at MqttClient.emit (events.js:400:28)
Sat Oct 30 18:17:04 2021 daemon.info node[4149]: at MqttClient._handlePublish (/opt/lumi/node_modules/mqtt/lib/client.js:1277:12)
Sat Oct 30 18:17:04 2021 daemon.info node[4149]: at MqttClient._handlePacket (/opt/lumi/node_modules/mqtt/lib/client.js:410:12)
Sat Oct 30 18:17:04 2021 daemon.info node[4149]: at work (/opt/lumi/node_modules/mqtt/lib/client.js:321:12)
Sat Oct 30 18:17:04 2021 daemon.info node[4149]: at Writable.writable._write (/opt/lumi/node_modules/mqtt/lib/client.js:335:5)
Sat Oct 30 18:17:04 2021 daemon.info node[4149]: at doWrite (/opt/lumi/node_modules/readable-stream/lib/_stream_writable.js:409:139)
Sat Oct 30 18:17:04 2021 daemon.info node[4149]: at writeOrBuffer (/opt/lumi/node_modules/readable-stream/lib/_stream_writable.js:398:5) {
Sat Oct 30 18:17:04 2021 daemon.info node[4149]: code: 'ERR_INVALID_ARG_TYPE'
Sat Oct 30 18:17:04 2021 daemon.info node[4149]: } �[0m
Для датчика почвы Xiaomi Flower care не отображается влажность и фертильность почвы из-за неверного формата конфигурационного сообщения.
Такое сообщение приходит для влажности:
{"name":"80eaca895950_moisture","unique_id":"80eaca895950_moisture","device_class":"moisture","state_topic":"lumi/80eaca895950","value_template":"{{ value_json.moisture }}","device":{"name":"Flower care","identifiers":["Flower care"],"sw_version":"1.0","model":"Xiaomi Gateway","manufacturer":"Xiaomi"}}
Из него необходимо убрать "device_class":"moisture" (полностью, менять на другойо нет необходимости)
а так же для красоты можно добавить: "icon":"mdi:water-percent"
Для фертильности почвы приходит такое сообщение:
{"name":"80eaca895950_fertility","unique_id":"80eaca895950_fertility","device_class":"fertility","state_topic":"lumi/80eaca895950","value_template":"{{ value_json.fertility }}","device":{"name":"Flower care","identifiers":["Flower care"],"sw_version":"1.0","model":"Xiaomi Gateway","manufacturer":"Xiaomi"}}
Из него необходимо убрать "device_class":"fertility", так же можно добавить:
"icon": "mdi:flower", "unit_of_measurement": "µS/cm"
Заранне спасибо
Приходят такие ворнинги. В описании ничего конкретного нет, но я методом тыка проверил. Если выключить lumi, то они пропадают, если включить, то тут же появляются снова.
Как выяснилось, у бесплатного Goggle TTS движка есть ограничение на 200 проговариваемых символов. Надо сделать проверку на превышение. Или попробовать разбивать большой текст на несколько мелких отрезков
В коде вижу возможную ошибку url = msg.url.toLowerCase();
Весь текст приводим в нижний регистр. А файлы могут быть с заглавными буквами.
А вот тут скорее всего вылезают пролемы с пробелами в именах файлов cp.execSync('mpg123 ' + url);
When I run node /opt/lumi/lumi.js process I get the following error
`internal/modules/cjs/loader.js:1131
return process.dlopen(module, path.toNamespacedPath(filename));
^
Error: Error relocating /opt/lumi/node_modules/@abandonware/bluetooth-hci-socket/lib/binding/bluetooth_hci_socket.node: _ZN2v816FunctionTemplate3NewEPNS_7IsolateEPFvRKNS_20FunctionCallbackInfoINS_5ValueEEEENS_5LocalIS4_EENSA_INS_9SignatureEEEiNS_19ConstructorBehaviorENS_14SideEffectTypeE: symbol not found
at Object.Module._extensions..node (internal/modules/cjs/loader.js:1131:18)
at Module.load (internal/modules/cjs/loader.js:937:32)
at Function.Module._load (internal/modules/cjs/loader.js:778:12)
at Module.require (internal/modules/cjs/loader.js:961:19)
at require (internal/modules/cjs/helpers.js:92:18)
at Object. (/opt/lumi/node_modules/@abandonware/bluetooth-hci-socket/lib/native.js:7:17)
at Module._compile (internal/modules/cjs/loader.js:1072:14)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1101:10)
at Module.load (internal/modules/cjs/loader.js:937:32)
at Function.Module._load (internal/modules/cjs/loader.js:778:12)
`
root@OpenWrt:/tmp# node /opt/lumi/lumi.js
mqtt_client.connect
MPD error: Connection refused
child_process.js:866
throw err;
^
Error: Command failed: mpc current --format '%name% - %artist% - %title%'
MPD error: Connection refused
at checkExecSyncError (child_process.js:790:11)
at Object.execSync (child_process.js:863:15)
at getPlay (/opt/lumi/gateway.js:284:32)
at Object.getState (/opt/lumi/gateway.js:183:5)
at MqttClient.<anonymous> (/opt/lumi/mqtt_client.js:10:13)
at MqttClient.emit (events.js:412:35)
at Readable.<anonymous> (/opt/lumi/node_modules/mqtt/lib/client.js:1570:14)
at Readable.emit (events.js:400:28)
at endReadableNT (/opt/lumi/node_modules/readable-stream/lib/_stream_readable.js:1094:12)
at processTicksAndRejections (internal/process/task_queues.js:82:21) {
status: 1,
signal: null,
output: [
null,
Buffer(0) [Uint8Array] [],
Buffer(30) [Uint8Array] [
77, 80, 68, 32, 101, 114, 114,
111, 114, 58, 32, 67, 111, 110,
110, 101, 99, 116, 105, 111, 110,
32, 114, 101, 102, 117, 115, 101,
100, 10
]
],
pid: 9884,
stdout: Buffer(0) [Uint8Array] [],
stderr: Buffer(30) [Uint8Array] [
77, 80, 68, 32, 101, 114, 114,
111, 114, 58, 32, 67, 111, 110,
110, 101, 99, 116, 105, 111, 110,
32, 114, 101, 102, 117, 115, 101,
100, 10
]
}
Есть в планах реализовать возможность отслеживать местоположение ble устройств по комнатам, как пример https://github.com/mKeRix/room-assistant?
This is a very nice project and works better than other similar lumimqtt versions. I think that a nice improvement would be if it supported a "light transition period" setting for the led. Other fixes that can be implemented as well. For example the maximum light intensity does not go to 100% in home assistant.
Может быть добавить под гит package.json и lock вместо node_modules?
Hi! I think it can be rather usefull to add the repeat option for /lumi/audio/play/set like this:
{"url": "/tmp/whitenoise.mp3", "volume": 20, "repeat":"ON"}
This option can be used with some baby lullables, white noise for sleeping, etc.
Добрый день! Думаю, довольно полезным было бы добавить функцию повтора для /lumi/audio/play/set примерно таким образом:
{"url": "/tmp/whitenoise.mp3", "volume": 20, "repeat":"ON"}
Этот параметр можно было бы использовать для детских колыбельных, белого шума для засыпания и т.п..
Для термомента "MJ_HT_V1" не отображается значение температуры в Homeassistant из-за неверного формата конфигурационного сообщения.
Для сравнения во влажности:
{"name":"582d34302358_humidity","unique_id":"582d34302358_humidity","device_class":"humidity","state_topic":"lumi/582d34302358","unit_of_measurement":"%","value_template":"{{ value_json.humidity }}","device":{"name":"MJ_HT_V1","identifiers":["MJ_HT_V1"],"sw_version":"1.0","model":"Xiaomi Gateway","manufacturer":"Xiaomi"}}
В температуре:
{"name":"582d34302358_temperature","unique_id":"582d34302358_temperature","device_class":"temperature","state_topic":"lumi/582d34302358","unit_of_measurement":"°C","value_template":"{{ value_json.temperature }}","device":{"identifiers":[null],"sw_version":"1.0","model":"Xiaomi Gateway","manufacturer":"Xiaomi"}}
При добавлении недостающих
"device":{"name":"MJ_HT_V1","identifiers":["MJ_HT_V1"] к сообщению вручную все работает правильно
П.С. к сожалению поскольку в JS не понимаю ничего то и PR создать нет возможности
MPD error: Connection refused
child_process.js:866
throw err;
^
Error: Command failed: mpc current --format '%name% - %artist% - %title%'
MPD error: Connection refused
at checkExecSyncError (child_process.js:790:11)
at Object.execSync (child_process.js:863:15)
at getPlay (/opt/lumi/gateway.js:284:32)
at Object.getState (/opt/lumi/gateway.js:183:5)
at MqttClient.<anonymous> (/opt/lumi/mqtt_client.js:10:13)
at MqttClient.emit (events.js:412:35)
at Readable.<anonymous> (/opt/lumi/node_modules/mqtt/lib/client.js:1570:14)
at Readable.emit (events.js:400:28)
at endReadableNT (/opt/lumi/node_modules/readable-stream/lib/_stream_readable.js:1094:12)
at processTicksAndRejections (internal/process/task_queues.js:82:21) {
status: 1,
signal: null,
output: [
null,
Buffer(0) [Uint8Array] [],
Buffer(30) [Uint8Array] [
77, 80, 68, 32, 101, 114, 114,
111, 114, 58, 32, 67, 111, 110,
110, 101, 99, 116, 105, 111, 110,
32, 114, 101, 102, 117, 115, 101,
100, 10
]
],
pid: 12529,
stdout: Buffer(0) [Uint8Array] [],
stderr: Buffer(30) [Uint8Array] [
77, 80, 68, 32, 101, 114, 114,
111, 114, 58, 32, 67, 111, 110,
110, 101, 99, 116, 105, 111, 110,
32, 114, 101, 102, 117, 115, 101,
100, 10
]
}
При наличии 2х устройство в сети и включенной отправкой в HA оба устройства пишут в 1 топик
homeassistant/light/lumi_light
homeassistant/sensor/lumi_illuminance
и тд
Hi All thankls for your work.
Lately i have this problem with mp3 playback.
Until recently it worked flawlessly.
{'url': 'https://xxxx.duckdns.org:8123/local/mp3/disinserito.mp3','volume': '100'}
This error:
Do you have any idea why this problem came up ??
Было б красиво добавить в alarm (наряду с морганием диода) добавить повторное (N раз или до остановки) проигрывание tts или mp3 файла с объявлением проблемы.
that happened when play any music local or url i lose control back to work after music end
is it possible to make value with int or float type, not string with quotes?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.