1
+ /*
2
+ * HelTec Automation(TM) Wireless Bridge dedicated test code, witch includ
3
+ * follow functions:
4
+ *
5
+ * - Transfer WiFi message to LoRaWAN payload;
6
+ *
7
+ * Detail description about this demo code, please refer to this document:
8
+ *
9
+ *
10
+ * by Aaron.Lee from HelTec AutoMation, ChengDu, China
11
+ * 成都惠利特自动化科技有限公司
12
+ * www.heltec.cn
13
+ *
14
+ * this project also realess in GitHub:
15
+ * https://github.com/HelTecAutomation/ESP32_LoRaWAN
16
+ */
17
+ #include " Arduino.h"
18
+ #include < WiFi.h>
19
+ #include < WiFiClient.h>
20
+ #include < WebServer.h>
21
+ #include < ESPmDNS.h>
22
+ #include < Update.h>
23
+ #include < LoRaWan_APP.h>
24
+
25
+
26
+ const char * ssid = " Your_WiFi_Name" ;
27
+ const char * password = " Your_WiFi_Password" ;
28
+
29
+
30
+ /* OTAA para*/
31
+ uint8_t devEui[] = { 0x22 , 0x32 , 0x33 , 0x00 , 0x00 , 0x88 , 0x88 , 0x02 };
32
+ uint8_t appEui[] = { 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 };
33
+ uint8_t appKey[] = { 0x88 , 0x88 , 0x88 , 0x88 , 0x88 , 0x88 , 0x88 , 0x88 , 0x88 , 0x88 , 0x88 , 0x88 , 0x88 , 0x88 , 0x66 , 0x01 };
34
+
35
+ /* ABP para*/
36
+ uint8_t nwkSKey[] = { 0x15 , 0xb1 , 0xd0 , 0xef , 0xa4 , 0x63 , 0xdf , 0xbe , 0x3d , 0x11 , 0x18 , 0x1e , 0x1e , 0xc7 , 0xda ,0x85 };
37
+ uint8_t appSKey[] = { 0xd7 , 0x2c , 0x78 , 0x75 , 0x8c , 0xdc , 0xca , 0xbf , 0x55 , 0xee , 0x4a , 0x77 , 0x8d , 0x16 , 0xef ,0x67 };
38
+ uint32_t devAddr = ( uint32_t )0x007e6ae1 ;
39
+
40
+ /* LoraWan channelsmask, default channels 0-7*/
41
+ uint16_t userChannelsMask[6 ]={ 0x00FF ,0x0000 ,0x0000 ,0x0000 ,0x0000 ,0x0000 };
42
+
43
+ /* LoraWan region, select in arduino IDE tools*/
44
+ LoRaMacRegion_t loraWanRegion = ACTIVE_REGION;
45
+
46
+ /* LoraWan Class, Class A and Class C are supported*/
47
+ DeviceClass_t loraWanClass = CLASS_C;
48
+
49
+ /* the application data transmission duty cycle. value in [ms].*/
50
+ uint32_t appTxDutyCycle = 15000 ;
51
+
52
+ /* OTAA or ABP*/
53
+ bool overTheAirActivation = true ;
54
+
55
+ /* ADR enable*/
56
+ bool loraWanAdr = true ;
57
+
58
+ /* Indicates if the node is sending confirmed or unconfirmed messages */
59
+ bool isTxConfirmed = true ;
60
+
61
+ /* Application port */
62
+ uint8_t appPort = 2 ;
63
+ /* !
64
+ * Number of trials to transmit the frame, if the LoRaMAC layer did not
65
+ * receive an acknowledgment. The MAC performs a datarate adaptation,
66
+ * according to the LoRaWAN Specification V1.0.2, chapter 18.4, according
67
+ * to the following table:
68
+ *
69
+ * Transmission nb | Data Rate
70
+ * ----------------|-----------
71
+ * 1 (first) | DR
72
+ * 2 | DR
73
+ * 3 | max(DR-1,0)
74
+ * 4 | max(DR-1,0)
75
+ * 5 | max(DR-2,0)
76
+ * 6 | max(DR-2,0)
77
+ * 7 | max(DR-3,0)
78
+ * 8 | max(DR-3,0)
79
+ *
80
+ * Note, that if NbTrials is set to 1 or 2, the MAC will not decrease
81
+ * the datarate, in case the LoRaMAC layer did not receive an acknowledgment
82
+ */
83
+ uint8_t confirmedNbTrials = 4 ;
84
+
85
+ static void prepareTxFrame ( uint8_t port )
86
+ {
87
+ appDataSize = 4 ;// AppDataSize max value is 64
88
+ appData[0 ] = ' A' ;
89
+ appData[1 ] = ' B' ;
90
+ appData[2 ] = ' C' ;
91
+ appData[3 ] = ' D' ;
92
+ }
93
+
94
+ String LoRa_data;
95
+ uint16_t num=0 ;
96
+ bool LoRaDownLink = false ;
97
+ uint32_t LoRadonwlinkTime;
98
+ void downLinkDataHandle (McpsIndication_t *mcpsIndication)
99
+ {
100
+ LoRa_data = " " ;
101
+ Serial.printf (" +REV DATA:%s,RXSIZE %d,PORT %d\r\n " ,mcpsIndication->RxSlot ?" RXWIN2" :" RXWIN1" ,mcpsIndication->BufferSize ,mcpsIndication->Port );
102
+ Serial.print (" +REV DATA:" );
103
+ for (uint8_t i=0 ;i<mcpsIndication->BufferSize ;i++)
104
+ {
105
+ Serial.printf (" %d" ,mcpsIndication->Buffer [i]);
106
+ LoRa_data = LoRa_data + (String)(char )mcpsIndication->Buffer [i];
107
+ }
108
+ LoRaDownLink = true ;
109
+ LoRadonwlinkTime = millis ();
110
+ num++;
111
+ Serial.println ();
112
+ Serial.print (num);
113
+ Serial.print (" :" );
114
+ Serial.println (LoRa_data);
115
+ }
116
+
117
+ WebServer server (80 );
118
+ String htmlS =" <html>\
119
+ <head>\
120
+ <title>Wireless_Bridge</title>\
121
+ <meta name=\" viewport\" content=\" width=device-width, initial-scale=1\" >\
122
+ </head>\
123
+ <style type=\" text/css\" >\
124
+ .header{display: block;margin-top:10px;text-align:center;width:100%;font-size:10px}\
125
+ .input{display: block;text-align:center;width:100%}\
126
+ .input input{height: 20px;width: 300px;text-align:center;border-radius:15px;}\
127
+ .input select{height: 26px;width: 305px;text-align:center;border-radius:15px;}\
128
+ .btn,button{width: 305px;height: 40px;border-radius:20px; background-color: #000000; border:0px; color:#ffffff; margin-top:20px;}\
129
+ </style>\
130
+ <script type=\" text/javascript\" >\
131
+ function myrefresh()\
132
+ {\
133
+ window.location.reload();\
134
+ }\
135
+ window.onload=function(){\
136
+ setTimeout('myrefresh()',10000);\
137
+ } \
138
+ </script>\
139
+ <body>\
140
+ <div style=\" width:100%;text-align:center;font-size:25px;font-weight:bold;margin-bottom:20px\" >Wireless_Bridge</div>\
141
+ <div style=\" width:100%;text-align:center;\" >\
142
+ <div class=\" header\" ><span>(Note 1: The default refresh time of this page is 10s. If you need to modify the refresh time, you can modify it in the 'setTimeout' function.)</span></div>\
143
+ <div class=\" header\" ><span>(Note 2: The refresh time needs to be modified according to the data sending frequency.)</span></div>\
144
+ <div class=\" header\" ><span>Data: " ;
145
+ String htmlF = " </span></div>\
146
+ </form>\
147
+ </div>\
148
+ </body>\
149
+ </html>" ;
150
+
151
+ String htmlW = " <html>\
152
+ <head>\
153
+ <title>Wireless_Bridge</title>\
154
+ <meta name=\" viewport\" content=\" width=device-width, initial-scale=1\" >\
155
+ </head>\
156
+ <style type=\" text/css\" >\
157
+ .header{display: block;margin-top:10px;text-align:center;width:100%;font-size:10px}\
158
+ .input{display: block;text-align:center;width:100%}\
159
+ .input input{height: 20px;width: 300px;text-align:center;border-radius:15px;}\
160
+ .input select{height: 26px;width: 305px;text-align:center;border-radius:15px;}\
161
+ .btn,button{width: 305px;height: 40px;border-radius:20px; background-color: #000000; border:0px; color:#ffffff; margin-top:20px;}\
162
+ </style>\
163
+ <script type=\" text/javascript\" >\
164
+ window.onload=function(){\
165
+ document.getElementsByName(\" server\" )[0].value = \"\" ;\
166
+ } \
167
+ </script>\
168
+ <body>\
169
+ <div style=\" width:100%;text-align:center;font-size:25px;font-weight:bold;margin-bottom:20px\" >Wireless_Bridge</div>\
170
+ <div style=\" width:100%;text-align:center;\" >\
171
+ <div class=\" header\" ><span>(Note 1: The data sent from this webpage to LoRa needs to be decoded to be able to be viewed normally.)</span></div>\
172
+ <div class=\" header\" ><span>(Note 2: The default size of data sent by LoRa is 4 bytes, which can be modified in the program.)</span></div>\
173
+ <form method=\" POST\" action=\"\" onsubmit=\"\" >\
174
+ <div class=\" header\" ><span>DATA</span></div>\
175
+ <div class=\" input\" ><input type=\" text\" name=\" server\" value=\"\" ></div>\
176
+ <div class=\" header\" ><input class=\" btn\" type=\" submit\" name=\" submit\" value=\" Submit\" ></div>\
177
+ </form>\
178
+ </div>\
179
+ </body>\
180
+ </html>" ;
181
+
182
+ String Page_data=" " ;
183
+ String symbol=" :" ;
184
+ void ROOT_HTML ()
185
+ {
186
+ Page_data =Page_data+ (String)num+ symbol + LoRa_data +" <br>" ;
187
+ String html = htmlS + Page_data + htmlF;
188
+ server.send (200 ," text/html" ,html);
189
+ }
190
+
191
+ bool WiFiDownLink = false ;
192
+ uint32_t WiFidonwlinkTime;
193
+ String Write_data=" " ;
194
+ void ROOT_HTMLW ()
195
+ {
196
+ if (server.hasArg (" server" ))
197
+ {
198
+ Serial.println (server.arg (" server" ));
199
+ Write_data=server.arg (" server" );
200
+ WiFiDownLink = true ;
201
+ WiFidonwlinkTime = millis ();
202
+ unsigned char *puc;
203
+ puc = (unsigned char *)(&Write_data);
204
+ appDataSize = 4 ;// AppDataSize max value is 64
205
+ appData[0 ] = puc[0 ];
206
+ appData[1 ] = puc[1 ];
207
+ appData[2 ] = puc[2 ];
208
+ appData[3 ] = puc[3 ];
209
+ LoRaWAN.send ();
210
+ }
211
+ server.send (200 ," text/html" ,htmlW);
212
+ }
213
+
214
+ void setup (void ) {
215
+ Serial.begin (115200 );
216
+ while (!Serial);
217
+ Mcu.begin ();
218
+ deviceState = DEVICE_STATE_INIT;
219
+ pinMode (WIFI_LED, OUTPUT);
220
+ pinMode (LoRa_LED, OUTPUT);
221
+ digitalWrite (WIFI_LED, HIGH);
222
+ digitalWrite (LoRa_LED, HIGH);
223
+ delay (1000 );
224
+ digitalWrite (WIFI_LED, LOW);
225
+ digitalWrite (LoRa_LED, LOW);
226
+ Serial.println ();
227
+ Serial.println (" Booting Sketch..." );
228
+ WiFi.mode (WIFI_STA);
229
+ WiFi.begin (ssid, password);
230
+ if (WiFi.waitForConnectResult () == WL_CONNECTED) {
231
+ server.on (" /" , ROOT_HTML);
232
+ server.on (" /w" , ROOT_HTMLW);
233
+ server.begin ();
234
+ MDNS.addService (" http" , " tcp" , 80 );
235
+ Serial.println (" " );
236
+ Serial.println (" WiFi connected." );
237
+ Serial.println (" View page IP address: " );
238
+ Serial.println (WiFi.localIP ());
239
+ Serial.println (" Write page IP address: " );
240
+ Serial.print (WiFi.localIP ());
241
+ Serial.println (" /w" );
242
+ } else {
243
+ Serial.println (" WiFi Failed" );
244
+ }
245
+ }
246
+
247
+ void loop (void ) {
248
+ server.handleClient ();
249
+ switch ( deviceState )
250
+ {
251
+ case DEVICE_STATE_INIT:
252
+ {
253
+ #if (LORAWAN_DEVEUI_AUTO)
254
+ LoRaWAN.generateDeveuiByChipID ();
255
+ #endif
256
+ LoRaWAN.init (loraWanClass,loraWanRegion);
257
+ break ;
258
+ }
259
+ case DEVICE_STATE_JOIN:
260
+ {
261
+ LoRaWAN.join ();
262
+ break ;
263
+ }
264
+ case DEVICE_STATE_SEND:
265
+ {
266
+ prepareTxFrame ( appPort );
267
+ LoRaWAN.send ();
268
+ deviceState = DEVICE_STATE_CYCLE;
269
+ break ;
270
+ }
271
+ case DEVICE_STATE_CYCLE:
272
+ {
273
+ // Schedule next packet transmission
274
+ txDutyCycleTime = appTxDutyCycle + randr ( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
275
+ LoRaWAN.cycle (txDutyCycleTime);
276
+ deviceState = DEVICE_STATE_SLEEP;
277
+ break ;
278
+ }
279
+ case DEVICE_STATE_SLEEP:
280
+ {
281
+ LoRaWAN.sleep (loraWanClass);
282
+ break ;
283
+ }
284
+ default :
285
+ {
286
+ deviceState = DEVICE_STATE_INIT;
287
+ break ;
288
+ }
289
+ }
290
+ if (LoRaDownLink)
291
+ {
292
+ LoRaDownLink = false ;
293
+ digitalWrite (LoRa_LED,HIGH);
294
+ }
295
+ else if (digitalRead (LoRa_LED) && (millis ()-LoRadonwlinkTime)> 1000 )
296
+ {
297
+ digitalWrite (LoRa_LED,LOW);
298
+ }
299
+ if (WiFiDownLink)
300
+ {
301
+ WiFiDownLink = false ;
302
+ digitalWrite (WIFI_LED,HIGH);
303
+ }
304
+ else if (digitalRead (WIFI_LED) && (millis ()-WiFidonwlinkTime)> 1000 )
305
+ {
306
+ digitalWrite (WIFI_LED,LOW);
307
+ }
308
+ }
0 commit comments