Skip to content

ESP-NOW GLEDOPTO GL-RC-001WL remote

How to use Berry espnow.rx in firmware 0.12.11 to receive raw ESP-NOW packets from the GLEDOPTO GL-RC-001WL remote.

The GLEDOPTO GL-RC-001WL remote sends short raw ESP-NOW packets on multiple Wi-Fi channels when a button is pressed. With Berry espnow.rx(filter, callback), a controller can receive those packets as side-channel raw traffic without disabling the regular Spectoda Mesh ESP-NOW communication between controllers.

This is the main difference from older ESPNOWRADIO IO usage. ESPNOWRADIO owns the ESP-NOW receive callback and is not suitable for installations where the same controller should also participate in Controller-to-Controller communication.

Write raw ESP-NOW receive logic like this:

import espnow
var off = espnow.rx({
"mac": "AA:BB:CC:DD:EE:FF",
"size": 13,
"magic": [129, 145]
}, def(mac, data, rssi, channel)
print(mac, data.tohex(), rssi, channel)
end)
# When you need to unregister the callback:
off()

The callback receives:

ArgumentMeaning
macsender MAC address as string
datapayload as Berry bytes
rssireceived signal strength
channelWi-Fi channel on which the packet arrived

The filter runs natively in firmware before the packet is passed to Berry. For the GLEDOPTO remote, start with this shape:

{
"size": 13,
"magic": [129, 145]
}

Meaning of values:

KeyMeaning
sizeexpected payload length; GL-RC-001WL uses 13 bytes
magicallow-list of the first payload byte; 129 is 0x81, 145 is 0x91
macoptional lock to one physical remote

Three parts of the payload matter for button mapping:

PositionMeaning
byte 0program/magic, typically 0x81 or 0x91
bytes 1..4button press sequence
byte 6button code

The remote sends the same press repeatedly on multiple channels. Plugins therefore keep the last sequence from data.get(1, 4) and ignore the same sequence when it appears again.

Button mapping:

CodeButtonRecommended meaning
1ONturn on
2OFFturn off
9brightness +increase brigh
8brightness -decrease brigh
3nightnight-mode scene
16preset 1optional toggle
17preset 2optional toggle
18preset 3warmer tempe
19preset 4colder tempe

For a simple luminaire, use the GledoptoRemoteSingle(S) plugin.

GledoptoRemoteSingle is not a built-in Berry function. First paste the plugin definition from public examples into the Controller Berry Script: gledopto-single-id.be. Then add the call with your S map below it.

It only writes:

  • EVS("toggl", id)
  • EVS("brigh", id)

Example Berry call:

GledoptoRemoteSingle({
"id": 1,
"mac": "AA:BB:CC:DD:EE:FF",
"brigh": 50,
"brighStep": 10
})

The same call as a TNGL BERRY block:

BERRY(`
GledoptoRemoteSingle({
"id": ID1,
"mac": "AA:BB:CC:DD:EE:FF",
"brigh": 50,
"brighStep": 10
})
`);

S map for the single-ID variant:

KeyDefaultMeaning
id1Spectoda ID controlled by the remote
mac""optional remote MAC address
macFiltermac != ""whether packets from other MAC addresses should be rejected
debugfalselog received packets and ignored buttons
brigh50initial local brightness cache
brighStep10brightness step per press

Behaviour:

  • ON sets toggl to 100%.
  • OFF sets toggl to 0%.
  • Brightness +/- adjusts brigh and keeps toggl aligned with the resulting brightness. When brigh reaches 0%, toggl is also set to 0%.
  • Preset 1 and preset 2 toggle the same ID on/off.
  • Night, warmer and colder are ignored by the single-ID variant unless debug is enabled.

For a luminaire split into two logical zones, use GledoptoRemote(S).

GledoptoRemote is also not a built-in Berry function. First paste the plugin definition from public examples into the Controller Berry Script: gledopto-direct-indirect.be. Then add the call with your S map below it.

It writes:

  • EVS("toggl", direct) and EVS("toggl", indirect)
  • EVS("brigh", direct) and EVS("brigh", indirect)
  • EVS("tempe", direct) and EVS("tempe", indirect)

Example call:

GledoptoRemote({
"direct": 1,
"indirect": 2,
"mac": "AA:BB:CC:DD:EE:FF",
"brigh": 50,
"brighStep": 10,
"tempeStep": 10
})

S map for the direct/indirect variant:

KeyDefaultMeaning
direct1Spectoda ID for the direct part of the luminaire
indirect2Spectoda ID for the indirect part of the luminaire
mac""optional remote MAC address
macFiltermac != ""whether packets from other MAC addresses should be rejected
debugfalselog received packets and unknown buttons
brigh50initial shared brightness cache
brighStep10brightness step per press
tempeStep10colour temperature step per press

Behaviour:

  • ON/OFF controls toggl for both IDs.
  • Brightness +/- adjusts brigh for both IDs and keeps both toggl states aligned with the resulting brightness. When shared brigh reaches 0%, both toggl states are set to 0%.
  • Night turns direct off, turns indirect on and sets both tempe values to warm.
  • Preset 1 toggles indirect.
  • Preset 2 toggles direct.
  • Preset 3/4 moves tempe for both IDs warmer/colder.

During first bring-up, enable debug:

GledoptoRemoteSingle({
"id": 1,
"debug": true
})

Then press a button on the remote and watch the serial log. Once you know the MAC address, add it to the S map:

GledoptoRemoteSingle({
"id": 1,
"mac": "AA:BB:CC:DD:EE:FF"
})

When mac is set and macFilter is not explicitly false, the plugin accepts only that one remote.

For a DEVKIT or installation, upload Berry through a TNGL BERRY(...) block or through a Studio Berry Script block. You do not need to upload a filesystem image for this.

Recommended workflow:

  1. Keep regular ESP-NOW communication enabled. espnow.enable does not need to be set to true; current firmware enables it by default.
  2. Upload the plugin and its call to the controller.
  3. For the first test, set "debug": true.
  4. Press ON, OFF, brightness + and brightness -.
  5. Check in the log or in Spectoda App that toggl and brigh change on the expected Spectoda ID.

For the direct/indirect variant, also test preset 1, preset 2 and preset 3/4.

espnow.rx and espnow.tx are raw APIs for the concrete ESP-NOW transport. Use them when you need to work with MAC address, payload and transport details.

Raw espnow.tx supports:

espnow.tx("AA:BB:CC:DD:EE:FF", data)
espnow.tx("AA:BB:CC:DD:EE:FF", data, {"mode": "transmit"})
espnow.tx("AA:BB:CC:DD:EE:FF", data, {"mode": "deliver"})

Meaning:

  • transmit is one non-flooded packet without ack.
  • deliver is one non-flooded unicast packet with ack.
  • raw espnow.tx has no broadcast or transfer mode; flooded broadcast and larger transfers belong to the higher Spectoda Mesh layer through spectoda.tx.

Use spectoda.tx and spectoda.rx for general Controller-to-Controller messages in Berry. Use espnow.tx and espnow.rx for exact work with raw ESP-NOW packets.