handlers.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. // Copyright 2015 by Thorsten von Eicken, see LICENSE.txt
  2. //
  3. // Adapted from: github.com/tuanpmt/esp_bridge, Created on: Jan 9, 2015, Author: Minh
  4. #include "esp8266.h"
  5. #include "sntp.h"
  6. #include "cmd.h"
  7. #include "uart.h"
  8. #include <cgiwifi.h>
  9. #ifdef MQTT
  10. #include <mqtt_cmd.h>
  11. #endif
  12. #ifdef REST
  13. #include <rest.h>
  14. #endif
  15. #ifdef WEBSERVER
  16. #include <web-server.h>
  17. #endif
  18. #ifdef SOCKET
  19. #include <socket.h>
  20. #endif
  21. #include <ip_addr.h>
  22. #include "meta-id/cgi.h"
  23. #include "config.h"
  24. #ifdef CMD_DBG
  25. #define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0)
  26. #else
  27. #define DBG(format, ...) do { } while(0)
  28. #endif
  29. static void cmdNull(CmdPacket *cmd);
  30. static void cmdSync(CmdPacket *cmd);
  31. static void cmdWifiStatus(CmdPacket *cmd);
  32. static void cmdGetTime(CmdPacket *cmd);
  33. static void cmdGetWifiInfo(CmdPacket *cmd);
  34. // static void cmdSetWifiInfo(CmdPacket *cmd);
  35. static void cmdAddCallback(CmdPacket *cmd);
  36. static void cmdWifiGetApCount(CmdPacket *cmd);
  37. static void cmdWifiGetApName(CmdPacket *cmd);
  38. static void cmdWifiSelectSSID(CmdPacket *cmd);
  39. static void cmdWifiSignalStrength(CmdPacket *cmd);
  40. static void cmdWifiQuerySSID(CmdPacket *cmd);
  41. static void cmdWifiStartScan(CmdPacket *cmd);
  42. void cmdMqttGetClientId(CmdPacket *cmd);
  43. // keep track of last status sent to uC so we can notify it when it changes
  44. static uint8_t lastWifiStatus = wifiIsDisconnected;
  45. // keep track of whether we have registered our cb handler with the wifi subsystem
  46. static bool wifiCbAdded = false;
  47. // keep track of whether we received a sync command from uC
  48. bool cmdInSync = false;
  49. // Command dispatch table for serial -> ESP commands
  50. const CmdList commands[] = {
  51. {CMD_NULL, "NULL", cmdNull}, // no-op
  52. {CMD_SYNC, "SYNC", cmdSync}, // synchronize
  53. {CMD_WIFI_STATUS, "WIFI_STATUS", cmdWifiStatus},
  54. {CMD_CB_ADD, "ADD_CB", cmdAddCallback},
  55. {CMD_GET_TIME, "GET_TIME", cmdGetTime},
  56. {CMD_GET_WIFI_INFO, "GET_WIFI_INFO", cmdGetWifiInfo},
  57. // {CMD_SET_WIFI_INFO, "SET_WIFI_INFO", cmdSetWifiInfo},
  58. {CMD_WIFI_GET_APCOUNT, "WIFI_GET_APCOUNT", cmdWifiGetApCount},
  59. {CMD_WIFI_GET_APNAME, "WIFI_GET_APNAME", cmdWifiGetApName},
  60. {CMD_WIFI_SELECT_SSID, "WIFI_SELECT_SSID", cmdWifiSelectSSID},
  61. {CMD_WIFI_SIGNAL_STRENGTH, "WIFI_SIGNAL_STRENGTH", cmdWifiSignalStrength},
  62. {CMD_WIFI_GET_SSID, "WIFI_GET_SSID", cmdWifiQuerySSID},
  63. {CMD_WIFI_START_SCAN, "WIFI_START_SCAN", cmdWifiStartScan},
  64. #ifdef MQTT
  65. {CMD_MQTT_SETUP, "MQTT_SETUP", MQTTCMD_Setup},
  66. {CMD_MQTT_PUBLISH, "MQTT_PUB", MQTTCMD_Publish},
  67. {CMD_MQTT_SUBSCRIBE , "MQTT_SUB", MQTTCMD_Subscribe},
  68. {CMD_MQTT_LWT, "MQTT_LWT", MQTTCMD_Lwt},
  69. {CMD_MQTT_GET_CLIENTID,"MQTT_CLIENTID", cmdMqttGetClientId},
  70. #endif
  71. #ifdef REST
  72. {CMD_REST_SETUP, "REST_SETUP", REST_Setup},
  73. {CMD_REST_REQUEST, "REST_REQ", REST_Request},
  74. {CMD_REST_SETHEADER, "REST_SETHDR", REST_SetHeader},
  75. #endif
  76. #ifdef WEBSERVER
  77. {CMD_WEB_SETUP, "WEB_SETUP", WEB_Setup},
  78. {CMD_WEB_DATA, "WEB_DATA", WEB_Data},
  79. #endif
  80. #ifdef SOCKET
  81. {CMD_SOCKET_SETUP, "SOCKET_SETUP", SOCKET_Setup},
  82. {CMD_SOCKET_SEND, "SOCKET_SEND", SOCKET_Send},
  83. #endif
  84. };
  85. //===== List of registered callbacks (to uC)
  86. // WifiCb plus 10 for other stuff
  87. #define MAX_CALLBACKS 12
  88. CmdCallback callbacks[MAX_CALLBACKS]; // cleared in cmdSync
  89. uint32_t ICACHE_FLASH_ATTR
  90. cmdAddCb(char* name, uint32_t cb) {
  91. for (uint8_t i = 0; i < MAX_CALLBACKS; i++) {
  92. //DBG("cmdAddCb: index %d name=%s cb=%p\n", i, callbacks[i].name,
  93. // (void *)callbacks[i].callback);
  94. // find existing callback or add to the end
  95. if (os_strncmp(callbacks[i].name, name, CMD_CBNLEN) == 0 || callbacks[i].name[0] == '\0') {
  96. os_strncpy(callbacks[i].name, name, sizeof(callbacks[i].name));
  97. callbacks[i].name[CMD_CBNLEN-1] = 0; // strncpy doesn't null terminate
  98. callbacks[i].callback = cb;
  99. DBG("cmdAddCb: '%s'->0x%x added at %d\n", callbacks[i].name, cb, i);
  100. return 1;
  101. }
  102. }
  103. return 0;
  104. }
  105. CmdCallback* ICACHE_FLASH_ATTR
  106. cmdGetCbByName(char* name) {
  107. for (uint8_t i = 0; i < MAX_CALLBACKS; i++) {
  108. //DBG("cmdGetCbByName: index %d name=%s cb=%p\n", i, callbacks[i].name,
  109. // (void *)callbacks[i].callback);
  110. // if callback doesn't exist or it's null
  111. if (os_strncmp(callbacks[i].name, name, CMD_CBNLEN) == 0) {
  112. DBG("cmdGetCbByName: cb %s found at index %d\n", name, i);
  113. return &callbacks[i];
  114. }
  115. }
  116. DBG("cmdGetCbByName: cb %s not found\n", name);
  117. return 0;
  118. }
  119. //===== Wifi callback
  120. // Callback from wifi subsystem to notify us of status changes
  121. static void ICACHE_FLASH_ATTR
  122. cmdWifiCb(uint8_t wifiStatus) {
  123. if (wifiStatus != lastWifiStatus){
  124. DBG("cmdWifiCb: wifiStatus=%d\n", wifiStatus);
  125. lastWifiStatus = wifiStatus;
  126. CmdCallback *wifiCb = cmdGetCbByName("wifiCb");
  127. if ((uint32_t)wifiCb->callback != -1) {
  128. uint8_t status = wifiStatus == wifiGotIP ? 5 : 1;
  129. cmdResponseStart(CMD_RESP_CB, (uint32_t)wifiCb->callback, 1);
  130. cmdResponseBody((uint8_t*)&status, 1);
  131. cmdResponseEnd();
  132. }
  133. }
  134. }
  135. //===== Command handlers
  136. // Command handler for Null command
  137. static void ICACHE_FLASH_ATTR
  138. cmdNull(CmdPacket *cmd) {
  139. }
  140. // Command handler for sync command
  141. static void ICACHE_FLASH_ATTR
  142. cmdSync(CmdPacket *cmd) {
  143. CmdRequest req;
  144. uart0_write_char(SLIP_END); // prefix with a SLIP END to ensure we get a clean start
  145. cmdRequest(&req, cmd);
  146. if(cmd->argc != 0 || cmd->value == 0) {
  147. cmdResponseStart(CMD_RESP_V, 0, 0);
  148. cmdResponseEnd();
  149. return;
  150. }
  151. // clear callbacks table
  152. os_memset(callbacks, 0, sizeof(callbacks));
  153. // TODO: call other protocols back to tell them to reset
  154. // register our callback with wifi subsystem
  155. if (!wifiCbAdded) {
  156. wifiAddStateChangeCb(cmdWifiCb);
  157. wifiCbAdded = true;
  158. }
  159. // send OK response
  160. cmdResponseStart(CMD_RESP_V, cmd->value, 0);
  161. cmdResponseEnd();
  162. cmdInSync = true;
  163. // save the MCU's callback and trigger an initial callback
  164. cmdAddCb("wifiCb", cmd->value);
  165. lastWifiStatus = 0xff; // set to invalid value so we immediately send status cb in all cases
  166. cmdWifiCb(wifiState);
  167. return;
  168. }
  169. // Command handler for wifi status command
  170. static void ICACHE_FLASH_ATTR
  171. cmdWifiStatus(CmdPacket *cmd) {
  172. cmdResponseStart(CMD_RESP_V, wifiState, 0);
  173. cmdResponseEnd();
  174. return;
  175. }
  176. // Command handler for time
  177. static void ICACHE_FLASH_ATTR
  178. cmdGetTime(CmdPacket *cmd) {
  179. cmdResponseStart(CMD_RESP_V, sntp_get_current_timestamp(), 0);
  180. cmdResponseEnd();
  181. return;
  182. }
  183. // Command handler for IP information
  184. static void ICACHE_FLASH_ATTR
  185. cmdGetWifiInfo(CmdPacket *cmd) {
  186. CmdRequest req;
  187. cmdRequest(&req, cmd);
  188. if(cmd->argc != 0 || cmd->value == 0) {
  189. cmdResponseStart(CMD_RESP_V, 0, 0);
  190. cmdResponseEnd();
  191. return;
  192. }
  193. uint32_t callback = req.cmd->value;
  194. struct ip_info info;
  195. wifi_get_ip_info(0, &info);
  196. uint8_t mac[6];
  197. wifi_get_macaddr(0, mac);
  198. cmdResponseStart(CMD_RESP_CB, callback, 4);
  199. cmdResponseBody(&info.ip.addr, sizeof(info.ip.addr));
  200. cmdResponseBody(&info.netmask.addr, sizeof(info.netmask.addr));
  201. cmdResponseBody(&info.gw.addr, sizeof(info.gw.addr));
  202. cmdResponseBody(mac, sizeof(mac));
  203. cmdResponseEnd();
  204. }
  205. // Command handler to add a callback to the named-callbacks list, this is for a callback to the uC
  206. static void ICACHE_FLASH_ATTR
  207. cmdAddCallback(CmdPacket *cmd) {
  208. CmdRequest req;
  209. cmdRequest(&req, cmd);
  210. if (cmd->argc != 1 || cmd->value == 0) return;
  211. char name[16];
  212. uint16_t len;
  213. // get the callback name
  214. len = cmdArgLen(&req);
  215. if (len > 15) return; // max size of name is 15 characters
  216. if (cmdPopArg(&req, (uint8_t *)name, len)) return;
  217. name[len] = 0;
  218. DBG("cmdAddCallback: name=%s\n", name);
  219. cmdAddCb(name, cmd->value); // save the sensor callback
  220. }
  221. // Query the number of wifi access points
  222. static void ICACHE_FLASH_ATTR cmdWifiGetApCount(CmdPacket *cmd) {
  223. int n = wifiGetApCount();
  224. DBG("WifiGetApCount : %d\n", n);
  225. cmdResponseStart(CMD_RESP_V, n, 0);
  226. cmdResponseEnd();
  227. }
  228. // Query the name of a wifi access point
  229. static void ICACHE_FLASH_ATTR cmdWifiGetApName(CmdPacket *cmd) {
  230. CmdRequest req;
  231. cmdRequest(&req, cmd);
  232. int argc = cmdGetArgc(&req);
  233. DBG("cmdWifiGetApName: argc %d\n", argc);
  234. if (argc != 1)
  235. return;
  236. uint16_t i;
  237. cmdPopArg(&req, (uint8_t*)&i, 2);
  238. uint32_t callback = req.cmd->value;
  239. char myssid[33];
  240. wifiGetApName(i, myssid);
  241. myssid[32] = '\0';
  242. DBG("wifiGetApName(%d) -> {%s}\n", i, myssid);
  243. cmdResponseStart(CMD_RESP_CB, callback, 1);
  244. cmdResponseBody(myssid, strlen(myssid)+1);
  245. cmdResponseEnd();
  246. }
  247. /*
  248. * Select a wireless network.
  249. * This can be called in two ways :
  250. * - with a pair of strings (SSID, password)
  251. * - with a number and a string (index into network array, password)
  252. */
  253. static void ICACHE_FLASH_ATTR cmdWifiSelectSSID(CmdPacket *cmd) {
  254. CmdRequest req;
  255. cmdRequest(&req, cmd);
  256. int argc = cmdGetArgc(&req);
  257. char ssid[33], pass[65];
  258. if (argc != 2) return;
  259. int len = cmdArgLen(&req);
  260. if (len == 1) {
  261. // Assume this is the index
  262. uint8_t ix;
  263. cmdPopArg(&req, &ix, 1);
  264. wifiGetApName(ix, ssid);
  265. ssid[32] = '\0';
  266. } else {
  267. // Longer than 1 byte: must be SSID
  268. if (len > 32) return;
  269. cmdPopArg(&req, ssid, len);
  270. ssid[len] = 0;
  271. }
  272. // Extract password from message
  273. len = cmdArgLen(&req);
  274. if (len > 64) return;
  275. cmdPopArg(&req, pass, len);
  276. pass[len] = 0;
  277. DBG("SelectSSID(%s,%s)", ssid, pass);
  278. connectToNetwork(ssid, pass);
  279. }
  280. #if 0
  281. /*
  282. * Once we're attached to some wireless network, choose not to pick up address from
  283. * DHCP or so but set our own.
  284. */
  285. static void ICACHE_FLASH_ATTR cmdSetWifiInfo(CmdPacket *cmd) {
  286. DBG("SetWifiInfo()\n");
  287. }
  288. #endif
  289. static void ICACHE_FLASH_ATTR cmdWifiSignalStrength(CmdPacket *cmd) {
  290. CmdRequest req;
  291. cmdRequest(&req, cmd);
  292. int argc = cmdGetArgc(&req);
  293. if (argc != 1) {
  294. DBG("cmdWifiSignalStrength: argc %d\n", argc);
  295. return;
  296. }
  297. char x;
  298. cmdPopArg(&req, (uint8_t*)&x, 1);
  299. int i = x;
  300. DBG("cmdWifiSignalStrength: argc %d, ", argc);
  301. DBG("i %d\n", i);
  302. int rssi = wifiSignalStrength(i);
  303. cmdResponseStart(CMD_RESP_V, rssi, 0);
  304. cmdResponseEnd();
  305. }
  306. //
  307. static void ICACHE_FLASH_ATTR cmdWifiQuerySSID(CmdPacket *cmd) {
  308. CmdRequest req;
  309. cmdRequest(&req, cmd);
  310. uint32_t callback = req.cmd->value;
  311. struct station_config conf;
  312. bool res = wifi_station_get_config(&conf);
  313. if (res) {
  314. // #warning handle me
  315. } else {
  316. }
  317. DBG("QuerySSID : %s\n", conf.ssid);
  318. cmdResponseStart(CMD_RESP_CB, callback, 1);
  319. cmdResponseBody(conf.ssid, strlen((char *)conf.ssid)+1);
  320. cmdResponseEnd();
  321. }
  322. // Start scanning, API interface
  323. static void ICACHE_FLASH_ATTR cmdWifiStartScan(CmdPacket *cmd) {
  324. // call a function that belongs in meta-id/cgiwifi.c due to variable access
  325. wifiStartScan();
  326. }
  327. // Command handler for MQTT information
  328. void ICACHE_FLASH_ATTR cmdMqttGetClientId(CmdPacket *cmd) {
  329. CmdRequest req;
  330. cmdRequest(&req, cmd);
  331. if(cmd->argc != 0 || cmd->value == 0) {
  332. cmdResponseStart(CMD_RESP_V, 0, 0);
  333. cmdResponseEnd();
  334. return;
  335. }
  336. uint32_t callback = req.cmd->value;
  337. cmdResponseStart(CMD_RESP_CB, callback, 1);
  338. cmdResponseBody(flashConfig.mqtt_clientid, strlen(flashConfig.mqtt_clientid)+1);
  339. cmdResponseEnd();
  340. os_printf("MqttGetClientId : %s\n", flashConfig.mqtt_clientid);
  341. }