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

Somfy RTS blind remote control via RF module #7870

Closed
pnuding opened this issue Mar 7, 2020 · 17 comments
Closed

Somfy RTS blind remote control via RF module #7870

pnuding opened this issue Mar 7, 2020 · 17 comments
Labels
feature request (devs?) Action - awaiting response from developers

Comments

@pnuding
Copy link

pnuding commented Mar 7, 2020

Have you looked for this feature in other issues and in the docs?
Yes, there was a discussion about using a Sonoff RF bridge but since Somfy's code is rolling things get messy

Is your feature request related to a problem? Please describe.
Somfy roller shutter motors run using their custom RTS protocol with rolling code and home automation integrations are very limited unless one splurge a lot of money on their integrator gateways

Describe the solution you'd like
I'd like to see an option to use a GPIO pin for a 433MHz RF module emitting Somfy commands, with Tasmota persisting the rolling code in flash

Describe alternatives you've considered
Some years ago when i encountered this need first with an awning equipped with a Somfy motor.
I found https://github.com/Nickduino/Somfy_Remote addressing the issue for Arduino, so i slapped together a hack onto Tasmota 4.1.1 which I was using at the time. It works but it's ugly (e.g. it has discrete commands for Prog, up, stop and down rather than using parameters as one should) and my skills aren't sufficient to integrate it nicely with current Tasmota versions.
It would be nice to get this functionality properly integrated.

Additional context
Attached is the xdrv I hacked together back then. It went with a GPIO pin definiton and modification for storing the rolling count.
Also my hacking version went with some lines for setting an inital rolling code and the remote ID, which probably should be done nicer

xdrv_somfy_send.txt

(Please, remember to close the issue when the problem has been addressed)

@pnuding
Copy link
Author

pnuding commented Mar 7, 2020

Two more things:
Remote ID can be a random number or user set - since the remotes are taught to the receive, it can really be anything as long as it stays the same later.
You'll notice the commands are repeated a few times - this isn't strictly necessary but helps with transmission robustness, especially since common 433MHz transmitters and Somfy's slightly lower custom frequency don't match perfectly. The receivers take no issue with repetitions and will not treat them as separate commands since they're having the same rolling code. Actually I'd now send them more often (5-10 times) than this code does, it sometimes fails on me

@Jason2866
Copy link
Collaborator

Jason2866 commented Mar 7, 2020

A PR is welcome. None of the main developers / contributors have somfy devices.
Do not expect anything from this side.
Hardware is not easy to get. No standard RF transmitter does work because Somfy uses 433.42 Mhz.
The usual ones are 433.92 Mhz

@pnuding
Copy link
Author

pnuding commented Mar 8, 2020

I'm afraid my dev skills won't be sufficient for that :/ If nobody else is interested then I guess it'll just remain the hack on 4.1.1 for me

@Jason2866
Copy link
Collaborator

Maybe someone does it.

@ascillato2 ascillato2 added the feature request (devs?) Action - awaiting response from developers label Mar 8, 2020
@he-so
Copy link
Contributor

he-so commented Mar 19, 2020

So, if the code was working, the integration should not be the problem. Regarding storing the rolling code counter and device ID, this is exaclty the same I was using for my keeloq integration for the jarolift roller shutter. So one should share this config setting?

@he-so
Copy link
Contributor

he-so commented Mar 21, 2020

@pnuding: You need to test this please, since I do not have the Somfy hardware.

This implements the SomfySet command with the parameters: <device serial> <rolling code counter>
Those are stored persistently in the flash using the same space as the keeloq driver.

Furthermore, there are SomfyUp, SomfyDown, SomfyStop and SomfyProg commands without parameter. So have fun using those with the shutter driver.

@Chaosflori25
Copy link

I'd like to try this code and help because I own Somfy blinds, but it is, at least for me, not quite clear how. I've taken a look at the other repo, so should I connect this 433.32Mhz transmitter to the GPIO X? Am I able to use the Remote and the Sonoff Bridge? And last but not least, where could I find the code, or is it already in the release? I'd like to help but I'm stuck right now.

@Jason2866
Copy link
Collaborator

@Chaosflori25 No, Sonoff Bridge can NOT be used for. You need a extra rf transmitter supporting the
Somfy frequency. See #7870 (comment)
It is not so easy.

