[erledigt][HM Wired] Protokoll Befehl 0x45 "E" und 0x65 "e"

Begonnen von hresalg, 05 Mai 2018, 00:39:24

Vorheriges Thema - Nächstes Thema

hresalg

Hallo Thorsten,

es scheint als wären die beiden Befehle "E" und "e" im HMW Protokoll noch nicht unterstützt. Ich habe mal ein wenig herum probiert. und es in meine "Homebrew" Module integriert.

Hier einmal ein Mitschnitt eines originalen Dimmers:
RX: Dest FF:FF:FF:FF Ctl 9A I  s1 r0 Y,F,B Ret 00:00:00:01 lng 01 cmd 7A z
| handle_broadcast 7A | rx_status  | quiet_startRX: Dest FF:FF:FF:FF Ctl 98 I  s0 r0 Y,F,B Ret 00:00:00:01 lng 01 cmd 5A Z
| handle_broadcast 5A | rx_status  | quiet_endRX: Dest 00:00:92:66 Ctl 38 I  s0 r1 F,B Ret 00:00:00:01 lng 01 cmd 68 h
RX: Dest 00:00:00:01 Ctl 1C I  s2 r0 F,B Ret 00:00:92:66 lng 02 cmd 14  data 00
RX: Dest 00:00:92:66 Ctl 59 ACK   r2 F,B Ret 00:00:00:01 lng 00
RX: Dest 00:00:92:66 Ctl 5A I  s1 r2 F,B Ret 00:00:00:01 lng 01 cmd 76 v
RX: Dest 00:00:00:01 Ctl 3E I  s3 r1 F,B Ret 00:00:92:66 lng 02 cmd 03  data 03
RX: Dest 00:00:92:66 Ctl 79 ACK   r3 F,B Ret 00:00:00:01 lng 00
RX: Dest 00:00:92:66 Ctl 7C I  s2 r3 F,B Ret 00:00:00:01 lng 01 cmd 6E n
RX: Dest 00:00:00:01 Ctl 58 I  s0 r2 F,B Ret 00:00:92:66 lng 0A cmd 4A J data 455130353435393636
RX: Dest 00:00:92:66 Ctl 19 ACK   r0 F,B Ret 00:00:00:01 lng 00
RX: Dest 00:00:92:66 Ctl 1E I  s3 r0 F,B Ret 00:00:00:01 lng 04 cmd 52 R data 000010
RX: Dest 00:00:00:01 Ctl 7A I  s1 r3 F,B Ret 00:00:92:66 lng 10 cmd FF ÿ data 1400000001FFFFFFFFFFFF00009624
RX: Dest 00:00:92:66 Ctl 39 ACK   r1 F,B Ret 00:00:00:01 lng 00
RX: Dest 00:00:92:66 Ctl 38 I  s0 r1 F,B Ret 00:00:00:01 lng 14 cmd 57 W data 000010FF1400000001FFFFFFFFFFFF00009624
RX: Dest 00:00:00:01 Ctl 19 ACK   r0 F,B Ret 00:00:92:66 lng 00
RX: Dest 00:00:92:66 Ctl 3A I  s1 r1 F,B Ret 00:00:00:01 lng 05 cmd 45 E data 00001040
RX: Dest 00:00:00:01 Ctl 3C I  s2 r1 F,B Ret 00:00:92:66 lng 0C cmd 65 e data 000010FFFF030000000000
RX: Dest 00:00:92:66 Ctl 59 ACK   r2 F,B Ret 00:00:00:01 lng 00
RX: Dest 00:00:92:66 Ctl 5C I  s2 r2 F,B Ret 00:00:00:01 lng 04 cmd 52 R data 001010
RX: Dest 00:00:00:01 Ctl 5E I  s3 r2 F,B Ret 00:00:92:66 lng 10 cmd 03  data 02110014C80A0A0000050000C00000
RX: Dest 00:00:92:66 Ctl 79 ACK   r3 F,B Ret 00:00:00:01 lng 00
RX: Dest 00:00:92:66 Ctl 7E I  s3 r3 F,B Ret 00:00:00:01 lng 04 cmd 52 R data 004010
RX: Dest 00:00:00:01 Ctl 78 I  s0 r3 F,B Ret 00:00:92:66 lng 10 cmd 43 C data 05000096240502110014C80A0A0000
RX: Dest 00:00:92:66 Ctl 19 ACK   r0 F,B Ret 00:00:00:01 lng 00
RX: Dest 00:00:92:66 Ctl 18 I  s0 r0 F,B Ret 00:00:00:01 lng 04 cmd 52 R data 007010
RX: Dest 00:00:00:01 Ctl 1A I  s1 r0 F,B Ret 00:00:92:66 lng 10 cmd 00


