Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add E1.31 Support #2355

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
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
5 changes: 5 additions & 0 deletions code/espurna/config/dependencies.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@
#define TELNET_SERVER_ASYNC_BUFFERED 1 // enable buffered telnet by default on latest Cores
#endif

#if LIGHT_PROVIDER == LIGHT_PROVIDER_NONE
#undef E131_SUPPORT
#define E131_SUPPORT 0 // E1.31 needs light provider to work
#endif

#if LIGHT_PROVIDER == LIGHT_PROVIDER_TUYA
#undef TUYA_SUPPORT
#define TUYA_SUPPORT 1 // Need base Tuya module for this to work
Expand Down
8 changes: 8 additions & 0 deletions code/espurna/config/general.h
Original file line number Diff line number Diff line change
Expand Up @@ -1388,6 +1388,14 @@
#define DOMOTICZ_OUT_TOPIC "domoticz/out" // Default publication topic
#endif

// -----------------------------------------------------------------------------
// E1.31
// -----------------------------------------------------------------------------

#ifndef E131_SUPPORT
#define E131_SUPPORT 1 // Enable E1.31 by default
mcspr marked this conversation as resolved.
Show resolved Hide resolved
#endif

// -----------------------------------------------------------------------------
// HOME ASSISTANT
// -----------------------------------------------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions code/espurna/config/hardware.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
#define DEBUG_TELNET_SUPPORT 0
#define DEBUG_WEB_SUPPORT 0
#define DOMOTICZ_SUPPORT 0
#define E131_SUPPORT 0
#define HOMEASSISTANT_SUPPORT 0
#define I2C_SUPPORT 0
#define MQTT_SUPPORT 0
Expand Down Expand Up @@ -96,6 +97,7 @@
#define DEBUG_SERIAL_SUPPORT 0
//#define DEBUG_TELNET_SUPPORT 0
//#define DEBUG_WEB_SUPPORT 0
#define E131_SUPPORT 0
#define HOMEASSISTANT_SUPPORT 0
#define I2C_SUPPORT 0
#define MQTT_SUPPORT 0
Expand Down
178 changes: 178 additions & 0 deletions code/espurna/e131.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/*

E1.31 MODULE

Copyright (C) 2020 by Adam Honse <calcprogrammer1 at gmail dot com>

*/

#include "e131.h"

#if E131_SUPPORT

#if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE

// -----------------------------------------------------------------------------

#include "light.h"
#include "wifi.h"
#include "web.h"
#include "ws.h"

#include <ESPAsyncE131.h>

bool _e131_wifi_connected = false;
bool _e131_enabled = false;
bool _e131_multicast = false;
unsigned int _e131_universe = 1;
bool _e131_light_0_enabled = false;
unsigned int _e131_light_0_channel = 1;
bool _e131_light_1_enabled = false;
unsigned int _e131_light_1_channel = 2;
bool _e131_light_2_enabled = false;
unsigned int _e131_light_2_channel = 3;
bool _e131_light_3_enabled = false;
unsigned int _e131_light_3_channel = 4;
bool _e131_light_4_enabled = false;
unsigned int _e131_light_4_channel = 5;
bool _e131_initialized = false;

ESPAsyncE131 e131(2);

// -----------------------------------------------------------------------------
// E1.31
// -----------------------------------------------------------------------------

#if WEB_SUPPORT

bool _e131WebSocketOnKeyCheck(const char * key, JsonVariant& value) {
return (strncmp(key, "e131", 4) == 0);
}

void _e131WebSocketOnVisible(JsonObject& root) {
root["e131Visible"] = 1;
}

void _e131WebSocketOnData(JsonObject& root) {

}

