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.

347 lines
7.7 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
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
providers: relays, lights and buttons refactoring (#2414) - gpio module now tracks the known providers (right now, hardware and mcp expander) - refactored relay struct to use 'Provider' implementing setup,notify,change,boot instead of just BasePin actions - refactored button module to use gpio provider instead of referencing types itself - removed dual & stm code from buttons, migrate both to relay module - added status notify and change callbacks for relayStatus (i.e. 'notify' when relay status was called, but not changed. and 'changed' when it did) - relays runtime configuration keys - relay command now shows configured relays and current & target statuses - refactor the code using relayStatus(0, blah) under LIGHT_PROVIDER check to use lightState instead - remove rfbridge code form relay module. implement through a basic state listener in the rfbridge module, depend on RELAY_SUPPORT - allow to bind rf codes to real relays - drop tuya-specific lights provider, remove tuya code from relays and lights modules - integrate tuya via relay listeners and providers, use lights custom provider - implement channel transitions for tuya. disabled by default, and transition time and step are overridden to 2000 + 100. needs to be set to some value below the total time (i.e. `total transition time / step time == number of steps`, we need to figure out a correct time that serial comms could handle) - lights custom provider (global, not per-pin) and state listeners - remove lights code from relay module. implement through providers & listeners in the lights module, depend on RELAY_SUPPORT - lights per-channel relay provider (unused atm), depend on RELAY_SUPPORT - refactored channel transition - calculate step only once, make sure time + step values are sane, generate quick transitions with very small delay (10ms hardcoded) for transitions during OFF state i.e. we no longer waste 500ms (or whatever transition time is set to) on boot doing nothing - transition time + step parameter for the lightUpdate - report mask parameter for the lightUpdate - minor fixes across the board resolve #2222
3 years ago
  1. /*
  2. ESPurna
  3. Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "espurna.h"
  16. #include "alexa.h"
  17. #include "api.h"
  18. #include "broker.h"
  19. #include "button.h"
  20. #include "crash.h"
  21. #include "curtain_kingart.h"
  22. #include "debug.h"
  23. #include "domoticz.h"
  24. #include "encoder.h"
  25. #include "homeassistant.h"
  26. #include "garland.h"
  27. #include "i2c.h"
  28. #include "influxdb.h"
  29. #include "ir.h"
  30. #include "led.h"
  31. #include "light.h"
  32. #include "lightfox.h"
  33. #include "llmnr.h"
  34. #include "mdns.h"
  35. #include "mqtt.h"
  36. #include "netbios.h"
  37. #include "nofuss.h"
  38. #include "ntp.h"
  39. #include "ota.h"
  40. #include "relay.h"
  41. #include "rfbridge.h"
  42. #include "rfm69.h"
  43. #include "rpc.h"
  44. #include "rpnrules.h"
  45. #include "rtcmem.h"
  46. #include "scheduler.h"
  47. #include "sensor.h"
  48. #include "ssdp.h"
  49. #include "telnet.h"
  50. #include "thermostat.h"
  51. #include "thingspeak.h"
  52. #include "tuya.h"
  53. #include "uartmqtt.h"
  54. #include "web.h"
  55. #include "ws.h"
  56. #include "mcp23s08.h"
  57. #include "prometheus.h"
  58. std::vector<void_callback_f> _loop_callbacks;
  59. std::vector<void_callback_f> _reload_callbacks;
  60. bool _reload_config = false;
  61. unsigned long _loop_delay = 0;
  62. // -----------------------------------------------------------------------------
  63. // GENERAL CALLBACKS
  64. // -----------------------------------------------------------------------------
  65. void espurnaRegisterLoop(void_callback_f callback) {
  66. _loop_callbacks.push_back(callback);
  67. }
  68. void espurnaRegisterReload(void_callback_f callback) {
  69. _reload_callbacks.push_back(callback);
  70. }
  71. void espurnaReload() {
  72. _reload_config = true;
  73. }
  74. void _espurnaReload() {
  75. for (const auto& callback : _reload_callbacks) {
  76. callback();
  77. }
  78. }
  79. unsigned long espurnaLoopDelay() {
  80. return _loop_delay;
  81. }
  82. // -----------------------------------------------------------------------------
  83. // BOOTING
  84. // -----------------------------------------------------------------------------
  85. void setup() {
  86. // -------------------------------------------------------------------------
  87. // Basic modules, will always run
  88. // -------------------------------------------------------------------------
  89. // Cache initial free heap value
  90. setInitialFreeHeap();
  91. // Init logging module
  92. #if DEBUG_SUPPORT
  93. debugSetup();
  94. #endif
  95. // Init GPIO functions
  96. gpioSetup();
  97. // Init RTCMEM
  98. rtcmemSetup();
  99. // Init EEPROM
  100. eepromSetup();
  101. // Init persistance
  102. settingsSetup();
  103. // Configure logger and crash recorder
  104. #if DEBUG_SUPPORT
  105. debugConfigureBoot();
  106. crashSetup();
  107. #endif
  108. // Return bogus free heap value for broken devices
  109. // XXX: device is likely to trigger other bugs! tread carefuly
  110. wtfHeap(getSetting("wtfHeap", 0));
  111. // Init Serial, SPIFFS and system check
  112. systemSetup();
  113. // Init terminal features
  114. #if TERMINAL_SUPPORT
  115. terminalSetup();
  116. #endif
  117. // Hostname & board name initialization
  118. if (getSetting("hostname").length() == 0) {
  119. setDefaultHostname();
  120. }
  121. setBoardName();
  122. // Show welcome message and system configuration
  123. info(true);
  124. wifiSetup();
  125. otaSetup();
  126. #if TELNET_SUPPORT
  127. telnetSetup();
  128. #endif
  129. // -------------------------------------------------------------------------
  130. // Check if system is stable
  131. // -------------------------------------------------------------------------
  132. #if SYSTEM_CHECK_ENABLED
  133. if (!systemCheck()) return;
  134. #endif
  135. // -------------------------------------------------------------------------
  136. // Next modules will be only loaded if system is flagged as stable
  137. // -------------------------------------------------------------------------
  138. // Init webserver required before any module that uses API
  139. #if WEB_SUPPORT
  140. webSetup();
  141. wsSetup();
  142. #if DEBUG_WEB_SUPPORT
  143. debugWebSetup();
  144. #endif
  145. #if OTA_WEB_SUPPORT
  146. otaWebSetup();
  147. #endif
  148. #endif
  149. // Multiple modules depend on the generic 'API' services
  150. #if API_SUPPORT || TERMINAL_WEB_API_SUPPORT || PROMETHEUS_SUPPORT
  151. apiCommonSetup();
  152. #endif
  153. #if API_SUPPORT
  154. apiSetup();
  155. #endif
  156. // Run terminal command and send back the result
  157. #if TERMINAL_WEB_API_SUPPORT
  158. terminalWebApiSetup();
  159. #endif
  160. // Special HTTP metrics endpoint
  161. #if PROMETHEUS_SUPPORT
  162. prometheusSetup();
  163. #endif
  164. // Hardware GPIO expander, needs to be available for modules down below
  165. #if MCP23S08_SUPPORT
  166. MCP23S08Setup();
  167. #endif
  168. // lightSetup must be called before relaySetup
  169. #if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE
  170. lightSetup();
  171. #endif
  172. // rpnSetup must be called before relaySetup
  173. #if RPN_RULES_SUPPORT
  174. rpnSetup();
  175. #endif
  176. #if RELAY_SUPPORT
  177. relaySetup();
  178. #endif
  179. #if BUTTON_SUPPORT
  180. buttonSetup();
  181. #endif
  182. #if ENCODER_SUPPORT && (LIGHT_PROVIDER != LIGHT_PROVIDER_NONE)
  183. encoderSetup();
  184. #endif
  185. #if LED_SUPPORT
  186. ledSetup();
  187. #endif
  188. #if MQTT_SUPPORT
  189. mqttSetup();
  190. #endif
  191. #if MDNS_SERVER_SUPPORT
  192. mdnsServerSetup();
  193. #endif
  194. #if MDNS_CLIENT_SUPPORT
  195. mdnsClientSetup();
  196. #endif
  197. #if LLMNR_SUPPORT
  198. llmnrSetup();
  199. #endif
  200. #if NETBIOS_SUPPORT
  201. netbiosSetup();
  202. #endif
  203. #if SSDP_SUPPORT
  204. ssdpSetup();
  205. #endif
  206. #if NTP_SUPPORT
  207. ntpSetup();
  208. #endif
  209. #if I2C_SUPPORT
  210. i2cSetup();
  211. #endif
  212. #if RFB_SUPPORT
  213. rfbSetup();
  214. #endif
  215. #if ALEXA_SUPPORT
  216. alexaSetup();
  217. #endif
  218. #if NOFUSS_SUPPORT
  219. nofussSetup();
  220. #endif
  221. #if SENSOR_SUPPORT
  222. sensorSetup();
  223. #endif
  224. #if INFLUXDB_SUPPORT
  225. idbSetup();
  226. #endif
  227. #if THINGSPEAK_SUPPORT
  228. tspkSetup();
  229. #endif
  230. #if RFM69_SUPPORT
  231. rfm69Setup();
  232. #endif
  233. #if IR_SUPPORT
  234. irSetup();
  235. #endif
  236. #if DOMOTICZ_SUPPORT
  237. domoticzSetup();
  238. #endif
  239. #if HOMEASSISTANT_SUPPORT
  240. haSetup();
  241. #endif
  242. #if SCHEDULER_SUPPORT
  243. schSetup();
  244. #endif
  245. #if UART_MQTT_SUPPORT
  246. uartmqttSetup();
  247. #endif
  248. #ifdef FOXEL_LIGHTFOX_DUAL
  249. lightfoxSetup();
  250. #endif
  251. #if THERMOSTAT_SUPPORT
  252. thermostatSetup();
  253. #endif
  254. #if THERMOSTAT_DISPLAY_SUPPORT
  255. displaySetup();
  256. #endif
  257. #if TUYA_SUPPORT
  258. tuya::setup();
  259. #endif
  260. #if KINGART_CURTAIN_SUPPORT
  261. kingartCurtainSetup();
  262. #endif
  263. // 3rd party code hook
  264. #if USE_EXTRA
  265. extraSetup();
  266. #endif
  267. #if GARLAND_SUPPORT
  268. garlandSetup();
  269. #endif
  270. // Prepare configuration for version 2.0
  271. migrate();
  272. // Set up delay() after loop callbacks are finished
  273. // Note: should be after settingsSetup()
  274. _loop_delay = constrain(
  275. getSetting("loopDelay", LOOP_DELAY_TIME), 0, 300
  276. );
  277. saveSettings();
  278. }
  279. void loop() {
  280. // Reload config before running any callbacks
  281. if (_reload_config) {
  282. _espurnaReload();
  283. _reload_config = false;
  284. }
  285. // Call registered loop callbacks
  286. for (unsigned char i = 0; i < _loop_callbacks.size(); i++) {
  287. (_loop_callbacks[i])();
  288. }
  289. // Power saving delay
  290. if (_loop_delay) delay(_loop_delay);
  291. }