Der "E" Befehl , fragt nach benutzten EEProm Blöcken:
[0] 0x45 //E
[1] 0x0   //Startadresse des eeprom LSB
[2] 0x0   //Startadresse des eeprom MSB
[3] 0x10 //Block Größe;
[4] 0x40 //Block Zeilen;
in diesem Fall also 0x10 mal 0x40 = 0x400 = 1024 dezimal. Also die EEProm Größe.
Ich habe bisher immer nur diesen Frame gesehen. Blockgröße und Anzahl scheint sich bei der CCU nicht zu ändern.

wenn sich also in der ersten eeprom zeile in der größe von 16 byte nur 0xFF's stehen ist das 1. Bit in der Anwort eine 0 ansonsten eine 1. Um das zu veranschaulichen einmal der Auszug meines EEProm:
adr data bit byte
000 FF1400000001FFFFFFFFFFFF00009624 1 7
010 0302110014C80A0A0000050000C00000 1 6
020 050000C000C80A214305160014C80A0A 1 5
030 0000050000C00000050000C000C80A21 1 4
040 4305000096240502110014C80A0A0000 1 3
050 050000C00000050000C000C80A214305 1 2
060 160014C80A0A0000050000C000000500 1 1
070 00C000C80A2143050000962404021100 1 0
______________________________________________
0xFF
080 14C80A0A0000050000C00000050000C0 1 7
090 00C80A214305160014C80A0A00000500 1 6
0A0 00C00000050000C000C80A214305FFFF 1 5
0B0 FFFFFFFF110014C80A0A0000050000C0 1 4
0C0 0000050000C000C80A214305160014C8 1 3
0D0 0A0A0000050000C00000050000C000C8 1 2
0E0 0A2143050000E1DD0702110014C80A0A 1 1
0F0 0000050000C00000050000C000C80A21 1 0
______________________________________________
0xFF
100 4305160014C80A0A0000050000C00000 1 0
110 050000C000C80A214305FFFFFFFFFFFF 1 1
120 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 0 2
130 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 0 3
140 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 0 4
150 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 0 5
160 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 0 6
170 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 0 7
______________________________________________
0x03
180 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 0 0
. .
. .
. rest alles FF                                                   0 7
______________________________________________
0x00

somit ergibt sich als Antwort in diesem Beispiel:

FF 000 010 020 030 040 050 060 070
1 1 1 1 1 1 1 1
FF 080 090 0A0 0B0 0C0 0D0 0E0 0F0
1 1 1 1 1 1 1 1
03 100 110 120 130 140 150 160 170
1 1 0 0 0 0 0 0
00 180 190 1A0 1B0 1C0 1D0 1E0 1F0
0 0 0 0 0 0 0 0
00 200 210 220 230 240 250 260 270
0 0 0 0 0 0 0 0
00 280 290 2A0 2B0 2C0 2D0 2E0 2F0
0 0 0 0 0 0 0 0
00 300 310 320 330 340 350 360 370
0 0 0 0 0 0 0 0
00 380 390 3A0 3B0 3C0 3D0 3E0 3F0
0 0 0 0 0 0 0 0

