Skip to content

Commit

Permalink
v.1.9-beta
Browse files Browse the repository at this point in the history
* Добавлены функции зональной уборки (**zoned_clean**), движения к точке (**goto_target**) и смены мощности/режима работы (**custom_mode**) для пылесосов.
* Добавлена справка по метрикам для шлюза Mijia.
* Добавлена справка по метрикам для шлюза Aqara AC.
* Добавлена справка по метрикам для IR-шайбы.
* Обновлен readme.md
  • Loading branch information
skysilver-lab committed Aug 23, 2018
1 parent 316ce17 commit 63b210f
Show file tree
Hide file tree
Showing 7 changed files with 349 additions and 68 deletions.
54 changes: 52 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,52 @@
# majordomo-xiaomimiio
Xiaomi Smart Home miIO-devices integration
# Xiaomi miIO

Модуль предназначен для интеграции **MajorDoMo** с Wi-Fi устройствами из экосистемы **Xiaomi Mihome**, взаимодействующих по протоколу **miIO**.

**miIO** - проприетарный сетевой протокол Xiaomi с шифрованием, по которому взаимодействуют wifi-устройства из экосистемы Xiaomi и приложение Mihome на смартфоне. В качестве транспорта используется UDP и порт 54321. Содержимое пакетов шифруется. Ключи шифрования формируются на основе уникальных токенов. Для контроля корректности принимаемых пакетов используется контрольная сумма на основе алгоритма MD5.

Использование этого протокола позволяет управлять теми устройствами, которые не имеют открытого API (режима разработчика). Например, пылесосы, лампы, светильники, увлажнители и очистители воздуха, розетки и многие другие. Также позволяет расширить имеющиеся возможности открытого API у xiaomi-шлюза, в частности переводить его в режим сопряжения, привязывать и отвязывать zigbee-устройства, управлять радио и др.

