Browse Source

Headers cleanup (#2134)

* Config: remove prototypes.h

* fixup order

* word

* add missing

* fix warning while still using .ino

* bad at c/p;
mcspr-patch-1
Max Prokhorov 4 years ago
committed by GitHub
parent
commit
f7f41980b6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
66 changed files with 1398 additions and 949 deletions
  1. +28
    -0
      code/espurna/alexa.h
  2. +20
    -23
      code/espurna/alexa.ino
  3. +31
    -0
      code/espurna/api.h
  4. +3
    -5
      code/espurna/api.ino
  5. +288
    -1
      code/espurna/board.ino
  6. +3
    -3
      code/espurna/broker.h
  7. +87
    -0
      code/espurna/compat.h
  8. +4
    -2
      code/espurna/config/all.h
  9. +2
    -0
      code/espurna/config/arduino.h
  10. +6
    -0
      code/espurna/config/defaults.h
  11. +4
    -2
      code/espurna/config/general.h
  12. +2
    -0
      code/espurna/config/hardware.h
  13. +0
    -395
      code/espurna/config/progmem.h
  14. +0
    -319
      code/espurna/config/prototypes.h
  15. +2
    -0
      code/espurna/config/sensors.h
  16. +2
    -0
      code/espurna/config/types.h
  17. +6
    -0
      code/espurna/config/version.h
  18. +2
    -28
      code/espurna/config/webui.h
  19. +48
    -0
      code/espurna/crash.h
  20. +3
    -40
      code/espurna/crash.ino
  21. +28
    -0
      code/espurna/domoticz.h
  22. +3
    -4
      code/espurna/domoticz.ino
  23. +28
    -4
      code/espurna/espurna.ino
  24. +15
    -0
      code/espurna/gpio.h
  25. +2
    -0
      code/espurna/gpio.ino
  26. +19
    -0
      code/espurna/homeassistant.h
  27. +2
    -1
      code/espurna/homeassistant.ino
  28. +42
    -0
      code/espurna/i2c.h
  29. +0
    -3
      code/espurna/i2c.ino
  30. +21
    -0
      code/espurna/ir.h
  31. +2
    -8
      code/espurna/ir.ino
  32. +2
    -1
      code/espurna/light.ino
  33. +54
    -0
      code/espurna/mqtt.h
  34. +5
    -5
      code/espurna/mqtt.ino
  35. +1
    -1
      code/espurna/ntp.ino
  36. +32
    -67
      code/espurna/ota.h
  37. +79
    -0
      code/espurna/ota.ino
  38. +1
    -0
      code/espurna/ota_arduinoota.ino
  39. +3
    -1
      code/espurna/ota_asynctcp.ino
  40. +4
    -4
      code/espurna/ota_httpupdate.ino
  41. +4
    -2
      code/espurna/relay.ino
  42. +24
    -0
      code/espurna/rfbridge.h
  43. +3
    -4
      code/espurna/rfbridge.ino
  44. +29
    -0
      code/espurna/rfm69.h
  45. +2
    -1
      code/espurna/rfm69.ino
  46. +14
    -3
      code/espurna/rtcmem.h
  47. +2
    -0
      code/espurna/rtcmem.ino
  48. +105
    -1
      code/espurna/sensor.ino
  49. +2
    -0
      code/espurna/settings.ino
  50. +24
    -0
      code/espurna/storage_eeprom.h
  51. +3
    -3
      code/espurna/storage_eeprom.ino
  52. +8
    -0
      code/espurna/system.h
  53. +21
    -0
      code/espurna/terminal.h
  54. +1
    -0
      code/espurna/terminal.ino
  55. +19
    -0
      code/espurna/thermostat.h
  56. +2
    -4
      code/espurna/thermostat.ino
  57. +120
    -0
      code/espurna/timelibshim.h
  58. +18
    -0
      code/espurna/uartmqtt.h
  59. +3
    -1
      code/espurna/uartmqtt.ino
  60. +2
    -0
      code/espurna/utils.h
  61. +26
    -1
      code/espurna/utils.ino
  62. +41
    -0
      code/espurna/web.h
  63. +2
    -8
      code/espurna/web.ino
  64. +36
    -0
      code/espurna/wifi.h
  65. +1
    -0
      code/espurna/ws.h
  66. +2
    -4
      code/espurna/ws.ino

+ 28
- 0
code/espurna/alexa.h View File

@ -0,0 +1,28 @@
/*
ALEXA MODULE
Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#pragma once
#include "web.h"
struct alexa_queue_element_t {
unsigned char device_id;
bool state;
unsigned char value;
};
#if ALEXA_SUPPORT
#include <fauxmoESP.h>
#include <ArduinoJson.h>
bool alexaEnabled();
void alexaSetup();
#endif // ALEXA_SUPPORT == 1

+ 20
- 23
code/espurna/alexa.ino View File

@ -8,18 +8,15 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#if ALEXA_SUPPORT
#include "relay.h"
#include "broker.h"
#include <queue>
#include <fauxmoESP.h>
fauxmoESP alexa;
#include "alexa.h"
#include "broker.h"
#include "relay.h"
#include "ws.h"
#include "web.h"
#include <queue>
typedef struct {
unsigned char device_id;
bool state;
unsigned char value;
} alexa_queue_element_t;
fauxmoESP _alexa;
static std::queue<alexa_queue_element_t> _alexa_queue;
// -----------------------------------------------------------------------------
@ -36,17 +33,17 @@ void _alexaWebSocketOnConnected(JsonObject& root) {
}
void _alexaConfigure() {
alexa.enable(wifiConnected() && alexaEnabled());
_alexa.enable(wifiConnected() && alexaEnabled());
}
#if WEB_SUPPORT
bool _alexaBodyCallback(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {
return alexa.process(request->client(), request->method() == HTTP_GET, request->url(), String((char *)data));
return _alexa.process(request->client(), request->method() == HTTP_GET, request->url(), String((char *)data));
}
bool _alexaRequestCallback(AsyncWebServerRequest *request) {
String body = (request->hasParam("body", true)) ? request->getParam("body", true)->value() : String();
return alexa.process(request->client(), request->method() == HTTP_GET, request->url(), body);
return _alexa.process(request->client(), request->method() == HTTP_GET, request->url(), body);
}
#endif
@ -60,14 +57,14 @@ void _alexaBrokerCallback(const String& topic, unsigned char id, unsigned int va
}
if (topic.equals(MQTT_TOPIC_CHANNEL)) {
alexa.setState(id + 1, value > 0, value);
_alexa.setState(id + 1, value > 0, value);
}
if (topic.equals(MQTT_TOPIC_RELAY)) {
#if RELAY_PROVIDER == RELAY_PROVIDER_LIGHT
if (id > 0) return;
#endif
alexa.setState(id, value, value > 0 ? 255 : 0);
_alexa.setState(id, value, value > 0 ? 255 : 0);
}
}
@ -85,8 +82,8 @@ void alexaSetup() {
moveSetting("fauxmoEnabled", "alexaEnabled");
// Basic fauxmoESP configuration
alexa.createServer(!WEB_SUPPORT);
alexa.setPort(80);
_alexa.createServer(!WEB_SUPPORT);
_alexa.setPort(80);
// Use custom alexa hostname if defined, device hostname otherwise
String hostname = getSetting("alexaName", ALEXA_HOSTNAME);
@ -98,11 +95,11 @@ void alexaSetup() {
#if RELAY_PROVIDER == RELAY_PROVIDER_LIGHT
// Global switch
alexa.addDevice(hostname.c_str());
_alexa.addDevice(hostname.c_str());
// For each channel
for (unsigned char i = 1; i <= lightChannels(); i++) {
alexa.addDevice((hostname + " " + i).c_str());
_alexa.addDevice((hostname + " " + i).c_str());
}
// Relays
@ -110,10 +107,10 @@ void alexaSetup() {
unsigned int relays = relayCount();
if (relays == 1) {
alexa.addDevice(hostname.c_str());
_alexa.addDevice(hostname.c_str());
} else {
for (unsigned int i=1; i<=relays; i++) {
alexa.addDevice((hostname + " " + i).c_str());
_alexa.addDevice((hostname + " " + i).c_str());
}
}
@ -140,7 +137,7 @@ void alexaSetup() {
});
// Callback
alexa.onSetState([&](unsigned char device_id, const char * name, bool state, unsigned char value) {
_alexa.onSetState([&](unsigned char device_id, const char * name, bool state, unsigned char value) {
alexa_queue_element_t element;
element.device_id = device_id;
element.state = state;
@ -159,7 +156,7 @@ void alexaSetup() {
void alexaLoop() {
alexa.handle();
_alexa.handle();
while (!_alexa_queue.empty()) {


+ 31
- 0
code/espurna/api.h View File

@ -0,0 +1,31 @@
/*
API MODULE
Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#pragma once
#include "web.h"
#include <functional>
// TODO: need these prototypes for .ino
using api_get_callback_f = std::function<void(char * buffer, size_t size)>;
using api_put_callback_f = std::function<void(const char * payload)> ;
#if API_SUPPORT
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include <vector>
#if WEB_SUPPORT
void apiRegister(const char * key, api_get_callback_f getFn, api_put_callback_f putFn = nullptr);
#endif
#endif // API_SUPPORT == 1

+ 3
- 5
code/espurna/api.ino View File

@ -8,12 +8,10 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#if API_SUPPORT
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include <vector>
#include "api.h"
#include "system.h"
#include "web.h"
#include "ws.h"
typedef struct {
char * key;


+ 288
- 1
code/espurna/board.ino View File

@ -6,6 +6,293 @@ BOARD MODULE
#include "board.h"
//--------------------------------------------------------------------------------
PROGMEM const char espurna_modules[] =
#if ALEXA_SUPPORT
"ALEXA "
#endif
#if API_SUPPORT
"API "
#endif
#if BROKER_SUPPORT
"BROKER "
#endif
#if BUTTON_SUPPORT
"BUTTON "
#endif
#if DEBUG_SERIAL_SUPPORT
"DEBUG_SERIAL "
#endif
#if DEBUG_TELNET_SUPPORT
"DEBUG_TELNET "
#endif
#if DEBUG_UDP_SUPPORT
"DEBUG_UDP "
#endif
#if DEBUG_WEB_SUPPORT
"DEBUG_WEB "
#endif
#if DOMOTICZ_SUPPORT
"DOMOTICZ "
#endif
#if ENCODER_SUPPORT
"ENCODER "
#endif
#if HOMEASSISTANT_SUPPORT
"HOMEASSISTANT "
#endif
#if I2C_SUPPORT
"I2C "
#endif
#if INFLUXDB_SUPPORT
"INFLUXDB "
#endif
#if IR_SUPPORT
"IR "
#endif
#if LED_SUPPORT
"LED "
#endif
#if LLMNR_SUPPORT
"LLMNR "
#endif
#if MDNS_CLIENT_SUPPORT
"MDNS_CLIENT "
#endif
#if MDNS_SERVER_SUPPORT
"MDNS_SERVER "
#endif
#if MQTT_SUPPORT
"MQTT "
#endif
#if NETBIOS_SUPPORT
"NETBIOS "
#endif
#if NOFUSS_SUPPORT
"NOFUSS "
#endif
#if NTP_SUPPORT
"NTP "
#endif
#if RFM69_SUPPORT
"RFM69 "
#endif
#if RF_SUPPORT
"RF "
#endif
#if SCHEDULER_SUPPORT
"SCHEDULER "
#endif
#if SENSOR_SUPPORT
"SENSOR "
#endif
#if SPIFFS_SUPPORT
"SPIFFS "
#endif
#if SSDP_SUPPORT
"SSDP "
#endif
#if TELNET_SUPPORT
#if TELNET_SERVER == TELNET_SERVER_WIFISERVER
"TELNET_SYNC "
#else
"TELNET "
#endif // TELNET_SERVER == TELNET_SERVER_WIFISERVER
#endif
#if TERMINAL_SUPPORT
"TERMINAL "
#endif
#if THERMOSTAT_SUPPORT
"THERMOSTAT "
#endif
#if THERMOSTAT_DISPLAY_SUPPORT
"THERMOSTAT_DISPLAY "
#endif
#if THINGSPEAK_SUPPORT
"THINGSPEAK "
#endif
#if UART_MQTT_SUPPORT
"UART_MQTT "
#endif
#if WEB_SUPPORT
"WEB "
#endif
"";
PROGMEM const char espurna_ota_modules[] =
#if OTA_ARDUINOOTA_SUPPORT
"ARDUINO "
#endif
#if (OTA_CLIENT == OTA_CLIENT_ASYNCTCP)
"ASYNCTCP "
#endif
#if (OTA_CLIENT == OTA_CLIENT_HTTPUPDATE)
#if (SECURE_CLIENT == SECURE_CLIENT_NONE)
"*HTTPUPDATE "
#endif
#if (SECURE_CLIENT == SECURE_CLIENT_AXTLS)
"*HTTPUPDATE_AXTLS "
#endif
#if (SECURE_CLIENT == SECURE_CLIENT_BEARSSL)
"*HTTPUPDATE_BEARSSL "
#endif
#endif // OTA_CLIENT_HTTPUPDATE
#if OTA_MQTT_SUPPORT
"MQTT "
#endif
#if WEB_SUPPORT
"WEB "
#endif
"";
PROGMEM const char espurna_webui[] =
#if WEBUI_IMAGE == WEBUI_IMAGE_SMALL
"SMALL"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_LIGHT
"LIGHT"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_SENSOR
"SENSOR"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_RFBRIDGE
"RFBRIDGE"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_RFM69
"RFM69"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_LIGHTFOX
"LIGHTFOX"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_THERMOSTAT
"THERMOSTAT"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_FULL
"FULL"
#endif
"";
#if SENSOR_SUPPORT
PROGMEM const char espurna_sensors[] =
#if AM2320_SUPPORT
"AM2320_I2C "
#endif
#if ANALOG_SUPPORT
"ANALOG "
#endif
#if BH1750_SUPPORT
"BH1750 "
#endif
#if BMP180_SUPPORT
"BMP180 "
#endif
#if BMX280_SUPPORT
"BMX280 "
#endif
#if CSE7766_SUPPORT
"CSE7766 "
#endif
#if DALLAS_SUPPORT
"DALLAS "
#endif
#if DHT_SUPPORT
"DHTXX "
#endif
#if DIGITAL_SUPPORT
"DIGITAL "
#endif
#if ECH1560_SUPPORT
"ECH1560 "
#endif
#if EMON_ADC121_SUPPORT
"EMON_ADC121 "
#endif
#if EMON_ADS1X15_SUPPORT
"EMON_ADX1X15 "
#endif
#if EMON_ANALOG_SUPPORT
"EMON_ANALOG "
#endif
#if EVENTS_SUPPORT
"EVENTS "
#endif
#if GEIGER_SUPPORT
"GEIGER "
#endif
#if GUVAS12SD_SUPPORT
"GUVAS12SD "
#endif
#if HLW8012_SUPPORT
"HLW8012 "
#endif
#if LDR_SUPPORT
"LDR "
#endif
#if MHZ19_SUPPORT
"MHZ19 "
#endif
#if MICS2710_SUPPORT
"MICS2710 "
#endif
#if MICS5525_SUPPORT
"MICS5525 "
#endif
#if NTC_SUPPORT
"NTC "
#endif
#if PMSX003_SUPPORT
"PMSX003 "
#endif
#if PULSEMETER_SUPPORT
"PULSEMETER "
#endif
#if PZEM004T_SUPPORT
"PZEM004T "
#endif
#if SDS011_SUPPORT
"SDS011 "
#endif
#if SENSEAIR_SUPPORT
"SENSEAIR "
#endif
#if SHT3X_I2C_SUPPORT
"SHT3X_I2C "
#endif
#if SI7021_SUPPORT
"SI7021 "
#endif
#if SONAR_SUPPORT
"SONAR "
#endif
#if T6613_SUPPORT
"T6613 "
#endif
#if TMP3X_SUPPORT
"TMP3X "
#endif
#if V9261F_SUPPORT
"V9261F "
#endif
#if VEML6075_SUPPORT
"VEML6075 "
#endif
#if VL53L1X_SUPPORT
"VL53L1X "
#endif
#if EZOPH_SUPPORT
"EZOPH "
#endif
#if ADE7953_SUPPORT
"ADE7953 "
#endif
"";
#endif // SENSOR_SUPPORT == 1
//--------------------------------------------------------------------------------
String getIdentifier() {
char buffer[20];
snprintf_P(buffer, sizeof(buffer), PSTR("%s-%06X"), APP_NAME, ESP.getChipId());
@ -24,7 +311,7 @@ String getEspurnaOTAModules() {
String getEspurnaSensors() {
return FPSTR(espurna_sensors);
}
#endif
#endif // SENSOR_SUPPORT == 1
String getEspurnaWebUI() {
return FPSTR(espurna_webui);


+ 3
- 3
code/espurna/broker.h View File

@ -6,10 +6,10 @@ Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#if BROKER_SUPPORT
#pragma once
#if BROKER_SUPPORT
#include <functional>
#include <vector>
#include <utility>
@ -56,4 +56,4 @@ using SensorReportBroker = TBroker<TBrokerType::SENSOR_REPORT, const String&, un
using ConfigBroker = TBroker<TBrokerType::CONFIG, const String&, const String&>;
#endif // BROKER_SUPPORT
#endif // BROKER_SUPPORT == 1

+ 87
- 0
code/espurna/compat.h View File

@ -0,0 +1,87 @@
/*
COMPATIBILITY BETWEEN 2.3.0 and latest versions
*/
#pragma once
// -----------------------------------------------------------------------------
// Core version 2.4.2 and higher changed the cont_t structure to a pointer:
// https://github.com/esp8266/Arduino/commit/5d5ea92a4d004ab009d5f642629946a0cb8893dd#diff-3fa12668b289ccb95b7ab334833a4ba8L35
// Core version 2.5.0 introduced EspClass helper method:
// https://github.com/esp8266/Arduino/commit/0e0e34c614fe8a47544c9998201b1d9b3c24eb18
// -----------------------------------------------------------------------------
extern "C" {
#include <cont.h>
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) \
|| defined(ARDUINO_ESP8266_RELEASE_2_4_0) \
|| defined(ARDUINO_ESP8266_RELEASE_2_4_1)
extern cont_t g_cont;
#define getFreeStack() cont_get_free_stack(&g_cont)
#elif defined(ARDUINO_ESP8266_RELEASE_2_4_2)
extern cont_t* g_pcont;
#define getFreeStack() cont_get_free_stack(g_pcont)
#else
#define getFreeStack() ESP.getFreeContStack()
#endif
}
#include <pgmspace.h>
// -----------------------------------------------------------------------------
// ref: https://github.com/esp8266/Arduino/blob/master/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h
// __STRINGIZE && __STRINGIZE_NX && PROGMEM definitions port
// -----------------------------------------------------------------------------
// Do not replace macros unless running version older than 2.5.0
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) \
|| defined(ARDUINO_ESP8266_RELEASE_2_4_0) \
|| defined(ARDUINO_ESP8266_RELEASE_2_4_1) \
|| defined(ARDUINO_ESP8266_RELEASE_2_4_2)
// Quoting esp8266/Arduino comments:
// "Since __section__ is supposed to be only use for global variables,
// there could be conflicts when a static/inlined function has them in the
// same file as a non-static PROGMEM object.
// Ref: https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Variable-Attributes.html
// Place each progmem object into its own named section, avoiding conflicts"
#define __TO_STR_(A) #A
#define __TO_STR(A) __TO_STR_(A)
#undef PROGMEM
#define PROGMEM __attribute__((section( "\".irom.text." __FILE__ "." __TO_STR(__LINE__) "." __TO_STR(__COUNTER__) "\"")))
// "PSTR() macro modified to start on a 32-bit boundary. This adds on average
// 1.5 bytes/string, but in return memcpy_P and strcpy_P will work 4~8x faster"
#undef PSTR
#define PSTR(s) (__extension__({static const char __c[] __attribute__((__aligned__(4))) PROGMEM = (s); &__c[0];}))
#endif
// -----------------------------------------------------------------------------
// Division by zero bug
// https://github.com/esp8266/Arduino/pull/2397
// https://github.com/esp8266/Arduino/pull/2408
// -----------------------------------------------------------------------------
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0)
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);
#endif
// -----------------------------------------------------------------------------
// std::make_unique backport for C++11, since we still use it
// -----------------------------------------------------------------------------
#if 201103L >= __cplusplus
namespace std {
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
}
#endif
#define UNUSED(x) (void)(x)