Es tut mir leid. es ist wohl nicht sehr verständlich. daher auch noch ein Auszug aus meiner Homebrew Source. Dann sollte es deutlicher werden,

//hmw.c
.
.

case 0x45: // Read EEProm Blocks E

  packet->type = iMessage;
  packet->payload[0] = 0x65;  //e
  packet->payload[1] = 0; // start address lsb
  packet->payload[2] = 0; // start address msb
  packet->payload[3] = 0x10; // block size
  packet->payloadLength = hmw_read_eeprom_blocks (packet);
  break;
.
.
.
/* returns 1 if a eeprom block is not empty */
uint8_t
hmw_eeprom_blocks_used (const uint16_t addr, const uint8_t size)
{
  for (uint8_t i = 0; i < size; i++)
    {
      if (eeprom_read_byte ((uint8_t*) (uint16_t) (addr + i)) != 0xFF)
{
  return 1;
}
    }
  return 0;
}

uint8_t
hmw_read_eeprom_blocks (Packet_t* packet)
{
  // Request used EEPROM blocks E data 00001040
  uint16_t adrStart = ((uint16_t) (packet->payload[1]) << 8) | packet->payload[2]; // start address of eeprom
  uint8_t adrBlockSize = packet->payload[3];
  uint8_t adrBlockRow = packet->payload[4];
  uint8_t index = 4;
  uint8_t bit = 0;

  for (uint16_t addr = adrStart; addr < (adrBlockSize * adrBlockRow); addr += adrBlockSize)
    {
      if (hmw_eeprom_blocks_used (addr, adrBlockSize))
{
  packet->payload[index] |= (1 << bit);
}
      else
{
  packet->payload[index] &= ~(1 << bit);
}
      bit++;
      if (bit == 8)
{
  index++;
  bit = 0;
}
    }
  return index;
}
.
.
.


Das ganze hätte den Vorteil, daß man nur die benutzen Blöcke aus dem EEProm beim Start von FHEM auslesen müsste.

lg H.

Thorsten Pferdekaemper

Hi,
das hatte ich vor Jahren schon einmal analysiert, siehe Anhang.
Implementiert ist das in der Datei HBWired.cpp:

void HBWDevice::processEmessage(uint8_t const * const frameData) {
// process E-Message

     uint8_t blocksize = frameData[3];
     uint8_t blocknum  = frameData[4];

     // length of response
     txFrameDataLength = 4 + blocknum / 8;
     // care for odd block numbers
     if(blocknum % 8) txFrameDataLength++;
     // we don't need to check the size as it can maximum
     // be 4 + 255 div 8 + 1 = 36
     // init to zero, mainly because we need it later
     memset(txFrameData,0,txFrameDataLength);
     // first byte "e" - answer on "E"
     txFrameData[0]  = 0x65;  //e
     // next 3 bytes are just repeated from request
     txFrameData[1]  = frameData[1];
     txFrameData[2]  = frameData[2];
     txFrameData[3]  = frameData[3];

     // determine whether blocks are used
     for(int block = 0; block <= blocknum; block++) {
       // check this memory block
       for(int byteIdx = 0; byteIdx < blocksize; byteIdx++) {
    if(EEPROM.read(block * blocksize + byteIdx) != 0xFF) {
       bitSet(txFrameData[4 + block / 8], block % 8);
       break;
    }
       }
     };
   };

Die FHEM-Seite verwendet das tatsächlich nicht, soweit ich mich erinnern kann. Im Coding habe ich auf die Schnelle auch nichts dazu gefunden.

Gruß,
   Thorsten
FUIP

hresalg

Hallo Thorsten

Ach, das wusste ich nicht. daß Du das schon hattest. Hat sich also erledigt.
Man könnte es für den start von FHEM auch nutzen.

lg H.