EnigmaIOT  0.9.8
Secure sensor and gateway platform based on ESP8266 and ESP32
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GatewayAPI.cpp
Go to the documentation of this file.
1 
9 #include "GatewayAPI.h"
10 #include <functional>
11 
12 using namespace std;
13 using namespace placeholders;
14 
15 const char* getNodeNumberUri = "/api/gw/nodenumber";
16 const char* getMaxNodesUri = "/api/gw/maxnodes";
17 const char* getNodesUri = "/api/gw/nodes";
18 const char* getNodeUri = "/api/node/node";
19 const char* getGwInfoUri = "/api/gw/info";
20 const char* getGwRestartUri = "/api/gw/restart";
21 const char* getGwResettUri = "/api/gw/reset";
22 const char* getNodeRestartUri = "/api/node/restart";
23 const char* nodeIdParam = "nodeid";
24 const char* nodeNameParam = "nodename";
25 const char* nodeAddrParam = "nodeaddr";
26 const char* confirmParam = "confirm";
27 
29  //if (!gw) {
30  // return;
31  //}
32  //gateway = gw;
33  server = new AsyncWebServer (WEB_API_PORT);
34  server->on (getNodeNumberUri, HTTP_GET, std::bind (&GatewayAPI::getNodeNumber, this, _1));
35  server->on (getMaxNodesUri, HTTP_GET, std::bind (&GatewayAPI::getMaxNodes, this, _1));
36  server->on (getNodesUri, HTTP_GET, std::bind (&GatewayAPI::getNodes, this, _1));
37  server->on (getNodeUri, HTTP_GET | HTTP_DELETE, std::bind (&GatewayAPI::nodeOp, this, _1));
38  server->on (getGwInfoUri, HTTP_GET, std::bind (&GatewayAPI::getGwInfo, this, _1));
39  server->on (getGwRestartUri, HTTP_PUT, std::bind (&GatewayAPI::restartGw, this, _1));
40  server->on (getGwResettUri, HTTP_PUT, std::bind (&GatewayAPI::resetGw, this, _1));
41  server->on (getNodeRestartUri, HTTP_PUT, std::bind (&GatewayAPI::restartNode, this, _1));
42  server->onNotFound (std::bind (&GatewayAPI::onNotFound, this, _1));
43  server->begin ();
44 }
45 
46 void GatewayAPI::getNodeNumber (AsyncWebServerRequest* request) {
47  char response[25];
48 
49  snprintf (response, 25, "{\"nodeNumber\":%d}", EnigmaIOTGateway.getActiveNodesNumber ());
50  DEBUG_INFO ("Response: %s", response);
51  request->send (200, "application/json", response);
52 }
53 
54 char* GatewayAPI::buildGwInfo (char* gwInfo, size_t len) {
55  DEBUG_INFO ("Build Gateway Info");
56  //resultCode = 200;
57  //time_t currentMillis = millis ();
58  snprintf (gwInfo, len, "{\"version\":\"%d.%d.%d\",\"network\":\"%s\",\"addresses\":{\"AP\":\"%s\",\"STA\":\"%s\"},"
59  "\"channel\":%d,\"ap\":\"%s\",\"bssid\":\"%s\",\"rssi\":%d,"
60 #ifdef ESP32
61  "\"txpower\":%.1f,"
62 #endif
63  "\"dns\":\"%s\",\"mem\":%d}",
66  WiFi.macAddress ().c_str (), WiFi.softAPmacAddress ().c_str (),
67  WiFi.channel (), WiFi.SSID ().c_str (), WiFi.BSSIDstr ().c_str (), WiFi.RSSI (),
68 #ifdef ESP32
69  (float)(WiFi.getTxPower ()) / 4,
70 #endif
71  WiFi.dnsIP ().toString ().c_str (),
72  ESP.getFreeHeap ()
73  );
74  DEBUG_DBG ("GwInfo: %s", gwInfo);
75  return gwInfo;
76 }
77 
78 void GatewayAPI::getGwInfo (AsyncWebServerRequest* request) {
79  int resultCode = 404;
80  char response[RESPONSE_SIZE];
81  const char* strTemp = buildGwInfo (response, RESPONSE_SIZE);
82  if (strTemp) {
83  resultCode = 200;
84  }
85  if (resultCode == 404) {
86  snprintf (response, RESPONSE_SIZE, "{\"result\":\"not found\"}");
87  }
88  DEBUG_DBG ("Response: %d --> %s", resultCode, response);
89  request->send (resultCode, "application/json", response);
90 }
91 
92 Node* GatewayAPI::getNodeFromParam (AsyncWebServerRequest* request) {
93  Node* node = NULL;
94  int params = request->params ();
95  int nodeIndex = -1;
96 
97  for (int i = 0; i < params; i++) {
98  AsyncWebParameter* p = request->getParam (i);
99  if (p->name () == nodeIdParam) {
100  if (isNumber (p->value ())) {
101  nodeIndex = atoi (p->value ().c_str ());
102  DEBUG_INFO ("Node to process is %d", nodeIndex);
103  node = EnigmaIOTGateway.nodelist.getNodeFromID (nodeIndex);
104  break;
105  }
106  }
107  if (p->name () == nodeNameParam) {
108  if (strcmp (p->value ().c_str (), BROADCAST_NONE_NAME)) {
109  node = EnigmaIOTGateway.nodelist.getNodeFromName (p->value ().c_str ());
110  DEBUG_INFO ("Node to process is %s", node ? node->getNodeName () : "NULL");
111  } else {
112  DEBUG_INFO ("Wrong node name %s", p->value ().c_str ());
113  }
114  break;
115  }
116  if (p->name () == nodeAddrParam) {
117  uint8_t addr[ENIGMAIOT_ADDR_LEN];
118  uint8_t* addrResult = str2mac (p->value ().c_str (), addr);
119  if (addrResult) {
120  if (memcmp (addr, BROADCAST_ADDRESS, ENIGMAIOT_ADDR_LEN)) {
122  DEBUG_INFO ("Node to process is %s", p ? p->value ().c_str () : "NULL");
123  }
124  }
125  break;
126  }
127  DEBUG_DBG ("Parameter %s = %s", p->name ().c_str (), p ? p->value ().c_str () : "NULL");
128  }
129 
130  DEBUG_DBG ("NodeId = %d, node: %p", nodeIndex, node);
131 
132  if (node) {
133  if (node->isRegistered ()) {
134  return node;
135  }
136  }
137  return node;
138 }
139 
140 const char* GatewayAPI::deleteNode (Node* node, int& resultCode) {
141  if (node) {
142  DEBUG_DBG ("Node %d is %p", node->getNodeId (), node);
143  if (node->isRegistered ()) {
144  DEBUG_INFO ("Node %d is registered", node->getNodeId ());
145  resultCode = 200;
147  return "{\"result\":\"ok\"}";
148  } else {
149  DEBUG_INFO ("Node %d is not registered", node->getNodeId ());
150  }
151  }
152  return NULL;
153 }
154 
155 char* GatewayAPI::getNodeInfo (Node* node, int& resultCode, char* nodeInfo, size_t len) {
156  if (node) {
157  DEBUG_DBG ("Node %d is %p", node->getNodeId (), node);
158  if (node->isRegistered ()) {
159  DEBUG_INFO ("Node %d is registered", node->getNodeId ());
160  resultCode = 200;
161  time_t currentMillis = millis ();
162  uint8_t* version = node->getVersion ();
163  size_t index;
164  index = snprintf (nodeInfo, len,
165  "{\"version\":\"%d.%d.%d\",\"node_id\":%d,\"address\":\"" MACSTR "\","\
166  "\"keyValidSince\":%lld,\"lastMessageTime\":%lld,\"sleepy\":%s,"\
167  "\"Broadcast\":%s,\"TimeSync\":%s,\"rssi\":%d,\"packetsHour\":%f,\"per\":%f",
168  version[0], version[1], version[2],
169  node->getNodeId (),
170  MAC2STR (node->getMacAddress ()),
171  currentMillis - node->getKeyValidFrom (),
172  currentMillis - node->getLastMessageTime (),
173  node->getSleepy () ? "True" : "False",
174  node->broadcastIsEnabled () ? "True" : "False",
175  node->useTimeSync () ? "True" : "False",
176  node->getRSSI (),
177  node->packetsHour,
178  node->per
179  );
180  char* nodeName = node->getNodeName ();
181  if (nodeName && strlen (nodeName)) {
182  index = index + snprintf (nodeInfo + index, len - index, ",\"Name\":\"%s\"", nodeName);
183  }
184  snprintf (nodeInfo + index, len - index, "}");
185  DEBUG_DBG ("NodeInfo: %s", nodeInfo);
186  return nodeInfo;
187  } else {
188  DEBUG_INFO ("Node %d is not registered", node->getNodeId ());
189  }
190  }
191  return NULL;
192 }
193 
195  return EnigmaIOTGateway.sendDownstream (node->getMacAddress (), NULL, 0, RESTART_NODE);
196 }
197 
198 void GatewayAPI::restartNode (AsyncWebServerRequest* request) {
199  Node* node;
200  int resultCode = 404;
201  char response[RESPONSE_SIZE];
202 
203  node = getNodeFromParam (request);
204 
205  DEBUG_WARN ("Send restart command to node %p", node);
206 
207  bool result = restartNodeRequest (node);
208  if (result) {
209  snprintf (response, 30, "{\"node_restart\":\"processed\"}");
210  resultCode = 200;
211  }
212  if (resultCode == 404) {
213  snprintf (response, 25, "{\"result\":\"not found\"}");
214  }
215  DEBUG_WARN ("Response: %d --> %s", resultCode, response);
216  request->send (resultCode, "application/json", response);
217 }
218 
219 void GatewayAPI::nodeOp (AsyncWebServerRequest* request) {
220  Node* node;
221  int resultCode = 404;
222  char response[RESPONSE_SIZE];
223 
224  node = getNodeFromParam (request);
225 
226  WebRequestMethodComposite method = request->method ();
227  DEBUG_INFO ("Method: %s", methodToString (request->method ()).c_str ());
228 
229  if (method == HTTP_DELETE) {
230  DEBUG_INFO ("Delete node %p", node);
231  const char* strTemp = deleteNode (node, resultCode);
232  if (strTemp) {
233  strncpy (response, strTemp, RESPONSE_SIZE);
234  }
235  } else if (method == HTTP_GET) {
236  DEBUG_INFO ("Info node %p", node);
237  const char* strTemp = getNodeInfo (node, resultCode, response, RESPONSE_SIZE);
238  DEBUG_DBG ("strTemp = %p", strTemp);
239  if (!strTemp) {
240  //strncpy (response, strTemp, 200);
241  resultCode = 404;
242  }
243  }
244  if (resultCode == 404) {
245  snprintf (response, 25, "{\"result\":\"not found\"}");
246  }
247  DEBUG_DBG ("Response: %d --> %s", resultCode, response);
248  request->send (resultCode, "application/json", response);
249 }
250 
251 void GatewayAPI::getMaxNodes (AsyncWebServerRequest* request) {
252  char response[25];
253 
254  snprintf (response, 25, "{\"maxNodes\":%d}", NUM_NODES);
255  DEBUG_INFO ("Response: %s", response);
256  request->send (200, "application/json", response);
257 }
258 
259 void GatewayAPI::restartGw (AsyncWebServerRequest* request) {
260  char response[30];
261  bool confirm = false;
262  int resultCode = 404;
263 
264  int params = request->params ();
265 
266  for (int i = 0; i < params; i++) {
267  AsyncWebParameter* p = request->getParam (i);
268  if (p->name () == confirmParam) {
269  if (p->value () == "1") {
270  confirm = true;
271  resultCode = 200;
272  break;
273  }
274  }
275  }
276 
277  if (confirm) {
278  snprintf (response, 30, "{\"gw_restart\":\"processed\"}");
279  request->send (resultCode, "application/json", response);
280  } else {
281  snprintf (response, 25, "{\"gw_restart\":\"fail\"}");
282  request->send (resultCode, "application/json", response);
283  }
284 
285  DEBUG_INFO ("Response: %s", response);
286 
287  if (confirm && EnigmaIOTGateway.notifyRestartRequested) {
289  }
290 }
291 
292 void GatewayAPI::resetGw (AsyncWebServerRequest* request) {
293  char response[30];
294  bool confirm = false;
295  int resultCode = 404;
296 
297  int params = request->params ();
298 
299  for (int i = 0; i < params; i++) {
300  AsyncWebParameter* p = request->getParam (i);
301  if (p->name () == confirmParam) {
302  if (p->value () == "1") {
303  confirm = true;
304  resultCode = 200;
305  break;
306  }
307  }
308  }
309 
310  if (confirm) {
311  snprintf (response, 30, "{\"gw_reset\":\"processed\"}");
312  request->send (resultCode, "application/json", response);
313  } else {
314  snprintf (response, 25, "{\"gw_reset\":\"fail\"}");
315  request->send (resultCode, "application/json", response);
316  }
317 
318  DEBUG_INFO ("Response: %s", response);
319 
321 
322 }
323 
324 
325 void GatewayAPI::getNodes (AsyncWebServerRequest* request) {
326  Node* node = NULL;
327 
328  AsyncResponseStream* response = request->beginResponseStream ("application/json");
329  response->setCode (200);
330 
331  response->print ("{\"nodes\":[");
332  do {
333  bool first = (node == NULL);
335  if (node && !first) {
336  DEBUG_DBG ("First is %s, node is %p", first ? "true" : "false", node);
337  response->print (',');
338  }
339  if (node) {
340  DEBUG_DBG ("LastNode: %u, node: %p", node->getNodeId (), node);
341  }
342  if (node) {
343  DEBUG_DBG ("Got node. NodeId -> %u", node->getNodeId ());
344  response->printf ("{\"nodeId\":%u,\"address\":\"" MACSTR "\"",
345  node->getNodeId (),
346  MAC2STR (node->getMacAddress ()));
347  char* nodeName = node->getNodeName ();
348  if (nodeName && strlen (nodeName)) {
349  response->printf (", \"name\":\"%s\"", node->getNodeName ());
350  }
351  response->print ("}");
352  }
353  } while (node != NULL);
354  response->print ("]}");
355  request->send (response);
356 }
357 
358 String methodToString (WebRequestMethodComposite method) {
359  switch (method) {
360  case HTTP_GET:
361  return String ("GET");
362  case HTTP_POST:
363  return String ("POST");
364  case HTTP_DELETE:
365  return String ("DELETE");
366  case HTTP_PUT:
367  return String ("PUT");
368  case HTTP_PATCH:
369  return String ("PATCH");
370  case HTTP_HEAD:
371  return String ("HEAD");
372  case HTTP_OPTIONS:
373  return String ("OPTIONS");
374  }
375  return "";
376 }
377 
378 void GatewayAPI::onNotFound (AsyncWebServerRequest* request) {
379  DEBUG_WARN ("404 Not found: %s", request->url ().c_str ());
380  DEBUG_WARN ("Method: %s", methodToString (request->method ()).c_str ());
381  int params = request->params ();
382  for (int i = 0; i < params; i++) {
383 #if DEBUG_LEVEL >= INFO
384  AsyncWebParameter* p = request->getParam (i);
385  DEBUG_INFO ("Parameter %s = %s", p->name ().c_str (), p->value ().c_str ());
386 #endif
387  }
388  request->send (404, "text/plain", "Not Found");
389 }
390 
GatewayAPI::onNotFound
void onNotFound(AsyncWebServerRequest *request)
Processes unknown entry points or methods.
Definition: GatewayAPI.cpp:378
EnigmaIOTGatewayClass::getActiveNodesNumber
int getActiveNodesNumber()
Gets number of active nodes.
Definition: EnigmaIOTGateway.h:592
EnigmaIOTGatewayClass::invalidateKey
bool invalidateKey(Node *node, gwInvalidateReason_t reason)
Creates an InvalidateKey message and sned it. This trigger a new key agreement to start on related no...
Definition: EnigmaIOTGateway.cpp:1624
getGwRestartUri
const char * getGwRestartUri
Definition: GatewayAPI.cpp:20
EnigmaIOTGatewayClass::doResetConfig
static void doResetConfig(void)
Activates a flag that signals that configuration has to be saved.
Definition: EnigmaIOTGateway.cpp:47
RESTART_NODE
@ RESTART_NODE
Definition: NodeList.h:65
NodeList::getNodeFromName
Node * getNodeFromName(const char *name)
Gets node that correspond with given node name.
Definition: NodeList.cpp:174
nodeIdParam
const char * nodeIdParam
Definition: GatewayAPI.cpp:23
ENIGMAIOT_ADDR_LEN
static const size_t ENIGMAIOT_ADDR_LEN
Address size. Mac address = 6 bytes.
Definition: EnigmaIoTconfigAdvanced.h:23
GatewayAPI::getMaxNodes
void getMaxNodes(AsyncWebServerRequest *request)
Processes max node number request.
Definition: GatewayAPI.cpp:251
GatewayAPI
Definition: GatewayAPI.h:25
Node::getVersion
uint8_t * getVersion()
Gets node EnigmaIOT version.
Definition: NodeList.h:449
GwAPI
GatewayAPI GwAPI
API instance.
Definition: GatewayAPI.cpp:391
Node::broadcastIsEnabled
bool broadcastIsEnabled()
Returns if node broadcast mode is enabled. In that case, node is able to send and receive encrypted b...
Definition: NodeList.h:373
getGwInfoUri
const char * getGwInfoUri
Definition: GatewayAPI.cpp:19
str2mac
uint8_t * str2mac(const char *macAddrString, uint8_t *macBytes)
Debug helper function that creates MAC address byte array from text representation.
Definition: helperFunctions.cpp:104
NodeList::getNodeFromMAC
Node * getNodeFromMAC(const uint8_t *mac)
Gets node that correspond with given address.
Definition: NodeList.cpp:142
GatewayAPI::getNodeFromParam
Node * getNodeFromParam(AsyncWebServerRequest *request)
Gets node reference from request parameters.
Definition: GatewayAPI.cpp:92
GatewayAPI::resetGw
void resetGw(AsyncWebServerRequest *request)
Processes gateway configuration reset request.
Definition: GatewayAPI.cpp:292
ENIGMAIOT_PROT_VERS
static const uint8_t ENIGMAIOT_PROT_VERS[3]
EnitmaIoT Version.
Definition: EnigmaIoTconfig.h:16
EnigmaIOTGatewayClass::getNetworkName
char * getNetworkName()
Gets EnigmaIOT network name.
Definition: EnigmaIOTGateway.h:349
KICKED
@ KICKED
Definition: EnigmaIOTGateway.h:82
methodToString
String methodToString(WebRequestMethodComposite method)
Definition: GatewayAPI.cpp:358
GatewayAPI::restartNodeRequest
bool restartNodeRequest(Node *node)
Sends restart node message.
Definition: GatewayAPI.cpp:194
GatewayAPI::getNodes
void getNodes(AsyncWebServerRequest *request)
Processes node list request.
Definition: GatewayAPI.cpp:325
getGwResettUri
const char * getGwResettUri
Definition: GatewayAPI.cpp:21
nodeAddrParam
const char * nodeAddrParam
Definition: GatewayAPI.cpp:25
Node::getSleepy
bool getSleepy()
Gets node working mode regarding battery saving strategy. If node is sleepy it will turn into deep sl...
Definition: NodeList.h:363
EnigmaIOTGatewayClass::notifyRestartRequested
simpleEventHandler_t notifyRestartRequested
Callback function that will be invoked when a hardware restart is requested.
Definition: EnigmaIOTGateway.h:138
GatewayAPI::nodeOp
void nodeOp(AsyncWebServerRequest *request)
Processes node information request.
Definition: GatewayAPI.cpp:219
GatewayAPI.h
API web server to control EnigmaIOT Gateway.
Node::getNodeId
uint16_t getNodeId()
Gets Node identifier.
Definition: NodeList.h:136
Node::getLastMessageTime
time_t getLastMessageTime()
Gets last time that node sent a message.
Definition: NodeList.h:203
RESPONSE_SIZE
const size_t RESPONSE_SIZE
Maximum API response size.
Definition: GatewayAPI.h:21
confirmParam
const char * confirmParam
Definition: GatewayAPI.cpp:26
getNodesUri
const char * getNodesUri
Definition: GatewayAPI.cpp:17
GatewayAPI::begin
void begin()
Starts REST API web server.
Definition: GatewayAPI.cpp:28
Node::packetsHour
double packetsHour
Packet rate for a specific nope.
Definition: NodeList.h:472
GatewayAPI::getNodeNumber
void getNodeNumber(AsyncWebServerRequest *request)
Processes node number request.
Definition: GatewayAPI.cpp:46
NodeList::getNextActiveNode
Node * getNextActiveNode(uint16_t nodeId)
Gets next active node by nodeId.
Definition: NodeList.cpp:295
NUM_NODES
static const int NUM_NODES
Maximum number of nodes that this gateway can handle.
Definition: EnigmaIoTconfig.h:32
getMaxNodesUri
const char * getMaxNodesUri
Definition: GatewayAPI.cpp:16
GatewayAPI::getNodeInfo
char * getNodeInfo(Node *node, int &resultCode, char *nodeInfo, size_t len)
Builds node info.
Definition: GatewayAPI.cpp:155
GatewayAPI::restartNode
void restartNode(AsyncWebServerRequest *request)
Processes node information request.
Definition: GatewayAPI.cpp:198
GatewayAPI::deleteNode
const char * deleteNode(Node *node, int &resultCode)
Processes node deletion request.
Definition: GatewayAPI.cpp:140
EnigmaIOTGatewayClass::nodelist
NodeList nodelist
Node database that keeps status and shared keys.
Definition: EnigmaIOTGateway.h:126
EnigmaIOTGateway
EnigmaIOTGatewayClass EnigmaIOTGateway
Definition: EnigmaIOTGateway.cpp:2050
BROADCAST_NONE_NAME
static const char BROADCAST_NONE_NAME[]
Name to reference broadcast node.
Definition: EnigmaIoTconfigAdvanced.h:27
Node::getNodeName
char * getNodeName()
Gets Node name.
Definition: NodeList.h:152
BROADCAST_ADDRESS
static const uint8_t BROADCAST_ADDRESS[]
Broadcast address.
Definition: EnigmaIoTconfigAdvanced.h:26
MACSTR
#define MACSTR
Definition: helperFunctions.cpp:83
Node
Class definition for a single sensor Node.
Definition: NodeList.h:109
getNodeRestartUri
const char * getNodeRestartUri
Definition: GatewayAPI.cpp:22
Node::isRegistered
bool isRegistered()
Gets registration state of this node.
Definition: NodeList.h:292
Node::getMacAddress
uint8_t * getMacAddress()
Gets address from Node.
Definition: NodeList.h:128
Node::getKeyValidFrom
time_t getKeyValidFrom()
Gets last time that key was agreed with gateway.
Definition: NodeList.h:187
GatewayAPI::buildGwInfo
char * buildGwInfo(char *gwInfo, size_t len)
Builds gateway info.
Definition: GatewayAPI.cpp:54
WEB_API_PORT
const int WEB_API_PORT
TCP port where Web API will listen through.
Definition: EnigmaIoTconfigAdvanced.h:77
EnigmaIOTGatewayClass::sendDownstream
bool sendDownstream(uint8_t *mac, const uint8_t *data, size_t len, control_message_type_t controlData, gatewayPayloadEncoding_t payload_type=RAW, char *nodeName=NULL)
Starts a downstream data message transmission.
Definition: EnigmaIOTGateway.cpp:364
GatewayAPI::getGwInfo
void getGwInfo(AsyncWebServerRequest *request)
Processes gateway information request.
Definition: GatewayAPI.cpp:78
getNodeNumberUri
const char * getNodeNumberUri
Definition: GatewayAPI.cpp:15
Node::per
double per
Current packet error rate of a specific node.
Definition: NodeList.h:471
NodeList::getNodeFromID
Node * getNodeFromID(uint16_t nodeId)
Gets node that correspond with given nodeId.
Definition: NodeList.cpp:135
nodeNameParam
const char * nodeNameParam
Definition: GatewayAPI.cpp:24
GatewayAPI::restartGw
void restartGw(AsyncWebServerRequest *request)
Processes gateway restart request.
Definition: GatewayAPI.cpp:259
isNumber
bool isNumber(const char *input)
Checks if input string is numeric.
Definition: helperFunctions.cpp:169
Node::useTimeSync
bool useTimeSync()
Gets node info to check if it has requested time sync ever.
Definition: NodeList.h:434
Node::getRSSI
int8_t getRSSI()
Gets last RSSI measurement of Gateway.
Definition: NodeList.h:418
getNodeUri
const char * getNodeUri
Definition: GatewayAPI.cpp:18