void _e131WebSocketOnConnected(JsonObject& root) {
root["e131Enabled"] = getSetting("e131Enabled", false);
root["e131Multicast"] = getSetting("e131Multicast", false);
root["e131Universe"] = getSetting("e131Universe", 1);
root["e131Light0Enabled"] = getSetting("e131Light0Enabled", false);
root["e131Light0Channel"] = getSetting("e131Light0Channel", 1);
root["e131Light1Enabled"] = getSetting("e131Light1Enabled", false);
root["e131Light1Channel"] = getSetting("e131Light1Channel", 2);
root["e131Light2Enabled"] = getSetting("e131Light2Enabled", false);
root["e131Light2Channel"] = getSetting("e131Light2Channel", 3);
root["e131Light3Enabled"] = getSetting("e131Light3Enabled", false);
root["e131Light3Channel"] = getSetting("e131Light3Channel", 4);
root["e131Light4Enabled"] = getSetting("e131Light4Enabled", false);
root["e131Light4Channel"] = getSetting("e131Light4Channel", 5);
Comment on lines +64 to +73
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(again about the cfg)
We also will send less keys to the WebUI.

But, it will be more complicated from the .js script side :/
Another alternative to map string is to use e131Ch# and simply loop all channels like Domoticz, Thingspeak map internal IDs to external.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to keep the same web UI and pack the settings from it into a string? I basically just copy pasted the web functionality from other pages as I'm not really sure how it works, nor am I well versed in javascript.

Copy link
Collaborator

@mcspr mcspr Sep 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now this sends key-values as-is, so every key is 'mapped' to the same 'input name=...' elem, this is done at the end of processData() func of custom.js

What I meant about e131Ch# approach is to do something like:

String base("e131Ch");
for (unsigned index = 0; index < lightChannels(); ++index) {
    String key(base + index);
    root[key] = getSetting(key); // without 'default' 2nd param, always returns String
}

Treating empty string as disabled and non-empty as e1.31 channel number, while always creating N-channels items. Same thing in the configuration.

Then, we either create html block programmatically like dczRelayTemplate, or always have html blocks in the index.html but hide them by default via display: none css style and add additional js code such as:

// processData() near the top...

if (key.startsWith("e131Ch")) {
    $("input[name=" + key + "]").show();
}

// ...rest of processData()

}

#endif // WEB_SUPPORT

void _e131WifiCallback(justwifi_messages_t code, char * parameter) {

if (MESSAGE_CONNECTED == code) {
_e131_wifi_connected = true;
return;
}

if (MESSAGE_DISCONNECTED == code) {
_e131_wifi_connected = false;
return;
}
}

void _e131Loop() {
if (!_e131_enabled) return;

//* Initializing multicast mode must be done when the WiFi is connected, so
//* set a flag to track when WiFi is connected and disconnected
if (_e131_wifi_connected) {
if(_e131_initialized == 0) {
if(_e131_multicast) {
e131.begin(E131_MULTICAST, _e131_universe, 1);
}
else {
e131.begin(E131_UNICAST);
}

_e131_initialized = 1;
}
}
else {
_e131_initialized = 0;
}

if(!e131.isEmpty())
{
e131_packet_t pkt;
e131.pull(&pkt);

if(_e131_light_0_enabled) {
lightChannel(0, pkt.property_values[_e131_light_0_channel]);
}

if(_e131_light_1_enabled) {
lightChannel(1, pkt.property_values[_e131_light_1_channel]);
}

if(_e131_light_2_enabled) {
lightChannel(2, pkt.property_values[_e131_light_2_channel]);
}

if(_e131_light_3_enabled) {
lightChannel(3, pkt.property_values[_e131_light_3_channel]);
}

if(_e131_light_4_enabled) {
lightChannel(4, pkt.property_values[_e131_light_4_channel]);
}

lightUpdate(false, false, false);
}
}

bool e131Enabled() {
return _e131_enabled;
}

void e131Setup() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the config be purely though settings / UI, no use for build flags to pre-configure the defauls?

_e131_initialized = 0;
_e131_enabled = getSetting("e131Enabled", false);
_e131_multicast = getSetting("e131Multicast", false);
_e131_universe = getSetting("e131Universe", 1);
_e131_light_0_enabled = getSetting("e131Light0Enabled", false);
_e131_light_0_channel = getSetting("e131Light0Channel", 1);
_e131_light_1_enabled = getSetting("e131Light1Enabled", false);
_e131_light_1_channel = getSetting("e131Light1Channel", 2);
_e131_light_2_enabled = getSetting("e131Light2Enabled", false);
_e131_light_2_channel = getSetting("e131Light2Channel", 3);
_e131_light_3_enabled = getSetting("e131Light3Enabled", false);
_e131_light_3_channel = getSetting("e131Light3Channel", 4);
_e131_light_4_enabled = getSetting("e131Light4Enabled", false);
_e131_light_4_channel = getSetting("e131Light4Channel", 5);
Comment on lines +150 to +159
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note of lightChannels(). Right now configuration... seems straightforward, but bulky :/
As noticed in the other comment, my92xx uses simple string to map as 1,2,3,4,5 to map espurna channel 0 to 1, channel 1 to 2 and etc. We also won't need 10 config keys at the same time. (and we need a bit different parser, as there are more channels in e131 that go above a single digit)

'no mapping' is another question?

  • 1,,3,4,5
  • 1,-,-,4,5
  • 0:1,2:2 (left of ':' is our channel, right is e131)


espurnaRegisterLoop(_e131Loop);

