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

Update esa.c #2888

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 110 additions & 29 deletions src/devices/esa.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

Copyright (C) 2016 TylerDurden23, initial cleanup by Benjamin Larsson

Bug fixes / modifications for GIRA WST: D. Clawin (DCTRONIC Engineering)

Check failure on line 7 in src/devices/esa.c

View workflow job for this annotation

GitHub Actions / Check code style

TRAILING whitespace error
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
Expand All @@ -13,72 +15,149 @@

#define MAXMSG 40 // ESA messages

static uint8_t decrypt_esa(uint8_t *b)
static uint16_t decrypt_esa(uint8_t *b,unsigned blen)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add space before keywords, , unsigned

{
uint8_t pos = 0;
uint8_t i = 0;
uint8_t salt = 0x89;
uint16_t crc = 0xf00f;
uint8_t byte;
// uint16_t crc = 0xf00f;
uint16_t crc = 0;

for (i = 0; i < 15; i++) {
uint8_t i = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reduce scope to the loop, for (int i; ...

uint8_t byte;
for (i = 0; i < blen-3; i++) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add spaces around operators: blen - 3

byte = b[pos];
crc += byte;
b[pos++] ^= salt;
salt = byte + 0x24;
}
byte = b[pos];
crc += byte;
// byte = b[pos]; // ??

Check failure on line 33 in src/devices/esa.c

View workflow job for this annotation

GitHub Actions / Check code style

TRAILING whitespace error
crc += b[pos];;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove extra semicolon ;

b[pos++] ^= 0xff;

crc -= (b[pos] << 8) | b[pos + 1];
crc = ( (b[blen-2] << 8) | b[blen-1]) - crc ; // substract from CRC at EOM
return crc;
}

/**
ELV Energy Counter ESA 1000/2000.
ELV Energy Counter ESA 1000/2000, GIRA EHZ
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First comment line needs a dot at the end.


@todo Documentation needed.

ELV-ESA devices and Gira-EHZ share modulation and decryption. Only CRC base is different.


ELVx000 data format, copied from FHEM source: (soory, in German)

ss Sequenze und Sequenzwiederhohlung mit gesetzten h?chsten Bit
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preformatted blocks need an indent of four spaces

dddd Device
cccc Code + Batterystate
tttttttt Gesamtimpules
aaaa Impulse je Sequenz
zzzzzz Zeitstempel seit Start des Adapters (ESA1000)
kkkk Impulse je kWh/m3

GIRA data format (bytes), reverse engineered:

H II SS J PP TTT II UUUUUU KK CC

- H: Header with sequence number
- I: Dev ID
- S: Status and device type (same for all Gira cc1e)
- J: Single byte: 04
- P: power in Watts
- T: Total ticks since startup
- I: Ticks since last message
- U: Unknown, appears always zero
- K: Ticks / kWh xor 1st byte of devid
- C: CRC, sum of message bytes + 0xee11


*/
static int esa_cost_callback(r_device *decoder, bitbuffer_t *bitbuffer)
{
data_t *data;
uint8_t b[MAXMSG];
uint16_t crc ;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove space before semicolon

unsigned len ;

unsigned is_retry, sequence_id, deviceid, impulses;
char *model;

unsigned is_retry, sequence_id, deviceid;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use one line for each var.

unsigned status=0;
unsigned power=0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add space around equal sign

unsigned impulse_constant, impulses_val, impulses_total;
float energy_total_val, energy_impulse_val;

if (bitbuffer->bits_per_row[0] != 160 || bitbuffer->num_rows != 1)
return DECODE_ABORT_LENGTH;
//if (bitbuffer->bits_per_row[0] != 160 || bitbuffer->num_rows != 1)
//
// allow 16 bit preamble
len=bitbuffer->bits_per_row[0] ; // # of bytes

// remove first two bytes?
bitbuffer_extract_bytes(bitbuffer, 0, 16, b, 160 - 16);
if ( (! (len == 176 || len == 160 )) || bitbuffer->num_rows != 1 )
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove spaces inside parens: if ((!(len == 176...
Use braces also on single line blocks if () {

return DECODE_ABORT_LENGTH;

if (decrypt_esa(b))
// remove first two bytes

bitbuffer_extract_bytes(bitbuffer, 0, 16, b, len-16 );

crc=decrypt_esa(b,len/8-2) ; // pass packet length w/o header in bytes

Check failure on line 103 in src/devices/esa.c

View workflow job for this annotation

GitHub Actions / Check code style

TRAILING whitespace error
// decoder_logf(decoder, 1, __func__,

Check failure on line 104 in src/devices/esa.c

View workflow job for this annotation

GitHub Actions / Check code style

TRAILING whitespace error
// "Decoded: %02x %02x%02x %02x%02x %02x%02x %02x%02x%02x %02x%02x %02x%02x%02x %02x%2x ",
// b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7],
// b[8],b[9],b[10],b[11],b[12],b[13],b[14],b[15],b[16] );
// decoder_logf(decoder, 1, __func__,"Checks: %4i %02x %02x %02x",len,b[17],b[18],b[19]) ;

Check failure on line 109 in src/devices/esa.c

View workflow job for this annotation

GitHub Actions / Check code style

TRAILING whitespace error
switch(crc) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this easier to write as if (...) {} else if (...) {} else {}?

case 0xf00f: { // ESA
if (b[3] == 0x01) model = "ESAx000WZ";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need different protocol "model" keys?

else if (b[3] == 0x03) model = "ESA1000Z" ;
else model = "ESA-unknown";

Check failure on line 115 in src/devices/esa.c

View workflow job for this annotation

GitHub Actions / Check code style

TRAILING whitespace error
is_retry = (b[0] >> 7);
sequence_id = (b[0] & 0x7f);
deviceid = ((unsigned)b[1] << 8) | b[2] ; // tbd
status = ((unsigned)b[3] << 8) | b[4] ; // FHEM uses bit 7 as bat status
impulses_val = (b[9] << 8) | b[10];
impulses_total = ((unsigned)b[5] << 24) | (b[6] << 16) | (b[7] << 8) | b[8];
impulse_constant = ((b[14] << 8) | b[15]) ^ b[1];
energy_total_val = 1.0f * impulses_total / impulse_constant;
energy_impulse_val = 1.0f * impulses_val / impulse_constant;
break;
}
case 0xee11: { // GIRA Wetterstation/Energiezaehler
model = "Gira-EHZ" ;
is_retry = (b[0] >> 6) & 0x01 ;
sequence_id = (b[0] & 0x3f) ;
deviceid = ((unsigned)b[1] << 8) | b[2] ; // tbd
status = ((unsigned)b[3] << 8) | b[4] ; // bat status in here ?
impulses_val = (b[11] << 8) | b[12] ;
impulses_total = ( ((unsigned)b[8]<<16) | (b[9]<<8) | b[10] ) ;
impulse_constant = (b[16] << 8) | (b[17] ^ b[1]) ; // experimental: xor DD ??
energy_total_val = 1.0f * impulses_total / impulse_constant;
energy_impulse_val = 1.0f * impulses_val / impulse_constant;
power = (b[6] << 8) | b[7] ; // Power in Watts, add-on for GIRA
break ;
}
default: {

Check failure on line 141 in src/devices/esa.c

View workflow job for this annotation

GitHub Actions / Check code style

TRAILING whitespace error
decoder_logf(decoder, 1, __func__, "Bad CRC: %04x",crc );
return DECODE_FAIL_MIC; // checksum fail

is_retry = (b[0] >> 7);
sequence_id = (b[0] & 0x7f);
deviceid = (b[1]);
impulses = (b[3] << 8) | b[4];
impulse_constant = ((b[14] << 8) | b[15]) ^ b[1];
impulses_total = ((unsigned)b[5] << 24) | (b[6] << 16) | (b[7] << 8) | b[8];
impulses_val = (b[9] << 8) | b[10];
energy_total_val = 1.0f * impulses_total / impulse_constant;
energy_impulse_val = 1.0f * impulses_val / impulse_constant;
}
}

/* clang-format off */
data = data_make(
"model", "Model", DATA_STRING, "ESA-x000",
//"model", "Model", DATA_STRING, "ESA-x000",
"model", "Model", DATA_STRING, model,
"id", "Id", DATA_INT, deviceid,
"impulses", "Impulses", DATA_INT, impulses,
"impulses", "Impulses", DATA_INT, impulses_val,
"impulses_total", "Impulses Total", DATA_INT, impulses_total,
"impulse_constant", "Impulse Constant", DATA_INT, impulse_constant,
"total_kWh", "Energy Total", DATA_DOUBLE, energy_total_val,
"impulse_kWh", "Energy Impulse", DATA_DOUBLE, energy_impulse_val,
"sequence_id", "Sequence ID", DATA_INT, sequence_id,
"is_retry", "Is Retry", DATA_INT, is_retry,
"status", "Status/Type", DATA_INT, status,
"power", "Power", DATA_INT, power, // added for GIRA
"mic", "Integrity", DATA_STRING, "CRC",
NULL);
/* clang-format on */
Expand All @@ -97,12 +176,14 @@
"impulse_kWh",
"sequence_id",
"is_retry",
"status",
"power", // added for GIRA
"mic",
NULL,
};

r_device const esa_energy = {
.name = "ESA1000 / ESA2000 Energy Monitor",
.name = "ESA1000 / ESA2000 Energy Monitor, GIRA Wetterstation",
.modulation = OOK_PULSE_MANCHESTER_ZEROBIT,
.short_width = 260,
.long_width = 0,
Expand Down
Loading