В основе модуля лежит библиотека **[php-miio](https://github.com/skysilver-lab/php-miio)**.

Обсуждение модуля на **[Форуме](https://majordomo.smartliving.ru/forum/viewtopic.php?f=5&t=4863)**.

Модуль в **[Connect](https://connect.smartliving.ru/tasks/51.html)**.

![miio](https://kb.smartliving.ru/wp-content/uploads/2018/07/module_miio.gif)

### Поддерживаемые устройства
> По состоянию на июль 2018 года.
1. Шлюз ZigBee ***Mi Smart Home Gateway 2***
2. Шлюз ZigBee ***Aqara AC Companion Gateway***
3. Розетка ***Mi Smart Socket Plug 2***
4. Розетка ***Mi Smart Socket Plug with USB***
5. Розетка ***Mi Smart Socket Plug with 2 USB***
6. Пылесос ***Mi Vacuum Cleaner***
7. Пылесос ***Mi Roborock S50/S51***
8. Настольная лампа ***Philips EyeCare Smart Desk Lamp 2***
9. Лампочка белая Е27 ***Philips Light Bulb***
10. Лампочка белая Е27 ***Yeelight White Bulb***
11. Лампочка цветная Е27 ***Yeelight Color Bulb***
12. Лампочки ***Philips Rui Chi Candle Light Bulb
13. Настольная лампа ***Mi LED Desk Lamp***
14. Потолочный светильник ***Yeelight Ceiling Light***
15. Потолочный светильник ***Philips EyeCare Smart Ceiling Lamp***
16. Светодиодная лента ***Yeelight LED Lightstrip***
17. Удлинитель (6 розеток) ***Mi Smart Power Strip 6 Plugs***
18. Увлажнитель воздуха ***Mi Air Humidifier***
19. Увлажнитель воздуха ***Mi Air Humidifier 2***
20. Очиститель воздуха ***Mi Air Purifier 2S***
21. IR-контроллер ***Mi IR Remote 360***
22. WiFi-колонка ***Mi Internet Speaker***
23. Ночник ***Yeelight Bedside Lamp***
24. Светильник (спот) ***Philips Zhirui Downlight***

![devices](https://connect.smartliving.ru/cms/data_images/152_image.png)
### Документация по модулю
* [Общие сведения](https://kb.smartliving.ru/xiaomimiio_help/)
* [Установка, обновление, удаление модуля](https://kb.smartliving.ru/xiaomimiio-ustanovka-obnovlenie/)
* [Интерфейс модуля](https://kb.smartliving.ru/xiaomimiio-gui/)
* [Настройка модуля](https://kb.smartliving.ru/xiaomimiio-settings/)
* [Протокол miIO](https://kb.smartliving.ru/xiaomimiio-protocol/)
* [Токены устройств](https://kb.smartliving.ru/xiaomimiio-tokens/)
31 changes: 17 additions & 14 deletions modules/xiaomimiio/miio_devices_edit.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/*
* @author <[email protected]>
* @copyright 2017-2018 Agaphonov Dmitri aka skysilver <[email protected]> (c)
* @version 1.8.5b
* @version 1.9b
*/

if ($this->owner->name == 'panel') {
Expand Down Expand Up @@ -46,21 +46,24 @@
$rec['NEXT_UPDATE'] = date('Y-m-d H:i:s');
}

$commands = array('online', 'command', 'message');
if (($rec['DEVICE_TYPE'] == 'lumi.gateway.v3') || ($rec['DEVICE_TYPE'] == 'lumi.acpartner.v3')) {
$commands[] = 'add_program';
$commands[] = 'del_program';
}
if ($rec['DEVICE_TYPE'] == 'chuangmi.ir.v2' || $rec['DEVICE_TYPE'] == 'lumi.acpartner.v3') {
$commands[] = 'ir_play';
}
if ($rec['DEVICE_TYPE'] == 'xiaomi.wifispeaker.v1') {
$commands[] = 'vol_up';
$commands[] = 'vol_down';
}
if ($rec['DEVICE_TYPE'] == 'lumi.acpartner.v3') {
// Базовые метрики устройств
$commands = array('online', 'command', 'message');

// Специфичные метрики для некоторых устройств
if (($rec['DEVICE_TYPE'] == 'lumi.gateway.v3') || ($rec['DEVICE_TYPE'] == 'lumi.acpartner.v3')) {
$commands[] = 'add_program';
$commands[] = 'del_program';
} else if ($rec['DEVICE_TYPE'] == 'chuangmi.ir.v2' || $rec['DEVICE_TYPE'] == 'lumi.acpartner.v3') {
$commands[] = 'ir_play';
} else if ($rec['DEVICE_TYPE'] == 'xiaomi.wifispeaker.v1') {
$commands[] = 'vol_up';
$commands[] = 'vol_down';
} else if ($rec['DEVICE_TYPE'] == 'lumi.acpartner.v3') {
$commands[] = 'power';
$commands[] = 'load_power';
} else if ($rec['DEVICE_TYPE'] == 'rockrobo.vacuum.v1' || $rec['DEVICE_TYPE'] == 'roborock.vacuum.s5') {
$commands[] = 'goto_target';
$commands[] = 'zoned_clean';
}
}

Expand Down
105 changes: 63 additions & 42 deletions modules/xiaomimiio/xiaomimiio.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* @package project
* @author <[email protected]>
* @copyright 2017-2018 Agaphonov Dmitri aka skysilver <[email protected]> (c)
* @version 1.8b
* @version 1.9b
*/

define ('MIIO_YEELIGHT_WHITE_BULB_PROPS', 'power,bright,flow_params,flowing');
Expand Down Expand Up @@ -33,24 +33,26 @@
define ('MIIO_MIWIFISPEAKER_V1_PROPS', 'umi,volume,rel_time');

define ('MIIO_MIVACUUM_1_STATE_CODES', serialize (array('0' => 'Unknown',
'1' => 'Initiating',
'2' => 'Sleeping',
'3' => 'Waiting',
'4' => 'Remote control active',
'5' => 'Cleaning',
'6' => 'Back to home',
'7' => 'Manual mode',
'8' => 'Charging',
'9' => 'Charging Error',
'10' => 'Pause',
'11' => 'Spot Cleaning',
'12' => 'In Error',
'13' => 'Shutting down',
'14' => 'Updating',
'15' => 'Docking',
'16' => 'Going to target',
'17' => 'Zoned cleaning',
'100' => 'Full')));
'1' => 'Initiating',
'2' => 'Sleeping',
'3' => 'Waiting',
'4' => 'Remote control active',
'5' => 'Cleaning',
'6' => 'Back to home',
'7' => 'Manual mode',
'8' => 'Charging',
'9' => 'Charging Error',
'10' => 'Pause',
'11' => 'Spot Cleaning',
'12' => 'In Error',
'13' => 'Shutting down',
'14' => 'Updating',
'15' => 'Docking',
'16' => 'Going to target',
'17' => 'Zoned cleaning',
'100' => 'Full',
'101' => 'Wet cleaning',
'105' => 'Turbo')));

define ('MIIO_MIVACUUM_1_ERROR_CODES', serialize (array('0' => 'No error',
'1' => 'Laser distance sensor error',
Expand Down Expand Up @@ -358,7 +360,7 @@ function discover($ip = '') {
continue;
}

//TO-DO: новые сравниваются по sid и devcode, но если устройство было добавлено вручную, то эти параметры будут отсутствовать,
//TODO: новые сравниваются по sid и devcode, но если устройство было добавлено вручную, то эти параметры будут отсутствовать,
//соотвественно устройство добавится как новое, а не перезапишет (обновит) добавленно вручную.
$dev_rec = SQLSelectOne("SELECT * FROM miio_devices WHERE DEVICE_TYPE_CODE='$device_type_code' AND SERIAL='$device_serial'");

Expand Down Expand Up @@ -406,31 +408,32 @@ function discover($ip = '') {
}
}

$dev_rec['ID'] = SQLInsert('miio_devices', $dev_rec);
$dev_rec['ID'] = SQLInsert('miio_devices', $dev_rec);

// Базовые метрики устройств
$this->processCommand($dev_rec['ID'], 'online', 1);
$this->processCommand($dev_rec['ID'], 'command', '');
$this->processCommand($dev_rec['ID'], 'message', '');

// Специфичные метрики для некоторых устройств
if ($dev_rec['DEVICE_TYPE'] != '') {
$this->requestStatus($dev_rec['ID']);
if (($dev_rec['DEVICE_TYPE'] == 'lumi.gateway.v3') || ($dev_rec['DEVICE_TYPE'] == 'lumi.acpartner.v3')) {
$this->processCommand($dev_rec['ID'], 'add_program', '');
$this->processCommand($dev_rec['ID'], 'del_program', '');
}
if ($dev_rec['DEVICE_TYPE'] == 'chuangmi.ir.v2' || $dev_rec['DEVICE_TYPE'] == 'lumi.acpartner.v3') {
$this->processCommand($dev_rec['ID'], 'ir_play', '');
}
if ($dev_rec['DEVICE_TYPE'] == 'xiaomi.wifispeaker.v1') {
$this->processCommand($dev_rec['ID'], 'vol_up', '');
$this->processCommand($dev_rec['ID'], 'vol_down', '');
}
if ($dev_rec['DEVICE_TYPE'] == 'lumi.acpartner.v3') {
$this->requestStatus($dev_rec['ID']);
if (($dev_rec['DEVICE_TYPE'] == 'lumi.gateway.v3') || ($dev_rec['DEVICE_TYPE'] == 'lumi.acpartner.v3')) {
$this->processCommand($dev_rec['ID'], 'add_program', '');
$this->processCommand($dev_rec['ID'], 'del_program', '');
} else if ($dev_rec['DEVICE_TYPE'] == 'chuangmi.ir.v2' || $dev_rec['DEVICE_TYPE'] == 'lumi.acpartner.v3') {
$this->processCommand($dev_rec['ID'], 'ir_play', '');
} else if ($dev_rec['DEVICE_TYPE'] == 'xiaomi.wifispeaker.v1') {
$this->processCommand($dev_rec['ID'], 'vol_up', '');
$this->processCommand($dev_rec['ID'], 'vol_down', '');
} else if ($dev_rec['DEVICE_TYPE'] == 'lumi.acpartner.v3') {
$this->processCommand($dev_rec['ID'], 'power', '');
$this->processCommand($dev_rec['ID'], 'load_power', '');
} else if ($dev_rec['DEVICE_TYPE'] == 'rockrobo.vacuum.v1' || $dev_rec['DEVICE_TYPE'] == 'roborock.vacuum.s5') {
$this->processCommand($dev_rec['ID'], 'goto_target', '');
$this->processCommand($dev_rec['ID'], 'zoned_clean', '');
}
}
}
}
}
}
Expand Down Expand Up @@ -520,10 +523,12 @@ function requestStatus($device_id) {
}
$this->addToQueue($device_id, 'get_prop', '[' . implode(',', $props) . ']');
} else if (($device_rec['DEVICE_TYPE'] == 'rockrobo.vacuum.v1') || ($device_rec['DEVICE_TYPE'] == 'roborock.vacuum.s5')) {
//
$this->addToQueue($device_id, 'get_status');
sleep(1);
$this->addToQueue($device_id, 'get_consumable');
//
$this->addToQueue($device_id, 'get_status');
sleep(1);
$this->addToQueue($device_id, 'get_consumable');
sleep(1);
$this->addToQueue($device_id, 'get_custom_mode');
} elseif ($device_rec['DEVICE_TYPE'] == 'chuangmi.plug.m1') {
//
$props = explode(',', MIIO_CHUANGMI_PLUG_M1_PROPS);
Expand Down Expand Up @@ -813,7 +818,7 @@ function propertySetHandle($object, $property, $value) {
// Например, miIO.info, toggle, app_start и др.
$this->addToQueue($properties[$i]['DEVICE_ID'], $value, '[]');
}
//TO-DO: после отправки команды желательно обновить сведения об устройстве,
//TODO: после отправки команды желательно обновить сведения об устройстве,
//но при этом перезапишется поле message (удалится результат выполнения команды),
//что может быть неприемлемо.
//$this->requestStatus($properties[$i]['DEVICE_ID']);
Expand Down Expand Up @@ -993,7 +998,20 @@ function propertySetHandle($object, $property, $value) {
$this->addToQueue($properties[$i]['DEVICE_ID'], 'set_mode', '["' . $value . '"]');
}
}
} elseif ($properties[$i]['TITLE'] == 'flow') {
} elseif ($properties[$i]['TITLE'] == 'custom_mode') {
// Изменение режима работы (мощности) пылесоса (от 1 до 100%, 101 - влажная уборка, 105 - турбо)
$this->addToQueue($properties[$i]['DEVICE_ID'], 'set_custom_mode', '[' . $value . ']');
} elseif ($properties[$i]['TITLE'] == 'zoned_clean') {
// Уборка указанных зон (параметры - либо одна зона [[zone1]], либо список зон [[zone1],[zone2]])
// [x1 Integer, y1 Integer, x2 Integer, y2 Integer, times Integer]
// {"id":8338,"method":"app_zoned_clean","params":[[26234,26042,27284,26642,5]]}
// {"id":8338,"method":"app_zoned_clean","params":[[26234,26042,27284,26642,1],[26232,25304,27282,25804,2],[26246,24189,27296,25139,3]]}
$this->addToQueue($properties[$i]['DEVICE_ID'], 'app_zoned_clean', '[' . $value . ']');
} elseif ($properties[$i]['TITLE'] == 'goto_target') {
// Движение в заданную точку (параметры [x Integer, y Integer])
// {"id": 25736111,"method": "app_goto_target","params": [24200,20200]}
$this->addToQueue($properties[$i]['DEVICE_ID'], 'app_goto_target', '[' . $value . ']');
} elseif ($properties[$i]['TITLE'] == 'flow') {
//
if ($value != '') {
$this->addToQueue($properties[$i]['DEVICE_ID'], 'start_cf', "[$value]");
Expand Down Expand Up @@ -1242,7 +1260,10 @@ function processMessage($message, $command, $device_id) {
if (array_key_exists($value, $error_codes)) $res_commands[] = array('command' => 'error_text', 'value' => $error_codes[$value]);
}
}
}
} else if ($command == 'get_custom_mode' && is_array($data['result'])) {
//get_custom_mode {"result":[60],"id":1535013272}
$res_commands[] = array('command' => 'custom_mode', 'value' => $data['result'][0]);
}
} elseif ($device['DEVICE_TYPE'] == 'chuangmi.plug.m1' && $command == 'get_prop' && is_array($data['result'])) {
$props = explode(',', MIIO_CHUANGMI_PLUG_M1_PROPS);
$i = 0;
Expand Down
2 changes: 1 addition & 1 deletion templates/xiaomimiio/action_admin.html
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ <h4 class="modal-title">Xiaomi miIO</h4>
<div class="modal-body">
<div class="float-right">
<img src="../templates/xiaomimiio/milogo.png" width="48" height="48">
<br><br><p><b>v.1.8.5</b></p>
<br><br><p><b>v.1.9b</b></p>
</div>
<p class="float-left">
<#LANG_XIMI_APP_MODULE#><br><br>
Expand Down
Loading

0 comments on commit 63b210f

Please sign in to comment.