build: clean up the mess of ifdefs from platform into a scons-configured hal

This commit is contained in:
Torrie Fischer 2023-12-20 10:47:26 +01:00
parent 236795917a
commit 23993a09cf
21 changed files with 376 additions and 410 deletions

9
build-hal.py Normal file
View File

@ -0,0 +1,9 @@
Import("env")
board = env.get("BOARD_MCU")
frameworks = env.get("PIOFRAMEWORK")
print(f"HAL configuration:")
for framework in frameworks:
env.Append(SRC_FILTER=[f"+<platform/{framework}/{board}/*>"])
env.Append(SRC_FILTER=[f"+<platform/{framework}/*.cpp>"])
print(f"- platform/{framework}{board}")

View File

@ -71,7 +71,7 @@ MainLoop::loop()
Task* slowestTask = NULL;
for(Task* task : scheduler) {
//unsigned int start = millis();
#if defined(BOARD_ESP32) or defined(BOARD_ESP8266)
#if defined(ESP32) or defined(ESP8266)
unsigned int start = ESP.getCycleCount();
#else
unsigned int start = millis();
@ -79,7 +79,7 @@ MainLoop::loop()
Log.verbose("Running %s", task->name);
s_lastTaskName = task->name;
task->loop();
#if defined(BOARD_ESP32) or defined(BOARD_ESP8266)
#if defined(ESP32) or defined(ESP8266)
unsigned int runtime = (ESP.getCycleCount() - start) / 160000;
#else
unsigned int runtime = millis() - start;

View File

@ -8,20 +8,24 @@
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env]
extra_scripts = pre:verify-configs.py, pre:build-hal.py
[common_env_data]
src_filter = "+<*> -<.git/> -<.svn/> -<platform/> -<inputs/> +<inputs/BPM.cpp> +<inputs/Serial.cpp> +<inputs/CircadianRhythm.cpp>"
src_filter = +<*>, -<.git/>, -<.svn/>, -<platform/>
lib_ldf_mode = chain+
extra_scripts = verify-configs.py
src_build_flags =
-DRENDERBUG_VERSION=3
-DRENDERBUG_LED_PIN=14
-DRENDERBUG_LED_PACKING=RGB
-DDEFAULT_PATTERN_INDEX=0
-fstack-protector
-Wall
lib_deps_external =
fastled/FastLED@^3.5.0
thijse/ArduinoLog@^1.1.0
bblanchon/ArduinoJson@^6.17.3
JsonStreamingParser
LittleFS
[config_u8display]
@ -31,32 +35,10 @@ lib_deps =
olikraus/U8g2@^2.34.15
src_filter = "+<platform/arduino/U8Display.cpp>"
[config_mqtt]
src_build_flags =
-DCONFIG_MQTT
lib_deps =
knolleary/PubSubClient@^2.8.0
src_filter = "+<platform/arduino/MQTTTelemetry.cpp>"
[config_wifi]
src_build_flags =
-DCONFIG_WIFI
src_filter = "+<platform/arduino/WiFiTask.cpp>"
[config_bluetooth]
src_build_flags =
-DCONFIG_BLUETOOTH
src_filter = "+<platform/arduino/BluetoothSerialTelemetry.cpp>"
lib_deps =
BluetoothSerial
[config_ota]
src_build_flags =
-DCONFIG_OTA
src_filter = "+<platform/arduino/OTA.cpp>"
lib_deps =
ArduinoOTA
ESP8266mDNS
[config_nocolor]
src_build_flags =
@ -72,28 +54,8 @@ src_build_flags =
-DCONFIG_MPU5060
src_filter = "+<inputs/MPU6050.cpp>"
[env:bike]
extends = env:esp32, config_u8display
src_filter = "${env:esp32.src_filter} ${config_u8display.src_filter}"
lib_deps =
${env:esp32.lib_deps}
${config_u8display.lib_deps}
src_build_flags =
${env:esp32.src_build_flags}
${config_u8display.src_build_flags}
build_type = debug
[env:bike_ble]
extends = env:bike
lib_deps =
${env:bike.lib_deps}
nkolban/ESP32 BLE Arduino@1.0.1
src_build_flags =
${env:bike.src_build_flags}
[env:esp32]
extends = config_nocolor
extra_scripts = verify-configs.py
board_build.filesystem = littlefs
platform = espressif32
board = featheresp32
@ -103,11 +65,13 @@ check_flags =
src_build_flags =
${common_env_data.src_build_flags}
${config_nocolor.src_build_flags}
-DPLATFORM_ARDUINO
-DBOARD_ESP32
-DCONFIG_THREADED_INPUTS
-DRENDERBUG_LED_PIN=14
lib_deps =
${common_env_data.lib_deps_external}
BluetoothSerial
knolleary/PubSubClient@^2.8.0
src_filter = "${common_env_data.src_filter}"
monitor_filters = esp32_exception_decoder
monitor_speed = 115200
@ -131,43 +95,19 @@ platform = espressif8266
board = huzzah
framework = arduino
board_build.filesystem = littlefs
monitor_filters = esp8266_exception_decoder
src_build_flags =
${common_env_data.src_build_flags}
-DPLATFORM_ARDUINO
-DBOARD_ESP8266
-DCORE_DEBUG_LEVEL=5
-fstack-protector
lib_deps =
${common_env_data.lib_deps_external}
knolleary/PubSubClient@^2.8.0
arduino-libraries/NTPClient@^3.1.0
ESP8266WiFi
ESP8266mDNS
ArduinoOTA
src_filter = "${common_env_data.src_filter}"
[env:esp32_bluetooth]
extends = env:esp32, config_bluetooth
src_filter = "${env:esp32.src_filter} ${config_mqtt.src_filter} ${config_wifi.src_filter} ${config_bluetooth.src_filter}"
lib_deps =
${env:esp32.lib_deps}
${config_bluetooth.lib_deps}
${config_mqtt.lib_deps}
src_build_flags =
${env:esp32.src_build_flags}
${config_bluetooth.src_build_flags}
${config_wifi.src_build_flags}
-DRENDERBUG_LED_PIN=14
[env:esp32_wifi]
extends = env:esp32, config_wifi, config_mqtt
src_filter = "${env:esp32.src_filter} ${config_wifi.src_filter} ${config_mqtt.src_filter}"
buid_type = debug
lib_deps =
${env:esp32.lib_deps}
${config_mqtt.lib_deps}
src_build_flags =
${env:esp32.src_build_flags}
${config_mqtt.src_build_flags}
${config_wifi.src_build_flags}
-DRENDERBUG_LED_PIN=14
[env:esp32_display]
extends = env:esp32, config_u8display
src_filter = "${env:esp32.src_filter} ${config_u8display.src_filter}"
@ -179,46 +119,3 @@ src_build_flags =
${env:esp32.src_build_flags}
${config_u8display.src_build_flags}
-DRENDERBUG_LED_PIN=14
[env:esp32_wifi_display]
extends = env:esp32, config_wifi, config_mqtt, config_u8display
src_filter = "${env:esp32.src_filter} ${config_wifi.src_filter} ${config_mqtt.src_filter} ${config_u8display.src_filter}"
build_type = debug
lib_deps =
${env:esp32.lib_deps}
${config_mqtt.lib_deps}
${config_u8display.lib_deps}
src_build_flags =
${env:esp32.src_build_flags}
${config_mqtt.src_build_flags}
${config_wifi.src_build_flags}
${config_u8display.src_build_flags}
-DRENDERBUG_LED_PIN=14
[env:prototype]
extends = env:esp32, config_buttons, config_mpu5060
src_filter = "${env:esp32.src_filter} ${config_buttons.src_filter} ${config_mpu5060.src_filter}"
[env:esp8266_wifi]
extends = env:esp8266, config_wifi, config_mqtt, config_ota
src_filter = "${env:esp32.src_filter} ${config_ota.src_filter} ${config_wifi.src_filter} ${config_mqtt.src_filter}"
src_build_flags =
${env:esp8266.src_build_flags}
${config_mqtt.src_build_flags}
${config_wifi.src_build_flags}
${config_ota.src_build_flags}
lib_deps =
${env:esp8266.lib_deps}
${config_mqtt.lib_deps}
ESP8266WiFi
${config_ota.lib_deps}
#[env:home_lighting_grb]
#extends = env:esp8266_wifi config_u8display
#src_build_flags =
# ${env:home_lighting.src_build_flags}
# -DRENDERBUG_LED_PACKING=GRB
#[env:home_lighting-12f]
#extends = env:esp8266_wifi config_u8display
#board = esp12e

