Mon système domotique est entièrement contrôlable depuis l’intérieur comme l’extérieur de la maison, donc depuis le réseau local ou depuis Internet. Il est donc possible d’allumer ou éteindre une lampe ou encore activer/désactiver l’alarme à distance sans être présent dans la maison.
Ces opérations sont possibles car le serveur qui héberge l’interface web est branché sur le réseau local de la maison.
Problème : si la connexion internet tombe chez moi, je ne suis plus informé d’une alarme, je ne peux plus agir dessus.
La solution selon moi est de pouvoir déclencher des scénarios à l’aide d’un téléphone mobile, qui, lui, sera toujours joignable.
Comment donc déclencher des opérations à l’aide d’un mobile ?
- Par le fait d’être appelé : trop dangereux, n’importe qui connaissant le numéro pourrait déclencher l’action, sans même s’en apercevoir.
- Par commande vocale : plutôt complexe, il faut de la reconnaissance vocale derrière … peut être plus tard
- par réception d’un SMS : parfait ! Un ordinateur sait très bien gérer les éléments textuels
Le matériel utilisé
- une carte SIM
- un nokia 3220 (ressorti d’un tiroir où il dort depuis 3 ans !)
- un câble USB/série DKU acheté pour trois fois rien en Chine à l’époque
Communication avec le PC
Tout d’abord il faut que le PC reconnaisse le téléphone. L’objectif initial était de le faire fonctionner sous linux.
Apres plusieurs jours d’acharnement entre le drivers, le firmware du câble etc j’ai reporté cette étape à plus tard et suis donc passé sous Windows.
J’ai pu retrouver dans les méandres d’internet un drivers fournit par TI qui fonctionne.
Drivers TIUSB3410 : TEXAS-INSTRUMENTS_TUSB3410-U_A03_R286478.exe
Tout d’abord, vérifions que le dialogue avec le téléphone fonctionne.
- Ouvrez un Hyper Terminal (si vous êtes sous Win >Vista il n’est plus présent par défaut, vous pourrez facilement le retrouver via google)
- Ouvrez une connexion standard sur le port COM monté par Windows sur le cable USB
- Lancez la commande « AT » et vérifiez que vous avez bien un « OK » en retour
La démarche complète peut être récupérée sur le site wiki pour développeurs de nokia.
Scriptage
Une fois que l’on arrive à dialoguer à l’aide des commandes AT standard, il est possible d’écrire un script pour automatiser la récupération de message.
J’ai choisi de le faire en python car une librairie de dialogue Série existe déjà : pySerial. De plus, je souhaite à terme brancher le telephone sur une machine Linux, Python est portable d’un OS à l’autre.
Ouverture du flux
Voici un premier script qui ouvre simplement le flux sur le port COM3 sous Windows et essaye 5 fois d’envoyer une commande AT.
#initialization and open the port #possible timeout values: # 1. None: wait forever, block call # 2. 0: non-blocking mode, return immediately # 3. x, x is bigger than 0, float allowed, timeout block call ser = serial.Serial() ser.port = "\\.\COM3" #ser.port = "/dev/ttyS2" ser.baudrate = 9600 ser.bytesize = serial.EIGHTBITS #number of bits per bytes ser.parity = serial.PARITY_NONE #set parity check: no parity ser.stopbits = serial.STOPBITS_ONE #number of stop bits ser.timeout = 2 #non-block read ser.xonxoff = False #disable software flow control ser.rtscts = True #disable hardware (RTS/CTS) flow control ser.dsrdtr = True #disable hardware (DSR/DTR) flow control ser.writeTimeout = 2 #timeout for write try: ser.open() except Exception, e: print "error open serial port: " + str(e) exit() if ser.isOpen(): try: ser.flushInput() #flush input buffer, discarding all its contents ser.flushOutput()#flush output buffer, aborting current output #and discard all that is in buffer #init print("connecting") print("---------------------------------------------") for i in range(1,5): print(" + try " + str(i) + "/5 :") ser.write("AT\x0D") response = ser.readline() print(" read data: " + response) if "OK" in response: print(" connexion established") break ser.close() except Exception, e1: print "error communicating...: " + str(e1) else: print "cannot open serial port "
Commandes AT
Les commandes enchaînées sont les suivantes :
AT : tester de dialogue avec le telephone
AT+CMGF=1 : permet de se mettre en mode texte pour SMS
AT+CMGL= »ALL » : permet de lister tous les messages reçus
AT+CMGD=1 : permet de supprimer le message dont l’identifiant est 1.
Script final
Principe :
- test de la connexion au téléphone
- configuration en mode texte SMS
- récupération des messages SMS
- stockage des messages dans un tableau python
- traitement des messages stockés (en fonction d’un émetteur ou d’un contenu ou encore du temps, il est possible d’enrichir le script)
- suppression des messages traités
- bouclage
Script:
#!/usr/bin/python import serial, time, urllib def supprimer_msg (ser, ID_msg): etat_final = False ser.flushInput() ser.flushOutput() print(" [supprimer_msg] write data: AT+CMGD="+str(ID_msg)+"\x0D") for i in range (1,5): ser.write("AT+CMGD="+str(ID_msg)+"\x0D") response = ser.readline() print(" [supprimer_msg] read data: " + response) if "OK" in response: print(" ok recieved") etat_final = True break return etat_final def traitement_message_recu( ser ): messages_tab = [] current_message = 0 for i in range (1,15): response = ser.readline() print(" [traitement_message_recu] read data: " + response) if "OK" in response: print(" OK recieved") break elif "ERROR" in response: print(" ERROR") break elif "+CMGL" in response: response = response.translate(None, '"') data_msg = response.split(",") current_message = data_msg[0].translate(None, '+CMGL: ') elif len(response) < 3: print(" skip empty line") continue else: print(" Message Processing ID [" + str(current_message) + "]") messages_tab.append( [current_message, str(data_msg[2]), data_msg[4], response] ) # data_msg # data_msg[0] : ID interne telephone # data_msg[1] : from # data_msg[2] : date recieved # data_msg[3] : message content print("Processing stored messages") for message in messages_tab: print("message [" + str(message[0]) + "] from ["+ message[1] +"] at ["+ message[2] +"]: " + message[3]) # if data_msg[2] != "+33123456789": # print ("message "+ current_message + " : expediteur inconnu :" + data_msg[2]) print("appel de webservice_phone"); urllib.urlopen("http://serveur_domotique/dhomeCore/ws_phone.php?id=xxxfrom="+urllib.quote(message[1],"")+"&date="+urllib.quote(message[2],"")+"&content="+urllib.quote(message[3],"")+"&type=sms"); print("call http://serveur_domotique/dhomeCore/ws_phone.php?id=xxx&from="+urllib.quote(message[1],"")+"&date="+urllib.quote(message[2],"")+"&content="+urllib.quote(message[3],"")+"&type=sms"); if "coucou" in message[3]: print("appel de webservice_action"); urllib.urlopen("http://serveur_domotique/dhomeCore/ws_action.php?id=xxx&valeur1="+message[3]); print("suppression du message [" + message[0] + "]") supprimer_msg(ser,message[0]) #+CMGL: 1,"REC READ","+33123456789",,"12/12/15,17:54:41+04" urllib.urlcleanup() return #initialization and open the port #possible timeout values: # 1. None: wait forever, block call # 2. 0: non-blocking mode, return immediately # 3. x, x is bigger than 0, float allowed, timeout block call ser = serial.Serial() ser.port = "\\.\COM3" #ser.port = "/dev/ttyS2" ser.baudrate = 9600 ser.bytesize = serial.EIGHTBITS #number of bits per bytes ser.parity = serial.PARITY_NONE #set parity check: no parity ser.stopbits = serial.STOPBITS_ONE #number of stop bits ser.timeout = 2 #non-block read ser.xonxoff = False #disable software flow control ser.rtscts = True #disable hardware (RTS/CTS) flow control ser.dsrdtr = True #disable hardware (DSR/DTR) flow control ser.writeTimeout = 2 #timeout for write try: ser.open() except Exception, e: print "error open serial port: " + str(e) exit() if ser.isOpen(): try: ser.flushInput() #flush input buffer, discarding all its contents ser.flushOutput()#flush output buffer, aborting current output #and discard all that is in buffer #init print("connecting") print("---------------------------------------------") for i in range(1,5): print(" + try " + str(i) + "/5 :") ser.write("AT\x0D") response = ser.readline() print(" read data: " + response) if "OK" in response: print(" connexion established") break #config print("configuring +CMGF=1") print("---------------------------------------------") for i in range(1,5): print(" + try " + str(i) + "/5 :") ser.write("AT+CMGF=1\x0D") print(" write data: AT+CMGF=1\x0D") response = ser.readline() print(" read data: " + response) if "OK" in response: print(" configuration completed") break print("looping") print("---------------------------------------------") while True: ser.flushInput() ser.flushOutput() print(" get messages") ser.write("AT+CMGL=\"ALL\"\x0D") response = ser.readline() print(" read data: " + response) traitement_message_recu(ser) time.sleep(20) ser.close() except Exception, e1: print "error communicating...: " + str(e1) else: print "cannot open serial port "
Salut
intéressant tout ça, je pense que bien entendu il faut un abonnement mobile pour la réception des sms? 😀
Salut,
Hé bien non ! Une carte pré payée b&you fait parfaitement l’affaire
https://www.b-and-you.fr/carte-prepayee
Pas de limite de validité, il faut juste passer un coup de fil par an 😉