#if WEB_SUPPORT
wsRegister()
.onVisible(_e131WebSocketOnVisible)
.onConnected(_e131WebSocketOnConnected)
.onData(_e131WebSocketOnData)
.onKeyCheck(_e131WebSocketOnKeyCheck);
#endif

jw.subscribe(_e131WifiCallback);

DEBUG_MSG_P(PSTR("[E131] E131 setup code finished \n"));
}

#endif // LIGHT_PROVIDER != LIGHT_PROVIDER_NONE

#endif // E131_SUPPORT
18 changes: 18 additions & 0 deletions code/espurna/e131.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*

E1.31 MODULE

Copyright (C) 2020 by Adam Honse <calcprogrammer1 at gmail dot com>

*/

#pragma once

#include "espurna.h"

#if E131_SUPPORT

void e131Setup();
bool e131Enabled();

#endif // E131_SUPPORT == 1
6 changes: 5 additions & 1 deletion code/espurna/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "curtain_kingart.h"
#include "debug.h"
#include "domoticz.h"
#include "e131.h"
#include "encoder.h"
#include "homeassistant.h"
#include "i2c.h"
Expand Down Expand Up @@ -301,7 +302,10 @@ void setup() {
#if KINGART_CURTAIN_SUPPORT
kingartCurtainSetup();
#endif

#if E131_SUPPORT
e131Setup();
#endif

// 3rd party code hook
#if USE_EXTRA
extraSetup();
Expand Down
99 changes: 99 additions & 0 deletions code/html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ <h2>Before using this device you have to change the default password for the use
<a href="#" class="pure-menu-link" data="panel-thingspeak">THINGSPEAK</a>
</li>

<li class="pure-menu-item module module-e131">
<a href="#" class="pure-menu-link" data="panel-e131">E1.31</a>
</li>

<li class="pure-menu-item">
<a href="#" class="pure-menu-link" data="panel-wifi">WIFI</a>
</li>
Expand Down Expand Up @@ -349,6 +353,101 @@ <h2>Current configuration</h2>
</div>
</div>

<form id="form-e131" class="pure-form form-settings">
<div class="panel" id="panel-e131">

<div class="header">
<h1>E1.31</h1>
<h2>
E1.31 (Streaming ACN) Protocol Settings.
</h2>
</div>

<div class="page">
<fieldset>
<legend>General</legend>

<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">E1.31 Enabled</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="e131Enabled" tabindex="30" /></div>
</div>

<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Multicast</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="e131Multicast" tabindex="30" /></div>
</div>

<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Universe</label>
<input class="pure-u-1 pure-u-lg-3-4" name="e131Universe" type="text" tabindex="41" />
</div>

<legend>Light 0</legend>

<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Enabled</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="e131Light0Enabled" tabindex="30" /></div>
</div>

<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Channel</label>
<input class="pure-u-1 pure-u-lg-3-4" name="e131Light0Channel" type="text" tabindex="41" />
</div>

<legend>Light 1</legend>

<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Enabled</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="e131Light1Enabled" tabindex="30" /></div>
</div>

<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Channel</label>
<input class="pure-u-1 pure-u-lg-3-4" name="e131Light1Channel" type="text" tabindex="41" />
</div>

<legend>Light 2</legend>

<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Enabled</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="e131Light2Enabled" tabindex="30" /></div>
</div>

<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Channel</label>
<input class="pure-u-1 pure-u-lg-3-4" name="e131Light2Channel" type="text" tabindex="41" />
</div>

<legend>Light 3</legend>

<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Enabled</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="e131Light3Enabled" tabindex="30" /></div>
</div>

<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Channel</label>
<input class="pure-u-1 pure-u-lg-3-4" name="e131Light3Channel" type="text" tabindex="41" />
</div>

<legend>Light 4</legend>

<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Enabled</label>
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="e131Light4Enabled" tabindex="30" /></div>
</div>

<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Channel</label>
<input class="pure-u-1 pure-u-lg-3-4" name="e131Light4Channel" type="text" tabindex="41" />
</div>

</fieldset>
</div>

</div>
</form>

<form id="form-general" class="pure-form form-settings">
<div class="panel" id="panel-general">

Expand Down
2 changes: 2 additions & 0 deletions code/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ lib_deps =
https://github.com/ThingPulse/esp8266-oled-ssd1306#3398c97
Adafruit SI1145 Library@~1.1.1
https://github.com/BoschSensortec/BSEC-Arduino-library.git#c5503e0
https://github.com/me-no-dev/ESPAsyncUDP.git#master
https://github.com/forkineye/ESPAsyncE131.git#master

# ------------------------------------------------------------------------------
# COMMON ENVIRONMENT SETTINGS:
Expand Down