View File

@ -3,10 +3,6 @@
#include <EEPROM.h>
#ifdef BOARD_ESP8266
#include <ESP8266WiFi.h>
#endif
#ifdef PLATFORM_PHOTON
LEDStatus serialStatus = LEDStatus(RGB_COLOR_ORANGE, LED_PATTERN_FADE, LED_SPEED_FAST, LED_PRIORITY_BACKGROUND);
LEDStatus configStatus = LEDStatus(RGB_COLOR_YELLOW, LED_PATTERN_FADE, LED_SPEED_NORMAL, LED_PRIORITY_IMPORTANT);
@ -14,21 +10,6 @@ retained bool LAST_BOOT_WAS_FLASH;
retained bool LAST_BOOT_WAS_SERIAL;
#endif
#ifndef __NOINIT_ATTR // Pre-defined on esp32
#define __NOINIT_ATTR __attribute__ ((section (".noinit")))
#endif
#define SAFE_MODE_MAGIC 6942
__NOINIT_ATTR uint8_t s_rebootCount;
__NOINIT_ATTR uint16_t s_forceSafeMode;
void
BootOptions::forceSafeMode()
{
s_forceSafeMode = SAFE_MODE_MAGIC;
}
void
BootOptions::initPins()
{
@ -53,40 +34,7 @@ BootOptions::BootOptions()
configStatus.setActive(isSetup);
serialStatus.setActive(isSerial);
#endif
#ifdef BOARD_ESP32
resetReason = esp_reset_reason();
crashCount = s_rebootCount;
if (resetReason >= 4) { // TODO: These values are defined in
// esp32/rom/rtc.h, but not sure if that's included
// on platformio builds
if (crashCount++ >= 3) {
// Boot into safe mode if the watchdog reset us three times in a row.
isSafeMode = true;
}
} else {
crashCount = 0;
}
s_rebootCount = crashCount;
#endif
#ifdef BOARD_ESP8266
struct rst_info resetInfo = *ESP.getResetInfoPtr();
resetReason = resetInfo.reason;
crashCount = s_rebootCount;
if (resetInfo.reason == REASON_SOFT_WDT_RST || resetInfo.reason == REASON_WDT_RST || resetInfo.reason == REASON_EXCEPTION_RST) {
if (crashCount++ >= 3) {
// Boot into safe mode if the watchdog reset us three times in a row.
isSafeMode = true;
}
} else {
crashCount = 0;
}
s_rebootCount = crashCount;
if (resetInfo.reason > 0 && s_forceSafeMode == SAFE_MODE_MAGIC) {
isSafeMode = true;
s_forceSafeMode = 0;
}
#endif
PlatformImpl<>::initBootOptions(*this);
}
void