@he-so
Copy link
Contributor

he-so commented Mar 22, 2020

@Chaosflori25 basically yes, connect that transmitter with the appropriate frequency to one gpio pin. I don't see an issue at using the original remote and the tasmotized mqtt remote for the same shutter. It's about you to verify this. Other RF roller shutters i know are capable of "learning" the serials of multiple remotes.

For the esp8266 hardware, you can use any device that has a spare gpio. I tested the code on a Wemos D1 R2.
(If it’s an issue to get a 433,42MHz transmitter, the CC1101 can be an option, since that can be tuned by software. But it needs the full SPI wiring and some more adjustments during initialisation.)

If you are able to build the firmware, download the development branch of my fork: https://github.com/he-so/Tasmota

The binary is attached here.
tasmota.zip

You need to configure the GPIO to the pin of your transceiver as shown in the screenshot.
configure-somfy

@pnuding
Copy link
Author

pnuding commented Mar 22, 2020

It took me a while to try this but in principle it looks good. Thanks so much for stepping in to help!
My problem is that just today something seems to have gone off, probably on the hardware level, because my damn Somfy motor doesn't work with this and it now doesn't work with the old 4.1.1 Sonoff, either. I can see the signal flying by when hooking up a 433MHz receiver to my scope, so I really don't get what's going on. Spent the last 4 hours trying, will try again another day :-S

@he-so
Copy link
Contributor

he-so commented Mar 22, 2020

Do you have the firmware known to work, so I can make a trace of the signal with a logic analyser and compare it to my fork.

@pnuding
Copy link
Author

pnuding commented Mar 24, 2020

Sorry, i've had a bit of a trip down the rabbithole, but great idea with the logic analyser.
I have the working 4.1.1 code, but not the binary, and it doesn't compile anymore with the current Platformio setup.
The previously working Sonoff here seems to be half-dead for reasons I can't fathom and I can't get it to send the sequence anymore.
But I also have the Arduino project which I tested functionality on Arduino with before digging into Tasmota, and that still compiles.
So what i'll do tonight is:
Put that on an Arduino, capture the output with a logic analyser.
Put the code from your pull request on an esp8266 and do the same with the same remote ID and rolling code.
And then post the whole thing here.

@pnuding
Copy link
Author

pnuding commented Mar 24, 2020

The Arduino code in the meantime:

/* This sketch allows you to emulate a Somfy RTS or Simu HZ remote.
If you want to learn more about the Somfy RTS protocol, check out https://pushstack.wordpress.com/somfy-rts-protocol/

The rolling code will be stored in EEPROM, so that you can power the Arduino off.

Easiest way to make it work for you:
- Choose a remote number
- Choose a starting point for the rolling code. Any unsigned int works, 1 is a good start
- Upload the sketch
- Long-press the program button of YOUR ACTUAL REMOTE until your blind goes up and down slightly
- send 'p' to the serial terminal
To make a group command, just repeat the last two steps with another blind (one by one)

Then:
- m, u or h will make it to go up
- s make it stop
- b, or d will make it to go down
- you can also send a HEX number directly for any weird command you (0x9 for the sun and wind detector for instance)
*/

//#include <EEPROM.h>
#define PORT_TX 5 // Transmission port
#define SYMBOL 640
#define UP 0x2
#define STOP 0x1
#define DOWN 0x4
#define PROG 0x8
//#define EEPROM_ADDRESS 0

#define REMOTE 0x123300 // Remote ID we're using (changeable)

unsigned int rollingCode = 1;
byte frame[7];
byte checksum;

void BuildFrame(byte *frame, byte button);
void SendCommand(byte *frame, byte sync);

void setup() {
Serial.begin(115200);
pinMode(PORT_TX, OUTPUT);
digitalWrite(PORT_TX, LOW);

Serial.print("Simulated remote number : "); Serial.println(REMOTE, HEX);
Serial.print("Current rolling code : "); Serial.println(rollingCode);
}

