-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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
Support for ESP-NOW Wireless Remote Control #3237
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
8ebc012
Initial checkin for ESP-NOW remote feature
ctsims 4aa4fe7
cleanup irrelevant comment
ctsims 553c715
don't bring in espnow package includes when feature disabled
ctsims d3b4c9f
Formatting and removing inaccurate call mode hardcoding
ctsims 1ef0299
Fork ESP Now code by platform (8266 v. esp32)
ctsims 85b4d04
Merge branch 'main' into ctsims/espnow_remote
ctsims 14185df
compiled html update
ctsims 49a5847
Disable ESP-NOW remote by default on ESP32 until tested
ctsims dfd0214
Merge branch 'main' into pr/3237
Aircoookie 09b564c
Enable ESP-NOW remote for ESP32
Aircoookie 3c28bbd
Rename ESP NOW define
Aircoookie File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
#include "wled.h" | ||
|
||
#define ESP_NOW_STATE_UNINIT 0 | ||
#define ESP_NOW_STATE_ON 1 | ||
#define ESP_NOW_STATE_ERROR 2 | ||
|
||
#define NIGHT_MODE_DEACTIVATED -1 | ||
#define NIGHT_MODE_BRIGHTNESS 5 | ||
|
||
#define WIZMOTE_BUTTON_ON 1 | ||
#define WIZMOTE_BUTTON_OFF 2 | ||
#define WIZMOTE_BUTTON_NIGHT 3 | ||
#define WIZMOTE_BUTTON_ONE 16 | ||
#define WIZMOTE_BUTTON_TWO 17 | ||
#define WIZMOTE_BUTTON_THREE 18 | ||
#define WIZMOTE_BUTTON_FOUR 19 | ||
#define WIZMOTE_BUTTON_BRIGHT_UP 9 | ||
#define WIZMOTE_BUTTON_BRIGHT_DOWN 8 | ||
|
||
#ifdef WLED_DISABLE_ESPNOW | ||
void handleRemote(){} | ||
#else | ||
|
||
// This is kind of an esoteric strucure because it's pulled from the "Wizmote" | ||
// product spec. That remote is used as the baseline for behavior and availability | ||
// since it's broadly commercially available and works out of the box as a drop-in | ||
typedef struct message_structure { | ||
uint8_t program; // 0x91 for ON button, 0x81 for all others | ||
uint8_t seq[4]; // Incremetal sequence number 32 bit unsigned integer LSB first | ||
uint8_t byte5 = 32; // Unknown | ||
uint8_t button; // Identifies which button is being pressed | ||
uint8_t byte8 = 1; // Unknown, but always 0x01 | ||
uint8_t byte9 = 100; // Unnkown, but always 0x64 | ||
|
||
uint8_t byte10; // Unknown, maybe checksum | ||
uint8_t byte11; // Unknown, maybe checksum | ||
uint8_t byte12; // Unknown, maybe checksum | ||
uint8_t byte13; // Unknown, maybe checksum | ||
} message_structure; | ||
|
||
static int esp_now_state = ESP_NOW_STATE_UNINIT; | ||
static uint32_t last_seq = -1; | ||
static int brightnessBeforeNightMode = NIGHT_MODE_DEACTIVATED; | ||
static message_structure incoming; | ||
|
||
// Pulled from the IR Remote logic but reduced to 10 steps with a constant of 3 | ||
const byte brightnessSteps[] = { | ||
6, 9, 14, 22, 33, 50, 75, 113, 170, 255 | ||
}; | ||
const size_t numBrightnessSteps = sizeof(brightnessSteps) / sizeof(uint8_t); | ||
|
||
bool nightModeActive() { | ||
return brightnessBeforeNightMode != NIGHT_MODE_DEACTIVATED; | ||
} | ||
|
||
void activateNightMode() { | ||
brightnessBeforeNightMode = bri; | ||
bri = NIGHT_MODE_BRIGHTNESS; | ||
} | ||
|
||
bool resetNightMode() { | ||
if (!nightModeActive()) { | ||
return false; | ||
} | ||
bri = brightnessBeforeNightMode; | ||
brightnessBeforeNightMode = NIGHT_MODE_DEACTIVATED; | ||
return true; | ||
} | ||
|
||
// increment `bri` to the next `brightnessSteps` value | ||
void brightnessUp() { | ||
if (nightModeActive()) { return; } | ||
// dumb incremental search is efficient enough for so few items | ||
for (uint8_t index = 0; index < numBrightnessSteps; ++index) { | ||
if (brightnessSteps[index] > bri) { | ||
bri = brightnessSteps[index]; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
// decrement `bri` to the next `brightnessSteps` value | ||
void brightnessDown() { | ||
if (nightModeActive()) { return; } | ||
// dumb incremental search is efficient enough for so few items | ||
for (int index = numBrightnessSteps - 1; index >= 0; --index) { | ||
if (brightnessSteps[index] < bri) { | ||
bri = brightnessSteps[index]; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
void setOn() { | ||
if (resetNightMode()) { | ||
stateUpdated(CALL_MODE_BUTTON); | ||
} | ||
if (!bri) { | ||
toggleOnOff(); | ||
} | ||
} | ||
|
||
void setOff() { | ||
if (resetNightMode()) { | ||
stateUpdated(CALL_MODE_BUTTON); | ||
} | ||
if (bri) { | ||
toggleOnOff(); | ||
} | ||
} | ||
|
||
void presetWithFallback(uint8_t presetID, uint8_t effectID, uint8_t paletteID) { | ||
applyPresetWithFallback(presetID, CALL_MODE_BUTTON_PRESET, effectID, paletteID); | ||
} | ||
|
||
// Callback function that will be executed when data is received | ||
#ifdef ESP8266 | ||
void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) { | ||
#else | ||
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) { | ||
#endif | ||
|
||
sprintf (last_signal_src, "%02x%02x%02x%02x%02x%02x", | ||
mac [0], mac [1], mac [2], mac [3], mac [4], mac [5]); | ||
|
||
if (strcmp(last_signal_src, linked_remote) != 0) { | ||
DEBUG_PRINT(F("ESP Now Message Received from Unlinked Sender: ")); | ||
DEBUG_PRINTLN(last_signal_src); | ||
return; | ||
} | ||
|
||
if (len != sizeof(incoming)) { | ||
DEBUG_PRINT(F("Unknown incoming ESP Now message received of length ")); | ||
DEBUG_PRINTLN(len); | ||
return; | ||
} | ||
|
||
memcpy(&(incoming.program), incomingData, sizeof(incoming)); | ||
uint32_t cur_seq = incoming.seq[0] | (incoming.seq[1] << 8) | (incoming.seq[2] << 16) | (incoming.seq[3] << 24); | ||
|
||
if (cur_seq == last_seq) { | ||
return; | ||
} | ||
|
||
|
||
DEBUG_PRINT(F("Incoming ESP Now Packet[")); | ||
DEBUG_PRINT(cur_seq); | ||
DEBUG_PRINT(F("] from sender[")); | ||
DEBUG_PRINT(last_signal_src); | ||
DEBUG_PRINT(F("] button: ")); | ||
DEBUG_PRINTLN(incoming.button); | ||
switch (incoming.button) { | ||
case WIZMOTE_BUTTON_ON : setOn(); stateUpdated(CALL_MODE_BUTTON); break; | ||
case WIZMOTE_BUTTON_OFF : setOff(); stateUpdated(CALL_MODE_BUTTON); break; | ||
case WIZMOTE_BUTTON_ONE : presetWithFallback(1, FX_MODE_STATIC, 0); resetNightMode(); break; | ||
case WIZMOTE_BUTTON_TWO : presetWithFallback(2, FX_MODE_BREATH, 0); resetNightMode(); break; | ||
case WIZMOTE_BUTTON_THREE : presetWithFallback(3, FX_MODE_FIRE_FLICKER, 0); resetNightMode(); break; | ||
case WIZMOTE_BUTTON_FOUR : presetWithFallback(4, FX_MODE_RAINBOW, 0); resetNightMode(); break; | ||
case WIZMOTE_BUTTON_NIGHT : activateNightMode(); stateUpdated(CALL_MODE_BUTTON); break; | ||
case WIZMOTE_BUTTON_BRIGHT_UP : brightnessUp(); stateUpdated(CALL_MODE_BUTTON); break; | ||
case WIZMOTE_BUTTON_BRIGHT_DOWN : brightnessDown(); stateUpdated(CALL_MODE_BUTTON); break; | ||
default: break; | ||
|
||
} | ||
|
||
last_seq = cur_seq; | ||
} | ||
|
||
void handleRemote() { | ||
if (enable_espnow_remote) { | ||
if (esp_now_state == ESP_NOW_STATE_UNINIT) { | ||
DEBUG_PRINTLN(F("Initializing ESP_NOW listener")); | ||
// Init ESP-NOW | ||
if (esp_now_init() != 0) { | ||
DEBUG_PRINTLN(F("Error initializing ESP-NOW")); | ||
esp_now_state = ESP_NOW_STATE_ERROR; | ||
} | ||
|
||
#ifdef ESP8266 | ||
esp_now_set_self_role(ESP_NOW_ROLE_SLAVE); | ||
#endif | ||
|
||
esp_now_register_recv_cb(OnDataRecv); | ||
esp_now_state = ESP_NOW_STATE_ON; | ||
} | ||
} else { | ||
if (esp_now_state == ESP_NOW_STATE_ON) { | ||
DEBUG_PRINTLN(F("Disabling ESP-NOW Remote Listener")); | ||
if (esp_now_deinit() != 0) { | ||
DEBUG_PRINTLN(F("Error de-initializing ESP-NOW")); | ||
} | ||
esp_now_state = ESP_NOW_STATE_UNINIT; | ||
} else if (esp_now_state == ESP_NOW_STATE_ERROR) { | ||
//Clear any error states (allows retrying by cycling) | ||
esp_now_state = ESP_NOW_STATE_UNINIT; | ||
} | ||
} | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this is now just a duplicate of
applyPresetWithFallback()
, we should remove it