Compare commits

...

13 Commits

9 changed files with 259 additions and 299 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
config.h

View File

@@ -2,30 +2,22 @@
* Libraries and global scope code
*/
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <time.h>
BearSSL::WiFiClientSecure net;
time_t now;
unsigned long lastMillis = 0;
String devname; // Device identifier for MQTT
struct Settings {
String name = "";
String ip = "";
uint8_t mode = 0, // Current animation effect
offset = 0,
brightness = 20; // Default brightness (range 0-255)
long color = 0x00A4B3; // Starting color
} settings;
struct State {
String text = "";
uint8_t mode = 0;
long color = 0x00A4B3; // Starting color
} state;
time_t now;
/*
* Modules will plug in to this thing via function pointers
*/
// see also http://www.gammon.com.au/forum/?id=12607
//void module_message(const String& shorttopic, const String& message) { //@@@@FIXME@@@@ instead of brightness, adjust mode?
//void module_message(const String& shorttopic, const String& message) {
//
//}
/*
* Debugging might be nice sometimes

148
10_wifi_conf.ino Normal file
View File

@@ -0,0 +1,148 @@
/*
* Wifi and OTA related stuff
*/
#include <time.h>
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <WiFiManager.h>
#include <ESP8266httpUpdate.h>
WiFiManager WifiManager;
WiFiClientSecure net;
//BearSSL::WiFiClientSecure net;
unsigned long ota_lastcheck = 0;
//
// If the WifiManager configuration portal is called, we can do stuff
//
//void WifiManagerCallback(WiFiManager *myWiFiManager) {
// PRINTLN_SERIAL("Entered AP config mode");
//}
void wifi_associate() {
char apname[80];
settings.name.toCharArray(apname, 80);
WifiManager.setConfigPortalTimeout(300); // If no configuration is done in 5 mins, exit/restart quietly
if (WifiManager.autoConnect(apname)) { // @@@FIXME@@@ we should really set a PSK for the AP (but in my brief testing it crashed the ESP, so what's up with that)
settings.ip = WiFi.localIP().toString();
PRINTLN_SERIAL("Figured out my network \\O/");
//wificlient.setFingerprint(WTR_SHA1);
net.setInsecure(); // Do not check fingerprint
net.setTimeout(15000); // 15 Seconds
PRINT_SERIAL("Setting time using SNTP");
configTime(-5 * 3600, 0, "pool.ntp.org", "time.nist.gov");
now = time(nullptr);
while (now < 1510592825) {
delay(500);
APPEND_SERIAL(".");
now = time(nullptr);
}
APPENDLN_SERIAL(" done!");
struct tm timeinfo;
gmtime_r(&now, &timeinfo);
PRINT_SERIAL("Current time: ");
APPENDLN_SERIAL(asctime(&timeinfo));
}
}
void wifi_checkin() {
// 'Native' in WiFiClient because we need to push the entire clientbuffer in the API
// As a result copying the buffer in to a new String for HTTPClient library use is highly inefficient
if (!net.connect(OTA_SERVER, OTA_PORT)) {
Serial.println("HTTPS connection failed");
} else {
Serial.println("HTTPS connection up");
// Check for firmware upgrades
String version = settings.name;
version.concat("-v");
version.concat(FW_VERSION);
String json = "{\"mac\":\"" + WiFi.macAddress() + "\",";
json.concat("\"version\":\"" + version + "\",");
json.concat("\"millis\":" + String(millis()) + "}");
// Send request to the server:
net.println("POST " OTA_CHECKIN " HTTP/1.1");
net.println("Host: " OTA_SERVER);
net.println("Accept: */*");
net.println("Content-Type: application/json");
net.print("Content-Length: ");
net.println(json.length());
net.println("Connection: close");
net.println();
// Construct the REST/JSON POST data
net.print(json);
Serial.println("POST sent");
while (net.connected()) {
String line = net.readStringUntil('\n');
if (line == "\r") {
Serial.println("Headers received");
break;
}
}
String line = net.readStringUntil('\n');
Serial.println("reply was:");
Serial.println("==========");
Serial.println(line);
Serial.println("==========");
Serial.println("closing connection");
net.stop(); // DISCONNECT FROM THE SERVER
}
}
void wifi_setup() {
// WifiManager.setAPCallback(WifiManagerCallback); // Enable WifiManager callback to clear the cache
wifi_associate();
}
void wifi_loop() {
if(WiFi.status() != WL_CONNECTED) {
PRINTLN_SERIAL("Wifi disconnected, trying to reconnect");
wifi_associate();
}
// OTA routine to be run once every X seconds
unsigned long ota_check = millis()/1000;
if((ota_lastcheck == 0) || ((ota_check - ota_lastcheck) > OTA_UPDATE_INTERVAL)) {
PRINTLN_SERIAL("Checking for OTA update");
// Check for firmware upgrades
String version = settings.name;
version.concat("-v");
version.concat(FW_VERSION);
PRINTLN_SERIAL("net.status: " + String(net.status()));
t_httpUpdate_return ret = ESPhttpUpdate.update(net, OTA_SERVER, OTA_PORT, OTA_URI, version);
PRINTLN_SERIAL("after httpupdate check net.status: " + String(net.status()));
switch(ret) {
case HTTP_UPDATE_FAILED: // HTTP 403, 404
PRINT_SERIAL("Connection error, update failed ");
APPEND_SERIAL("(ERR ");
APPEND_SERIAL(String(ESPhttpUpdate.getLastError()));
APPEND_SERIAL(") ");
APPENDLN_SERIAL(ESPhttpUpdate.getLastErrorString().c_str());
break;
case HTTP_UPDATE_NO_UPDATES: // HTTP 304
PRINTLN_SERIAL("No firmware upgrade available");
break;
case HTTP_UPDATE_OK: // HTTP 200
PRINTLN_SERIAL("Firmware upgrade available, upgraded ok."); // may not called we reboot the ESP
break;
}
ota_lastcheck = ota_check;
// Check in with IoT server
wifi_checkin();
}
}