+ 4
- 2
code/espurna/config/all.h View File

@ -19,7 +19,11 @@
*/
#pragma once
#include <Arduino.h>
#include <core_version.h>
#include <pgmspace.h>
#ifdef USE_CUSTOM_H
#include "custom.h"
@ -34,7 +38,5 @@
#include "deprecated.h"
#include "general.h"
#include "dependencies.h"
#include "prototypes.h"
#include "sensors.h"
#include "webui.h"
#include "progmem.h"

+ 2
- 0
code/espurna/config/arduino.h View File

@ -3,6 +3,8 @@
// Uncomment the appropiate line(s) to build from the Arduino IDE
//--------------------------------------------------------------------------------
#pragma once
//--------------------------------------------------------------------------------
// Hardware
//--------------------------------------------------------------------------------


+ 6
- 0
code/espurna/config/defaults.h View File

@ -1,3 +1,9 @@
// -----------------------------------------------------------------------------
// DEFAULTS PER MODULE
// -----------------------------------------------------------------------------
#pragma once
// -----------------------------------------------------------------------------
// Buttons
// -----------------------------------------------------------------------------


+ 4
- 2
code/espurna/config/general.h View File

@ -1,8 +1,10 @@
// // //------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Do not change this file unless you know what you are doing
// Configuration settings are in the settings.h file
// To override user configuration, please see custom.h
//------------------------------------------------------------------------------
#pragma once
//------------------------------------------------------------------------------
// GENERAL
//------------------------------------------------------------------------------


+ 2
- 0
code/espurna/config/hardware.h View File

@ -20,6 +20,8 @@
//
// Besides, other hardware specific information should be stated here
#pragma once
// -----------------------------------------------------------------------------
// Custom hardware
// -----------------------------------------------------------------------------


+ 0
- 395
code/espurna/config/progmem.h View File