View File

@ -1,5 +1,6 @@
#pragma once
#include <Arduino.h>
#include "Hal.h"
struct BootOptions {
static void initPins();
@ -7,7 +8,6 @@ struct BootOptions {
BootOptions();
void waitForRelease();
void forceSafeMode();
bool isSetup = false;
bool isSerial = false;

View File

@ -6,10 +6,10 @@ filename_iterator::filename_iterator()
{}
filename_iterator::filename_iterator(const char* path, const char* suffix)
#ifdef BOARD_ESP8266
#ifdef ESP8266
: dir(LittleFS.openDir(path)),
#endif
#ifdef BOARD_ESP32
#ifdef ESP32
: dir(LittleFS.open(path)),
#endif
valid(true),
@ -26,7 +26,7 @@ filename_iterator::next()
}
int extPos = -1;
do {
#ifdef BOARD_ESP8266
#ifdef ESP8266
valid = dir.next();
if (valid) {
String fname = dir.fileName();
@ -36,7 +36,7 @@ filename_iterator::next()
}
}
#endif
#ifdef BOARD_ESP32
#ifdef ESP32
File next = dir.openNextFile();
valid = (bool)next;
if (valid && !next.isDirectory()) {

View File

@ -24,10 +24,10 @@ struct filename_iterator: public std::iterator<std::input_iterator_tag, const ch
bool valid;
const char* suffix;
#ifdef BOARD_ESP8266
#ifdef ESP8266
Dir dir;
#endif
#ifdef BOARD_ESP32
#ifdef ESP32
File dir;
#endif
};

30
src/Hal.h Normal file
View File

@ -0,0 +1,30 @@
#pragma once
struct BootOptions;
typedef enum {
HAL_UNKNOWN,
HAL_ESP32,
HAL_ESP8266
} HalBackend;
constexpr HalBackend DefaultBackend = HAL_ESP8266;
template<HalBackend Backend = DefaultBackend>
class PlatformImpl {
public:
static const char* name();
static const char* version();
static int freeRam();
static void startWatchdog();
static void startNTP();
static bool getLocalTime(struct tm* timedata, int timezone);
static void loop();
static const char* deviceID();
__attribute__((noreturn)) static void restart();
static void bootSplash();
static void printCrashInfo();
static void initBootOptions(BootOptions& opts);
static void forceSafeMode();
};

View File

@ -3,40 +3,16 @@
#include "Static.h"
#include <time.h>
#ifdef BOARD_ESP32
#ifdef CONFIG_WIFI
#include <WiFi.h>
#endif
#include <esp_task_wdt.h>
#elif defined(BOARD_ESP8266)
#ifdef CONFIG_WIFI
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <ctime>
WiFiUDP wifiUdp;
NTPClient timeClient(wifiUdp, "pool.ntp.org", 3600 * -7);
#endif
#endif
#ifdef PLATFORM_PHOTON
STARTUP(BootOptions::initPins());
#else
#include "inputs/Serial.h"
#ifdef CONFIG_MQTT
#include "platform/arduino/MQTTTelemetry.h"
#endif
void printNewline(Print* logOutput, int logLevel)
{
(void)logLevel; // unused
logOutput->print("\n");
}
int printEspLog(const char* fmt, va_list args)
{
Log.notice(fmt, args);
return 1;
}
#endif
int Platform::s_timezone = 0;
@ -46,24 +22,18 @@ Platform::TaskRegistration* Platform::lastTask = NULL;
const char*
Platform::name()
{
return PlatformImpl<>::name();
#ifdef PLATFORM_PHOTON
return "Photon";
#elif defined(BOARD_ESP8266)
return "ESP8266";
#elif defined(BOARD_ESP32)
return "ESP32";
#else
return "Unknown!";
#endif
}
const char*
Platform::version()
{
return PlatformImpl<>::version();
#ifdef PLATFORM_PHOTON
return System.version().c_str();
#elif defined(BOARD_ESP32) || defined(BOARD_ESP8266)
return ESP.getSdkVersion();
#else
return "Unknown!";
#endif
@ -72,9 +42,7 @@ Platform::version()
int
Platform::freeRam()
{
#if defined(BOARD_ESP8266) || defined(BOARD_ESP32)
return ESP.getFreeHeap();
#endif
return PlatformImpl<>::freeRam();
}
void
@ -94,26 +62,17 @@ Platform::preSetup()
Log.notice("\xf0\x9f\x94\x8c Serial connected");
}
#else
#ifdef CONFIG_MQTT
Log.begin(LOG_LEVEL_TRACE, Static<MQTTTelemetry>::instance()->logPrinter());
Static<MQTTTelemetry>::instance()->setSequencer(Static<Sequencer>::instance());
#else
Log.begin(LOG_LEVEL_TRACE, Static<SerialInput>::instance()->logPrinter());
#endif
Log.setSuffix(printNewline);
#endif
#ifdef BOARD_ESP32
esp_task_wdt_init(10, true);
esp_task_wdt_add(NULL);
esp_log_set_vprintf(printEspLog);
#endif
#ifdef BOARD_ESP8266
ESP.wdtEnable(0);
if (!ESP.checkFlashCRC()) {
Log.fatal("Firmware failed CRC check!!!");
}
#endif
PlatformImpl<>::startWatchdog();
}
void
@ -121,19 +80,15 @@ Platform::setup()
{
#ifdef PLATFORM_PHOTON
Time.zone(Static<Platform>::instance()->getTimezone());
#elif defined(BOARD_ESP32)
constexpr int dst = 1;
configTime(s_timezone* 3600, 3600 * dst, "pool.ntp.org");
#elif defined(BOARD_ESP8266)
#ifdef CONFIG_WIFI
timeClient.begin();
#endif
#endif
PlatformImpl<>::startNTP();
}
void
Platform::bootSplash()
{
PlatformImpl<>::bootSplash();
#ifdef PLATFORM_PHOTON
Log.notice(u8" Boot pin configuration:");
Log.notice(u8" 2: Setup - %d", bootopts.isSetup);
@ -148,14 +103,7 @@ Platform::bootSplash()
lastTaskBuf[15] = 0;
Log.error(u8"Crash occurred in task %s", lastTaskBuf);
#ifdef BOARD_ESP8266
auto rInfo = ESP.getResetInfoPtr();
if (Platform::bootopts.resetReason == REASON_EXCEPTION_RST) {
Log.error("Fatal exception (%d):", rInfo->exccause);
}
Log.error("epc1=%X, epc2=%X, epc3=%X, excvaddr=%X, depc=%X",
rInfo->epc1, rInfo->epc2, rInfo->epc3, rInfo->excvaddr, rInfo->depc);
#endif
PlatformImpl<>::printCrashInfo();
strncpy(lastTaskBuf, Renderer::lastFigmentName(), sizeof(lastTaskBuf));
lastTaskBuf[15] = 0;
@ -164,7 +112,6 @@ Platform::bootSplash()
Log.trace("Startup reason: %d", bootopts.resetReason);
Log.trace("Registered tasks:");
auto it = beginTasks();
while (it != endTasks()) {
@ -180,16 +127,7 @@ Platform::bootSplash()
void
Platform::loop()
{
#ifdef BOARD_ESP8266
#ifdef CONFIG_WIFI
if (WiFi.status() == WL_CONNECTED) {
timeClient.update();
}
#endif
ESP.wdtFeed();
#elif defined(BOARD_ESP32)
esp_task_wdt_reset();
#endif
PlatformImpl<>::loop();
}
bool
@ -202,40 +140,19 @@ Platform::getLocalTime(struct tm* timedata)
return true;
}
return false;
#elif defined(BOARD_ESP32)
time_t rawtime;
memset(&rawtime, 0, sizeof(rawtime));
time(&rawtime);
(*timedata) = (*localtime(&rawtime));
return (timedata->tm_year > (2016-1990));
#else
#ifdef CONFIG_WIFI
timedata->tm_hour = timeClient.getHours();
timedata->tm_min = timeClient.getMinutes();
#else
memset(timedata, sizeof(struct tm), 0);
return false;
#endif
return true;
#endif
return PlatformImpl<>::getLocalTime(timedata, s_timezone);
}
const char*
Platform::deviceID()
{
uint64_t chipid;
#ifdef BOARD_ESP32
chipid = ESP.getEfuseMac();
#elif defined(BOARD_ESP8266)
chipid = ESP.getChipId();
#endif
snprintf(s_deviceID, sizeof(s_deviceID), "%08X", (uint32_t)chipid);
return s_deviceID;
return PlatformImpl<>::deviceID();
}
void
Platform::addLEDs(CRGB* leds, uint16_t ledCount) {
FastLED.addLeds<WS2812, RENDERBUG_LED_PIN, RENDERBUG_LED_PACKING>(leds, ledCount);
FastLED.addLeds<NEOPIXEL, RENDERBUG_LED_PIN>(leds, ledCount);
}
const String
@ -247,12 +164,7 @@ Platform::model()
void
Platform::restart() {
#ifdef BOARD_ESP8266
ESP.wdtDisable();
ESP.restart();
#elif defined(BOARD_ESP32)
ESP.restart();
#endif
PlatformImpl<>::restart();
}
@ -260,15 +172,15 @@ void
Platform::doReboot(Args& args, Print& out)
{
out.println("Rebooting");
Platform::restart();
restart();
}
void
Platform::doSafeMode(Args& args, Print& out)
{
out.println("Rebooting into safe mode");
Platform::bootopts.forceSafeMode();
Platform::restart();
PlatformImpl<>::forceSafeMode();
restart();
}
String s;

