RSS Tags

C'est toi le titre


Flasher une prise connectée Konyks Priska Mini 3 pour la relier à OpenHAB avec MQTT

Martin Kirchgessner, 2024-11-11

Tags : openhab  in_french 


En 2021 j'ai acheté une prise connectée Konyks Priska Mini 3, qui permet via le Wifi d'allumer ou éteindre la prise, et de suivre la consommation de ce qui est branché. La prise n'est censée fonctionner qu'avec l'application de la marque. Mais on ne sait pas où vont les données... et depuis peu j'ai OpenHAB. Je me suis donc mis en tête de relier la prise à OpenHAB, pour que mes précieuses données de consommation ne quittent plus la maison, et cet article va vous raconter cette aventure.

La prise vue du dessus La prise vue du dessous (ou le contraire)
Un petit format très pratique mais manifestement indémontable.

ATTENTION si vous souhaitez effectuer ces manipulations, vous le faites à vos risques et périls. Votre prise pourrait devenir inutilisable. Ce qui suit reflète ma propre expérience, mais rien ne garantit que cela peut être reproduit ailleurs. Je pars aussi du principe que vous avez déjà installé OpenHAB et un serveur MQTT.

Identifier ce qui est faisable

En cherchant un peu autour de l'application Android, je découvre que cette prise en en fait fabriquée par Tuya. J'ai donc essayé d'utiliser tuya-convert, mais il me suggère que le contrôleur de la prise n'est pas un ESP8266. La documentation Tasmota le confirme, en suggèrant que depuis 2021 ce n'est plus le même contrôleur. Ma prise serait basée sur un contrôleur BK7231N, donc elle pourrait plutôt être flashée avec tuya-cloudcutter. Le bug exploité par tuya-cloudcutter est connu et corrigé depuis 2022, donc il faut d'abord vérifier que la prise est flashable avec cette méthode.

J'utilise un ordinateur sous Linux, avec un service Docker actif et Python déjà installé. Je clone tuya-cloudcutter :

git clone https://github.com/tuya-cloudcutter/tuya-cloudcutter.git
cd tuya-cloudcutter

Du coté de la prise, j'appuie 5 ou 6 secondes sur son bouton, jusqu'à ce qu'ilclignote lentement (toutes les deux secondes). Alors un réseau Wifi "SL-KONYKS-AP-XYZZ" apppaît. Je m'y connecte, puis lance le test :

$ python proof-of-concept/test_device_exploitable.py 
This script will attempt to help you lower the chances of prying open a device that won't be exploitable
However, it's not 100% foolproof either, there are more devices that are vulnerable which are not based on
the BK7231 chipset. So, please take that into account.
Before continuing, please set your device in AP mode first. This usually takes 6 power cycles off and on with ~1 sec between each.
Is your device now in AP mode? (yes/no) [default: no]: yes
Please connect to the device's AP then hit enter to continue.
Exploit payload sent! If the device has an LED and now seems to be 'frozen', it's likely exploitable.
Leave it be for ~60 seconds, if its WiFi AP stops showing up then it reboots and 'unfreezes' by itself, then it's almost definitely exploitable.

En effet le wifi disparait, la LED est bloquée, puis la prise redémarre : elle serait flashable avec cette méthode ! Elle peut rester dans cet état, qui correspond à la première étape pour flasher.

Par contre, ce modèle n'est pas connu par tuya-cloudcutter (et ce n'est pas gagné). Dans ce cas, la documentation recommande de relever le numéro de firmware (1.1.8) et rechercher le modèle par nom. Après plusieurs essais je découvre un modèle qui ressemble beaucoup à ma prise, la Nous A1.

The Flash

Je tente donc d'utiliser le profil de la Nous A1 pour flasher ma prise avec OpenBeken :