@ -1,395 +0,0 @@
//--------------------------------------------------------------------------------
// PROGMEM definitions
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// Various strings
//--------------------------------------------------------------------------------
PROGMEM const char pstr_unknown[] = "UNKNOWN";
//--------------------------------------------------------------------------------
// Reset reasons
//--------------------------------------------------------------------------------
PROGMEM const char custom_reset_hardware[] = "Hardware button";
PROGMEM const char custom_reset_web[] = "Reboot from web interface";
PROGMEM const char custom_reset_terminal[] = "Reboot from terminal";
PROGMEM const char custom_reset_mqtt[] = "Reboot from MQTT";
PROGMEM const char custom_reset_rpc[] = "Reboot from RPC";
PROGMEM const char custom_reset_ota[] = "Reboot after successful OTA update";
PROGMEM const char custom_reset_http[] = "Reboot from HTTP";
PROGMEM const char custom_reset_nofuss[] = "Reboot after successful NoFUSS update";
PROGMEM const char custom_reset_upgrade[] = "Reboot after successful web update";
PROGMEM const char custom_reset_factory[] = "Factory reset";
PROGMEM const char* const custom_reset_string[] = {
custom_reset_hardware, custom_reset_web, custom_reset_terminal,
custom_reset_mqtt, custom_reset_rpc, custom_reset_ota,
custom_reset_http, custom_reset_nofuss, custom_reset_upgrade,
custom_reset_factory
};
//--------------------------------------------------------------------------------
// Capabilities
//--------------------------------------------------------------------------------
PROGMEM const char espurna_modules[] =
#if ALEXA_SUPPORT
"ALEXA "
#endif
#if API_SUPPORT
"API "
#endif
#if BROKER_SUPPORT
"BROKER "
#endif
#if BUTTON_SUPPORT
"BUTTON "
#endif
#if DEBUG_SERIAL_SUPPORT
"DEBUG_SERIAL "
#endif
#if DEBUG_TELNET_SUPPORT
"DEBUG_TELNET "
#endif
#if DEBUG_UDP_SUPPORT
"DEBUG_UDP "
#endif
#if DEBUG_WEB_SUPPORT
"DEBUG_WEB "
#endif
#if DOMOTICZ_SUPPORT
"DOMOTICZ "
#endif
#if ENCODER_SUPPORT
"ENCODER "
#endif
#if HOMEASSISTANT_SUPPORT
"HOMEASSISTANT "
#endif
#if I2C_SUPPORT
"I2C "
#endif
#if INFLUXDB_SUPPORT
"INFLUXDB "
#endif
#if IR_SUPPORT
"IR "
#endif
#if LED_SUPPORT
"LED "
#endif
#if LLMNR_SUPPORT
"LLMNR "
#endif
#if MDNS_CLIENT_SUPPORT
"MDNS_CLIENT "
#endif
#if MDNS_SERVER_SUPPORT
"MDNS_SERVER "
#endif
#if MQTT_SUPPORT
"MQTT "
#endif
#if NETBIOS_SUPPORT
"NETBIOS "
#endif
#if NOFUSS_SUPPORT
"NOFUSS "
#endif
#if NTP_SUPPORT
"NTP "
#endif
#if RFM69_SUPPORT
"RFM69 "
#endif
#if RF_SUPPORT
"RF "
#endif
#if SCHEDULER_SUPPORT
"SCHEDULER "
#endif
#if SENSOR_SUPPORT
"SENSOR "
#endif
#if SPIFFS_SUPPORT
"SPIFFS "
#endif
#if SSDP_SUPPORT
"SSDP "
#endif
#if TELNET_SUPPORT
#if TELNET_SERVER == TELNET_SERVER_WIFISERVER
"TELNET_SYNC "
#else
"TELNET "
#endif // TELNET_SERVER == TELNET_SERVER_WIFISERVER
#endif
#if TERMINAL_SUPPORT
"TERMINAL "
#endif
#if THERMOSTAT_SUPPORT
"THERMOSTAT "
#endif
#if THERMOSTAT_DISPLAY_SUPPORT
"THERMOSTAT_DISPLAY "
#endif
#if THINGSPEAK_SUPPORT
"THINGSPEAK "
#endif
#if UART_MQTT_SUPPORT
"UART_MQTT "
#endif
#if WEB_SUPPORT
"WEB "
#endif
"";
PROGMEM const char espurna_ota_modules[] =
#if OTA_ARDUINOOTA_SUPPORT
"ARDUINO "
#endif
#if (OTA_CLIENT == OTA_CLIENT_ASYNCTCP)
"ASYNCTCP "
#endif
#if (OTA_CLIENT == OTA_CLIENT_HTTPUPDATE)
#if (SECURE_CLIENT == SECURE_CLIENT_NONE)
"*HTTPUPDATE "
#endif
#if (SECURE_CLIENT == SECURE_CLIENT_AXTLS)
"*HTTPUPDATE_AXTLS "
#endif
#if (SECURE_CLIENT == SECURE_CLIENT_BEARSSL)
"*HTTPUPDATE_BEARSSL "
#endif
#endif // OTA_CLIENT_HTTPUPDATE
#if OTA_MQTT_SUPPORT
"MQTT "
#endif
#if WEB_SUPPORT
"WEB "
#endif
"";
//--------------------------------------------------------------------------------
// Sensors
//--------------------------------------------------------------------------------
#if SENSOR_SUPPORT
PROGMEM const char espurna_sensors[] =
#if AM2320_SUPPORT
"AM2320_I2C "
#endif
#if ANALOG_SUPPORT
"ANALOG "
#endif
#if BH1750_SUPPORT
"BH1750 "
#endif
#if BMP180_SUPPORT
"BMP180 "
#endif
#if BMX280_SUPPORT
"BMX280 "
#endif
#if CSE7766_SUPPORT
"CSE7766 "
#endif
#if DALLAS_SUPPORT
"DALLAS "
#endif
#if DHT_SUPPORT
"DHTXX "
#endif
#if DIGITAL_SUPPORT
"DIGITAL "
#endif
#if ECH1560_SUPPORT
"ECH1560 "
#endif
#if EMON_ADC121_SUPPORT
"EMON_ADC121 "
#endif
#if EMON_ADS1X15_SUPPORT
"EMON_ADX1X15 "
#endif
#if EMON_ANALOG_SUPPORT
"EMON_ANALOG "
#endif
#if EVENTS_SUPPORT
"EVENTS "
#endif
#if GEIGER_SUPPORT
"GEIGER "
#endif
#if GUVAS12SD_SUPPORT
"GUVAS12SD "
#endif
#if HLW8012_SUPPORT
"HLW8012 "
#endif
#if LDR_SUPPORT
"LDR "
#endif
#if MHZ19_SUPPORT
"MHZ19 "
#endif
#if MICS2710_SUPPORT
"MICS2710 "
#endif
#if MICS5525_SUPPORT
"MICS5525 "
#endif
#if NTC_SUPPORT
"NTC "
#endif
#if PMSX003_SUPPORT
"PMSX003 "
#endif
#if PULSEMETER_SUPPORT
"PULSEMETER "
#endif
#if PZEM004T_SUPPORT
"PZEM004T "
#endif
#if SDS011_SUPPORT
"SDS011 "
#endif
#if SENSEAIR_SUPPORT
"SENSEAIR "
#endif
#if SHT3X_I2C_SUPPORT
"SHT3X_I2C "
#endif
#if SI7021_SUPPORT
"SI7021 "
#endif
#if SONAR_SUPPORT
"SONAR "
#endif
#if T6613_SUPPORT
"T6613 "
#endif
#if TMP3X_SUPPORT
"TMP3X "
#endif
#if V9261F_SUPPORT
"V9261F "
#endif
#if VEML6075_SUPPORT
"VEML6075 "
#endif
#if VL53L1X_SUPPORT
"VL53L1X "
#endif
#if EZOPH_SUPPORT
"EZOPH "
#endif
#if ADE7953_SUPPORT
"ADE7953 "
#endif
"";
PROGMEM const unsigned char magnitude_decimals[] = {
0,
1, 0, 2, // THP
3, 0, 0, 0, 0, 0, 0, 0, // Power decimals
0, 0, 0, // analog, digital, event
0, 0, 0, // PM
0, 0,
0, 0, 3, // UVA, UVB, UVI
3, 0,
4, 4, // Geiger Counter decimals
0,
0, 0, 0, 3 // NO2, CO, Ohms, pH
};
PROGMEM const char magnitude_unknown_topic[] = "unknown";
PROGMEM const char magnitude_temperature_topic[] = "temperature";
PROGMEM const char magnitude_humidity_topic[] = "humidity";
PROGMEM const char magnitude_pressure_topic[] = "pressure";
PROGMEM const char magnitude_current_topic[] = "current";
PROGMEM const char magnitude_voltage_topic[] = "voltage";
PROGMEM const char magnitude_active_power_topic[] = "power";
PROGMEM const char magnitude_apparent_power_topic[] = "apparent";
PROGMEM const char magnitude_reactive_power_topic[] = "reactive";
PROGMEM const char magnitude_power_factor_topic[] = "factor";
PROGMEM const char magnitude_energy_topic[] = "energy";
PROGMEM const char magnitude_energy_delta_topic[] = "energy_delta";
PROGMEM const char magnitude_analog_topic[] = "analog";
PROGMEM const char magnitude_digital_topic[] = "digital";
PROGMEM const char magnitude_event_topic[] = "event";
PROGMEM const char magnitude_pm1dot0_topic[] = "pm1dot0";
PROGMEM const char magnitude_pm2dot5_topic[] = "pm2dot5";
PROGMEM const char magnitude_pm10_topic[] = "pm10";
PROGMEM const char magnitude_co2_topic[] = "co2";
PROGMEM const char magnitude_lux_topic[] = "lux";
PROGMEM const char magnitude_uva_topic[] = "uva";
PROGMEM const char magnitude_uvb_topic[] = "uvb";
PROGMEM const char magnitude_uvi_topic[] = "uvi";
PROGMEM const char magnitude_distance_topic[] = "distance";
PROGMEM const char magnitude_hcho_topic[] = "hcho";
PROGMEM const char magnitude_geiger_cpm_topic[] = "ldr_cpm"; // local dose rate [Counts per minute]
PROGMEM const char magnitude_geiger_sv_topic[] = "ldr_uSvh"; // local dose rate [µSievert per hour]
PROGMEM const char magnitude_count_topic[] = "count";
PROGMEM const char magnitude_no2_topic[] = "no2";
PROGMEM const char magnitude_co_topic[] = "co";
PROGMEM const char magnitude_resistance_topic[] = "resistance";
PROGMEM const char magnitude_ph_topic[] = "ph";
PROGMEM const char* const magnitude_topics[] = {
magnitude_unknown_topic, magnitude_temperature_topic, magnitude_humidity_topic,
magnitude_pressure_topic, magnitude_current_topic, magnitude_voltage_topic,
magnitude_active_power_topic, magnitude_apparent_power_topic, magnitude_reactive_power_topic,
magnitude_power_factor_topic, magnitude_energy_topic, magnitude_energy_delta_topic,
magnitude_analog_topic, magnitude_digital_topic, magnitude_event_topic,
magnitude_pm1dot0_topic, magnitude_pm2dot5_topic, magnitude_pm10_topic,
magnitude_co2_topic, magnitude_lux_topic,
magnitude_uva_topic, magnitude_uvb_topic, magnitude_uvi_topic,
magnitude_distance_topic, magnitude_hcho_topic,
magnitude_geiger_cpm_topic, magnitude_geiger_sv_topic,
magnitude_count_topic,
magnitude_no2_topic, magnitude_co_topic, magnitude_resistance_topic, magnitude_ph_topic
};
PROGMEM const char magnitude_empty[] = "";
PROGMEM const char magnitude_celsius[] = "°C";
PROGMEM const char magnitude_fahrenheit[] = "°F";
PROGMEM const char magnitude_percentage[] = "%";
PROGMEM const char magnitude_hectopascals[] = "hPa";
PROGMEM const char magnitude_amperes[] = "A";
PROGMEM const char magnitude_volts[] = "V";
PROGMEM const char magnitude_watts[] = "W";
PROGMEM const char magnitude_kw[] = "kW";
PROGMEM const char magnitude_joules[] = "J";
PROGMEM const char magnitude_kwh[] = "kWh";
PROGMEM const char magnitude_ugm3[] = "µg/m³";
PROGMEM const char magnitude_ppm[] = "ppm";
PROGMEM const char magnitude_lux[] = "lux";
PROGMEM const char magnitude_distance[] = "m";
PROGMEM const char magnitude_mgm3[] = "mg/m³";
PROGMEM const char magnitude_geiger_cpm[] = "cpm"; // Counts per Minute: Unit of local dose rate (Geiger counting)
PROGMEM const char magnitude_geiger_sv[] = "µSv/h"; // µSievert per hour: 2nd unit of local dose rate (Geiger counting)
PROGMEM const char magnitude_resistance[] = "ohm";
PROGMEM const char* const magnitude_units[] = {
magnitude_empty, magnitude_celsius, magnitude_percentage,
magnitude_hectopascals, magnitude_amperes, magnitude_volts,
magnitude_watts, magnitude_watts, magnitude_watts,
magnitude_percentage, magnitude_joules, magnitude_joules,
magnitude_empty, magnitude_empty, magnitude_empty,
magnitude_ugm3, magnitude_ugm3, magnitude_ugm3,
magnitude_ppm, magnitude_lux,
magnitude_empty, magnitude_empty, magnitude_empty,
magnitude_distance, magnitude_mgm3,
magnitude_geiger_cpm, magnitude_geiger_sv, // Geiger counter units
magnitude_empty, //
magnitude_ppm, magnitude_ppm, // NO2 & CO2
magnitude_resistance,
magnitude_empty // pH
};
#endif

