| src | ||
| .gitignore | ||
| LICENSE | ||
| README.md | ||
| xiaomi.nimble | ||
This README was generated with Nim to Markdown
XIAOMI
Library for working with Xiaomi IOT devices.
Requirements
- nim >= 0.19.0
- multicast >= 0.1.1
- nimcrypto >= 0.3.2
Devices
Xiaomi IOT devices are supported. The following devices has been thoroughly tested:
Working with Xiaomi
You can interact with the Xiaomi devices in 3 ways:
- Read - Asking for a status, e.g. is the door open (door sensor)
- Report - Awaiting an action, e.g. when the door opens, it sends a notification (door sensor)
- Write - Send a message to the device (only some devices accepted this), e.g. play a sound (gateway)
All you Xiaomi devices are connected to a gateway. It is through this gateway, we are communicating with each of the devices. Each devices is identified with a SID.
Examples (basic)
Discover devices
But before we get started, you need to acquire your devices SID.
Get the gateways SID
import xiaomi
xiaomiConnect()
echo xiaomiGatewayGetSid()
Get the devices SID
import xiaomi
xiaomiConnect()
echo xiaomiDiscover()
Read
There are numerous ways to read. Some proc's just read the next message, some waits for a specific device, etc.
Read the next message sent
import xiaomi
xiaomiConnect()
echo xiaomiReadMessage()
Request a device status and read the reply
import xiaomi
xiaomiConnect()
echo xiaomiReadDevice("device-SID")
Read the next message from custom-x This will await that the cmd = "heartbeat" and the model = "gateway".
import xiaomi
xiaomiConnect()
echo xiaomiReadCustom("heartbeat", "gateway")
Read messages forever
import xiaomi
xiaomiConnect()
xiaomiListenForever()
Report
For PIR sensors you will receive a report, when there's motion or there hasn't been motion for 300 seconds.
For magnet sensors you will receive a report when they are connected (close) and disconnected (open).
Read next report
import xiaomi
xiaomiConnect()
echo xiaomiReportAck()
Read next report for device
import xiaomi
xiaomiConnect()
echo xiaomiReadReport("device-SID")
Write to a device
To write to a device, we need to exchange an encrypted key with the gateway based on an ever-changing token. We are utilizing nimcrypto AES CBC 128 to do this.
Gateway password
But before we can generate the key, you need to gather you gateway password. Follow this guide Domotics or the bullets below. Remember to write the key down.
- Install the Xiaomi app
- Set the region to Mainland China under Settings->Locale
- You can set the language to English, even though the region is China
- Sign in/Make an account
- Select your Gateway in the app
- Tap the 3 dots in top right corner
- Click About
- Tap on the version repeatedly until a new menu appear
- Click on Wireless communication protocol
- Enable the this and write down you password and press Ok
Setting the password
If you need to write to a device, insert your password in the global variable at the top of your code:
xiaomiGatewayPassword = "secretPassword"
Getting the encrypted key
The gateways token is changing all the time. You therefore need to the generate the encrypted key before each writing.
This is done with:
xiaomiTokenRefresh()
xiaomiSecretUpdate()
OR
xiaomiTokenRefresh(true)
OR while writing
xiaomiWrite("device-SID", "message", true)
Gateway writing options
There are 2 main elements you can write to the gateway - the light and sound.
Light writing
import xiaomi
xiaomiGatewayPassword = "secretPassword"
xiaomiTokenRefresh()
xiaomiWrite(xiaomiGatewaySid, "\"rgb\": 4294914304")
Light options
To assign a RGB color, you have to use the Android() color format.
You can convert HEX to Android() at this website.
- Red =
4294914304 - Green =
4283359807 - Purple =
4283637131 - Yellow =
4292211292 - Blue =
4283327469 - Off =
0
Sound writing
import xiaomi
xiaomiGatewayPassword = "secretPassword"
xiaomiTokenRefresh()
xiaomiWrite(xiaomiGatewaySid, "\"mid\": 7, \"vol\": 4")
Sound options
The volume is in percentage, whereas 10 = 100%.
The following sounds are available:
Alarms:
- 0 - Police car 1
- 1 - Police car 2
- 2 - Accident
- 3 - Countdown
- 4 - Ghost
- 5 - Sniper rifle
- 6 - Battle
- 7 - Air raid
- 8 - Bark
Doorbells
- 10 - Doorbell
- 11 - Knock at a door
- 12 - Amuse
- 13 - Alarm clock
Alarm clock
- 20 - MiMix
- 21 - Enthusiastic
- 22 - GuitarClassic
- 23 - IceWorldPiano
- 24 - LeisureTime
- 25 - ChildHood
- 26 - MorningStream
- 27 - MusicBox
- 28 - Orange
- 29 - Thinker
Types
Procs
proc xiaomiSecretUpdate*
proc xiaomiSecretUpdate*(password = xiaomiGatewayPassword, token = xiaomiGatewayToken) =
Update encrypt the secret for writing
proc xiaomiTokenRefresh*
proc xiaomiTokenRefresh*(updateKey = false) =
Wait for updated Gateway token. This does also populate the gateway sid.
proc xiaomiWrite*
proc xiaomiWrite*(sid, message: string, updateKey = false) =
Send a write command to the specified "sid" with a "message".
proc xiaomiSendRead*
proc xiaomiSendRead*(deviceSid: string) =
Tell the device to reply with it's status. This proc does not read the reply, only ask the device for sending a message with it's status and the cmd = read_ack.
proc xiaomiSend*
proc xiaomiSend*(message: string) =
Send a custom message
proc xiaomiReadMessage*
proc xiaomiReadMessage*(): string =
Read a single Xiaomi message and return it.
proc xiaomiReadCustom*
proc xiaomiReadCustom*(cmd = "", model = "", sid = ""): string =
Tell the device to reply with status. and return the reply if the custom parameters are fulfilled. It is optional to specify the parameters. Example: cmd => heartbeat model => gateway
proc xiaomiReadDevice*
proc xiaomiReadDevice*(deviceSid: string): string =
Tell the device to reply with it's status and return the reply.
proc xiaomiReadAck*
proc xiaomiReadAck*(deviceSid = ""): string =
Return next message with cmd = "read_ack". This is useful after telling a device to reply with it's status
proc xiaomiReadReport*
proc xiaomiReadReport*(deviceSid = ""): string =
Return next message with cmd = "report". This is useful if you are waiting for a sensor to reply with a change
proc xiaomiGatewayGetSid*
proc xiaomiGatewayGetSid*(): string =
Get the gateway's sid
proc xiaomiGatewayGetToken*
proc xiaomiGatewayGetToken*(): string =
Get the gateway's token
proc xiaomiDiscover*
proc xiaomiDiscover*(): string =
Discover xiaomi devices
proc xiaomiUpdateToken*
proc xiaomiUpdateToken*(message: string): string =
Updates the gateway token if possible and returns the data
proc xiaomiListenForever*
proc xiaomiListenForever*() =
Listen for Xiaomi mesages
proc xiaomiDisconnect*
proc xiaomiDisconnect*() =
Close connection to multicast
proc xiaomiConnect*
proc xiaomiConnect*() =
Initialize socket