RTW protocol: linked remote presses decoded as wrong command (Up→My, Down→MyUp)
Summary
When a linked remote uses the RTW protocol, button presses are correctly received (rolling code is incremented in the linked remote tracker), but the command is decoded as the wrong somfy_commands enum value. As a result, the shade's position/state never updates when the physical wall remote is used.
Symptom
- Mural remote linked to a shade via UI (works fine)
- User presses DOWN on physical mural
- Volet moves down physically (the motor itself receives correctly)
- ESPSomfy
linkedRemotes[0].lastRollingCode increments correctly (e.g., 7121 → 7126 after 5 presses)
- ESPSomfy
shade.position and shade.target do NOT change
- Home Assistant cover state remains stale
Root cause analysis
In Somfy.cpp, around line 80 in somfy_frame_t::decodeFrame():
else if(this->encKey > 133) {
this->proto = radio_proto::RTW;
this->cmd = (somfy_commands)(this->encKey - 133);
}
The RTW encoder uses these encKey values (around line 350-380 in same file):
frame[0] = 133 for My
frame[0] = 134 for Up
frame[0] = 135 for MyUp
frame[0] = 136 for Down
frame[0] = 137 for MyDown
- ...
But the somfy_commands enum in Somfy.h:
My = 0x1,
Up = 0x2,
MyUp = 0x3,
Down = 0x4,
MyDown = 0x5,
With the current formula cmd = encKey - 133:
encKey = 134 (Up) → cmd = 1 = My (wrong, should be Up=2)
encKey = 136 (Down) → cmd = 3 = MyUp (wrong, should be Down=4)
encKey = 133 (My) → cmd = 0 = Unknown0 (wrong) — actually 133 doesn't trigger the > 133 branch at all, so My is unreachable in this code path
The condition > 133 itself excludes the My encKey (133), and the offset is one less than needed.
Proposed fix
else if(this->encKey >= 133) {
this->proto = radio_proto::RTW;
this->cmd = (somfy_commands)(this->encKey - 132);
}
With this:
encKey = 133 (My) → cmd = 1 = My ✓
encKey = 134 (Up) → cmd = 2 = Up ✓
encKey = 135 (MyUp) → cmd = 3 = MyUp ✓
encKey = 136 (Down) → cmd = 4 = Down ✓
encKey = 137 (MyDown) → cmd = 5 = MyDown ✓
The corresponding check for RTV (encKey > 148) should probably also be reviewed but I haven't traced its expected mapping.
Reproduction
- Hardware: ESP32-WROOM-32 + CC1101 V2.0 (433 MHz Chinese clone)
- Firmware: v2.4.6
- Motors: Mantion SMT (French OEM, Made in Italy wall remotes, branded "ASA" in Servistores catalog) — confirmed RTW protocol, 80-bit
- Wiring: standard ESPSomfy (CS=GPIO5, GDO0=GPIO13, GDO2=GPIO12, SPI=18/19/23)
Steps:
- Configure shade with
proto=1 (RTW), bitLength=80
- Pair via PROG command (works correctly — TX of RTW PROG triggers motor pairing)
- Link the mural remote via UI (works correctly — frame received and address learned)
- Press UP/DOWN on physical mural
- Observe: rolling code increments, but shade position and direction unchanged
- Confirm via
curl http://IP/shade?shadeId=N — position, target, direction all unchanged
Workarounds tried
- ✅ Set transceiver global
proto=1 (RTW) — no effect on this bug
- ✅ Widened
rxBandwidth to 203 kHz — improves reception reliability but doesn't fix decode
- ✅ Reboot ESPSomfy — works once then stuck again
Impact
Anyone using ESPSomfy with RTW-protocol motors (e.g., Mantion in France) cannot get state sync from physical wall remotes. The system still works for ESPSomfy-initiated commands (TX is correct), but linked remote functionality is broken.
Environment
- ESPSomfy-RTS v2.4.6 (latest release as of June 2026)
- ESP32-WROOM-32 / CC1101 V2.0 clone (10€ AliExpress)
- Home Assistant 2025.x via MQTT discovery (works perfectly for TX)
Happy to test a fix and provide a PR if useful.
RTW protocol: linked remote presses decoded as wrong command (Up→My, Down→MyUp)
Summary
When a linked remote uses the RTW protocol, button presses are correctly received (rolling code is incremented in the linked remote tracker), but the command is decoded as the wrong
somfy_commandsenum value. As a result, the shade's position/state never updates when the physical wall remote is used.Symptom
linkedRemotes[0].lastRollingCodeincrements correctly (e.g., 7121 → 7126 after 5 presses)shade.positionandshade.targetdo NOT changeRoot cause analysis
In
Somfy.cpp, around line 80 insomfy_frame_t::decodeFrame():The RTW encoder uses these
encKeyvalues (around line 350-380 in same file):frame[0] = 133forMyframe[0] = 134forUpframe[0] = 135forMyUpframe[0] = 136forDownframe[0] = 137forMyDownBut the
somfy_commandsenum inSomfy.h:With the current formula
cmd = encKey - 133:encKey = 134(Up) →cmd = 1=My(wrong, should be Up=2)encKey = 136(Down) →cmd = 3=MyUp(wrong, should be Down=4)encKey = 133(My) →cmd = 0=Unknown0(wrong) — actually 133 doesn't trigger the> 133branch at all, so My is unreachable in this code pathThe condition
> 133itself excludes the My encKey (133), and the offset is one less than needed.Proposed fix
With this:
encKey = 133(My) →cmd = 1 = My✓encKey = 134(Up) →cmd = 2 = Up✓encKey = 135(MyUp) →cmd = 3 = MyUp✓encKey = 136(Down) →cmd = 4 = Down✓encKey = 137(MyDown) →cmd = 5 = MyDown✓The corresponding check for RTV (
encKey > 148) should probably also be reviewed but I haven't traced its expected mapping.Reproduction
Steps:
proto=1(RTW),bitLength=80curl http://IP/shade?shadeId=N—position,target,directionall unchangedWorkarounds tried
proto=1(RTW) — no effect on this bugrxBandwidthto 203 kHz — improves reception reliability but doesn't fix decodeImpact
Anyone using ESPSomfy with RTW-protocol motors (e.g., Mantion in France) cannot get state sync from physical wall remotes. The system still works for ESPSomfy-initiated commands (TX is correct), but linked remote functionality is broken.
Environment
Happy to test a fix and provide a PR if useful.