Bonsoir Jean-Marie.
Si l'on utilise lua, on ne dispose plus des commandes AT.
Il est préférable d'utiliser lua en mode autonome car l'intelligence est dans le code lua.
Pour récupérer les données envoyées par l'ESP8266 plusieurs cas:
On récupère les données et on les traites ensuite en différé.
On veut traiter les données en temps réel quand elles arrivent dans ce cas, il faut programmer.
On ne peut pas se permettre de perdre des données.
On peut par exemple utiliser le langage python à travers des sockets.
Voici plusieurs exemples de communications.
Avec les commandes at:
dans les exemples suivant on utilise la commande nc (netcat) sous Windows ou sous linux pour écouter sur un port.
On peut en python écouter sur un port et faire des traitements en temps réel.
La difficulté est de prévoir les cas ou les connexions sont fermées.
Code : Tout sélectionner
AT
OK
AT+GMR
00200.9.5(b1) -> sdk 20 firmware 9.5
compiled @ Dec 25 2014 21:40:28
AT+CWMODE? -> ? Utilisé pour interroger une valeur
+CWMODE:3 -> 1=STA 2=AP 3=STA+AP
AT+CWMODE=3 -> = utilisé pour modifier une valeur
OK
AT+CWLAP -> points d’accès à portée
+CWLAP:(3,"WRT54G_409B",-59,"00:12:17:b3:40:9d",1)
+CWLAP:(4,"larivoire234",-82,"34:8a:ae:3c:cc:44",6)
AT+CWJAP="WRT54G_409B","23423423423423423423423423" -> connexion au routeur WRT54G_409B
OK
On peut configure l’AP (nom, pwd, authentification, sauf l’adresse IP qui est par défaut 192.168.4.1)
Par défaut pas de mot de passe et le nom du point d’accès est xxx_yyyy (YYY= fin adresse MAC du point d’accès).
AT+CWSAP="ESP8266","00000000",4,3 -> SSID, pwd,canal, authentification 1=WEP,2=WPA,3=WPA2,4=WPA+WPA2
AT+CIFSR -> Infos connexions
+CIFSR:APIP,"192.168.4.1" -> AP (Acces point) IP non modifiable par commandes AT
+CIFSR:APMAC,"1a:fe:34:9b:c8:31"
+CIFSR:STAIP,"192.168.1.17" -> IP affectée par le DHCP du routeur WRT54G_409B
+CIFSR:STAMAC,"18:fe:34:9b:c8:31"
OK
Après connexion en WIFI au point d’accès 192.168.4.1 depuis un PC
AT+CWLIF
192.168.4.101 f8:4e:06:1c:f2:b7 -> Adresse IP affectée par le DHCP du point d’accès 192.168.4.1
Dans une console sur un PC le ping répond sur 192.168.1.17 ou 192.168.4.101
Réponse de 192.168.1.17 : octets=32 temps=4 ms TTL=255
AT+CIPMUX=1 ->multi connexions
OK
Sur le pc d’adresse IP 192.168.1.30 lancer la commande netcat pour écouter sur l’IP 192.168.1.17 port 4444
nc -l 192.168.1.17 -p 4444
AT+CIPSTART=0,"TCP","192.168.1.30",4444 -> connexion au PC d’adresse IP 192.168.1.30 sur le port 4444
0,CONNECT
OK
AT+CIPSEND=0,5 -> envoi sur canal 0, sur 5 octets
> aaaaa
SEND OK
Il existe des firmwares modifiés par exemple pour gérer les GPIO via des commandes AT http://www.electrodragon.com/w/ESP8266_Custom_AT_Firmware
AT + CIOADC command reads the ADC value Note: ADC input voltage 0,1V 0 to 1024,10 bit precision
AT + CIOREAD command reads the GPIO AT + CIOREAD = 0 reads GPIO0 level return 1 , 0
AT + CIOWRITE command to set the GPIO AT + CIOWRITE = 0,0 setting GPIO0 level is low
AT + CIOWRITE = 16,1 set of high level GPIO16
Je viens de tester un solution d'envoi de données par mail directement depuis lua.
Cette solution à l'avantage de régler les cas ou le serveur qui écoute les esp8266 est hors fonction.
Pour comprendre le protocole utilisé par un serveur de mails SMTP (mails sortants)
On peut simplement utiliser un client telnet sur le port 25
Et répondre aux messages du serveur SMTP.
Ne pas oublier le point (.) en fin de message.
Par exemple depuis une ligne de commande CMD sous Windows (sous linux c’est le même principe).
Code : Tout sélectionner
telnet smtp.orange.fr 25
220 mwinf5d23 ME ESMTP server ready
HELO orange.fr
250 mwinf5d23 hello [90.15.24.192], pleased to meet you
MAIL FROM: <SMBA38.esp8266@orange.fr>
250 2.1.0 <SMBA38.esp8266@orange.fr fr
> sender ok
RCPT TO: <esp8266.michel@orange.fr>
250 2.1.5 <esp8266.michel@orange.fr> recipient ok
DATA
354 enter mail, end with "." on a line by itself
Reply-to: <SMBA38.esp8266@orange.fr>
Subject: test envoi mail par esp8266
Et en plus ça fonctionne
C’est super
SMBA38
.
250 2.0.0 wYzq1p00Q48gNr603Z0e5d mail accepted for delivery
QUIT
221 2.0.0 mwinf5d23 ME closing connection
Perte de la connexion à l'hôte.
Et bien sur on peut faire la même chose en LUA
Infos récupérées sur
http://www.esp8266.com/viewtopic.php?f=24&t=1231
Le programme utilise une table d’états step[].
A chacune des 8 étapes le code renvoyé par le serveur SMTP doit être correct pour passer à l’état suivant.
A la fin de l’envoi d’un mail on peut choisir de ne pas quitter le programme, de rebooter
Ou de se mettre en veille « node.dsleep() » (mais il faut PIN32(RST) et PIN8(XPD_DCDC) reliées).
En fin de veille, l’esp8266 effectue un reboot.
Le Reboot est conseillé car le ramasse miettes « collectgarbage() » ne semble pas sur et le second mail n’est pas envoyé , mais le troisième est envoyé ? ( A creuser).
Il faut modifier l’avant dernière ligne du code pour indiquer :
les adresses mails de l’émetteur, du récepteur, le sujet le corps du mail et le serveur SMTP.
Code : Tout sélectionner
-- Fonction d'envoi d'un mail (sur une idée de http://www.esp8266.com/viewtopic.php?f=24&t=1231)
-- avec le traitements des Evenements associés à la vie de la connexion TCP
-- le traitement du mail comporte 8 étapes enchainées au fur et à mesure des réponses du serveur SMTP
-- A chaque étape "handle_response est appelé"
-- Problèmes a voir: pas de "de" dans les messages reçus, pas d'envoi au second appel de send mail.
-- Idées d’améliorations : création fichier log des alertes envoyé en pièce jointe
-- + Récupération de la date sur un serveur NTP.
sendmail=function(from,to,subject,body,server)
-- reponses au message reçus du serveur SMTP
local handle_response = function(conn,response,step,state)
--print("handling state:" .. state .. "Heap=" .. node.heap() .. "expecting:" .. step[state].expected .. " got:" .. response)
if response:match(step[state].expected )
then -- c'est le code attendu du serveur SMTP
print ("(" .. state ..") OK")
if step[state].request -- il existe un request dans la table
then
conn:send(step[state].request .. "\r\n") -- envoi contenu message request au serveur SMTP
else
conn:close() -- pas de request dans la table step[state], on ferme la connexion
end
state = state + 1 -- on passe à l'état suivant
else
conn:close() -- la réponse attendue n'est pas la bonne on ferme la connexion
end
return(state) -- Etat en cours en retour
end
-- gestion des états
local step={}
local smtp_server,smtp_port
smtp_server,smtp_port = server:match("(.*):(.*)")
local domain=from:match("@(.*)$")
-- table des états de connexion
step[1]={expected="^220",request="HELO " .. domain}
step[2]={expected="^250",request="MAIL FROM: <" .. from ..">"} -- from
step[3]={expected="^250",request="RCPT TO: <" .. to .. ">"} -- to
step[4]={expected="^250",request="DATA"} -- données
step[5]={expected="^354"} -- SMTP pret à recevoir des données
-- A addapter en fonction des serveurs de mail on peut utiliser: To:, From:, Reply-to, …
-- A tester pour que le mail ne soit pas considéré comme un Spam.
-- le From peut être différent du MAIL FROM: (c'est l'adresse mail de retour).
step[5].request =string.format("From:<%s>\r\nSubject:%s\r\n\r\n%s\r\n.",from,subject,body)
step[6]={expected="^250",request = "QUIT"} -- headers/message
step[7]={expected="^221"} -- quit
-- step[8] se produit sur Evenement "disconnection"
-- création connexion TCP et traitement des Evenements conn:on("evenement", ...)
local conn=net.createConnection(net.TCP, false)
local state=0
-- Réponses aux Evenements conn:on
conn:on("connection", function(conn) -- Evenement connexion OK
print("connected")
state = 1
end )
conn:on("receive", function(conn, payload) -- Evenement : un message vient d'arriver
--print("received:" .. payload) -- log du message
state=handle_response(conn,payload,step,state) -- réponse au message envoyé par SMTP
end )
conn:on("sent", function(conn) -- Evenement message envoyé
--print("sent data")
end )
conn:on("disconnection", function(conn) -- Evenement deconnexion
print("disconnected:".. state .."Heap="..node.heap())
-- plusieurs façon de terminer le traitement du mail
-- fermer seulement la connexion, Reboot, ou se mettre en veille (avec pin32 et pin8 reliées) avec un boot à la sortie de veille.
conn:close() conn=nil
collectgarbage() -- ramasse miettes pour faire le ménage dans la mémoire
print("Finramasse miettes" .. "Heap=" .. node.heap() )
node.restart() -- reboot
-- node.dsleep(5000000) -- reveil dans n microseconds selement si PIN32(RST) et PIN8(XPD_DCDC) reliées
end )
-- Fin réponses aux Evenements
-- on se connecte au serveur SMTP
-- la fonction sendmail va se terminer mais elle sera reveillée par les Evenements conn:on("xxxx" ...)
print("connecting to " .. smtp_server .. ":" .. smtp_port)
conn:connect(smtp_port,smtp_server)
end -- fin fonction sendmail
-- connexion au WIFI en mode Station
wifi.setmode(wifi.STATION)
wifi.sta.config("SSID","xxxxxxxx")
print(wifi.sta.getip()) -- Adresse IP allouée par le DHCP du routeur
print(wifi.sta.getmac()) -- Adresse MAC esp8266
-- Envoi d'un mail
-- sendmail("from@xxx.yyy","to@xxx.yyy","subject","body1\r\n body2 …","smtp.server.xxx:25")
sendmail("michel.esp8266@orange.fr","esp8266.michel@orange.fr","test envoi mail par esp8266 ","test \r\n à 15H17 ","smtp.orange.fr:25")
print("fin" ..node.heap()) -- attention le print s'execute avant la fin de l'envoi du mail
Donc un module esp8266 < 3€, deux piles AAA, et un capteur suffisent pour envoyer une alerte par mail.
On pourrait améliorer le principe en ajoutant un fichier log pour tracer les alertes.
C’est assez facile en lua car on a toutes les fonctions sur fichiers nécessaires :
open, close, readline, writeline, read, write, flush, seek, list, format, rename
Un appel à un serveur NTP pourrait permettre de dater les alertes.
Et pourquoi ne pas envoyer le fichier log en pièce jointe.
Cette puce esp8266, elle à tout d’une grande.
En principe les serveurs de mails sont toujours actifs.
si l'on veut perdre aucun mail, il faut mettre en file d'attente dans un fichier les mails en erreur d'émission (en testant les codes retour envoyés par le serveur SMTP). pour les envoyer plus tard.
On peut si l'on veut traiter les mails en provenance des esp8266 écrire un programme par exemple en python sur un Raspberry qui récupéré des mails structurés d'une certaine façon et qui les traite.
Prochaine étape, tester le protocole MQTT (machine to machine) prévu dans lua.
Ce protocole va peut être s’imposer dans l’Internet des objets (IOT : Internet Of Things).
Mais avant un exemple simple d'utilisation de python pour se connecter sur un esp8266 configuré en serveur Telnet
SMBA38.