void loop() {
if (Serial.available() > 0) {
char serie = (char)Serial.read();
Serial.println("");
if(serie == 'u') {
Serial.println("Up");
BuildFrame(frame, UP);
}
else if(serie == 's') {
Serial.println("Stop");
BuildFrame(frame, STOP);
}
else if(serie == 'd') {
Serial.println("Down");
BuildFrame(frame, DOWN);
}
else if(serie == 'p') {
Serial.println("Prog");
BuildFrame(frame, PROG);
}
Serial.println("");
SendCommand(frame, 2);
for(int i = 0; i<2; i++) {
SendCommand(frame, 7);
}
}
}

void BuildFrame(byte *frame, byte button) {
unsigned int code;
code = rollingCode;
frame[0] = 0xA7; // Encryption key. Doesn't matter much
frame[1] = button << 4; // Which button did you press? The 4 LSB will be the checksum
frame[2] = code >> 8; // Rolling code (big endian)
frame[3] = code; // Rolling code
frame[4] = REMOTE >> 16; // Remote address
frame[5] = REMOTE >> 8; // Remote address
frame[6] = REMOTE; // Remote address

// Checksum calculation: a XOR of all the nibbles
checksum = 0;
for(byte i = 0; i < 7; i++) {
checksum = checksum ^ frame[i] ^ (frame[i] >> 4);
}
checksum &= 0b1111; // We keep the last 4 bits only

//Checksum integration
frame[1] |= checksum; // If a XOR of all the nibbles is equal to 0, the blinds will
// consider the checksum ok.

// Obfuscation: a XOR of all the bytes
for(byte i = 1; i < 7; i++) {
frame[i] ^= frame[i-1];
}

Serial.print("Rolling Code : "); Serial.println(code);
rollingCode = code + 1;
}

void SendCommand(byte *frame, byte sync) {
if(sync == 2) { // Only with the first frame.
//Wake-up pulse & Silence
digitalWrite(PORT_TX, HIGH);
delayMicroseconds(9415);
digitalWrite(PORT_TX, LOW);
delayMicroseconds(89565);
}

// Hardware sync: two sync for the first frame, seven for the following ones.
for (int i = 0; i < sync; i++) {
digitalWrite(PORT_TX, HIGH);
delayMicroseconds(4SYMBOL);
digitalWrite(PORT_TX, LOW);
delayMicroseconds(4
SYMBOL);
}

// Software sync
digitalWrite(PORT_TX, HIGH);
delayMicroseconds(4550);
digitalWrite(PORT_TX, LOW);
delayMicroseconds(SYMBOL);

//Data: bits are sent one by one, starting with the MSB.
for(byte i = 0; i < 56; i++) {
if(((frame[i/8] >> (7 - (i%8))) & 1) == 1) {
digitalWrite(PORT_TX, LOW);
delayMicroseconds(SYMBOL);
digitalWrite(PORT_TX, HIGH);
delayMicroseconds(SYMBOL);
}
else {
digitalWrite(PORT_TX, HIGH);
delayMicroseconds(SYMBOL);
digitalWrite(PORT_TX, LOW);
delayMicroseconds(SYMBOL);
}
}

digitalWrite(PORT_TX, LOW);

delayMicroseconds(30415); // Inter-frame silence
}

@pnuding
Copy link
Author

pnuding commented Mar 24, 2020

(note that in the above I had removed the bits with the eeprom for simplicity)

@pnuding
Copy link
Author

pnuding commented Mar 24, 2020

Attachign the Sigrok Pulseview files for sending the "same" thing (Command "Up", Remote serial 123300, rolling code 1) with the Arduino code above and then with the code from the PR:
They're similar although the timings are slightly off - the big thing seems to be the gap between the wakeup pulse at the start and the next bits. Looking at the Arduino code I don't quite get why they're this close. https://pushstack.wordpress.com/somfy-rts-protocol/ has more on the timings.

However something is defo off here, my damn Somfy motor now ignores everything except my original remote, even a genuine remote i borrowed from my neigbors is not recognised.
Archive.zip

@he-so
Copy link
Contributor

he-so commented Mar 25, 2020

Ok, since both don't work, there is no point in looking for differences here.
Maybe you have to "learn" the serials first to make the receiver react? Did you use a fresh serial here? If not, what was the last used rolling code counter?

@ascillato2
Copy link
Collaborator

Thread continues on #7969

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request (devs?) Action - awaiting response from developers
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants