ไลบรารีสำหรับทำการสืบค้น HTTP ด้วยโมดูล ESP8266 WiFi และ Arduino
วิธีง่ายๆ ในการส่งข้อมูลไปและกลับจากไมโครคอนโทรลเลอร์คือการรวมศูนย์ข้อมูลนั้นไว้บนเว็บเซิร์ฟเวอร์ แม้ว่าวิธีการจะไม่มีประสิทธิภาพเท่ากับการเข้าถึงฐานข้อมูลโดยตรง แต่ก็มีประสิทธิภาพเพียงพอ โดยเฉพาะอย่างยิ่งหากคุณพิจารณาโครงการที่ใช้ไมโครคอนโทรลเลอร์ และเพิ่มข้อดีของความแพร่หลาย (ข้อมูลในระบบคลาวด์) และความเรียบง่าย (มัน สามารถจัดการเป็นข้อมูลข้อความและคำสั่งได้) การส่งข้อมูลโดยใช้ระบบนี้อาจประกอบด้วยการร้องขอ HTTP POST และรับโดยการวิเคราะห์เนื้อหาการตอบสนองต่อคำขอ HTTP GET
El โมดูล WiFi ESP8266 เป็นตัวเลือกที่ประหยัดมาก ด้วยประสิทธิภาพที่เหมาะมากสำหรับใช้กับไมโครคอนโทรลเลอร์ และใช้งานง่ายมากกับการทำงานกับคำสั่ง AT
เพื่อจัดระบบการใช้งานด้วยคำขอ HTTP ฉันได้พัฒนาไลบรารีขนาดเล็กที่รองรับความต้องการของโปรเจ็กต์อุปกรณ์การจัดการการนอนหลับของฉัน (ซึ่งฉันเรียกว่า SleepManager) เนื่องจากอิงโครงสร้างพื้นฐานบนเว็บเซิร์ฟเวอร์ที่อนุญาตให้ขยายไปยังอ็อบเจ็กต์ได้ IoT ในขณะที่ บริการคลาวด์. การเพิ่มบริการอื่นๆ เช่น คำขอ UDP ไปยังไลบรารีได้ไม่ใช่เรื่องยาก เป็นต้น การซิงโครไนซ์เวลาผ่าน NTP แม้ว่าดังที่ฉันอธิบายในข้อความที่เชื่อมโยง มันไม่สำคัญสำหรับความต้องการของฉัน และฉันสามารถแก้ไขได้ด้วยคำขอ HTTP ไปยังหน้าเว็บที่เตรียมไว้สำหรับวัตถุประสงค์นั้น ดังที่ฉันแสดงในตัวอย่างการใช้ไลบรารีนี้
การทำงานของไลบรารีจะขึ้นอยู่กับการส่งคำสั่ง AT เมื่ออุปกรณ์พร้อมใช้งานและทำซ้ำคำสั่งเหล่านั้น (โดยมีความล่าช้าเล็กน้อย) ในกรณีที่เกิดข้อผิดพลาด ซึ่งตีความได้ว่าไม่พร้อมใช้งาน (สำเร็จโดยการทดสอบ) เช่น จากการเข้าถึง WiFi แบบจุดหรือ กำลังปรึกษาเซิร์ฟเวอร์
ไลบรารีใช้ประโยชน์จากข้อเท็จจริงที่ว่าโมดูล ESP8266 WiFi ส่งคืนรหัส +IPD เพื่อเป็นคำเตือนการรับข้อมูลเพื่อเติมบัฟเฟอร์ขนาดเล็กด้วยข้อมูลที่เซิร์ฟเวอร์ส่งคืน สำหรับโปรเจ็กต์อุปกรณ์การจัดการการนอนหลับ ฉันจำเป็นต้องวิเคราะห์ข้อมูลที่ส่งคืนจากเซิร์ฟเวอร์น้อยมาก ดังนั้น เพื่อประหยัด บัฟเฟอร์และตัวชี้ที่เรียกใช้ผ่านบัฟเฟอร์จึงมีขนาดเล็กเป็นพิเศษ นี่จะเป็นหนึ่งในสิ่งแรกที่คุณจะต้องเปลี่ยนเพื่อนำไลบรารีกลับมาใช้ใหม่เพื่อประมวลผลข้อมูลปริมาณมากขึ้น
ฟังก์ชั่นที่เปิดเผยเป็นสาธารณะช่วยให้ (1) รู้สถานะของโมดูล: เชื่อมต่ออยู่หรือไม่ มีข้อมูลในบัฟเฟอร์และจำนวนเท่าใด และหากโมดูล ESP8266 ดำเนินการตามที่ร้องขอเสร็จสิ้นแล้วหรือไม่ (2) เชื่อมต่อกับจุดเชื่อมต่อ WiFi บนเครือข่ายที่มีเซิร์ฟเวอร์ DHCP และ (3) ส่งคำขอ HTTP GET และ POST แม้ว่าคุณจะเห็นแล้วว่าโค้ดได้รับการออกแบบมาเพื่อให้ง่ายต่อการเพิ่มผู้อื่น
เกี่ยวกับการทำงานภายใน เมทริกซ์สองตัวแรกถูกสร้างขึ้น ตัวแรกมีคำสั่ง AT และอีกตัวหนึ่งมีการตอบสนองที่คาดหวังสำหรับความสำเร็จและข้อผิดพลาด ดังนั้นโปรแกรมที่ใช้ไลบรารีจะต้องเรียกใช้ฟังก์ชันเป็นครั้งคราว
ซึ่งจะทำหน้าที่ส่งคำสั่งซื้อไปยังโมดูลหากว่างและไม่ยุ่งและไปที่ฟังก์ชัน ซึ่งจะประมวลผลการตอบสนองจากโมดูล ESP8266 (และจากเซิร์ฟเวอร์ HTTP ผ่านโมดูลนั้นหากมี)เนื่องจากมีความเป็นไปได้ที่โมดูลอาจถูกตัดการเชื่อมต่อเนื่องจากสัญญาณขาดหาย โปรแกรมหลักสามารถตรวจสอบได้ว่าโมดูล ESP8266 เชื่อมต่อกับจุดเชื่อมต่อ WiFi หรือไม่ (พร้อมฟังก์ชัน
) และลองเชื่อมต่อเป็นอย่างอื่น (ด้วยฟังก์ชัน )หากต้องการทราบว่าการดำเนินการที่ร้องขอเสร็จสิ้นแล้วหรือไม่ โปรแกรมสามารถใช้ฟังก์ชันนี้ได้
และในกรณีนั้นให้ส่งข้อมูลอื่นหรือใช้ข้อมูลผลลัพธ์ที่ใช้ฟังก์ชันนี้ โดยส่งคืนเนื้อหาของบัฟเฟอร์ที่เติมข้อมูลที่มาถึงโมดูล ESP8266 จนกว่าการดำเนินการจะเสร็จสิ้นและฟังก์ชัน ซึ่งรายงานจำนวนข้อมูลนี้ที่เซิร์ฟเวอร์เตือนว่ากำลังจะถูกส่ง (เพื่อให้ข้อมูลจากโมดูลเองสามารถลดราคาได้)
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
332
333
334
335
336
337
|
//ESP8266.cpp
#if defined(ARDUINO) && ARDUINO>=100
#include “Arduino.h”
#else
#include “WProgram.h”
#endif
// Para monitorizar (CONSOLA) a la vez que se comunica con el módulo por el puerto serie hace falta una placa Arduino con varios puertos (como Mega o Leonardo) en caso contrario hay que cambiar a MODULO_WIFI Serial y desactivar la depuración
// No se inicializan las comunicaciones serie, es necesario inicializarlas desde el programa que usa la librería
#define CONSOLA Serial
#define MODULO_WIFI Serial1
#include “ESP8266.h”
ESP8266::ESP8266(boolean depuracion)
{
constructor(depuracion);
}
ESP8266::ESP8266()
{
constructor(false);
}
ESP8266::~ESP8266()
{
}
void ESP8266::constructor(boolean depuracion)
{
mostrar_salida=false; // Sin depuración para Arduino Uno
//mostrar_salida=depuracion;
estado_orden=ORDEN_OK;
indicador_operacion_terminada=&ESP8266_operacion_terminada;
*indicador_operacion_terminada=true;
reiniciar_buffer();
mensaje_buscado[ORDEN_RECIBIENDO]=CODIGO_INICIO_RECEPCION;
}
void ESP8266::conectar_wifi
(
String ssid,
String clave,
String ip,
byte timeout
)
{
estado_orden=ORDEN_OK;
pasos_operacion=0;
paso_operacion=255; //Para poder incrementar al principio del proceso y que empiece en cero
ESP8266_conectado=false;
indicador_operacion_terminada=&ESP8266_conectado;
*indicador_operacion_terminada=false;
respuesta[pasos_operacion][ORDEN_KO]=“”; //reiniciar para descartar la configuración anterior que es desconocida
respuesta[pasos_operacion][ORDEN_OK]=“ready”;
comando[pasos_operacion++]=“AT+RST”; //reiniciar para descartar la configuración anterior que es desconocida
//respuesta[pasos_operacion][ORDEN_KO]=”ERROR”; //Consultar el firmware
//respuesta[pasos_operacion][ORDEN_OK]=”OK”;
//comando[pasos_operacion++]=”AT+GMR”; //Consultar el firmware
respuesta[pasos_operacion][ORDEN_KO]=“”; //Modo Sta (1|3)
respuesta[pasos_operacion][ORDEN_OK]=“”;
comando[pasos_operacion++]=“AT+CWMODE=1”; //Modo Sta = 1 (también es posible con 3, mixto)
//respuesta[pasos_operacion][ORDEN_KO]=””; //Listado de puntos de acceso
//respuesta[pasos_operacion][ORDEN_OK]=””;
//comando[pasos_operacion++]=”AT+CWLAP”; //Listado de puntos de acceso
respuesta[pasos_operacion][ORDEN_KO]=“”;
respuesta[pasos_operacion][ORDEN_OK]=“”;
comando[pasos_operacion++]=“ATE0”; //Desactivar el eco antes de mandar la clave
respuesta[pasos_operacion][ORDEN_KO]=“FAIL”; //En el firmware original era “Error”
respuesta[pasos_operacion][ORDEN_OK]=“OK”;
comando[pasos_operacion++]=“AT+CWJAP=\””+ssid+“\”,\””+clave+“\””; //SSID y clave
respuesta[pasos_operacion][ORDEN_KO]=“”;
respuesta[pasos_operacion][ORDEN_OK]=“”;
comando[pasos_operacion++]=“ATE1”; //Activar el eco antes de seguir
respuesta[pasos_operacion][ORDEN_KO]=“”;
respuesta[pasos_operacion][ORDEN_OK]=“\””+ssid+“\””;
comando[pasos_operacion++]=“AT+CWJAP?”; //Comprobar que se ha conectado
respuesta[pasos_operacion][ORDEN_KO]=“ERROR”;
respuesta[pasos_operacion][ORDEN_OK]=ip.substring(0,ip.lastIndexOf(‘.’)+1);
comando[pasos_operacion++]=“AT+CIFSR”; //Consultar la dirección IP
respuesta[pasos_operacion][ORDEN_KO]=“ERROR”;
respuesta[pasos_operacion][ORDEN_OK]=“AT+CIPMUX=0\r\r\n\r\nOK”;
comando[pasos_operacion++]=“AT+CIPMUX=0”; //Conenexión simple
}
void ESP8266::http
(
byte tipo_consulta_http,
String direccion_servidor,
unsigned int puerto,
String nombre_servidor,
String agente,
String pagina,
String texto_consulta,
String respuesta_ko,
String respuesta_ok
)
{
String consulta=“”;
estado_orden=ORDEN_OK;
pasos_operacion=0;
paso_operacion=255; //Para poder incrementar al principio del proceso y que empiece en cero
consultando_http=true;
reiniciar_buffer();
indicador_operacion_terminada=&consultando_http;
*indicador_operacion_terminada=false;
switch(tipo_consulta_http)
{
case HTTP_GET:
consulta+=“GET”;
if(texto_consulta!=“”)
{
pagina+=“?”+texto_consulta;
}
break;
case HTTP_POST:
consulta+=“POST”;
break;
}
consulta+=” /”+pagina+” HTTP/1.1″+“\r\n”;
consulta+=“User-Agent: “+agente+“\r\n”;
consulta+=“Host: “+nombre_servidor+“\r\n”;
if(tipo_consulta_http==HTTP_POST)
{
consulta+=“Content-Type: application/x-www-form-urlencoded\r\n”;
consulta+=“Content-Length: “+String(texto_consulta.length(),DEC)+“\r\n”;
consulta+=“\r\n”;
consulta+=texto_consulta;
}
consulta+=“\r\n”;
respuesta[pasos_operacion][ORDEN_KO]=“ERROR”; //en el firmware anterior era “Error”
respuesta[pasos_operacion][ORDEN_OK]=“OK”; //en el firmware anterior era “Linked”
comando[pasos_operacion++]=“AT+CIPSTART=\”TCP\”,\””+direccion_servidor+“\”,”+String(puerto,DEC);
respuesta[pasos_operacion][ORDEN_KO]=“Error”;
respuesta[pasos_operacion][ORDEN_OK]=“>”;
comando[pasos_operacion++]=“AT+CIPSEND=”+String(consulta.length(),DEC);
respuesta[pasos_operacion][ORDEN_KO]=respuesta_ko;
respuesta[pasos_operacion][ORDEN_OK]=respuesta_ok;
//respuesta[pasos_operacion][ORDEN_OK]=”CLOSED”; //en el firmware anterior era “Unlink”
comando[pasos_operacion++]=consulta;
/*
respuesta[pasos_operacion][ORDEN_KO]=””;
respuesta[pasos_operacion][ORDEN_OK]=”OK”;
comando[pasos_operacion++]=”AT+CIPCLOSE”;
*/
}
void ESP8266::enviar()
{
if(!*indicador_operacion_terminada)
{
switch(estado_orden)
{
case ORDEN_OK:
paso_operacion++;
if(paso_operacion<pasos_operacion)
{
enviar_comando
(
comando[paso_operacion],
respuesta[paso_operacion][ORDEN_KO],
respuesta[paso_operacion][ORDEN_OK]
);
}
else
{
*indicador_operacion_terminada=true;
}
break;
case ORDEN_KO:
paso_operacion—;
estado_orden=ORDEN_OK;
delay(ESPERA_REINTENTO);
break;
/*
case ORDEN_RECIBIENDO:
break;
case ORDEN_ACTIVA:
break;
*/
}
}
}
//integrar en enviar
void ESP8266::enviar_comando(String comando,String respuesta_ko,String respuesta_ok)
{
/* //Monitorizar las ordenes que se envian
if(mostrar_salida)
{
CONSOLA.print(“\n”);
CONSOLA.print(“(“+String(millis(),DEC)+”)”);
//CONSOLA.print(“\n”);
CONSOLA.print(String(paso_operacion+1,DEC)+”/”+String(pasos_operacion,DEC)+”> “);
CONSOLA.print(comando);
CONSOLA.print(” [“+respuesta_ko+”|”+respuesta_ok+”]”);
CONSOLA.print(“\n”);
}
*/
MODULO_WIFI.println(comando);
mensaje_buscado[ORDEN_KO]=respuesta_ko;
mensaje_buscado[ORDEN_OK]=respuesta_ok;
if(respuesta_ok==“”)
{
estado_orden=ORDEN_OK;
delay(ESPERA_ORDEN);
}
else
{
estado_orden=ORDEN_ACTIVA;
reiniciar_busqueda_mensaje();
}
}
void ESP8266::reiniciar_buffer()
{
puntero_buffer=0;
buffer_activo=false;
longitud_ipd=0;
}
void ESP8266::reiniciar_busqueda_mensaje()
{
byte contador;
buscando_mensaje=true;
//estados=sizeof(mensaje_buscado)/sizeof(String); //Es posible generalizar calculando los estados
for(contador=0;contador<ESTADOS_COMUNICACION;contador++)
{
puntero_mensaje[contador]=0;
longitud_mensaje[contador]=mensaje_buscado[contador].length();
}
}
void ESP8266::recibir()
{
char lectura;
while(MODULO_WIFI.available()>0)
{
lectura=MODULO_WIFI.read();
if(mostrar_salida)
{
CONSOLA.print(lectura);
}
if(buffer_activo)
{
if(longitud_ipd==0&&lectura==CODIGO_FIN_RECEPCION)
{
ESP8266_buffer[puntero_buffer]=0;
longitud_ipd=atoi(ESP8266_buffer);
puntero_buffer=0;
}
else
{
ESP8266_buffer[puntero_buffer++]=lectura;
}
}
if(estado_orden==ORDEN_ACTIVA||estado_orden==ORDEN_RECIBIENDO)
{
estado_orden=buscar_mensaje(lectura,mensaje_buscado);
if(estado_orden==ORDEN_RECIBIENDO)
{
buffer_activo=true;
estado_orden=ORDEN_ACTIVA;
buscando_mensaje=true;
}
}
}
}
byte ESP8266::buscar_mensaje(char lectura,String *mensaje)
{
byte contador;
byte numero_de_estado=0;
while(numero_de_estado<ESTADOS_COMUNICACION–buffer_activo&&buscando_mensaje)
{
if(longitud_mensaje[numero_de_estado])
{
if(lectura==mensaje[numero_de_estado].charAt(puntero_mensaje[numero_de_estado]))
{
puntero_mensaje[numero_de_estado]++;
if(puntero_mensaje[numero_de_estado]==longitud_mensaje[numero_de_estado])
{
buscando_mensaje=false;
for(contador=0;contador<ESTADOS_COMUNICACION–buffer_activo;contador++)
{
puntero_mensaje[contador]=0;
}
}
}
else
{
puntero_mensaje[numero_de_estado]=0;
}
}
numero_de_estado=numero_de_estado+buscando_mensaje;
}
if(buscando_mensaje)
{
return ORDEN_ACTIVA;
}
else
{
return numero_de_estado;
}
}
char *ESP8266::leer_buffer()
{
reiniciar_buffer();
return ESP8266_buffer;
}
byte ESP8266::longitud_buffer()
{
return longitud_ipd;
}
boolean ESP8266::conectado()
{
return ESP8266_conectado;
}
boolean ESP8266::desconectado()
{
return ESP8266_conectado;
}
boolean ESP8266::consulta_ok()
{
return estado_orden==ORDEN_OK;
}
boolean ESP8266::operacion_terminada()
{
return *indicador_operacion_terminada;
}
|
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
|
//ESP8266.h
#if defined(ARDUINO) && ARDUINO>=100
#include “Arduino.h”
#else
#include “WProgram.h”
#endif
#define HTTP_CONNECT 0 //Codigos HTTP (en uso + reservados)
#define HTTP_DELETE 1
#define HTTP_GET 2
#define HTTP_HEAD 3
#define HTTP_OPTIONS 4
#define HTTP_PATCH 5
#define HTTP_POST 6
#define HTTP_PUT 7
#define HTTP_TRACE 8
#define PASOS_HTTP 4
#define MAXIMO_PASOS_OPERACION 8 //+listar puntos de acceso +verificar firmware
#define ESTADOS_COMUNICACION 3 //Estados que contienen mensajes que hay que atender
#define ORDEN_KO 0
#define ORDEN_OK 1
#define ORDEN_RECIBIENDO 2 //debe ser el último de los estados para desactivarlo cuando se este rellenando el buffer
#define ORDEN_ACTIVA 3 //debe ser igual a ESTADOS_COMUNICACION (uno más que el último estado)
#define ESPERA_ORDEN 3000 //milisegundos despues de una orden AT sin respuesta
#define ESPERA_REINTENTO 5000 //milisegundos antes de reintentar una orden AT
#define MAX_BUFFER 256 //cambiar también el tipo de puntero_buffer si aumenta
#define CODIGO_INICIO_RECEPCION “+IPD,”
#define CODIGO_FIN_RECEPCION ‘:’
class ESP8266
{
private:
boolean ESP8266_conectado;
boolean consultando_http;
boolean ESP8266_operacion_terminada;
boolean *indicador_operacion_terminada;
boolean mostrar_salida;
boolean datos_recibidos;
byte paso_operacion;
byte pasos_operacion;
//boolean estado_operacion;
String comando[MAXIMO_PASOS_OPERACION];
String respuesta[MAXIMO_PASOS_OPERACION][ESTADOS_COMUNICACION];
String mensaje_buscado[MAXIMO_PASOS_OPERACION];
byte puntero_mensaje[ESTADOS_COMUNICACION]; //ORDEN_KO->error (0/false), ORDEN_OK->acierto (1/true)
byte longitud_mensaje[ESTADOS_COMUNICACION]; //longitudes la cadena de error y de la de acierto
boolean buscando_mensaje;
byte estado_orden;
//boolean error_de_conexion;
byte buscar_mensaje(char lectura,String *mensaje);
void reiniciar_busqueda_mensaje();
char ESP8266_buffer[MAX_BUFFER];
boolean buffer_activo;
byte puntero_buffer;
byte longitud_ipd;
void enviar_comando
(
String comando,
String respuesta_ok,
String respuesta_ko
);
protected:
public:
ESP8266();
ESP8266(boolean depuracion);
~ESP8266();
void conectar_wifi
(
String ssid,
String clave,
String ip,
byte timeout
);
void constructor(boolean depuracion);
void http
(
byte tipo_consulta_http,
String direccion_servidor,
unsigned int puerto,
String nombre_servidor,
String agente,
String pagina,
String texto_consulta,
String respuesta_ko,
String respuesta_ok
);
void reiniciar_buffer();
char *leer_buffer();
byte longitud_buffer();
void enviar();
void recibir();
boolean conectado();
boolean desconectado();
boolean consulta_ok();
boolean operacion_terminada();
};
|
ตัวอย่างด้านล่างใช้ไลบรารีแบบสอบถาม HTTP กับโมดูล ESP8266 WiFi เพื่อส่งข้อมูลไปยังเซิร์ฟเวอร์ (เปอร์เซ็นต์ที่ได้รับจากการอ่านอินพุตแบบอะนาล็อก) ทุกๆ ช่วงเวลาที่กำหนด เนื่องจากไม่คาดว่าจะได้รับการตอบสนองใดๆ จึงไม่ได้ใช้บัฟเฟอร์ และเพียงพอสำหรับการดำเนินการให้เสร็จสมบูรณ์อย่างถูกต้อง ระบบนี้คือสิ่งที่ฉันใช้ในโปรเจ็กต์อุปกรณ์จัดการการนอนหลับเพื่อจัดเก็บผลลัพธ์การอ่านเซ็นเซอร์บนเซิร์ฟเวอร์
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
|
#include “ESP8266.h”
#define MODO_DEPURACION true
#define PIN_LED_CONEXION 13
#define WIFI_VELOCIDAD 115200
#define WIFI_SSID “SleepManager”
#define WIFI_CLAVE “****”
#define CONSOLA_VELOCIDAD 115200
#define SERVIDOR_DIRECCION “192.168.1.22”
#define SERVIDOR_PUERTO 80
#define SERVIDOR_PROTOCOLO “HTTP/1.1”
#define SERVIDOR_NOMBRE “”
#define SERVIDOR_AGENTE “sleepmanager-clinic-wifi”
#define PAGINA_PRUEBA “pruebas/lectura_porcentaje.php”
#define PARAMETRO_PRUEBA “porcentaje”
#define CONSULTA_KO “”
#define CONSULTA_OK “porcentaje recibido correctamente”
#define TIMEOUT_CONEXION 30000
#define INTERVALO_LECTURAS_SENSOR 60000
float valor_sensor_analogico;
String texto_consulta;
unsigned long cronometro_lectura=0;
ESP8266 conexion_wifi_servidor(MODO_DEPURACION);
void setup()
{
Serial.begin(CONSOLA_VELOCIDAD); // Cambiar para que el puerto serie corresponda con el de la consola
Serial1.begin(WIFI_VELOCIDAD); // Cambiar para que el puerto serie corresponda con el del módulo WiFi
delay(5000); //Unos segundos para que el humano active la consola
conexion_wifi_servidor.conectar_wifi
(
WIFI_SSID,
WIFI_CLAVE,
SERVIDOR_DIRECCION,
TIMEOUT_CONEXION
);
}
void loop()
{
if(conexion_wifi_servidor.operacion_terminada())
{
if(conexion_wifi_servidor.conectado())
{
digitalWrite(PIN_LED_CONEXION,HIGH);
if(cronometro_lectura<millis())
{
valor_sensor_analogico=analogRead(A0)*100.0/1023.0;
texto_consulta=String(PARAMETRO_PRUEBA)+“=”+String(valor_sensor_analogico,DEC);
cronometro_lectura=millis()+INTERVALO_LECTURAS_SENSOR;
conexion_wifi_servidor.http
(
HTTP_POST,
SERVIDOR_DIRECCION,
SERVIDOR_PUERTO,
SERVIDOR_NOMBRE,
SERVIDOR_AGENTE,
PAGINA_PRUEBA,
texto_consulta,
CONSULTA_KO,
CONSULTA_OK
);
}
}
else
{
digitalWrite(PIN_LED_CONEXION,LOW);
conexion_wifi_servidor.conectar_wifi
(
WIFI_SSID,
WIFI_CLAVE,
SERVIDOR_DIRECCION,
TIMEOUT_CONEXION
);
}
}
else
{
conexion_wifi_servidor.enviar();
}
conexion_wifi_servidor.recibir();
}
|
ตัวอย่างต่อไปนี้ใช้แบบสอบถาม HTTP GET เพื่อสอบถามเวลาของเซิร์ฟเวอร์และซิงโครไนซ์กับเวลาของอุปกรณ์ควบคุมไมโครโดยเพิ่มเวลาตอบสนองโดยประมาณ ในความเป็นจริงมันเพิ่มอีก 4 ถึง 6 วินาทีเพื่อให้แน่ใจว่าเวลาของอุปกรณ์นั้นมากกว่าเวลาของเซิร์ฟเวอร์และเพื่อตรวจสอบได้อย่างง่ายดายว่าเวลาบนนาฬิกาเรียลไทม์ที่เป็นส่วนหนึ่งของอุปกรณ์นั้นถูกต้องหรือสูญหายเนื่องจากการดาวน์โหลด . แบตเตอรี่
หลังจากการทดสอบหลายครั้งฉันได้ตรวจสอบแล้วว่าระบบนี้ของ การซิงโครไนซ์เวลากับโมดูล ESP8266 WiFi มันแม่นยำเพียงพอสำหรับความต้องการของฉัน ในกรณีที่เลวร้ายที่สุดโดยมีข้อผิดพลาดน้อยกว่า 10 วินาทีซึ่งค่อนข้างไม่เกี่ยวข้องในกรณีของฉัน
ดังที่เห็นในโค้ด จำเป็นต้องสืบค้นความยาวของบัฟเฟอร์ก่อน เนื่องจากการอ่านจะรีเซ็ตเพื่อให้สามารถจัดเก็บข้อมูลใหม่ได้
เมื่ออ่านเนื้อหาของบัฟเฟอร์แล้ว ในตัวอย่างนี้ บัฟเฟอร์จะถูกประมวลผลเพื่อให้ได้เวลา ขั้นแรก เลือกข้อความระหว่างเครื่องหมายปีกกา (เซิร์ฟเวอร์ตอบสนองโดยใช้คำสั่ง PHP ) lo transforma en un “objeto tiempo” y de él obtiene en formato humano la fecha y la hora.
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
|
#include <Time.h>
#include “ESP8266.h”
#define MODO_DEPURACION true
#define PIN_LED_CONEXION 13
#define WIFI_VELOCIDAD 115200
#define WIFI_SSID “SleepManager”
#define WIFI_CLAVE “****”
#define CONSOLA_VELOCIDAD 115200
#define SERVIDOR_DIRECCION “192.168.1.22”
#define SERVIDOR_PUERTO 80
#define SERVIDOR_PROTOCOLO “HTTP/1.1”
#define SERVIDOR_NOMBRE “”
#define SERVIDOR_AGENTE “sleepmanager-clinic-wifi”
#define PAGINA_PRUEBA “pruebas/hora_servidor.php”
#define CONSULTA_KO “”
#define CONSULTA_OK “CLOSED” // Cuando se desconecte el servidor pasado el timeout
#define TIMEOUT_CONEXION 3000
#define INTERVALO_LECTURAS_HORA 60000
String texto_consulta;
unsigned long cronometro_lectura=0;
ESP8266 conexion_wifi_servidor(MODO_DEPURACION);
byte longitud_buffer;
byte inicio_fecha;
byte fin_fecha;
char *buffer;
time_t fecha_hora;
void setup()
{
Serial.begin(CONSOLA_VELOCIDAD); // Cambiar para que el puerto serie corresponda con el de la consola
Serial1.begin(WIFI_VELOCIDAD); // Cambiar para que el puerto serie corresponda con el del módulo WiFi
delay(5000); //Unos segundos para que el humano active la consola
conexion_wifi_servidor.conectar_wifi
(
WIFI_SSID,
WIFI_CLAVE,
SERVIDOR_DIRECCION,
TIMEOUT_CONEXION
);
texto_consulta=“”; //no se envía información, solo se lee la pagina
}
void loop()
{
if(conexion_wifi_servidor.operacion_terminada())
{
if(conexion_wifi_servidor.conectado())
{
digitalWrite(PIN_LED_CONEXION,HIGH);
if(cronometro_lectura<millis())
{
cronometro_lectura=millis()+INTERVALO_LECTURAS_HORA;
conexion_wifi_servidor.http
(
HTTP_GET,
SERVIDOR_DIRECCION,
SERVIDOR_PUERTO,
SERVIDOR_NOMBRE,
SERVIDOR_AGENTE,
PAGINA_PRUEBA,
texto_consulta,
CONSULTA_KO,
CONSULTA_OK
);
}
else
{
longitud_buffer=conexion_wifi_servidor.longitud_buffer();
if(longitud_buffer)
{
buffer=conexion_wifi_servidor.leer_buffer();
inicio_fecha=String(buffer).indexOf(‘{‘);
if(inicio_fecha<255)
{
fin_fecha=String(buffer).indexOf(‘}’);
if(fin_fecha>0)
{
fecha_hora=String(buffer).substring(inicio_fecha+1,fin_fecha).toInt()+10;
Serial.println
(
“Fecha: “+
String(day(fecha_hora),DEC)+“/”+
String(month(fecha_hora),DEC)+“/”+
String(year(fecha_hora),DEC)+” “+
“Hora: “+
String(hour(fecha_hora),DEC)+“:”+
String(minute(fecha_hora),DEC)+“:”+
String(second(fecha_hora),DEC)
);
}
}
}
}
}
else
{
digitalWrite(PIN_LED_CONEXION,LOW);
conexion_wifi_servidor.conectar_wifi
(
WIFI_SSID,
WIFI_CLAVE,
SERVIDOR_DIRECCION,
TIMEOUT_CONEXION
);
}
}
else
{
conexion_wifi_servidor.enviar();
}
conexion_wifi_servidor.recibir();
}
|
โปรแกรมตัวอย่างต่อไปนี้ ซึ่งได้รับแรงบันดาลใจจากข้อความค้นหาของผู้ใช้ ใช้เพื่อค้นหาที่อยู่ IP สาธารณะที่ใช้บริการ ตรวจสอบ IP AWS (บริการเว็บ Amazon) ทุกห้านาที
เช่นเดียวกับในตัวอย่างก่อนหน้านี้ มีการตั้งสมมติฐานหลายประการที่จะต้องเปลี่ยนแปลงขึ้นอยู่กับการกำหนดค่าเครือข่ายที่ใช้ (ในตัวอย่าง 192.168.1.X) SSID และคีย์ WiFi... วิธีค้นหา ที่อยู่ IP ไม่ได้หรูหรามากนัก แต่ถือว่ามันเป็นบรรทัดสุดท้ายของการตอบสนองต่อคำขอ HTTP GET แม้ว่าอาจมี API ที่จะทำในลักษณะที่ออร์โธดอกซ์มากกว่าก็ตาม
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
|
#include “ESP8266.h”
#define MODO_DEPURACION true
#define PIN_LED_CONEXION 13
#define WIFI_VELOCIDAD 115200
#define WIFI_SSID “SleepManager”
#define WIFI_CLAVE “****”
#define CONSOLA_VELOCIDAD 115200
#define RED_DIRECCION “192.168.1.X”
#define SERVIDOR_DIRECCION “23.23.144.23” // ¡¡Mucho cuidado, puede cambiar la dirección IP!! (buscarla antes de usar el programa, por ejemplo, con ping checkip.amazonaws.com)
#define SERVIDOR_PUERTO 80
#define SERVIDOR_PROTOCOLO “HTTP/1.1”
#define SERVIDOR_NOMBRE “checkip.amazonaws.com”
#define SERVIDOR_AGENTE “buscadordeipes”
#define PAGINA_IP “”
#define CONSULTA_KO “Error”
#define CONSULTA_OK “\n\r\nOK”
#define TIMEOUT_CONEXION 3000
#define INTERVALO_LECTURAS_IP 300000 //Leer la IP publica cada 5 minutos
String texto_consulta;
unsigned long cronometro_lectura=0;
ESP8266 conexion_wifi_servidor(MODO_DEPURACION);
byte longitud_buffer;
byte inicio_ip;
byte fin_ip;
char *buffer;
void setup()
{
Serial.begin(CONSOLA_VELOCIDAD); // Cambiar para que el puerto serie corresponda con el de la consola
Serial1.begin(WIFI_VELOCIDAD); // Cambiar para que el puerto serie corresponda con el del módulo WiFi
pinMode(PIN_LED_CONEXION,OUTPUT);
digitalWrite(PIN_LED_CONEXION,LOW);
delay(5000); //Unos segundos para que el humano active la consola
conexion_wifi_servidor.conectar_wifi
(
WIFI_SSID,
WIFI_CLAVE,
RED_DIRECCION,
TIMEOUT_CONEXION
);
texto_consulta=“”; //no se envia informacion, solo se lee la pagina
}
void loop()
{
if(conexion_wifi_servidor.operacion_terminada())
{
if(conexion_wifi_servidor.conectado())
{
digitalWrite(PIN_LED_CONEXION,HIGH);
if(cronometro_lectura<millis())
{
cronometro_lectura=millis()+INTERVALO_LECTURAS_IP;
conexion_wifi_servidor.http
(
HTTP_GET,
SERVIDOR_DIRECCION,
SERVIDOR_PUERTO,
SERVIDOR_NOMBRE,
SERVIDOR_AGENTE,
PAGINA_IP,
texto_consulta,
CONSULTA_KO,
CONSULTA_OK
);
}
else
{
longitud_buffer=conexion_wifi_servidor.longitud_buffer();
if(longitud_buffer)
{
buffer=conexion_wifi_servidor.leer_buffer();
inicio_ip=String(buffer).indexOf(“\r\n\r\n”)+4;
fin_ip=String(buffer).indexOf(“\r\n”,inicio_ip)–1;
Serial.println(“IP [“+String(buffer).substring(inicio_ip,fin_ip)+“]”);
}
}
}
else
{
digitalWrite(PIN_LED_CONEXION,LOW);
conexion_wifi_servidor.conectar_wifi
(
WIFI_SSID,
WIFI_CLAVE,
SERVIDOR_DIRECCION,
TIMEOUT_CONEXION
);
}
}
else
{
conexion_wifi_servidor.enviar();
}
conexion_wifi_servidor.recibir();
}
|
ที่นี่คุณสามารถ ดาวน์โหลดไลบรารี่ ESP8266 สำหรับการสืบค้น HTTP ด้วย Arduino Uno (ไม่มีคอนโซล) และจากที่นี่คุณก็ทำได้ ดาวน์โหลดไลบรารี่แบบสอบถาม HTTP ESP8266 สำหรับ Arduino ที่ใช้คอนโซล กล่าวคือ ต้องใช้พอร์ตอนุกรมโดยซอฟต์แวร์หรือใช้เป็นฮาร์ดแวร์ เช่น เมนบอร์ด Arduino Mega o Arduino Leonardo.
แสดงความคิดเห็น