Mirror of espurna firmware for wireless switches and more
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.

365 lines
13 KiB

6 years ago
6 years ago
6 years ago
  1. #include <Arduino.h>
  2. #include <ArduinoJson.h>
  3. #include <functional>
  4. #include <algorithm>
  5. #include <vector>
  6. #include <memory>
  7. extern "C" {
  8. #include "user_interface.h"
  9. extern struct rst_info resetInfo;
  10. }
  11. #define UNUSED(x) (void)(x)
  12. // -----------------------------------------------------------------------------
  13. // System
  14. // -----------------------------------------------------------------------------
  15. #define LWIP_INTERNAL
  16. #include <ESP8266WiFi.h>
  17. #undef LWIP_INTERNAL
  18. extern "C" {
  19. #include <lwip/opt.h>
  20. #include <lwip/ip.h>
  21. #include <lwip/tcp.h>
  22. #include <lwip/inet.h> // ip_addr_t
  23. #include <lwip/err.h> // ERR_x
  24. #include <lwip/dns.h> // dns_gethostbyname
  25. #include <lwip/ip_addr.h> // ip4/ip6 helpers
  26. #include <lwip/init.h> // LWIP_VERSION_MAJOR
  27. }
  28. // ref: https://github.com/me-no-dev/ESPAsyncTCP/pull/115/files#diff-e2e636049095cc1ff920c1bfabf6dcacR8
  29. // This is missing with Core 2.3.0 and is sometimes missing from the build flags. Assume HIGH_BANDWIDTH version.
  30. #ifndef TCP_MSS
  31. #define TCP_MSS (1460)
  32. #endif
  33. // -----------------------------------------------------------------------------
  34. // PROGMEM
  35. // -----------------------------------------------------------------------------
  36. #include <pgmspace.h>
  37. // ref: https://github.com/esp8266/Arduino/blob/master/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h
  38. // __STRINGIZE && __STRINGIZE_NX && PROGMEM definitions port
  39. // Do not replace macros unless running version older than 2.5.0
  40. #if defined(ARDUINO_ESP8266_RELEASE_2_3_0) \
  41. || defined(ARDUINO_ESP8266_RELEASE_2_4_0) \
  42. || defined(ARDUINO_ESP8266_RELEASE_2_4_1) \
  43. || defined(ARDUINO_ESP8266_RELEASE_2_4_2)
  44. // Quoting esp8266/Arduino comments:
  45. // "Since __section__ is supposed to be only use for global variables,
  46. // there could be conflicts when a static/inlined function has them in the
  47. // same file as a non-static PROGMEM object.
  48. // Ref: https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Variable-Attributes.html
  49. // Place each progmem object into its own named section, avoiding conflicts"
  50. #define __TO_STR_(A) #A
  51. #define __TO_STR(A) __TO_STR_(A)
  52. #undef PROGMEM
  53. #define PROGMEM __attribute__((section( "\".irom.text." __FILE__ "." __TO_STR(__LINE__) "." __TO_STR(__COUNTER__) "\"")))
  54. // "PSTR() macro modified to start on a 32-bit boundary. This adds on average
  55. // 1.5 bytes/string, but in return memcpy_P and strcpy_P will work 4~8x faster"
  56. #undef PSTR
  57. #define PSTR(s) (__extension__({static const char __c[] __attribute__((__aligned__(4))) PROGMEM = (s); &__c[0];}))
  58. #endif
  59. // -----------------------------------------------------------------------------
  60. // API
  61. // -----------------------------------------------------------------------------
  62. using api_get_callback_f = std::function<void(char * buffer, size_t size)>;
  63. using api_put_callback_f = std::function<void(const char * payload)> ;
  64. #if WEB_SUPPORT
  65. void apiRegister(const char * key, api_get_callback_f getFn, api_put_callback_f putFn = NULL);
  66. #endif
  67. // -----------------------------------------------------------------------------
  68. // Debug
  69. // -----------------------------------------------------------------------------
  70. #include "../libs/DebugSend.h"
  71. void debugSendImpl(const char*);
  72. extern "C" {
  73. void custom_crash_callback(struct rst_info*, uint32_t, uint32_t);
  74. }
  75. class PrintRaw;
  76. class PrintHex;
  77. // Core version 2.4.2 and higher changed the cont_t structure to a pointer:
  78. // https://github.com/esp8266/Arduino/commit/5d5ea92a4d004ab009d5f642629946a0cb8893dd#diff-3fa12668b289ccb95b7ab334833a4ba8L35
  79. // Core version 2.5.0 introduced EspClass helper method:
  80. // https://github.com/esp8266/Arduino/commit/0e0e34c614fe8a47544c9998201b1d9b3c24eb18
  81. extern "C" {
  82. #include <cont.h>
  83. #if defined(ARDUINO_ESP8266_RELEASE_2_3_0) \
  84. || defined(ARDUINO_ESP8266_RELEASE_2_4_0) \
  85. || defined(ARDUINO_ESP8266_RELEASE_2_4_1)
  86. extern cont_t g_cont;
  87. #define getFreeStack() cont_get_free_stack(&g_cont)
  88. #elif defined(ARDUINO_ESP8266_RELEASE_2_4_2)
  89. extern cont_t* g_pcont;
  90. #define getFreeStack() cont_get_free_stack(g_pcont)
  91. #else
  92. #define getFreeStack() ESP.getFreeContStack()
  93. #endif
  94. }
  95. void infoMemory(const char* , unsigned int, unsigned int);
  96. unsigned int getFreeHeap();
  97. unsigned int getInitialFreeHeap();
  98. // -----------------------------------------------------------------------------
  99. // Domoticz
  100. // -----------------------------------------------------------------------------
  101. #if DOMOTICZ_SUPPORT
  102. template<typename T> void domoticzSend(const char * key, T value);
  103. template<typename T> void domoticzSend(const char * key, T nvalue, const char * svalue);
  104. #endif
  105. // -----------------------------------------------------------------------------
  106. // EEPROM_ROTATE
  107. // -----------------------------------------------------------------------------
  108. #include <EEPROM_Rotate.h>
  109. EEPROM_Rotate EEPROMr;
  110. void eepromSectorsDebug();
  111. // -----------------------------------------------------------------------------
  112. // GPIO
  113. // -----------------------------------------------------------------------------
  114. bool gpioValid(unsigned char gpio);
  115. bool gpioGetLock(unsigned char gpio);
  116. bool gpioReleaseLock(unsigned char gpio);
  117. // -----------------------------------------------------------------------------
  118. // Homeassistant
  119. // -----------------------------------------------------------------------------
  120. struct ha_config_t;
  121. void haSetup();
  122. // -----------------------------------------------------------------------------
  123. // I2C
  124. // -----------------------------------------------------------------------------
  125. void i2cScan();
  126. void i2cClearBus();
  127. bool i2cGetLock(unsigned char address);
  128. bool i2cReleaseLock(unsigned char address);
  129. unsigned char i2cFindAndLock(size_t size, unsigned char * addresses);
  130. void i2c_wakeup(uint8_t address);
  131. uint8_t i2c_write_buffer(uint8_t address, uint8_t * buffer, size_t len);
  132. uint8_t i2c_write_uint8(uint8_t address, uint8_t value);
  133. uint8_t i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value);
  134. uint8_t i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value1, uint8_t value2);
  135. uint8_t i2c_write_uint16(uint8_t address, uint16_t value);
  136. uint8_t i2c_write_uint16(uint8_t address, uint8_t reg, uint16_t value);
  137. uint8_t i2c_read_uint8(uint8_t address);
  138. uint8_t i2c_read_uint8(uint8_t address, uint8_t reg);
  139. uint16_t i2c_read_uint16(uint8_t address);
  140. uint16_t i2c_read_uint16(uint8_t address, uint8_t reg);
  141. uint16_t i2c_read_uint16_le(uint8_t address, uint8_t reg);
  142. int16_t i2c_read_int16(uint8_t address, uint8_t reg);
  143. int16_t i2c_read_int16_le(uint8_t address, uint8_t reg);
  144. void i2c_read_buffer(uint8_t address, uint8_t * buffer, size_t len);
  145. // -----------------------------------------------------------------------------
  146. // MQTT
  147. // -----------------------------------------------------------------------------
  148. #if MQTT_LIBRARY == MQTT_LIBRARY_ASYNCMQTTCLIENT
  149. #include <ESPAsyncTCP.h>
  150. #include <AsyncMqttClient.h>
  151. #elif MQTT_LIBRARY == MQTT_LIBRARY_ARDUINOMQTT
  152. #include <MQTTClient.h>
  153. #elif MQTT_LIBRARY == MQTT_LIBRARY_PUBSUBCLIENT
  154. #include <PubSubClient.h>
  155. #endif
  156. using mqtt_callback_f = std::function<void(unsigned int type, const char * topic, char * payload)>;
  157. using mqtt_msg_t = std::pair<String, String>; // topic, payload
  158. void mqttRegister(mqtt_callback_f callback);
  159. String mqttTopic(const char * magnitude, bool is_set);
  160. String mqttTopic(const char * magnitude, unsigned int index, bool is_set);
  161. String mqttMagnitude(char * topic);
  162. bool mqttSendRaw(const char * topic, const char * message, bool retain);
  163. bool mqttSendRaw(const char * topic, const char * message);
  164. void mqttSend(const char * topic, const char * message, bool force, bool retain);
  165. void mqttSend(const char * topic, const char * message, bool force);
  166. void mqttSend(const char * topic, const char * message);
  167. void mqttSend(const char * topic, unsigned int index, const char * message, bool force);
  168. void mqttSend(const char * topic, unsigned int index, const char * message);
  169. const String& mqttPayloadOnline();
  170. const String& mqttPayloadOffline();
  171. const char* mqttPayloadStatus(bool status);
  172. void mqttSendStatus();
  173. // -----------------------------------------------------------------------------
  174. // OTA
  175. // -----------------------------------------------------------------------------
  176. #include <ArduinoOTA.h>
  177. #if OTA_CLIENT == OTA_CLIENT_ASYNCTCP
  178. #include <ESPAsyncTCP.h>
  179. #endif
  180. #if OTA_CLIENT == OTA_CLIENT_HTTPUPDATE
  181. #include <ESP8266HTTPClient.h>
  182. #include <ESP8266httpUpdate.h>
  183. #endif
  184. #if SECURE_CLIENT != SECURE_CLIENT_NONE
  185. #include <WiFiClientSecure.h>
  186. #endif // SECURE_CLIENT != SECURE_CLIENT_NONE
  187. // -----------------------------------------------------------------------------
  188. // RFM69
  189. // -----------------------------------------------------------------------------
  190. typedef struct {
  191. unsigned long messageID;
  192. unsigned char packetID;
  193. unsigned char senderID;
  194. unsigned char targetID;
  195. char * key;
  196. char * value;
  197. int16_t rssi;
  198. } packet_t;
  199. // -----------------------------------------------------------------------------
  200. // Settings
  201. // -----------------------------------------------------------------------------
  202. #include <Embedis.h>
  203. template<typename T> bool setSetting(const String& key, T value);
  204. template<typename T> bool setSetting(const String& key, unsigned int index, T value);
  205. template<typename T> String getSetting(const String& key, T defaultValue);
  206. template<typename T> String getSetting(const String& key, unsigned int index, T defaultValue);
  207. void settingsGetJson(JsonObject& data);
  208. bool settingsRestoreJson(JsonObject& data);
  209. struct settings_cfg_t {
  210. String& setting;
  211. const char* key;
  212. const char* default_value;
  213. };
  214. using settings_filter_t = std::function<String(String& value)>;
  215. using settings_cfg_list_t = std::initializer_list<settings_cfg_t>;
  216. void settingsProcessConfig(const settings_cfg_list_t& config, settings_filter_t filter = nullptr);
  217. // -----------------------------------------------------------------------------
  218. // Terminal
  219. // -----------------------------------------------------------------------------
  220. #if TERMINAL_SUPPORT
  221. void terminalRegisterCommand(const String& name, void (*call)(Embedis*));
  222. void terminalInject(void *data, size_t len);
  223. Stream & terminalSerial();
  224. #endif
  225. // -----------------------------------------------------------------------------
  226. // Utils
  227. // -----------------------------------------------------------------------------
  228. char * ltrim(char * s);
  229. void nice_delay(unsigned long ms);
  230. bool inline eraseSDKConfig();
  231. #define ARRAYINIT(type, name, ...) type name[] = {__VA_ARGS__};
  232. size_t strnlen(const char*, size_t);
  233. char* strnstr(const char*, const char*, size_t);
  234. // -----------------------------------------------------------------------------
  235. // WebServer
  236. // -----------------------------------------------------------------------------
  237. class AsyncClient;
  238. class AsyncWebServer;
  239. #if WEB_SUPPORT
  240. #include <ESPAsyncWebServer.h>
  241. AsyncWebServer * webServer();
  242. #else
  243. class AsyncWebServerRequest;
  244. class ArRequestHandlerFunction;
  245. class AsyncWebSocketClient;
  246. class AsyncWebSocket;
  247. class AwsEventType;
  248. #endif
  249. using web_body_callback_f = std::function<bool(AsyncWebServerRequest*, uint8_t* data, size_t len, size_t index, size_t total)>;
  250. using web_request_callback_f = std::function<bool(AsyncWebServerRequest*)>;
  251. void webBodyRegister(web_body_callback_f);
  252. void webRequestRegister(web_request_callback_f);
  253. // -----------------------------------------------------------------------------
  254. // WIFI
  255. // -----------------------------------------------------------------------------
  256. #include <JustWifi.h>
  257. struct wifi_scan_info_t;
  258. using wifi_scan_f = std::function<void(wifi_scan_info_t& info)>;
  259. using wifi_callback_f = std::function<void(justwifi_messages_t code, char * parameter)>;
  260. void wifiRegister(wifi_callback_f callback);
  261. bool wifiConnected();
  262. #if LWIP_VERSION_MAJOR == 1
  263. #include <netif/etharp.h>
  264. #else // LWIP_VERSION_MAJOR >= 2
  265. #include <lwip/etharp.h>
  266. #endif
  267. // -----------------------------------------------------------------------------
  268. // THERMOSTAT
  269. // -----------------------------------------------------------------------------
  270. using thermostat_callback_f = std::function<void(bool state)>;
  271. #if THERMOSTAT_SUPPORT
  272. void thermostatRegister(thermostat_callback_f callback);
  273. #endif
  274. // -----------------------------------------------------------------------------
  275. // RTC MEMORY
  276. // -----------------------------------------------------------------------------
  277. #include "rtcmem.h"
  278. // -----------------------------------------------------------------------------
  279. // Warn about broken Arduino functions
  280. // -----------------------------------------------------------------------------
  281. // Division by zero bug
  282. // https://github.com/esp8266/Arduino/pull/2397
  283. // https://github.com/esp8266/Arduino/pull/2408
  284. #if defined(ARDUINO_ESP8266_RELEASE_2_3_0)
  285. long __attribute__((deprecated("Please avoid using map() with Core 2.3.0"))) map(long x, long in_min, long in_max, long out_min, long out_max);
  286. #endif
  287. // -----------------------------------------------------------------------------
  288. // std::make_unique backport for C++11
  289. // -----------------------------------------------------------------------------
  290. #if 201103L >= __cplusplus
  291. namespace std {
  292. template<typename T, typename... Args>
  293. std::unique_ptr<T> make_unique(Args&&... args) {
  294. return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
  295. }
  296. }
  297. #endif