Nous utilisons un commutateur sans fil 433 MHz pour contrôler le PC

Bonjour Geektimes Habr.

Chez moi, plusieurs commutateurs sans fil à 433 MHz se sont accumulés à la maison, il est devenu intéressant de savoir s'ils peuvent être utilisés pour n'importe quelle tâche, par exemple, pour contrôler un ordinateur ou pour intégrer une «maison intelligente» dans le système.

Ces commutateurs sont pratiques pour leur faible coût et leur fonctionnement stable, ils ressemblent à ceci:



Comment cela fonctionne et ce qui peut être fait avec eux (les hussards se taisent :), détails sous la coupe.

Théorie


Je dois dire tout de suite comment fonctionne un tel interrupteur, je ne sais pas, bien que je suppose à ce sujet. Vous devrez donc faire un peu de rétro-ingénierie.

Tout d'abord, le signal doit être reçu, pour lequel nous utilisons le récepteur RTL-SDR déjà bien connu, souvent appelé simplement un «sifflet» pour les radio-amateurs. Cet appareil, au prix de 10 $ seulement, vous permet de recevoir des signaux radio dans une plage d'environ 50 à 1250 MHz, pour nous ce dont nous avons besoin. Le sujet est ancien, mais si quelqu'un ne l'a pas lu, lisez-le .

Nous prenons la première étape de l'analyse - nous examinons attentivement le commutateur. Nous constatons qu'au dos du boîtier, il est écrit «Made in China» (qui aurait pensé?) Et, plus important encore, la fréquence 433 MHz est indiquée. Vous pouvez maintenant connecter le récepteur SDR, démarrer SDR # et vous assurer que les données sont bien transmises.



La symétrie du signal sur le spectre suggère la présence d'une modulation AM. À propos, un signal «étranger» plus faible est visible à droite - ils peuvent également être reçus et décodés, ils seront discutés plus en détail séparément. Mais revenons au signal. Nous l'enregistrons au format WAV habituel et appuyons sur les boutons de la télécommande - par exemple, j'ai appuyé sur les boutons ON et OFF sur le canal «1».

Ouvrez le fichier son dans n'importe quel éditeur audio et utilisez un autre outil d'analyse professionnel, Paint, pour comparer les signaux. Nous plaçons 2 signaux de différents boutons l'un au-dessus de l'autre pour voir la différence:



Il est facile de voir que nous avons la séquence de bits habituelle, dont la différence est juste sur un bit, correspondant au bouton ON ou OFF. Pendant que le bouton est enfoncé, l'interrupteur répète simplement cycliquement cette séquence sur l'air à une vitesse de 20 fois par seconde. Bon marché et facile, même si une séquence est déformée pendant la transmission, l'autre sera acceptée.

À partir de cela, en passant, une conclusion importante peut être tirée - les signaux de ces commutateurs (nous parlons de modèles bon marché) sont transmis «tels quels» sans aucune authentification, protection ou cryptage. Un tel interrupteur ou une prise sans fil avec un tel interrupteur ne doit pas être utilisé pour certaines fonctions importantes, par exemple pour allumer des radiateurs puissants ou encore plus pour ouvrir la porte d'entrée ou le garage. Ce n'est même pas une question de pirates (la chance que quelqu'un pirate ma maison sans fil, j'estime moins que la chance de tomber sur ma maison ISS), mais qu'un voisin peut accidentellement acheter le même commutateur, et les codes peuvent correspondre ( cependant sur l'interrupteur il y a un choix entre 4 canaux). D'après mon expérience d'utilisation, 2-3 fois par an, le disjoncteur s'est déclenché «lui-même», soit un obstacle, soit un signal éloigné du même modèle a été réellement reçu.

Bien sûr, cela ne s'applique pas aux systèmes plus complexes, tels que Lora ou Philips Hue, tout est correct avec le cryptage.

Mais revenons à notre tâche. Vous pouvez écrire un décodeur de tels signaux vous-même, mais heureusement, cela a déjà été fait avant nous, dans un projet appelé "rtl_433". Le programme a été créé à l'origine pour Linux, la version Windows peut être téléchargée à la version Linux peut être téléchargée à partir de GitHub .