View File

@@ -1 +0,0 @@
// Future use

View File

@@ -1,20 +1,13 @@
#ifdef ENABLE_MQTT
/*
* Define a function newcmd in your module to be able to accept mqtt commands
* Syntax and parameters are like this:
*/
void newcmd(String cmd);
void module_message(const String& shorttopic, const String& message);
// sample schema's to use: https://www.home-assistant.io/integrations/light.mqtt/
#include <PubSubClient.h>
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
PubSubClient mqtt(net);
// Setup the MQTT client class by passing in the WiFi client
PubSubClient mqtt(net);
String deviceprefix;
const char* fingerprint = "EA:2A:2B:80:C1:00:57:35:66:26:FF:FC:FA:27:EA:5F:3D:91:5A:F9";
long logtimerMillis = 0;
void mqtt_subscribe(const String& topic) {
@@ -72,52 +65,38 @@ void mqtt_callback(char* topic, byte* payload, unsigned int length) {
}
}
void WifiMQTTconnect() {
if(WiFi.status() != WL_CONNECTED) {
PRINTLN_SERIAL("Wifi not connected, connecting...");
WiFi.mode(WIFI_STA); // Weird MQTT connection bug, https://github.com/knolleary/pubsubclient/issues/138#issuecomment-326113915
WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED) {
PRINTLN_SERIAL("Waiting for Wifi...");
delay(500);
}
settings.ip = WiFi.localIP().toString();
PRINTLN_SERIAL("Wifi connected");
}
void mqtt_connect() {
/* bool success= false;
success = net.connect(MQTT_SERVER, MQTT_SERVERPORT);
if (success) {
PRINTLN_SERIAL("Connection complete, valid cert, valid fingerprint.");
} else {
PRINTLN_SERIAL("Connection failed!");
} */
PRINTLN_SERIAL("prepare mqtt connect check net.status: " + String(net.status()));
PRINT_SERIAL("Setting time using SNTP");
configTime(-5 * 3600, 0, "pool.ntp.org", "time.nist.gov");
now = time(nullptr);
while (now < 1510592825) {
delay(500);
APPEND_SERIAL(".");
now = time(nullptr);
}
APPENDLN_SERIAL(" done!");
struct tm timeinfo;
gmtime_r(&now, &timeinfo);
PRINT_SERIAL("Current time: ");
APPENDLN_SERIAL(asctime(&timeinfo));
net.setInsecure(); // verification options set to none
mqtt.setServer(MQTT_SERVER, MQTT_SERVERPORT);
mqtt.setCallback(mqtt_callback);
if(!mqtt.connected()) {
while (!mqtt.connected()) {
PRINTLN_SERIAL("MQTT not connected, connecting...");
// Attempt to connect
// Note - the default maximum packet size is 128 bytes. If the
// combined length of clientId, username and password exceed this,
// you will need to increase the value of MQTT_MAX_PACKET_SIZE in
// PubSubClient.h
if (mqtt.connect(settings.name.c_str(), MQTT_USERNAME, MQTT_PASSWORD)) {
PRINTLN_SERIAL("MQTT connected");
} else {
PRINTLN_SERIAL("MQTT connection failed, rc=" + String(mqtt.state()) + "...");
delay(10000); // @@@FIXME@@@ delays are not cool
}
PRINTLN_SERIAL("before mqtt connect check net.status: " + String(net.status()));
while (!mqtt.connected()) {
PRINTLN_SERIAL("MQTT not connected, connecting...");
PRINTLN_SERIAL("while mqtt connecting check net.status: " + String(net.status()));
// Attempt to connect
// Note - the default maximum packet size is 128 bytes. If the
// combined length of clientId, username and password exceed this,
// you will need to increase the value of MQTT_MAX_PACKET_SIZE in
// PubSubClient.h
if (mqtt.connect(settings.name.c_str(), MQTT_USERNAME, MQTT_PASSWORD)) {
PRINTLN_SERIAL("MQTT connected");
PRINTLN_SERIAL("mqtt just connected check net.status: " + String(net.status()));
} else {
PRINTLN_SERIAL("MQTT connection failed, rc=" + String(mqtt.state()) + "...");
PRINTLN_SERIAL("mqtt failed connected check net.status: " + String(net.status()));
delay(10000); // @@@FIXME@@@ delays are not cool
}
// (re)subscribe to the topics we need
@@ -126,14 +105,15 @@ void WifiMQTTconnect() {
mqtt_subscribe(MQTT_PREFIX "ping"); // global topic: send a ping, and we will respond with some device info
mqtt_subscribe(deviceprefix + "#");
mqtt_publish(deviceprefix + "log", "Booting up " + settings.name + " running v" + FW_VERSION + " at " + settings.ip);
mqtt_publish(deviceprefix + "log", "Connected " + settings.name + " running v" + FW_VERSION + " at " + settings.ip);
mqtt_publish(deviceprefix + "log", "Free Heap: " + String(ESP.getFreeHeap()));
PRINTLN_SERIAL("after mqtt connect check net.status: " + String(net.status()));
}
}
void mqtt_setup() {
PRINTLN_SERIAL(devname + "initialising module MQTT");
PRINTLN_SERIAL("Initialising MQTT");
}
void mqtt_loop() {
@@ -141,7 +121,7 @@ void mqtt_loop() {
// Check for MQTT instructions
if(!mqtt.connected()) {
WifiMQTTconnect();
mqtt_connect();
} else {
mqtt.loop();

View File

@@ -6,14 +6,10 @@
void newcmd(String cmd) {
cmd.toLowerCase();
if(cmd.equals("off")) {
settings.mode = 0;
PRINTLN_SERIAL("Lights off");
state.text = "Sonoff switched off";
}
if(cmd.equals("on")) {
settings.mode = 1;
PRINTLN_SERIAL("Lights on");
state.text = "Sonoff switched off";
}
}

View File

@@ -1,183 +1,68 @@
#ifdef ENABLE_MOON
// Needs refactoring
// Use https://adrianotiger.github.io/Neopixel-Effect-Generator/ for inspiration
// Read up on final comment at https://forum.arduino.cc/index.php?topic=534060.0
#include <WS2812FX.h>
#include <Adafruit_NeoPixel.h>
/*
* Based on https://adrianotiger.github.io/Neopixel-Effect-Generator/
* TODO: Refactor for just a single string effect, less frills
* Rainbow pattern
*/
class Strip
{
public:
uint8_t effect;
uint8_t effects;
uint16_t effStep;
unsigned long effStart;
Adafruit_NeoPixel strip;
Strip(uint16_t leds, uint8_t pin, uint8_t toteffects) : strip(leds, pin, NEO_GRB + NEO_KHZ800) {
effect = -1;
effects = toteffects;
Reset();
}
void Reset(){
effStep = 0;
effect = (effect + 1) % effects;
effStart = millis();
}
};
struct Loop
{
uint8_t currentChild;
uint8_t childs;
bool timeBased;
uint16_t cycles;
uint16_t currentTime;
Loop(uint8_t totchilds, bool timebased, uint16_t tottime) {currentTime=0;currentChild=0;childs=totchilds;timeBased=timebased;cycles=tottime;}
};
Strip strip_0(7, MOON_PIXEL, 7 );
struct Loop strip0loop0(1, false, 1);
//[GLOBAL_VARIABLES]
int speed = 200; // started at 101
uint8_t strip0_loop0_eff0() {
// Strip ID: 0 - Effect: Rainbow - LEDS: 7
// Steps: 35 - Delay: 100
// Colors: 6 (255.255.0, 0.255.0, 0.0.255, 255.0.255, 255.0.0, 255.255.255, )
// Options: toLeft=true,
if(millis() - strip_0.effStart < 100 * (strip_0.effStep)) return 0x00;
float factor1, factor2;
uint16_t ind;
for(uint16_t j=0;j<7;j++) {
ind = strip_0.effStep + j * 1;
switch((int)((ind % 35) / 5.833333333333333)) {
case 0: factor1 = 1.0 - ((float)(ind % 35 - 0 * 5.833333333333333) / 5.833333333333333);
factor2 = (float)((int)(ind - 0) % 35) / 5.833333333333333;
strip_0.strip.setPixelColor(j, 255 * factor1 + 0 * factor2, 255 * factor1 + 255 * factor2, 0 * factor1 + 0 * factor2);
break;
case 1: factor1 = 1.0 - ((float)(ind % 35 - 1 * 5.833333333333333) / 5.833333333333333);
factor2 = (float)((int)(ind - 5.833333333333333) % 35) / 5.833333333333333;
strip_0.strip.setPixelColor(j, 0 * factor1 + 0 * factor2, 255 * factor1 + 0 * factor2, 0 * factor1 + 255 * factor2);
break;
case 2: factor1 = 1.0 - ((float)(ind % 35 - 2 * 5.833333333333333) / 5.833333333333333);
factor2 = (float)((int)(ind - 11.666666666666666) % 35) / 5.833333333333333;
strip_0.strip.setPixelColor(j, 0 * factor1 + 255 * factor2, 0 * factor1 + 0 * factor2, 255 * factor1 + 255 * factor2);
break;
case 3: factor1 = 1.0 - ((float)(ind % 35 - 3 * 5.833333333333333) / 5.833333333333333);
factor2 = (float)((int)(ind - 17.5) % 35) / 5.833333333333333;
strip_0.strip.setPixelColor(j, 255 * factor1 + 255 * factor2, 0 * factor1 + 0 * factor2, 255 * factor1 + 0 * factor2);
break;
case 4: factor1 = 1.0 - ((float)(ind % 35 - 4 * 5.833333333333333) / 5.833333333333333);
factor2 = (float)((int)(ind - 23.333333333333332) % 35) / 5.833333333333333;
strip_0.strip.setPixelColor(j, 255 * factor1 + 255 * factor2, 0 * factor1 + 255 * factor2, 0 * factor1 + 255 * factor2);
break;
case 5: factor1 = 1.0 - ((float)(ind % 35 - 5 * 5.833333333333333) / 5.833333333333333);
factor2 = (float)((int)(ind - 29.166666666666664) % 35) / 5.833333333333333;
strip_0.strip.setPixelColor(j, 255 * factor1 + 255 * factor2, 255 * factor1 + 255 * factor2, 255 * factor1 + 0 * factor2);
break;
}
}
if(strip_0.effStep >= 35) {strip_0.Reset(); return 0x03; }
else strip_0.effStep++;
return 0x01;
}
uint8_t strip0_loop0() {
uint8_t ret = 0x00;
switch(strip0loop0.currentChild) {
case 0:
ret = strip0_loop0_eff0();break;
}
if(ret & 0x02) {
ret &= 0xfd;
if(strip0loop0.currentChild + 1 >= strip0loop0.childs) {
strip0loop0.currentChild = 0;
if(++strip0loop0.currentTime >= strip0loop0.cycles) {strip0loop0.currentTime = 0; ret |= 0x02;}
}
else {
strip0loop0.currentChild++;
}
};
return ret;
}
void strips_loop() {
if(strip0_loop0() & 0x01)
strip_0.strip.show();
}
// https://github.com/kitesurfer1404/WS2812FX/blob/master/src/WS2812FX.h
WS2812FX ws2812fx = WS2812FX(MOON_PIXEL_LEDS, MOON_PIXEL, NEO_GRB + NEO_KHZ800);
long color = 0x00A4B3; // Starting color
/*
* Interface with other modules
*/
void newcmd(String cmd) {
cmd.toLowerCase();
if(cmd.equals("off")) {
settings.mode = 0;
PRINTLN_SERIAL("Moon off");
strip_0.strip.setBrightness(0); // 0-255
state.text = "Moon switched off";
}
if(cmd.equals("on")) {
settings.mode = 1;
PRINTLN_SERIAL("Moon switched on");
strip_0.strip.setBrightness(10); // 0-255
state.text = "Moon switched off";
}
}
void module_message(const String& shorttopic, const String& message) {
void module_message(const String& shorttopic, const String& message) { //@@@@FIXME@@@@ instead of brightness, adjust mode?
char msgptr[10];
String buffer;
if(shorttopic.equalsIgnoreCase("cmd")) {
if(message.equalsIgnoreCase("off")) {
state.mode = 0;
PRINTLN_SERIAL("Moon off");
strip_0.strip.setBrightness(0); // 0-255
state.text = "Moon switched off";
} else if(message.equalsIgnoreCase("on")) {
state.mode = 1;
PRINTLN_SERIAL("Moon switched on");
strip_0.strip.setBrightness(10); // 0-255
state.text = "Moon switched off";
}
} else if(shorttopic.equalsIgnoreCase("mode")) {
if(message.equals("off")) {
state.mode = 0;
ws2812fx.setColor(0x000000);
ws2812fx.setMode(FX_MODE_STATIC);
PRINTLN_SERIAL("Shutting off");
} else if(message.equals("on")) { // restore last (static) color state
ws2812fx.setColor(color);
ws2812fx.setMode(FX_MODE_STATIC);
PRINTLN_SERIAL("Swtiching on (static)");
} else if(message.startsWith("0x")) {
state.mode = 1;
message.toCharArray(msgptr, 9);
state.color = strtoll( &msgptr[2], NULL, 16);
sprintf(printbuffer, "Switching to static color 0x%x", state.color);
color = strtoll( &msgptr[2], NULL, 16);
ws2812fx.setColor(color);
ws2812fx.setMode(FX_MODE_STATIC);
sprintf(printbuffer, "Switching to static color 0x%x", color);
PRINTLN_SERIAL(printbuffer);
} else if(message.startsWith("#")) {
state.mode = 1;
message.toCharArray(msgptr, 8);
state.color = strtoll( &msgptr[1], NULL, 16);
sprintf(printbuffer, "Switching to static color 0x%x", state.color);
color = strtoll( &msgptr[1], NULL, 16);
ws2812fx.setColor(color);
ws2812fx.setMode(FX_MODE_STATIC);
sprintf(printbuffer, "Switching to static color 0x%x", color);
PRINTLN_SERIAL(printbuffer);
} else if(message.equals("moon")) {
ws2812fx.setSpeed(20000);
ws2812fx.setLength(20); // Emulate a 20 pin cycle for a 7 pixel moon lamp
ws2812fx.setMode(FX_MODE_RAINBOW_CYCLE);
PRINTLN_SERIAL("Switching to moon mode");
} else if(message.equals("rainbow")) {
state.mode = 2;
ws2812fx.setSpeed(2000);
ws2812fx.setLength(MOON_PIXEL_LEDS);
ws2812fx.setMode(FX_MODE_RAINBOW_CYCLE);
PRINTLN_SERIAL("Switching to rainbow mode");
// Testing area for new scenes
} else if(message.equals("twinkle")) {
ws2812fx.setMode(FX_MODE_LARSON_SCANNER);
PRINTLN_SERIAL("Switching to twinkle mode");
}
mqtt_publish((deviceprefix + "log"), ("mode=" + String(state.mode))); // @@@FIXME@@@ this needs to go elsewhere
} else if(shorttopic.equalsIgnoreCase("brightness")) {
PRINTLN_SERIAL("Setting brightness to " + message);
settings.brightness = message.toInt();
strip_0.strip.setBrightness(settings.brightness);
ws2812fx.setBrightness(message.toInt()); // 0-255
buffer = "brightness=";
buffer.concat(settings.brightness);
buffer.concat(message.toInt());
mqtt_publish((deviceprefix + "log"), buffer.c_str()); // @@@FIXME@@@ this needs to go elsewhere
}
}
@@ -188,34 +73,16 @@ void module_message(const String& shorttopic, const String& message) {
void moon_setup() {
PRINTLN_SERIAL("initialising module Moon");
strip_0.strip.setBrightness(2); // 0-255
strip_0.strip.begin();
ws2812fx.init();
ws2812fx.setBrightness(5);
ws2812fx.setSpeed(200);
ws2812fx.setColor(0x000000);
ws2812fx.setMode(FX_MODE_STATIC);
ws2812fx.start();
}
void moon_loop() {
uint16_t r;
switch(state.mode) {
case 0: // Off
for(r=0; r< strip_0.strip.numPixels(); r++) {
strip_0.strip.setPixelColor(r, 0,0,0);
}
strip_0.strip.show();
break;
case 1: // Static color
for(r=0; r< strip_0.strip.numPixels(); r++) {
// Split the set color code up into r, g, b values
int rval = state.color >> 16;
int gval = state.color >> 8 & 0xFF;
int bval = state.color & 0xFF;
strip_0.strip.setPixelColor(r, rval, gval, bval);
}
strip_0.strip.show();
break;
case 2: // Rainbow
strips_loop();
break;
}
ws2812fx.service();
}
#endif

View File

@@ -23,8 +23,9 @@ void setup() {
// If we run in to trouble, this can painlessly be removed and the resulting device name will just be longer
settings.name.remove(devlen+1, 6);
PRINTLN_SERIAL("device name generated");
PRINTLN_SERIAL("Figured out who I am \\O/");
wifi_setup();
#ifdef ENABLE_MQTT
mqtt_setup();
@@ -36,10 +37,11 @@ void setup() {
moon_setup();
#endif
// Start the cooperative scheduler loops
PRINTLN_SERIAL(devname + "done setting up, ready for main loop");
PRINTLN_SERIAL("Done setting up, ready for main loop \\O/");
}
void loop() {
wifi_loop();
#ifdef ENABLE_MQTT
mqtt_loop();
#endif

View File

@@ -13,7 +13,7 @@
// Implement versioning so that new firmware can be done OTA
// Todo:
// Split the wifi and mqtt code in order to support http interface
// maybe: loading settings on SPIFFS or similar so we can create more generic firmware? https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#flash-layout
// Stay on the lookout for watchdog crashes, see also https://www.sigmdel.ca/michel/program/esp8266/arduino/watchdogs_en.html#ESP8266_WDT_RECOV
// Keeps crashing after a few days. Dunno why. https://www.pieterverhees.nl/sparklesagarbage/esp8266/130-difference-between-esp-reset-and-esp-restart
// More on this subject https://github.com/esp8266/Arduino/issues/1017
@@ -22,49 +22,24 @@
// Implement OTA https://www.bakke.online/index.php/2017/06/02/self-updating-ota-firmware-for-esp8266/
// Refactoring sources: https://www.arduinolibraries.info/architectures/esp8266
// Refactor String usage to minimize heap pollution. https://cpp4arduino.com/2018/11/21/eight-tips-to-use-the-string-class-efficiently.html
// Chec Michael Teeuw's MQTT/SSL workaround: https://github.com/MichMich/ESP8266-AWS/blob/master/src/main.ino
#define DEVICEPREFIX "Gadget" // Should be no longer than 8(?) chars or the MQTT clientId will become too long
const int FW_VERSION = 12;
// More WDT fixing:
// https://www.sigmdel.ca/michel/program/esp8266/arduino/watchdogs_en.html
// (background: https://internetofhomethings.com/homethings/?p=396
// (background: http://iot-bits.com/esp8266/esp8266-reset-causes-rst-cause/
// Version history:
// v14: Initial OTA support
// v13: Refactored so config-settings are in config.h, move from Adafruit Neopixel to WS2812FX library
// v12: Refactored inbound commands to hook in to the modules (module_message function), completed assimilation of (never-published) Moon_Connected sketch
// v11: Simplified scheduler, back to cooperative looping
// v10: First 'production' run. MQTT over TLS, but no OTA support.
const int FW_VERSION = 14;
/*
* Compile time settings
*/
//
// Configuration settings
//
#include "config.h"
/************************* WiFi Access Point *********************************/
#define WLAN_SSID "MY_SSID"
#define WLAN_PASS "MY_WIFIPASSWD"
/*********************** Select active modules *******************************/
#define ENABLE_MQTT
//#define ENABLE_SONOFF
#define ENABLE_MOON
#ifdef ENABLE_MQTT
/*************************** MQTT settings ***********************************/
#define MQTT_SERVER "MY_MQTT_SERVER"
#define MQTT_SERVERPORT 8883 // 8883 for MQTTS
#define MQTT_USERNAME "MY_MQTT_USER"
#define MQTT_PASSWORD "MY_MQTT_PASSWD"
#define MQTT_PREFIX "iot/" // MQTT publish/subscribe will be prefixed by this (mind the trailing slash)
#endif
#ifdef ENABLE_SONOFF
/*************************** MQTT settings ***********************************/
#define SONOFF_BUTTON 0
#define SONOFF_RELAY 12
#define SONOFF_LED 13
#endif
#ifdef ENABLE_MOON
/*********************** NeoPixel Moon settings ******************************/
#define MOON_PIXEL 4 // Which GPIO pin is the NeoPixel connected to
#define MOON_PIXEL_LEDS 7 // Amount of leds in the string
#endif