Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

201 lines
5.5 KiB

Terminal: change command-line parser (#2247) Change the underlying command line handling: - switch to a custom parser, inspired by redis / sds - update terminalRegisterCommand signature, pass only bare minimum - clean-up `help` & `commands`. update settings `set`, `get` and `del` - allow our custom test suite to run command-line tests - clean-up Stream IO to allow us to print large things into debug stream (for example, `eeprom.dump`) - send parsing errors to the debug log As a proof of concept, introduce `TERMINAL_MQTT_SUPPORT` and `TERMINAL_WEB_API_SUPPORT` - MQTT subscribes to the `<root>/cmd/set` and sends response to the `<root>/cmd`. We can't output too much, as we don't have any large-send API. - Web API listens to the `/api/cmd?apikey=...&line=...` (or PUT, params inside the body). This one is intended as a possible replacement of the `API_SUPPORT`. Internals introduce a 'task' around the AsyncWebServerRequest object that will simulate what WiFiClient does and push data into it continuously, switching between CONT and SYS. Both are experimental. We only accept a single command and not every command is updated to use Print `ctx.output` object. We are also somewhat limited by the Print / Stream overall, perhaps I am overestimating the usefulness of Arduino compatibility to such an extent :) Web API handler can also sometimes show only part of the result, whenever the command tries to yield() by itself waiting for something. Perhaps we would need to create a custom request handler for that specific use-case.
4 years ago
6 years ago
  1. /*
  2. NOFUSS MODULE
  3. Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
  4. */
  5. #include "nofuss.h"
  6. #if NOFUSS_SUPPORT
  7. #include "wifi.h"
  8. #include "mdns.h"
  9. #include "terminal.h"
  10. #include "ws.h"
  11. #include <NoFUSSClient.h>
  12. unsigned long _nofussLastCheck = 0;
  13. unsigned long _nofussInterval = 0;
  14. bool _nofussEnabled = false;
  15. // -----------------------------------------------------------------------------
  16. // NOFUSS
  17. // -----------------------------------------------------------------------------
  18. #if WEB_SUPPORT
  19. bool _nofussWebSocketOnKeyCheck(const char * key, JsonVariant& value) {
  20. return (strncmp(key, "nofuss", 6) == 0);
  21. }
  22. void _nofussWebSocketOnVisible(JsonObject& root) {
  23. root["nofussVisible"] = 1;
  24. }
  25. void _nofussWebSocketOnConnected(JsonObject& root) {
  26. root["nofussEnabled"] = getSetting("nofussEnabled", 1 == NOFUSS_ENABLED);
  27. root["nofussServer"] = getSetting("nofussServer", NOFUSS_SERVER);
  28. }
  29. #endif
  30. void _nofussConfigure() {
  31. String nofussServer = getSetting("nofussServer", NOFUSS_SERVER);
  32. #if MDNS_CLIENT_SUPPORT
  33. nofussServer = mdnsResolve(nofussServer);
  34. #endif
  35. if (nofussServer.length() == 0) {
  36. setSetting("nofussEnabled", 0);
  37. _nofussEnabled = false;
  38. } else {
  39. _nofussEnabled = getSetting("nofussEnabled", 1 == NOFUSS_ENABLED);
  40. }
  41. _nofussInterval = getSetting("nofussInterval", NOFUSS_INTERVAL);
  42. _nofussLastCheck = 0;
  43. if (!_nofussEnabled) {
  44. DEBUG_MSG_P(PSTR("[NOFUSS] Disabled\n"));
  45. } else {
  46. NoFUSSClient.setServer(nofussServer);
  47. NoFUSSClient.setDevice(APP_NAME "_" DEVICE);
  48. NoFUSSClient.setVersion(APP_VERSION);
  49. NoFUSSClient.setBuild(String(__UNIX_TIMESTAMP__));
  50. DEBUG_MSG_P(PSTR("[NOFUSS] Server : %s\n"), nofussServer.c_str());
  51. DEBUG_MSG_P(PSTR("[NOFUSS] Device: %s\n"), APP_NAME "_" DEVICE);
  52. DEBUG_MSG_P(PSTR("[NOFUSS] Version: %s\n"), APP_VERSION);
  53. DEBUG_MSG_P(PSTR("[NOFUSS] Build: %s\n"), String(__UNIX_TIMESTAMP__).c_str());
  54. DEBUG_MSG_P(PSTR("[NOFUSS] Enabled\n"));
  55. }
  56. }
  57. // -----------------------------------------------------------------------------
  58. void nofussRun() {
  59. NoFUSSClient.handle();
  60. _nofussLastCheck = millis();
  61. }
  62. void _nofussLoop() {
  63. if (!_nofussEnabled) return;
  64. if (!wifiConnected()) return;
  65. if ((_nofussLastCheck > 0) && ((millis() - _nofussLastCheck) < _nofussInterval)) return;
  66. nofussRun();
  67. }
  68. #if TERMINAL_SUPPORT
  69. void _nofussInitCommands() {
  70. terminalRegisterCommand(F("NOFUSS"), [](const terminal::CommandContext&) {
  71. terminalOK();
  72. nofussRun();
  73. });
  74. }
  75. #endif // TERMINAL_SUPPORT
  76. void nofussSetup() {
  77. _nofussConfigure();
  78. NoFUSSClient.onMessage([](nofuss_t code) {
  79. if (code == NOFUSS_START) {
  80. DEBUG_MSG_P(PSTR("[NoFUSS] Start\n"));
  81. }
  82. if (code == NOFUSS_UPTODATE) {
  83. DEBUG_MSG_P(PSTR("[NoFUSS] Already in the last version\n"));
  84. }
  85. if (code == NOFUSS_NO_RESPONSE_ERROR) {
  86. DEBUG_MSG_P(PSTR("[NoFUSS] Wrong server response: %d %s\n"), NoFUSSClient.getErrorNumber(), (char *) NoFUSSClient.getErrorString().c_str());
  87. }
  88. if (code == NOFUSS_PARSE_ERROR) {
  89. DEBUG_MSG_P(PSTR("[NoFUSS] Error parsing server response\n"));
  90. }
  91. if (code == NOFUSS_UPDATING) {
  92. DEBUG_MSG_P(PSTR("[NoFUSS] Updating\n"));
  93. DEBUG_MSG_P(PSTR(" New version: %s\n"), (char *) NoFUSSClient.getNewVersion().c_str());
  94. DEBUG_MSG_P(PSTR(" Firmware: %s\n"), (char *) NoFUSSClient.getNewFirmware().c_str());
  95. DEBUG_MSG_P(PSTR(" File System: %s\n"), (char *) NoFUSSClient.getNewFileSystem().c_str());
  96. #if WEB_SUPPORT
  97. wsSend_P(PSTR("{\"message\": 1}"));
  98. #endif
  99. // Disabling EEPROM rotation to prevent writing to EEPROM after the upgrade
  100. eepromRotate(false);
  101. // Force backup right now, because NoFUSS library will immediatly reset on success
  102. eepromBackup(0);
  103. }
  104. if (code == NOFUSS_FILESYSTEM_UPDATE_ERROR) {
  105. DEBUG_MSG_P(PSTR("[NoFUSS] File System Update Error: %s\n"), (char *) NoFUSSClient.getErrorString().c_str());
  106. }
  107. if (code == NOFUSS_FILESYSTEM_UPDATED) {
  108. DEBUG_MSG_P(PSTR("[NoFUSS] File System Updated\n"));
  109. }
  110. if (code == NOFUSS_FIRMWARE_UPDATE_ERROR) {
  111. DEBUG_MSG_P(PSTR("[NoFUSS] Firmware Update Error: %s\n"), (char *) NoFUSSClient.getErrorString().c_str());
  112. }
  113. if (code == NOFUSS_FIRMWARE_UPDATED) {
  114. DEBUG_MSG_P(PSTR("[NoFUSS] Firmware Updated\n"));
  115. }
  116. if (code == NOFUSS_RESET) {
  117. DEBUG_MSG_P(PSTR("[NoFUSS] Resetting board\n"));
  118. #if WEB_SUPPORT
  119. wsSend_P(PSTR("{\"action\": \"reload\"}"));
  120. #endif
  121. // TODO: NoFUSS will reset the board after this callback returns.
  122. // Maybe this should be optional
  123. customResetReason(CustomResetReason::Ota);
  124. nice_delay(100);
  125. }
  126. if (code == NOFUSS_END) {
  127. DEBUG_MSG_P(PSTR("[NoFUSS] End\n"));
  128. eepromRotate(true);
  129. }
  130. });
  131. #if WEB_SUPPORT
  132. wsRegister()
  133. .onVisible(_nofussWebSocketOnVisible)
  134. .onConnected(_nofussWebSocketOnConnected)
  135. .onKeyCheck(_nofussWebSocketOnKeyCheck);
  136. #endif
  137. #if TERMINAL_SUPPORT
  138. _nofussInitCommands();
  139. #endif
  140. // Main callbacks
  141. espurnaRegisterLoop(_nofussLoop);
  142. espurnaRegisterReload(_nofussConfigure);
  143. }
  144. #endif // NOFUSS_SUPPORT