$ sudo ./tuya-cloudcutter.sh -p nous-a1-smart-plug -f OpenBeken-v1.17.697_bk7231n.ug.bin
[!] WARNING: Selected wifi AP support: oui
AP support is manditory for tuya-cloudcutter to work.  If this is blank or 'no' your adapter doesn't support this feature.
Press any key to continue, or CTRL+C to exitBuilding cloudcutter docker image
[+] Building 0.8s (13/13) FINISHED                                                                                                               docker:default
=> [internal] load build definition from Dockerfile                                                                                                       0.0s
=> => transferring dockerfile: 521B                                                                                                                       0.0s
=> [internal] load metadata for docker.io/library/python:3.9.18-slim-bullseye                                                                             0.4s
=> [internal] load .dockerignore                                                                                                                          0.0s
=> => transferring context: 2B                                                                                                                            0.0s
=> [base 1/2] FROM docker.io/library/python:3.9.18-slim-bullseye@sha256:9ac27d4ecadc3ef02f980a8e2b37c7e8cdbf24039c5eddd9f98aff00d23b9e03                  0.0s
=> [internal] load build context                                                                                                                          0.0s
=> => transferring context: 6.79kB                                                                                                                        0.0s
=> CACHED [base 2/2] RUN apt-get -qq update && apt-get install -qy --no-install-recommends git hostapd rfkill dnsmasq build-essential libssl-dev iproute  0.0s
=> CACHED [python-deps 1/4] RUN pip install --upgrade pipenv                                                                                              0.0s
=> CACHED [python-deps 2/4] COPY src/Pipfile /src/                                                                                                        0.0s
=> CACHED [python-deps 3/4] COPY src/Pipfile.lock /src/                                                                                                   0.0s
=> CACHED [python-deps 4/4] RUN cd /src && PIPENV_VENV_IN_PROJECT=1 pipenv install --deploy                                                               0.0s
=> CACHED [cloudcutter 1/2] COPY src /src                                                                                                                 0.0s
=> CACHED [cloudcutter 2/2] WORKDIR /src                                                                                                                  0.0s
=> exporting to image                                                                                                                                     0.0s
=> => exporting layers                                                                                                                                    0.0s
=> => writing image sha256:fefeb7209759414c26b9356a5cf949f5057d8eade8a4bc65b70b9942dc2f0c8d                                                               0.0s
=> => naming to docker.io/library/cloudcutter                                                                                                             0.0s
Successfully built docker image
Loading options, please wait...

Performing safety checks to make sure all required ports are available
Checking UDP port 53... Occupied by systemd-resolve with PID 6840.
Port 53 is needed to resolve DNS queries
Do you wish to terminate systemd-resolve? [y/N] y
Attempting to stop systemd-resolved.service
Checking UDP port 67... Available.
Checking TCP port 80... Available.
Checking TCP port 443... Available.
Checking TCP port 1883... Available.
Checking TCP port 8886... Available.
Attempting to stop firewalld.service
When done, enable with: sudo systemctl start firewalld.service
Safety checks complete.

Selected Device Slug: nous-a1-smart-plug
Selected Profile: oem-bk7231n-plug-1.1.8-sdk-2.3.1-40.00
Selected Firmware: OpenBeken-v1.17.697_bk7231n.ug.bin

================================================================================
Place your device in AP (slow blink) mode.  This can usually be accomplished by either:
Power cycling off/on - 3 times and wait for the device to fast-blink, then repeat 3 more times.  Some devices need 4 or 5 times on each side of the pause
Long press the power/reset button on the device until it starts fast-blinking, then releasing, and then holding the power/reset button again until the device starts slow-blinking.
See https://support.tuya.com/en/help/_detail/K9hut3w10nby8 for more information.
================================================================================

Redirecting to /bin/systemctl start NetworkManager.service
Scanning for open Tuya SmartLife AP

Found access point name: "A-C1AB", trying to connect...
Périphérique « wlp1s0 » activé avec « c2d7cdb2-f932-412d-85ee-9ec3130bf0a1 ».
Connected to access point.
Waiting 1 sec to allow device to set itself up...
Running initial exploit toolchain...
Exploit run, saved device config too!
output=/work/configured-devices/q3TYMpfQvcX7.deviceconfig
Saved device config in /work/configured-devices/q3TYMpfQvcX7.deviceconfig

================================================================================
Power cycle and place your device in AP (slow blink) mode again.  This can usually be accomplished by either:
Power cycling off/on - 3 times and wait for the device to fast-blink, then repeat 3 more times.  Some devices need 4 or 5 times on each side of the pause
Long press the power/reset button on the device until it starts fast-blinking, then releasing, and then holding the power/reset button again until the device starts slow-blinking.
See https://support.tuya.com/en/help/_detail/K9hut3w10nby8 for more information.
================================================================================

