Skip to content
This repository has been archived by the owner on Apr 28, 2022. It is now read-only.

Add e131 mode #289

Merged
merged 11 commits into from
Jan 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
language: python
python:
- "2.7"
sudo: false
cache:
directories:
- "~/.platformio"
env:
- PLATFORMIO_CI_SRC=Arduino/McLighting
install:
- pip install -U platformio
- platformio update
script:
- platformio ci --project-conf=./platformio.ini -v
50 changes: 47 additions & 3 deletions Arduino/McLighting/McLighting.ino
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@
#endif
#endif

#ifdef ENABLE_E131
#include <ESPAsyncUDP.h> //https://github.com/me-no-dev/ESPAsyncUDP
#include <ESPAsyncE131.h> //https://github.com/forkineye/ESPAsyncE131
ESPAsyncE131 e131(END_UNIVERSE - START_UNIVERSE + 1);
#endif


// ***************************************************************************
// Instanciate HTTP(80) / WebSockets(81) Server
Expand Down Expand Up @@ -90,14 +96,18 @@ WS2812FX strip = WS2812FX(NUMLEDS, PIN, NEO_GRB + NEO_KHZ800);
// and minimize distance between Arduino and first pixel. Avoid connecting
// on a live circuit...if you must, connect GND first.

#ifdef USE_WS2812FX_DMA
#ifdef USE_WS2812FX_DMA // Uses GPIO3/RXD0/RX, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods
#include <NeoPixelBus.h>
NeoEsp8266Dma800KbpsMethod dma = NeoEsp8266Dma800KbpsMethod(NUMLEDS, 3); //800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//NeoEsp8266Dma400KbpsMethod dma = NeoEsp8266Dma400KbpsMethod(NUMLEDS, 3); //400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
#endif
#ifdef USE_WS2812FX_UART
#ifdef USE_WS2812FX_UART1 // Uses UART1: GPIO1/TXD0/TX, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods
#include <NeoPixelBus.h>
NeoEsp8266Uart0800KbpsMethod dma = NeoEsp8266Uart0800KbpsMethod(NUMLEDS, 3);
#endif
#ifdef USE_WS2812FX_UART2 // Uses UART2: GPIO2/TXD1/D4, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods
#include <NeoPixelBus.h>
NeoEsp8266Uart800KbpsMethod dma = NeoEsp8266Uart800KbpsMethod(NUMLEDS, 3);
NeoEsp8266Uart1800KbpsMethod dma = NeoEsp8266Uart1800KbpsMethod(NUMLEDS, 3);
#endif
#if defined(USE_WS2812FX_DMA) or defined(USE_WS2812FX_UART)
void DMA_Show(void) {
Expand Down Expand Up @@ -840,6 +850,26 @@ void setup() {
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
#endif
});

#ifdef ENABLE_E131
server.on("/e131", []() {
exit_func = true;
mode = E131;
getStatusJSON();
#ifdef ENABLE_MQTT
mqtt_client.publish(mqtt_outtopic, String("OK =e131").c_str());
#endif
#ifdef ENABLE_AMQTT
amqttClient.publish(mqtt_outtopic.c_str(), qospub, false, String("OK =131").c_str());
#endif
#ifdef ENABLE_HOMEASSISTANT
stateOn = true;
#endif
#ifdef ENABLE_STATE_SAVE_SPIFFS
if(!spiffs_save_state.active()) spiffs_save_state.once(3, tickerSpiffsSaveState);
#endif
});
#endif

