LOM2M  0.8.0
lom2m-server-base.h
Go to the documentation of this file.
1 /*
2  Copyright (c) 2013-2021 LAAS-CNRS (www.laas.fr)
3  7 Colonel Roche 31077 Toulouse - France
4 
5  The use of this source code requires an agreement with the CNRS.
6 
7  Initial Contributors:
8  David Gauchard, Guillaume Garzone, Thierry Monteil.
9 */
10 
11 #ifndef LOM2M_SERVER_BASE_H
12 #define LOM2M_SERVER_BASE_H
13 
14 #include "configuration.h"
15 
16 #if MQTTS_BINDING
17 #include "keys.h"
18 #include "mqttBinding.h"
19 #include <ESP8266WiFi.h>
20 #include <NTPClient.h>
21 #include <PubSubClient.h>
22 #include <WiFiUdp.h>
23 #endif
24 
25 #include <ESP8266HTTPUpdateServer.h>
26 #include <ESP8266mDNS.h>
27 #include <LittleFS.h>
28 #include <assert.h>
29 #include <map>
30 
31 #include "Entity.h"
32 #include "IPE.h"
33 #include "PersistenceHelper.h"
34 #include "bsp.h"
35 #include "gateway.h"
36 #include "lom2m.h"
37 #include "httpBinding.h"
38 #include "tools.h"
39 
40 #define HEAP_TRACE_MS 5000 // define to 0 to disable
41 #if MQTTS_BINDING
42 WiFiUDP ntpUDP;
43 NTPClient timeClient(ntpUDP, "pool.ntp.org");
44 #endif
45 
46 WiFiClient tcp;
47 String mDNSName = MDNSNAME;
48 ESP8266WebServer om2msrv(8282);
49 #if !CORE_MOCK
50 ESP8266HTTPUpdateServer httpUpdater; // <= OTA
51 #endif
52 
53 #if MQTTS_BINDING
54 WiFiClientSecure* espClient;
55 #endif
56 
57 void
59 void
61 void
63 
64 #if TARGET_UNIX
65 void
66 init_env_variables();
67 #endif
68 
69 bool registered = false;
70 
72 // adm
73 
75 #if HTTP_BINDING
76 void
78 {
79  log("----> NOT SERVED URI = %s\n", om2msrv.uri().c_str());
80 
81  String uri = om2msrv.uri().c_str();
82  uri.replace(F("//"), F("/"));
84 }
85 
86 bool
87 serveFile(String path)
88 {
89  if (path.endsWith("/"))
90  {
91  path += F("index.html");
92  }
93  String pathgz = path + F(".gz");
94  if (LittleFS.exists(pathgz))
95  {
96  path = pathgz;
97  }
98  if (LittleFS.exists(path))
99  {
100  File file = LittleFS.open(path, "r");
101  om2msrv.streamFile(file, contentType(path));
102  file.close();
103  return true;
104  }
105  return false;
106 }
107 
108 #define printHttpCode(code) _printHttpCode(code, #code)
109 HTTPCode
110 _printHttpCode(HTTPCode code, const char* desc)
111 {
112  log("\n----> %s: request returned %d (%s)\n\n", desc, code, HTTPCode2Human(code).c_str());
113  return code;
114 }
115 #endif
117 void
119 {
120  Serial.begin(115200);
121  Serial.printf("\n\nESP826/Arduino - %s\n", ESP.getFullVersion().c_str());
122  Serial.printf("host name = " MDNSNAME "\n");
123  Serial.printf("mac address = %s\n", WiFi.macAddress().c_str());
124  Serial.printf("\n\n---- LOM2M server ----\n\n");
125  Serial.printf("Connecting to '%s'", mySSID);
126  WiFi.hostname(mDNSName);
127 #if TARGET_UNIX
128  const char* ssid = std::getenv("LOM2M_SSID");
129  const char* psk = std::getenv("LOM2M_PSK");
130  if (ssid && psk)
131  {
132  WiFi.begin(ssid, psk);
133  }
134  else
135  {
136  WiFi.begin(mySSID, myPSK);
137  }
138  delete ssid;
139  delete psk;
140 #else
141  WiFi.begin(mySSID, myPSK);
142 #endif
143  while (WiFi.status() != WL_CONNECTED)
144  {
145  Serial.print(".");
146  delay(1000);
147  }
148  log_setup();
149  log("\nConnected\n");
150 
151  log("Try me at these addresses:");
152  log("(with 'telnet <addr> or 'nc -u <addr> 23')");
153 
154  IP = WiFi.localIP().toString();
155  uint8_t mac[6];
156  char ret[14];
157  WiFi.macAddress(mac);
158  sprintf(ret, "%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
159  CSE_ID = "mn-cse-" + String(ret);
160  CSE_NAME = "mn-" + String(ret);
161 #if TARGET_UNIX
162  init_env_variables();
163 #endif
164 
166 
167 #if 1 //CORE_MOCK
168  log("IP=%s\n", IP.c_str());
169 #else
170  for (auto a : addrList)
171  {
172  log("IF='%s' IPv6=%d local=%d hostname='%s' addr= %s",
173  a.ifname().c_str(),
174  a.isV6(),
175  a.isLocal(),
176  a.ifhostname(),
177  a.toString().c_str());
178 
179  if (a.isLegacy())
180  log(" mask:%s / gw:%s",
181  a.netmask().toString().c_str(),
182  a.gw().toString().c_str());
183  }
184 #endif
185 
186 #if 0
187  MDNS.begin(mDNSName);
188  MDNS.addService("http", "tcp", "port", 8282);
189 #endif
190 
191 #if !CORE_MOCK
192  httpUpdater.setup(&om2msrv); // <= setup OTA before om2msrv.begin();
193 #endif
194 
195 #if HTTP_BINDING
196  // enables the HTTP server to store specified headers
197  // otherwise they are discarded for
199  {
200  const char* headers[] = { "Content-Type", "X-M2M-Origin", "Accept", "X-M2M-RI", "X-M2M-RVI" };
201  om2msrv.collectHeaders(headers, sizeof headers / sizeof headers[0]);
202  om2msrv.begin();
203  om2msrv.onNotFound([]() {
204  if (!serveFile(om2msrv.uri()))
205  {
206  serveFallback();
207  }
208  });
209  }
210 #endif // HTTP_BINDING
211 
212 #if PERSISTENCE_FEAT
213  // LOAD DATA FROM PERSISTENCE FILE
214  if (BACKUP_ENABLED)
215  {
216  int error = PersistenceHelper::loadAll();
217  if (error != PersistenceHelper::P_SUCCESS && error != PersistenceHelper::P_FILE_NOT_FOUND)
218  {
219  Serial.println("\n\nERROR: error while loading data from persistence.\n");
220  }
221  }
222 #endif
223 
224 #if MQTTS_BINDING
225  if (MQTTS_ENABLED)
226  {
227  espClient = new WiFiClientSecure();
228  timeClient.begin();
229  while (!timeClient.update())
230  {
231  timeClient.forceUpdate();
232  }
233  espClient->setX509Time(timeClient.getEpochTime());
235  //set MQTT port number to 8883 as per //standard
236  MQTT_CLIENT = new PubSubClient(MQTTS_ENDPOINT.c_str(), MQTTS_PORT, mqtt_callback, *espClient);
238  if (!MQTT_CLIENT->connected())
239  {
241  }
242  }
243 #endif
244 
246  // TODO send CSE REGISTRATION MQTT
248 }
249 
250 #if HEAP_TRACE_MS
252 #endif // HEAP_TRACE_MS
253 #if PERSISTENCE_FEAT
254 Millis lastPersistMs = 0;
255 #endif // PERSISTENCE_FEAT
256 #if MQTTS_BINDING
258 #endif // MQTTS_BINDING
259 
260 void
262 {
263 
264  Millis nowMs = millis();
265 
266 #if DEBUG
267  if (nowMs - heapLastMs > HEAP_TRACE_MS)
268  {
269  heapLastMs = nowMs;
270  log("-- free heap: %d bytes", ESP.getFreeHeap());
271  }
272 #endif
273 #if HTTP_BINDING
275  {
276  om2msrv.handleClient();
277  }
278 #endif // HTTP_BINDING
279 
280 #if MQTTS_BINDING
281  if (MQTTS_ENABLED)
282  {
283  // Cheking if MQTTS client is still connected
284  if (!MQTT_CLIENT->connected())
285  {
286  if (nowMs - lastReconnect > MQTTS_RETRY_PERIOD)
287  {
289  lastReconnect = nowMs;
290  }
291  }
292  else
293  {
294  // Receiving new messages on subscribed topics
295  MQTT_CLIENT->loop();
297  }
298  }
299 #endif //MQTTS_BINDING
300 
301 #if 0
302  MDNS.update();
303 #endif
304  user_loop();
305 #if SUBSCRIPTION_FEAT
307 #endif // SUBSCRIPTION_FEAT
308 
309 #if PERSISTENCE_FEAT
310  if (BACKUP_ENABLED)
311  {
312  if ((nowMs - lastPersistMs > BACKUP_PERIOD) && dataUpdated)
313  {
314  int result = PersistenceHelper::persistAll();
315  Serial.printf("DEBUG: persitence, result code: %d\n", result);
316  dataUpdated = false;
317  lastPersistMs = nowMs;
318  }
319  }
320 #endif
321 }
322 
326 #if TARGET_UNIX
327 void
328 init_env_variables()
329 {
330  if (const char* poa = std::getenv("LOM2M_REMOTE_POA"))
331  {
332  REMOTE_CSE_POA = String(poa);
333  }
334  if (const char* cseId = std::getenv("LOM2M_REMOTE_CSE_ID"))
335  {
336  REMOTE_CSE_ID = String(cseId);
337  }
338  if (const char* cseName = std::getenv("LOM2M_REMOTE_CSE_NAME"))
339  {
340  REMOTE_CSE_NAME = String(cseName);
341  }
342  if (const char* cseName = std::getenv("LOM2M_CSE_NAME"))
343  {
344  CSE_NAME = String(cseName);
345  }
346  if (const char* cseId = std::getenv("LOM2M_CSE_ID"))
347  {
348  CSE_ID = String(cseId);
349  }
350  if (const char* adminOriginator = std::getenv("LOM2M_ADMIN_ORIGINATOR"))
351  {
352  ADMIN_ORIGINATOR = String(adminOriginator);
353  }
354  if (const char* envIp = std::getenv("LOM2M_LOCAL_POA_IP"))
355  {
356  IP = String(envIp);
357  }
358  if (const char* envPort = std::getenv("LOM2M_LOCAL_POA_PORT"))
359  {
360  PORT = String(envPort);
361  }
362  #if PERSISTENCE_FEAT
363  if (const char* envBackup = std::getenv("LOM2M_BACKUP_PERIOD"))
364  {
365  BACKUP_PERIOD = std::atoi(envBackup);
366  }
367  if (const char* envBackup = std::getenv("LOM2M_BACKUP_ENABLED"))
368  {
369  BACKUP_ENABLED = std::atoi(envBackup);
370  }
371  #endif
372  #if MQTTS_BINDING
373  if (const char* in = std::getenv("LOM2M_MQTTS_ENDPOINT"))
374  {
375  MQTTS_ENDPOINT = String(in);
376  }
377  if (const char* in = std::getenv("LOM2M_MQTTS_PORT"))
378  {
379  MQTTS_PORT = std::atoi(in);
380  }
381  if (const char* in = std::getenv("LOM2M_MQTTS_RETRY_PERIOD"))
382  {
383  MQTTS_RETRY_PERIOD = std::atoi(in);
384  }
385  if (const char* in = std::getenv("LOM2M_MQTTS_TIMEOUT"))
386  {
387  MQTTS_TIMEOUT = std::atoi(in);
388  }
389  if (const char* in = std::getenv("LOM2M_MQTTS_CLIENT_ID_PREFIX"))
390  {
391  MQTTS_CLIENT_ID_PREFIX = String(in);
392  }
393  if (const char* mqttsBind = std::getenv("LOM2M_MQTTS_BINDING"))
394  {
395  MQTTS_ENABLED = std::atoi(mqttsBind);
396  }
397  #endif // MQTTS_BINDING
398  if (const char* in = std::getenv("LOM2M_MAX_NUMBER_OF_INSTANCES_DEFAULT"))
399  {
400  MAX_NUMBER_OF_INSTANCES_DEFAULT = std::atoi(in);
401  }
402  if (const char* in = std::getenv("LOM2M_MAX_NUMBER_RESOURCES"))
403  {
404  globalResourcesThreshold = std::atoi(in);
405  }
406  #if HTTP_BINDING
407  if (const char* in = std::getenv("LOM2M_HTTP_BINDING"))
408  {
409  HTTP_BINDING_ENABLED = std::atoi(in);
410  }
411  #endif // HTTP_BINDING
412  if (const char* in = std::getenv("LOM2M_DEFAULT_PROTOCOL"))
413  {
414  DEFAULT_PROTOCOL = String(in);
415  }
416 
417 }
418 #endif
419 
420 #endif // LOM2M_SERVER_BASE_H
void log(const char *fmt,...)
Definition: bsp-esp8266.cpp:100
const char * contentType(const String &filename)
Definition: bsp-esp8266.cpp:13
void log_setup()
Definition: bsp-esp8266.cpp:93
const String HTTPCode2Human(HTTPCode code)
Definition: bsp-esp8266.h:30
decltype(millis()) Millis
Definition: bsp.h:112
HTTPCode
Definition: bsp.h:19
static void serveOM2M(const String &uri)
Definition: httpBinding-esp8266.cpp:555
static void processFirstPendingRequest()
Definition: mqttBinding.cpp:285
#define mySSID
Definition: configuration.h:18
#define myPSK
Definition: configuration.h:19
#define CONF_MQTTS_CLIENT_BUFFER_SIZE
Definition: configuration.h:107
bool registerCSE()
Definition: gateway.cpp:883
void handleNotifications(int max=5)
Definition: Notify.cpp:106
bool serveFile(String path)
Definition: lom2m-server-base.h:87
String mDNSName
Definition: lom2m-server-base.h:47
WiFiUDP ntpUDP
Definition: lom2m-server-base.h:42
void user_initial_setup()
Millis heapLastMs
Definition: lom2m-server-base.h:251
bool registered
Definition: lom2m-server-base.h:69
void setup()
Definition: lom2m-server-base.h:118
#define HEAP_TRACE_MS
Definition: lom2m-server-base.h:40
Millis lastReconnect
Definition: lom2m-server-base.h:257
WiFiClientSecure * espClient
Definition: lom2m-server-base.h:54
void serveFallback()
Definition: lom2m-server-base.h:77
ESP8266WebServer om2msrv(8282)
HTTPCode _printHttpCode(HTTPCode code, const char *desc)
Definition: lom2m-server-base.h:110
void user_final_setup()
NTPClient timeClient(ntpUDP, "pool.ntp.org")
ESP8266HTTPUpdateServer httpUpdater
Definition: lom2m-server-base.h:50
void user_loop()
WiFiClient tcp
Definition: lom2m-server-base.h:46
void loop()
Definition: lom2m-server-base.h:261
String REMOTE_CSE_NAME
String IP
Definition: lom2m.cpp:18
int MQTTS_PORT
Definition: lom2m.cpp:34
String MQTTS_CLIENT_ID_PREFIX
Definition: lom2m.cpp:37
String MQTTS_ENDPOINT
Definition: lom2m.cpp:36
String CSE_ID
Definition: lom2m.cpp:13
int MQTTS_ENABLED
Definition: lom2m.cpp:33
String CSE_NAME
Definition: lom2m.cpp:14
int MQTTS_TIMEOUT
Definition: lom2m.cpp:38
String PORT
Definition: lom2m.cpp:17
int MAX_NUMBER_OF_INSTANCES_DEFAULT
Definition: lom2m.cpp:40
String DEFAULT_PROTOCOL
Definition: lom2m.cpp:21
bool dataUpdated
Definition: lom2m.cpp:104
int globalResourcesThreshold
Definition: lom2m.cpp:41
int MQTTS_RETRY_PERIOD
Definition: lom2m.cpp:35
String ADMIN_ORIGINATOR
String REMOTE_CSE_POA
int HTTP_BINDING_ENABLED
Definition: lom2m.cpp:26
String REMOTE_CSE_ID
PubSubClient * MQTT_CLIENT
Definition: mqttBinding.cpp:26
bool mqtt_setup(WiFiClientSecure *espClient)
Definition: mqttBinding.cpp:47
void mqtt_callback(char *topic, byte *payload, unsigned int length)
Definition: mqttBinding.cpp:194
void mqtt_reconnect(WiFiClientSecure *espClient, PubSubClient *client, bool loop)
Definition: mqttBinding.cpp:140