Nous démarrons le programme à partir de la ligne de commande: "rtl_433.exe -F json"



Nous avons obtenu les données, il reste à écrire un programme pour leur traitement.

Raspberry pi


La première chose intéressante à considérer est le Raspberry Pi. Pour installer rtl_433 sur Raspbian, décompressez l' archive et exécutez les commandes suivantes.

sudo apt-get install libtool libusb-1.0.0-dev librtlsdr-dev rtl-sdr build-essential autoconf cmake pkg-config cd rtl_433/ autoreconf --install ./configure make make install 

La deuxième étape consiste à écrire un programme qui recevra ces données et, en fonction de celles-ci, à effectuer les actions nécessaires. Le code Python est assez simple:

 from __future__ import print_function import os, sys, io import json import subprocess print("RTLSDR listening started") transmitter_name = "Waveman Switch Transmitter" transmitter_channel = 1 proc = subprocess.Popen(["rtl_433 -F json"], stdout=subprocess.PIPE, shell=True) while True: try: line = proc.stdout.readline().encode('ascii','ignore') proc.poll() data = json.loads(line) print(data) m,st,ch,btn= data['model'],data['state'],data['channel'],data['button'] if m==transmitter_name and ch==transmitter_channel and btn==1 and st=='on': print("ON") elif m==transmitter_name and ch==transmitter_channel and btn==1 and st=='off': print("OFF") except KeyboardInterrupt: break except: pass print("RTLSDR listening done") 

Pour exécuter le code, vous devez l'enregistrer dans un fichier (par exemple rtl_listen.py) et exécuter la commande "python rtl_listen.py".

Comme vous pouvez le voir, le programme démarre le processus en utilisant subprocess.Popen et en lit les données. Ensuite, tout est simple, le code est assez lisible et il ne sera pas difficile de faire des changements. Dans cet exemple, lorsque le bouton «1» est enfoncé, le message print («ON») s'affiche, à la place, vous pouvez faire autre chose, par exemple, activer la broche GPIO, allumer le relais, envoyer des données au serveur, etc. Avant de l'utiliser, vous devrez le changer en même temps nom transmetteur_nom dans le nom du modèle de la console qui sera utilisé.

Soit dit en passant, le récepteur RTL-SDR lui-même, par rapport au Raspberry Pi, ressemble à ceci:



Windows


Malheureusement, sous Windows 10, le code ci-dessus ne fonctionnait pas. Mais comme une recherche sur github l'a suggéré, la lecture asynchrone des données d'un flux distinct fonctionne. Pourquoi, c'était trop paresseux pour le découvrir, je vais juste mettre le code de travail sous le spoiler.

Code source
 from __future__ import print_function import os, sys import subprocess import time import threading import Queue import json class AsynchronousFileReader(threading.Thread): # Helper class to implement asynchronous reading def __init__(self, fd, queue): assert isinstance(queue, Queue.Queue) assert callable(fd.readline) threading.Thread.__init__(self) self._fd = fd self._queue = queue def run(self): # The body of the tread: read lines and put them on the queue. for line in iter(self._fd.readline, ''): self._queue.put(line) def eof(self): # Check whether there is no more content to expect return not self.is_alive() and self._queue.empty() def replace(string): while ' ' in string: string = string.replace(' ', ' ') return string def read_rtl_data(): process = subprocess.Popen(["rtl_433.exe", "-F", "json"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Launch the asynchronous readers of stdout and stderr. stdout_queue = Queue.Queue() stdout_reader = AsynchronousFileReader(process.stdout, stdout_queue) stdout_reader.start() stderr_queue = Queue.Queue() stderr_reader = AsynchronousFileReader(process.stderr, stderr_queue) stderr_reader.start() transmitter_name = "Waveman Switch Transmitter" transmitter_channel = 1 # Check the queues if we received some output while not stdout_reader.eof() or not stderr_reader.eof(): # Show what we received from standard output. while not stdout_queue.empty(): line = stdout_queue.get() print("Line1:", repr(line)) data = json.loads(line) # print("Data:", repr(line)) m,st,ch,btn= data['model'],data['state'],data['channel'],data['button'] if m==transmitter_name and ch==transmitter_channel and btn==1 and st=='on': print("ON") elif m==transmitter_name and ch==transmitter_channel and btn==1 and st=='off': print("OFF") # Show what we received from standard error. while not stderr_queue.empty(): line = replace(stderr_queue.get()) print("Line2:", line) # Sleep a bit before asking the readers again. time.sleep(0.1) stdout_reader.join() stderr_reader.join() # Close subprocess' file descriptors. process.stdout.close() process.stderr.close() if __name__ == '__main__': print("RTLSDR listening started") read_rtl_data() print("RTLSDR listening done") 