Redirecting to /bin/systemctl start NetworkManager.service
Scanning for open Tuya SmartLife AP
.
Found access point name: "A-C1AB", trying to connect...
Périphérique « wlp1s0 » activé avec « c2d7cdb2-f932-412d-85ee-9ec3130bf0a1 ».
Redirecting to /bin/systemctl start NetworkManager.service
.
Found access point name: "A-C1AB", trying to connect...
Périphérique « wlp1s0 » activé avec « c2d7cdb2-f932-412d-85ee-9ec3130bf0a1 ».
Connected to access point.
Configured device to connect to 'cloudcutterflash'
Device is connecting to 'cloudcutterflash' access point. Passphrase for the AP is 'abcdabcd' (without ')
Flashing custom firmware...

================================================================================
Wait for up to 10-120 seconds for the device to connect to 'cloudcutterflash'. This script will then show the firmware upgrade requests sent by the device.
================================================================================

Using WLAN adapter: wlp1s0
Configuration file: /dev/stdin
Using interface wlp1s0 with hwaddr d4:25:8b:19:e5:97 and ssid "cloudcutterflash"
wlp1s0: interface state UNINITIALIZED->ENABLED
wlp1s0: AP-ENABLED 
Using PSK v1 - Received PSK ID version 01
Processing endpoint /v2/url_config
Processing endpoint tuya.device.active
Processing endpoint tuya.device.dynamic.config.get
Processing endpoint tuya.device.uuid.pskkey.get
Processing endpoint atop.online.debug.log
Processing endpoint tuya.device.dynamic.config.get
Processing endpoint tuya.device.dynamic.config.ack
Processing endpoint tuya.device.upgrade.silent.get
Processing endpoint tuya.device.timer.count
Processing endpoint tuya.device.upgrade.status.update
Processing endpoint /files/OpenBeken-v1.17.697_bk7231n.ug.bin
Firmware update progress: 5%
Firmware update progress: 11%
Firmware update progress: 14%
Firmware update progress: 44%
Firmware update progress: 74%
[Firmware Upload] /files/OpenBeken-v1.17.697_bk7231n.ug.bin send complete, request range: bytes=0-504271/504272
Firmware update progress: 98%
Firmware file has been sent and MQTT reported a progress of nearly complete.  Waiting 15 seconds to ensure flashing completes.
Flashing should be complete.  It takes about 15 seconds for the device to reboot and verify the flash was valid.
Please wait about 30 seconds then look for signs of activity from the firmware you supplied (either watch for AP mode or check if it joined your network).
Device MAC address: cc:8c:bf:d7:c1:ab

Ça semble avoir marché ! Notons l'adresse MAC en dernière ligne, elle peut servir à reconnaître la prise plus tard. A ce stade j'ai du redémarrer mon laptop car mon wifi ne marchait plus.

Ensuite un nouveau réseau wifi (sans mot de passe) est apparu, il s'apelle OpenBK7231N_********. Je m'y connecte et ouvre un navigateur vers http://192.168.4.1/ , miracle:

screenshot OpenBeken

Je clique sur "Config" puis "Configure Wifi & Web", car ce sera plus pratique que la prise rejoigne le réseau wifi habituel. Je reviens aussi sur mon wifi habituel, mais il va falloir retrouver l'IP de la prise: mon réseau local utilise des IP en 192.168.1.*, donc je peux lister les périphériques connectés avec la commande suivante :

$ nmap -sP 192.168.1.0/24 | grep OpenBK
Nmap scan report for OpenBK7231N_BFD7C1AB.lan (192.168.1.102)

Le BFD7C1AB correspond à la fin de l'adresse MAC notée plus haut. Donc je dois aller sur http://192.168.1.102/. Sur cette page il faut surtout passer par Launch Web Application, et dans cette nouvelle interface atteindre l'onglet Import.

Voici le template que j'ai utilisé dans la boite 1 :

{
    "vendor": "Tuya",
    "bDetailed": "0",
    "name": "Konyks Priska Mini 3",
    "model": "BK7231N + BL0942",
    "chip": "BK7231N",
    "flags": "1024",
    "keywords": [
      "BL0942",
      "fr",
    ],
    "pins": {
      "6": "LED_n;1",
      "9": "Btn;1",
      "26": "Rel;1"
    },
    "command": "startDriver BL0942",
    "image": "https://obrazki.elektroda.pl/8044484300_1730546950.jpg",
    "wiki": "https://www.elektroda.com/rtvforum/topic4084537.html"
  }

reste à cliquer à droite sur Clear OBK and apply new script from above. La LED s'allume !

Après avoir branché une lampe, pour tester, revenons sur l'interface principale : il y a un bouton pour allumer/éteindre la lampe, avec les mesures d'énergie en direct:

La prise est complètement fonctionnelle avec OpenBeken

Je suis aussi passé par Configure Startup pour choisir si la prise doit être allumée ou non lorsqu'on la branche (ou si le courant revient).

Relier à OpenHAB en MQTT

L'interface Web propose aussi Configure MQTT, où l'on peut entrer les paramètres du broker MQTT, ainsi que le nom d'un topic pour les commandes et les mesures. J'ai mis /home/konyks pour "Client Topic" et "Group Topic", on va retrouver ce préfixe dans les canaux MQTT.

Coté OpenHAB j'ajoute une Thing qui utilise le MQTT Binding. Je sélectionne Generic MQTT Thing. En plus de lui donner un ID/label/location, je précise que son Parent Bidge est mon broker MQTT, et je clique sur Show advanced pour préciser

Une fois créée, il va falloir ajouter deux Channels.

La prise peut aussi donner la consommation cumulée du jour via /home/konyks/energycounter_today/get, mais je ne suis pas sûr d'avoir saisi le mode de calcul. Vous trouverez plusieurs canaux de ce genre avec MQTT Explorer.

Conclusion

J'étais un peu surpris de découvrir que cette prise à beaucoup d'autres clones, que d'autres sont même parvenus à démonter. On dirait que dans chaque pays, il y a un revendeur Tuya.

En tout cas, ma prise fonctionne avec OpenHab, mais cela m'a pris beaucoup trop de temps... et j'ai peut être eu de la chance d'avoir un modèle pas trop à jour.

On peut en parler sur le fédiverse.