View File

@ -2,6 +2,7 @@
#include <FastLED.h>
#include <Figments.h>
#include "BootOptions.h"
#include "Hal.h"
class Platform : public Task {
static int s_timezone;

View File

@ -1,5 +0,0 @@
#include "./ConfigInput.h"
#include "./Static.h"
STATIC_ALLOC(ConfigInput);
STATIC_TASK(ConfigInput);

View File

@ -1,77 +0,0 @@
#pragma once
#include <Figments.h>
class ConfigInputTask : public BufferedInputSource {
public:
ConfigInputTask() : BufferedInputSource("ConfigInput") {}
void handleEvent(const InputEvent& evt) override {
if (evt.intent == InputEvent::UserInput) {
Buttons::Chord chord = (Buttons::Chord) evt.asInt();
switch (chord) {
case Buttons::Circle:
m_currentIntent = nextIntent();
//Log.info("Next setting... (%d)", m_currentIntent);
break;
case Buttons::CircleTriangle:
//Log.info("Increment...");
increment();
break;
case Buttons::CircleCross:
//Log.info("Decrement...");
decrement();
break;
case Buttons::Triangle:
//Log.info("Save...");
setEvent(InputEvent::SaveConfigurationRequest);
break;
default:
break;
}
}
}
private:
InputEvent::Intent m_currentIntent = InputEvent::SetDisplayLength;
void decrement() {
int current = 0;
switch (m_currentIntent) {
case InputEvent::SetDisplayLength:
current = Static<ConfigService>::instance()->coordMap()->pixelCount;
break;
case InputEvent::SetDisplayOffset:
current = Static<ConfigService>::instance()->coordMap()->startPixel;
break;
default:
break;
}
setEvent(InputEvent{m_currentIntent, current - 1});
}
void increment() {
int current = 0;
switch (m_currentIntent) {
case InputEvent::SetDisplayLength:
current = Static<ConfigService>::instance()->coordMap()->pixelCount;
break;
case InputEvent::SetDisplayOffset:
current = Static<ConfigService>::instance()->coordMap()->startPixel;
break;
default:
break;
}
setEvent(InputEvent{m_currentIntent, current + 1});
}
InputEvent::Intent nextIntent() {
switch (m_currentIntent) {
case InputEvent::SetDisplayLength:
return InputEvent::SetDisplayOffset;
case InputEvent::SetDisplayOffset:
return InputEvent::SetDisplayLength;
default:
return InputEvent::None;
}
}
};

View File

@ -31,7 +31,7 @@ const MQTTDevice Device{
Platform::deviceID(),
Platform::deviceName(),
Platform::model(),
#ifdef BOARD_ESP8266
#ifdef ESP8266
ESP.getSketchMD5(),
#else
"",
@ -95,10 +95,6 @@ const MQTTEntity Lightswitch {
"light", Device, "lightswitch"
};
const MQTTEntity flashlightSwitch {
"switch", Device, "flashlight"
};
const MQTTEntity FPSSensor {
"sensor", Device, "fps"
};
@ -124,27 +120,28 @@ MQTTTelemetry::handleEventOnline(const InputEvent& evt)
m_json.clear();
Lightswitch.toJson(m_json);
int i = 0;
for(const Sequencer::Scene& scene : m_sequencer->scenes()) {
m_json["fx_list"][i++] = scene.name;
}
m_json["brightness"] = true;
m_json["rgb"] = true;
publishDoc(Lightswitch.configTopic().c_str(), true);
//Log.verbose("Publish %s %s", Lightswitch.configTopic().c_str(), buf);
//m_mqtt.publish(Lightswitch.configTopic().c_str(), (uint8_t*)buf, strlen(buf), true);
m_mqtt.subscribe(Lightswitch.commandTopic().c_str());
m_json.clear();
flashlightSwitch.toJson(m_json, false);
m_json["cmd_t"] = "~/set";
m_json["ret"] = true;
publishDoc(flashlightSwitch.configTopic().c_str(), true);
//m_mqtt.publish(flashlightSwitch.configTopic().c_str(), (uint8_t*)buf, strlen(buf), true);
m_mqtt.subscribe(flashlightSwitch.commandTopic().c_str());
for(auto scene : Static<Sequencer>::instance()->scenes()) {
m_json.clear();
String strName{scene.name};
MQTTEntity sceneObj {
"scene",
Device,
strName
};
sceneObj.toJson(m_json, false);
m_json["cmd_t"] = "~/set";
m_json["ret"] = false;
m_json["payload_on"] = "active";
publishDoc(sceneObj.configTopic().c_str(), false);
m_mqtt.subscribe(sceneObj.commandTopic().c_str());
Log.info("Published scene %s", sceneObj.configTopic().c_str());
}
m_json.clear();
FPSSensor.toJson(m_json, false);
@ -168,13 +165,7 @@ MQTTTelemetry::handleEventOnline(const InputEvent& evt)
}
} else {
String statTopic = Lightswitch.statTopic();
if (evt.intent == InputEvent::StopThing && String(evt.asString()) == "Flashlight") {
String flashlightStatTopic = flashlightSwitch.statTopic();
m_mqtt.publish(flashlightStatTopic.c_str(), "OFF");
} else if (evt.intent == InputEvent::StartThing && String(evt.asString()) == "Flashlight") {
String flashlightStatTopic = flashlightSwitch.statTopic();
m_mqtt.publish(flashlightStatTopic.c_str(), "ON");
} else if (evt.intent == InputEvent::SetPower) {
if (evt.intent == InputEvent::SetPower) {
m_json.clear();
m_isOn = evt.asInt() ? true : false;
m_json["state"] = m_isOn ? "ON" : "OFF";
@ -192,7 +183,7 @@ MQTTTelemetry::handleEventOnline(const InputEvent& evt)
m_json["color"]["b"] = color.b;
m_json["state"] = m_isOn ? "ON" : "OFF";
publishDoc(statTopic.c_str());
} else if (evt.intent == InputEvent::SetPattern) {
} else if (evt.intent == InputEvent::SetScene) {
m_json.clear();
m_json["effect"] = evt.asString();
m_json["state"] = m_isOn ? "ON" : "OFF";
@ -280,17 +271,7 @@ void
MQTTTelemetry::callback(char* topic, const char* payload)
{
setEvent(InputEvent::NetworkActivity);
if (flashlightSwitch.isCommandTopic(topic)) {
if (!strncmp((char*)payload, "ON", sizeof("ON"))) {
Log.notice("Turning on flashlight");
setEvent(InputEvent{InputEvent::SetPower, true});
setEvent(InputEvent{InputEvent::SetPattern, "Flashlight"});
setEvent(InputEvent{InputEvent::SetBrightness, 255});
} else if (!strncmp((char*)payload, "OFF", sizeof("OFF"))) {
Log.notice("Turning off flashlight");
setEvent(InputEvent{InputEvent::SetPattern, "Idle"});
}
} else if (Lightswitch.isCommandTopic(topic)) {
if (Lightswitch.isCommandTopic(topic)) {
deserializeJson(m_json, payload);
if (m_json.containsKey("state")) {
@ -299,7 +280,7 @@ MQTTTelemetry::callback(char* topic, const char* payload)
setEvent(InputEvent{InputEvent::SetPower, true});
} else if (m_json["state"] == "OFF") {
Log.notice("Turning off power");
setEvent(InputEvent{InputEvent::SetPattern, "Idle"});
setEvent(InputEvent{InputEvent::SetScene, "Idle"});
setEvent(InputEvent{InputEvent::SetPower, false});
}
}
@ -352,7 +333,7 @@ MQTTTelemetry::callback(char* topic, const char* payload)
if (m_json.containsKey("effect")) {
strcpy(m_patternBuf, m_json["effect"].as<const char*>());
setEvent(InputEvent{InputEvent::SetPattern, m_patternBuf});
setEvent(InputEvent{InputEvent::SetScene, m_patternBuf});
}
if (m_json.containsKey("color")) {
@ -367,6 +348,19 @@ MQTTTelemetry::callback(char* topic, const char* payload)
}
Log.notice("Event done.");
} else {
for(auto scene : Static<Sequencer>::instance()->scenes()) {
String strName{scene.name};
MQTTEntity sceneObj {
"scene",
Device,
strName
};
if (sceneObj.isCommandTopic(topic)) {
setEvent(InputEvent{InputEvent::SetScene, scene.name});
return;
}
}
}
}

View File

@ -7,9 +7,9 @@
#include "../../Sequencer.h"
#ifdef BOARD_ESP8266
#ifdef ESP8266
#include <ESP8266WiFi.h>
#elif defined(BOARD_ESP32)
#elif defined(ESP32)
#include <WiFi.h>
#endif

View File

@ -1,10 +1,10 @@
#include <Input.h>
#include <ArduinoLog.h>
#ifdef BOARD_ESP8266
#ifdef ESP8266
#include <ESP8266WiFi.h>
#endif
#ifdef BOARD_ESP32
#ifdef ESP32
#include <WiFi.h>
#endif
#include "Static.h"

View File

@ -0,0 +1,106 @@
#include "../../../Platform.h"
#include <WiFi.h>
#include <esp_task_wdt.h>
__NOINIT_ATTR static uint8_t s_rebootCount;
__NOINIT_ATTR static uint16_t s_forceSafeMode;
#define SAFE_MODE_MAGIC 6942
template<>
void
PlatformImpl<HAL_ESP32>::initBootOptions(BootOptions& opts)
{
opts.resetReason = esp_reset_reason();
opts.crashCount = s_rebootCount;
if (opts.resetReason >= 4) { // TODO: These values are defined in
// esp32/rom/rtc.h, but not sure if that's included
// on platformio builds
if (opts.crashCount++ >= 3) {
// Boot into safe mode if the watchdog reset us three times in a row.
isSafeMode = true;
}
} else {
opts.crashCount = 0;
}
s_rebootCount = crashCount;
}
template<>
const char*
PlatformImpl<HAL_ESP32>::name()
{
return "ESP32";
}
template<>
const char*
PlatformImpl<HAL_ESP32>::version()
{
return ESP.getSdkVersion();
}
template<>
const char*
PlatformImpl<HAL_ESP32>::deviceID()
{
uint64_t chipid;
chipid = ESP.getEfuseMac();
snprintf(s_deviceID, sizeof(s_deviceID), "%08X", (uint32_t)chipid);
return s_deviceID;
}
template<>
int
PlatformImpl<HAL_ESP32>::freeRam()
{
return ESP.getFreeHeap();
}
int printEspLog(const char* fmt, va_list args)
{
Log.notice(fmt, args);
return 1;
}
template<>
void
PlatformImpl<HAL_ESP32>::startWatchdog()
{
esp_task_wdt_init(10, true);
esp_task_wdt_add(NULL);
esp_log_set_vprintf(printEspLog);
}
template<>
void
PlatformImpl<HAL_ESP32>::startNTP()
{
constexpr int dst = 1;
configTime(0, 3600 * dst, "pool.ntp.org");
}
template<>
void
PlatformImpl<HAL_ESP32>::loop()
{
esp_task_wdt_reset();
}
template<>
bool
PlatformImpl<HAL_ESP32>::getLocalTime(struct tm* timedata, int timezone)
{
time_t rawtime;
memset(&rawtime, 0, sizeof(rawtime));
time(&rawtime);
(*timedata) = (*localtime(&rawtime));
return (timedata->tm_year > (2016-1990));
}
template<>
void
PlatformImpl<HAL_ESP32>::restart()
{
ESP.restart();
}

View File

@ -0,0 +1,134 @@
#include "../../../Platform.h"
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <ctime>
#define __NOINIT_ATTR __attribute__ ((section (".noinit")))
__NOINIT_ATTR static uint8_t s_rebootCount;
__NOINIT_ATTR static uint16_t s_forceSafeMode;
#define SAFE_MODE_MAGIC 6942
WiFiUDP wifiUdp;
NTPClient timeClient(wifiUdp, "pool.ntp.org", 3600 * -7);
template<>
const char*
PlatformImpl<HAL_ESP8266>::name()
{
return "ESP8266";
}
template<>
const char*
PlatformImpl<HAL_ESP8266>::version()
{
return ESP.getSdkVersion();
}
template<>
int
PlatformImpl<HAL_ESP8266>::freeRam()
{
return ESP.getFreeHeap();
}
template<>
void
PlatformImpl<HAL_ESP8266>::startWatchdog()
{
ESP.wdtEnable(0);
}
template<>
bool
PlatformImpl<HAL_ESP8266>::getLocalTime(struct tm* timedata, int timezone)
{
timedata->tm_hour = (timeClient.getHours() + timezone) % 23;
timedata->tm_min = timeClient.getMinutes();
return true;
}
template<>
void
PlatformImpl<HAL_ESP8266>::startNTP()
{
timeClient.begin();
}
template<>
void
PlatformImpl<HAL_ESP8266>::loop()
{
if (WiFi.status() == WL_CONNECTED) {
timeClient.update();
}
ESP.wdtFeed();
}
template<>
const char*
PlatformImpl<HAL_ESP8266>::deviceID()
{
static char s_deviceID[15];
static uint16_t chipid = ESP.getChipId();
snprintf(s_deviceID, sizeof(s_deviceID), "%08X", (uint32_t)chipid);
return s_deviceID;
}
template<>
void
PlatformImpl<HAL_ESP8266>::restart()
{
ESP.wdtDisable();
ESP.restart();
}
template<>
void
PlatformImpl<HAL_ESP8266>::bootSplash()
{
Log.notice("ESP8266!");
}
template<>
void
PlatformImpl<HAL_ESP8266>::printCrashInfo()
{
auto rInfo = ESP.getResetInfoPtr();
if (Platform::bootopts.resetReason == REASON_EXCEPTION_RST) {
Log.error("Fatal exception (%d):", rInfo->exccause);
}
Log.error("epc1=%X, epc2=%X, epc3=%X, excvaddr=%X, depc=%X",
rInfo->epc1, rInfo->epc2, rInfo->epc3, rInfo->excvaddr, rInfo->depc);
}
template<>
void
PlatformImpl<HAL_ESP8266>::initBootOptions(BootOptions& opts)
{
struct rst_info resetInfo = *ESP.getResetInfoPtr();
opts.resetReason = resetInfo.reason;
opts.crashCount = s_rebootCount;
if (resetInfo.reason == REASON_SOFT_WDT_RST || resetInfo.reason == REASON_WDT_RST || resetInfo.reason == REASON_EXCEPTION_RST) {
if (opts.crashCount++ >= 3) {
// Boot into safe mode if the watchdog reset us three times in a row.
opts.isSafeMode = true;
}
} else {
opts.crashCount = 0;
}
s_rebootCount = opts.crashCount;
if (resetInfo.reason > 0 && s_forceSafeMode == SAFE_MODE_MAGIC) {
opts.isSafeMode = true;
s_forceSafeMode = 0;
}
}
template<>
void
PlatformImpl<HAL_ESP8266>::forceSafeMode()
{
s_forceSafeMode = SAFE_MODE_MAGIC;
}

View File

@ -11,4 +11,21 @@ def verify_json(source, target, env):
print("Validating " + root + '/' + file + '...')
json.load(open(root + '/' + file, 'r'))
usedTasks = set()
for root, dirnames, files in os.walk("data/profiles/"):
for file in files:
if file.endswith(".json"):
data = json.load(open(root + '/' + file, 'r'))
for task in data['tasks']:
usedTasks.add(task)
for sceneName in data['scenes']:
for task in data['scenes'][sceneName]:
usedTasks.add(task)
print("Used tasks:")
for task in sorted(usedTasks):
print("- " + task)
env.AddPreAction("buildfs", verify_json)