Added temperature support for multical21 and fixed im871a bug.

pull/22/head
weetmuts 2018-11-29 22:25:50 +01:00
rodzic 843038a4f9
commit 016578ebd7
16 zmienionych plików z 221 dodań i 65 usunięć

Wyświetl plik

@ -57,6 +57,7 @@ struct CommandLine {
char *usb_device {};
LinkMode link_mode {};
bool link_mode_set {};
bool no_init {};
vector<MeterInfo> meters;
};

Wyświetl plik

@ -77,7 +77,7 @@ bool parseDV(Telegram *t,
int datalen = difLenBytes(dif);
DEBUG_PARSER("(dvparser debug) dif=%02x datalen=%d \"%s\"\n", dif, datalen, difType(dif).c_str());
if (datalen == -2) {
warning("(dvparser) cannot handle dif %02X ignoring rest of telegram.\n", dif);
debug("(dvparser) cannot handle dif %02X ignoring rest of telegram.\n", dif);
return false;
}
if (dif == 0x2f) {
@ -96,7 +96,7 @@ bool parseDV(Telegram *t,
(*format)++;
}
if (*format == format_end) { warning("(dvparser) warning: unexpected end of data (vif expected)"); break; }
if (*format == format_end) { debug("(dvparser) warning: unexpected end of data (vif expected)"); break; }
uchar vif = **format;
DEBUG_PARSER("(dvparser debug) vif=%02x \"%s\"\n", vif, vifType(vif).c_str());
@ -110,7 +110,7 @@ bool parseDV(Telegram *t,
strprintf(dv, "%02X%02X", dif, vif);
if ((vif&0x80) == 0x80) {
// vif extension
if (*format == format_end) { warning("(dvparser) warning: unexpected end of data (vife expected)"); break; }
if (*format == format_end) { debug("(dvparser) warning: unexpected end of data (vife expected)"); break; }
uchar vife = **format;
DEBUG_PARSER("(dvparser debug) vife=%02x\n", vife);
if (full_header) {
@ -140,7 +140,7 @@ bool parseDV(Telegram *t,
int remaining = std::distance(data, data_end);
if (variable_length) {
debug("(dvparser) varlen %02x\n", *(data+0));
debug("(dvparser debug) varlen %02x\n", *(data+0));
if (remaining > 2) {
datalen = *(data);
} else {
@ -149,7 +149,7 @@ bool parseDV(Telegram *t,
}
DEBUG_PARSER("(dvparser debug) remaining data %d len=%d\n", remaining, datalen);
if (remaining < datalen) {
warning("(dvparser) warning: unexpected end of data\n");
debug("(dvparser) warning: unexpected end of data\n");
datalen = remaining;
}
@ -164,6 +164,10 @@ bool parseDV(Telegram *t,
t->addExplanation(data, datalen, "%s", value.c_str());
DEBUG_PARSER("(dvparser debug) data \"%s\"\n", value.c_str());
}
if (remaining == datalen) {
// We are done here!
break;
}
}
string format_string = bin2hex(format_bytes);

Wyświetl plik

@ -43,6 +43,10 @@ struct MeterIperl : public virtual WaterMeter, public virtual MeterCommonImpleme
bool hasTargetWaterConsumption();
double maxFlow();
bool hasMaxFlow();
double flowTemperature();
bool hasFlowTemperature();
double externalTemperature();
bool hasExternalTemperature();
string statusHumanReadable();
string status();
@ -225,6 +229,26 @@ bool MeterIperl::hasMaxFlow()
return false;
}
double MeterIperl::flowTemperature()
{
return 127;
}
bool MeterIperl::hasFlowTemperature()
{
return false;
}
double MeterIperl::externalTemperature()
{
return 127;
}
bool MeterIperl::hasExternalTemperature()
{
return false;
}
string MeterIperl::statusHumanReadable()
{
return "";

Wyświetl plik

@ -59,6 +59,12 @@ struct MeterMultical21 : public virtual WaterMeter, public virtual MeterCommonIm
// Max flow during last month or last 24 hours depending on meter configuration.
double maxFlow();
bool hasMaxFlow();
// Water temperature
double flowTemperature();
bool hasFlowTemperature();
// Surrounding temperature
double externalTemperature();
bool hasExternalTemperature();
// statusHumanReadable: DRY,REVERSED,LEAK,BURST if that status is detected right now, followed by
// (dry 15-21 days) which means that, even it DRY is not active right now,
@ -87,6 +93,10 @@ private:
bool has_target_volume_ {};
double max_flow_ {};
bool has_max_flow_ {};
double flow_temperature_ { 127 };
bool has_flow_temperature_ {};
double external_temperature_ { 127 };
bool has_external_temperature_ {};
const char *meter_name_; // multical21 or flowiq3100
int expected_version_ {}; // 0x1b for Multical21 and 0x1d for FlowIQ3100
@ -138,6 +148,26 @@ bool MeterMultical21::hasMaxFlow()
return has_max_flow_;
}
double MeterMultical21::flowTemperature()
{
return flow_temperature_;
}
bool MeterMultical21::hasFlowTemperature()
{
return has_flow_temperature_;
}
double MeterMultical21::externalTemperature()
{
return external_temperature_;
}
bool MeterMultical21::hasExternalTemperature()
{
return has_external_temperature_;
}
WaterMeter *createMultical21(WMBus *bus, const char *name, const char *id, const char *key, MeterType mt)
{
if (mt != MULTICAL21_METER && mt != FLOWIQ3100_METER) {
@ -215,13 +245,6 @@ void MeterMultical21::processContent(Telegram *t)
if (frame_type == 0x79)
{
if (t->content.size() != 15) {
warning("(%s) warning: Unexpected length of short frame %zu. Expected 15 bytes! ", meter_name_,
t->content.size());
padWithZeroesTo(&t->content, 15, &t->content);
warning("\n");
}
// 0,1 = crc for format signature = hash over DRH (Data Record Header)
// The DRH is the dif(dife)vif(vife) bytes for all the records...
// This hash should be used to pick up a suitable format string.
@ -270,18 +293,8 @@ void MeterMultical21::processContent(Telegram *t)
else
if (frame_type == 0x78)
{
if (t->content.size() != 22) {
warning("(%s) warning: Unexpected length of long frame %zu. Expected 22 bytes! ", meter_name_, t->content.size());
padWithZeroesTo(&t->content, 22, &t->content);
warning("\n");
}
map<string,pair<int,string>> values;
parseDV(t, t->content.begin()+3, t->content.size()-3-2, &values);
// There are two more bytes in the data. Unknown purpose.
int val0 = t->content[20];
int val1 = t->content[21];
parseDV(t, t->content.begin()+3, t->content.size()-3, &values);
int offset;
@ -293,13 +306,19 @@ void MeterMultical21::processContent(Telegram *t)
t->addMoreExplanation(offset, " total consumption (%f m3)", total_water_consumption_);
extractDVdouble(&values, "4413", &offset, &target_volume_);
has_target_volume_ = true;
has_target_volume_ = true;
t->addMoreExplanation(offset, " target consumption (%f m3)", target_volume_);
// To unknown bytes, seems to be very constant.
vector<uchar>::iterator unknowns = t->content.begin()+20;
t->addExplanation(unknowns, 2, "%02x%02x unknown", val0, val1);
} else {
extractDVdouble(&values, "615B", &offset, &flow_temperature_);
has_flow_temperature_ = true;
t->addMoreExplanation(offset, " flow temperature (%f °C)", flow_temperature_);
extractDVdouble(&values, "6167", &offset, &external_temperature_);
has_external_temperature_ = true;
t->addMoreExplanation(offset, " external temperature (%f °C)", external_temperature_);
}
else
{
warning("(%s) warning: unknown frame %02x (did you use the correct encryption key?)\n", meter_name_, frame_type);
}
}
@ -434,21 +453,25 @@ void MeterMultical21::printMeter(string *human_readable,
char buf[65536];
buf[65535] = 0;
snprintf(buf, sizeof(buf)-1, "%s\t%s\t% 3.3f m3\t% 3.3f m3\t%s\t%s",
snprintf(buf, sizeof(buf)-1, "%s\t%s\t% 3.3f m3\t% 3.3f m3\t% 2.0f°C\t% 2.0f°C\t%s\t%s",
name().c_str(),
id().c_str(),
totalWaterConsumption(),
targetWaterConsumption(),
flowTemperature(),
externalTemperature(),
statusHumanReadable().c_str(),
datetimeOfUpdateHumanReadable().c_str());
*human_readable = buf;
snprintf(buf, sizeof(buf)-1, "%s%c%s%c%f%c%f%c%s%c%s",
snprintf(buf, sizeof(buf)-1, "%s%c" "%s%c" "%f%c" "%f%c" "%.0f%c" "%.0f%c" "%s%c" "%s",
name().c_str(), separator,
id().c_str(), separator,
totalWaterConsumption(), separator,
targetWaterConsumption(), separator,
flowTemperature(), separator,
externalTemperature(), separator,
statusHumanReadable().c_str(), separator,
datetimeOfUpdateRobot().c_str());
@ -465,6 +488,8 @@ void MeterMultical21::printMeter(string *human_readable,
QS(id,%s)
Q(total_m3,%f)
Q(target_m3,%f)
Q(flow_temperature,%.0f)
Q(external_temperature,%.0f)
QS(current_status,%s)
QS(time_dry,%s)
QS(time_reversed,%s)
@ -478,6 +503,8 @@ void MeterMultical21::printMeter(string *human_readable,
id().c_str(),
totalWaterConsumption(),
targetWaterConsumption(),
flowTemperature(),
externalTemperature(),
status().c_str(), // DRY REVERSED LEAK BURST
timeDry().c_str(),
timeReversed().c_str(),
@ -492,6 +519,8 @@ void MeterMultical21::printMeter(string *human_readable,
envs->push_back(string("METER_ID=")+id());
envs->push_back(string("METER_TOTAL_M3=")+to_string(totalWaterConsumption()));
envs->push_back(string("METER_TARGET_M3=")+to_string(targetWaterConsumption()));
envs->push_back(string("METER_FLOW_TEMPERATURE=")+to_string(flowTemperature()));
envs->push_back(string("METER_EXTERNAL_TEMPERATURE=")+to_string(externalTemperature()));
envs->push_back(string("METER_STATUS=")+status());
envs->push_back(string("METER_TIME_DRY=")+timeDry());
envs->push_back(string("METER_TIME_REVERSED=")+timeReversed());

Wyświetl plik

@ -119,11 +119,12 @@ void MeterMultical302::processContent(Telegram *t) {
t->addExplanation(bytes, 1, "%02x frame type (%s)", frame_type, frameTypeKamstrupC1(frame_type).c_str());
if (frame_type == 0x79) {
if (t->content.size() != 17) {
/*if (t->content.size() != 17) {
fprintf(stderr, "(multical302) warning: Unexpected length of frame %zu. Expected 17 bytes! ", t->content.size());
padWithZeroesTo(&t->content, 17, &t->content);
warning("\n");
}
}*/
// This code should be rewritten to use parseDV see the Multical21 code.
// But I cannot do this without more examples of 302 telegrams.
@ -151,11 +152,11 @@ void MeterMultical302::processContent(Telegram *t) {
}
else if (frame_type == 0x78)
{
if (t->content.size() != 26) {
/*if (t->content.size() != 26) {
fprintf(stderr, "(multical302) warning: Unexpected length of frame %zu. Expected 26 bytes! ", t->content.size());
padWithZeroesTo(&t->content, 26, &t->content);
warning("\n");
}
}*/
// This code should be rewritten to use parseDV see the Multical21 code.
// But I cannot do this without more examples of 302 telegrams.

Wyświetl plik

@ -42,6 +42,10 @@ struct MeterSupercom587 : public virtual WaterMeter, public virtual MeterCommonI
bool hasTargetWaterConsumption();
double maxFlow();
bool hasMaxFlow();
double flowTemperature();
bool hasFlowTemperature();
double externalTemperature();
bool hasExternalTemperature();
string statusHumanReadable();
string status();
@ -223,6 +227,26 @@ bool MeterSupercom587::hasMaxFlow()
return false;
}
double MeterSupercom587::flowTemperature()
{
return 127;
}
bool MeterSupercom587::hasFlowTemperature()
{
return false;
}
double MeterSupercom587::externalTemperature()
{
return 127;
}
bool MeterSupercom587::hasExternalTemperature()
{
return false;
}
string MeterSupercom587::statusHumanReadable()
{
return "";

Wyświetl plik

@ -73,6 +73,10 @@ struct WaterMeter : public virtual Meter {
virtual bool hasTargetWaterConsumption() = 0;
virtual double maxFlow() = 0;
virtual bool hasMaxFlow() = 0;
virtual double flowTemperature() = 0; // °C
virtual bool hasFlowTemperature() = 0;
virtual double externalTemperature() = 0; // °C
virtual bool hasExternalTemperature() = 0;
virtual string statusHumanReadable() = 0;
virtual string status() = 0;

Wyświetl plik

@ -1,12 +1,12 @@
# Test Multical21 C1 telegrams
# short telegram
telegram=|23442D2C998734761B168D2093E13CBA20|967F79EDA8047B7100F4180000E918|
{"media":"cold water","meter":"multical21","name":"MyTapWater","id":"76348799","total_m3":6.388000,"target_m3":6.377000,"current_status":"DRY","time_dry":"22-31 days","time_reversed":"","time_leaking":"","time_bursting":"","timestamp":"1111-11-11T11:11:11Z"}
telegram=|23442D2C998734761B168D208870F81821|09EA79EDA869F57100F8180000F41800007F17|
{"media":"cold water","meter":"multical21","name":"MyTapWater","id":"76348799","total_m3":6.392000,"target_m3":6.388000,"flow_temperature":0,"external_temperature":0,"current_status":"DRY","time_dry":"22-31 days","time_reversed":"","time_leaking":"","time_bursting":"","timestamp":"1111-11-11T11:11:11Z"}
# full telegram
telegram=|2A442D2C998734761B168D2049F03FBA20|39A17802FF2071000413F41800004413E9180000615B|
{"media":"cold water","meter":"multical21","name":"MyTapWater","id":"76348799","total_m3":6.388000,"target_m3":6.377000,"current_status":"DRY","time_dry":"22-31 days","time_reversed":"","time_leaking":"","time_bursting":"","timestamp":"1111-11-11T11:11:11Z"}
telegram=|2A442D2C998734761B168D208971F81821|542F7802FF2071000413F81800004413F4180000615B7F616717|
{"media":"cold water","meter":"multical21","name":"MyTapWater","id":"76348799","total_m3":6.392000,"target_m3":6.388000,"flow_temperature":127,"external_temperature":23,"current_status":"DRY","time_dry":"22-31 days","time_reversed":"","time_leaking":"","time_bursting":"","timestamp":"1111-11-11T11:11:11Z"}
# Test Multical302 C1 telegrams

Wyświetl plik

@ -1,13 +1,12 @@
# Test Supercom587 T1 telegrams
telegram=|A244EE4D785634123C067A73000000|0C1334190000426CE1F14C130000000082046C21298C0413330000008D04931E3A3CFE3300000033000000330000003300000033000000330000003300000033000000330000003300000033000000330000004300000034180000046D0113412B03FD6CDE120082206C5C290BFD0F0200018C4079678885238310FD3100000082106C01018110FD610002FD66020002|
{"media":"warm water","meter":"supercom587","name":"MyWarmWater","id":"12345678","total_m3":1.934000,"timestamp":"1111-11-11T11:11:11Z"}
telegram=|A244EE4D785634123C067A8F000000|0C1348550000426CE1F14C130000000082046C21298C0413330000008D04931E3A3CFE3300000033000000330000003300000033000000330000003300000033000000330000003300000033000000330000004300000034180000046D0D0B5C2B03FD6C5E150082206C5C290BFD0F0200018C4079678885238310FD3100000082106C01018110FD610002FD66020002FD170000|
{"media":"warm water","meter":"supercom587","name":"MyWarmWater","id":"12345678","total_m3":5.548000,"timestamp":"1111-11-11T11:11:11Z"}
telegram=|A244EE4D111111113C077A72000000|0C1374140000426CE1F14C130000000082046C21298C0413010000008D04931E3A3CFE0100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000001600000031130000046D0113412B03FD6CDF120082206C5C290BFD0F0200018C4079629885238310FD3100000082106C01018110FD610002FD66020002|
{"media":"water","meter":"supercom587","name":"MyColdWater","id":"11111111","total_m3":1.474000,"timestamp":"1111-11-11T11:11:11Z"}
telegram=|A244EE4D111111113C077AAC000000|0C1389490000426CE1F14C130000000082046C21298C0413010000008D04931E3A3CFE0100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000001600000031130000046D0A0C5C2B03FD6C60150082206C5C290BFD0F0200018C4079629885238310FD3100000082106C01018110FD610002FD66020002FD170000|
{"media":"water","meter":"supercom587","name":"MyColdWater","id":"11111111","total_m3":4.989000,"timestamp":"1111-11-11T11:11:11Z"}
# Test iPerl T1 telegram
# 12345678 "1234567890ABCDEF1234567890ABCDEF"
telegram=|1E44AE4C7856341268077AB5000000|53cb05c02cf40b38e4cfe6a9f6565ec27261ae620df9257179197ef2dc6512f2|
{"media":"water","meter":"iperl","name":"MoreWater","id":"12345678","total_m3":3.699000,"timestamp":"1111-11-11T11:11:11Z"}
telegram=|1E44AE4C9956341268077A36001005|2F2F0413181E0000023B00002F2F2F2F|
{"media":"water","meter":"iperl","name":"MoreWater","id":"12345699","total_m3":7.704000,"timestamp":"1111-11-11T11:11:11Z"}

Wyświetl plik

@ -14,7 +14,7 @@ then
diff test_expected.txt test_responses.txt
if [ "$?" == "0" ]
then
echo OK
echo C1 OK
fi
else
Failure.
@ -24,7 +24,7 @@ cat simulation_t1.txt | grep '^{' > test_expected.txt
$PROG --robot=json simulation_t1.txt \
MyWarmWater supercom587 12345678 "" \
MyColdWater supercom587 11111111 "" \
MoreWater iperl 12345678 "1234567890ABCDEF1234567890ABCDEF" \
MoreWater iperl 12345699 "" \
> test_output.txt
if [ "$?" == "0" ]
then
@ -32,7 +32,7 @@ then
diff test_expected.txt test_responses.txt
if [ "$?" == "0" ]
then
echo OK
echo T1 OK
fi
else
Failure.

32
util.cc
Wyświetl plik

@ -406,3 +406,35 @@ uint16_t crc16_EN13757(uchar *data, size_t len)
return (~crc);
}
#define CRC16_INIT_VALUE 0xFFFF
#define CRC16_GOOD_VALUE 0x0F47
#define CRC16_POLYNOM 0x8408
uint16_t crc16_CCITT(uchar *data, uint16_t length)
{
uint16_t initVal = CRC16_INIT_VALUE;
uint16_t crc = initVal;
while(length--)
{
int bits = 8;
uchar byte = *data++;
while(bits--)
{
if((byte & 1) ^ (crc & 1))
{
crc = (crc >> 1) ^ CRC16_POLYNOM;
}
else
crc >>= 1;
byte >>= 1;
}
}
return crc;
}
bool crc16_CCITT_check(uchar *data, uint16_t length)
{
uint16_t crc = ~crc16_CCITT(data, length);
return crc == CRC16_GOOD_VALUE;
}

4
util.h
Wyświetl plik

@ -72,4 +72,8 @@ int parseTime(std::string time);
uint16_t crc16_EN13757(uchar *data, size_t len);
// This crc is used by im871a for its serial communication.
uint16_t crc16_CCITT(uchar *data, uint16_t length);
bool crc16_CCITT_check(uchar *data, uint16_t length);
#endif

Wyświetl plik

@ -26,7 +26,7 @@
#define LIST_OF_LINK_MODES X(LinkModeC1)X(LinkModeT1)X(UNKNOWN_LINKMODE)
// In link mode T1, the meter transmits a telegram every few seconds.
// In link mode T1, the meter transmits a telegram every few seconds or minutes.
// Suitable for drive-by/walk-by collection of meter values.
// Link mode C1 is like T1 but uses less energy when transmitting due to

Wyświetl plik

@ -222,7 +222,10 @@ void WMBusAmber::waitForResponse() {
}
FrameStatus WMBusAmber::checkAMB8465Frame(vector<uchar> &data,
size_t *frame_length, int *msgid_out, int *payload_len_out, int *payload_offset)
size_t *frame_length,
int *msgid_out,
int *payload_len_out,
int *payload_offset)
{
if (data.size() == 0) return PartialFrame;
int payload_len = 0;
@ -387,9 +390,6 @@ bool detectAMB8465(string device, SerialCommunicationManager *manager)
serial->close();
string sent = bin2hex(msg);
string recv = bin2hex(data);
if (data.size() < 8 ||
data[0] != 0xff ||
data[1] != (0x80 | msg[1]) ||

Wyświetl plik

@ -251,19 +251,21 @@ void WMBusIM871A::setLinkMode(LinkMode lm)
}
pthread_mutex_lock(&command_lock_);
vector<uchar> msg(8);
vector<uchar> msg(10);
msg[0] = IM871A_SERIAL_SOF;
msg[1] = DEVMGMT_ID;
sent_command_ = msg[2] = DEVMGMT_MSG_SET_CONFIG_REQ;
msg[3] = 3; // Len
msg[3] = 6; // Len
msg[4] = 0; // Temporary
msg[5] = 2; // iff1 bits: Set Radio Mode only
msg[5] = 2; // iff1 bits: Set Radio Mode
if (lm == LinkModeC1) {
msg[6] = (int)im871a_C1a;
} else {
msg[6] = (int)im871a_T1;
}
msg[7] = 0; // iff2 bits: Set nothing
msg[7] = 16+32; // iff2 bits: Set rssi+timestamp
msg[8] = 1; // Enable rssi
msg[9] = 1; // Enable timestamp
verbose("(im871a) set link mode %02x\n", msg[6]);
serial()->send(msg);
@ -293,6 +295,7 @@ FrameStatus WMBusIM871A::checkFrame(vector<uchar> &data,
{
if (data.size() == 0) return PartialFrame;
if (data[0] != 0xa5) return ErrorInFrame;
int ctrlbits = (data[1] & 0xf0) >> 4;
if (ctrlbits & 1) return ErrorInFrame; // Bit 1 is reserved, we do not expect it....
bool has_timestamp = ((ctrlbits&2)==2);
@ -319,6 +322,35 @@ FrameStatus WMBusIM871A::checkFrame(vector<uchar> &data,
*frame_length = *payload_offset+payload_len+(has_timestamp?4:0)+(has_rssi?1:0)+(has_crc16?2:0);
if (data.size() < *frame_length) return PartialFrame;
int i = *payload_offset + payload_len;
if (has_timestamp) {
uint32_t a = data[i];
uint32_t b = data[i+1];
uint32_t c = data[i+2];
uint32_t d = data[i+3];
uint32_t ts = a+b*256+c*256*256+d*256*256*256;
debug("(im871a) timestamp %08x\n", ts);
i += 4;
}
if (has_rssi) {
uint32_t rssi = data[i];
debug("(im871a) rssi %02x\n", rssi);
i++;
}
if (has_crc16) {
uint32_t a = data[i];
uint32_t b = data[i+1];
uint32_t crc16 = a+b*256;
i+=2;
uint16_t gotcrc = ~crc16_CCITT(&data[1], i-1-2);
bool crcok = crc16_CCITT_check(&data[1], i-1);
debug("(im871a) got crc16 %04x expected %04x\n", crc16, gotcrc);
if (!crcok) {
warning("(im871a) warning: got wrong crc %04x expected %04x\n", gotcrc, crc16);
}
}
return FullFrame;
}
@ -348,14 +380,18 @@ void WMBusIM871A::processSerialData()
if (status == FullFrame) {
vector<uchar> payload;
if (payload_len > 0) {
if (payload_len > 0)
{
if (endpoint == RADIOLINK_ID &&
msgid == RADIOLINK_MSG_WMBUSMSG_IND)
{
uchar l = payload_len;
payload.insert(payload.begin(), &l, &l+1); // Re-insert the len byte.
}
payload.insert(payload.end(), read_buffer_.begin()+payload_offset, read_buffer_.begin()+payload_len);
// Insert the payload.
payload.insert(payload.end(),
read_buffer_.begin()+payload_offset,
read_buffer_.begin()+payload_offset+payload_len);
}
read_buffer_.erase(read_buffer_.begin(), read_buffer_.begin()+frame_length);

Wyświetl plik

@ -57,10 +57,6 @@ void decryptMode1_AES_CTR(Telegram *t, vector<uchar> &aeskey)
vector<uchar> dec(decrypt, decrypt+remaining);
debugPayload("(Mode1) decrypted first block", dec);
if (content.size() > 22) {
warning("(Mode1) warning: decryption received too many bytes of content! "
"Got %zu bytes, expected at most 22.\n", content.size());
}
if (content.size() > 16) {
// Yay! Lets decrypt a second block. Full frame content is 22 bytes.
// So a second block should enough for everyone!
@ -146,8 +142,10 @@ bool loadFormatBytesFromSignature(uint16_t format_signature, vector<uchar> *form
{
hex2bin("02FF2004134413", format_bytes);
// The hash of this string should equal the format signature above.
uint16_t format_hash = crc16_EN13757(&(*format_bytes)[0], 7);
debug("(utils) format signature %4X format hash %4X\n", format_signature, format_hash);
uint16_t format_hash1 = crc16_EN13757(&(*format_bytes)[0], 7);
uint16_t format_hash2 = ~crc16_CCITT(&(*format_bytes)[0], 7);
debug("(utils) format signature %4X format hash a=%4X b=%4X c=%4X d=%4X\n",
format_signature, format_hash1, (uint16_t)(~format_hash1), format_hash2, (uint16_t)(~format_hash2));
return true;
}
// Unknown format signature.