Fixed issue where step up and down command bytes were reversed on receive.

* TX commands for 80-bit controllers now send the last 3 bytes as witnessed by others
* RX commands for step up/down only translate the last byte as a command byte.
* Fixed inverted step commands for the API.
This commit is contained in:
Robert Strouse 2023-03-20 17:11:28 -07:00
parent d3acf6bb5f
commit ab7cdba519
8 changed files with 18 additions and 14 deletions

View file

@ -3,7 +3,7 @@
#ifndef configsettings_h #ifndef configsettings_h
#define configsettings_h #define configsettings_h
#define FW_VERSION "v1.4.2" #define FW_VERSION "v1.4.3"
enum DeviceStatus { enum DeviceStatus {
DS_OK = 0, DS_OK = 0,
DS_ERROR = 1, DS_ERROR = 1,

View file

@ -48,6 +48,7 @@ somfy_commands translateSomfyCommand(const String& string) {
else if (string.equalsIgnoreCase("Prog")) return somfy_commands::Prog; else if (string.equalsIgnoreCase("Prog")) return somfy_commands::Prog;
else if (string.equalsIgnoreCase("SunFlag")) return somfy_commands::SunFlag; else if (string.equalsIgnoreCase("SunFlag")) return somfy_commands::SunFlag;
else if (string.equalsIgnoreCase("StepUp")) return somfy_commands::StepUp; else if (string.equalsIgnoreCase("StepUp")) return somfy_commands::StepUp;
else if (string.equalsIgnoreCase("StepDown")) return somfy_commands::StepDown;
else if (string.equalsIgnoreCase("Flag")) return somfy_commands::Flag; else if (string.equalsIgnoreCase("Flag")) return somfy_commands::Flag;
else if (string.startsWith("mud") || string.startsWith("MUD")) return somfy_commands::MyUpDown; else if (string.startsWith("mud") || string.startsWith("MUD")) return somfy_commands::MyUpDown;
else if (string.startsWith("md") || string.startsWith("MD")) return somfy_commands::MyDown; else if (string.startsWith("md") || string.startsWith("MD")) return somfy_commands::MyDown;
@ -115,10 +116,13 @@ void somfy_frame_t::decodeFrame(byte* frame) {
this->checksum = decoded[1] & 0b1111; this->checksum = decoded[1] & 0b1111;
this->encKey = decoded[0]; this->encKey = decoded[0];
// Pull in the 80-bit commands. The upper nibble will be 0 even on 80 bit packets. // Pull in the 80-bit commands. The upper nibble will be 0 even on 80 bit packets.
this->cmd = (somfy_commands)((decoded[1] >> 4) | ((decoded[8] & 0x08) << 4)); this->cmd = (somfy_commands)((decoded[1] >> 4));
// Pull in the data for an 80-bit step command.
if(this->cmd == somfy_commands::StepDown)
this->cmd = (somfy_commands)((decoded[1] >> 4) | ((decoded[8] & 0x08) << 4));
this->rollingCode = decoded[3] + (decoded[2] << 8); this->rollingCode = decoded[3] + (decoded[2] << 8);
this->remoteAddress = (decoded[6] + (decoded[5] << 8) + (decoded[4] << 16)); this->remoteAddress = (decoded[6] + (decoded[5] << 8) + (decoded[4] << 16));
this->valid = this->checksum == checksum && this->remoteAddress < 16777215; this->valid = this->checksum == checksum && this->remoteAddress < 16777215 && this->rollingCode > 0;
if (this->valid) { if (this->valid) {
// Check for valid command. // Check for valid command.
switch (this->cmd) { switch (this->cmd) {
@ -215,8 +219,8 @@ void somfy_frame_t::encodeFrame(byte *frame) {
frame[9] = 29; frame[9] = 29;
switch(this->cmd) { switch(this->cmd) {
case somfy_commands::StepUp: case somfy_commands::StepUp:
frame[7] = 136; frame[7] = 132;
frame[8] = 52; frame[8] = 56;
frame[9] = 22; frame[9] = 22;
break; break;
case somfy_commands::StepDown: case somfy_commands::StepDown:
@ -1449,6 +1453,7 @@ void SomfyRemote::sendCommand(somfy_commands cmd, uint8_t repeat) {
frame.cmd = cmd; frame.cmd = cmd;
frame.repeats = repeat; frame.repeats = repeat;
frame.bitLength = this->bitLength; frame.bitLength = this->bitLength;
frame.encKey = 0xA0 | static_cast<uint8_t>(frame.rollingCode & 0x000F);
if(frame.bitLength == 0) frame.bitLength = bit_length; if(frame.bitLength == 0) frame.bitLength = bit_length;
this->lastRollingCode = frame.rollingCode; this->lastRollingCode = frame.rollingCode;
somfy.sendFrame(frame, repeat); somfy.sendFrame(frame, repeat);
@ -1646,7 +1651,6 @@ void Transceiver::sendFrame(byte *frame, uint8_t sync, uint8_t bitLength) {
REG_WRITE(GPIO_OUT_W1TC_REG, pin); REG_WRITE(GPIO_OUT_W1TC_REG, pin);
delayMicroseconds(SYMBOL); delayMicroseconds(SYMBOL);
// Data: bits are sent one by one, starting with the MSB. // Data: bits are sent one by one, starting with the MSB.
// TODO: Handle the 80-bit send protocol
for (byte i = 0; i < bitLength; i++) { for (byte i = 0; i < bitLength; i++) {
if (((frame[i / 8] >> (7 - (i % 8))) & 1) == 1) { if (((frame[i / 8] >> (7 - (i % 8))) & 1) == 1) {
REG_WRITE(GPIO_OUT_W1TC_REG, pin); REG_WRITE(GPIO_OUT_W1TC_REG, pin);

View file

@ -22,13 +22,13 @@ enum class somfy_commands : byte {
Prog = 0x8, Prog = 0x8,
SunFlag = 0x9, SunFlag = 0x9,
Flag = 0xA, Flag = 0xA,
StepUp = 0xB, StepDown = 0xB,
UnknownC = 0xC, UnknownC = 0xC,
UnknownD = 0xD, UnknownD = 0xD,
UnknownE = 0xE, UnknownE = 0xE, // This command byte has been witnessed in the wild but cannot tell if it is from Somfy. No rolling code is sent with this and it is 56-bits.
UnknownF = 0xF, UnknownF = 0xF,
// Command extensions for 80 bit frames // Command extensions for 80 bit frames
StepDown = 0x8B StepUp = 0x8B
}; };
enum class shade_types : byte { enum class shade_types : byte {
roller = 0x00, roller = 0x00,

Binary file not shown.

Binary file not shown.

View file

@ -1 +1 @@
1.4.0 1.4.3

View file

@ -3,10 +3,10 @@
<head> <head>
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="main.css?v=1.4.2" type="text/css" /> <link rel="stylesheet" href="main.css?v=1.4.3" type="text/css" />
<link rel="stylesheet" href="icons.css?v=1.4.2" type="text/css" /> <link rel="stylesheet" href="icons.css?v=1.4.3" type="text/css" />
<link rel="icon" type="image/png" href="favicon.png" /> <link rel="icon" type="image/png" href="favicon.png" />
<script type="text/javascript" src="index.js?v=1.4.2"></script> <script type="text/javascript" src="index.js?v=1.4.3"></script>
</head> </head>
<body> <body>
<div id="divContainer" class="container" style="user-select:none;position:relative;border-radius:27px;"> <div id="divContainer" class="container" style="user-select:none;position:relative;border-radius:27px;">

View file

@ -372,7 +372,7 @@ async function reopenSocket() {
await initSockets(); await initSockets();
} }
class General { class General {
appVersion = 'v1.4.2'; appVersion = 'v1.4.3';
reloadApp = false; reloadApp = false;
async init() { async init() {
this.setAppVersion(); this.setAppVersion();