wmbusmeters/src/meter_qsmoke.cc

371 wiersze
13 KiB
C++

/*
Copyright (C) 2021 Fredrik Öhrström (gpl-3.0-or-later)
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 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include"dvparser.h"
#include"meters.h"
#include"meters_common_implementation.h"
#include"wmbus.h"
#include"wmbus_utils.h"
#define INFO_CODE_SMOKE 0x0001
struct MeterQSmoke : public virtual MeterCommonImplementation
{
MeterQSmoke(MeterInfo &mi);
string status();
bool smokeDetected();
private:
void processContent(Telegram *t);
private:
uchar counter_ {};
uint16_t info_codes_ {};
bool error_ {};
uint8_t ui_event_count_ {};
string ui_event_date_ {};
uint8_t al_event_count_ {};
string al_event_date_ {};
uint32_t error_flags_ {};
string error_date_ {};
string device_date_time_ {};
int duration_since_readout_s_ {};
};
MeterQSmoke::MeterQSmoke(MeterInfo &mi) :
MeterCommonImplementation(mi, "qsmoke")
{
setMeterType(MeterType::SmokeDetector);
setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV);
addLinkMode(LinkMode::C1);
addPrint("status", Quantity::Text,
[&](){ return status(); },
"The current status: OK, SMOKE or ERROR.",
PrintProperty::FIELD | PrintProperty::JSON);
addPrint("counter", Quantity::Counter,
[&](Unit u){ return counter_; },
"Transmission counter.",
PrintProperty::JSON);
addPrint("device_date_time", Quantity::Text,
[&](){ return device_date_time_; },
"Device date time.",
PrintProperty::JSON);
}
shared_ptr<Meter> createQSmoke(MeterInfo &mi)
{
return shared_ptr<Meter>(new MeterQSmoke(mi));
}
bool MeterQSmoke::smokeDetected()
{
return info_codes_ & INFO_CODE_SMOKE;
}
/*
(wmbus) 0b: 01 dif (8 Bit Integer/Binary Instantaneous value)
(wmbus) 0c: FD vif (Second extension FD of VIF-codes)
(wmbus) 0d: 08 vife (Access Number (transmission count))
(wmbus) 0e: F0
(wmbus) 0f: 81 dif (8 Bit Integer/Binary Instantaneous value)
(wmbus) 10: 02 dife (subunit=0 tariff=0 storagenr=4)
(wmbus) 11: 7C vif (VIF in following string (length in first byte))
(wmbus) 12: 03 viflen (3)
(wmbus) 13: 49 vif (I)
(wmbus) 14: 55 vif (U)
(wmbus) 15: 23 vif (#)
(wmbus) 16: 00
(wmbus) 17: 82 dif (16 Bit Integer/Binary Instantaneous value)
(wmbus) 18: 02 dife (subunit=0 tariff=0 storagenr=4)
(wmbus) 19: 6C vif (Date type G)
(wmbus) 1a: FFFF
(wmbus) 1c: 81 dif (8 Bit Integer/Binary Instantaneous value)
(wmbus) 1d: 03 dife (subunit=0 tariff=0 storagenr=6)
(wmbus) 1e: 7C vif (VIF in following string (length in first byte))
(wmbus) 1f: 03 viflen (3)
(wmbus) 20: 4C vif (L)
(wmbus) 21: 41 vif (A)
(wmbus) 22: 23 vif (#)
(wmbus) 23: 00
(wmbus) 24: 82 dif (16 Bit Integer/Binary Instantaneous value)
(wmbus) 25: 03 dife (subunit=0 tariff=0 storagenr=6)
(wmbus) 26: 6C vif (Date type G)
(wmbus) 27: FFFF
(wmbus) 29: 03 dif (24 Bit Integer/Binary Instantaneous value)
(wmbus) 2a: FD vif (Second extension FD of VIF-codes)
(wmbus) 2b: 17 vife (Error flags (binary))
(wmbus) 2c: 000000
(wmbus) 2f: 32 dif (16 Bit Integer/Binary Value during error state)
(wmbus) 30: 6C vif (Date type G)
(wmbus) 31: FFFF
(wmbus) 33: 04 dif (32 Bit Integer/Binary Instantaneous value)
(wmbus) 34: 6D vif (Date and time type)
(wmbus) 35: 0F0ABC2B
(wmbus) 39: 02 dif (16 Bit Integer/Binary Instantaneous value)
(wmbus) 3a: FD vif (Second extension FD of VIF-codes)
(wmbus) 3b: AC vife (Duration since last readout [second(s)])
(wmbus) 3c: 7E vife (Reserved)
(wmbus) 3d: 1100
Another version 0x23
(qsmoke) 0f: 81 dif (8 Bit Integer/Binary Instantaneous value)
(qsmoke) 10: 02 dife (subunit=0 tariff=0 storagenr=4)
(qsmoke) 11: 7C vif (VIF in following string (length in first byte))
(qsmoke) 12: 03 viflen (3)
(qsmoke) 13: 49 vif (I)
(qsmoke) 14: 55 vif (U)
(qsmoke) 15: 23 vif (#)
(qsmoke) 16: 00
(qsmoke) 17: 82 dif (16 Bit Integer/Binary Instantaneous value)
(qsmoke) 18: 02 dife (subunit=0 tariff=0 storagenr=4)
(qsmoke) 19: 6C vif (Date type G)
(qsmoke) 1a: FFFF
(qsmoke) 1c: 81 dif (8 Bit Integer/Binary Instantaneous value)
(qsmoke) 1d: 03 dife (subunit=0 tariff=0 storagenr=6)
(qsmoke) 1e: 7C vif (VIF in following string (length in first byte))
(qsmoke) 1f: 03 viflen (3)
(qsmoke) 20: 4C vif (L)
(qsmoke) 21: 41 vif (A)
(qsmoke) 22: 23 vif (#)
(qsmoke) 23: 00
(qsmoke) 24: 82 dif (16 Bit Integer/Binary Instantaneous value)
(qsmoke) 25: 03 dife (subunit=0 tariff=0 storagenr=6)
(qsmoke) 26: 6C vif (Date type G)
(qsmoke) 27: FFFF
(qsmoke) 29: 02 dif (16 Bit Integer/Binary Instantaneous value)
(qsmoke) 2a: FD vif (Second extension FD of VIF-codes)
(qsmoke) 2b: 17 vife (Error flags (binary))
(qsmoke) 2c: 0000
(qsmoke) 2e: 32 dif (16 Bit Integer/Binary Value during error state)
(qsmoke) 2f: 6C vif (Date type G)
(qsmoke) 30: FFFF
(qsmoke) 32: 04 dif (32 Bit Integer/Binary Instantaneous value)
(qsmoke) 33: 6D vif (Date and time type)
(qsmoke) 34: * 2514BC2B device datetime (2021-11-28 20:37)
Telegram with #UI set
#UI is increased after removing the smoke setector from the mounting plate.
If that triggers the dismantling alarm or the environmental monitoring is not known yet.
telegram=|3E44934480570147231A78#01FD089E81027C034955230282026CBB2C81037C034C41230082036CFFFF03FD17100010326CFFFF046D060FBB2C02FDAC7E8000|
(qsmoke) 000 : 3e length (62 bytes)
(qsmoke) 001 : 44 dll-c (from meter SND_NR)
(qsmoke) 002 : 9344 dll-mfct (QDS)
(qsmoke) 004 : 80570147 dll-id (47015780)
(qsmoke) 008 : 23 dll-version
(qsmoke) 009 : 1a dll-type (Smoke detector)
(qsmoke) 010 : 78 tpl-ci-field (EN 13757-3 Application Layer (no tplh))
(qsmoke) 011 : 01 dif (8 Bit Integer/Binary Instantaneous value)
(qsmoke) 012 : FD vif (Second extension FD of VIF-codes)
(qsmoke) 013 : 08 vife (Access Number (transmission count))
(qsmoke) 014 C?: 9E
(qsmoke) 015 : 81 dif (8 Bit Integer/Binary Instantaneous value)
(qsmoke) 016 : 02 dife (subunit=0 tariff=0 storagenr=4)
(qsmoke) 017 : 7C vif (VIF in following string (length in first byte))
(qsmoke) 018 : 03 viflen (3)
(qsmoke) 019 : 49 vif (I)
(qsmoke) 020 : 55 vif (U)
(qsmoke) 021 : 23 vif (#)
(qsmoke) 022 C!: 02 UI event count (2)
(qsmoke) 023 : 82 dif (16 Bit Integer/Binary Instantaneous value)
(qsmoke) 024 : 02 dife (subunit=0 tariff=0 storagenr=4)
(qsmoke) 025 : 6C vif (Date type G)
(qsmoke) 026 C!: BB2C UI event date (2021-12-27)
(qsmoke) 028 : 81 dif (8 Bit Integer/Binary Instantaneous value)
(qsmoke) 029 : 03 dife (subunit=0 tariff=0 storagenr=6)
(qsmoke) 030 : 7C vif (VIF in following string (length in first byte))
(qsmoke) 031 : 03 viflen (3)
(qsmoke) 032 : 4C vif (L)
(qsmoke) 033 : 41 vif (A)
(qsmoke) 034 : 23 vif (#)
(qsmoke) 035 C!: 00 AL event count (0)
(qsmoke) 036 : 82 dif (16 Bit Integer/Binary Instantaneous value)
(qsmoke) 037 : 03 dife (subunit=0 tariff=0 storagenr=6)
(qsmoke) 038 : 6C vif (Date type G)
(qsmoke) 039 C!: FFFF AL event date (2127-15-31)
(qsmoke) 041 : 03 dif (24 Bit Integer/Binary Instantaneous value)
(qsmoke) 042 : FD vif (Second extension FD of VIF-codes)
(qsmoke) 043 : 17 vife (Error flags (binary))
(qsmoke) 044 C!: 100010 error flags (100010)
(qsmoke) 047 : 32 dif (16 Bit Integer/Binary Value during error state)
(qsmoke) 048 : 6C vif (Date type G)
(qsmoke) 049 C!: FFFF error date (2127-15-31)
(qsmoke) 051 : 04 dif (32 Bit Integer/Binary Instantaneous value)
(qsmoke) 052 : 6D vif (Date and time type)
(qsmoke) 053 C!: 060FBB2C device datetime (2021-12-27 15:06)
(qsmoke) 057 : 02 dif (16 Bit Integer/Binary Instantaneous value)
(qsmoke) 058 : FD vif (Second extension FD of VIF-codes)
(qsmoke) 059 : AC vife (Duration since last readout [second(s)])
(qsmoke) 060 : 7E vife (Reserved)
(qsmoke) 061 C!: 8000 duration (128 s)
Telegram with #AL set
telegram=|3744934471478946231A7A6B100020#81027C034955230082026CFFFF81037C034C41230182036CB92902FD170400326CFFFF046D1B12AC2C|
(qsmoke) 000 : 37 length (55 bytes)
(qsmoke) 001 : 44 dll-c (from meter SND_NR)
(qsmoke) 002 : 9344 dll-mfct (QDS)
(qsmoke) 004 : 71478946 dll-id (46894771)
(qsmoke) 008 : 23 dll-version
(qsmoke) 009 : 1a dll-type (Smoke detector)
(qsmoke) 010 : 7a tpl-ci-field (EN 13757-3 Application Layer (short tplh))
(qsmoke) 011 : 6b tpl-acc-field
(qsmoke) 012 : 10 tpl-sts-field (TEMPORARY_ERROR)
(qsmoke) 013 : 0020 tpl-cfg 2000 (synchronous )
(qsmoke) 015 : 81 dif (8 Bit Integer/Binary Instantaneous value)
(qsmoke) 016 : 02 dife (subunit=0 tariff=0 storagenr=4)
(qsmoke) 017 : 7C vif (VIF in following string (length in first byte))
(qsmoke) 018 : 03 viflen (3)
(qsmoke) 019 : 49 vif (I)
(qsmoke) 020 : 55 vif (U)
(qsmoke) 021 : 23 vif (#)
(qsmoke) 022 C!: 00 UI event count (0)
(qsmoke) 023 : 82 dif (16 Bit Integer/Binary Instantaneous value)
(qsmoke) 024 : 02 dife (subunit=0 tariff=0 storagenr=4)
(qsmoke) 025 : 6C vif (Date type G)
(qsmoke) 026 C!: FFFF UI event date (2127-15-31)
(qsmoke) 028 : 81 dif (8 Bit Integer/Binary Instantaneous value)
(qsmoke) 029 : 03 dife (subunit=0 tariff=0 storagenr=6)
(qsmoke) 030 : 7C vif (VIF in following string (length in first byte))
(qsmoke) 031 : 03 viflen (3)
(qsmoke) 032 : 4C vif (L)
(qsmoke) 033 : 41 vif (A)
(qsmoke) 034 : 23 vif (#)
(qsmoke) 035 C!: 01 AL event count (1)
(qsmoke) 036 : 82 dif (16 Bit Integer/Binary Instantaneous value)
(qsmoke) 037 : 03 dife (subunit=0 tariff=0 storagenr=6)
(qsmoke) 038 : 6C vif (Date type G)
(qsmoke) 039 C!: B929 AL event date (2021-09-25)
(qsmoke) 041 : 02 dif (16 Bit Integer/Binary Instantaneous value)
(qsmoke) 042 : FD vif (Second extension FD of VIF-codes)
(qsmoke) 043 : 17 vife (Error flags (binary))
(qsmoke) 044 C!: 0400 error flags (0004)
(qsmoke) 046 : 32 dif (16 Bit Integer/Binary Value during error state)
(qsmoke) 047 : 6C vif (Date type G)
(qsmoke) 048 C!: FFFF error date (2127-15-31)
(qsmoke) 050 : 04 dif (32 Bit Integer/Binary Instantaneous value)
(qsmoke) 051 : 6D vif (Date and time type)
(qsmoke) 052 C!: 1B12AC2C device datetime (2021-12-12 18:27)
*/
void MeterQSmoke::processContent(Telegram *t)
{
int offset;
string key;
key = "81027C495523";
if (hasKey(&t->values, key)) {
if (extractDVuint8(&t->values, key, &offset, &ui_event_count_)) {
t->addMoreExplanation(offset, " UI event count (%d)", ui_event_count_);
}
}
if (findKey(MeasurementType::Instantaneous, ValueInformation::Date, 4, 0, &key, &t->values)) {
struct tm date;
extractDVdate(&t->values, key, &offset, &date);
ui_event_date_ = strdate(&date);
t->addMoreExplanation(offset, " UI event date (%s)", ui_event_date_.c_str());
}
key = "81037C4C4123";
if (hasKey(&t->values, key)) {
if (extractDVuint8(&t->values, key, &offset, &al_event_count_)) {
t->addMoreExplanation(offset, " AL event count (%d)", al_event_count_);
}
}
if (findKey(MeasurementType::Instantaneous, ValueInformation::Date, 6, 0, &key, &t->values)) {
struct tm date;
extractDVdate(&t->values, key, &offset, &date);
al_event_date_ = strdate(&date);
t->addMoreExplanation(offset, " AL event date (%s)", al_event_date_.c_str());
}
key = "02FD17";
if (hasKey(&t->values, key)) {
if (extractDVuint16(&t->values, key, &offset, (uint16_t*) &error_flags_)) {
t->addMoreExplanation(offset, " error flags (%04X)", error_flags_);
}
} else {
key = "03FD17";
if (hasKey(&t->values, key)) {
if (extractDVuint24(&t->values, key, &offset, &error_flags_)) {
t->addMoreExplanation(offset, " error flags (%06X)", error_flags_);
}
}
}
if (findKey(MeasurementType::AtError, ValueInformation::Date, 0, 0, &key, &t->values)) {
struct tm date;
extractDVdate(&t->values, key, &offset, &date);
error_date_ = strdate(&date);
t->addMoreExplanation(offset, " error date (%s)", error_date_.c_str());
}
if (findKey(MeasurementType::Unknown, ValueInformation::DateTime, 0, 0, &key, &t->values)) {
struct tm datetime;
extractDVdate(&t->values, key, &offset, &datetime);
device_date_time_ = strdatetime(&datetime);
t->addMoreExplanation(offset, " device datetime (%s)", device_date_time_.c_str());
}
key = "02FDAC7E";
if (hasKey(&t->values, key)) {
uint64_t seconds;
if (extractDVlong(&t->values, key, &offset, &seconds))
{
duration_since_readout_s_ = (int)seconds;
t->addMoreExplanation(offset, " duration (%d s)", duration_since_readout_s_);
}
}
}
string MeterQSmoke::status()
{
// We do not yet know how to understand the fields!
return "WOOT";
/*
string s;
bool smoke = 0;
if (smoke)
{
s.append("SMOKE ");
}
if (error_)
{
s.append("ERROR ");
}
if (s.length() > 0)
{
s.pop_back();
return s;
}
*/
}