Avec ce code, nous pouvons utiliser toutes les actions dans le gestionnaire, la logique est la même que dans le code du Raspberry Pi.

Exemple : supposons que nous ayons un ordinateur dédié à un home cinéma et que nous voulions l'éteindre en appuyant sur le bouton de la télécommande. Remplacez le code 'print ("OFF")' par

  os.system('shutdown -s') sys.exit(0) 

Après quoi, l'ordinateur s'éteindra en appuyant sur le bouton approprié. Bien sûr, en plus de «shutdown -s», vous pouvez utiliser n'importe quelle autre commande Windows, il suffit de considérer que les commandes seront envoyées à plusieurs reprises, tandis que le bouton de la télécommande est enfoncé, pour éviter une telle duplication, vous devez améliorer le code.

Conclusion


Comme vous pouvez le voir, tout est assez simple et il y a de la place pour l'expérimentation. Enfin, un petit bonus pour ceux qui ont lu jusqu'ici. À 433 MHz, il existe un grand nombre de périphériques différents que rtl_433 peut décoder, vous pouvez simplement laisser le programme fonctionner pendant plusieurs heures et voir ce qui «attrape». Sous le spoiler, un exemple d'un tel journal, enregistré plus tôt:

Journal
2018-01-10 21:15:17 : Prologue sensor : 5 : 15
Channel: 1
Battery: OK
Button: 0
Temperature: 6.00 C
Humidity: 11 %

2018-01-10 21:15:28 : inFactory sensor
ID: 71
Temperature: 6.67 °C
Humidity: 99 %

2018-01-10 21:16:07 : Toyota : TPMS : 61511475 : 60e5006b : CRC

2018-01-10 21:20:33 : Prologue sensor : 5 : 15
Channel: 1
Battery: OK
Button: 0
Temperature: 6.00 C
Humidity: 11 %
: Waveman Switch Transmitter
id: A
channel: 2
button: 1
state: on
: Waveman Switch Transmitter
id: A
channel: 2
button: 1
state: on
: Waveman Switch Transmitter
id: A
channel: 2
button: 1
state: on

2018-01-10 21:21:21 : Akhan 100F14 remote keyless entry
ID (20bit): 0x41
Data (4bit): 0x4 (Mute)
: Waveman Switch Transmitter
id: A
channel: 2
button: 1
state: off

2018-01-10 21:32:31 : Ford : TPMS : 00268b1f : a34a0e : CHECKSUM
2018-01-10 21:32:32 : Ford : TPMS : 00268a5c : 9c440e : CHECKSUM
2018-01-10 21:32:37 : Ford : TPMS : 016dbfce : 99430e : CHECKSUM
2018-01-10 21:32:39 : Ford : TPMS : 002671a0 : 9c4a0e : CHECKSUM


Il existe des données intéressantes, par exemple, la pression des pneus de la voiture d'un voisin (TPMS, système de surveillance de la pression des pneus), ou la température extérieure +6 du capteur de quelqu'un d'autre. Cela permet par exemple d'afficher la température extérieure si les voisins ont accidentellement une station météo compatible avec ce protocole.

Toutes les expériences réussies.

Avertissement : De toute évidence, l'utilisation du SDR et du traitement numérique pour lire les signaux de modulation OOK est essentiellement un coup de feu sur des moineaux. Peut-être que sur aliexpress, il existe des récepteurs standard pour 1-2 $ qui font la même chose, avec un coût inférieur et une consommation d'énergie inférieure. Si quelqu'un connaît de tels modèles, écrivez dans les commentaires.

Source: https://habr.com/ru/post/fr414285/


All Articles