+ 0
- 319
code/espurna/config/prototypes.h View File

@ -1,319 +0,0 @@
#include <Arduino.h>
#include <ArduinoJson.h>
#include <functional>
#include <algorithm>
#include <limits>
#include <vector>
#include <memory>
extern "C" {
#include "user_interface.h"
extern struct rst_info resetInfo;
}
#define UNUSED(x) (void)(x)
// -----------------------------------------------------------------------------
// System
// -----------------------------------------------------------------------------
#define LWIP_INTERNAL
#include <ESP8266WiFi.h>
#undef LWIP_INTERNAL
extern "C" {
#include <lwip/opt.h>
#include <lwip/ip.h>
#include <lwip/tcp.h>
#include <lwip/inet.h> // ip_addr_t
#include <lwip/err.h> // ERR_x
#include <lwip/dns.h> // dns_gethostbyname
#include <lwip/ip_addr.h> // ip4/ip6 helpers
#include <lwip/init.h> // LWIP_VERSION_MAJOR
}
// ref: https://github.com/me-no-dev/ESPAsyncTCP/pull/115/files#diff-e2e636049095cc1ff920c1bfabf6dcacR8
// This is missing with Core 2.3.0 and is sometimes missing from the build flags. Assume HIGH_BANDWIDTH version.
#ifndef TCP_MSS
#define TCP_MSS (1460)
#endif
// -----------------------------------------------------------------------------
// PROGMEM
// -----------------------------------------------------------------------------
#include <pgmspace.h>
// ref: https://github.com/esp8266/Arduino/blob/master/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h
// __STRINGIZE && __STRINGIZE_NX && PROGMEM definitions port
// Do not replace macros unless running version older than 2.5.0
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) \
|| defined(ARDUINO_ESP8266_RELEASE_2_4_0) \
|| defined(ARDUINO_ESP8266_RELEASE_2_4_1) \
|| defined(ARDUINO_ESP8266_RELEASE_2_4_2)
// Quoting esp8266/Arduino comments:
// "Since __section__ is supposed to be only use for global variables,
// there could be conflicts when a static/inlined function has them in the
// same file as a non-static PROGMEM object.
// Ref: https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Variable-Attributes.html
// Place each progmem object into its own named section, avoiding conflicts"
#define __TO_STR_(A) #A
#define __TO_STR(A) __TO_STR_(A)
#undef PROGMEM
#define PROGMEM __attribute__((section( "\".irom.text." __FILE__ "." __TO_STR(__LINE__) "." __TO_STR(__COUNTER__) "\"")))
// "PSTR() macro modified to start on a 32-bit boundary. This adds on average
// 1.5 bytes/string, but in return memcpy_P and strcpy_P will work 4~8x faster"
#undef PSTR
#define PSTR(s) (__extension__({static const char __c[] __attribute__((__aligned__(4))) PROGMEM = (s); &__c[0];}))
#endif
// -----------------------------------------------------------------------------
// API
// -----------------------------------------------------------------------------
using api_get_callback_f = std::function<void(char * buffer, size_t size)>;
using api_put_callback_f = std::function<void(const char * payload)> ;
#if WEB_SUPPORT
void apiRegister(const char * key, api_get_callback_f getFn, api_put_callback_f putFn = NULL);
#endif
// Core version 2.4.2 and higher changed the cont_t structure to a pointer:
// https://github.com/esp8266/Arduino/commit/5d5ea92a4d004ab009d5f642629946a0cb8893dd#diff-3fa12668b289ccb95b7ab334833a4ba8L35
// Core version 2.5.0 introduced EspClass helper method:
// https://github.com/esp8266/Arduino/commit/0e0e34c614fe8a47544c9998201b1d9b3c24eb18
extern "C" {
#include <cont.h>
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) \
|| defined(ARDUINO_ESP8266_RELEASE_2_4_0) \
|| defined(ARDUINO_ESP8266_RELEASE_2_4_1)
extern cont_t g_cont;
#define getFreeStack() cont_get_free_stack(&g_cont)
#elif defined(ARDUINO_ESP8266_RELEASE_2_4_2)
extern cont_t* g_pcont;
#define getFreeStack() cont_get_free_stack(g_pcont)
#else
#define getFreeStack() ESP.getFreeContStack()
#endif
}
void infoMemory(const char* , unsigned int, unsigned int);
unsigned int getFreeHeap();
unsigned int getInitialFreeHeap();
// -----------------------------------------------------------------------------
// Domoticz
// -----------------------------------------------------------------------------
#if DOMOTICZ_SUPPORT
template<typename T> void domoticzSend(const char * key, T value);
template<typename T> void domoticzSend(const char * key, T nvalue, const char * svalue);
#endif
// -----------------------------------------------------------------------------
// EEPROM_ROTATE
// -----------------------------------------------------------------------------
#include <EEPROM_Rotate.h>
EEPROM_Rotate EEPROMr;
void eepromSectorsDebug();
// -----------------------------------------------------------------------------
// GPIO
// -----------------------------------------------------------------------------
bool gpioValid(unsigned char gpio);
bool gpioGetLock(unsigned char gpio);
bool gpioReleaseLock(unsigned char gpio);
// -----------------------------------------------------------------------------
// Homeassistant
// -----------------------------------------------------------------------------
struct ha_config_t;
void haSetup();
// -----------------------------------------------------------------------------
// I2C
// -----------------------------------------------------------------------------
void i2cScan();
void i2cClearBus();
bool i2cGetLock(unsigned char address);
bool i2cReleaseLock(unsigned char address);
unsigned char i2cFindAndLock(size_t size, unsigned char * addresses);
void i2c_wakeup(uint8_t address);
uint8_t i2c_write_buffer(uint8_t address, uint8_t * buffer, size_t len);
uint8_t i2c_write_uint8(uint8_t address, uint8_t value);
uint8_t i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value);
uint8_t i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value1, uint8_t value2);
uint8_t i2c_write_uint16(uint8_t address, uint16_t value);
uint8_t i2c_write_uint16(uint8_t address, uint8_t reg, uint16_t value);
uint8_t i2c_read_uint8(uint8_t address);
uint8_t i2c_read_uint8(uint8_t address, uint8_t reg);
uint16_t i2c_read_uint16(uint8_t address);
uint16_t i2c_read_uint16(uint8_t address, uint8_t reg);
uint16_t i2c_read_uint16_le(uint8_t address, uint8_t reg);
int16_t i2c_read_int16(uint8_t address, uint8_t reg);
int16_t i2c_read_int16_le(uint8_t address, uint8_t reg);
void i2c_read_buffer(uint8_t address, uint8_t * buffer, size_t len);
// -----------------------------------------------------------------------------
// MQTT
// -----------------------------------------------------------------------------
#if MQTT_LIBRARY == MQTT_LIBRARY_ASYNCMQTTCLIENT
#include <ESPAsyncTCP.h>
#include <AsyncMqttClient.h>
#elif MQTT_LIBRARY == MQTT_LIBRARY_ARDUINOMQTT
#include <MQTTClient.h>
#elif MQTT_LIBRARY == MQTT_LIBRARY_PUBSUBCLIENT
#include <PubSubClient.h>
#endif
using mqtt_callback_f = std::function<void(unsigned int type, const char * topic, char * payload)>;
using mqtt_msg_t = std::pair<String, String>; // topic, payload
void mqttRegister(mqtt_callback_f callback);
String mqttTopic(const char * magnitude, bool is_set);
String mqttTopic(const char * magnitude, unsigned int index, bool is_set);
String mqttMagnitude(char * topic);
bool mqttSendRaw(const char * topic, const char * message, bool retain);
bool mqttSendRaw(const char * topic, const char * message);
void mqttSend(const char * topic, const char * message, bool force, bool retain);
void mqttSend(const char * topic, const char * message, bool force);
void mqttSend(const char * topic, const char * message);
void mqttSend(const char * topic, unsigned int index, const char * message, bool force);
void mqttSend(const char * topic, unsigned int index, const char * message);
const String& mqttPayloadOnline();
const String& mqttPayloadOffline();
const char* mqttPayloadStatus(bool status);
void mqttSendStatus();
// -----------------------------------------------------------------------------
// OTA
// -----------------------------------------------------------------------------
#include <ArduinoOTA.h>
#if OTA_CLIENT == OTA_CLIENT_ASYNCTCP
#include <ESPAsyncTCP.h>
#endif
#if OTA_CLIENT == OTA_CLIENT_HTTPUPDATE
#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>
#endif
#if SECURE_CLIENT != SECURE_CLIENT_NONE
#include <WiFiClientSecure.h>
#endif // SECURE_CLIENT != SECURE_CLIENT_NONE
// -----------------------------------------------------------------------------
// RFM69
// -----------------------------------------------------------------------------
typedef struct {
unsigned long messageID;
unsigned char packetID;
unsigned char senderID;
unsigned char targetID;
char * key;
char * value;
int16_t rssi;
} packet_t;
// -----------------------------------------------------------------------------
// Terminal
// -----------------------------------------------------------------------------
class Embedis; // FIXME: order
using embedis_command_f = void (*)(Embedis*);
void terminalRegisterCommand(const String& name, embedis_command_f func);
void terminalInject(void *data, size_t len);
Stream& terminalSerial();
// -----------------------------------------------------------------------------
// WebServer
// -----------------------------------------------------------------------------
class AsyncClient;
class AsyncWebServer;
#if WEB_SUPPORT
#include <ESPAsyncWebServer.h>
AsyncWebServer * webServer();
#else
class AsyncWebServerRequest;
class ArRequestHandlerFunction;
class AsyncWebSocketClient;
class AsyncWebSocket;
class AwsEventType;
#endif
using web_body_callback_f = std::function<bool(AsyncWebServerRequest*, uint8_t* data, size_t len, size_t index, size_t total)>;
using web_request_callback_f = std::function<bool(AsyncWebServerRequest*)>;
void webBodyRegister(web_body_callback_f);
void webRequestRegister(web_request_callback_f);
// -----------------------------------------------------------------------------
// WIFI
// -----------------------------------------------------------------------------
#include <JustWifi.h>
struct wifi_scan_info_t;
using wifi_scan_f = std::function<void(wifi_scan_info_t& info)>;
using wifi_callback_f = std::function<void(justwifi_messages_t code, char * parameter)>;
void wifiRegister(wifi_callback_f callback);
bool wifiConnected();
#if LWIP_VERSION_MAJOR == 1
#include <netif/etharp.h>
#else // LWIP_VERSION_MAJOR >= 2
#include <lwip/etharp.h>
#endif
// -----------------------------------------------------------------------------
// THERMOSTAT
// -----------------------------------------------------------------------------
using thermostat_callback_f = std::function<void(bool state)>;
#if THERMOSTAT_SUPPORT
void thermostatRegister(thermostat_callback_f callback);
#endif
// -----------------------------------------------------------------------------
// RTC MEMORY
// -----------------------------------------------------------------------------
#include "rtcmem.h"
// -----------------------------------------------------------------------------
// Warn about broken Arduino functions
// -----------------------------------------------------------------------------
// Division by zero bug
// https://github.com/esp8266/Arduino/pull/2397
// https://github.com/esp8266/Arduino/pull/2408
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0)
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);
#endif
// -----------------------------------------------------------------------------
// std::make_unique backport for C++11
// -----------------------------------------------------------------------------
#if 201103L >= __cplusplus
namespace std {
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
}
#endif

