GithubHelp home page GithubHelp logo

lumi's People

Contributors

beetle-ii avatar condemil avatar freefelt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

lumi's Issues

Issue with lumi/audio/play/set

Hello,

When music is playing it's impossible to stop it with lumi/audio/play/set "STOP"

Thanks for your great work!

Regards,

Miguel

Support for /sys/class/leds/red/brightness instead of backlight

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
image

Из обнаруженных проблем:

  • Все строковые переменные ошибочно передаются в MQTT с кавычками. А должны без. Пытаюсь разобраться где находится процедура по записи в MQTT. Пока отследил mqtt.publish(button);[gateway.js] -> mqtt_client.publish(device.state_topic, JSON.stringify(device.value), {retain: false});[mqtt_client.js] -> [mqtt.js]

`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

Обнаружил неприятные моменты при включении BLE:

  1. BLE устройства адски спамят в MQTT. 1-3 сообщения в секунду и пофиг на настройки в конфиге..
  2. Начинает течь память на шлюзе со скоростью 20-30Мб в сутки.
    Поймал "отвал вайфай при ble". По факту оперативка шлюза была съедена в 0. После чистки запущенных служб отвалов не было. Отключил БТ, утечек памяти не наблюдаю

UPD: После отключения БТ спам пошел от датчика освещенности

Add license

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?

ERR_INVALID_ARG_TYPE

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 не отображается влажность и фертильность почвы

Для датчика почвы 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"

Заранне спасибо

JSON result was not a dictionary

Приходят такие ворнинги. В описании ничего конкретного нет, но я методом тыка проверил. Если выключить lumi, то они пропадают, если включить, то тут же появляются снова.

Проверка длины передаваемого сообщения в lumi/say/set

Как выяснилось, у бесплатного Goggle TTS движка есть ограничение на 200 проговариваемых символов. Надо сделать проверку на превышение. Или попробовать разбивать большой текст на несколько мелких отрезков

Проблемы с проигрыванием файлов в медиаплеере

В коде вижу возможную ошибку url = msg.url.toLowerCase(); Весь текст приводим в нижний регистр. А файлы могут быть с заглавными буквами.
А вот тут скорее всего вылезают пролемы с пробелами в именах файлов cp.execSync('mpg123 ' + url);

bluetooth_hci_socket.node symbol not found

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)
`

MPD error: Connection refused

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
  ]
}

Light transition period

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

Может быть добавить под гит package.json и lock вместо node_modules?

Repeat option for playing

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

Для термомента "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

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 устройства пишут в 1 топик

При наличии 2х устройство в сети и включенной отправкой в HA оба устройства пишут в 1 топик
homeassistant/light/lumi_light
homeassistant/sensor/lumi_illuminance
и тд

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.