Merge pull request #9 from FabLab-Luenen/development
Development -> Master
This commit is contained in:
@@ -38,7 +38,7 @@
|
||||
// ***************************************************************************
|
||||
#include <PubSubClient.h>
|
||||
WiFiClient espClient;
|
||||
PubSubClient* mqtt_client = NULL;
|
||||
PubSubClient mqtt_client(espClient);
|
||||
#endif
|
||||
|
||||
#if ENABLE_MQTT == 1
|
||||
@@ -47,7 +47,7 @@
|
||||
// ***************************************************************************
|
||||
#include <AsyncMqttClient.h> //https://github.com/marvinroger/async-mqtt-client
|
||||
//https://github.com/me-no-dev/ESPAsyncTCP
|
||||
AsyncMqttClient* mqtt_client = NULL;
|
||||
AsyncMqttClient mqtt_client;
|
||||
WiFiEventHandler wifiConnectHandler;
|
||||
WiFiEventHandler wifiDisconnectHandler;
|
||||
#endif
|
||||
@@ -135,7 +135,6 @@ WS2812FX* strip = NULL;
|
||||
#endif
|
||||
|
||||
void initDMA(uint16_t stripSize = NUMLEDS){
|
||||
if (dma) delete dma;
|
||||
uint8_t ledcolors = 3;
|
||||
if (strstr(WS2812FXStripSettings.RGBOrder, "W") != NULL) {
|
||||
ledcolors = 4;
|
||||
@@ -190,7 +189,7 @@ Ticker ticker;
|
||||
|
||||
void tick() {
|
||||
//toggle state
|
||||
int state = digitalRead(LED_BUILTIN); // get the current state of GPIO1 pin
|
||||
uint16_t state = digitalRead(LED_BUILTIN); // get the current state of GPIO1 pin
|
||||
digitalWrite(LED_BUILTIN, !state); // set pin to the opposite state
|
||||
}
|
||||
|
||||
@@ -206,13 +205,13 @@ Ticker settings_save_state;
|
||||
// Saved state handling in WifiManager
|
||||
// ***************************************************************************
|
||||
// https://stackoverflow.com/questions/9072320/split-string-into-string-array
|
||||
String getValue(String data, char separator, int index)
|
||||
String getValue(String data, char separator, uint8_t index)
|
||||
{
|
||||
int found = 0;
|
||||
int strIndex[] = {0, -1};
|
||||
int maxIndex = data.length()-1;
|
||||
uint8_t found = 0;
|
||||
uint8_t strIndex[] = {0, -1};
|
||||
uint8_t maxIndex = data.length()-1;
|
||||
|
||||
for(int i=0; i<=maxIndex && found<=index; i++){
|
||||
for(uint8_t i=0; i<=maxIndex && found<=index; i++){
|
||||
if(data.charAt(i)==separator || i==maxIndex){
|
||||
found++;
|
||||
strIndex[0] = strIndex[1]+1;
|
||||
@@ -267,18 +266,23 @@ void saveConfigCallback () {
|
||||
#include "mode_custom_ws2812fx_animations.h" // Add animations in this file
|
||||
#endif
|
||||
|
||||
|
||||
// function to Initialize the strip
|
||||
void initStrip(uint16_t stripSize = WS2812FXStripSettings.stripSize, char RGBOrder[5] = WS2812FXStripSettings.RGBOrder, uint8_t pin = WS2812FXStripSettings.pin, uint8_t fxoptions = WS2812FXStripSettings.fxoptions ){
|
||||
if (strip != NULL) {
|
||||
DBG_OUTPUT_PORT.println("Deleting strip!");
|
||||
DBG_OUTPUT_PORT.println("Initializing strip!");
|
||||
if (dma != NULL) {
|
||||
delete(dma);
|
||||
}
|
||||
if (strip != NULL) { //second one created second to delete
|
||||
delete(strip);
|
||||
WS2812FXStripSettings.stripSize = stripSize;
|
||||
strcpy(WS2812FXStripSettings.RGBOrder, RGBOrder);
|
||||
WS2812FXStripSettings.pin = pin;
|
||||
WS2812FXStripSettings.fxoptions = fxoptions;
|
||||
}
|
||||
DBG_OUTPUT_PORT.println("Initializing strip!");
|
||||
if (ledstates != NULL) {
|
||||
delete(ledstates);
|
||||
}
|
||||
ledstates = new uint8_t [WS2812FXStripSettings.stripSize];
|
||||
#if !defined(LED_TYPE_WS2811)
|
||||
strip = new WS2812FX(stripSize, pin, checkRGBOrder(RGBOrder) + NEO_KHZ800);
|
||||
#else
|
||||
@@ -296,25 +300,6 @@ void initStrip(uint16_t stripSize = WS2812FXStripSettings.stripSize, char RGBOrd
|
||||
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
|
||||
// and minimize distance between Arduino and first pixel. Avoid connecting
|
||||
// on a live circuit...if you must, connect GND first.
|
||||
|
||||
#if defined(CUSTOM_WS2812FX_ANIMATIONS)
|
||||
if (heat != NULL) {
|
||||
delete(heat);
|
||||
}
|
||||
heat = new byte [WS2812FXStripSettings.stripSize];
|
||||
#endif
|
||||
#if defined(ENABLE_TV)
|
||||
if (ledStates != NULL) {
|
||||
delete(ledStates);
|
||||
}
|
||||
ledStates = new uint8_t [WS2812FXStripSettings.stripSize];
|
||||
#endif
|
||||
/*
|
||||
if (ledstates != NULL) {
|
||||
delete(ledstates);
|
||||
}
|
||||
ledStates = new LEDState ledstates[WS2812FXStripSettings.stripSize];
|
||||
*/
|
||||
strip->init();
|
||||
#if defined(USE_WS2812FX_DMA)
|
||||
initDMA(stripSize);
|
||||
@@ -326,6 +311,20 @@ void initStrip(uint16_t stripSize = WS2812FXStripSettings.stripSize, char RGBOrd
|
||||
#if defined(CUSTOM_WS2812FX_ANIMATIONS)
|
||||
strip->setCustomMode(0, F("Fire 2012"), myCustomEffect0);
|
||||
//strip->setCustomMode(1, F("CustEffect"), myCustomEffect1);
|
||||
gReverseDirection = (WS2812FXStripSettings.fxoptions & 128);
|
||||
#endif
|
||||
#if defined(ENABLE_E131)
|
||||
/*
|
||||
uint8_t universe_leds = 170.0; // a universe has only 512 (0..511) channels: 3*170 or 4*128 <= 512
|
||||
if (strstr(WS2812FXStripSettings.RGBOrder, "W") != NULL) {
|
||||
universe_leds = 128.0;
|
||||
}
|
||||
*/
|
||||
float float_enduni = stripSize/170.0;
|
||||
uint8_t END_UNIVERSE = stripSize/170.0;
|
||||
if (float_enduni > END_UNIVERSE) {
|
||||
END_UNIVERSE = END_UNIVERSE +1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -335,12 +334,12 @@ void initMqtt() {
|
||||
// ***************************************************************************
|
||||
// Configure MQTT
|
||||
// ***************************************************************************
|
||||
#if ENABLE_MQTT == 0
|
||||
/*#if ENABLE_MQTT == 0
|
||||
mqtt_client = new PubSubClient(espClient);
|
||||
#endif
|
||||
#if ENABLE_MQTT == 1
|
||||
mqtt_client = new AsyncMqttClient();
|
||||
#endif
|
||||
#endif*/
|
||||
|
||||
#if defined(ENABLE_MQTT_HOSTNAME_CHIPID)
|
||||
snprintf(mqtt_clientid, sizeof(mqtt_clientid), "%s-%08X", HOSTNAME, ESP.getChipId());
|
||||
@@ -358,25 +357,24 @@ void initMqtt() {
|
||||
if ((strlen(mqtt_host) != 0) && (mqtt_port != 0)) {
|
||||
#if ENABLE_MQTT == 0
|
||||
DBG_OUTPUT_PORT.printf("MQTT active: %s:%d\r\n", mqtt_host, mqtt_port);
|
||||
mqtt_client->setServer(mqtt_host, mqtt_port);
|
||||
mqtt_client->setCallback(mqtt_callback);
|
||||
mqtt_client.setServer(mqtt_host, mqtt_port);
|
||||
mqtt_client.setCallback(mqtt_callback);
|
||||
#endif
|
||||
#if ENABLE_MQTT == 1
|
||||
DBG_OUTPUT_PORT.printf("AMQTT active: %s:%d\r\n", mqtt_host, mqtt_port);
|
||||
mqtt_client->onConnect(onMqttConnect);
|
||||
mqtt_client->onDisconnect(onMqttDisconnect);
|
||||
mqtt_client->onMessage(onMqttMessage);
|
||||
if ((strlen(mqtt_user) != 0) || (strlen(mqtt_pass) != 0)) mqtt_client->setCredentials(mqtt_user, mqtt_pass);
|
||||
mqtt_client->setClientId(mqtt_clientid);
|
||||
mqtt_client->setWill(mqtt_will_topic, 2, true, mqtt_will_payload, 0);
|
||||
mqtt_client->setServer(mqtt_host, mqtt_port);
|
||||
mqtt_client.onConnect(onMqttConnect);
|
||||
mqtt_client.onDisconnect(onMqttDisconnect);
|
||||
mqtt_client.onMessage(onMqttMessage);
|
||||
if ((strlen(mqtt_user) != 0) || (strlen(mqtt_pass) != 0)) mqtt_client.setCredentials(mqtt_user, mqtt_pass);
|
||||
mqtt_client.setClientId(mqtt_clientid);
|
||||
mqtt_client.setWill(mqtt_will_topic, 2, true, mqtt_will_payload, 0);
|
||||
mqtt_client.setServer(mqtt_host, mqtt_port);
|
||||
connectToMqtt();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// MAIN Setup
|
||||
// ***************************************************************************
|
||||
@@ -504,7 +502,6 @@ void setup() {
|
||||
wifiManager.setConfigPortalTimeout(WIFIMGR_PORTAL_TIMEOUT);
|
||||
#endif
|
||||
|
||||
// Uncomment if you want to set static IP
|
||||
// Order is: IP, Gateway and Subnet
|
||||
#if defined(WIFIMGR_SET_MANUAL_IP)
|
||||
wifiManager.setSTAStaticIPConfig(IPAddress(_ip[0], _ip[1], _ip[2], _ip[3]), IPAddress(_gw[0], _gw[1], _gw[2], _gw[3]), IPAddress(_sn[0], _sn[1], _sn[2], _sn[3]));
|
||||
@@ -532,7 +529,7 @@ void setup() {
|
||||
strcpy(mqtt_pass, custom_mqtt_pass.getValue());
|
||||
#endif
|
||||
strcpy(tmp_strip_size, custom_strip_size.getValue());
|
||||
WS2812FXStripSettings.stripSize = atoi(custom_strip_size.getValue());
|
||||
WS2812FXStripSettings.stripSize = constrain(atoi(custom_strip_size.getValue()), 1, MAXLEDS);
|
||||
#if !defined(USE_WS2812FX_DMA)
|
||||
checkPin(atoi(custom_led_pin.getValue()));
|
||||
#endif
|
||||
@@ -541,7 +538,6 @@ void setup() {
|
||||
WS2812FXStripSettings.fxoptions = atoi(custom_fxoptions.getValue());
|
||||
#if ENABLE_STATE_SAVE == 1
|
||||
(writeConfigFS(shouldSaveConfig)) ? DBG_OUTPUT_PORT.println("WiFiManager config FS Save success!"): DBG_OUTPUT_PORT.println("WiFiManager config FS Save failure!");
|
||||
(writeStateFS(shouldSaveConfig)) ? DBG_OUTPUT_PORT.println("State config FS Save success!"): DBG_OUTPUT_PORT.println("State config FS Save failure!");
|
||||
#endif
|
||||
#if ENABLE_STATE_SAVE == 0
|
||||
if (shouldSaveConfig) {
|
||||
@@ -558,8 +554,6 @@ void setup() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
initStrip();
|
||||
|
||||
//if you get here you have connected to the WiFi
|
||||
DBG_OUTPUT_PORT.println("connected...yeey :)");
|
||||
ticker.detach();
|
||||
@@ -594,7 +588,7 @@ void setup() {
|
||||
ArduinoOTA.onEnd([]() {
|
||||
DBG_OUTPUT_PORT.println("Arduino OTA: End");
|
||||
});
|
||||
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
|
||||
ArduinoOTA.onProgress([](uint16_t progress, uint16_t total) {
|
||||
DBG_OUTPUT_PORT.printf("Arduino OTA Progress: %u%%\r", (progress / (total / 100)));
|
||||
});
|
||||
ArduinoOTA.onError([](ota_error_t error) {
|
||||
@@ -618,6 +612,8 @@ void setup() {
|
||||
initMqtt();
|
||||
#endif
|
||||
|
||||
initStrip();
|
||||
|
||||
#if ENABLE_MQTT == 1
|
||||
wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect);
|
||||
wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect);
|
||||
@@ -667,7 +663,7 @@ void setup() {
|
||||
DBG_OUTPUT_PORT.println(F("*** e131.begin failed ***"));
|
||||
}
|
||||
#endif
|
||||
DBG_OUTPUT_PORT.println("You are here!: 1117");
|
||||
|
||||
prevmode = mode;
|
||||
|
||||
#if defined(ENABLE_BUTTON_GY33)
|
||||
@@ -716,14 +712,14 @@ void loop() {
|
||||
WiFi.begin();
|
||||
} else {
|
||||
if ((strlen(mqtt_host) != 0) && (mqtt_port != 0) && (mqtt_reconnect_retries < MQTT_MAX_RECONNECT_TRIES)) {
|
||||
if (!mqtt_client->connected()) {
|
||||
if (!mqtt_client.connected()) {
|
||||
#if defined(ENABLE_HOMEASSISTANT)
|
||||
ha_send_data.detach();
|
||||
#endif
|
||||
DBG_OUTPUT_PORT.println("MQTT disconnected, reconnecting!");
|
||||
mqtt_reconnect();
|
||||
} else {
|
||||
mqtt_client->loop();
|
||||
mqtt_client.loop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -835,6 +831,7 @@ void loop() {
|
||||
strip->setColors(0, hex_colors);
|
||||
mode = prevmode;
|
||||
prevmode = SET_COLOR;
|
||||
//DBG_OUTPUT_PORT.printf("mode: %d\r\n", mode);
|
||||
if (mode == HOLD) strip->trigger();
|
||||
}
|
||||
if (mode == SET_SPEED) {
|
||||
@@ -853,6 +850,7 @@ void loop() {
|
||||
strip->setBrightness(brightness);
|
||||
mode = prevmode;
|
||||
prevmode = SET_BRIGHTNESS;
|
||||
//DBG_OUTPUT_PORT.printf("mode: %d\r\n", mode);
|
||||
if (mode == HOLD) strip->trigger();
|
||||
}
|
||||
|
||||
@@ -865,10 +863,10 @@ void loop() {
|
||||
}
|
||||
#if defined(ENABLE_MQTT)
|
||||
#if ENABLE_MQTT == 0
|
||||
mqtt_client->publish(mqtt_outtopic, mqtt_buf);
|
||||
mqtt_client.publish(mqtt_outtopic, mqtt_buf);
|
||||
#endif
|
||||
#if ENABLE_MQTT == 1
|
||||
mqtt_client->publish(mqtt_outtopic, qospub, false, mqtt_buf);
|
||||
mqtt_client.publish(mqtt_outtopic, qospub, false, mqtt_buf);
|
||||
#endif
|
||||
#if defined(ENABLE_HOMEASSISTANT)
|
||||
if(!ha_send_data.active()) ha_send_data.once(3, tickerSendState);
|
||||
|
||||
@@ -2,16 +2,17 @@
|
||||
|
||||
// Neopixel
|
||||
#define LED_PIN 3 // PIN (15 / D8) where neopixel / WS2811 strip is attached; is configurable, if USE_WS2812FX_DMA is not defined. Just for the start
|
||||
#define NUMLEDS 144 // Number of leds in the; is configurable just for the start
|
||||
#define NUMLEDS 50 // Number of leds in the; is configurable just for the start
|
||||
#define MAXLEDS 700 // due to memory limit of esp8266 at the moment only 700 leds are supported.
|
||||
#define RGBORDER "GRBW" // RGBOrder; is configurable just for the start
|
||||
#define FX_OPTIONS 56 // ws2812fx Options 56 = SIZE_SMALL + FADE_MEDIUM + GAMMA is configurable just for the start; for WS2812FX setSegment OPTIONS, see: https://github.com/kitesurfer1404/WS2812FX/blob/master/extras/WS2812FX%20Users%20Guide.md
|
||||
//#define LED_TYPE_WS2811 // Uncomment, if LED type uses 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
|
||||
#define LED_BUILTIN 2 // ESP-12F has the built in LED on GPIO2, see https://github.com/esp8266/Arduino/issues/2192
|
||||
|
||||
char HOSTNAME[65] = "McLightingRGBW_02"; // Friedly hostname is configurable just for the start
|
||||
char HOSTNAME[65] = "McLightingRGBW"; // Friedly hostname is configurable just for the start
|
||||
|
||||
#define ENABLE_OTA 1 // If defined, enable Arduino OTA code. If set to 0 enable Arduino OTA code, if set to 1 enable ESP8266HTTPUpdateServer OTA code.
|
||||
#define ENABLE_MQTT 1 // If defined use MQTT OR AMQTT, if set to 0 enable MQTT client code, see: https://github.com/toblum/McLighting/wiki/MQTT-API, if set to 1, enable Async MQTT code, see: https://github.com/marvinroger/async-mqtt-client
|
||||
#define ENABLE_MQTT 0 // If defined use MQTT OR AMQTT, if set to 0 enable MQTT client code, see: https://github.com/toblum/McLighting/wiki/MQTT-API, if set to 1, enable Async MQTT code, see: https://github.com/marvinroger/async-mqtt-client
|
||||
//#define ENABLE_MQTT_HOSTNAME_CHIPID // Uncomment/comment to add ESPChipID to end of MQTT hostname
|
||||
#define ENABLE_HOMEASSISTANT // If defined, enable Homeassistant integration, ENABLE_MQTT must be active
|
||||
#define MQTT_HOME_ASSISTANT_SUPPORT // If defined, use AMQTT and select Tools -> IwIP Variant -> Higher Bandwidth
|
||||
@@ -30,13 +31,12 @@ char HOSTNAME[65] = "McLightingRGBW_02"; // Friedly hostname is configurable
|
||||
#if defined(ENABLE_E131)
|
||||
#define MULTICAST false
|
||||
#define START_UNIVERSE 1 // First DMX Universe to listen for
|
||||
#define END_UNIVERSE 2 // Total number of Universes to listen for, starting at UNIVERSE
|
||||
// MUST: END_UNIVERSE >= START_UNIVERSE
|
||||
uint8_t END_UNIVERSE = 1; // Total number of Universes to listen for, starting at UNIVERSE
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_REMOTE)
|
||||
int selected_color = 1;
|
||||
int chng = 1;
|
||||
uint8_t selected_color = 1;
|
||||
uint64_t last_remote_cmd;
|
||||
enum RMT_BTN {ON_OFF, MODE_UP, MODE_DOWN, RED_UP, RED_DOWN, GREEN_UP, GREEN_DOWN, BLUE_UP, BLUE_DOWN, WHITE_UP, WHITE_DOWN, BRIGHTNESS_UP, BRIGHTNESS_DOWN, SPEED_UP, SPEED_DOWN, COL_M, COL_B, COL_X, AUTOMODE, CUST_1, CUST_2, CUST_3, CUST_4, CUST_5, REPEATCMD, BTN_CNT};
|
||||
// Change your IR Commands here. You can see them in console, after you pressed a button on the remote
|
||||
@@ -86,13 +86,14 @@ uint32_t autoParams[][6] = { // main_color, back_color, xtra_color, speed, mod
|
||||
#if defined(ENABLE_MQTT)
|
||||
char mqtt_buf[80];
|
||||
char mqtt_will_topic[sizeof(HOSTNAME) + 7]; // Topic 'will' will be:HOSTNAME "/status";
|
||||
char mqtt_will_payload[] = "ONLINE";
|
||||
const char mqtt_will_payload[] = "OFFLINE";
|
||||
char mqtt_intopic[sizeof(HOSTNAME) + 3]; // Topic 'in' will be: <HOSTNAME>/in
|
||||
char mqtt_outtopic[sizeof(HOSTNAME) + 4]; // Topic 'out' will be: <HOSTNAME>/out
|
||||
bool mqtt_lwt_boot_flag = true;
|
||||
#if ENABLE_MQTT == 0
|
||||
#define MQTT_MAX_PACKET_SIZE 512
|
||||
#define MQTT_MAX_RECONNECT_TRIES 4
|
||||
int mqtt_reconnect_retries = 0;
|
||||
uint8_t mqtt_reconnect_retries = 0;
|
||||
uint8_t qossub = 0; // PubSubClient can sub qos 0 or 1
|
||||
#endif
|
||||
|
||||
@@ -133,14 +134,14 @@ uint32_t autoParams[][6] = { // main_color, back_color, xtra_color, speed, mod
|
||||
MODE mode = SET_ALL; // Standard mode that is active when software starts
|
||||
MODE prevmode = mode;
|
||||
|
||||
int ws2812fx_speed = 196; // Global variable for storing the delay between color changes --> smaller == faster
|
||||
int brightness = 196; // Global variable for storing the brightness (255 == 100%)
|
||||
uint8_t ws2812fx_speed = 196; // Global variable for storing the delay between color changes --> smaller == faster
|
||||
uint8_t brightness = 196; // Global variable for storing the brightness (255 == 100%)
|
||||
|
||||
int ws2812fx_mode = 0; // Global variable for storing the WS2812FX modes
|
||||
uint8_t ws2812fx_mode = 0; // Global variable for storing the WS2812FX modes
|
||||
|
||||
bool shouldSaveConfig = false; // For WiFiManger custom config
|
||||
|
||||
uint32_t hex_colors[3] = {}; // Color array for setting WS2812FX
|
||||
uint32_t hex_colors[3] = {}; // Color array for setting WS2812FX
|
||||
struct ledstate // Data structure to store a state of a single led
|
||||
{
|
||||
uint8_t red;
|
||||
@@ -149,8 +150,8 @@ struct ledstate // Data structure to store a state of a single le
|
||||
uint8_t white;
|
||||
};
|
||||
|
||||
typedef struct ledstate LEDState; // Define the datatype LEDState
|
||||
LEDState ledstates[NUMLEDS]; // Get an array of led states to store the state of the whole strip
|
||||
typedef struct ledstate LEDState; // Define the datatype LEDState
|
||||
uint8_t* ledstates; // Set a pointer to get an array of led states to store the state of the whole strip
|
||||
LEDState main_color = { 255, 0, 0, 0 }; // Store the "main color" of the strip used in single color modes
|
||||
LEDState back_color = { 0, 0, 0, 0 }; // Store the "2nd color" of the strip used in single color modes
|
||||
LEDState xtra_color = { 0, 0, 0, 0 }; // Store the "3rd color" of the strip used in single color modes
|
||||
|
||||
+1663
-1647
File diff suppressed because it is too large
Load Diff
@@ -9,8 +9,6 @@ More info on how to create custom aniamtions for WS2812FX: https://github.com/ki
|
||||
|
||||
#include <FastLED.h> //https://github.com/FastLED/FastLED
|
||||
|
||||
byte* heat;
|
||||
|
||||
/*
|
||||
* paste in the Fire2012 code with a small edit at the end which uses the
|
||||
* setPixelColor() function to copy the color data to the ws2812fx instance.
|
||||
@@ -60,31 +58,31 @@ void Fire2012() {
|
||||
// Array of temperature readings at each simulation cell
|
||||
|
||||
// Step 1. Cool down every cell a little
|
||||
for( int i = 0; i < WS2812FXStripSettings.stripSize; i++) {
|
||||
heat[i] = qsub8( heat[i], random8(0, ((COOLING * 10) / WS2812FXStripSettings.stripSize) + 2));
|
||||
for( uint16_t i = 0; i < WS2812FXStripSettings.stripSize; i++) {
|
||||
ledstates[i] = qsub8( ledstates[i], random8(0, ((COOLING * 10) / WS2812FXStripSettings.stripSize) + 2));
|
||||
}
|
||||
|
||||
// Step 2. Heat from each cell drifts 'up' and diffuses a little
|
||||
for( int k= WS2812FXStripSettings.stripSize - 1; k >= 2; k--) {
|
||||
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
|
||||
for( uint16_t k= WS2812FXStripSettings.stripSize - 1; k >= 2; k--) {
|
||||
ledstates[k] = (ledstates[k - 1] + ledstates[k - 2] + ledstates[k - 2]) / 3;
|
||||
}
|
||||
|
||||
// Step 3. Randomly ignite new 'sparks' of heat near the bottom
|
||||
if( random8() < SPARKING ) {
|
||||
int y = random8(7);
|
||||
heat[y] = qadd8( heat[y], random8(160,255) );
|
||||
uint8_t y = random8(7);
|
||||
ledstates[y] = qadd8(ledstates[y], random8(160,255) );
|
||||
}
|
||||
|
||||
// Step 4. Map from heat cells to LED colors
|
||||
for( int j = 0; j < WS2812FXStripSettings.stripSize; j++) {
|
||||
CRGB color = HeatColor( heat[j]);
|
||||
int pixelnumber;
|
||||
for( uint16_t j = 0; j < WS2812FXStripSettings.stripSize; j++) {
|
||||
CRGB color = HeatColor( ledstates[j]);
|
||||
uint16_t pixelnumber;
|
||||
if( gReverseDirection ) {
|
||||
pixelnumber = (WS2812FXStripSettings.stripSize - 1) - j;
|
||||
} else {
|
||||
pixelnumber = j;
|
||||
}
|
||||
strip->setPixelColor(pixelnumber, color.red, color.green, color.blue);
|
||||
strip->setPixelColor(pixelnumber, color.red, color.green, color.blue, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ uint8_t twitch = 50;
|
||||
uint8_t dipCount = 0;
|
||||
uint8_t analogLevel = 100;
|
||||
boolean timeToDip = false;
|
||||
uint8_t* ledStates;
|
||||
|
||||
|
||||
void hsb2rgbAN1(uint16_t index, uint8_t sat, uint8_t bright, uint8_t myled) {
|
||||
@@ -29,10 +28,10 @@ void hsb2rgbAN1(uint16_t index, uint8_t sat, uint8_t bright, uint8_t myled) {
|
||||
|
||||
|
||||
void updateLed (uint16_t led, uint8_t brightness) {
|
||||
ledStates[led] = brightness;
|
||||
for (int i=0; i<WS2812FXStripSettings.stripSize; i++) {
|
||||
ledstates[led] = brightness;
|
||||
for (uint16_t i=0; i<WS2812FXStripSettings.stripSize; i++) {
|
||||
uint16_t index = (i%3 == 0) ? 400 : random(0,767);
|
||||
hsb2rgbAN1(index, 200, ledStates[i], i);
|
||||
hsb2rgbAN1(index, 200, ledstates[i], i);
|
||||
}
|
||||
strip->show();
|
||||
}
|
||||
@@ -50,7 +49,7 @@ void handleTV() {
|
||||
dipCount = dipCount++;
|
||||
}
|
||||
if(currentMillis-previousMillis<twitch) {
|
||||
led=random(0, (strip->numPixels()-1));
|
||||
led=random(0, WS2812FXStripSettings.stripSize - 1);
|
||||
analogLevel=random(50,255);// set the range of the 3 pwm leds
|
||||
ledState = ledState == LOW ? HIGH: LOW; // if the LED is off turn it on and vice-versa:
|
||||
updateLed(led, (ledState) ? 255 : 0);
|
||||
@@ -67,12 +66,12 @@ void handleTV() {
|
||||
DBG_OUTPUT_PORT.println("Dip Time");
|
||||
currentDipTime = millis();
|
||||
if (currentDipTime - dipStartTime < darkTime) {
|
||||
for (int i=3; i<strip->numPixels(); i++) {
|
||||
for (uint16_t i=3; i<WS2812FXStripSettings.stripSize; i++) {
|
||||
updateLed(i, 0);
|
||||
}
|
||||
} else {
|
||||
timeToDip = false;
|
||||
}
|
||||
strip->show();
|
||||
//strip->show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,10 +208,11 @@ void handleSetSingleLED(uint8_t * mypayload, uint8_t firstChar = 0) {
|
||||
// decode led index
|
||||
char templed[3];
|
||||
strncpy (templed, (const char *) &mypayload[firstChar], 2 );
|
||||
templed[2] = 0x00;
|
||||
uint8_t led = atoi(templed);
|
||||
|
||||
DBG_OUTPUT_PORT.printf("led value: [%i]. Entry threshold: <= [%i] (=> %s)\r\n", led, strip->numPixels(), mypayload );
|
||||
if (led <= strip->numPixels()) {
|
||||
DBG_OUTPUT_PORT.printf("led value: [%i]. Entry threshold: <= [%i] (=> %s)\r\n", led, WS2812FXStripSettings.stripSize, mypayload );
|
||||
if (led <= WS2812FXStripSettings.stripSize) {
|
||||
char redhex[3];
|
||||
char greenhex[3];
|
||||
char bluehex[3];
|
||||
@@ -223,6 +224,8 @@ void handleSetSingleLED(uint8_t * mypayload, uint8_t firstChar = 0) {
|
||||
redhex[2] = 0x00;
|
||||
greenhex[2] = 0x00;
|
||||
bluehex[2] = 0x00;
|
||||
whitehex[2] = 0x00;
|
||||
/*
|
||||
ledstates[led].red = strtol(redhex, NULL, 16);
|
||||
ledstates[led].green = strtol(greenhex, NULL, 16);
|
||||
ledstates[led].blue = strtol(bluehex, NULL, 16);
|
||||
@@ -231,6 +234,16 @@ void handleSetSingleLED(uint8_t * mypayload, uint8_t firstChar = 0) {
|
||||
DBG_OUTPUT_PORT.printf("rgb.red: [%i] rgb.green: [%i] rgb.blue: [%i] rgb.white: [%i]\r\n", strtol(redhex, NULL, 16), strtol(greenhex, NULL, 16), strtol(bluehex, NULL, 16), strtol(whitehex, NULL, 16));
|
||||
DBG_OUTPUT_PORT.printf("WS: Set single led [%i] to [%i] [%i] [%i] [%i] (%s)!\r\n", led, ledstates[led].red, ledstates[led].green, ledstates[led].blue, ledstates[led].white, mypayload);
|
||||
strip->setPixelColor(led, ledstates[led].red, ledstates[led].green, ledstates[led].blue, ledstates[led].white);
|
||||
*/
|
||||
LEDState color;
|
||||
color.red = strtol(redhex, NULL, 16);
|
||||
color.green = strtol(greenhex, NULL, 16);
|
||||
color.blue = strtol(bluehex, NULL, 16);
|
||||
color.white = strtol(whitehex, NULL, 16);
|
||||
//DBG_OUTPUT_PORT.printf("rgb.red: [%s] rgb.green: [%s] rgb.blue: [%s] rgb.white: [%s]\r\n", redhex, greenhex, bluehex, whitehex);
|
||||
//DBG_OUTPUT_PORT.printf("rgb.red: [%i] rgb.green: [%i] rgb.blue: [%i] rgb.white: [%i]\r\n", strtol(redhex, NULL, 16), strtol(greenhex, NULL, 16), strtol(bluehex, NULL, 16), strtol(whitehex, NULL, 16));
|
||||
//DBG_OUTPUT_PORT.printf("WS: Set single led [%i] to [%i] [%i] [%i] [%i] (%s)!\r\n", led, color.red, color.green, color.blue, color.white, mypayload);
|
||||
strip->setPixelColor(led, color.red, color.green, color.blue, color.white);
|
||||
strip->show();
|
||||
}
|
||||
mode = CUSTOM;
|
||||
@@ -252,26 +265,22 @@ void handleRangeDifferentColors(uint8_t * mypayload) {
|
||||
|
||||
while (nextCommand) {
|
||||
// Loop for each LED.
|
||||
char startled[4] = { 0, 0, 0 };
|
||||
char endled[4] = { 0, 0, 0 };
|
||||
char colorval[9] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
char startled[4];
|
||||
char endled[4];
|
||||
char colorval[9];
|
||||
strncpy ( startled, (const char *) &nextCommand[0], 2 );
|
||||
startled[3] = 0x00;
|
||||
strncpy ( endled, (const char *) &nextCommand[2], 2 );
|
||||
endled[3] = 0x00;
|
||||
strncpy ( colorval, (const char *) &nextCommand[4], 8 );
|
||||
int rangebegin = atoi(startled);
|
||||
int rangeend = atoi(endled);
|
||||
colorval[8] = 0x00;
|
||||
uint8_t rangebegin = atoi(startled);
|
||||
uint8_t rangeend = atoi(endled);
|
||||
DBG_OUTPUT_PORT.printf("Setting RANGE from [%i] to [%i] as color [%s] \r\n", rangebegin, rangeend, colorval);
|
||||
|
||||
while ( rangebegin <= rangeend ) {
|
||||
char rangeData[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
if ( rangebegin < 10 ) {
|
||||
// Create the valid 'nextCommand' structure
|
||||
snprintf(rangeData, sizeof(rangeData), "0%d%s", rangebegin, colorval);
|
||||
}
|
||||
if ( rangebegin >= 10 ) {
|
||||
// Create the valid 'nextCommand' structure
|
||||
snprintf(rangeData, sizeof(rangeData), "%d%s", rangebegin, colorval);
|
||||
}
|
||||
char rangeData[11];
|
||||
snprintf(rangeData, sizeof(rangeData), "%02d%s", rangebegin, colorval);
|
||||
// Set one LED
|
||||
handleSetSingleLED((uint8_t*) rangeData, 0);
|
||||
rangebegin++;
|
||||
@@ -292,9 +301,9 @@ bool checkPin(uint8_t pin) {
|
||||
|
||||
|
||||
neoPixelType checkRGBOrder(char rgbOrder[5]) {
|
||||
for( int i=0 ; i < sizeof(rgbOrder) ; ++i ) rgbOrder[i] = toupper(rgbOrder[i]) ;
|
||||
for( uint8_t i=0 ; i < sizeof(rgbOrder) ; ++i ) rgbOrder[i] = toupper(rgbOrder[i]) ;
|
||||
DBG_OUTPUT_PORT.printf("Checking RGB Order: %s ...", rgbOrder);
|
||||
neoPixelType returnOrder;
|
||||
neoPixelType returnOrder = 0;
|
||||
if (strcmp(rgbOrder, "GRB") == 0) {
|
||||
returnOrder = NEO_GRB;
|
||||
} else if (strcmp(rgbOrder, "GBR") == 0) {
|
||||
@@ -357,7 +366,14 @@ neoPixelType checkRGBOrder(char rgbOrder[5]) {
|
||||
returnOrder = NEO_BGRW;
|
||||
} else {
|
||||
DBG_OUTPUT_PORT.print("invalid input!");
|
||||
returnOrder = static_cast<neoPixelType>(checkRGBOrder(WS2812FXStripSettings.RGBOrder));
|
||||
uint16_t check = checkRGBOrder(WS2812FXStripSettings.RGBOrder);
|
||||
if (check != 0) {
|
||||
returnOrder = static_cast<neoPixelType>(check);
|
||||
strcpy(rgbOrder, WS2812FXStripSettings.RGBOrder);
|
||||
} else {
|
||||
returnOrder = static_cast<neoPixelType>(checkRGBOrder(RGBORDER));
|
||||
strcpy(rgbOrder, RGBORDER);
|
||||
}
|
||||
}
|
||||
DBG_OUTPUT_PORT.println("success!");
|
||||
strcpy(WS2812FXStripSettings.RGBOrder, rgbOrder);
|
||||
@@ -374,12 +390,12 @@ bool setConfByConfString(String saved_conf_string) {
|
||||
getValue(saved_conf_string, '|', 4).toCharArray(mqtt_user, 32);
|
||||
getValue(saved_conf_string, '|', 5).toCharArray(mqtt_pass, 32);
|
||||
#endif
|
||||
WS2812FXStripSettings.stripSize = getValue(saved_conf_string, '|', 6).toInt();
|
||||
WS2812FXStripSettings.stripSize = constrain(getValue(saved_conf_string, '|', 6).toInt(), 1, MAXLEDS);
|
||||
checkPin(getValue(saved_conf_string, '|', 7).toInt());
|
||||
char tmp_rgbOrder[5];
|
||||
getValue(saved_conf_string, '|', 8).toCharArray(tmp_rgbOrder, 4);
|
||||
checkRGBOrder(tmp_rgbOrder);
|
||||
WS2812FXStripSettings.fxoptions = getValue(saved_conf_string, '|', 9).toInt();
|
||||
WS2812FXStripSettings.fxoptions = constrain(((getValue(saved_conf_string, '|', 9).toInt()>>1)<<1), 0, 255);
|
||||
return true;
|
||||
} else {
|
||||
DBG_OUTPUT_PORT.println("Saved conf not found!");
|
||||
@@ -513,6 +529,9 @@ void handleSetWS2812FXMode(uint8_t * mypayload) {
|
||||
mode = E131;
|
||||
}
|
||||
#endif
|
||||
if (strcmp((char *) &mypayload[1], "custom") == 0) {
|
||||
mode = CUSTOM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -602,6 +621,9 @@ String listModesJSON() {
|
||||
objecte131["mode"] = "e131";
|
||||
objecte131["name"] = "E131";
|
||||
#endif
|
||||
JsonObject objectcustom = root.createNestedObject();
|
||||
objectcustom["mode"] = "custom";
|
||||
objectcustom["name"] = "CUSTOM WS";
|
||||
for (uint8_t i = 0; i < strip->getModeCount(); i++) {
|
||||
JsonObject object = root.createNestedObject();
|
||||
object["mode"] = i;
|
||||
@@ -665,7 +687,7 @@ void handleNotFound() {
|
||||
// Functions and variables for automatic cycling
|
||||
// ***************************************************************************
|
||||
Ticker autoTicker;
|
||||
int autoCount = 0;
|
||||
uint8_t autoCount = 0;
|
||||
|
||||
void autoTick() {
|
||||
uint32_t setcolors[] = {autoParams[autoCount][0],autoParams[autoCount][1],autoParams[autoCount][2]};
|
||||
@@ -793,10 +815,10 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) {
|
||||
DBG_OUTPUT_PORT.print("MQTT: ");
|
||||
#if defined(ENABLE_MQTT)
|
||||
#if ENABLE_MQTT == 0
|
||||
mqtt_client->publish(mqtt_outtopic, json.c_str());
|
||||
mqtt_client.publish(mqtt_outtopic, json.c_str());
|
||||
#endif
|
||||
#if ENABLE_MQTT == 1
|
||||
mqtt_client->publish(mqtt_outtopic, qospub, false, json.c_str());
|
||||
mqtt_client.publish(mqtt_outtopic, qospub, false, json.c_str());
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
@@ -816,18 +838,21 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) {
|
||||
if (payload[2] == 'c') {
|
||||
char tmp_count[6];
|
||||
snprintf(tmp_count, sizeof(tmp_count), "%s", &payload[3]);
|
||||
WS2812FXStripSettings.stripSize = constrain(atoi(tmp_count), 0, 65535);
|
||||
tmp_count[5] = 0x00;
|
||||
WS2812FXStripSettings.stripSize = constrain(atoi(tmp_count), 1, MAXLEDS);
|
||||
updateStrip = true;
|
||||
}
|
||||
if (payload[2] == 'r') {
|
||||
char tmp_rgbOrder[5];
|
||||
snprintf(tmp_rgbOrder, sizeof(tmp_rgbOrder), "%s", &payload[3]);
|
||||
tmp_rgbOrder[4] = 0x00;
|
||||
checkRGBOrder(tmp_rgbOrder);
|
||||
updateStrip=true;
|
||||
}
|
||||
#if !defined(USE_WS2812FX_DMA)
|
||||
if (payload[2] == 'p') {
|
||||
char tmp_pin[3];
|
||||
tmp_pin[2] = 0x00;
|
||||
snprintf(tmp_pin, sizeof(tmp_pin), "%s", &payload[3]);
|
||||
checkPin(atoi(tmp_pin));
|
||||
updateStrip = true;
|
||||
@@ -837,7 +862,8 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) {
|
||||
if (payload[2] == 'o') {
|
||||
char tmp_fxoptions[4];
|
||||
snprintf(tmp_fxoptions, sizeof(tmp_fxoptions), "%s", &payload[3]);
|
||||
WS2812FXStripSettings.fxoptions = constrain(atoi(tmp_fxoptions), 0, 255);
|
||||
tmp_fxoptions[3] = 0x00;
|
||||
WS2812FXStripSettings.fxoptions = ((constrain(atoi(tmp_fxoptions), 0, 255)>>1)<<1);
|
||||
updateStrip = true;
|
||||
}
|
||||
}
|
||||
@@ -886,6 +912,7 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) {
|
||||
#else
|
||||
snprintf(last_conf, sizeof(last_conf), "CNF|%64s|%64s|%5d|%32s|%32s|%4d|%2d|%4s|%3d", HOSTNAME, "", "", "", "", WS2812FXStripSettings.stripSize, WS2812FXStripSettings.pin, WS2812FXStripSettings.RGBOrder, WS2812FXStripSettings.fxoptions);
|
||||
#endif
|
||||
last_conf[sizeof(last_conf)-1]= 0x00;
|
||||
writeEEPROM(0, 222, last_conf);
|
||||
EEPROM.commit();
|
||||
}
|
||||
@@ -896,10 +923,10 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) {
|
||||
DBG_OUTPUT_PORT.print("MQTT: ");
|
||||
#if defined(ENABLE_MQTT)
|
||||
#if ENABLE_MQTT == 0
|
||||
mqtt_client->publish(mqtt_outtopic, json.c_str());
|
||||
mqtt_client.publish(mqtt_outtopic, json.c_str());
|
||||
#endif
|
||||
#if ENABLE_MQTT == 1
|
||||
mqtt_client->publish(mqtt_outtopic, qospub, false, json.c_str());
|
||||
mqtt_client.publish(mqtt_outtopic, qospub, false, json.c_str());
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
@@ -918,17 +945,14 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) {
|
||||
if (mqtt == true) {
|
||||
DBG_OUTPUT_PORT.print("MQTT: ");
|
||||
#if defined(ENABLE_MQTT)
|
||||
#if ENABLE_MQTT == 0
|
||||
String json = listModesJSON();
|
||||
unsigned int msg_len = measureJson(json) + 1;
|
||||
char buffer[msg_len];
|
||||
serializeJson(json, buffer, sizeof(buffer));
|
||||
mqtt_client->beginPublish(mqtt_outtopic, msg_len, true);
|
||||
mqtt_client->write((const uint8_t*)buffer, msg_len);
|
||||
mqtt_client->endPublish();
|
||||
#if ENABLE_MQTT == 2
|
||||
uint16_t msg_len = strlen(json.c_str()) + 1;
|
||||
mqtt_client.beginPublish(mqtt_outtopic, msg_len, true);
|
||||
mqtt_client.write((const uint8_t*)json.c_str(), msg_len);
|
||||
mqtt_client.endPublish();
|
||||
#endif
|
||||
#if ENABLE_MQTT == 1
|
||||
mqtt_client->publish(mqtt_outtopic, qospub, false, json.c_str());
|
||||
mqtt_client.publish(mqtt_outtopic, qospub, false, json.c_str());
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
@@ -996,8 +1020,8 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
||||
new_ha_mqtt_msg = true;
|
||||
}
|
||||
|
||||
LEDState temp2rgb(unsigned int kelvin) {
|
||||
int tmp_internal = kelvin / 100.0;
|
||||
LEDState temp2rgb(uint16_t kelvin) {
|
||||
uint16_t tmp_internal = kelvin / 100.0;
|
||||
LEDState tmp_color;
|
||||
|
||||
// red
|
||||
@@ -1102,11 +1126,11 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
||||
serializeJson(root, buffer, sizeof(buffer));
|
||||
jsonBuffer.clear();
|
||||
#if ENABLE_MQTT == 0
|
||||
mqtt_client->publish(mqtt_ha_state_out, buffer, true);
|
||||
mqtt_client.publish(mqtt_ha_state_out, buffer, true);
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Send [%s]: %s\r\n", mqtt_ha_state_out, buffer);
|
||||
#endif
|
||||
#if ENABLE_MQTT == 1
|
||||
mqtt_client->publish(mqtt_ha_state_out, 1, true, buffer);
|
||||
mqtt_client.publish(mqtt_ha_state_out, 1, true, buffer);
|
||||
DBG_OUTPUT_PORT.printf("MQTT: Send [%s]: %s\r\n", mqtt_ha_state_out, buffer);
|
||||
#endif
|
||||
new_ha_mqtt_msg = false;
|
||||
@@ -1175,7 +1199,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
||||
if (root.containsKey("color_temp")) {
|
||||
//temp comes in as mireds, need to convert to kelvin then to RGB
|
||||
color_temp = (uint16_t) root["color_temp"];
|
||||
unsigned int kelvin = 1000000 / color_temp;
|
||||
uint16_t kelvin = 1000000 / color_temp;
|
||||
main_color = temp2rgb(kelvin);
|
||||
mode = SET_COLOR;
|
||||
}
|
||||
@@ -1232,7 +1256,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
||||
#endif
|
||||
|
||||
#if ENABLE_MQTT == 0
|
||||
void mqtt_callback(char* topic, byte* payload_in, unsigned int length) {
|
||||
void mqtt_callback(char* topic, byte* payload_in, uint16_t length) {
|
||||
uint8_t * payload = (uint8_t *)malloc(length + 1);
|
||||
memcpy(payload, payload_in, length);
|
||||
payload[length] = 0;
|
||||
@@ -1259,22 +1283,27 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
||||
#if ENABLE_MQTT == 0
|
||||
void mqtt_reconnect() {
|
||||
// Loop until we're reconnected
|
||||
while (!mqtt_client->connected() && mqtt_reconnect_retries < MQTT_MAX_RECONNECT_TRIES) {
|
||||
while (!mqtt_client.connected() && mqtt_reconnect_retries < MQTT_MAX_RECONNECT_TRIES) {
|
||||
mqtt_reconnect_retries++;
|
||||
DBG_OUTPUT_PORT.printf("Attempting MQTT connection %d / %d ...\r\n", mqtt_reconnect_retries, MQTT_MAX_RECONNECT_TRIES);
|
||||
// Attempt to connect
|
||||
if (mqtt_client->connect(mqtt_clientid, mqtt_user, mqtt_pass)) {
|
||||
if (mqtt_client.connect(mqtt_clientid, mqtt_user, mqtt_pass, mqtt_will_topic, 2, true, mqtt_will_payload, true)) {
|
||||
DBG_OUTPUT_PORT.println("MQTT connected!");
|
||||
// Once connected, publish an announcement...
|
||||
char * message = new char[18 + strlen(HOSTNAME) + 1];
|
||||
char message[18 + strlen(HOSTNAME) + 1];
|
||||
strcpy(message, "McLighting ready: ");
|
||||
strcat(message, HOSTNAME);
|
||||
mqtt_client->publish(mqtt_outtopic, message);
|
||||
mqtt_client.publish(mqtt_outtopic, message);
|
||||
// ... and resubscribe
|
||||
mqtt_client->subscribe(mqtt_intopic, qossub);
|
||||
mqtt_client.subscribe(mqtt_intopic, qossub);
|
||||
if(mqtt_lwt_boot_flag) {
|
||||
mqtt_client.publish(mqtt_will_topic, "ONLINE");
|
||||
//mqtt_lwt_boot_flag = false;
|
||||
}
|
||||
#if defined(ENABLE_HOMEASSISTANT)
|
||||
ha_send_data.detach();
|
||||
mqtt_client->subscribe(mqtt_ha_state_in, qossub);
|
||||
mqtt_client.subscribe(mqtt_ha_state_in, qossub);
|
||||
ha_send_data.once(5, tickerSendState);
|
||||
#if defined(MQTT_HOME_ASSISTANT_SUPPORT)
|
||||
const size_t bufferSize = JSON_ARRAY_SIZE(strip->getModeCount()+ 4) + JSON_OBJECT_SIZE(11) + 1500;
|
||||
DynamicJsonDocument jsonBuffer(bufferSize);
|
||||
@@ -1313,16 +1342,16 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
||||
// Following will never work for PubSubClient as message size > 1.6kB
|
||||
// char buffer[measureJson(json) + 1];
|
||||
// serializeJson(json, buffer, sizeof(buffer));
|
||||
// mqtt_client->publish(String("homeassistant/light/" + String(HOSTNAME) + "/config").c_str(), buffer, true);
|
||||
// mqtt_client.publish(String("homeassistant/light/" + String(HOSTNAME) + "/config").c_str(), buffer, true);
|
||||
|
||||
// Alternate way to publish large messages using PubSubClient
|
||||
unsigned int msg_len = measureJson(json) + 1;
|
||||
uint16_t msg_len = measureJson(json) + 1;
|
||||
char buffer[msg_len];
|
||||
serializeJson(json, buffer, sizeof(buffer));
|
||||
|
||||
mqtt_client->beginPublish(mqtt_ha_config, msg_len, true);
|
||||
mqtt_client->write((const uint8_t*)buffer, msg_len);
|
||||
mqtt_client->endPublish();
|
||||
DBG_OUTPUT_PORT.println(buffer);
|
||||
mqtt_client.beginPublish(String("homeassistant/light/" + String(HOSTNAME) + "/config").c_str(), msg_len-1, true);
|
||||
mqtt_client.write((const uint8_t*)buffer, msg_len-1);
|
||||
mqtt_client.endPublish();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1330,7 +1359,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
||||
DBG_OUTPUT_PORT.printf("MQTT topic out: %s\r\n", mqtt_outtopic);
|
||||
} else {
|
||||
DBG_OUTPUT_PORT.print("failed, rc=");
|
||||
DBG_OUTPUT_PORT.print(mqtt_client->state());
|
||||
DBG_OUTPUT_PORT.print(mqtt_client.state());
|
||||
DBG_OUTPUT_PORT.println(" try again in 5 seconds");
|
||||
// Wait 5 seconds before retrying
|
||||
delay(5000);
|
||||
@@ -1351,7 +1380,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
||||
|
||||
void connectToMqtt() {
|
||||
DBG_OUTPUT_PORT.println("Connecting to MQTT...");
|
||||
mqtt_client->connect();
|
||||
mqtt_client.connect();
|
||||
}
|
||||
|
||||
void onWifiConnect(const WiFiEventStationModeGotIP& event) {
|
||||
@@ -1372,16 +1401,20 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
||||
DBG_OUTPUT_PORT.println("Connected to MQTT.");
|
||||
DBG_OUTPUT_PORT.print("Session present: ");
|
||||
DBG_OUTPUT_PORT.println(sessionPresent);
|
||||
char * message = new char[18 + strlen(HOSTNAME) + 1];
|
||||
char message[18 + strlen(HOSTNAME) + 1];
|
||||
strcpy(message, "McLighting ready: ");
|
||||
strcat(message, HOSTNAME);
|
||||
mqtt_client->publish(mqtt_outtopic, qospub, false, message);
|
||||
mqtt_client.publish(mqtt_outtopic, qospub, false, message);
|
||||
//Subscribe
|
||||
uint16_t packetIdSub1 = mqtt_client->subscribe((char *)mqtt_intopic, qossub);
|
||||
uint16_t packetIdSub1 = mqtt_client.subscribe(mqtt_intopic, qossub);
|
||||
DBG_OUTPUT_PORT.printf("Subscribing at QoS %d, packetId: ", qossub); DBG_OUTPUT_PORT.println(packetIdSub1);
|
||||
if(mqtt_lwt_boot_flag) {
|
||||
mqtt_client.publish(mqtt_will_topic, qospub, false, "ONLINE");
|
||||
mqtt_lwt_boot_flag = false;
|
||||
}
|
||||
#if defined(ENABLE_HOMEASSISTANT)
|
||||
ha_send_data.detach();
|
||||
uint16_t packetIdSub2 = mqtt_client->subscribe((char *)mqtt_ha_state_in, qossub);
|
||||
uint16_t packetIdSub2 = mqtt_client.subscribe((char *)mqtt_ha_state_in, qossub);
|
||||
DBG_OUTPUT_PORT.printf("Subscribing at QoS %d, packetId: ", qossub); DBG_OUTPUT_PORT.println(packetIdSub2);
|
||||
#if defined(MQTT_HOME_ASSISTANT_SUPPORT)
|
||||
const size_t bufferSize = JSON_ARRAY_SIZE(strip->getModeCount()+ 4) + JSON_OBJECT_SIZE(11) + 1500;
|
||||
@@ -1421,7 +1454,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
||||
char buffer[measureJson(json) + 1];
|
||||
serializeJson(json, buffer, sizeof(buffer));
|
||||
jsonBuffer.clear();
|
||||
mqtt_client->publish(mqtt_ha_config, qospub, true, buffer);
|
||||
mqtt_client.publish(mqtt_ha_config, qospub, true, buffer);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@@ -1627,13 +1660,13 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
||||
strcpy(mqtt_user, json["mqtt_user"]);
|
||||
strcpy(mqtt_pass, json["mqtt_pass"]);
|
||||
#endif
|
||||
WS2812FXStripSettings.stripSize = (uint8_t) json["ws_cnt"];
|
||||
WS2812FXStripSettings.stripSize = constrain ((uint8_t) json["ws_cnt"], 1, MAXLEDS);
|
||||
char tmp_rgbOrder[5];
|
||||
strcpy(tmp_rgbOrder, json["ws_rgbo"]);
|
||||
checkRGBOrder(tmp_rgbOrder);
|
||||
uint8_t temp_pin;
|
||||
WS2812FXStripSettings.pin = (uint8_t) json["ws_pin"];
|
||||
WS2812FXStripSettings.fxoptions = (uint8_t) json["ws_fxopt"];
|
||||
WS2812FXStripSettings.pin = checkPin((uint8_t) json["ws_pin"]);
|
||||
WS2812FXStripSettings.fxoptions = ((constrain((uint8_t) json["ws_fxopt"], 0, 255)>>1)<<1);
|
||||
jsonBuffer.clear();
|
||||
return true;
|
||||
} else {
|
||||
@@ -1740,9 +1773,9 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
||||
// ***************************************************************************
|
||||
// EEPROM helper
|
||||
// ***************************************************************************
|
||||
String readEEPROM(int offset, int len) {
|
||||
String readEEPROM(uint16_t offset, uint16_t len) {
|
||||
String res = "";
|
||||
for (int i = 0; i < len; ++i)
|
||||
for (uint16_t i = 0; i < len; ++i)
|
||||
{
|
||||
res += char(EEPROM.read(i + offset));
|
||||
//DBG_OUTPUT_PORT.println(char(EEPROM.read(i + offset)));
|
||||
@@ -1751,9 +1784,9 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
||||
return res;
|
||||
}
|
||||
|
||||
void writeEEPROM(int offset, int len, String value) {
|
||||
void writeEEPROM(uint16_t offset, uint16_t len, String value) {
|
||||
DBG_OUTPUT_PORT.printf("writeEEPROM(): %s\r\n", value.c_str());
|
||||
for (int i = 0; i < len; ++i)
|
||||
for (uint16_t i = 0; i < len; ++i)
|
||||
{
|
||||
if (i < value.length()) {
|
||||
EEPROM.write(i + offset, value[i]);
|
||||
@@ -1773,6 +1806,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
|
||||
// Request handler for IR remote support
|
||||
// ***************************************************************************
|
||||
void handleRemote() {
|
||||
uint8_t chng = 1;
|
||||
if (irrecv.decode(&results)) {
|
||||
DBG_OUTPUT_PORT.print("IR Code: 0x");
|
||||
DBG_OUTPUT_PORT.print(uint64ToString(results.value, HEX));
|
||||
@@ -1780,8 +1814,6 @@ void handleRemote() {
|
||||
if (results.value == rmt_commands[REPEATCMD]) { //Repeat
|
||||
results.value = last_remote_cmd;
|
||||
chng = 5;
|
||||
} else {
|
||||
chng = 1;
|
||||
}
|
||||
if (results.value == rmt_commands[ON_OFF]) { // ON/OFF TOGGLE
|
||||
last_remote_cmd = 0;
|
||||
|
||||
@@ -277,7 +277,7 @@
|
||||
if(server.hasArg("ws_cnt")){
|
||||
uint16_t pixelCt = server.arg("ws_cnt").toInt();
|
||||
if (pixelCt > 0) {
|
||||
WS2812FXStripSettings.stripSize = pixelCt;
|
||||
WS2812FXStripSettings.stripSize = constrain(pixelCt, 1, MAXLEDS);
|
||||
updateStrip = true;
|
||||
}
|
||||
}
|
||||
@@ -301,7 +301,7 @@
|
||||
#endif
|
||||
|
||||
if(server.hasArg("ws_fxopt")){
|
||||
WS2812FXStripSettings.fxoptions = server.arg("ws_fxopt").toInt();
|
||||
WS2812FXStripSettings.fxoptions = ((constrain(server.arg("ws_fxopt").toInt(), 0, 255)>>1)<<1);
|
||||
updateStrip = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define SKETCH_VERSION "2.2.2.rgbw.3c"
|
||||
#define SKETCH_VERSION "2.2.3.rgbw.3c"
|
||||
|
||||
@@ -129,4 +129,15 @@
|
||||
* 17 Mar 2019
|
||||
* adressed issue: #2
|
||||
* adressed issue: #3
|
||||
*
|
||||
* 18 Mar 2019
|
||||
* adressed issue: #6 (possibly affects R[r_start][r_end][hexrgb] [...]; +[numled][hexrgb]+[numled][hexrgb]+[numled][hexrgb] !<numled><hexrgb>)
|
||||
*
|
||||
* 19 Mar 2019
|
||||
* included custom mode in UI
|
||||
* adressed issue #4
|
||||
*
|
||||
* Version Bump to 2.2.3 rgbw 3colors
|
||||
* PubSubClient Bug fixes
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,674 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>SPIFFS Editor</title>
|
||||
<style type="text/css" media="screen">
|
||||
.contextMenu {
|
||||
z-index: 300;
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
border: 1px solid #444;
|
||||
background-color: #F5F5F5;
|
||||
display: none;
|
||||
box-shadow: 0 0 10px rgba( 0, 0, 0, .4 );
|
||||
font-size: 12px;
|
||||
font-family: sans-serif;
|
||||
font-weight:bold;
|
||||
}
|
||||
.contextMenu ul {
|
||||
list-style: none;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.contextMenu li {
|
||||
position: relative;
|
||||
min-width: 60px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.contextMenu span {
|
||||
color: #444;
|
||||
display: inline-block;
|
||||
padding: 6px;
|
||||
}
|
||||
.contextMenu li:hover { background: #444; }
|
||||
.contextMenu li:hover span { color: #EEE; }
|
||||
|
||||
.css-treeview ul, .css-treeview li {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.css-treeview input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.css-treeview {
|
||||
font: normal 11px Verdana, Arial, Sans-serif;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.css-treeview span {
|
||||
color: #00f;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.css-treeview span:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.css-treeview input + label + ul {
|
||||
margin: 0 0 0 22px;
|
||||
}
|
||||
|
||||
.css-treeview input ~ ul {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.css-treeview label, .css-treeview label::before {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.css-treeview input:disabled + label {
|
||||
cursor: default;
|
||||
opacity: .6;
|
||||
}
|
||||
|
||||
.css-treeview input:checked:not(:disabled) ~ ul {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.css-treeview label, .css-treeview label::before {
|
||||
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAACgCAYAAAAFOewUAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAApxJREFUeNrslM1u00AQgGdthyalFFOK+ClIIKQKyqUVQvTEE3DmAhLwAhU8QZoH4A2Q2gMSFace4MCtJ8SPBFwAkRuiHKpA6sRN/Lu7zG5i14kctaUqRGhGXnu9O/Pt7MzsMiklvF+9t2kWTDvyIrAsA0aKRRi1T0C/hJ4LUbt5/8rNpWVlp8RSr9J40b48fxFaTQ9+ft8EZ6MJYb0Ok+dnYGpmPgXwKIAvLx8vYXc5GdMAQJgQEkpjRTh36TS2U+DWW/D17WuYgm8pwJyY1npZsZKOxImOV1I/h4+O6vEg5GCZBpgmA6hX8wHKUHDRBXQYicQ4rlc3Tf0VMs8DHBS864F2YFspjgUYjKX/Az3gsdQd2eeBHwmdGWXHcgBGSkZXOXohcEXebRoQcAgjqediNY+AVyu3Z3sAKqfKoGMsewBeEIOPgQxxPJIjcGH6qtL/0AdADzKGnuuD+2tLK7Q8DhHHbOBW+KEzcHLuYc82MkEUekLiwuvVH+guQBQzOG4XdAb8EOcRcqQvDkY2iCLuxECJ43JobMXoutqGgDa2T7UqLKwt9KRyuxKVByqVXXqIoCCUCAqhUOioTWC7G4TQEOD0APy2/7G2Xpu1J4+lxeQ4TXBbITDpoVelRN/BVFbwu5oMMJUBhoXy5tmdRcMwymP2OLQaLjx9/vnBo6V3K6izATmSnMa0Dq7ferIohJhr1p01zrlz49rZF4OMs8JkX23vVQzYp+wbYGV/KpXKjvspl8tsIKCrMNAYFxj2GKS5ZWxg4ewKsJfaGMIY5KXqPz8LBBj6+yDvVP79+yDp/9F9oIx3OisHWwe7Oal0HxCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgwD8E/BZgAP0qhKj3rXO7AAAAAElFTkSuQmCC") no-repeat;
|
||||
}
|
||||
|
||||
.css-treeview label, .css-treeview span, .css-treeview label::before {
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.css-treeview label {
|
||||
background-position: 18px 0;
|
||||
}
|
||||
|
||||
.css-treeview label::before {
|
||||
content: "";
|
||||
width: 16px;
|
||||
margin: 0 22px 0 0;
|
||||
vertical-align: middle;
|
||||
background-position: 0 -32px;
|
||||
}
|
||||
|
||||
.css-treeview input:checked + label::before {
|
||||
background-position: 0 -16px;
|
||||
}
|
||||
|
||||
/* webkit adjacent element selector bugfix */
|
||||
@media screen and (-webkit-min-device-pixel-ratio:0)
|
||||
{
|
||||
.css-treeview{
|
||||
-webkit-animation: webkit-adjacent-element-selector-bugfix infinite 1s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes webkit-adjacent-element-selector-bugfix
|
||||
{
|
||||
from {
|
||||
padding: 0;
|
||||
}
|
||||
to {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#uploader {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height:28px;
|
||||
line-height: 24px;
|
||||
padding-left: 10px;
|
||||
background-color: #444;
|
||||
color:#EEE;
|
||||
}
|
||||
#tree {
|
||||
position: absolute;
|
||||
top: 28px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width:200px;
|
||||
padding: 8px;
|
||||
}
|
||||
#editor, #preview {
|
||||
position: absolute;
|
||||
top: 28px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 200px;
|
||||
}
|
||||
#preview {
|
||||
background-color: #EEE;
|
||||
padding:5px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function createFileUploader(element, tree, editor){
|
||||
var xmlHttp;
|
||||
var input = document.createElement("input");
|
||||
input.type = "file";
|
||||
input.multiple = false;
|
||||
input.name = "data";
|
||||
document.getElementById(element).appendChild(input);
|
||||
var path = document.createElement("input");
|
||||
path.id = "upload-path";
|
||||
path.type = "text";
|
||||
path.name = "path";
|
||||
path.defaultValue = "/";
|
||||
document.getElementById(element).appendChild(path);
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = 'Upload';
|
||||
document.getElementById(element).appendChild(button);
|
||||
var mkdir = document.createElement("button");
|
||||
mkdir.innerHTML = 'MkDir';
|
||||
document.getElementById(element).appendChild(mkdir);
|
||||
var mkfile = document.createElement("button");
|
||||
mkfile.innerHTML = 'MkFile';
|
||||
document.getElementById(element).appendChild(mkfile);
|
||||
|
||||
function httpPostProcessRequest(){
|
||||
if (xmlHttp.readyState == 4){
|
||||
if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
|
||||
else {
|
||||
tree.refreshPath(path.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
function createPath(p){
|
||||
xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = httpPostProcessRequest;
|
||||
var formData = new FormData();
|
||||
formData.append("path", p);
|
||||
xmlHttp.open("PUT", "/edit");
|
||||
xmlHttp.send(formData);
|
||||
}
|
||||
|
||||
mkfile.onclick = function(e){
|
||||
if(path.value.indexOf(".") === -1) return;
|
||||
createPath(path.value);
|
||||
editor.loadUrl(path.value);
|
||||
};
|
||||
mkdir.onclick = function(e){
|
||||
if(path.value.length < 2) return;
|
||||
var dir = path.value
|
||||
if(dir.indexOf(".") !== -1){
|
||||
if(dir.lastIndexOf("/") === 0) return;
|
||||
dir = dir.substring(0, dir.lastIndexOf("/"));
|
||||
}
|
||||
createPath(dir);
|
||||
};
|
||||
button.onclick = function(e){
|
||||
if(input.files.length === 0){
|
||||
return;
|
||||
}
|
||||
xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = httpPostProcessRequest;
|
||||
var formData = new FormData();
|
||||
formData.append("data", input.files[0], path.value);
|
||||
xmlHttp.open("POST", "/edit");
|
||||
xmlHttp.send(formData);
|
||||
}
|
||||
input.onchange = function(e){
|
||||
if(input.files.length === 0) return;
|
||||
var filename = input.files[0].name;
|
||||
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
|
||||
var name = /(.*)\.[^.]+$/.exec(filename)[1];
|
||||
if(typeof name !== undefined){
|
||||
if(name.length > 8) name = name.substring(0, 8);
|
||||
filename = name;
|
||||
}
|
||||
if(typeof ext !== undefined){
|
||||
if(ext === "html") ext = "htm";
|
||||
else if(ext === "jpeg") ext = "jpg";
|
||||
filename = filename + "." + ext;
|
||||
}
|
||||
if(path.value === "/" || path.value.lastIndexOf("/") === 0){
|
||||
path.value = "/"+filename;
|
||||
} else {
|
||||
path.value = path.value.substring(0, path.value.lastIndexOf("/")+1)+filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createTree(element, editor){
|
||||
var preview = document.getElementById("preview");
|
||||
var treeRoot = document.createElement("div");
|
||||
treeRoot.className = "css-treeview";
|
||||
document.getElementById(element).appendChild(treeRoot);
|
||||
|
||||
function loadDownload(path){
|
||||
document.getElementById('download-frame').src = path+"?download=true";
|
||||
}
|
||||
|
||||
function loadPreview(path){
|
||||
document.getElementById("editor").style.display = "none";
|
||||
preview.style.display = "block";
|
||||
preview.innerHTML = '<img src="'+path+'" style="max-width:100%; max-height:100%; margin:auto; display:block;" />';
|
||||
}
|
||||
|
||||
function fillFolderMenu(el, path){
|
||||
var list = document.createElement("ul");
|
||||
el.appendChild(list);
|
||||
var action = document.createElement("li");
|
||||
list.appendChild(action);
|
||||
var isChecked = document.getElementById(path).checked;
|
||||
var expnd = document.createElement("li");
|
||||
list.appendChild(expnd);
|
||||
if(isChecked){
|
||||
expnd.innerHTML = "<span>Collapse</span>";
|
||||
expnd.onclick = function(e){
|
||||
document.getElementById(path).checked = false;
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
var refrsh = document.createElement("li");
|
||||
list.appendChild(refrsh);
|
||||
refrsh.innerHTML = "<span>Refresh</span>";
|
||||
refrsh.onclick = function(e){
|
||||
var leaf = document.getElementById(path).parentNode;
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
} else {
|
||||
expnd.innerHTML = "<span>Expand</span>";
|
||||
expnd.onclick = function(e){
|
||||
document.getElementById(path).checked = true;
|
||||
var leaf = document.getElementById(path).parentNode;
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
}
|
||||
var upload = document.createElement("li");
|
||||
list.appendChild(upload);
|
||||
upload.innerHTML = "<span>Upload</span>";
|
||||
upload.onclick = function(e){
|
||||
var pathEl = document.getElementById("upload-path");
|
||||
if(pathEl){
|
||||
var subPath = pathEl.value;
|
||||
if(subPath.lastIndexOf("/") < 1) pathEl.value = path+subPath;
|
||||
else pathEl.value = path.substring(subPath.lastIndexOf("/"))+subPath;
|
||||
}
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
var delFile = document.createElement("li");
|
||||
list.appendChild(delFile);
|
||||
delFile.innerHTML = "<span>Delete</span>";
|
||||
delFile.onclick = function(e){
|
||||
httpDelete(path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
}
|
||||
|
||||
function fillFileMenu(el, path){
|
||||
var list = document.createElement("ul");
|
||||
el.appendChild(list);
|
||||
var action = document.createElement("li");
|
||||
list.appendChild(action);
|
||||
if(isTextFile(path)){
|
||||
action.innerHTML = "<span>Edit</span>";
|
||||
action.onclick = function(e){
|
||||
editor.loadUrl(path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
} else if(isImageFile(path)){
|
||||
action.innerHTML = "<span>Preview</span>";
|
||||
action.onclick = function(e){
|
||||
loadPreview(path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
}
|
||||
var download = document.createElement("li");
|
||||
list.appendChild(download);
|
||||
download.innerHTML = "<span>Download</span>";
|
||||
download.onclick = function(e){
|
||||
loadDownload(path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
var delFile = document.createElement("li");
|
||||
list.appendChild(delFile);
|
||||
delFile.innerHTML = "<span>Delete</span>";
|
||||
delFile.onclick = function(e){
|
||||
httpDelete(path);
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
|
||||
};
|
||||
}
|
||||
|
||||
function showContextMenu(e, path, isfile){
|
||||
var divContext = document.createElement("div");
|
||||
var scrollTop = document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop;
|
||||
var scrollLeft = document.body.scrollLeft ? document.body.scrollLeft : document.documentElement.scrollLeft;
|
||||
var left = e.clientX + scrollLeft;
|
||||
var top = e.clientY + scrollTop;
|
||||
divContext.className = 'contextMenu';
|
||||
divContext.style.display = 'block';
|
||||
divContext.style.left = left + 'px';
|
||||
divContext.style.top = top + 'px';
|
||||
if(isfile) fillFileMenu(divContext, path);
|
||||
else fillFolderMenu(divContext, path);
|
||||
document.body.appendChild(divContext);
|
||||
var width = divContext.offsetWidth;
|
||||
var height = divContext.offsetHeight;
|
||||
divContext.onmouseout = function(e){
|
||||
if(e.clientX < left || e.clientX > (left + width) || e.clientY < top || e.clientY > (top + height)){
|
||||
if(document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(divContext);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function createTreeLeaf(path, name, size){
|
||||
var leaf = document.createElement("li");
|
||||
leaf.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
|
||||
var label = document.createElement("span");
|
||||
label.textContent = name.toLowerCase();
|
||||
leaf.appendChild(label);
|
||||
leaf.onclick = function(e){
|
||||
if(isTextFile(leaf.id)){
|
||||
editor.loadUrl(leaf.id);
|
||||
} else if(isImageFile(leaf.id)){
|
||||
loadPreview(leaf.id);
|
||||
}
|
||||
};
|
||||
leaf.oncontextmenu = function(e){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
showContextMenu(e, leaf.id, true);
|
||||
};
|
||||
return leaf;
|
||||
}
|
||||
|
||||
function createTreeBranch(path, name, disabled){
|
||||
var leaf = document.createElement("li");
|
||||
var check = document.createElement("input");
|
||||
check.type = "checkbox";
|
||||
check.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
|
||||
if(typeof disabled !== "undefined" && disabled) check.disabled = "disabled";
|
||||
leaf.appendChild(check);
|
||||
var label = document.createElement("label");
|
||||
label.for = check.id;
|
||||
label.textContent = name.toLowerCase();
|
||||
leaf.appendChild(label);
|
||||
check.onchange = function(e){
|
||||
if(check.checked){
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, check.id);
|
||||
}
|
||||
};
|
||||
label.onclick = function(e){
|
||||
if(!check.checked){
|
||||
check.checked = true;
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, check.id);
|
||||
} else {
|
||||
check.checked = false;
|
||||
}
|
||||
};
|
||||
leaf.oncontextmenu = function(e){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
showContextMenu(e, check.id, false);
|
||||
}
|
||||
return leaf;
|
||||
}
|
||||
|
||||
function addList(parent, path, items){
|
||||
var list = document.createElement("ul");
|
||||
parent.appendChild(list);
|
||||
var ll = items.length;
|
||||
for(var i = 0; i < ll; i++){
|
||||
var item = items[i];
|
||||
var itemEl;
|
||||
if(item.type === "file"){
|
||||
itemEl = createTreeLeaf(path, item.name, item.size);
|
||||
} else {
|
||||
itemEl = createTreeBranch(path, item.name);
|
||||
}
|
||||
list.appendChild(itemEl);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function isTextFile(path){
|
||||
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
|
||||
if(typeof ext !== undefined){
|
||||
switch(ext){
|
||||
case "txt":
|
||||
case "htm":
|
||||
case "html":
|
||||
case "js":
|
||||
case "json":
|
||||
case "c":
|
||||
case "h":
|
||||
case "cpp":
|
||||
case "css":
|
||||
case "xml":
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isImageFile(path){
|
||||
var ext = /(?:\.([^.]+))?$/.exec(path)[1];
|
||||
if(typeof ext !== undefined){
|
||||
switch(ext){
|
||||
case "png":
|
||||
case "jpg":
|
||||
case "gif":
|
||||
case "ico":
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.refreshPath = function(path){
|
||||
if(path.lastIndexOf('/') < 1){
|
||||
path = '/';
|
||||
treeRoot.removeChild(treeRoot.childNodes[0]);
|
||||
httpGet(treeRoot, "/");
|
||||
} else {
|
||||
path = path.substring(0, path.lastIndexOf('/'));
|
||||
var leaf = document.getElementById(path).parentNode;
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, path);
|
||||
}
|
||||
};
|
||||
|
||||
function delCb(path){
|
||||
return function(){
|
||||
if (xmlHttp.readyState == 4){
|
||||
if(xmlHttp.status != 200){
|
||||
alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
|
||||
} else {
|
||||
if(path.lastIndexOf('/') < 1){
|
||||
path = '/';
|
||||
treeRoot.removeChild(treeRoot.childNodes[0]);
|
||||
httpGet(treeRoot, "/");
|
||||
} else {
|
||||
path = path.substring(0, path.lastIndexOf('/'));
|
||||
var leaf = document.getElementById(path).parentNode;
|
||||
if(leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
|
||||
httpGet(leaf, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function httpDelete(filename){
|
||||
xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = delCb(filename);
|
||||
var formData = new FormData();
|
||||
formData.append("path", filename);
|
||||
xmlHttp.open("DELETE", "/edit");
|
||||
xmlHttp.send(formData);
|
||||
}
|
||||
|
||||
function getCb(parent, path){
|
||||
return function(){
|
||||
if (xmlHttp.readyState == 4){
|
||||
//clear loading
|
||||
if(xmlHttp.status == 200) addList(parent, path, JSON.parse(xmlHttp.responseText));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function httpGet(parent, path){
|
||||
xmlHttp = new XMLHttpRequest(parent, path);
|
||||
xmlHttp.onreadystatechange = getCb(parent, path);
|
||||
xmlHttp.open("GET", "/list?dir="+path, true);
|
||||
xmlHttp.send(null);
|
||||
//start loading
|
||||
}
|
||||
|
||||
httpGet(treeRoot, "/");
|
||||
return this;
|
||||
}
|
||||
|
||||
function createEditor(element, file, lang, theme, type){
|
||||
function getLangFromFilename(filename){
|
||||
var lang = "plain";
|
||||
var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
|
||||
if(typeof ext !== undefined){
|
||||
switch(ext){
|
||||
case "txt": lang = "plain"; break;
|
||||
case "htm": lang = "html"; break;
|
||||
case "js": lang = "javascript"; break;
|
||||
case "c": lang = "c_cpp"; break;
|
||||
case "cpp": lang = "c_cpp"; break;
|
||||
case "css":
|
||||
case "scss":
|
||||
case "php":
|
||||
case "html":
|
||||
case "json":
|
||||
case "xml":
|
||||
lang = ext;
|
||||
}
|
||||
}
|
||||
return lang;
|
||||
}
|
||||
|
||||
if(typeof file === "undefined") file = "/index.htm";
|
||||
|
||||
if(typeof lang === "undefined"){
|
||||
lang = getLangFromFilename(file);
|
||||
}
|
||||
|
||||
if(typeof theme === "undefined") theme = "textmate";
|
||||
|
||||
if(typeof type === "undefined"){
|
||||
type = "text/"+lang;
|
||||
if(lang === "c_cpp") type = "text/plain";
|
||||
}
|
||||
|
||||
var xmlHttp = null;
|
||||
var editor = ace.edit(element);
|
||||
|
||||
//post
|
||||
function httpPostProcessRequest(){
|
||||
if (xmlHttp.readyState == 4){
|
||||
if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
|
||||
}
|
||||
}
|
||||
function httpPost(filename, data, type){
|
||||
xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = httpPostProcessRequest;
|
||||
var formData = new FormData();
|
||||
formData.append("data", new Blob([data], { type: type }), filename);
|
||||
xmlHttp.open("POST", "/edit");
|
||||
xmlHttp.send(formData);
|
||||
}
|
||||
//get
|
||||
function httpGetProcessRequest(){
|
||||
if (xmlHttp.readyState == 4){
|
||||
document.getElementById("preview").style.display = "none";
|
||||
document.getElementById("editor").style.display = "block";
|
||||
if(xmlHttp.status == 200) editor.setValue(xmlHttp.responseText);
|
||||
else editor.setValue("");
|
||||
editor.clearSelection();
|
||||
}
|
||||
}
|
||||
function httpGet(theUrl){
|
||||
xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.onreadystatechange = httpGetProcessRequest;
|
||||
xmlHttp.open("GET", theUrl, true);
|
||||
xmlHttp.send(null);
|
||||
}
|
||||
|
||||
if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
|
||||
editor.setTheme("ace/theme/"+theme);
|
||||
editor.$blockScrolling = Infinity;
|
||||
editor.getSession().setUseSoftTabs(true);
|
||||
editor.getSession().setTabSize(2);
|
||||
editor.setHighlightActiveLine(true);
|
||||
editor.setShowPrintMargin(false);
|
||||
editor.commands.addCommand({
|
||||
name: 'saveCommand',
|
||||
bindKey: {win: 'Ctrl-S', mac: 'Command-S'},
|
||||
exec: function(editor) {
|
||||
httpPost(file, editor.getValue()+"", type);
|
||||
},
|
||||
readOnly: false
|
||||
});
|
||||
editor.commands.addCommand({
|
||||
name: 'undoCommand',
|
||||
bindKey: {win: 'Ctrl-Z', mac: 'Command-Z'},
|
||||
exec: function(editor) {
|
||||
editor.getSession().getUndoManager().undo(false);
|
||||
},
|
||||
readOnly: false
|
||||
});
|
||||
editor.commands.addCommand({
|
||||
name: 'redoCommand',
|
||||
bindKey: {win: 'Ctrl-Shift-Z', mac: 'Command-Shift-Z'},
|
||||
exec: function(editor) {
|
||||
editor.getSession().getUndoManager().redo(false);
|
||||
},
|
||||
readOnly: false
|
||||
});
|
||||
httpGet(file);
|
||||
editor.loadUrl = function(filename){
|
||||
file = filename;
|
||||
lang = getLangFromFilename(file);
|
||||
type = "text/"+lang;
|
||||
if(lang !== "plain") editor.getSession().setMode("ace/mode/"+lang);
|
||||
httpGet(file);
|
||||
}
|
||||
return editor;
|
||||
}
|
||||
function onBodyLoad(){
|
||||
var vars = {};
|
||||
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { vars[key] = value; });
|
||||
var editor = createEditor("editor", vars.file, vars.lang, vars.theme);
|
||||
var tree = createTree("tree", editor);
|
||||
createFileUploader("uploader", tree, editor);
|
||||
};
|
||||
</script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.9/ace.js" type="text/javascript" charset="utf-8"></script>
|
||||
</head>
|
||||
<body onload="onBodyLoad();">
|
||||
<div id="uploader"></div>
|
||||
<div id="tree"></div>
|
||||
<div id="editor"></div>
|
||||
<div id="preview" style="display:none;"></div>
|
||||
<iframe id=download-frame style='display:none;'></iframe>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
File diff suppressed because one or more lines are too long
Binary file not shown.
+2
-1
@@ -31,12 +31,13 @@ upload_resetmethod = nodemcu
|
||||
lib_deps =
|
||||
WiFiManager@0.14
|
||||
AsyncMqttClient
|
||||
https://github.com/bblanchon/ArduinoJson.git#v6.7.0-beta
|
||||
ArduinoJson
|
||||
WS2812FX
|
||||
NeoPixelBus@2.4.1
|
||||
WebSockets
|
||||
ESPAsyncE131
|
||||
ESPAsyncUDP
|
||||
https://github.com/FabLab-Luenen/GY33_MCU
|
||||
Brzo_I2C
|
||||
|
||||
[env:esp01_1m]
|
||||
|
||||
Reference in New Issue
Block a user