server.on("/tv", []() {
exit_func = true;
Expand Down Expand Up @@ -895,6 +925,15 @@ void setup() {
if (mdns_result) {
MDNS.addService("http", "tcp", 80);
}

#ifdef ENABLE_E131
// Choose one to begin listening for E1.31 data
// if (e131.begin(E131_UNICAST)) // Listen via Unicast
if (e131.begin(E131_MULTICAST, START_UNIVERSE, END_UNIVERSE)) // Listen via Multicast
Serial.println(F("Listening for data..."));
else
Serial.println(F("*** e131.begin failed ***"));
#endif
#ifdef ENABLE_STATE_SAVE_SPIFFS
(readStateFS()) ? DBG_OUTPUT_PORT.println(" Success!") : DBG_OUTPUT_PORT.println(" Failure!");
#endif
Expand Down Expand Up @@ -1013,6 +1052,11 @@ void loop() {
strip.trigger();
mode = HOLD;
}
#ifdef ENABLE_E131
if (mode == E131) {
handleE131();
}
#endif
#endif
if (mode == HOLD || mode == CUSTOM) {
if(!strip.isRunning()) strip.start();
Expand Down
17 changes: 14 additions & 3 deletions Arduino/McLighting/definitions.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//#define USE_WS2812FX_DMA // Uses PIN is ignored & set to RX/GPIO3 Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX
//#define USE_WS2812FX_UART // Uses PIN is ignored & set to D4/GPIO2 Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX
//#define USE_WS2812FX_UART1 // Uses PIN is ignored & set to D4/GPIO2 Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX
//#define USE_WS2812FX_UART2 // Uses PIN is ignored & set to TX/GPIO1 Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX

// Neopixel
#define PIN 14 // PIN (14 / D5) where neopixel / WS2811 strip is attached
Expand All @@ -16,7 +17,13 @@ const char HOSTNAME[] = "McLighting01"; // Friedly hostname
#define ENABLE_HOMEASSISTANT // If defined, enable Homeassistant integration, ENABLE_MQTT or ENABLE_AMQTT must be active
#define ENABLE_BUTTON // If defined, enable button handling code, see: https://github.com/toblum/McLighting/wiki/Button-control
//#define MQTT_HOME_ASSISTANT_SUPPORT // If defined, use AMQTT and select Tools -> IwIP Variant -> Higher Bandwidth
#define ENABLE_LEGACY_ANIMATIONS
#define ENABLE_LEGACY_ANIMATIONS // Dont disbale this for now
#define ENABLE_E131 // E1.31 implementation

#ifdef ENABLE_E131
#define START_UNIVERSE 1 // First DMX Universe to listen for
#define END_UNIVERSE 2 // Total number of Universes to listen for, starting at UNIVERSE
#endif

//#define WIFIMGR_PORTAL_TIMEOUT 180
//#define WIFIMGR_SET_MANUAL_IP
Expand Down Expand Up @@ -104,7 +111,11 @@ uint32_t autoParams[][4] = { // color, speed, mode, duration (seconds)

// List of all color modes
#ifdef ENABLE_LEGACY_ANIMATIONS
enum MODE { SET_MODE, HOLD, OFF, SETCOLOR, SETSPEED, BRIGHTNESS, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW, TV, CUSTOM };
#ifdef ENABLE_E131
enum MODE { SET_MODE, HOLD, OFF, SETCOLOR, SETSPEED, BRIGHTNESS, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW, TV, CUSTOM, E131 };
#else
enum MODE { SET_MODE, HOLD, OFF, SETCOLOR, SETSPEED, BRIGHTNESS, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW, TV, CUSTOM };
#endif
MODE mode = RAINBOW; // Standard mode that is active when software starts
bool exit_func = false; // Global helper variable to get out of the color modes when mode changes
#else
Expand Down
87 changes: 86 additions & 1 deletion Arduino/McLighting/request_handlers.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,40 @@
// ***************************************************************************
// Request handlers
// ***************************************************************************
#ifdef ENABLE_E131
void checkForRequests(void); //prototype

void handleE131(){
if (!e131.isEmpty())
{
e131_packet_t packet;
e131.pull(&packet); // Pull packet from ring buffer

uint16_t universe = htons(packet.universe);
uint8_t *data = packet.property_values + 1;

if (universe < START_UNIVERSE || universe > END_UNIVERSE) return; //async will take care about filling the buffer

// Serial.printf("Universe %u / %u Channels | Packet#: %u / Errors: %u / CH1: %u\n",
// htons(packet.universe), // The Universe for this packet
// htons(packet.property_value_count) - 1, // Start code is ignored, we're interested in dimmer data
// e131.stats.num_packets, // Packet counter
// e131.stats.packet_errors, // Packet error counter
// packet.property_values[1]); // Dimmer data for Channel 1

uint16_t multipacketOffset = (universe - START_UNIVERSE) * 170; //if more than 170 LEDs (510 channels), client will send in next higher universe
if (NUMLEDS <= multipacketOffset) return;
debsahu marked this conversation as resolved.
Show resolved Hide resolved
uint16_t len = (170 + multipacketOffset > NUMLEDS) ? (NUMLEDS - multipacketOffset) : 170;
for (uint16_t i = 0; i < len; i++){
uint16_t j = i * 3;
strip.setPixelColor(i + multipacketOffset, data[j], data[j + 1], data[j + 2]);
}
strip.show();
checkForRequests();
}
}
#endif

#ifdef ENABLE_HOMEASSISTANT
void tickerSendState(){
new_ha_mqtt_msg = true;
Expand Down Expand Up @@ -268,6 +302,19 @@ void setModeByStateString(String saved_state_string) {
}
#endif

#ifdef ENABLE_E131
void handleE131NamedMode(String str_mode) {
exit_func = true;
if (str_mode.startsWith("=e131") or str_mode.startsWith("/e131")) {
if(strip.isRunning()) strip.stop();
mode = E131;
#ifdef ENABLE_HOMEASSISTANT
stateOn = true;
#endif
}
}
#endif

void handleSetWS2812FXMode(uint8_t * mypayload) {
mode = SET_MODE;
uint8_t ws2812fx_mode_tmp = (uint8_t) strtol((const char *) &mypayload[1], NULL, 10);
Expand Down Expand Up @@ -305,6 +352,11 @@ String listModesJSON(void) {
const size_t bufferSize = JSON_ARRAY_SIZE(strip.getModeCount()+1) + strip.getModeCount()*JSON_OBJECT_SIZE(2) + 1000;
debsahu marked this conversation as resolved.
Show resolved Hide resolved
DynamicJsonDocument jsonBuffer(bufferSize);
JsonArray json = jsonBuffer.to<JsonArray>();
#ifdef ENABLE_E131
JsonObject objecte131 = json.createNestedObject();
objecte131["mode"] = "e131";
objecte131["name"] = "E131";
#endif
for (uint8_t i = 0; i < strip.getModeCount(); i++) {
JsonObject object = json.createNestedObject();
object["mode"] = i;
Expand Down Expand Up @@ -556,6 +608,9 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) {
String str_mode = String((char *) &payload[0]);

handleSetNamedMode(str_mode);
#ifdef ENABLE_E131
handleE131NamedMode(str_mode);
#endif
if (mqtt == true) {
DBG_OUTPUT_PORT.print("MQTT: ");
} else {
Expand Down Expand Up @@ -628,6 +683,10 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) {
// / ==> Set WS2812 mode.
if (payload[0] == '/') {
handleSetWS2812FXMode(payload);
#ifdef ENABLE_E131
String str_mode = String((char *) &payload[0]);
handleE131NamedMode(str_mode);
#endif
if (mqtt == true) {
DBG_OUTPUT_PORT.print("MQTT: ");
} else {
Expand Down Expand Up @@ -783,7 +842,14 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght

//char modeName[30];
//strncpy_P(modeName, (PGM_P)strip.getModeName(strip.getMode()), sizeof(modeName)); // copy from progmem
root["effect"] = strip.getModeName(strip.getMode());
#if defined(ENABLE_E131) and defined(ENABLE_HOMEASSISTANT)
if (mode == E131)
root["effect"] = "E131";
else
root["effect"] = strip.getModeName(strip.getMode());
#else
root["effect"] = strip.getModeName(strip.getMode());
#endif

char buffer[measureJson(root) + 1];
serializeJson(root, buffer, sizeof(buffer));
Expand Down Expand Up @@ -862,6 +928,13 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
String effectString = root["effect"].as<String>();

for (uint8_t i = 0; i < strip.getModeCount(); i++) {
#if defined(ENABLE_E131) and defined(ENABLE_HOMEASSISTANT)
if(effectString == "E131"){
if(strip.isRunning()) strip.stop();
mode = E131;
break;
}
#endif
if(String(strip.getModeName(i)) == effectString) {
mode = SET_MODE;
ws2812fx_mode = i;
Expand Down Expand Up @@ -956,6 +1029,9 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
for (uint8_t i = 0; i < strip.getModeCount(); i++) {
effect_list.add(strip.getModeName(i));
}
#if defined(ENABLE_E131) and defined(MQTT_HOME_ASSISTANT_SUPPORT)
effect_list.add("E131");
#endif
char buffer[measureJson(json) + 1];
serializeJson(json, buffer, sizeof(buffer));
mqtt_client.publish(String("homeassistant/light/" + String(HOSTNAME) + "/config").c_str(), buffer, true);
Expand Down Expand Up @@ -1040,6 +1116,9 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght
for (uint8_t i = 0; i < strip.getModeCount(); i++) {
effect_list.add(strip.getModeName(i));
}
#if defined(ENABLE_E131) and defined(MQTT_HOME_ASSISTANT_SUPPORT)
effect_list.add("E131");
#endif
char buffer[measureJson(json) + 1];
serializeJson(json, buffer, sizeof(buffer));
DBG_OUTPUT_PORT.println(buffer);
Expand Down Expand Up @@ -1322,6 +1401,12 @@ bool readStateFS() {
strip.setSpeed(convertSpeed(ws2812fx_speed));
strip.setBrightness(brightness);
strip.setColor(main_color.red, main_color.green, main_color.blue);

#ifdef ENABLE_E131
if (mode == E131) {
strip.stop();
}
#endif

updateFS = false;
return true;
Expand Down
2 changes: 1 addition & 1 deletion Arduino/McLighting/version.h
Original file line number Diff line number Diff line change
@@ -1 +1 @@
#define SKETCH_VERSION "2.1.11"
#define SKETCH_VERSION "2.2.0"
13 changes: 12 additions & 1 deletion Arduino/McLighting/version_info.ino
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,27 @@
* - Fix Auto-Discovery for HA version >= 0.84 #286
* - Fix #283
*
* 12 Dec 2018 v 2.2.0
* - Add E1.31 mode initial commit
* - E1.31 mode when activated now stops current animation
*
* 13 Dec 2018 v 2.1.9
* - HA is not getting the correct animation name being run, boils down to changes to ArduinoJson library
* - Bump ArduinoJson library requirment for v6.7.0-beta (better memory management)
* - sendState() needs extra memory for jsonBuffer
* - sensState() effect can be sent directly instead of copying from PROGMEM
*
* 16 Dec 2018 v 1.1.10
* 16 Dec 2018 v 2.1.10
* - more ArduinoJson library memory managment fixes
*
* 18 Dec 2018 v 2.1.11
* - More Auto-Discovery fix for HA version >= 0.84 #286
* - Suggestions from https://github.com/home-assistant/home-assistant/issues/19420
*
* 23 Dec 2018 v 2.2.0
* - Add E1.31 mode to getModes(), no need to change McLightingUI
*
* 6 Jan 2018 v 2.2.0
* - fix webserver not responding when E1.31 is mode is acivated: do a webserver.loop() for every 1.31 packet
* - HA E1.31 mode added
*/
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# McLighting v2 - The ESP8266 based multi-client lighting gadget

[![Gitter](https://badges.gitter.im/mclighting/Lobby.svg)](https://gitter.im/mclighting/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Gitter](https://badges.gitter.im/mclighting/Lobby.svg)](https://gitter.im/mclighting/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Build Status](https://travis-ci.com/toblum/McLighting.svg?branch=master)](https://travis-ci.com/toblum/McLighting) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![version](https://img.shields.io/badge/version-v2.2.0-blue.svg)](https://github.com/toblum/McLighting/blob/master/Arduino/McLighting/version.h)

McLighting (the multi-client lighting gadget) is a very cheap internet-controllable lighting solution based on the famous ESP8266 microcontroller and WS2811/2812 led strips. It features among other things a web-interface, a REST-API and a websocket connector.

Expand Down
5 changes: 3 additions & 2 deletions clients/HomeAssistant/light.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ light:
- "Bicolor Chase"
- "Tricolor Chase"
- "ICU"
- "E131"
brightness: true
color_temp: true
rgb: true
Expand All @@ -80,7 +81,7 @@ input_number:
step: 5

automation:
- id: 71938579813759813757
- id: "71938579813759813757"
alias: NeoPixel Animation Speed Send
initial_state: true
hide_entity: false
Expand All @@ -94,7 +95,7 @@ automation:
topic: home/McLighting01_ha/state/in
service: mqtt.publish

- id: 93786598732698756967
- id: "93786598732698756967"
alias: NeoPixel Animation Speed Receive
trigger:
- platform: mqtt
Expand Down
4 changes: 3 additions & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,7 @@ lib_deps =
AsyncMqttClient
https://github.com/bblanchon/ArduinoJson.git#v6.7.0-beta
WS2812FX
NeoPixelBus
NeoPixelBus@2.4.1
WebSockets
ESPAsyncE131
ESPAsyncUDP