UNPKG

xiaomi-mqtt

Version:

Bridge between Xiaomi Mi Smart Home Gateway and Mqtt broker.

451 lines (352 loc) 10 kB
# xiaomi-mqtt [![NPM version][npm-image]][npm-url] [npm-image]: http://img.shields.io/npm/v/xiaomi-mqtt.svg [npm-url]: https://npmjs.org/package/xiaomi-mqtt A Bridge between the Xiaomi Mi Smart Home Gateway and the Mqtt broker. Xiaomi-mqtt exchanges data between the xiaomi gateway and the mqtt-broker at a low-level, principally based on the device `sid` (Security Identifier?). The automation and dashboard tasks are implemented at a higher level. [Node-RED](http://nodered.org/) is the perfect tool to use for this purpose. ### Installation ```sh sudo npm install -g xiaomi-mqtt ``` ### Installation from GitHub Clone the source repository directly from GitHub to a local folder: ```sh git clone https://github.com/cflurin/xiaomi-mqtt.git ``` Local Installation: ```sh cd xiaomi-mqtt npm install ``` ### Configuration Copy the `config.json` file to the `.xiaomi-mqtt` folder inside of your home folder. ```sh mkdir ~/.xiaomi-mqtt cp config.json ~/.xiaomi-mqtt/ ``` On Linux the full path for your config.json would be `~/.xiaomi-mqtt/config.json`. Edit `~/xiaomi-mqtt/config.json` to fit your requirements: ```sh { "xiaomi": { "serverPort": 9898, "multicastAddress": "224.0.0.50", "multicastPort": 4321, "password": "FFF..." }, "mqtt": { "url": "mqtt://127.0.0.1", "port": 1883, "username": "foo", "password": "bar", "topic_mode": "short", "topic_prefix": "xiaomi" }, "loglevel": "info", "heartbeatfreq": 6, "dataFormat": "parsed" } ``` ```sh "topic_mode": <"short"> | <"full"> | <"both"> ``` - `short` default - `full` allow you to do some topic filtering directly on client side. - `both` 2 topics are sent, `short` and `full`. ```sh "loglevel": <"debug"> | <"info"> | <"warn"> | <"error"> ``` Replace `127.0.0.1` with the address of your mqtt broker. Set `dataFormat` to `raw` to get data without parsing. By default the gateway send heartbeat every 10s which can do some pollution when testing/debug, the counter parameter in config named `heartbeatfreq` avoid this, in the example above set to 6 means only send a MQTT message each 6 heartbeat, so each 60s. Note this apply only to gateway heartbeat not the device's one. ### Usage (global installation) Use `xiaomi-mqtt` or `xm` to run xiaomi-mqtt.<br> Use `ctrl c` to stop xiaomi-mqtt. ### Usage (local installation) In the `xiaomi-mqtt` folder. Use `npm start` to run xiaomi-mqtt.<br> Use `ctrl c` to stop xiaomi-mqtt. # # mqtt API If the configuration option `topic_mode` is set to `short` or `both`, the data (payload) is sent/received in a JSON format using following topics: * xiaomi/from * xiaomi/to/read * xiaomi/to/write * xiaomi/to/get_id_list **Note**: Have look at: [How to benefit of the full topic option](https://github.com/cflurin/xiaomi-mqtt/wiki/How-to-benefit-of-the-full-topic-option) ## Howto examples At start and stop xiaomi-mqtt sends following messages. ### start ```sh topic: xiaomi/from payload: {"cmd":"xm","msg":"xiaomi-mqtt started."} ``` and ```sh topic: xiaomi/from payload: { "cmd":"get_id_list_ack", "sid":"fff...", "data":["158d00017118ac","158d0001a2eb66","158d0001f35b90","158d0001e52516"] } ``` ### stop ```sh topic: xiaomi/from payload: {"cmd":"xm","msg":"xiaomi-mqtt stopped."} ``` ### heartbeat **gateway** ```sh topic: xiaomi/from payload: { "cmd": "heartbeat", "model": "gateway", "sid": "fff...", "short_id": "0", "token": "v4GeGCO9TBpTUlVy", "data": { "ip": "127.0.0.1" } } ``` **cube** ```sh topic: xiaomi/from payload: { "cmd": "heartbeat", "model": "cube", "sid": "158d0003102db5", "short_id": 46605, "data": { "voltage": 2985 } } ``` ### reporting Xiaomi-mqtt sends periodically or on events device reports. **gateway** ```sh topic: xiaomi/from payload: { "cmd": "report", "model": "gateway", "sid": "fff...", "short_id": 0, "data": { "rgb": 0, "illumination": 1292 } } ``` **sensor_ht** ```sh topic: xiaomi/from payload: { "cmd":"report", "model":"sensor_ht", "sid":"158d0001a2eb66", "short_id":30124, "data":{"voltage":3005,"temperature":16.7,"humidity":null} } ``` ```sh "data": {"voltage":3005,"temperature":16.7,"humidity":null} or "data": {"voltage":3005,"temperature":null,"humidity":51.7} ``` **magnet** ```sh topic: xiaomi/from payload: { "cmd": "report", "model": "magnet", "sid": "158d0001f3651f", "short_id": 57029, "data": { "status": "close" } } ``` ```sh "status": "close", "open" ``` **switch** ```sh topic: xiaomi/from payload: { "cmd":"report", "model":"switch", "sid":"158d0001f35b90", "short_id":46517, "data":{"status":"click"} } ``` ```sh "status": "click", "double_click", "long_click_press", "long_click_release" ``` **86sw2** ```sh topic: xiaomi/from payload: { "cmd":"report", "model":"86sw2", "sid":"158d0001f55b88", "short_id":33911, "data":{"channel_0":"click"} } ``` ```sh "data":{"channel_0":"click"} or "data":{"channel_1":"click"} ``` **cube** ```sh topic: xiaomi/from payload: { "cmd":"report", "model":"cube", "sid":"158d0003102db5", "short_id":46605, "data":{"status":"move"} } ``` ```sh "status": "move", "flip90", "flip180", "tape_twice", "shake_air", "alert" or "rotate": "99,999", "-99.999" ``` ### read **gateway** ```sh topic: xiaomi/to/read payload: {"sid":"fff..."} ``` response ```sh topic: xiaomi/from payload: { "cmd":"read_ack", "model":"gateway", "sid":"fff...", "short_id":0, "data":{"rgb":0,"illumination":1292,"proto_version":"1.0.9"} } ``` **sensor_ht** ```sh topic: xiaomi/to/read payload: {"sid":"158d00017118ac"} ``` response ```sh topic: xiaomi/from payload: { "cmd":"read_ack", "model":"sensor_ht", "sid":"158d00017118ac", "short_id":48290, "data":{"voltage":2985,"temperature":19,"humidity":46.3} } ``` **switch** ```sh topic: xiaomi/to/read payload: {"sid":"158d0001f35b90"} ``` response ```sh topic: xiaomi/from payload: { "cmd":"read_ack", "model":"switch", "sid":"158d0001f35b90", "short_id":46517, "data":{"voltage":3112} } ``` ### write ```sh topic: xiaomi/to/write payload: { "cmd": "write", "model": "gateway", "sid": "fff...", "data": { "rgb": "1000FF00" } } ``` **Note:** rgb = [brightness] [red] [green] [blue] - each hex 00 to FF response ```sh topic: xiaomi/from payload: { "cmd":"write_ack", "model":"gateway", "sid":"fff...", "short_id":0, "data":{"rgb":268500736,"illumination":1292,"proto_version":"1.0.9"} } ``` ### get_id_list: ```sh topic: xiaomi/to/get_id_list payload: {"sid":"fff..."} ``` **Note:** sid = gateway sid. response ```sh topic: xiaomi/from payload: { "cmd":"get_id_list_ack", "sid":"fff...", "data":["158d00017118ac","158d0001a2eb66","158d0001f35b90","158d0001e52516"] } ``` ## Tested devices (models): * gateway * sensor_ht * motion * sensor_motion.aq2 * sensor_wleak.aq1 * magnet * switch * 86sw1 * 86sw2 * cube * ctrl_neutral1 * ctrl_neutral2 * ctrl_ln1.aq1 **Note:** Untested devices using the same format will also send a payload. # # Node-RED examples ### basic ![node-red-ex1](https://user-images.githubusercontent.com/5056710/37292838-1612a042-2612-11e8-8473-939496dc0022.jpeg) ### write gateway ![node-red-ex2](https://user-images.githubusercontent.com/5056710/37520088-f6fe26a6-291b-11e8-9040-c32bf7c38c94.jpeg) Flow: ```sh [{"id":"9339669d.8e38b8","type":"mqtt out","z":"d0877ed4.9e0cc","name":"","topic":"xiaomi/to/write","qos":"","retain":"","broker":"325f5be5.555734","x":560,"y":480,"wires":[]},{"id":"c508a302.61467","type":"ui_colour_picker","z":"d0877ed4.9e0cc","name":"","label":"gateway color","group":"4d5fcade.c527d4","format":"hex","outformat":"string","showSwatch":true,"showPicker":false,"showValue":true,"showAlpha":false,"showLightness":true,"dynOutput":"false","order":0,"width":0,"height":0,"passthru":true,"topic":"","x":220,"y":480,"wires":[["dcd9ac95.fd93"]]},{"id":"dcd9ac95.fd93","type":"template","z":"d0877ed4.9e0cc","name":"map","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{\n \"cmd\": \"write\",\n \"model\": \"gateway\",\n \"sid\": \"fff...\",\n \"data\": {\n \"rgb\": \"10{{payload}}\"\n }\n}","output":"json","x":390,"y":480,"wires":[["9339669d.8e38b8"]]},{"id":"325f5be5.555734","type":"mqtt-broker","z":"","broker":"127.0.0.1","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"willTopic":"","willQos":"0","willPayload":"","birthTopic":"","birthQos":"0","birthPayload":""},{"id":"4d5fcade.c527d4","type":"ui_group","z":"","name":"Xiaomi","tab":"f3d46e49.beaec","order":1,"disp":true,"width":"6"},{"id":"f3d46e49.beaec","type":"ui_tab","z":"","name":"Main","icon":"dashboard","order":1}] ``` ![node-red-ex3](https://user-images.githubusercontent.com/5056710/37528165-327882b8-2934-11e8-98b1-cdcbf039f724.jpeg) Flow: ```sh [{"id":"aacbdba0.0519f8","type":"inject","z":"d0877ed4.9e0cc","name":"doorbell","topic":"","payload":"{\"cmd\":\"write\",\"model\":\"gateway\",\"sid\":\"fff...\",\"short_id\":0,\"key\":\"8\",\"data\":{\"mid\":10}}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":120,"y":580,"wires":[["83a2b4f.eb0d748"]]},{"id":"8f56c43e.16c048","type":"inject","z":"d0877ed4.9e0cc","name":"police","topic":"","payload":"{\"cmd\":\"write\",\"model\":\"gateway\",\"sid\":\"fff...\",\"short_id\":0,\"key\":\"8\",\"data\":{\"mid\":1}}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":620,"wires":[["83a2b4f.eb0d748"]]},{"id":"83a2b4f.eb0d748","type":"mqtt out","z":"d0877ed4.9e0cc","name":"","topic":"xiaomi/to/write","qos":"","retain":"","broker":"325f5be5.555734","x":340,"y":580,"wires":[]},{"id":"325f5be5.555734","type":"mqtt-broker","z":"","broker":"192.168.0.35","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"willTopic":"","willQos":"0","willPayload":"","birthTopic":"","birthQos":"0","birthPayload":""}] ```