+ 2
- 0
code/espurna/config/sensors.h View File

@ -2,6 +2,8 @@
// SENSORS - General configuration
// =============================================================================
#pragma once
#ifndef SENSOR_DEBUG
#define SENSOR_DEBUG 0 // Debug sensors
#endif


+ 2
- 0
code/espurna/config/types.h View File

@ -3,6 +3,8 @@
// Do not touch this definitions
//------------------------------------------------------------------------------
#pragma once
// -----------------------------------------------------------------------------
// WIFI
// -----------------------------------------------------------------------------


+ 6
- 0
code/espurna/config/version.h View File

@ -1,3 +1,9 @@
// -----------------------------------------------------------------------------
// APP NAME AND VERSION
// -----------------------------------------------------------------------------
#pragma once
#define APP_NAME "ESPURNA"
#define APP_VERSION "1.14.2-dev"
#define APP_AUTHOR "xose.perez@gmail.com"


+ 2
- 28
code/espurna/config/webui.h View File

@ -2,6 +2,8 @@
// WEB UI IMAGE
// -----------------------------------------------------------------------------
#pragma once
#define WEBUI_IMAGE_SMALL 0
#define WEBUI_IMAGE_LIGHT 1
#define WEBUI_IMAGE_SENSOR 2
@ -67,31 +69,3 @@
#define WEBUI_IMAGE WEBUI_IMAGE_SMALL
#endif
#include <pgmspace.h>
PROGMEM const char espurna_webui[] =
#if WEBUI_IMAGE == WEBUI_IMAGE_SMALL
"SMALL"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_LIGHT
"LIGHT"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_SENSOR
"SENSOR"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_RFBRIDGE
"RFBRIDGE"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_RFM69
"RFM69"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_LIGHTFOX
"LIGHTFOX"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_THERMOSTAT
"THERMOSTAT"
#endif
#if WEBUI_IMAGE == WEBUI_IMAGE_FULL
"FULL"
#endif
"";

+ 48
- 0
code/espurna/crash.h View File

@ -0,0 +1,48 @@
// -----------------------------------------------------------------------------
// Save crash info
// Taken from krzychb EspSaveCrash
// https://github.com/krzychb/EspSaveCrash
// -----------------------------------------------------------------------------
#pragma once
#define SAVE_CRASH_EEPROM_OFFSET 0x0100 // initial address for crash data
/**
* Structure of the single crash data set
*
* 1. Crash time
* 2. Restart reason
* 3. Exception cause
* 4. epc1
* 5. epc2
* 6. epc3
* 7. excvaddr
* 8. depc
* 9. adress of stack start
* 10. adress of stack end
* 11. stack trace size
* 12. stack trace bytes
* ...
*/
#define SAVE_CRASH_CRASH_TIME 0x00 // 4 bytes
#define SAVE_CRASH_RESTART_REASON 0x04 // 1 byte
#define SAVE_CRASH_EXCEPTION_CAUSE 0x05 // 1 byte
#define SAVE_CRASH_EPC1 0x06 // 4 bytes
#define SAVE_CRASH_EPC2 0x0A // 4 bytes
#define SAVE_CRASH_EPC3 0x0E // 4 bytes
#define SAVE_CRASH_EXCVADDR 0x12 // 4 bytes
#define SAVE_CRASH_DEPC 0x16 // 4 bytes
#define SAVE_CRASH_STACK_START 0x1A // 4 bytes
#define SAVE_CRASH_STACK_END 0x1E // 4 bytes
#define SAVE_CRASH_STACK_SIZE 0x22 // 2 bytes
#define SAVE_CRASH_STACK_TRACE 0x24 // variable
constexpr size_t crashUsedSpace() {
return (SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_STACK_SIZE + 2);
}
void crashClear();
void crashDump();
void crashSetup();

+ 3
- 40
code/espurna/crash.ino View File

