Je vous ai présenté il y a quelque temps le boîtier Pironman de SunFounder. C’est un superbe boîtier type PC avec des faces latérales transparentes qui laissent voir des LEDs colorées. Avec la carte NadHAT MK2 4G de Garatronic je me suis dit qu’on pouvait trouver une application regroupant les deux objets, pour piloter les LEDs par SMS.
Au sommaire :
Piloter les LEDs de Pironman par SMS avec la carte NadHAT MK2 4G de Garatronic
A quoi ça sert ?
A quoi ça sert de piloter les LEDs d’un boîtier de Raspberry Pi par SMS ?
A rien !
Et comme beaucoup de projets makers, quand ça ne sert à rien c’est indispensable …
Non, allez, je vous explique : Vous avez une maison au bout d’un chemin où Internet n’arrive pas (une zone blanche, c’est pour ça qu’il y a de la neige). Avec un Raspberry Pi et la carte 4G NadHAT MK2 de Garatronic vous pouvez connecter le Raspberry Pi à la 4G et naviguer sur Internet, mais aussi piloter une installation domotique par SMS.
Par exemple vous mettrez la chaudière en fonctionnement avant votre arrivée, vous ouvrirez les volets… En retour vous recevrez un accusé de réception et des valeurs de votre choix (température, humidité, détecteur de flamme de la chaudière…).
La carte NadHAT MK2 et le Raspberry Pi
La carte NadHAT MK2 dispose d’un connecteur qui permet de la raccorder au GPIO et d’utiliser le port série disponible sur le Raspberry Pi.
Pour montrer en exposition ce n’est pas la meilleure solution pour moi car avec le boîtier Pironman la carte serait impossible à monter à cause du Ventirad. De plus le port série est plus lent que l’USB et en 4G ça fait goulet d’étranglement.
J’ai donc choisi de coller la carte NadHAT MK2 4G au dessus du boîtier Pironman avec un double face.
Les commandes AT ou Hayes
Pour un « vieux » informaticien comme moi, les commandes du modem Hayes, ou commandes AT c’est tout un volet de mon travail à une époque lointaine (au millénaire dernier) parce que tous les modems parlaient ce langage. Si vous démarrez avec ces commandes qui commencent par… AT , je vous laisse les découvrir. Il y a des commandes « universelles » et certaines qui sont propres à certains constructeurs, parce qu’elles n’existent que chez CE constructeur ou qu’elles sont « un peu » aménagées pour répondre à ses besoins.
Le Programme Python
Comme je dis toujours, je suis un maker, pas un développeur. L’objectif de mes programmes, c’est de faire fonctionner le projet. Après si vous y regardez de près vous trouverez des trucs pas jolis, des choses qu’on ne fait pas… Moi, si ça fonctionne ça me va. Le programme est disponible sur GitHub, brut de fonderie et il ne tient qu’à vous de l’améliorer et de le redistribuer (j’ajouterai le lien avec plaisir !)
Il y a du debuggage de maker, oui, des print() ! pour voir par où passe le programme et m’aider à trouver mes conneries erreurs… Libre à vous de les enlever également. Mais pour ceux qui sont passés sur le stand à Vitré et ont changé les couleurs du Piroman par SMS, le programme a bien fonctionné 😉
A noter des sleep() qui laissent le temps à la carte de réagir. vous les supprimerez si ça vous chante, mais ça risque de moins bien marcher…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 |
# -*- coding : utf8 -*- # NadHat_MK2.py # https://www.python-exemplarisch.ch/index_en.php?inhalt_links=navigation_en.inc.php&inhalt_mitte=raspi/en/gsm.inc.php # NadHAT MK2 sur boitier Pironman # Attent un prénom puis une couleur # Affiche la couleur dans le Pironman import serial import io import time import os import subprocess import sys import shlex from gpiozero import CPUTemperature liste_couleurs = ['rouge', 'vert', 'bleu', 'jaune', 'mauve', 'blanc'] liste_hexa = ['FF000', '00FF00', '0000FF', 'FFFF00', 'FF00FF', 'FFFFFF'] tel_carte = "+336xxxxxx13" SERIAL_PORT = "/dev/ttyUSB2" signal = serial.Serial( port=SERIAL_PORT, baudrate=9600, bytesize=8, parity='N', timeout=1, stopbits=1, rtscts=False, dsrdtr=False ) signal_text = io.TextIOWrapper(signal, newline='\r\n') # Configurer la carte pour les SMS # Passer en mode ECHO OFF print("\r\nMode ECHO OFF") signal.write(str.encode('ATE0\r')) rep = signal.read(signal.inWaiting()) print(rep) # Stocker les SMS en mémoire flash print("\r\nStocker les SMS dans la mémoire flash") signal.write(str.encode('AT+CPMS="ME", "ME", "ME"\r')) rep = signal.read(signal.inWaiting()) print(rep) signal.write('AT+CSCS="IRA"\r'.encode()) # mode IRA time.sleep(1) rep = signal.read(signal.inWaiting()) print(rep) signal.write("AT+CMGF=1\r\n".encode()) # set to text mode time.sleep(1) rep = signal.read(signal.inWaiting()) print(rep) signal.write('AT+CMGD=1,4\r\n'.encode()) # delete all SMS time.sleep(1) rep = signal.read(signal.inWaiting()) print(rep) # ======================================================================= # On envoie un SMS sur la carte elle même pour récupérer l'heure GSM # et mettre le Raspberry Pi à l'heure s'il n'est pas connecté à un réseau # Envoyer SMS au N° de la carte print ('AT+CMGS="'+ tel_carte + '"') signal.write(('AT+CMGS="' + tel_carte +'"\r\n').encode()) time.sleep(3) rep = signal.read(signal.inWaiting()) print("Apres CGMS : \r\n",rep.decode()) time.sleep(3) sms = "SMS\r\n" signal.write(sms.encode()) time.sleep(1) rep = signal.read(signal.inWaiting()) print("SMS Carte envoyé : \r\n",rep.decode()) signal.write(chr(26).encode()) time.sleep(1) rep = signal.read(signal.inWaiting()) print("Fin SMS et OK : \r\n",rep.decode()) time.sleep(1) # On lit le SMS signal.write("AT+CMGR=1\r".encode()) time.sleep(1) reply = signal.read(signal.inWaiting()) print ("SMS sur la carte reçu : \n\r", reply) time.sleep(2) # Extraire les données du message data = reply.decode() # Séparer en fonction de CR LF decoupe=(data.split("\r\n")) #print ("Decoupe : ", decoupe) message = decoupe[2] print("Message : ", message) print("Message Type : ",type(message)) #Telephone de l'appelant tel = data[23:35] #print(type(tel)) print ("Téléphone : ", tel) # Date fournie par le réseau date = data[41:58] print("Date : ", date) #Créer chaine date_heure an= data[41:43] print(type(an)) mois=data[44:46] jour=data[47:49] heure=data[50:52] minute=data[53:55] seconde=data[56:58] # Traitement de la date et de l'heure date_sms = jour + " " + mois + " 20" + an heure_sms = heure + ":" + minute + ":" + seconde print("Date du SMS : ", date_sms) print("Heure du SMS : ", heure_sms) # Effacer tous les SMS signal.write('AT+CMGD=1,4\r\n'.encode()) # delete all SMS time.sleep(1) rep = signal.read(signal.inWaiting()) print("Efface les SMS : \r\n",rep.decode()) # Mettre l'OS à l'heure # Créer la chaine date Heure date_heure = "'20"+an+"-"+mois+"-"+jour+" "+heure+":"+minute+":"+seconde+"'" # Créer la chaine date Heure #date_heure = "'2023-01-17 11:00:00'" chaine = "sudo date -s " + date_heure print ("Chaine : ", chaine) # Arrêter la mise à l'heure NTP print("Arret NTP") subprocess.run(["sudo", "timedatectl", "set-ntp", "0"]) time.sleep(1) print("Mofifier heure système ") #subprocess.call(shlex.split("sudo date -s '2023-01-17 19:00:00'")) subprocess.call(shlex.split(chaine)) print ("Heure modifiée ") time.sleep(1) # On se met en attente du SMS qui va déclencher le programme reply = signal.read(signal.inWaiting()) # Clean bu print ("\r\n=============== EN ATTENTE DE SMS... ==============================") while True: reply = signal.read(signal.inWaiting()) #print(reply, len(reply)) # Est-ce qu'on a reçu un SMS ? if len(reply) != 0: signal.write("AT+CMGR=1\r".encode()) time.sleep(1) reply = signal.read(signal.inWaiting()) print ("SMS reçu : \n\r", reply) time.sleep(2) # Extraire les données du message data = reply.decode() # Séparer en fonction de CR LF decoupe=(data.split("\r\n")) #print ("Decoupe : ", decoupe) message = decoupe[2] print("Message : ", message) print("Message Type : ",type(message)) #Telephone de l'appelant tel = data[23:35] #print(type(tel)) print ("Téléphone : ", tel) # Date fournie par le réseau date = data[41:58] print("Date : ", date) #Créer chaine date_heure an= data[41:43] print(type(an)) mois=data[44:46] jour=data[47:49] heure=data[50:52] minute=data[53:55] seconde=data[56:58] # Now create new time string in the form MMDDhhmmYYYY for the date program date_sms = jour + " " + mois + " 20" + an heure_sms = heure + ":" + minute + ":" + seconde print("Date du SMS : ", date_sms) print("Heure du SMS : ", heure_sms) # Effacer tous les SMS signal.write('AT+CMGD=1,4\r\n'.encode()) # delete all SMS time.sleep(1) rep = signal.read(signal.inWaiting()) print("Efface les SMS : \r\n",rep.decode()) # Enlever les espaces avant/après message message = message.strip() #print(type(message)) # Envoyer la réponse au N° appelant print ('AT+CMGS="'+ tel + '"') signal.write(('AT+CMGS="' + tel +'"\r\n').encode()) time.sleep(3) rep = signal.read(signal.inWaiting()) print("Apres CGMS : \r\n",rep.decode()) time.sleep(3) choix_couleur = "\r\nChoisis ta couleur : \r\n Rouge, vert, bleu, jaune, mauve, blanc et envoie la par SMS" retour = "Bonjour " + message + choix_couleur +"\r\n" print ("Retour : ", retour) signal.write(retour.encode()) time.sleep(1) rep = signal.read(signal.inWaiting()) print("Texte retour envoyé : \r\n",rep.decode()) signal.write(chr(26).encode()) time.sleep(1) rep = signal.read(signal.inWaiting()) print("Fin SMS et OK : \r\n",rep.decode()) time.sleep(1) # Attendre la réponse +CMGR # Effacer tous les SMS signal.write('AT+CMGD=1,4\r\n'.encode()) # delete all SMS time.sleep(1) # Attendre la réponse du participant #print(reply, len(reply)) # Est-ce qu'on a reçu un SMS ? reply = signal.read(signal.inWaiting()) print(type(reply)) print("Reply avant le while : ",reply) while bytes("+CMGR", 'utf_8') not in reply : signal.write("AT+CMGR=1\r".encode()) time.sleep(1) reply = signal.read(signal.inWaiting()) data = reply.decode() decoupe=(data.split("\r\n")) time.sleep(1) print ("Decoupe : ", decoupe, "\r\nLongueur de Découpe : ", len(decoupe)) for morceau in decoupe : print("Decoupe : ", morceau) # Si la ligne 2 contient CMTI lire ligne 4 # Sinon lire ligne 2 """if len(decoupe) == 8 : couleur = decoupe[4] if len(decoupe) == 6 : couleur = decoupe[2] if len(decoupe) == 7 : couleur = decoupe[3]""" if "CMTI" in decoupe[1] : couleur = decoupe[4] else : couleur = decoupe[2] print("Couleur reçue : \r\n",couleur) # Vérifier si la couleur est présente rep_couleur = couleur.strip() # Supprimer les espaces avant/après rep_couleur = rep_couleur.lower() # mettre la réponse en minuscules # Effacer tous les SMS signal.write('AT+CMGD=1,4\r\n'.encode()) # delete all SMS time.sleep(1) if rep_couleur in liste_couleurs : # Lire la température CPU cpu = CPUTemperature() print("Température : ", cpu.temperature) # La couleur existe dans la liste print("La couleur existe : ", rep_couleur) # Répondre que la couleur est OK # Préparer la date date_sms = jour + "/" + mois + "/" + "20" + an heure_sms = heure + ":" + minute date = date_sms + heure_sms degre = "C" chaine = date_sms + "\r\n" + heure_sms + "\r\n" + "OK, je passe en couleur " + rep_couleur + "\r\n" + "La température du CPU est : " + "\r\n" + str(int(cpu.temperature)) + degre # Envoyer la réponse au N° appelant print ('AT+CMGS="'+ tel + '"') signal.write(('AT+CMGS="' + tel +'"\r\n').encode()) time.sleep(3) rep = signal.read(signal.inWaiting()) print("Apres CGMS : \r\n",rep.decode()) time.sleep(3) signal.write(chaine.encode()) time.sleep(1) rep = signal.read(signal.inWaiting()) print("Texte confirmation envoyé : \r\n",rep.decode()) signal.write(chr(26).encode()) time.sleep(1) rep = signal.read(signal.inWaiting()) print("Fin confirmation : \r\n",rep.decode()) time.sleep(1) # Récupérer l'indice de la couleur dans la liste position = liste_couleurs.index(rep_couleur) print("Position de la couleur : ", position) # Récupérer le code hexa correspondant hexa = liste_hexa[position] print("Code hexa : ", hexa) # Modifier la couleur des LED subprocess.run(["pironman", "-rc", hexa]) # Vider le buffer rep = signal.read(signal.inWaiting()) time.sleep(3) rep = signal.read(signal.inWaiting()) print("Contenu à la fin des op : ", rep) # Recommencer print ("\r\n======================= ENVOYEZ VOTRE PRENOM ==============================\n\r" ) else: # La couleur n'existe pas # On envoie un SMS pour dire que ce n'est pas bon ! print ('AT+CMGS="'+ tel + '"') signal.write(('AT+CMGS="' + tel +'"\r\n').encode()) time.sleep(1) rep = signal.read(signal.inWaiting()) print("Apres CGMS : \r\n",rep.decode()) erreur_couleur = "\r\nCette couleur n'existe pas dans la liste !" retour = "Désolé " + message + ", il faut recommencer à zéro en envoyant ton prénom !" +"\r\n" print ("Retour erreur : ", retour) signal.write(retour.encode()) time.sleep(1) rep = signal.read(signal.inWaiting()) print("Texte erreur envoyé : \r\n",rep.decode()) signal.write(chr(26).encode()) time.sleep(1) rep = signal.read(signal.inWaiting()) print("Fin SMS et OK : \r\n",rep.decode()) time.sleep(1) |
Comme le Raspberry Pi n’est pas connecté à Internet, ni au WiFi (je vous rappelle qu’on est en zone blanche Internet), il faut quand même le mettre à l’heure.
Je n’ai pas trouvé comment récupérer l’heure du réseau (apparemment la commande AT ne fonctionne pas alors qu’avec la NadHAT v1 en 2G ça fonctionnait). J’ai contourné le problème en enlevant la mise à l’heure via NTP et en envoyant un premier SMS à la carte. Comme le SMS est horodaté… Cette information me sert à mettre l’horloge sur RasPi à l’heure (et à la date). Ce n’est parfois pas immédiat mais ça fonctionne. Il faut désactiver le NTP (et le remettre lorsque vous connectez le Raspberry Pi à un réseau local en filaire ou en WiFi)
timedatectl set-ntp true (ou false)
Voilà je vous livre ça tel quel, c’est un exemple d’utilisation de la carte Garatronic « en vrai » et vous pourrez l’utiliser pour développer vos propres applications. Ceux qui sont passés sur le stand à Vitré ont pu tester ce programme…
Ping : Piloter les LEDs de Pironman par SMS avec la carte NadHAT MK2 4G de Garatronic
Ping : Boîtier Pironman 5 de SunFounder pour Raspberry Pi 5 avec M.2 NVMe PCIe - Framboise 314, le Raspberry Pi à la sauce française....