Python module for controlling Mira Mode digital showers via BLE.
Mira Mode is a line of digital showers and bathfills from Mira Showers. They work great in my experience, but having only a Bluetooth Low Energy (BLE) interface, they can only be controlled locally via smartphone and not via Alexa, Google Home and the likes, which makes the whole experience significantly less useful.
To overcome this limitation, here's a Python library that can be used to control Mira Mode devices from a Raspberry PI or any other computer equipped with BLE capabilities, allowing an easy integration with projects like Home Assistant which can then expose the shower outlets as switches to Alexa or Google Home.
Disclaimer: this projects contains only the results of personal experiments, use at your own risk!
- Python (3.x preferabily, but works with 2.7 as well)
pip install -r requirements.txt
- Gatttool, a common BLE CLI tool on Linux
import miramode
# This is the BLE address of the device
address = "xx:xx:xx:xx:xx:xx"
# See below for how to obtain the device_id and client_id
device_id = 1
client_id = 12345
# Turn on the 1st outlet with a 40C degrees water temperature
miramode.control_outlets(address, device_id, client_id, True, False, 40)
# Turn on both outlets
miramode.control_outlets(address, device_id, client_id, True, True, 40)
# Turn on the bathfill with the default memorized temperature
miramode.turn_on_bathfill(address, device_id, client_id)
# Turn off
miramode.control_outlets(address, device_id, client_id, False, False, 40)
At the moment the way in which those ids are obtained is by using a BLE sniffer, like the Bluefruit LE Sniffer from Adafruit, to get packets exchanged between your phone Mira Mode app and the Mira Shower when an outlet is turned on, using e.g. Wireshark. This complication can be avoided by finding out how the device pairing protocol works, something on the TODO list.
What we are looking for are binary payloads written to the BLE characterist 0x11 which look for example like this:
XX:87:05:01:01:90:64:00:YY:YY
XX is your device id and YYYY is a CRC code obtained from the rest of the payload plus the client id. Being the client id a 16 bit adapter, it can be quickly computed with a brute force loop.
Using crc16_loop.py - at the top of the python script are 2 byte arrays, you need to copy your value into these. data excludes the CRC and payl is the entire value.
Split the value into hex pairs so they look the same as below.
data = bytearray([ 0x01, 0x87, 0x05, 0x03, 0x01, 0x9a, 0x00, 0x00]) payl = bytearray([ 0x01, 0x87, 0x05, 0x03, 0x01, 0x9a, 0x00, 0x00, 0xd5,0x28])