kopia lustrzana https://github.com/weetmuts/wmbusmeters
Added :hex type for stdin, files and ttys.
rodzic
21c8ab66cf
commit
0788ad7b90
20
README.md
20
README.md
|
@ -291,6 +291,12 @@ These telegrams are expected to have the data link layer crc bytes removed alrea
|
|||
`telegrams.bin`, to read raw wmbus telegrams from this file.
|
||||
These telegrams are expected to have the data link layer crc bytes removed already!
|
||||
|
||||
`stdin:hex`, to read hex characters wbus telegrams from stdin.
|
||||
These telegrams are expected to have the data link layer crc bytes removed laready!
|
||||
|
||||
`telegrams.txt:hex`, to read hex characters wmbus telegrams from this file.
|
||||
These telegrams are expected to have the data link layer crc bytes removed already!
|
||||
|
||||
`stdin:rtlwmbus`, to read telegrams formatted using the rtlwmbus format from stdin. Works for rtl433 as well.
|
||||
|
||||
`telegrams.msg:rtlwmbus`, to read rtlwmbus formatted telegrams from this file. Works for rtl433 as well.
|
||||
|
@ -536,9 +542,9 @@ wmbusmeters --format=json --meterfiles /dev/ttyUSB0:im871a:c1 MyTapWater multica
|
|||
rtl_sdr -f 868.625M -s 1600000 - 2>/dev/null | rtl_wmbus -s | wmbusmeters --format=json stdin:rtlwmbus MyMeter auto 12345678 NOKEY | ...more processing...
|
||||
```
|
||||
|
||||
# Decoding a telegram supplied on the command line as a hex string
|
||||
# Decoding hex string telegrams
|
||||
|
||||
If you have a single telegram you want decoded, you do not need to create a simulation file,
|
||||
If you have a single telegram as hex, which you want decoded, you do not need to create a simulation file,
|
||||
you can just supply the telegram as a hex string on the command line.
|
||||
|
||||
```shell
|
||||
|
@ -567,6 +573,16 @@ which will output:
|
|||
{"media":"other","meter":"lansenpu","name":"MyCounter","id":"00010206","counter_a_int":4711,"counter_b_int":1234,"timestamp":"2021-09-12T08:45:52Z"}
|
||||
```
|
||||
|
||||
You can also pipe the hex into wmbusmeters like this:
|
||||
|
||||
```shell
|
||||
echo 234433300602010014007a8e0000002f2f0efd3a1147000000008e40fd3a341200000000 | ./build/wmbusmeters --silent --format=json stdin:hex MyCounter auto 00010206 NOKEY
|
||||
```
|
||||
|
||||
or read hex data from a a file, `wmbusmeters myfile.txt:hex`
|
||||
|
||||
Any non-hex characters are ignored when using the suffix `:hex`. The hex string must be proper
|
||||
with no spaces nor bad characters, when supplied on the command line.
|
||||
|
||||
# Additional tools
|
||||
|
||||
|
|
|
@ -213,6 +213,10 @@ shared_ptr<WMBus> BusManager::createWmbusObject(Detected *detected, Configuratio
|
|||
verbose("(rawtty) on %s\n", detected->found_file.c_str());
|
||||
wmbus = openRawTTY(*detected, serial_manager_, serial_override);
|
||||
break;
|
||||
case DEVICE_HEXTTY:
|
||||
verbose("(hextty) on %s\n", detected->found_file.c_str());
|
||||
wmbus = openHexTTY(*detected, serial_manager_, serial_override);
|
||||
break;
|
||||
case DEVICE_RTLWMBUS:
|
||||
wmbus = openRTLWMBUS(*detected, config->bin_dir, config->daemon, serial_manager_, serial_override);
|
||||
break;
|
||||
|
|
|
@ -141,6 +141,11 @@ int char2int(char input)
|
|||
return -1;
|
||||
}
|
||||
|
||||
bool isHexChar(uchar c)
|
||||
{
|
||||
return char2int(c) != -1;
|
||||
}
|
||||
|
||||
// The byte 0x13 i converted into the integer value 13.
|
||||
uchar bcd2bin(uchar c)
|
||||
{
|
||||
|
|
|
@ -39,6 +39,9 @@ typedef unsigned char uchar;
|
|||
uchar bcd2bin(uchar c);
|
||||
uchar revbcd2bin(uchar c);
|
||||
uchar reverse(uchar c);
|
||||
|
||||
bool isHexChar(uchar c);
|
||||
|
||||
bool isHexString(const char* txt, bool *invalid);
|
||||
bool isHexString(const std::string &txt, bool *invalid);
|
||||
bool hex2bin(const char* src, std::vector<uchar> *target);
|
||||
|
|
10
src/wmbus.cc
10
src/wmbus.cc
|
@ -4187,7 +4187,7 @@ FrameStatus checkWMBusFrame(vector<uchar> &data,
|
|||
// Ugly: 00615B2A442D2C998734761B168D2021D0871921|58387802FF2071000413F81800004413F8180000615B
|
||||
// Here the frame is prefixed with some random data.
|
||||
|
||||
debugPayload("(wmbus) checkWMBUSFrame\n", data);
|
||||
debugPayload("(wmbus) checkWMBUSFrame", data);
|
||||
|
||||
if (data.size() < 11)
|
||||
{
|
||||
|
@ -4447,6 +4447,7 @@ bool is_type_id_extras(string t, WMBusDeviceType *out_type, string *out_id, stri
|
|||
// im871a im871a[12345678] im871a(foo=123)
|
||||
// auto
|
||||
// rtlwmbus rtlwmbus[plast123] rtlwmbus(device extras) rtlwmbus[hej](extras)
|
||||
// hex
|
||||
if (t == "auto")
|
||||
{
|
||||
*out_type = WMBusDeviceType::DEVICE_AUTO;
|
||||
|
@ -4454,6 +4455,13 @@ bool is_type_id_extras(string t, WMBusDeviceType *out_type, string *out_id, stri
|
|||
return true;
|
||||
}
|
||||
|
||||
if (t == "hex")
|
||||
{
|
||||
*out_type = WMBusDeviceType::DEVICE_HEXTTY;
|
||||
*out_id = "";
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t bs = t.find('[');
|
||||
size_t be = t.find(']');
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ bool trimCRCsFrameFormatB(std::vector<uchar> &payload);
|
|||
X(IM871A,im871a,true,false,detectIM871AIM170A) \
|
||||
X(IM170A,im170a,true,false,detectSKIP) \
|
||||
X(RAWTTY,rawtty,true,false,detectRAWTTY) \
|
||||
X(HEXTTY,hextty,true,false,detectSKIP) \
|
||||
X(RC1180,rc1180,true,false,detectRC1180) \
|
||||
X(RTL433,rtl433,false,true,detectRTL433) \
|
||||
X(RTLWMBUS,rtlwmbus,false,true,detectRTLWMBUS) \
|
||||
|
@ -632,6 +633,9 @@ shared_ptr<WMBus> openAMB8465(Detected detected,
|
|||
shared_ptr<WMBus> openRawTTY(Detected detected,
|
||||
shared_ptr<SerialCommunicationManager> manager,
|
||||
shared_ptr<SerialDevice> serial_override);
|
||||
shared_ptr<WMBus> openHexTTY(Detected detected,
|
||||
shared_ptr<SerialCommunicationManager> manager,
|
||||
shared_ptr<SerialDevice> serial_override);
|
||||
shared_ptr<WMBus> openMBUS(Detected detected,
|
||||
shared_ptr<SerialCommunicationManager> manager,
|
||||
shared_ptr<SerialDevice> serial_override);
|
||||
|
|
|
@ -43,19 +43,24 @@ struct WMBusRawTTY : public virtual WMBusCommonImplementation
|
|||
void processSerialData();
|
||||
void simulate() { }
|
||||
|
||||
WMBusRawTTY(string bus_alias, shared_ptr<SerialDevice> serial, shared_ptr<SerialCommunicationManager> manager);
|
||||
WMBusRawTTY(string bus_alias, shared_ptr<SerialDevice> serial,
|
||||
shared_ptr<SerialCommunicationManager> manager, bool use_hex);
|
||||
~WMBusRawTTY() { }
|
||||
|
||||
private:
|
||||
|
||||
void copy(vector<uchar> *from, vector<uchar> *to);
|
||||
|
||||
vector<uchar> read_buffer_;
|
||||
vector<uchar> data_buffer_;
|
||||
LinkModeSet link_modes_;
|
||||
vector<uchar> received_payload_;
|
||||
};
|
||||
|
||||
shared_ptr<WMBus> openRawTTY(Detected detected,
|
||||
shared_ptr<SerialCommunicationManager> manager,
|
||||
shared_ptr<SerialDevice> serial_override)
|
||||
shared_ptr<WMBus> openRawTTYInternal(Detected detected,
|
||||
shared_ptr<SerialCommunicationManager> manager,
|
||||
shared_ptr<SerialDevice> serial_override,
|
||||
bool use_hex)
|
||||
{
|
||||
string bus_alias = detected.specified_device.bus_alias;
|
||||
string device = detected.found_file;
|
||||
|
@ -65,17 +70,32 @@ shared_ptr<WMBus> openRawTTY(Detected detected,
|
|||
|
||||
if (serial_override)
|
||||
{
|
||||
WMBusRawTTY *imp = new WMBusRawTTY(bus_alias, serial_override, manager);
|
||||
WMBusRawTTY *imp = new WMBusRawTTY(bus_alias, serial_override, manager, use_hex);
|
||||
imp->markAsNoLongerSerial();
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), bps, PARITY::NONE, "rawtty");
|
||||
WMBusRawTTY *imp = new WMBusRawTTY(bus_alias, serial, manager);
|
||||
auto serial = manager->createSerialDeviceTTY(device.c_str(), bps, PARITY::NONE, use_hex?"hextty":"rawtty");
|
||||
WMBusRawTTY *imp = new WMBusRawTTY(bus_alias, serial, manager, use_hex);
|
||||
return shared_ptr<WMBus>(imp);
|
||||
}
|
||||
|
||||
WMBusRawTTY::WMBusRawTTY(string bus_alias, shared_ptr<SerialDevice> serial, shared_ptr<SerialCommunicationManager> manager) :
|
||||
WMBusCommonImplementation(bus_alias, DEVICE_RAWTTY, manager, serial, true)
|
||||
shared_ptr<WMBus> openRawTTY(Detected detected,
|
||||
shared_ptr<SerialCommunicationManager> manager,
|
||||
shared_ptr<SerialDevice> serial_override)
|
||||
{
|
||||
return openRawTTYInternal(detected, manager, serial_override, false);
|
||||
}
|
||||
|
||||
shared_ptr<WMBus> openHexTTY(Detected detected,
|
||||
shared_ptr<SerialCommunicationManager> manager,
|
||||
shared_ptr<SerialDevice> serial_override)
|
||||
{
|
||||
return openRawTTYInternal(detected, manager, serial_override, true);
|
||||
}
|
||||
|
||||
WMBusRawTTY::WMBusRawTTY(string bus_alias, shared_ptr<SerialDevice> serial,
|
||||
shared_ptr<SerialCommunicationManager> manager, bool use_hex) :
|
||||
WMBusCommonImplementation(bus_alias, use_hex?DEVICE_HEXTTY:DEVICE_RAWTTY, manager, serial, true)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
@ -107,6 +127,59 @@ void WMBusRawTTY::deviceSetLinkModes(LinkModeSet lms)
|
|||
{
|
||||
}
|
||||
|
||||
void WMBusRawTTY::copy(vector<uchar> *from, vector<uchar> *to)
|
||||
{
|
||||
if (type() == WMBusDeviceType::DEVICE_RAWTTY)
|
||||
{
|
||||
// We expect binary bytes incoming.
|
||||
to->insert(to->end(), from->begin(), from->end());
|
||||
debug("copied %zu binary bytes\n", from->size());
|
||||
from->clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (type() == WMBusDeviceType::DEVICE_HEXTTY)
|
||||
{
|
||||
// We expect hex chars incoming. Everything else is thrown away.
|
||||
vector<uchar> hex;
|
||||
int num_hex = 0;
|
||||
int num_other = 0;
|
||||
for (uchar c : *from)
|
||||
{
|
||||
if (isHexChar(c))
|
||||
{
|
||||
hex.push_back(c); // Just ignore any non-hex chars!
|
||||
num_hex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
num_other++;
|
||||
}
|
||||
}
|
||||
debug("found %d hex chars and %d other bytes\n", num_hex, num_other);
|
||||
from->clear();
|
||||
if (hex.size() > 0)
|
||||
{
|
||||
if (hex.size() % 2 == 1)
|
||||
{
|
||||
// An odd hexadecimal char at the end!
|
||||
// Save it for later!
|
||||
from->push_back(hex.back());
|
||||
hex.pop_back();
|
||||
}
|
||||
// We now have an even number of hex chars to work with!
|
||||
vector<uchar> bin;
|
||||
bool ok = hex2bin(hex, &bin);
|
||||
assert(ok);
|
||||
debug("converted %zu hex bytes into %zu binary bytes.\n", hex.size(), bin.size());
|
||||
to->insert(to->end(), bin.begin(), bin.end());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void WMBusRawTTY::processSerialData()
|
||||
{
|
||||
vector<uchar> data;
|
||||
|
@ -116,12 +189,14 @@ void WMBusRawTTY::processSerialData()
|
|||
|
||||
read_buffer_.insert(read_buffer_.end(), data.begin(), data.end());
|
||||
|
||||
copy(&read_buffer_, &data_buffer_);
|
||||
|
||||
size_t frame_length;
|
||||
int payload_len, payload_offset;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
FrameStatus status = checkWMBusFrame(read_buffer_, &frame_length, &payload_len, &payload_offset);
|
||||
FrameStatus status = checkWMBusFrame(data_buffer_, &frame_length, &payload_len, &payload_offset);
|
||||
|
||||
if (status == PartialFrame)
|
||||
{
|
||||
|
@ -131,9 +206,9 @@ void WMBusRawTTY::processSerialData()
|
|||
if (status == ErrorInFrame)
|
||||
{
|
||||
verbose("(rawtty) protocol error in message received!\n");
|
||||
string msg = bin2hex(read_buffer_);
|
||||
string msg = bin2hex(data_buffer_);
|
||||
debug("(rawtty) protocol error \"%s\"\n", msg.c_str());
|
||||
read_buffer_.clear();
|
||||
data_buffer_.clear();
|
||||
break;
|
||||
}
|
||||
if (status == FullFrame)
|
||||
|
@ -143,9 +218,9 @@ void WMBusRawTTY::processSerialData()
|
|||
{
|
||||
uchar l = payload_len;
|
||||
payload.insert(payload.end(), &l, &l+1); // Re-insert the len byte.
|
||||
payload.insert(payload.end(), read_buffer_.begin()+payload_offset, read_buffer_.begin()+payload_offset+payload_len);
|
||||
payload.insert(payload.end(), data_buffer_.begin()+payload_offset, data_buffer_.begin()+payload_offset+payload_len);
|
||||
}
|
||||
read_buffer_.erase(read_buffer_.begin(), read_buffer_.begin()+frame_length);
|
||||
data_buffer_.erase(data_buffer_.begin(), data_buffer_.begin()+frame_length);
|
||||
AboutTelegram about("", 0, FrameType::WMBUS);
|
||||
handleTelegram(about, payload);
|
||||
}
|
||||
|
|
|
@ -78,3 +78,30 @@ else
|
|||
echo "======================="
|
||||
cat $TEST/test_stderr.txt
|
||||
fi
|
||||
|
||||
|
||||
TESTNAME="Test hex on stdin"
|
||||
|
||||
cat > $TEST/test_expected.txt <<EOF
|
||||
{"media":"other","meter":"lansenpu","name":"MyCounter","id":"00010206","counter_a_int":4711,"counter_b_int":1234,"timestamp":"1111-11-11T11:11:11Z"}
|
||||
{"media":"cold water","meter":"multical21","name":"MyWater","id":"76348799","total_m3":6.408,"target_m3":6.408,"max_flow_m3h":0,"flow_temperature_c":127,"external_temperature_c":19,"current_status":"DRY","time_dry":"22-31 days","time_reversed":"","time_leaking":"","time_bursting":"","timestamp":"1111-11-11T11:11:11Z"}
|
||||
{"media":"other","meter":"lansenpu","name":"MyCounter","id":"00010206","counter_a_int":4711,"counter_b_int":1234,"timestamp":"1111-11-11T11:11:11Z"}
|
||||
EOF
|
||||
|
||||
echo 234433300602010014007a8e0000002f2f0efd3a1147000000008e40fd3a3412000000002A442D2C998734761B168D2091D37CAC21E1D68CDAFFCD3DC452BD802913FF7B1706CA9E355D6C2701CC24234433300602010014007a8e0000002f2f0efd3a1147000000008e40fd3a341200000000999 | \
|
||||
$PROG --silent --ignoreduplicates=false --format=json stdin:hex MyCounter auto 00010206 NOKEY MyWater auto 76348799 28F64A24988064A079AA2C807D6102AE > $TEST/test_output.txt 2> $TEST/test_stderr.txt
|
||||
|
||||
if [ "$?" = "0" ]
|
||||
then
|
||||
cat $TEST/test_output.txt | sed 's/"timestamp":"....-..-..T..:..:..Z"/"timestamp":"1111-11-11T11:11:11Z"/' > $TEST/test_responses.txt
|
||||
diff $TEST/test_expected.txt $TEST/test_responses.txt
|
||||
if [ "$?" = "0" ]
|
||||
then
|
||||
echo OK: $TESTNAME
|
||||
TESTRESULT="OK"
|
||||
fi
|
||||
else
|
||||
echo "wmbusmeters returned error code: $?"
|
||||
cat $TEST/test_output.txt
|
||||
cat $TEST/test_stderr.txt
|
||||
fi
|
||||
|
|
Ładowanie…
Reference in New Issue