Integration ELRO HE800-Serie

Begonnen von Fuchks, 20 Oktober 2016, 17:06:25

Vorheriges Thema - Nächstes Thema

Fuchks

Gibt es Interesse das ELRO Homeeasy HE800-Protokoll zu implementieren?
Die Verschlüsselung und der Protokollaufbau sind mittlerweile bekannt:

Zitat von: Fuchks am 15 Oktober 2016, 20:29:39
Dimming und Decoder sind fertig und getestet.
Die Integration in die CUL-FW kann ich leider nicht übernehmen, aber mit meiner Vorarbeit sicher nicht allzu kompliziert  ;D

Das Beispielprogramm ver- und entschlüsselt alle möglichen Nachrichten einer Sender-ID:
// Example program for en- & decrypting ELRO HE800 series messages
#include <iostream>
#include <string>

int main()
{
    uint16_t txID = 0x9ac0; //unique transmitter-ID [0]1..65535 (0 valid?, 65535 or lower limit?)
    uint8_t cmd; //0=OFF 1=ON, 2=10%dim..9=80%dim (no 90%dim!)
    uint8_t rcd; //rolling-code 0-3 (differentiate new message from repeated message)
    uint8_t rxID; //receiver-ID [0]1..15, 0=Broadcast 1-15 (HE844A button# 1-4 & MASTER=0, HE850 UNIT# 1-15, HE853 = 1)

uint8_t key[17] = {9, 6, 3, 8, 10, 0, 2, 12, 4, 14, 7, 5, 1, 15, 11, 13, 9}; //cryptokey
uint8_t ikey [16] = {5, 12, 6, 2, 8, 11, 1, 10, 3, 0, 4, 14, 7, 15, 9, 13};  //invers cryptokey (exchanged index & value)

uint8_t mn[7]; //message separated in nibbles
uint32_t msg; //encrypted message

    std::string sTxID;
    std::cout << "Pls type in transmitterID 0..65535:";
    getline (std::cin, sTxID);
    txID = std::stoi( sTxID );

    for (uint8_t i_cmd = 0; i_cmd < 2; i_cmd++){
        cmd = i_cmd;
        for (uint8_t i_rxID = 0; i_rxID < 16; i_rxID++){
            rxID = i_rxID;
            std::cout << "\n";
            for (uint8_t i_rcd = 0; i_rcd < 4; i_rcd++){
                rcd = i_rcd;

//encrypt
            mn[0] = rxID; // mn[0] = iiiib i=receiver-ID
            mn[1] = (rcd << 2) & 15; // 2 lowest bits of rolling-code
            if (cmd > 0) { // ON or OFF
            mn[1] |= 2;
            } // mn[1] = rrs0b r=rolling-code, s=ON/OFF, 0=const 0?
            mn[2] = txID & 15; // mn[2..5] = ttttb t=txID in nibbles -> 4x ttttb
            mn[3] = (txID >> 4) & 15;
            mn[4] = (txID >> 8) & 15;
            mn[5] = (txID >> 12) & 15;
            if (cmd >= 2 && cmd <= 9) { // mn[6] = dpppb d = dim ON/OFF, p=%dim/10 - 1
            mn[6] = cmd - 2; // dim: 0=10%..7=80%
            mn[6] |= 8; // dim: ON
            } else {
            mn[6] = 0; // dim: OFF
            }

//XOR encryption 2 rounds
for (uint8_t r=0; r<=1; r++){ // 2 encryption rounds
mn[0] = key[ mn[0]-r+1]; // encrypt first nibble
for (uint8_t i=1; i<=5 ; i++){ // encrypt 4 nibbles
mn[i] = key[(mn[i] ^ mn[i-1])-r+1]; // crypted with predecessor & key
}
}

mn[6] = mn[6] ^ 9; // no  encryption

            msg = (mn[6] << 0x18) | (mn[5] << 0x14) | // copy the encrypted nibbles in output buffer
                   (mn[4] << 0x10) | (mn[3] << 0x0c) |
                   (mn[2] << 0x08) | (mn[1] << 0x04) | mn[0];
            msg = (msg >> 2) | ((msg & 3) << 0x1a); // shift 2 bits right & copy lowest 2 bits of cbuf[0] in msg bit 27/28

                //Output encrypted message
                std::cout << std::hex << std::uppercase << "out " << (~msg << 4) << " in  Receiver-ID: " << (uint16_t) rxID << " OFF/ON/DIM: " << (uint16_t) cmd << " Rolling-code: " << (uint16_t) rcd << " Transmitter-ID: " << (uint16_t) txID << "\n"; //encrypted message bitwise inverted
               

//decrypt
            msg = ((msg << 2) & 0x0FFFFFFF) | ((msg & 0xC000000) >> 0x1a); //shift 2 bits left & copy bit 27/28 to bit 1/2
            mn[0] =  msg & 0x0000000F;
            mn[1] = (msg & 0x000000F0) >> 0x4;
            mn[2] = (msg & 0x00000F00) >> 0x8;
            mn[3] = (msg & 0x0000F000) >> 0xc;
            mn[4] = (msg & 0x000F0000) >> 0x10;
            mn[5] = (msg & 0x00F00000) >> 0x14;
            mn[6] = (msg & 0x0F000000) >> 0x18;
               
            mn[6] = mn[6] ^ 9; // no decryption
           
//XOR decryption 2 rounds
for (uint8_t r=0; r<=1; r++){ // 2 decryption rounds
for (uint8_t i=5; i>=1 ; i--){ // decrypt 4 nibbles
mn[i] = ((ikey[mn[i]]-r) & 0x0F) ^ mn[i-1]; // decrypted with predecessor & key
}
mn[0] = (ikey[mn[0]]-r) & 0x0F; //decrypt first nibble
}
           
           
//Output decrypted message
            std::cout << std::hex << std::uppercase << "in  " << (~((msg >> 2) | (((msg & 3) << 0x1a))) << 4) << " out Receiver-ID: " << (uint16_t) mn[0] << " OFF/ON/DIM: " << (((mn[1]>>1) & 1) + (mn[6] & 0x7) + ((mn[6] & 0x8) >> 4)) << " Rolling-Code: " << (mn[1] >> 2) << " Transmitter-ID: " << (uint16_t) mn[5]  << (uint16_t) mn[4]  << (uint16_t) mn[3]  << (uint16_t) mn[2] << "\n";
            }
        }
    }

}


PS: wär wohl nur was für A-CUL-FW, falls hier nur für original CUL, dann bitte verschieben

VFRulez

Interesse daran gibt es wohl auf jeden Fall!

Fuchks

Ist bereits im Intertechno-Modul integriert, a-cul-fw war keine Änderung notwendig