@ -8,43 +8,10 @@
#include <stdio.h>
#include <stdarg.h>
#include <EEPROM_Rotate.h>
extern "C" {
#include "user_interface.h"
}
#define SAVE_CRASH_EEPROM_OFFSET 0x0100 // initial address for crash data
/**
* Structure of the single crash data set
*
* 1. Crash time
* 2. Restart reason
* 3. Exception cause
* 4. epc1
* 5. epc2
* 6. epc3
* 7. excvaddr
* 8. depc
* 9. adress of stack start
* 10. adress of stack end
* 11. stack trace size
* 12. stack trace bytes
* ...
*/
#define SAVE_CRASH_CRASH_TIME 0x00 // 4 bytes
#define SAVE_CRASH_RESTART_REASON 0x04 // 1 byte
#define SAVE_CRASH_EXCEPTION_CAUSE 0x05 // 1 byte
#define SAVE_CRASH_EPC1 0x06 // 4 bytes
#define SAVE_CRASH_EPC2 0x0A // 4 bytes
#define SAVE_CRASH_EPC3 0x0E // 4 bytes
#define SAVE_CRASH_EXCVADDR 0x12 // 4 bytes
#define SAVE_CRASH_DEPC 0x16 // 4 bytes
#define SAVE_CRASH_STACK_START 0x1A // 4 bytes
#define SAVE_CRASH_STACK_END 0x1E // 4 bytes
#define SAVE_CRASH_STACK_SIZE 0x22 // 2 bytes
#define SAVE_CRASH_STACK_TRACE 0x24 // variable
#include "system.h"
#include "storage_eeprom.h"
#include "crash.h"
uint16_t _save_crash_stack_trace_max = SAVE_CRASH_STACK_TRACE_MAX;
bool _save_crash_enabled = true;
@ -171,10 +138,6 @@ void crashDump() {
}
constexpr size_t crashUsedSpace() {
return (SAVE_CRASH_EEPROM_OFFSET + SAVE_CRASH_STACK_SIZE + 2);
}
void crashSetup() {
#if TERMINAL_SUPPORT


+ 28
- 0
code/espurna/domoticz.h View File

@ -0,0 +1,28 @@
/*
DOMOTICZ MODULE
Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#pragma once
#if DOMOTICZ_SUPPORT
#include <ArduinoJson.h>
#include <bitset>
template<typename T>
void domoticzSend(const char * key, T value);
template<typename T>
void domoticzSend(const char * key, T nvalue, const char * svalue);
void domoticzSendRelay(unsigned char relayID, bool status);
void domoticzSendRelays();
void domoticzSetup();
bool domoticzEnabled();
#endif // DOMOTICZ_SUPPORT == 1

+ 3
- 4
code/espurna/domoticz.ino View File

@ -8,11 +8,10 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#if DOMOTICZ_SUPPORT
#include "relay.h"
#include "broker.h"
#include <bitset>
#include <ArduinoJson.h>
#include "domoticz.h"
#include "mqtt.h"
#include "relay.h"
bool _dcz_enabled = false;
std::bitset<RELAYS_MAX> _dcz_relay_state;


+ 28
- 4
code/espurna/espurna.ino View File

@ -21,20 +21,44 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "config/all.h"
#include <functional>
#include <algorithm>
#include <limits>
#include <vector>
#include <memory>
#include "board.h"
#include "compat.h"
#include "storage_eeprom.h"
#include "gpio.h"
#include "settings.h"
#include "system.h"
#include "terminal.h"
#include "utils.h"
#include "wifi.h"
#include "alexa.h"
#include "api.h"
#include "broker.h"
#include "button.h"
#include "debug.h"
#include "domoticz.h"
#include "homeassistant.h"
#include "i2c.h"
#include "ir.h"
#include "led.h"
#include "mqtt.h"
#include "ntp.h"
#include "ota.h"
#include "relay.h"
#include "rfm69.h"
#include "rpnrules.h"
#include "settings.h"
#include "system.h"
#include "rtcmem.h"
#include "thermostat.h"
#include "tuya.h"
#include "utils.h"
#include "wifi.h"
#include "web.h"
#include "ws.h"
#include "libs/HeapStats.h"
using void_callback_f = void (*)();


+ 15
- 0
code/espurna/gpio.h View File

@ -0,0 +1,15 @@
/*
GPIO MODULE
Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#pragma once
bool gpioValid(unsigned char gpio);
bool gpioGetLock(unsigned char gpio);
bool gpioReleaseLock(unsigned char gpio);
void gpioSetup();

+ 2
- 0
code/espurna/gpio.ino View File

@ -6,6 +6,8 @@ Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#include "gpio.h"
#include <bitset>
constexpr const size_t GPIO_PINS = 17;


+ 19
- 0
code/espurna/homeassistant.h View File

@ -0,0 +1,19 @@
/*
HOME ASSISTANT MODULE
Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#pragma once
#if HOMEASSISTANT_SUPPORT
#include <ArduinoJson.h>
struct ha_config_t;
void haSetup();
#endif // HOMEASSISTANT_SUPPORT == 1

+ 2
- 1
code/espurna/homeassistant.ino View File

@ -10,8 +10,9 @@ Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
#include <Ticker.h>
#include <Schedule.h>
#include <ArduinoJson.h>
#include "homeassistant.h"
#include "mqtt.h"
#include "ws.h"
bool _ha_enabled = false;


+ 42
- 0
code/espurna/i2c.h View File

@ -0,0 +1,42 @@
/*
I2C MODULE
Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#pragma once
#if I2C_SUPPORT
#if I2C_USE_BRZO
#include <brzo_i2c.h>
#else
#include <Wire.h>
#endif
void i2c_wakeup(uint8_t address);
uint8_t i2c_write_buffer(uint8_t address, uint8_t * buffer, size_t len);
uint8_t i2c_write_uint8(uint8_t address, uint8_t value);
uint8_t i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value);
uint8_t i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value1, uint8_t value2);
uint8_t i2c_write_uint16(uint8_t address, uint16_t value);
uint8_t i2c_write_uint16(uint8_t address, uint8_t reg, uint16_t value);
uint8_t i2c_read_uint8(uint8_t address);
uint8_t i2c_read_uint8(uint8_t address, uint8_t reg);
uint16_t i2c_read_uint16(uint8_t address);
uint16_t i2c_read_uint16(uint8_t address, uint8_t reg);
uint16_t i2c_read_uint16_le(uint8_t address, uint8_t reg);
int16_t i2c_read_int16(uint8_t address, uint8_t reg);
int16_t i2c_read_int16_le(uint8_t address, uint8_t reg);
void i2c_read_buffer(uint8_t address, uint8_t * buffer, size_t len);
void i2cScan();
void i2cClearBus();
bool i2cGetLock(unsigned char address);
bool i2cReleaseLock(unsigned char address);
unsigned char i2cFindAndLock(size_t size, unsigned char * addresses);
#endif // I2C_SUPPORT == 1

+ 0
- 3
code/espurna/i2c.ino View File

@ -11,10 +11,7 @@ Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
unsigned int _i2c_locked[16] = {0};
#if I2C_USE_BRZO
#include "brzo_i2c.h"
unsigned long _i2c_scl_frequency = 0;
#else
#include "Wire.h"
#endif
// -----------------------------------------------------------------------------


+ 21
- 0
code/espurna/ir.h View File

@ -0,0 +1,21 @@
/*
IR MODULE
Copyright (C) 2018 by Alexander Kolesnikov (raw and MQTT implementation)
Copyright (C) 2017-2019 by François Déchery
Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#pragma once
#if IR_SUPPORT
#include <IRremoteESP8266.h>
#include <IRrecv.h>
#include <IRsend.h>
void irSetup();
#endif // IR_SUPPORT == 1

+ 2
- 8
code/espurna/ir.ino View File

@ -48,22 +48,16 @@ Raw messages:
#if IR_SUPPORT
#include "ir.h"
#include "mqtt.h"
#include "relay.h"
#include <IRremoteESP8266.h>
#if defined(IR_RX_PIN)
#include <IRrecv.h>
IRrecv _ir_receiver(IR_RX_PIN, IR_BUFFER_SIZE, IR_TIMEOUT, true);
decode_results _ir_results;
#endif // defined(IR_RX_PIN)
#if defined(IR_TX_PIN)
#include <IRsend.h>
IRsend _ir_sender(IR_TX_PIN);
#if IR_USE_RAW


+ 2
- 1
code/espurna/light.ino View File

@ -8,8 +8,9 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE
#include "tuya.h"
#include "broker.h"
#include "mqtt.h"
#include "tuya.h"
#include "ws.h"
#include "light.h"


+ 54
- 0
code/espurna/mqtt.h View File

@ -0,0 +1,54 @@
/*
MQTT MODULE
Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
Updated secure client support by Niek van der Maas < mail at niekvandermaas dot nl>
*/
#pragma once
#include <WString.h>
#include <utility>
#include <functional>
using mqtt_callback_f = std::function<void(unsigned int type, const char * topic, char * payload)>;
using mqtt_msg_t = std::pair<String, String>; // topic, payload
#if MQTT_SUPPORT
#if MQTT_LIBRARY == MQTT_LIBRARY_ASYNCMQTTCLIENT
#include <ESPAsyncTCP.h>
#include <AsyncMqttClient.h>
#elif MQTT_LIBRARY == MQTT_LIBRARY_ARDUINOMQTT
#include <MQTTClient.h>
#elif MQTT_LIBRARY == MQTT_LIBRARY_PUBSUBCLIENT
#include <PubSubClient.h>
#endif
void mqttRegister(mqtt_callback_f callback);
String mqttTopic(const char * magnitude, bool is_set);
String mqttTopic(const char * magnitude, unsigned int index, bool is_set);
String mqttMagnitude(char * topic);
bool mqttSendRaw(const char * topic, const char * message, bool retain);
bool mqttSendRaw(const char * topic, const char * message);
void mqttSend(const char * topic, const char * message, bool force, bool retain);
void mqttSend(const char * topic, const char * message, bool force);
void mqttSend(const char * topic, const char * message);
void mqttSend(const char * topic, unsigned int index, const char * message, bool force);
void mqttSend(const char * topic, unsigned int index, const char * message);
const String& mqttPayloadOnline();
const String& mqttPayloadOffline();
const char* mqttPayloadStatus(bool status);
void mqttSendStatus();
#endif // MQTT_SUPPORT == 1

+ 5
- 5
code/espurna/mqtt.ino View File

@ -9,19 +9,19 @@ Updated secure client support by Niek van der Maas < mail at niekvandermaas dot
#if MQTT_SUPPORT
#include <EEPROM_Rotate.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <ArduinoJson.h>
#include "mqtt.h"
#include <vector>
#include <utility>
#include <Ticker.h>
#include "system.h"
#include "libs/SecureClientHelpers.h"
#include "mqtt.h"
#include "ntp.h"
#include "ws.h"
#include "libs/SecureClientHelpers.h"
#if MQTT_LIBRARY == MQTT_LIBRARY_ASYNCMQTTCLIENT
AsyncMqttClient _mqtt;


+ 1
- 1
code/espurna/ntp.ino View File

@ -56,7 +56,7 @@ static time_t _ntp_ts = 0;
static tm _ntp_tm_local;
static tm _ntp_tm_utc;
static void _ntpTmCache(time_t ts) {
void _ntpTmCache(time_t ts) {
if (_ntp_ts != ts) {
_ntp_ts = ts;
localtime_r(&_ntp_ts, &_ntp_tm_local);


+ 32
- 67
code/espurna/ota.h View File

@ -1,79 +1,44 @@
/*
OTA COMMON FUNCTIONS
OTA MODULE
*/
#pragma once
#include "ws.h"
#include <Updater.h>
void otaPrintError() {
if (Update.hasError()) {
#if TERMINAL_SUPPORT
Update.printError(terminalSerial());
#elif DEBUG_SERIAL_SUPPORT && defined(DEBUG_PORT)
Update.printError(DEBUG_PORT);
#endif
}
}
bool otaFinalize(size_t size, int reason, bool evenIfRemaining = false) {
if (Update.isRunning() && Update.end(evenIfRemaining)) {
DEBUG_MSG_P(PSTR("[OTA] Success: %7u bytes\n"), size);
deferredReset(500, reason);
return true;
}
otaPrintError();
eepromRotate(true);
return false;
}
#if OTA_ARDUINOOTA_SUPPORT
#include <ArduinoOTA.h>
void arduinoOtaSetup();
#endif // OTA_ARDUINOOTA_SUPPORT == 1
#if OTA_CLIENT == OTA_CLIENT_ASYNCTCP
#include <ESPAsyncTCP.h>
void otaClientSetup();
#endif // OTA_CLIENT == OTA_CLIENT_ASYNCTCP
#if OTA_CLIENT == OTA_CLIENT_HTTPUPDATE
#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>
void otaClientSetup();
#endif // OTA_CLIENT == OTA_CLIENT_HTTPUPDATE
#if SECURE_CLIENT != SECURE_CLIENT_NONE
#include <WiFiClientSecure.h>
#endif
void otaPrintError();
bool otaFinalize(size_t size, int reason, bool evenIfRemaining = false);
// Helper methods from UpdaterClass that need to be called manually for async mode,
// because we are not using Stream interface to feed it data.
bool otaVerifyHeader(uint8_t* data, size_t len) {
if (len < 4) {
return false;
}
// ref: https://github.com/esp8266/Arduino/pull/6820
// accept gzip, let unpacker figure things out later
if (data[0] == 0x1F && data[1] == 0x8B) {
return true;
}
// Check for magic byte with a normal .bin
if (data[0] != 0xE9) {
return false;
}
// Make sure that flash config can be recognized and fit the flash
const auto flash_config = ESP.magicFlashChipSize((data[3] & 0xf0) >> 4);
if (flash_config && (flash_config > ESP.getFlashChipRealSize())) {
return false;
}
return true;
}
void otaProgress(size_t bytes, size_t each = 8192u) {
// Removed to avoid websocket ping back during upgrade (see #1574)
// TODO: implement as separate from debugging message
#if WEB_SUPPORT
if (wsConnected()) return;
#endif
// Telnet and serial will still output things, but slightly throttled
static size_t last = 0;
if (bytes < last) {
last = 0;
}
if ((bytes > each) && (bytes - each > last)) {
DEBUG_MSG_P(PSTR("[OTA] Progress: %7u bytes\r"), bytes);
last = bytes;
}
}
bool otaVerifyHeader(uint8_t* data, size_t len);
void otaProgress(size_t bytes, size_t each = 8192u);

+ 79
- 0
code/espurna/ota.ino View File

@ -0,0 +1,79 @@
/*
OTA MODULE COMMON FUNCTIONS
*/
#include "ota.h"
#include "system.h"
#include "terminal.h"
#include "ws.h"
void otaPrintError() {
if (Update.hasError()) {
#if TERMINAL_SUPPORT
Update.printError(terminalSerial());
#elif DEBUG_SERIAL_SUPPORT && defined(DEBUG_PORT)
Update.printError(DEBUG_PORT);
#endif
}
}
bool otaFinalize(size_t size, int reason, bool evenIfRemaining) {
if (Update.isRunning() && Update.end(evenIfRemaining)) {
DEBUG_MSG_P(PSTR("[OTA] Success: %7u bytes\n"), size);
deferredReset(500, reason);
return true;
}
otaPrintError();
eepromRotate(true);
return false;
}
// Helper methods from UpdaterClass that need to be called manually for async mode,
// because we are not using Stream interface to feed it data.
bool otaVerifyHeader(uint8_t* data, size_t len) {
if (len < 4) {
return false;
}
// ref: https://github.com/esp8266/Arduino/pull/6820
// accept gzip, let unpacker figure things out later
if (data[0] == 0x1F && data[1] == 0x8B) {
return true;
}
// Check for magic byte with a normal .bin
if (data[0] != 0xE9) {
return false;
}
// Make sure that flash config can be recognized and fit the flash
const auto flash_config = ESP.magicFlashChipSize((data[3] & 0xf0) >> 4);
if (flash_config && (flash_config > ESP.getFlashChipRealSize())) {
return false;
}
return true;
}
void otaProgress(size_t bytes, size_t each) {
// Removed to avoid websocket ping back during upgrade (see #1574)
// TODO: implement as separate from debugging message
#if WEB_SUPPORT
if (wsConnected()) return;
#endif
// Telnet and serial will still output things, but slightly throttled
static size_t last = 0;
if (bytes < last) {
last = 0;
}
if ((bytes > each) && (bytes - each > last)) {
DEBUG_MSG_P(PSTR("[OTA] Progress: %7u bytes\r"), bytes);
last = bytes;
}
}

+ 1
- 0
code/espurna/ota_arduinoota.ino View File

@ -8,6 +8,7 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#if OTA_ARDUINOOTA_SUPPORT
#include "ota.h"
#include "system.h"
#include "ws.h"


+ 3
- 1
code/espurna/ota_asynctcp.ino View File

@ -17,8 +17,10 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#include <Schedule.h>
#include <ESPAsyncTCP.h>
#include "system.h"
#include "mqtt.h"
#include "ota.h"
#include "system.h"
#include "terminal.h"
#include "libs/URL.h"


+ 4
- 4
code/espurna/ota_httpupdate.ino View File

@ -14,11 +14,11 @@ Copyright (C) 2019 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
#include <memory>
#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>
#include <Schedule.h>
#include "mqtt.h"
#include "ota.h"
#include "system.h"
#include "terminal.h"
#include "libs/URL.h"
#include "libs/TypeChecks.h"
#include "libs/SecureClientHelpers.h"


+ 4
- 2
code/espurna/relay.ino View File

@ -6,15 +6,17 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#include <EEPROM_Rotate.h>
#include <Ticker.h>
#include <ArduinoJson.h>
#include <vector>
#include <functional>
#include <bitset>
#include "relay.h"
#include "broker.h"
#include "storage_eeprom.h"
#include "settings.h"
#include "mqtt.h"
#include "relay.h"
#include "tuya.h"
#include "ws.h"


+ 24
- 0
code/espurna/rfbridge.h View File

@ -0,0 +1,24 @@
/*
RF BRIDGE MODULE
Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#if RF_SUPPORT
#if RFB_DIRECT
#include <RCSwitch.h>
#endif
void rfbStatus(unsigned char id, bool status);
void rfbLearn(unsigned char id, bool status);
String rfbRetrieve(unsigned char id, bool status);
void rfbStore(unsigned char id, bool status, const char * code);
void rfbForget(unsigned char id, bool status);
void rfbSetup();
#endif // RF_SUPPORT == 1

+ 3
- 4
code/espurna/rfbridge.ino View File

@ -10,11 +10,10 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#include <queue>
#if RFB_DIRECT
#include <RCSwitch.h>
#endif
#include "relay.h"
#include "rfbridge.h"
#include "terminal.h"
#include "mqtt.h"
#include "ws.h"
// -----------------------------------------------------------------------------


+ 29
- 0
code/espurna/rfm69.h View File

@ -0,0 +1,29 @@
/*
RFM69 MODULE
Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
*/
#pragma once
struct packet_t;
#if RFM69_SUPPORT
#include "libs/RFM69Wrap.h"
struct packet_t {
unsigned long messageID;
unsigned char packetID;
unsigned char senderID;
unsigned char targetID;
char * key;
char * value;
int16_t rssi;
};
void rfm69Setup();
#endif // RFM69_SUPPORT == 1

+ 2
- 1
code/espurna/rfm69.ino View File

@ -8,7 +8,8 @@ Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
#if RFM69_SUPPORT
#include "libs/RFM69Wrap.h"
#include "mqtt.h"
#include "rfm69.h"
#include "ws.h"
#define RFM69_PACKET_SEPARATOR ':'


code/espurna/config/rtcmem.h → code/espurna/rtcmem.h View File

@ -1,3 +1,11 @@
/*
RTMEM MODULE
Copyright (C) 2019 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
*/
#pragma once
// Base address of USER RTC memory
@ -16,17 +24,20 @@
// Change this when modifying RtcmemData
#define RTCMEM_MAGIC 0x45535075
// XXX When using bitfields / inner structs / etc:
// XXX: All access must be 4-byte aligned and always at full length.
//
// For example, using bitfields / inner structs / etc:
// ...
// uint32_t a : 8;
// uint32_t b : 8;
// uint32_t c : 8;
// uint32_t d : 8;
// ...
//
// This would not write the expected thing:
// mem->d = 4;
// At the same time writes 4 to the a, b and c
// TODO replace with custom memory segment in ldscript
// TODO replace with custom memory segment in ldscript?
struct RtcmemData {
uint32_t magic;
uint32_t sys;

+ 2
- 0
code/espurna/rtcmem.ino View File

@ -2,6 +2,8 @@
RTMEM MODULE
Copyright (C) 2019 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
*/
bool _rtcmem_status = false;


+ 105
- 1
code/espurna/sensor.ino View File

@ -11,12 +11,116 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#include <vector>
#include <float.h>
#include "relay.h"
#include "broker.h"
#include "mqtt.h"
#include "relay.h"
#include "terminal.h"
#include "ws.h"
//--------------------------------------------------------------------------------
PROGMEM const unsigned char magnitude_decimals[] = {
0,
1, 0, 2, // THP
3, 0, 0, 0, 0, 0, 0, 0, // Power decimals
0, 0, 0, // analog, digital, event
0, 0, 0, // PM
0, 0,
0, 0, 3, // UVA, UVB, UVI
3, 0,
4, 4, // Geiger Counter decimals
0,
0, 0, 0, 3 // NO2, CO, Ohms, pH
};
PROGMEM const char magnitude_unknown_topic[] = "unknown";
PROGMEM const char magnitude_temperature_topic[] = "temperature";
PROGMEM const char magnitude_humidity_topic[] = "humidity";
PROGMEM const char magnitude_pressure_topic[] = "pressure";
PROGMEM const char magnitude_current_topic[] = "current";
PROGMEM const char magnitude_voltage_topic[] = "voltage";
PROGMEM const char magnitude_active_power_topic[] = "power";
PROGMEM const char magnitude_apparent_power_topic[] = "apparent";
PROGMEM const char magnitude_reactive_power_topic[] = "reactive";
PROGMEM const char magnitude_power_factor_topic[] = "factor";
PROGMEM const char magnitude_energy_topic[] = "energy";
PROGMEM const char magnitude_energy_delta_topic[] = "energy_delta";
PROGMEM const char magnitude_analog_topic[] = "analog";
PROGMEM const char magnitude_digital_topic[] = "digital";
PROGMEM const char magnitude_event_topic[] = "event";
PROGMEM const char magnitude_pm1dot0_topic[] = "pm1dot0";
PROGMEM const char magnitude_pm2dot5_topic[] = "pm2dot5";
PROGMEM const char magnitude_pm10_topic[] = "pm10";
PROGMEM const char magnitude_co2_topic[] = "co2";
PROGMEM const char magnitude_lux_topic[] = "lux";
PROGMEM const char magnitude_uva_topic[] = "uva";
PROGMEM const char magnitude_uvb_topic[] = "uvb";
PROGMEM const char magnitude_uvi_topic[] = "uvi";
PROGMEM const char magnitude_distance_topic[] = "distance";
PROGMEM const char magnitude_hcho_topic[] = "hcho";
PROGMEM const char magnitude_geiger_cpm_topic[] = "ldr_cpm"; // local dose rate [Counts per minute]
PROGMEM const char magnitude_geiger_sv_topic[] = "ldr_uSvh"; // local dose rate [µSievert per hour]
PROGMEM const char magnitude_count_topic[] = "count";
PROGMEM const char magnitude_no2_topic[] = "no2";
PROGMEM const char magnitude_co_topic[] = "co";
PROGMEM const char magnitude_resistance_topic[] = "resistance";
PROGMEM const char magnitude_ph_topic[] = "ph";
PROGMEM const char* const magnitude_topics[] = {
magnitude_unknown_topic, magnitude_temperature_topic, magnitude_humidity_topic,
magnitude_pressure_topic, magnitude_current_topic, magnitude_voltage_topic,
magnitude_active_power_topic, magnitude_apparent_power_topic, magnitude_reactive_power_topic,
magnitude_power_factor_topic, magnitude_energy_topic, magnitude_energy_delta_topic,
magnitude_analog_topic, magnitude_digital_topic, magnitude_event_topic,
magnitude_pm1dot0_topic, magnitude_pm2dot5_topic, magnitude_pm10_topic,
magnitude_co2_topic, magnitude_lux_topic,
magnitude_uva_topic, magnitude_uvb_topic, magnitude_uvi_topic,
magnitude_distance_topic, magnitude_hcho_topic,
magnitude_geiger_cpm_topic, magnitude_geiger_sv_topic,
magnitude_count_topic,
magnitude_no2_topic, magnitude_co_topic, magnitude_resistance_topic, magnitude_ph_topic
};
PROGMEM const char magnitude_empty[] = "";
PROGMEM const char magnitude_celsius[] = "°C";
PROGMEM const char magnitude_fahrenheit[] = "°F";
PROGMEM const char magnitude_percentage[] = "%";
PROGMEM const char magnitude_hectopascals[] = "hPa";
PROGMEM const char magnitude_amperes[] = "A";
PROGMEM const char magnitude_volts[] = "V";
PROGMEM const char magnitude_watts[] = "W";
PROGMEM const char magnitude_kw[] = "kW";
PROGMEM const char magnitude_joules[] = "J";
PROGMEM const char magnitude_kwh[] = "kWh";
PROGMEM const char magnitude_ugm3[] = "µg/m³";
PROGMEM const char magnitude_ppm[] = "ppm";
PROGMEM const char magnitude_lux[] = "lux";
PROGMEM const char magnitude_distance[] = "m";
PROGMEM const char magnitude_mgm3[] = "mg/m³";
PROGMEM const char magnitude_geiger_cpm[] = "cpm"; // Counts per Minute: Unit of local dose rate (Geiger counting)
PROGMEM const char magnitude_geiger_sv[] = "µSv/h"; // µSievert per hour: 2nd unit of local dose rate (Geiger counting)
PROGMEM const char magnitude_resistance[] = "ohm";
PROGMEM const char* const magnitude_units[] = {
magnitude_empty, magnitude_celsius, magnitude_percentage,
magnitude_hectopascals, magnitude_amperes, magnitude_volts,
magnitude_watts, magnitude_watts, magnitude_watts,
magnitude_percentage, magnitude_joules, magnitude_joules,
magnitude_empty, magnitude_empty, magnitude_empty,
magnitude_ugm3, magnitude_ugm3, magnitude_ugm3,
magnitude_ppm, magnitude_lux,
magnitude_empty, magnitude_empty, magnitude_empty,
magnitude_distance, magnitude_mgm3,
magnitude_geiger_cpm, magnitude_geiger_sv, // Geiger counter units
magnitude_empty, //
magnitude_ppm, magnitude_ppm, // NO2 & CO2
magnitude_resistance,
magnitude_empty // pH
};
//--------------------------------------------------------------------------------
#include "filters/LastFilter.h"
#include "filters/MaxFilter.h"
#include "filters/MedianFilter.h"


+ 2
- 0
code/espurna/settings.ino View File

@ -10,6 +10,8 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#include <ArduinoJson.h>
#include "storage_eeprom.h"
#include "settings_internal.h"
#include "settings.h"


+ 24
- 0
code/espurna/storage_eeprom.h View File

@ -0,0 +1,24 @@
/*
EEPROM MODULE
*/
// XXX: with case insensitive filesystem, if named eeprom.h *could*
// be included as EEPROM.h and fail after including rotate library down below
#pragma once
#include <EEPROM_Rotate.h>
extern EEPROM_Rotate EEPROMr;
void eepromSectorsDebug();
void eepromRotate(bool value);
uint32_t eepromCurrent();
String eepromSectors();
void eepromBackup(uint32_t index);
void eepromCommit();
void eepromSetup();

code/espurna/eeprom.ino → code/espurna/storage_eeprom.ino View File

@ -4,10 +4,10 @@ EEPROM MODULE
*/
#include <EEPROM_Rotate.h>
// -----------------------------------------------------------------------------
#include "debug.h"
#include "storage_eeprom.h"
EEPROM_Rotate EEPROMr;
bool _eeprom_commit = false;
uint32_t _eeprom_commit_count = 0;

+ 8
- 0
code/espurna/system.h View File

@ -8,8 +8,16 @@ Copyright (C) 2019 by Xose Pérez <xose dot perez at gmail dot com>
#pragma once
#include <Ticker.h>
#include <Schedule.h>
#include <cstdint>
extern "C" {
#include "user_interface.h"
extern struct rst_info resetInfo;
}
uint32_t systemResetReason();
uint8_t systemStabilityCounter();
void systemStabilityCounter(uint8_t count);


+ 21
- 0
code/espurna/terminal.h View File

@ -0,0 +1,21 @@
/*
TERMINAL MODULE
Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#pragma once
#if TERMINAL_SUPPORT
#include "libs/EmbedisWrap.h"
using embedis_command_f = void (*)(Embedis*);
void terminalRegisterCommand(const String& name, embedis_command_f func);
void terminalInject(void *data, size_t len);
Stream& terminalSerial();
#endif // TERMINAL_SUPPORT == 1

+ 1
- 0
code/espurna/terminal.ino View File

@ -10,6 +10,7 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#include "settings.h"
#include "system.h"
#include "terminal.h"
#include "utils.h"
#include "libs/StreamInjector.h"
#include "libs/HeapStats.h"


+ 19
- 0
code/espurna/thermostat.h View File

@ -0,0 +1,19 @@
/*
THERMOSTAT MODULE
Copyright (C) 2017 by Dmitry Blinov <dblinov76 at gmail dot com>
*/
#pragma once
#include <ArduinoJson.h>
#include <float.h>
#if THERMOSTAT_DISPLAY_SUPPORT
#include <SSD1306.h> // alias for `#include "SSD1306Wire.h"`
#endif
using thermostat_callback_f = std::function<void(bool state)>;
void thermostatRegister(thermostat_callback_f callback);

+ 2
- 4
code/espurna/thermostat.ino View File

@ -8,11 +8,11 @@ Copyright (C) 2017 by Dmitry Blinov <dblinov76 at gmail dot com>
#if THERMOSTAT_SUPPORT
#include <ArduinoJson.h>
#include <float.h>
#include "relay.h"
#include "ntp.h"
#include "relay.h"
#include "thermostat.h"
#include "ws.h"
@ -603,8 +603,6 @@ void resetBurnCounters() {
#if THERMOSTAT_DISPLAY_SUPPORT
#include "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
#define wifi_on_width 16
#define wifi_on_height 16
const char wifi_on_bits[] PROGMEM = {


+ 120
- 0
code/espurna/timelibshim.h View File

@ -0,0 +1,120 @@
// Shim original TimeLib functions
#pragma once
constexpr time_t daysPerWeek = 7;
constexpr time_t secondsPerMinute = 60;
constexpr time_t secondsPerHour = 3600;
constexpr time_t secondsPerDay = secondsPerHour * 24;
constexpr time_t secondsPerWeek = daysPerWeek * secondsPerDay;
constexpr time_t secondsPerYear = secondsPerWeek * 52;
constexpr time_t secondsY2K = 946684800; // the time at the start of y2k
// wall clock values
constexpr const time_t numberOfSeconds(uint32_t ts) {
return (ts % secondsPerMinute);
}
constexpr const time_t numberOfMinutes(uint32_t ts) {
return ((ts / secondsPerMinute) % secondsPerMinute);
}
constexpr const time_t numberOfHours(uint32_t ts) {
return ((ts % secondsPerDay) / secondsPerHour);
}
// week starts with sunday as number 1, monday as 2 etc.
constexpr const time_t dayOfWeek(time_t ts) {
return ((ts / secondsPerDay + 4) % daysPerWeek) + 1;
}
// the number of days since 0 (Jan 1 1970 in case of time_t values)
constexpr const time_t elapsedDays(uint32_t ts) {
return (ts / secondsPerDay);
}
// the number of seconds since last midnight
constexpr const time_t elapsedSecsToday(uint32_t ts) {
return (ts % secondsPerDay);
}
// The following methods are used in calculating alarms and assume the clock is set to a date later than Jan 1 1971
// Always set the correct time before settting alarms
// time at the start of the given day
constexpr const time_t previousMidnight(time_t ts) {
return ((ts / secondsPerDay) * secondsPerDay);
}
// time at the end of the given day
constexpr const time_t nextMidnight(time_t ts) {
return previousMidnight(ts) + secondsPerDay;
}
// note that week starts on day 1
constexpr const time_t elapsedSecsThisWeek(uint32_t ts) {
return elapsedSecsToday(ts) + ((dayOfWeek(ts) - 1) * secondsPerDay);
}
// time at the start of the week for the given time
constexpr const time_t previousSunday(time_t ts) {
return ts - elapsedSecsThisWeek(ts);
}
// time at the end of the week for the given time
constexpr const time_t nextSunday(time_t ts) {
return previousSunday(ts) + secondsPerWeek;
}
year(t), month(t), day(t), hour(t), minute(t), second(t)
static time_t _ntp_ts = 0;
static tm _ntp_tm;
void _ntpTmCache(time_t ts) {
if (_ntp_tm != ts) {
_ntp_ts = ts;
localtime_r(_ntp_ts, _ntp_tm);
}
}
int hour(time_t ts) {
_ntpTmCache(ts);
return _ntp_tm.tm_hour;
}
int minute(time_t ts) {
_ntpTmCache(ts);
return _ntp_tm.tm_min;
}
int second(time_t ts) {
_ntpTmCache(ts);
return _ntp_tm.tm_sec;
}
int day(time_t ts) {
_ntpTmCache(ts);
return _ntp_tm.tm_day;
}
int weekday(time_t ts) {
_ntpTmCache(ts);
return _ntp_tm.tm_wday;
}
int month(time_t ts) {
_ntpTmCache(ts);
return _ntp_tm.tm_mon;
}
int year(time_t ts) {
_ntpTmCache(ts);
return _ntp_tm.tm_year;
}
time_t now() {
return time(nullptr);
}

+ 18
- 0
code/espurna/uartmqtt.h View File

@ -0,0 +1,18 @@
/*
UART_MQTT MODULE
Copyright (C) 2018 by Albert Weterings
Adapted by Xose Pérez <xose dot perez at gmail dot com>
*/
#pragma once
#if UART_MQTT_SUPPORT
#include <SoftwareSerial.h>
void uartmqttSetup();
#endif // UART_MQTT_SUPPORT == 1

+ 3
- 1
code/espurna/uartmqtt.ino View File

@ -9,11 +9,13 @@ Adapted by Xose Pérez <xose dot perez at gmail dot com>
#if UART_MQTT_SUPPORT
#include "mqtt.h"
#include "uartmqtt.h"
char _uartmqttBuffer[UART_MQTT_BUFFER_SIZE];
bool _uartmqttNewData = false;
#if UART_MQTT_USE_SOFT
#include <SoftwareSerial.h>
SoftwareSerial _uart_mqtt_serial(UART_MQTT_RX_PIN, UART_MQTT_TX_PIN, false, UART_MQTT_BUFFER_SIZE);
#define UART_MQTT_PORT _uart_mqtt_serial
#else


+ 2
- 0
code/espurna/utils.h View File

@ -8,6 +8,8 @@ Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
#pragma once
PROGMEM const char pstr_unknown[] = "UNKNOWN";
#define INLINE inline __attribute__((always_inline))
extern "C" uint32_t _SPIFFS_start;


+ 26
- 1
code/espurna/utils.ino View File

@ -9,10 +9,35 @@ Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
#include <limits>
#include "config/buildtime.h"
#include "libs/HeapStats.h"
#include "mqtt.h"
#include "ntp.h"
#include "utils.h"
#include "libs/HeapStats.h"
//--------------------------------------------------------------------------------
// Reset reasons
//--------------------------------------------------------------------------------
PROGMEM const char custom_reset_hardware[] = "Hardware button";
PROGMEM const char custom_reset_web[] = "Reboot from web interface";
PROGMEM const char custom_reset_terminal[] = "Reboot from terminal";
PROGMEM const char custom_reset_mqtt[] = "Reboot from MQTT";
PROGMEM const char custom_reset_rpc[] = "Reboot from RPC";
PROGMEM const char custom_reset_ota[] = "Reboot after successful OTA update";
PROGMEM const char custom_reset_http[] = "Reboot from HTTP";
PROGMEM const char custom_reset_nofuss[] = "Reboot after successful NoFUSS update";
PROGMEM const char custom_reset_upgrade[] = "Reboot after successful web update";
PROGMEM const char custom_reset_factory[] = "Factory reset";
PROGMEM const char* const custom_reset_string[] = {
custom_reset_hardware, custom_reset_web, custom_reset_terminal,
custom_reset_mqtt, custom_reset_rpc, custom_reset_ota,
custom_reset_http, custom_reset_nofuss, custom_reset_upgrade,
custom_reset_factory
};
void setDefaultHostname() {
if (strlen(HOSTNAME) > 0) {
setSetting("hostname", HOSTNAME);


+ 41
- 0
code/espurna/web.h View File

@ -0,0 +1,41 @@
/*
WEBSERVER MODULE
Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#pragma once
#include <functional>
#if WEB_SUPPORT
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <Hash.h>
#include <FS.h>
#include <AsyncJson.h>
#include <ArduinoJson.h>
#else
// TODO: need these prototypes for .ino
class AsyncClient;
class AsyncWebServer;
class AsyncWebServerRequest;
class ArRequestHandlerFunction;
class AsyncWebSocketClient;
class AsyncWebSocket;
class AwsEventType;
#endif // WEB_SUPPORT == 1
using web_body_callback_f = std::function<bool(AsyncWebServerRequest*, uint8_t* data, size_t len, size_t index, size_t total)>;
using web_request_callback_f = std::function<bool(AsyncWebServerRequest*)>;
AsyncWebServer* webServer();
void webBodyRegister(web_body_callback_f);
void webRequestRegister(web_request_callback_f);

+ 2
- 8
code/espurna/web.ino View File

@ -8,16 +8,10 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#if WEB_SUPPORT
#include "ota.h"
#include "system.h"
#include "utils.h"
#include "ota.h"
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <Hash.h>
#include <FS.h>
#include <AsyncJson.h>
#include <ArduinoJson.h>
#include "web.h"
#if WEB_EMBEDDED


+ 36
- 0
code/espurna/wifi.h View File

@ -6,6 +6,42 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#pragma once
#define LWIP_INTERNAL
#include <ESP8266WiFi.h>
#undef LWIP_INTERNAL
extern "C" {
#include <lwip/opt.h>
#include <lwip/ip.h>
#include <lwip/tcp.h>
#include <lwip/inet.h> // ip_addr_t
#include <lwip/err.h> // ERR_x
#include <lwip/dns.h> // dns_gethostbyname
#include <lwip/ip_addr.h> // ip4/ip6 helpers
#include <lwip/init.h> // LWIP_VERSION_MAJOR
};
#if LWIP_VERSION_MAJOR == 1
#include <netif/etharp.h>
#else // LWIP_VERSION_MAJOR >= 2
#include <lwip/etharp.h>
#endif
#include <JustWifi.h>
// ref: https://github.com/me-no-dev/ESPAsyncTCP/pull/115/files#diff-e2e636049095cc1ff920c1bfabf6dcacR8
// This is missing with Core 2.3.0 and is sometimes missing from the build flags. Assume HIGH_BANDWIDTH version.
#ifndef TCP_MSS
#define TCP_MSS (1460)
#endif
struct wifi_scan_info_t;
using wifi_scan_f = std::function<void(wifi_scan_info_t& info)>;
using wifi_callback_f = std::function<void(justwifi_messages_t code, char * parameter)>;
uint8_t wifiState();
void wifiReconnectCheck();
bool wifiConnected();


+ 1
- 0
code/espurna/ws.h View File

@ -14,6 +14,7 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#include <functional>
#include <vector>
#include "web.h"
#include "utils.h"
using ws_on_send_callback_f = std::function<void(JsonObject& root)>;


+ 2
- 4
code/espurna/ws.ino View File

@ -8,15 +8,13 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#if WEB_SUPPORT
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include <Ticker.h>
#include <vector>
#include "system.h"
#include "web.h"
#include "ws.h"
#include "ws_internal.h"
#include "libs/WebSocketIncommingBuffer.h"
AsyncWebSocket _ws("/ws");


Loading…
Cancel
Save