Porównaj commity

...

40 Commity

Autor SHA1 Wiadomość Data
Fredrik Öhrström 73dd60d67b Update xmq library. 2024-06-01 11:03:21 +02:00
Fredrik Öhrström b3771a9b8e Add another mvt combo for qwater. 2024-05-29 11:02:04 +02:00
Fredrik Öhrström 257a9c1ad2 Update documentation on how to create a new driver. 2024-05-28 17:10:56 +02:00
Fredrik Öhrström f954860d80 Add xmq drivers directory. 2024-05-28 17:01:21 +02:00
Fredrik Öhrström 251b575f68 Fix compiler warnings. 2024-05-28 15:46:30 +02:00
Fredrik Öhrström 7c117cc26c
Merge pull request #1292 from jetmcquack/patch-1
Update util.cc to fix const hex Ambiguity
2024-05-28 15:27:17 +02:00
jetmcquack 40229d81ff
Update util.cc to fix const hex Ambiguity 2024-05-28 11:21:48 +02:00
Fredrik Öhrström 8748a2d52f Add /opt/homebrew to build for macosx. 2024-05-28 00:27:27 +02:00
Fredrik Öhrström 1396fff5a0 Debug mac build. 2024-05-28 00:17:21 +02:00
Fredrik Öhrström 759160b415 Add new location for homebrews on arm macs. 2024-05-28 00:16:08 +02:00
Fredrik Öhrström 9684345cb6 Properly load tariff_nr and subunit_nr from xmq driver file.
Print error in frame if both mbus test and wmbus test fails.
2024-05-27 23:54:53 +02:00
Fredrik Öhrström 1a4169ed23
Merge pull request #1262 from PovilasID/patch-1
Documenting MQTT as telegram source
2024-04-29 23:19:23 +02:00
PovilasID aa4f1956e8
Documenting MQTT as telegram source 2024-04-29 19:49:52 +03:00
Fredrik Öhrström d90dbb196e Add another m,v,t combo for the lse_07_17 driver. 2024-04-15 08:44:14 +02:00
Fredrik Öhrström 14d021426a
Merge pull request #1245 from majonezz/patch-1
Avoid SIGSEGV in WMBusCUL::checkCULFrame
2024-04-14 16:13:26 +02:00
Michał Morański f32179a939
Avoid SIGSEGV in WMBusCUL::checkCULFrame
(cul) checkCULFrame "b2F4468506586269295620A17A2069F2"
(cul) no eol found yet, partial frame
(serial) received ascii "TMODE<0D><0A>b2F44685086625092957245C6A2069F2F6A06E0080000000000000000B9BF00000D0F0D11130512100F0F0F100F0F8E1F0F0E0D121310B241<0D><0A>b4E44B61065960200023732117A0E004005E4B5FD2A1E3DCCC84F38BDF21FD05D506BF685D50CB3AD9644F9FF7C893BF9DD0D2B64C85F703707B1965C69261E8CDF85046CDDC38F1336D67750E933854BA0C9A91240A18556E6064B<0D><0A>"
(cul) checkCULFrame "b2F4468506586269295620A17A2069F2TMODE<0D><0A>b2F44685086625092957245C6A2069F2F6A06E0080000000000000000B9BF00000D0F0D11130512100F0F0F100F0F8E1F0F0E0D121310B241<0D><0A>b4E44B61065960200023732117A0E004005E4B5FD2A1E3DCCC84F38BDF21FD05D506BF685D50CB3AD9644F9FF7C893BF9DD0D2B64C85F703707B1965C69261E8CDF85046CDDC38F1336D67750E933854BA0C9A91240A18556E6064B<0D><0A>"
(cul) bad hex for LQI and RSSI "MODE"
(cul) warning: the LQI and RSSI hex string is not properly formatted!

Thread 2 "wmbusmeters" received signal SIGSEGV, Segmentation fault.
0x571c718f in WMBusCUL::checkCULFrame (this=0xf0a03480, data=std::vector of length 339, capacity 339 = {...}, hex_frame_length=0xf07fe680,
    payload=std::vector of length 0, capacity 0, rssi_dbm=0xf07fe6c0) at src/wmbus_cul.cc:336
336         uint lqi = lqi_rssi[0]>>1;
(gdb)
2024-04-14 15:16:56 +02:00
Fredrik Öhrström a32fcfdf9a When generating IV for AES-CTR zero out H and R bit. 2024-04-13 13:42:25 +02:00
Fredrik Öhrström efcc41d107 Add support for GJ VIF. 2024-04-09 20:47:42 +02:00
Fredrik Öhrström a69e547a17 Update drivers with signedness. Fix tests. 2024-04-09 11:11:17 +02:00
Fredrik Öhrström 23f2279a64 Separate VIF scaling and DIF signedness. Default to signed DIF binary integers. 2024-04-09 10:41:30 +02:00
Fredrik Öhrström 05edab0882 Add help on intsalling jq. 2024-04-08 17:02:35 +02:00
Fredrik Öhrström ff72e1debc Add dynamic driver lookup bits translation to strings. 2024-04-04 20:59:03 +02:00
Fredrik Öhrström c1509f6139
Merge pull request #1218 from jsreynaud/better_message_for_vife
Adding a better description of combinable extension vife
2024-03-29 16:19:50 +01:00
Fredrik Öhrström 9facddf019 Add support for the same fully specified secondary address printed by libmbus after doing a bus scan. 2024-03-28 12:41:00 +01:00
Fredrik Öhrström 9a34a55abb Fail decoding if too many difes/vifes are found. 2024-03-28 12:41:00 +01:00
Fredrik Öhrström 465a450a8b
Merge pull request #1196 from avandorp/patch-1
topaseskr: Fix wording for date values
2024-03-22 20:23:08 +01:00
Jean-Samuel REYNAUD 9576550f85
Adding a better description of combinable extension vife 2024-03-22 16:25:49 +01:00
Fredrik Öhrström 1f2cd10160 Update README. 2024-03-03 19:40:06 +01:00
Fredrik Öhrström 8c09f7b2d8 The required field does not contribute to testing of the address expressions before. 2024-03-03 19:34:00 +01:00
Fredrik Öhrström 3247a4a576 Update README. 2024-03-03 15:44:59 +01:00
Fredrik Öhrström 23779cb9f7 Add option --identitymode=... 2024-03-03 12:57:40 +01:00
Fredrik Öhrström 5962e727ff Handle more address rules. 2024-03-02 22:46:50 +01:00
Arthur van Dorp 03d95e780e topaseskr: Fix wording for date values
Those are period end dates, not start dates. That was my bad, sorry.
2024-03-02 21:06:59 +01:00
Fredrik Öhrström 11c83c1f37 Remove unused code. 2024-03-02 15:42:39 +01:00
Fredrik Öhrström 7634b95438 New advanced addressing works. 2024-03-02 15:30:25 +01:00
Fredrik Öhrström 78e7c47503 Add filter_out to address expression. 2024-03-01 12:00:49 +01:00
Fredrik Öhrström 0c98b474bb Fix tests. 2024-02-27 11:52:45 +01:00
Fredrik Öhrström 9d27ab3fb3 New source file address.cc for mbus addressing. 2024-02-26 11:44:47 +01:00
Fredrik Öhrström c21efd1d69
Merge pull request #1187 from testuser7/docker-tag
Improve workflow syntax
2024-02-23 08:51:43 +01:00
testuser7 67230b4213 Improve workflow syntax 2024-02-22 18:52:59 +01:00
138 zmienionych plików z 5610 dodań i 2931 usunięć

Wyświetl plik

@ -11,8 +11,8 @@ on:
env:
DOCKERHUB_IMAGE: ${{ github.repository }}
IMAGE_TAG: |
${{ github.ref_type == 'tag' && (contains(github.ref_name, '-RC') &&
format('{0}-{1}', 'candidate', github.ref_name) || format('{0}-{1}', 'release', github.ref_name)) || 'latest' }}
${{ github.ref_type == 'tag' && format('{0}-{1}', (contains(github.ref_name, '-RC') &&
'candidate' || 'release'), github.ref_name) || 'latest' }}
jobs:
build:

Wyświetl plik

@ -3,6 +3,7 @@ on:
push:
branches:
- master
jobs:
build:
runs-on: macOS-latest

29
CHANGES
Wyświetl plik

@ -1,3 +1,32 @@
Fixed long standing confusion wether the DIF binary values are by
default signed or unsigned. It turns out that they are signed!
Thank you Mathias (Zeppelin500) and KaVauA for sorting this out!
For unknown VIFS and non-compliant meters the signedness
can be overriden to unsigned.
New improved address specification. E.g. use 12345678.M=KAM.V=1b.T=16
to listen to exactly the telegrams with id 12345678 manufacturer KAM,
version 0x1b and type 0x16. You if you do not specify any M,V or T, they
become wildcards which will be the old default behaviour.
If you receive multiple telegram versions from the same id, and you want to
filter out some versions, do: 12345678,!12345678.V=77
You can now specify p0 to p250, to read from an mbus using the primary address.
E.g. wmbusmeters --pollinterval=5s /dev/ttyUSB1:mbus:2400 TEMP piigth:mbus p0 NOKEY
Added option --identitymode=(id|id-mfct|full|none) to specify how
wmbusmeters groups meter state when receiving telegrams.
The default (which is the same as before) is to map state based only on id.
This usually works ok, however if you have two meters with the same id, but
from different manufacturers, you must separate their state with --identitymode=id-mfct
Full takes into account version and type as well. None means do not separate state
at all, used with wildcards and meters that do not need to keep state, ie all info
is in every telegram.
Version 1.16.1 2024-02-22
Fix docker file generation.

Wyświetl plik

@ -1,5 +1,4 @@
# Copyright (C) 2017-2023 Fredrik Öhrström (gpl-3.0-or-later)
# Copyright (C) 2017-2024 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
@ -153,6 +152,7 @@ $(BUILD)/%.o: src/%.c $(wildcard src/%.h)
$(CXX) -I/usr/include/libxml2 -fpermissive $(CXXFLAGS) $< -MMD -c -o $@
PROG_OBJS:=\
$(BUILD)/address.o \
$(BUILD)/aes.o \
$(BUILD)/aescmac.o \
$(BUILD)/bus.o \

Wyświetl plik

@ -6,6 +6,33 @@ wireless wm-bus meters. The readings can then be published using
MQTT, curled to a REST api, inserted into a database or stored in a
log file.
# What does it do?
Wmbusmeters converts incoming telegrams from (w)mbus/OMS compatible meters like:
`1844AE4C4455223368077A55000000_041389E20100023B0000`
into human readable:
`MyTapWater 33225544 123.529 m³ 0 m³/h 2024-03-03 19:36:22`
or into csv:
`MyTapWater;33225544;123.529;0;2024-03-03 19:36:45`
or into json:
```json
{
"media":"water",
"meter":"iperl",
"name":"MyTapWater",
"id":"33225544",
"max_flow_m3h":0,
"total_m3":123.529,
"timestamp":"2024-03-03T18:37:00Z"
}
```
Wmbusmeters can collect telegrams from radio using hardware dongles or rtl-sdr software radio dongles,
or from m-bus meters using serial ports, or from files/pipes.
[FAQ/WIKI/MANUAL pages](https://wmbusmeters.github.io/wmbusmeters-wiki/)
The program runs on GNU/Linux, MacOSX, FreeBSD, and Raspberry Pi.
@ -130,9 +157,11 @@ bus the mbus poll request should be sent to.
wmbusmeters --pollinterval=60s MAIN=/dev/ttyUSB0:mbus:2400 MyTempMeter piigth:MAIN:mbus 12001932 NOKEY
```
If you want to poll an mbus meter using the primary address, just use
a number between 0 and 250 instead of the full 8 digit secondary
address.
If you want to poll an mbus meter using the primary address, use p0 to p250 (deciman numbers)
instead of the full 8 digit secondary address.
```
wmbusmeters --pollinterval=60s MAIN=/dev/ttyUSB0:mbus:2400 MyTempMeter piigth:MAIN:mbus p0 NOKEY
```
# Example wmbusmeter.conf file
@ -173,7 +202,7 @@ And an mbus meter file in /etc/wmbusmeters.d/MyTempHygro
```ini
name=MyTempHygro
id=11223344
driver=piigth:mbus
driver=piigth:MAIN:mbus
pollinterval=60s
```
@ -217,9 +246,15 @@ The latest reading of the meter can also be found here: `/var/lib/wmbusmeters/me
You can use several ids using `id=1111111,2222222,3333333` or you can listen to all
meters of a certain type `id=*` or you can suffix with star `id=8765*` to match
all meters with a given prefix. If you supply at least one positive match rule, then you
can add negative match rules as well. For example `id=*,!2222*`
can add filter out rules as well. For example `id=*,!2222*`
which will match all meter ids, except those that begin with 2222.
You can also specify the exact manufacturer, version and type: `id=11111111.M=KAM.V=1b.T=16`
or a subset: `id=11111111.T=16` or all telegrams from 22222222 except those with version 77:
`id=22222222,!22222222.V=77` You can also use the fully specified secondary address that is
printed by libmbus after doing a bus scan, ie `100002842941011B` which is equivalent to
`10000284.M=PII.V=01.T=1B`
When matching all meters from the command line you can use `ANYID` instead of `*` to avoid shell quotes.
# Add static and calculated fields to the output
@ -419,6 +454,7 @@ As {options} you can use:
--exitafter=<time> exit program after time, eg 20h, 10m 5s
--format=<hr/json/fields> for human readable, json or semicolon separated fields
--help list all options
--identitymode=(id|id-mfct|full|none) group meter state based on the identity mode. Default is id.
--ignoreduplicates=<bool> ignore duplicate telegrams, remember the last 10 telegrams
--field_xxx=yyy always add "xxx"="yyy" to the json output and add shell env METER_xxx=yyy (--json_xxx=yyy also works)
--license print GPLv3+ license
@ -832,6 +868,12 @@ Or start nc explicitly in a pipe.
nc -lku 4444 | wmbusmeters stdin:rtlwmbus
```
Telegrams can also be pulled in by listening on MQTT topics if they were captured by other tools like [rtl_433](https://github.com/merbanan/rtl_433)
```shell
wmbusmeters 'hex:CMD(/usr/bin/mosquitto_sub -h 192.168.x.x -t rtl_433/device/devices/6/Wireless-MBus/+/data | tr -d "\n" )'
```
`+` is a wild card that listens to all the captured telegrams but can be replaced with a specific meter's ID
# Decoding hex string telegrams
If you have a single telegram as hex, which you want decoded, you do not need to create a simulation file,
@ -988,10 +1030,21 @@ If you like to send the bytes manually, the correct bytes are:
# How to add a new driver
Drivers are self contained source code files named `src/driver_xyz.cc`
They register themselves at startup. The source file also contains the necessary tests for that driver.
Drivers for OMS-compliant meters are text files `drivers/src/*.xmq`
First collect an unecrypted telegram as a hex string <hex> using --logtelegrams and any other driver.
Then run `wmbusmeters --analyze <hex>` to see the best match.
Read more here: [doc/CreateDriver.md](doc/CreateDriver.md)
Copy that meters aaa,xmq file to a new filename bbb.xmq and change the name field from aaa to bbb in the driver source.
Now run the new driver with `wmbusmeters --analyze=drivers/src/bbb.xmq <hex>`
and start modifying the driver until it produces the desired json output.
You can now run `make; make install` from within the drivers directory
and then rebuild from the wmbusmeters directory `make`. The new driver is now
compiled into the binary.
You can also put the new driver file bbb.xmq into /etc/wmbusmeters.drivers.d and it will immediately
be available to the wmbusmeters program without recompiling.
# Caveat

6
configure vendored
Wyświetl plik

@ -2283,6 +2283,12 @@ freebsd*)
CFLAGS="$CFLAGS -I/usr/local/include"
CXXFLAGS="$CXXFLAGS -I/usr/local/include"
LDFLAGS="$LDFLAGS -L/usr/local/lib"
;;
darwin*)
CFLAGS="$CFLAGS -I/usr/local/include -I/opt/homebrew/include"
CXXFLAGS="$CXXFLAGS -I/usr/local/include -I/opt/homebrew/include"
LDFLAGS="$LDFLAGS -L/usr/local/lib -L/opt/homebrew/lib"
find /opt -name "*rtlsdr*"
;;
esac

Wyświetl plik

@ -40,6 +40,11 @@ freebsd*)
CFLAGS="$CFLAGS -I/usr/local/include"
CXXFLAGS="$CXXFLAGS -I/usr/local/include"
LDFLAGS="$LDFLAGS -L/usr/local/lib"
;;
darwin*)
CFLAGS="$CFLAGS -I/usr/local/include -I/opt/homebrew/include"
CXXFLAGS="$CXXFLAGS -I/usr/local/include -I/opt/homebrew/include"
LDFLAGS="$LDFLAGS -L/usr/local/lib -L/opt/homebrew/lib"
;;
esac

Wyświetl plik

@ -1,362 +0,0 @@
# Creating a new driver
To create a new driver, it is very convenient, to start with an existing driver,
that mostly matches the one you want to integrate. I will use the EurisII as a base for
Integration of Aventies HCA.
In fact, most of the manufacturers already exist in the source code
with their respective shortcodes, e.g. Aventies with "AAA".
Create the `/etc/wmbusmeters.conf` with content adapted to your installation, e.g.:
```
loglevel=debug
device=/dev/ttyUSB0:t1
logtelegrams=true
format=json
meterfiles=/var/lib/wmbusmeters/meter_readings
meterfilesaction=overwrite
meterfilesnaming=name-id
logfile=/var/log/wmbusmeters/wmbusmeters.log
```
Create a meter config in `/etc/wmbusmeters.d/` with content like this, using the existing type, you selected as a base for your class (adjust also name, id and key to your needs):
```
name=ABOGGLKZ
driver=eurisii
id=60900126
key=xxxxxxxxx
```
If you now start wmbusmeters with `wmbusmeters --debug --verbose --useconfig=/etc` and your meter transmits a message,
you will see a log like this:
```
[2021-07-05_21:07:30] (meter) ABOGGLKZ: meter detection did not match the selected driver eurisii! correct driver is: unknown!
(meter) Not printing this warning again for id: 60900126 mfct: (AAA) Aventies, Germany (0x421) type: Heat Cost Allocator (0x08) ver: 0x55
[2021-07-05_21:07:30] (meter) please consider opening an issue at https://github.com/wmbusmeters/wmbusmeters/
[2021-07-05_21:07:30] (meter) to add support for this unknown mfct,media,version combination
(meter) ABOGGLKZ: yes for me
(meter) ABOGGLKZ eurisii handling telegram from 60900126
(meter) ABOGGLKZ 60900126 "7644210426019060550872260190602104550806006005CA4269D455F02AE4A475AD546F7FF1EDF3C959E5480AA0A2341B6B6EA28884FA1E0EC355A23E66D055E3C790298553C3870727149DF88612ABF2EA184AEF0821B16BC11DA5BAABEFB34E4E68C6F2728D935011EAB98FCAA29274CC685B8079F7"
(wmbus) parseDLL @0 119
(telegram) DLL L=76 C=44 (from meter SND_NR) M=0421 (AAA) A=60900126 VER=55 TYPE=08 (Heat Cost Allocator) (driver unknown!) DEV=im871a[00101387] RSSI=-77
(wmbus) parseELL @10 109
(wmbus) parseAFL @10 109
(wmbus) parseTPL @10 109
(TPL) decrypting "CA4269D455F02AE4A475AD546F7FF1EDF3C959E5480AA0A2341B6B6EA28884FA1E0EC355A23E66D055E3C790298553C3870727149DF88612ABF2EA184AEF0821B16BC11DA5BAABEFB34E4E68C6F2728D935011EAB98FCAA29274CC685B8079F7"
(TPL) num encrypted blocks 6 (96 bytes and remaining unencrypted 0 bytes)
(TPL) IV 21042601906055080606060606060606
(TPL) decrypted "2F2F0B6E660100426EA60082016EA600C2016E9E0082026E7E00C2026E5B0082036E4200C2036E770182046E5B01C2046E4C0182056E4701C2056E3E0182066E3B01C2066E3B0182076E3B01C2076E3B0182086E1301C2086E9C0002FD170000"
(telegram) TPL CI=72 ACC=06 STS=00 CFG=0560 (AES_CBC_IV nb=6 cntn=0 ra=0 hc=0) ID=26019060 MFT=2104 VER=55 TYPE=08 (Heat Cost Allocator)
telegram=|76442104260190605508722601906021045508060060052F2F|0B6E660100426EA60082016EA600C2016E9E0082026E7E00C2026E5B0082036E4200C2036E770182046E5B01C2046E4C0182056E4701C2056E3E0182066E3B01C2066E3B0182076E3B01C2076E3B0182086E1301C2086E9C0002FD170000|+6647
(eurisii) 00: 76 length (118 bytes)
(eurisii) 01: 44 dll-c (from meter SND_NR)
(eurisii) 02: 2104 dll-mfct (AAA)
(eurisii) 04: 26019060 dll-id (60900126)
(eurisii) 08: 55 dll-version
(eurisii) 09: 08 dll-type (Heat Cost Allocator)
(eurisii) 0a: 72 tpl-ci-field (EN 13757-3 Application Layer (long tplh))
(eurisii) 0b: 26019060 tpl-id (60900126)
(eurisii) 0f: 2104 tpl-mfct (AAA)
(eurisii) 11: 55 tpl-version
(eurisii) 12: 08 tpl-type (Heat Cost Allocator)
(eurisii) 13: 06 tpl-acc-field
(eurisii) 14: 00 tpl-sts-field (OK)
(eurisii) 15: 6005 tpl-cfg 0560 (AES_CBC_IV nb=6 cntn=0 ra=0 hc=0 )
(eurisii) 17: 2f2f decrypt check bytes
(eurisii) 19: 0B dif (6 digit BCD Instantaneous value)
(eurisii) 1a: 6E vif (Units for H.C.A.)
(eurisii) 1b: * 660100 current consumption (166.000000 hca)
(eurisii) 1e: 42 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(eurisii) 1f: 6E vif (Units for H.C.A.)
(eurisii) 20: * A600 consumption at set date 1 (166.000000 hca)
(eurisii) 22: 82 dif (16 Bit Integer/Binary Instantaneous value)
(eurisii) 23: 01 dife (subunit=0 tariff=0 storagenr=2)
(eurisii) 24: 6E vif (Units for H.C.A.)
(eurisii) 25: * A600 consumption at set date 2 (166.000000 hca)
(eurisii) 27: C2 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(eurisii) 28: 01 dife (subunit=0 tariff=0 storagenr=3)
(eurisii) 29: 6E vif (Units for H.C.A.)
(eurisii) 2a: * 9E00 consumption at set date 3 (158.000000 hca)
(eurisii) 2c: 82 dif (16 Bit Integer/Binary Instantaneous value)
(eurisii) 2d: 02 dife (subunit=0 tariff=0 storagenr=4)
(eurisii) 2e: 6E vif (Units for H.C.A.)
(eurisii) 2f: * 7E00 consumption at set date 4 (126.000000 hca)
(eurisii) 31: C2 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(eurisii) 32: 02 dife (subunit=0 tariff=0 storagenr=5)
(eurisii) 33: 6E vif (Units for H.C.A.)
(eurisii) 34: * 5B00 consumption at set date 5 (91.000000 hca)
(eurisii) 36: 82 dif (16 Bit Integer/Binary Instantaneous value)
(eurisii) 37: 03 dife (subunit=0 tariff=0 storagenr=6)
(eurisii) 38: 6E vif (Units for H.C.A.)
(eurisii) 39: * 4200 consumption at set date 6 (66.000000 hca)
(eurisii) 3b: C2 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(eurisii) 3c: 03 dife (subunit=0 tariff=0 storagenr=7)
(eurisii) 3d: 6E vif (Units for H.C.A.)
(eurisii) 3e: * 7701 consumption at set date 7 (375.000000 hca)
(eurisii) 40: 82 dif (16 Bit Integer/Binary Instantaneous value)
(eurisii) 41: 04 dife (subunit=0 tariff=0 storagenr=8)
(eurisii) 42: 6E vif (Units for H.C.A.)
(eurisii) 43: * 5B01 consumption at set date 8 (347.000000 hca)
(eurisii) 45: C2 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(eurisii) 46: 04 dife (subunit=0 tariff=0 storagenr=9)
(eurisii) 47: 6E vif (Units for H.C.A.)
(eurisii) 48: * 4C01 consumption at set date 9 (332.000000 hca)
(eurisii) 4a: 82 dif (16 Bit Integer/Binary Instantaneous value)
(eurisii) 4b: 05 dife (subunit=0 tariff=0 storagenr=10)
(eurisii) 4c: 6E vif (Units for H.C.A.)
(eurisii) 4d: * 4701 consumption at set date 10 (327.000000 hca)
(eurisii) 4f: C2 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(eurisii) 50: 05 dife (subunit=0 tariff=0 storagenr=11)
(eurisii) 51: 6E vif (Units for H.C.A.)
(eurisii) 52: * 3E01 consumption at set date 11 (318.000000 hca)
(eurisii) 54: 82 dif (16 Bit Integer/Binary Instantaneous value)
(eurisii) 55: 06 dife (subunit=0 tariff=0 storagenr=12)
(eurisii) 56: 6E vif (Units for H.C.A.)
(eurisii) 57: * 3B01 consumption at set date 12 (315.000000 hca)
(eurisii) 59: C2 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(eurisii) 5a: 06 dife (subunit=0 tariff=0 storagenr=13)
(eurisii) 5b: 6E vif (Units for H.C.A.)
(eurisii) 5c: * 3B01 consumption at set date 13 (315.000000 hca)
(eurisii) 5e: 82 dif (16 Bit Integer/Binary Instantaneous value)
(eurisii) 5f: 07 dife (subunit=0 tariff=0 storagenr=14)
(eurisii) 60: 6E vif (Units for H.C.A.)
(eurisii) 61: * 3B01 consumption at set date 14 (315.000000 hca)
(eurisii) 63: C2 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(eurisii) 64: 07 dife (subunit=0 tariff=0 storagenr=15)
(eurisii) 65: 6E vif (Units for H.C.A.)
(eurisii) 66: * 3B01 consumption at set date 15 (315.000000 hca)
(eurisii) 68: 82 dif (16 Bit Integer/Binary Instantaneous value)
(eurisii) 69: 08 dife (subunit=0 tariff=0 storagenr=16)
(eurisii) 6a: 6E vif (Units for H.C.A.)
(eurisii) 6b: * 1301 consumption at set date 16 (275.000000 hca)
(eurisii) 6d: C2 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(eurisii) 6e: 08 dife (subunit=0 tariff=0 storagenr=17)
(eurisii) 6f: 6E vif (Units for H.C.A.)
(eurisii) 70: * 9C00 consumption at set date 17 (156.000000 hca)
(eurisii) 72: 02 dif (16 Bit Integer/Binary Instantaneous value)
(eurisii) 73: FD vif (Second extension FD of VIF-codes)
(eurisii) 74: 17 vife (Error flags (binary))
(eurisii) 75: * 0000 error flags (0000)
```
Now keep especially the following lines in mind for integation into the meter definitions:
```
[2021-07-05_21:07:30] (meter) ABOGGLKZ: meter detection did not match the selected driver eurisii! correct driver is: unknown!
(meter) Not printing this warning again for id: 60900126 mfct: (AAA) Aventies, Germany (0x421) type: Heat Cost Allocator (0x08) ver: 0x55
```
and the telegram line with the decrypted content.
```
telegram=|76442104260190605508722601906021045508060060052F2F#0B6E660100426EA60082016EA600C2016E9E0082026E7E00C2026E5B0082036E4200C2036E770182046E5B01C2046E4C0182056E4701C2056E3E0182066E3B01C2066E3B0182076E3B01C2076E3B0182086E1301C2086E9C0002FD170000|+6647
```
You can now analyze the telegram with this command:
```
wmbusmeters --analyze 76442104260190605508722601906021045508060060052F2F0B6E660100426EA60082016EA600C2016E9E0082026E7E00C2026E5B0082036E4200C2036E770182046E5B01C2046E4C0182056E4701C2056E3E0182066E3B01C2066E3B0182076E3B01C2076E3B0182086E1301C2086E9C0002FD170000
```
This will test all existing drivers to see which drivers seems to be matching the best. (This method can be improved so do some sanity checks as well.) If the driver already decodes 100% of the content then perhaps you should only add
```
di.addDetection(MANUFACTURER_AAA, 0x08, 0x55);
```
to the existing driver_eursii.cc file. But in this case we chose to create a new driver.
(Remember to add a new test case at the end of the cc file.)
## Creating your new driver
As we used the eurisii meter as a template, you need to copy the driver_eurisii.cc to driver_xyz.cc replacing xyz
with a name created by you. In my case it is driver_aventieshca.cc
As long as you do not need any new (not-yet-implemented) wmbus protocol features, then the
entire driver is self contained within a single cc file, including tests.
Now replace all occurences of class name MeterEurisII by the class name you created (e.g. MeterAventiesHCA in my case).
Adjust the test cases at the end of the cc file! These test cases are picked up automatically
by the testing system. Such regression tests are very important for the future stability of wmbusmeters.
Media/type 0x08 is the code for a Heat Cost allocator. You can find other codes here [here](https://m-bus.com/assets/downloads/MBDOC48.PDF) (on page 76). At least you should check for plausibility...
### Further adjustments
If you need to do processing that is not support by the current addFieldWithExtractor code, then
you will have to implement the processContent function.
To collect the releavant data correctly, you need to adjust the code
for processing and printing the data from the meter. For this you
should edit the `MeterXXX::processContent` method to fit your
needs. Adhere to the debug log output of the processing function and
have a look at other meter's classes for examples how to process
multiple values with different sorage numbers or types.
If you get errors, it is quite probable that you missed the correct value information (e.g. ValueInformation::Volume):
```
if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 0, 0, &key, &t->values)) {
extractDVdouble(&t->values, key, &offset, &total_water_consumption_m3_);
t->addMoreExplanation(offset, " total consumption (%f m3)", total_water_consumption_m3_);
}
```
Possible ValueInformation types are:
- Volume (0x10,0x17)
- OperatingTime (0x24,0x27)
- VolumeFlow (0x38,0x3F)
- FlowTemperature (0x58,0x5B)
- ReturnTemperature (0x5C,0x5F)
- TemperatureDifference (0x60,0x63)
- ExternalTemperature (0x64,0x67)
- HeatCostAllocation (0x6E,0x6E)
- Date (0x6C,0x6C)
- DateTime (0x6D,0x6D)
- EnergyMJ (0x0E,0x0F)
- EnergyWh (0x00,0x07)
- PowerW (0x28,0x2f)
- ActualityDuration (0x74,0x77)
You can add also special properties and getters for special data of your meter, like it is handled with the error codes for EurisII.
## Compiling and testing
If everything was right, you can try compiling the project:
```
./configure
make -j4
```
Test your new version with the analyze command: `./build/wmbusmeters --analyze ...`
Now test your code:
./build/wmbusmeters --format=json <hex> MyHCA aventieshca 12345678 NOKEY
It should print:
```
{"media":"heat cost allocation","meter":"aventieshca","name":"MyHCA","id":"60900126","current_consumption_hca":166,"consumption_at_set_date_hca":166,"consumption_at_set_date_2_hca":166,"consumption_at_set_date_3_hca":158,"consumption_at_set_date_4_hca":126,"consumption_at_set_date_5_hca":91,"consumption_at_set_date_6_hca":66,"consumption_at_set_date_7_hca":375,"consumption_at_set_date_8_hca":347,"consumption_at_set_date_9_hca":332,"consumption_at_set_date_10_hca":327,"consumption_at_set_date_11_hca":318,"consumption_at_set_date_12_hca":315,"consumption_at_set_date_13_hca":315,"consumption_at_set_date_14_hca":315,"consumption_at_set_date_15_hca":315,"consumption_at_set_date_16_hca":275,"consumption_at_set_date_17_hca":156,"error_flags":"","timestamp":"2022-01-18T10:04:08Z"}
```
And now you can run it for real:
./build_debug/wmbusmeters --format=json auto:t1 Water MyMeter 12345678 <key>
or using the config that you setup before:
`./build/wmbusmeters --debug --verbose useconfig=/`
When it looks good, now run the tests:
```
make test
```
If you have the time please try to build with debug information as well: `make DEBUG=true` and `make testd`
This will test the code and check that there are no memory leaks or buffer overflows etc.
Finally try the daemon: make; sudo make install
(Do the daemon reload command if such is requested.)
sudo systemctl start wmbusmeters.service
Update the regression tests in the end of driver_aventieshca.cc
If again everything was ok, `sudo make install` the new wmbusmeters and start it.
## Provide some Information (for decumentation and debugging)
Now edit your meter config in `/etc/wmbusmeters.d/` to use the new meter type (mine is aventieshca).
The log should show the correct recognition (aventieshca)-tags at the beginning of each decoding line for your meter.
```
(aventieshca) 17: 2f2f decrypt check bytes
(aventieshca) 19: 0B dif (6 digit BCD Instantaneous value)
(aventieshca) 1a: 6E vif (Units for H.C.A.)
(aventieshca) 1b: * 660100 current consumption (166.000000 hca)
(aventieshca) 1e: 42 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(aventieshca) 1f: 6E vif (Units for H.C.A.)
(aventieshca) 20: * A600 consumption at set date 1 (166.000000 hca)
(aventieshca) 22: 82 dif (16 Bit Integer/Binary Instantaneous value)
(aventieshca) 23: 01 dife (subunit=0 tariff=0 storagenr=2)
(aventieshca) 24: 6E vif (Units for H.C.A.)
(aventieshca) 25: * A600 consumption at set date 2 (166.000000 hca)
(aventieshca) 27: C2 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(aventieshca) 28: 01 dife (subunit=0 tariff=0 storagenr=3)
(aventieshca) 29: 6E vif (Units for H.C.A.)
(aventieshca) 2a: * 9E00 consumption at set date 3 (158.000000 hca)
(aventieshca) 2c: 82 dif (16 Bit Integer/Binary Instantaneous value)
(aventieshca) 2d: 02 dife (subunit=0 tariff=0 storagenr=4)
(aventieshca) 2e: 6E vif (Units for H.C.A.)
(aventieshca) 2f: * 7E00 consumption at set date 4 (126.000000 hca)
(aventieshca) 31: C2 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(aventieshca) 32: 02 dife (subunit=0 tariff=0 storagenr=5)
(aventieshca) 33: 6E vif (Units for H.C.A.)
(aventieshca) 34: * 5B00 consumption at set date 5 (91.000000 hca)
(aventieshca) 36: 82 dif (16 Bit Integer/Binary Instantaneous value)
(aventieshca) 37: 03 dife (subunit=0 tariff=0 storagenr=6)
(aventieshca) 38: 6E vif (Units for H.C.A.)
(aventieshca) 39: * 4200 consumption at set date 6 (66.000000 hca)
(aventieshca) 3b: C2 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(aventieshca) 3c: 03 dife (subunit=0 tariff=0 storagenr=7)
(aventieshca) 3d: 6E vif (Units for H.C.A.)
(aventieshca) 3e: * 7701 consumption at set date 7 (375.000000 hca)
(aventieshca) 40: 82 dif (16 Bit Integer/Binary Instantaneous value)
(aventieshca) 41: 04 dife (subunit=0 tariff=0 storagenr=8)
(aventieshca) 42: 6E vif (Units for H.C.A.)
(aventieshca) 43: * 5B01 consumption at set date 8 (347.000000 hca)
(aventieshca) 45: C2 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(aventieshca) 46: 04 dife (subunit=0 tariff=0 storagenr=9)
(aventieshca) 47: 6E vif (Units for H.C.A.)
(aventieshca) 48: * 4C01 consumption at set date 9 (332.000000 hca)
(aventieshca) 4a: 82 dif (16 Bit Integer/Binary Instantaneous value)
(aventieshca) 4b: 05 dife (subunit=0 tariff=0 storagenr=10)
(aventieshca) 4c: 6E vif (Units for H.C.A.)
(aventieshca) 4d: * 4701 consumption at set date 10 (327.000000 hca)
(aventieshca) 4f: C2 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(aventieshca) 50: 05 dife (subunit=0 tariff=0 storagenr=11)
(aventieshca) 51: 6E vif (Units for H.C.A.)
(aventieshca) 52: * 3E01 consumption at set date 11 (318.000000 hca)
(aventieshca) 54: 82 dif (16 Bit Integer/Binary Instantaneous value)
(aventieshca) 55: 06 dife (subunit=0 tariff=0 storagenr=12)
(aventieshca) 56: 6E vif (Units for H.C.A.)
(aventieshca) 57: * 3B01 consumption at set date 12 (315.000000 hca)
(aventieshca) 59: C2 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(aventieshca) 5a: 06 dife (subunit=0 tariff=0 storagenr=13)
(aventieshca) 5b: 6E vif (Units for H.C.A.)
(aventieshca) 5c: * 3B01 consumption at set date 13 (315.000000 hca)
(aventieshca) 5e: 82 dif (16 Bit Integer/Binary Instantaneous value)
(aventieshca) 5f: 07 dife (subunit=0 tariff=0 storagenr=14)
(aventieshca) 60: 6E vif (Units for H.C.A.)
(aventieshca) 61: * 3B01 consumption at set date 14 (315.000000 hca)
(aventieshca) 63: C2 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(aventieshca) 64: 07 dife (subunit=0 tariff=0 storagenr=15)
(aventieshca) 65: 6E vif (Units for H.C.A.)
(aventieshca) 66: * 3B01 consumption at set date 15 (315.000000 hca)
(aventieshca) 68: 82 dif (16 Bit Integer/Binary Instantaneous value)
(aventieshca) 69: 08 dife (subunit=0 tariff=0 storagenr=16)
(aventieshca) 6a: 6E vif (Units for H.C.A.)
(aventieshca) 6b: * 1301 consumption at set date 16 (275.000000 hca)
(aventieshca) 6d: C2 dif (16 Bit Integer/Binary Instantaneous value storagenr=1)
(aventieshca) 6e: 08 dife (subunit=0 tariff=0 storagenr=17)
(aventieshca) 6f: 6E vif (Units for H.C.A.)
(aventieshca) 70: * 9C00 consumption at set date 17 (156.000000 hca)
(aventieshca) 72: 02 dif (16 Bit Integer/Binary Instantaneous value)
(aventieshca) 73: FD vif (Second extension FD of VIF-codes)
(aventieshca) 74: 17 vife (Error flags (binary))
(aventieshca) 75: * 0000 error flags (0000)
```
You can also provide an encrypted telegram, the AES key for the telegram and the decoded data in your pull request for Fredrik to add it to the regression tests. The information is part of the log and looks like this:
```
(serial) received binary "A5C203764421042601906055087226019060210455080A00600537A7B807E3BA027FE98D75848595628733C29F2D3262F23BA4D2C01D37084E784691E115674D6D8CB874698D4D2C9DB3832A38A39021457A46F151FCBC86947EE7E35CF7AFC049381E74FB2B19E0F835B867B40D22E61129D395263441F4DED061B541"
(im871a) checkIM871AFrame "A5C203764421042601906055087226019060210455080A00600537A7B807E3BA027FE98D75848595628733C29F2D3262F23BA4D2C01D37084E784691E115674D6D8CB874698D4D2C9DB3832A38A39021457A46F151FCBC86947EE7E35CF7AFC049381E74FB2B19E0F835B867B40D22E61129D395263441F4DED061B541"
(im871a) has_timestamp=0 has_rssi=1 has_crc16=1
[...]
(TPL) decrypting "37A7B807E3BA027FE98D75848595628733C29F2D3262F23BA4D2C01D37084E784691E115674D6D8CB874698D4D2C9DB3832A38A39021457A46F151FCBC86947EE7E35CF7AFC049381E74FB2B19E0F835B867B40D22E61129D395263441F4DED0"
(TPL) num encrypted blocks 6 (96 bytes and remaining unencrypted 0 bytes)
(TPL) IV 21042601906055080A0A0A0A0A0A0A0A
(TPL) decrypted "2F2F0B6E660100426EA60082016EA600C2016E9E0082026E7E00C2026E5B0082036E4200C2036E770182046E5B01C2046E4C0182056E4701C2056E3E0182066E3B01C2066E3B0182076E3B01C2076E3B0182086E1301C2086E9C0002FD170000"
(telegram) TPL CI=72 ACC=0a STS=00 CFG=0560 (AES_CBC_IV nb=6 cntn=0 ra=0 hc=0) ID=26019060 MFT=2104 VER=55 TYPE=08 (Heat Cost Allocator)
telegram=|764421042601906055087226019060210455080A0060052F2F|0B6E660100426EA60082016EA600C2016E9E0082026E7E00C2026E5B0082036E4200C2036E770182046E5B01C2046E4C0182056E4701C2056E3E0182066E3B01C2066E3B0182076E3B01C2076E3B0182086E1301C2086E9C0002FD170000|+7599
```
It would also be handy to provide a datasheet of the sensor within the pull request.
That's all :-)
Have fun!

32
drivers/Makefile 100644
Wyświetl plik

@ -0,0 +1,32 @@
$(shell mkdir -p build/test)
PROG?=wmbusmeters
database:
@./generate.sh $(PROG)
web:
@mkdir -p build/web
@for i in $(wildcard src/*) ; do xmq $$i render-html --darkbg > build/web/$$(basename $${i}).html; done
@./generate_index.sh > build/web/index.html
tests:
@echo -n "// Generated " > build/generated_tests.xmq
@date +%Y-%m-%d_%H:%M >> build/generated_tests.xmq
@for i in $(wildcard src/*) ; do xmq $$i select /driver/test to-xmq >> build/generated_tests.xmq; done
install: database tests
@grep -v "// Generated " < build/generated_database.cc > build/a
@grep -v "// Generated " < ../src/generated_database.cc > build/b
@if ! diff build/a build/b ; then \
cp build/generated_database.cc ../src ; echo "Installed db"; else echo "No changes db." ; fi
@grep -v "// Generated " < build/generated_tests.xmq > build/a
@grep -v "// Generated " < ../tests/generated_tests.xmq > build/b
@if ! diff build/a build/b ; then \
cp build/generated_tests.xmq ../tests/generated_tests.xmq ; echo "Installed tests." ; else echo "No changes test." ; fi
test:
@for i in $(wildcard src/*) ; do ./test.sh $(PROG) $$i ; done
.PHONY: database web tests install test

Wyświetl plik

@ -0,0 +1,58 @@
#!/bin/bash
export PROG="$1"
export OUT="build/generated_database.cc"
cat > $OUT <<EOF
/*
Copyright (C) 2024 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/>.
*/
// Generated $(date +%Y-%m-%d_%H:%M)
BuiltinDriver builtins_[] =
{
EOF
# { "elster", "driver{name=elster meter_type=GasMeter default_fields=name,id,total_m3,timestamp detect{mvt=ELS,81,03}field{name=total quantity=Volume match{measurement_type=Instantaneous vif_range=Volume}}}", false },
for i in src/*.xmq
do
NAME=$(basename $i)
NAME="${NAME%.*}"
CONTENT="$(xmq $i delete /driver/test to-xmq --compact | sed 's/"/\\"/g')"
cat >>$OUT <<EOF
{ "$NAME", "$CONTENT", false },
EOF
done
cat >> $OUT <<EOF
};
MapToDriver builtins_mvts_[] =
{
EOF
for i in src/*.xmq
do
NAME=$(basename $i)
export NAME="${NAME%.*}"
(xmq $i for-each /driver/detect/mvt --shell='./print_mvt.sh "${.}" "$NAME"') >> $OUT
done
cat >> $OUT <<EOF
};
EOF

Wyświetl plik

@ -0,0 +1 @@
#!/bin/bash

Wyświetl plik

@ -0,0 +1,10 @@
#!/bin/bash
MVT="$1"
DRIVER="$2"
M=$(echo "$1" | cut -f 1 -d ',')
V=$(echo "$1" | cut -f 2 -d ',')
T=$(echo "$1" | cut -f 3 -d ',')
echo " { { MANUFACTURER_${M},0x${V},0x${T} }, \"$DRIVER\" },"

Wyświetl plik

@ -0,0 +1,29 @@
driver {
name = elster
meter_type = GasMeter
default_fields = name,id,total_m3,timestamp
detect {
mvt = ELS,81,03
}
use = actuality_duration_s
field {
name = total
quantity = Volume
match {
measurement_type = Instantaneous
vif_range = Volume
}
about {
de = 'Der Gesamtwasserverbrauch.'
en = 'The total water consumption.'
fr = '''La consommation totale d'eau.'''
sv = 'Den totala vattenförbrukningen.'
}
}
test {
args = 'Gas elster 05105025 NOKEY'
telegram = 3644A511640010253837722550100593158103E70020052F2F_0374E602000C137034220302FD74EE0F2F2F2F2F2F2F2F2F2F2F2F2F2F2F
json = '{"media":"gas","meter":"elster","name":"Gas","id":"05105025","actuality_duration_s":742,"total_m3":3223.47,"timestamp":"1111-11-11T11:11:11Z"}'
fields = 'Gas;05105025;3223.47;1111-11-11 11:11.11'
}
}

Wyświetl plik

@ -0,0 +1,275 @@
driver {
name = eltako
default_fields = name,id,total_kwh,timestamp
meter_type = ElectricityMeter
detect {
mvt = ELT,01,02
}
field {
name = status
quantity = Text
info = status_and_error_flags
match {
measurement_type = Instantaneous
vif_range = ErrorFlags
}
lookup {
name = ERROR_FLAGS
map_type = BitToString
mask_bits = 0xff
default_message = OK
map {
name = BUSY
info = 'System is busy'
value = 0x01
test = Set
}
map {
name = GENERIC_APP_ERROR
info = 'Generic application error'
value = 0x02
test = Set
}
map {
name = CURRENT_LOW
info = 'Current too low'
value = 0x04
test = Set
}
map {
name = PERMANENT_ERROR
info = 'permanent error'
value = 0x08
test = Set
}
map {
name = TEMPORARY_ERROR
info = 'temporary error'
value = 0x10
test = Set
}
}
}
field {
name = 'total_tariff_1'
quantity = Energy
info = 'Total cumulative active energy per tariff.'
match {
measurement_type = Instantaneous
vif_scaling = Auto
vif_range = AnyEnergyVIF
tariff_nr = 1
}
}
field {
name = 'total_tariff_2'
quantity = Energy
info = 'Total cumulative active energy per tariff.'
match {
measurement_type = Instantaneous
vif_scaling = Auto
vif_range = AnyEnergyVIF
tariff_nr = 2
}
}
field {
name = 'total_reactive_tariff_{tariff_counter}'
quantity = Energy
info = 'Total cumulative reactive energy per tariff.'
match {
measurement_type = Instantaneous
vif_scaling = Auto
vif_range = AnyEnergyVIF
storage_nr = 2
tariff_nr = 1,10
}
}
field {
name = voltage_l1_n
quantity = Voltage
info = 'Instantaneous voltage between L1 and neutral.'
match {
measurement_type = Instantaneous
vif_scaling = Auto
vif_range = Voltage
add_combinable = Mfct01
}
}
field {
name = current_l1
quantity = Amperage
info = 'Instantaneous current in the L1 phase.'
match {
measurement_type = Instantaneous
vif_scaling = Auto
vif_range = Amperage
add_combinable = Mfct01
}
}
field {
name = power_l1
quantity = Power
info = 'active Power in L1 phase'
match {
measurement_type = Instantaneous
vif_scaling = Auto
vif_range = AnyPowerVIF
add_combinable = Mfct01
}
}
field {
name = reactive_power_l1
quantity = Power
info = 'reactive Power in L1 phase'
match {
measurement_type = Instantaneous
vif_scaling = Auto
vif_range = AnyPowerVIF
subunit_nr = 1
add_combinable = Mfct01
}
}
field {
name = voltage_l2_n
quantity = Voltage
info = 'Instantaneous voltage between L2 and neutral.'
match {
measurement_type = Instantaneous
vif_scaling = Auto
vif_range = Voltage
add_combinable = Mfct02
}
}
field {
name = current_l2
quantity = Amperage
info = 'Instantaneous current in the L2 phase.'
match {
measurement_type = Instantaneous
vif_scaling = Auto
vif_range = Amperage
add_combinable = Mfct02
}
}
field {
name = power_l2
quantity = Power
info = 'active Power in L2 phase'
match {
measurement_type = Instantaneous
vif_scaling = Auto
vif_range = AnyPowerVIF
add_combinable = Mfct02
}
}
field {
name = reactive_power_l2
quantity = Power
info = 'reactive Power in L2 phase'
match {
measurement_type = Instantaneous
vif_scaling = Auto
vif_range = AnyPowerVIF
subunit_nr = 1
add_combinable = Mfct02
}
}
field {
name = voltage_l3_n
quantity = Voltage
info = 'Instantaneous voltage between L3 and neutral.'
match {
measurement_type = Instantaneous
vif_scaling = Auto
vif_range = Voltage
add_combinable = Mfct03
}
}
field {
name = current_l3
quantity = Amperage
info = 'Instantaneous current in the L3 phase.'
match {
measurement_type = Instantaneous
vif_scaling = Auto
vif_range = Amperage
add_combinable = Mfct03
}
}
field {
name = power_l3
quantity = Power
info = 'active Power in L3 phase'
match {
measurement_type = Instantaneous
vif_scaling = Auto
vif_range = AnyPowerVIF
add_combinable = Mfct03
}
}
field {
name = reactive_power_l3
quantity = Power
info = 'reactive Power in L3 phase'
match {
measurement_type = Instantaneous
vif_scaling = Auto
vif_range = AnyPowerVIF
subunit_nr = 1
add_combinable = Mfct03
}
}
field {
name = ct_numerator
info = 'Current transformer ratio (numerator)'
quantity = Dimensionless
vif_scaling = None
match {
difvifkey = 02FF68
}
}
field {
name = active_power_overall
quantity = Power
info = 'active Power overall'
match {
measurement_type = Instantaneous
vif_scaling = Auto
vif_range = AnyPowerVIF
add_combinable = Mfct00
}
}
field {
name = reactive_power_overall
quantity = Power
info = 'reactive Power overall'
match {
measurement_type = Instantaneous
vif_scaling = Auto
vif_range = AnyPowerVIF
subunit_nr = 1
add_combinable = Mfct00
}
}
field {
name = active_tariff
info = 'active tariff'
quantity = Dimensionless
vif_scaling = None
match {
difvifkey = 01FF13
}
}
field {
name = 'total'
quantity = Energy
info = 'Total active energy over all tariffs.'
calculate = total_tariff_1_kwh+total_tariff_2_kwh
}
test {
args = 'Eltako eltako 23451236 NOKEY'
telegram = 689292680800723612452394150102cd0000008c1004688902008c1104688902008c2004000000008c21040000000002fdc9ff01ee0002fddBff01100002acff0120008240acff010a0002fdc9ff02ef0002fddBff02110002acff0224008240acff02070002fdc9ff03ee0002fddBff030e0002acff031c008240acff03060002ff68010002acff0062008240acff00190001ff1300f416
json = '{"active_power_overall_kw": 0.98,"active_tariff_counter": 0,"ct_numerator_counter": 1,"current_l1_a": 1.6,"current_l2_a": 1.7,"current_l3_a": 1.4,"id": "23451236","media": "electricity","meter": "eltako","name": "Eltako","power_l1_kw": 0.32,"power_l2_kw": 0.36,"power_l3_kw": 0.28,"reactive_power_l1_kw": 0.1,"reactive_power_l2_kw": 0.07,"reactive_power_l3_kw": 0.06,"reactive_power_overall_kw": 0.25,"timestamp": "1111-11-11T11:11:11Z","total_kwh": 289.68,"total_reactive_tariff_1_kwh": 289.68,"total_reactive_tariff_2_kwh": 0,"total_tariff_1_kwh": 289.68,"total_tariff_2_kwh": 0,"voltage_l1_n_v": 238,"voltage_l2_n_v": 239,"voltage_l3_n_v": 238}'
fields = 'Eltako;23451236;289.68;1111-11-11 11:11.11'
}
}

Wyświetl plik

@ -0,0 +1,49 @@
driver {
name = iperl
meter_type = WaterMeter
default_fields = name,id,total_m3,max_flow_m3h,timestamp
detect {
mvt = SEN,68,06
mvt = SEN,68,07
mvt = SEN,7c,07
}
field {
name = total
quantity = Volume
match {
measurement_type = Instantaneous
vif_range = Volume
}
about {
de = 'Der Gesamtwasserverbrauch.'
en = 'The total water consumption.'
fr = '''La consommation totale d'eau.'''
sv = 'Den totala vattenförbrukningen.'
}
}
field {
name = max_flow
quantity = Flow
match {
measurement_type = Instantaneous
vif_range = VolumeFlow
}
about {
en = 'The maximum flow recorded during previous period.'
}
}
test {
args = 'MoreWater iperl 12345699 NOKEY'
coment = 'Test iPerl T1 telegram, that after decryption, has 2f2f markers.'
telegram = 1E44AE4C9956341268077A36001000_2F2F0413181E0000023B00002F2F2F2F
json = '{"media":"water","meter":"iperl","name":"MoreWater","id":"12345699","total_m3":7.704,"max_flow_m3h":0,"timestamp":"1111-11-11T11:11:11Z"}'
fields = 'MoreWater;12345699;7.704;0;1111-11-11 11:11.11'
}
test {
args = 'WaterWater iperl 33225544 NOKEY'
comment = 'Test iPerl T1 telegram not encrypted, which has no 2f2f markers.'
telegram = 1844AE4C4455223368077A55000000_041389E20100023B0000
json = '{"media":"water","meter":"iperl","name":"WaterWater","id":"33225544","total_m3":123.529,"max_flow_m3h":0,"timestamp":"1111-11-11T11:11:11Z"}'
fields = 'WaterWater;33225544;123.529;0;1111-11-11 11:11.11'
}
}

Wyświetl plik

@ -0,0 +1,128 @@
driver {
name = kampress
default_fields = name,id,status,pressure_bar,max_pressure_bar,min_pressure_bar,timestamp
meter_type = PressureSensor
detect {
mvt = KAM,01,18
}
field {
name = status
quantity = Text
info = status_and_error_flags
match {
measurement_type = Instantaneous
vif_range = ErrorFlags
}
lookup {
name = ERROR_FLAGS
map_type = BitToString
mask_bits = 0xffff
default_message = OK
map {
name = DROP
info = 'Unexpected drop in pressure in relation to average pressure.'
value = 0x01
test = Set
}
map {
name = SURGE
info = 'Unexpected increase in pressure in relation to average pressure.'
value = 0x02
test = Set
}
map {
name = HIGH
info = 'Average pressure has reached configurable limit. Default 15 bar.'
value = 0x04
test = Set
}
map {
name = LOW
info = 'Average pressure has reached configurable limit. Default 1.5 bar.'
value = 0x08
test = Set
}
map {
name = TRANSIENT
info = 'Pressure changes quickly over short timeperiods. Average is fluctuating.'
value = 0x10
test = Set
}
map {
name = COMM_ERROR
info = 'Cannot measure properly or bad internal communication.'
value = 0x20
test = Set
}
}
}
field {
name = pressure
quantity = Pressure
info = 'The measured pressure.'
match {
measurement_type = Instantaneous
vif_range = Pressure
}
}
field {
name = max_pressure
quantity = Pressure
info = 'The maximum pressure measured during ?'
match {
measurement_type = Maximum
vif_range = Pressure
}
}
field {
name = min_pressure
quantity = Pressure
info = 'The minimum pressure measured during ?'
match {
measurement_type = Minimum
vif_range = Pressure
}
}
field {
name = alfa
info = 'We do not know what this is.'
quantity = Dimensionless
vif_scaling = None
match {
difvifkey = 05FF09
}
}
field {
name = beta
info = 'We do not know what this is.'
quantity = Dimensionless
vif_scaling = None
match {
difvifkey = 05FF0A
}
}
test {
args = 'Pressing kampress 77000317 NOKEY'
telegram = 32442D2C1703007701188D280080E39322DB8F78_22696600126967000269660005FF091954A33A05FF0A99BD823A02FD170800
json = '{"media":"pressure","meter":"kampress","name":"Pressing","id":"77000317","status":"LOW","pressure_bar":1.02,"max_pressure_bar":1.03,"min_pressure_bar":1.02,"alfa_counter":0.001246,"beta_counter":0.000997,"timestamp":"1111-11-11T11:11:11Z"}'
fields = 'Pressing;77000317;LOW;1.02;1.03;1.02;1111-11-11 11:11.11'
}
test {
args = 'Pressing kampress 77000317 NOKEY'
telegram = '32442D2C1703007701188D280080E39322DB8F78_22696600126967000269660005FF091954A33A05FF0A99BD823A02FD170800
27442D2C1703007701188D280194E393226EC679DE735657_660067006600962B913A21B9423A0800'
json = '{"media":"pressure","meter":"kampress","name":"Pressing","id":"77000317","status":"LOW","pressure_bar":1.02,"max_pressure_bar":1.03,"min_pressure_bar":1.02,"alfa_counter":0.001108,"beta_counter":0.000743,"timestamp":"1111-11-11T11:11:11Z"}'
fields = 'Pressing;77000317;LOW;1.02;1.03;1.02;1111-11-11 11:11.11'
}
test {
args = 'Pressing kampress 77000317 NOKEY'
telegram = '32442D2C1703007701188D280080E39322DB8F78_22696600126967000269660005FF091954A33A05FF0A99BD823A02FD170800
27442D2C1703007701188D289554F295224ED579DE73188A_650066006600E80EA43A6B97A3BA0800'
json = '{"media":"pressure","meter":"kampress","name":"Pressing","id":"77000317","status":"LOW","pressure_bar":1.02,"max_pressure_bar":1.02,"min_pressure_bar":1.01,"alfa_counter":0.001252,"beta_counter":-0.001248,"timestamp":"1111-11-11T11:11:11Z"}'
fields = 'Pressing;77000317;LOW;1.02;1.02;1.01;1111-11-11 11:11.11'
}
}

Wyświetl plik

@ -0,0 +1,24 @@
driver {
name = werhlemodwm
meter_type = WaterMeter
default_fields = name,id,total_m3,timestamp
detect {
mvt = WZG,03,16
}
use = meter_datetime
use = target_date
use = target_m3
use = total_m3
use = fabrication_no
field {
name = next_target
quantity = PointInTime
display_unit = date
match {
measurement_type = Instantaneous
vif_range = Date
add_combinable = FutureValue
storage_nr = 1
}
}
}

6
drivers/test.sh 100755
Wyświetl plik

@ -0,0 +1,6 @@
#!/bin/sh
export PROG="$1"
export DRIVER="$2"
echo Testing $DRIVER
xmq $DRIVER for-each /driver/test --shell='./test_case.sh "$PROG" "$DRIVER" "${args}" "${telegram}" "${json}" "${fields}" "$1"'

Wyświetl plik

@ -0,0 +1,47 @@
#!/bin/bash
TEST=build/test
PROG="$1"
DRIVER="$2"
ARGS="$3"
HEX="$4"
JSON="$5"
FIELDS="$6"
rm -f $TEST/test_output.txt $TEST/test_expected.txt $TEST/simulation_tmp.txt
echo "$HEX" | sed 's/^/telegram=/g' > $TEST/simulation_tmp.txt
$PROG --driver=$DRIVER --format=json $TEST/simulation_tmp.txt $ARGS \
| tail -n 1 \
| jq . --sort-keys \
| sed 's/"timestamp": "....-..-..T..:..:..Z"/"timestamp": "1111-11-11T11:11:11Z"/' \
> $TEST/test_output.txt
echo "$JSON" | jq . --sort-keys > $TEST/test_expected.txt
if ! diff $TEST/test_expected.txt $TEST/test_output.txt
then
if [ "$USE_MELD" = "true" ]
then
meld $TEST/test_expected.txt $TEST/test_output.txt
fi
fi
rm -f $TEST/test_output.txt $TEST/test_expected.txt
$PROG --driver=$DRIVER --format=fields $TEST/simulation_tmp.txt $ARGS \
| sed 's/....-..-.. ..:..:../1111-11-11 11:11.11/' \
| tail -n 1 \
> $TEST/test_output.txt
echo "$FIELDS" > $TEST/test_expected.txt
if ! diff $TEST/test_expected.txt $TEST/test_output.txt
then
if [ "$USE_MELD" = "true" ]
then
meld $TEST/test_expected.txt $TEST/test_output.txt
fi
fi

Wyświetl plik

@ -0,0 +1,2 @@
telegram=|7B4479169977997730378C208B900F002C25E4EF0A002EA98E7D58B3ADC57299779977991611028B005087102F2F#0DFD090F34302e3030562030303030303030300D790E31323334353637383839595345310DFD100AAAAAAAAAAAAAAAAAAAAA0D780E31323334353637383930594553312F2F2F2F2F2F2F2F2F2F2F|
telegram=|7B4479169977997730378C20F0900F002C2549EE0A0077C19D3D1A08ABCD729977997779161102F0005007102F2F#0702F5C3FA000000000007823C5407000000000000841004E081020084200415000000042938AB000004A9FF01FA0A000004A9FF02050A000004A9FF03389600002F2F2F2F2F2F2F2F2F2F2F2F2F|

Wyświetl plik

@ -0,0 +1,19 @@
telegram=|A244EE4D785634123C067A8F000000_0C1348550000426CE1F14C130000000082046C21298C0413330000008D04931E3A3CFE3300000033000000330000003300000033000000330000003300000033000000330000003300000033000000330000004300000034180000046D0D0B5C2B03FD6C5E150082206C5C290BFD0F0200018C4079678885238310FD3100000082106C01018110FD610002FD66020002FD170000|
{"media":"warm water","meter":"supercom587","name":"MyWarmWater","id":"12345678","total_m3":5.548,"software_version":"010002","status":"OK","timestamp":"1111-11-11T11:11:11Z"}
|MyWarmWater;12345678;5.548;1111-11-11 11:11.11
telegram=|A244EE4D111111113C077AAC000000_0C1389490000426CE1F14C130000000082046C21298C0413010000008D04931E3A3CFE0100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000001600000031130000046D0A0C5C2B03FD6C60150082206C5C290BFD0F0200018C4079629885238310FD3100000082106C01018110FD610002FD66020002FD170000|
{"media":"water","meter":"supercom587","name":"MyColdWater","id":"11111111","total_m3":4.989,"software_version":"010002","status":"OK","timestamp":"1111-11-11T11:11:11Z"}
|MyColdWater;11111111;4.989;1111-11-11 11:11.11
telegram=|1E44AE4C9956341268077A36001000_2F2F0413181E0000023B00002F2F2F2F|
{"media":"water","meter":"iperl","name":"MoreWater","id":"12345699","total_m3":7.704,"max_flow_m3h":0,"timestamp":"1111-11-11T11:11:11Z"}
|MoreWater;12345699;7.704;0;1111-11-11 11:11.11
telegram=|1844AE4C4455223368077A55000000_041389E20100023B0000|
{"media":"water","meter":"iperl","name":"WaterWater","id":"33225544","total_m3":123.529,"max_flow_m3h":0,"timestamp":"1111-11-11T11:11:11Z"}
|WaterWater;33225544;123.529;0;1111-11-11 11:11.11
telegram=|31446850226677116980A0119F27020480048300C408F709143C003D341A2B0B2A0707000000000000062D114457563D71A1850000|
{"media":"heat cost allocator","meter":"fhkvdataiii","name":"Room","id":"11776622","current_hca":131,"current_date":"2020-02-08T02:00:00Z","previous_hca":1026,"previous_date":"2019-12-31T02:00:00Z","temp_room_c":22.44,"temp_radiator_c":25.51,"timestamp":"1111-11-11T11:11:11Z"}
|Room;11776622;131;2020-02-08T02:00:00Z;1026;2019-12-31T02:00:00Z;22.44;25.51;1111-11-11 11:11.11

Wyświetl plik

@ -0,0 +1,4 @@
telegram=|414493447514916746377275149167934446044D000020_0C06490000004C0600000000426CFF2CCC080611000000C2086C1F3102FD170000326CFFFF046D330F1432|
telegram=|5b44934475149167463778077975149167934446040dff5f3500823d0000810007c006ffff49000000ff2c000000001f3111000000008000800080008000800080008000800080000000000B002f02fd170000046d390d1432488408|
telegram=|414493447514916746377275149167934446044D000020_0C06490000004C0600000000426CFF2CCC080611000000C2086C1F3102FD170000326CFFFF046D330F1432|
telegram=|5b44934475149167463778077975149167934446040dff5f3500823d0000810007c006ffff49000000ff2c000000001f3111000000008000800080008000800080008000800080000000000B002f02fd170000046d390d1432488408|

Wyświetl plik

@ -60,7 +60,7 @@ telegram=|374468506549235827C3A2_129F25383300A8622600008200800A2AF86211517555287
# Test FHKV data II/III
# There is a problem in the decoding here, the data stored inside the telegram does not seem to properly encode/decode the year....
# We should not report a current_date with a full year, if the year is actually not part of the telegram.
telegram=|31446850226677116980A0119F27020480048300C408F709143C003D341A2B0B2A0707000000000000062D114457563D71A1850000|
telegram=|34446850226677116980A0119F27020480048300C408F709143C003D341A2B0B2A0707000000000000062D114457563D71A1850000|
{"media":"heat cost allocator","meter":"fhkvdataiii","name":"Room","id":"11776622","current_hca":131,"current_date":"2020-02-08T02:00:00Z","previous_hca":1026,"previous_date":"2019-12-31T02:00:00Z","temp_room_c":22.44,"temp_radiator_c":25.51,"timestamp":"1111-11-11T11:11:11Z"}
|Room;11776622;131;2020-02-08T02:00:00Z;1026;2019-12-31T02:00:00Z;22.44;25.51;1111-11-11 11:11.11
@ -199,7 +199,7 @@ telegram=|3944FA122162092002067A3600202567C94D48D00DC47B11213E23383DB51968A705AA
# Test topaseskr water meter
telegram=|4E44B40512345678F1077A310040052F2F_01FD08040C13991848004C1359423500CC101300000000CC201359423500426C7F2C0B3B00000002FD74DA10025AD300C4016D3B179F27CC011387124600|
{"media":"water","meter":"topaseskr","name":"Witer","id":"78563412","total_m3":481.899,"access_counter":4,"temperature_c":21.1,"current_flow_m3h":0,"volume_year_period_m3":354.259,"reverse_volume_year_period_m3":0,"meter_year_period_start_date":"2019-12-31","volume_month_period_m3":461.287,"meter_month_period_start_datetime":"2020-07-31 23:59","battery_y":11.811331,"timestamp":"1111-11-11T11:11:11Z"}
{"media":"water","meter":"topaseskr","name":"Witer","id":"78563412","total_m3":481.899,"access_counter":4,"temperature_c":21.1,"current_flow_m3h":0,"volume_year_period_m3":354.259,"reverse_volume_year_period_m3":0,"meter_year_period_end_date":"2019-12-31","volume_month_period_m3":461.287,"meter_month_period_end_datetime":"2020-07-31 23:59","battery_y":11.811331,"timestamp":"1111-11-11T11:11:11Z"}
|Witer;78563412;481.899;21.1;0;354.259;0;2019-12-31;461.287;2020-07-31 23:59;1111-11-11 11:11.11
# Test Ultrimis water meter

656
src/address.cc 100644
Wyświetl plik

@ -0,0 +1,656 @@
/*
Copyright (C) 2017-2024 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"address.h"
#include"manufacturers.h"
#include<assert.h>
#include<algorithm>
#include<string.h>
using namespace std;
vector<string> splitSequenceOfAddressExpressionsAtCommas(const string& mes);
bool isValidMatchExpression(const std::string& s, bool *has_wildcard);
bool doesIdMatchExpression(const std::string& id, std::string match_rule);
bool doesAddressMatchExpressions(Address &address,
std::vector<AddressExpression>& address_expressions,
bool *used_wildcard,
bool *filtered_out,
bool *required_found,
bool *required_failed);
bool isValidMatchExpression(const string& s, bool *has_wildcard)
{
string me = s;
// Examples of valid match expressions:
// 12345678
// *
// 123*
// !12345677
// 2222222*
// !22222222
// We also accept an secondary libmbus address:
// 100002842941011B
// A match expression cannot be empty.
if (me.length() == 0) return false;
// An me can be filtered out with an exclamation mark first.
if (me.front() == '!') me.erase(0, 1);
// More than one negation is not allowed.
if (me.front() == '!') return false;
// A match expression cannot be only a negation mark.
if (me.length() == 0) return false;
int count = 0;
// Some non-compliant meters have full hex in the id,
// but according to the standard there should only be bcd here...
// We accept hex anyway.
while (me.length() > 0 &&
((me.front() >= '0' && me.front() <= '9') ||
(me.front() >= 'A' && me.front() <= 'F') ||
(me.front() >= 'a' && me.front() <= 'f')))
{
me.erase(0,1);
count++;
}
if (me.length() == 0 && count == 16)
{
// A secondary libmbus address: 100002842941011B
// Strictly speaking the leading 8 digits should be bcd,
// but we accept hex as well.
*has_wildcard = false;
return true;
}
bool wildcard_used = false;
// An expression can end with a *
if (me.length() > 0 && me.front() == '*')
{
me.erase(0,1);
wildcard_used = true;
if (has_wildcard) *has_wildcard = true;
}
// Now we should have eaten the whole expression.
if (me.length() > 0) return false;
// Check the length of the matching bcd/hex
// If no wildcard is used, then the match expression must be exactly 8 digits.
if (!wildcard_used) return count == 8;
// If wildcard is used, then the match expressions must be 7 or less digits,
// even zero is allowed which means a single *, which matches any bcd/hex id.
return count <= 7;
}
vector<string> splitSequenceOfAddressExpressionsAtCommas(const string& mes)
{
vector<string> r;
bool eof, err;
vector<uchar> v (mes.begin(), mes.end());
auto i = v.begin();
for (;;) {
auto id = eatTo(v, i, ',', 64, &eof, &err);
if (err) break;
trimWhitespace(&id);
if (id == "ANYID") id = "*";
r.push_back(id);
if (eof) break;
}
return r;
}
bool isValidSequenceOfAddressExpressions(const string& mes)
{
vector<string> v = splitSequenceOfAddressExpressionsAtCommas(mes);
for (string me : v)
{
AddressExpression ae;
if (!ae.parse(me)) return false;
}
return true;
}
vector<AddressExpression> splitAddressExpressions(const string &aes)
{
vector<string> v = splitSequenceOfAddressExpressionsAtCommas(aes);
vector<AddressExpression> r;
for (string me : v)
{
AddressExpression ae;
if (ae.parse(me))
{
r.push_back(ae);
}
}
return r;
}
bool doesIdMatchExpression(const string& s, string match)
{
string id = s;
if (id.length() == 0) return false;
// Here we assume that the match expression has been
// verified to be valid.
bool can_match = true;
// Now match bcd/hex until end of id, or '*' in match.
while (id.length() > 0 && match.length() > 0 && match.front() != '*')
{
if (id.front() != match.front())
{
// We hit a difference, it cannot match.
can_match = false;
break;
}
id.erase(0,1);
match.erase(0,1);
}
bool wildcard_used = false;
if (match.length() && match.front() == '*')
{
wildcard_used = true;
match.erase(0,1);
}
if (can_match)
{
// Ok, now the match expression should be empty.
// If wildcard is true, then the id can still have digits,
// otherwise it must also be empty.
if (wildcard_used)
{
can_match = match.length() == 0;
}
else
{
can_match = match.length() == 0 && id.length() == 0;
}
}
return can_match;
}
bool hasWildCard(const string& mes)
{
return mes.find('*') != string::npos;
}
bool AddressExpression::match(const std::string &i, uint16_t m, uchar v, uchar t)
{
if (!(mfct == 0xffff || mfct == m)) return false;
if (!(version == 0xff || version == v)) return false;
if (!(type == 0xff || type == t)) return false;
if (!doesIdMatchExpression(i, id)) return false;
return true;
}
void AddressExpression::trimToIdentity(IdentityMode im, Address &a)
{
switch (im)
{
case IdentityMode::FULL:
id = a.id;
mfct = a.mfct;
version = a.version;
type = a.type;
required = true;
break;
case IdentityMode::ID_MFCT:
id = a.id;
mfct = a.mfct;
version = 0xff;
type = 0xff;
required = true;
break;
case IdentityMode::ID:
id = a.id;
mfct = 0xffff;
version = 0xff;
type = 0xff;
required = true;
break;
default:
break;
}
}
bool AddressExpression::parse(const string &in)
{
string s = in;
// Example: 12345678
// or 12345678.M=PII.T=1B.V=01
// or 1234*
// or 1234*.M=PII
// or 1234*.V=01
// or 12 // mbus primary
// or 0 // mbus primary
// or 250.MPII.V01.T1B // mbus primary
// or !12345678
// or !*.M=ABC
// or libmbus secondary style:
// 123456782941011B
id = "";
mbus_primary = false;
mfct = 0xffff;
type = 0xff;
version = 0xff;
filter_out = false;
if (s.size() == 0) return false;
if (s.size() > 1 && s[0] == '!')
{
filter_out = true;
s = s.substr(1);
// Double ! not allowed.
if (s.size() > 1 && s[0] == '!') return false;
}
vector<string> parts = splitString(s, '.');
assert(parts.size() > 0);
id = parts[0];
if (!isValidMatchExpression(id, &has_wildcard))
{
// Not a long id, so lets check if it is p0 to p250 for primary mbus ids.
if (id.size() < 2) return false;
if (id[0] != 'p') return false;
for (size_t i=1; i < id.length(); ++i)
{
if (!isdigit(id[i])) return false;
}
// All digits good.
int v = atoi(id.c_str()+1);
if (v < 0 || v > 250) return false;
// It is 0-250 which means it is an mbus primary address.
mbus_primary = true;
}
if (parts.size() == 1 && id.length() == 16)
{
// This is a secondary libmbus address.
string mfct_hex = id.substr(8,4);
string version_hex = id.substr(12,2);
string type_hex = id.substr(14,2);
id = id.substr(0,8);
vector<uchar> data;
bool ok = hex2bin(mfct_hex.c_str(), &data);
if (!ok) return false;
if (data.size() != 2) return false;
mfct = data[1] << 8 | data[0];
data.clear();
ok = hex2bin(version_hex.c_str(), &data);
if (!ok) return false;
if (data.size() != 1) return false;
version = data[0];
data.clear();
ok = hex2bin(type_hex.c_str(), &data);
if (!ok) return false;
if (data.size() != 1) return false;
type = data[0];
return true;
}
for (size_t i=1; i<parts.size(); ++i)
{
if (parts[i].size() == 4) // V=xy or T=xy
{
if (parts[i][1] != '=') return false;
vector<uchar> data;
bool ok = hex2bin(&parts[i][2], &data);
if (!ok) return false;
if (data.size() != 1) return false;
if (parts[i][0] == 'V')
{
version = data[0];
}
else if (parts[i][0] == 'T')
{
type = data[0];
}
else
{
return false;
}
}
else if (parts[i].size() == 5) // M=xyz
{
if (parts[i][1] != '=') return false;
if (parts[i][0] != 'M') return false;
bool ok = flagToManufacturer(&parts[i][2], &mfct);
if (!ok) return false;
}
else if (parts[i].size() == 6) // M=abcd explicit hex version
{
if (parts[i][1] != '=') return false;
if (parts[i][0] != 'M') return false;
vector<uchar> data;
bool ok = hex2bin(&parts[i][2], &data);
if (!ok) return false;
if (data.size() != 2) return false;
mfct = data[1] << 8 | data[0];
if (!ok) return false;
}
else
{
return false;
}
}
return true;
}
bool flagToManufacturer(const char *s, uint16_t *out_mfct)
{
if (s[0] == 0 || s[1] == 0 || s[2] == 0 || s[3] != 0) return false;
if (s[0] < '@' || s[0] > 'Z' ||
s[1] < '@' || s[1] > 'Z' ||
s[2] < '@' || s[2] > 'Z') return false;
*out_mfct = MANFCODE(s[0],s[1],s[2]);
return true;
}
string AddressExpression::str()
{
string s;
if (filter_out) s = "!";
if (required) s = "R";
s.append(id);
if (mfct != 0xffff)
{
s += ".M="+manufacturerFlag(mfct);
}
if (version != 0xff)
{
s += ".V="+tostrprintf("%02x", version);
}
if (type != 0xff)
{
s += ".T="+tostrprintf("%02x", type);
}
return s;
}
string Address::str()
{
string s;
s.append(id);
if (mfct != 0xffff)
{
s += ".M="+manufacturerFlag(mfct);
}
if (version != 0xff)
{
s += ".V="+tostrprintf("%02x", version);
}
if (type != 0xff)
{
s += ".T="+tostrprintf("%02x", type);
}
return s;
}
string Address::concat(std::vector<Address> &addresses)
{
string s;
for (Address& a: addresses)
{
if (s.size() > 0) s.append(",");
s.append(a.str());
}
return s;
}
string AddressExpression::concat(std::vector<AddressExpression> &address_expressions)
{
string s;
for (AddressExpression& a: address_expressions)
{
if (s.size() > 0) s.append(",");
s.append(a.str());
}
return s;
}
string manufacturerFlag(int m_field) {
char a = (m_field/1024)%32+64;
char b = (m_field/32)%32+64;
char c = (m_field)%32+64;
string flag;
flag += a;
flag += b;
flag += c;
return flag;
}
void Address::decodeMfctFirst(const vector<uchar>::iterator &pos)
{
mfct = *(pos+1) << 8 | *(pos+0);
id = tostrprintf("%02x%02x%02x%02x", *(pos+5), *(pos+4), *(pos+3), *(pos+2));
version = *(pos+6);
type = *(pos+7);
}
void Address::decodeIdFirst(const vector<uchar>::iterator &pos)
{
id = tostrprintf("%02x%02x%02x%02x", *(pos+3), *(pos+2), *(pos+1), *(pos+0));
mfct = *(pos+5) << 8 | *(pos+4);
version = *(pos+6);
type = *(pos+7);
}
bool doesTelegramMatchExpressions(std::vector<Address> &addresses,
std::vector<AddressExpression>& address_expressions,
bool *used_wildcard)
{
bool match = false;
bool filtered_out = false;
bool required_found = false; // An R12345678 field was found.
bool required_failed = true; // Init to fail, set to true if R is satistifed anywhere.
for (Address &a : addresses)
{
if (doesAddressMatchExpressions(a,
address_expressions,
used_wildcard,
&filtered_out,
&required_found,
&required_failed))
{
match = true;
}
// Go through all ids even though there is an early match.
// This way we can see if theres an exact match later.
}
// If any expression triggered a filter out, then the whole telegram does not match.
if (filtered_out) match = false;
// If a required field was found and it failed....
if (required_found && required_failed) match = false;
return match;
}
bool doesAddressMatchExpressions(Address &address,
vector<AddressExpression>& address_expressions,
bool *used_wildcard,
bool *filtered_out,
bool *required_found,
bool *required_failed)
{
bool found_match = false;
bool found_negative_match = false;
bool exact_match = false;
// Goes through all possible match expressions.
// If no expression matches, neither positive nor negative,
// then the result is false. (ie no match)
// If more than one positive match is found, and no negative,
// then the result is true.
// If more than one negative match is found, irrespective
// if there is any positive matches or not, then the result is false.
// If a positive match is found, using a wildcard not any exact match,
// then *used_wildcard is set to true.
// If an expression is required and it fails, then the match fails.
for (AddressExpression &ae : address_expressions)
{
bool has_wildcard = ae.has_wildcard;
bool is_negative_rule = ae.filter_out;
// We currently assume that only a single expression is required, the last one!
bool is_required = ae.required;
if (is_required) *required_found = true;
bool m = ae.match(address.id, address.mfct, address.version, address.type);
if (is_negative_rule)
{
if (m) found_negative_match = true;
}
else
{
if (m)
{
// A match, but the required does not count.
if (!is_required)
{
found_match = true;
if (!has_wildcard)
{
exact_match = true;
}
}
else
{
*required_failed = false;
}
}
}
}
if (found_negative_match)
{
*filtered_out = true;
return false;
}
if (found_match)
{
if (exact_match)
{
*used_wildcard = false;
}
else
{
*used_wildcard = true;
}
return true;
}
return false;
}
const char *toString(IdentityMode im)
{
switch (im)
{
case IdentityMode::ID: return "id";
case IdentityMode::ID_MFCT: return "id-mfct";
case IdentityMode::FULL: return "full";
case IdentityMode::NONE: return "none";
case IdentityMode::INVALID: return "invalid";
}
return "?";
}
IdentityMode toIdentityMode(const char *s)
{
if (!strcmp(s,"id")) return IdentityMode::ID;
if (!strcmp(s,"id-mfct")) return IdentityMode::ID_MFCT;
if (!strcmp(s, "full")) return IdentityMode::FULL;
if (!strcmp(s, "none")) return IdentityMode::NONE;
return IdentityMode::INVALID;
}
void AddressExpression::clear()
{
id = "";
has_wildcard = false;
mbus_primary = false;
mfct = 0xffff;
version = 0xff;
type = 0xff;
}
void AddressExpression::appendIdentity(IdentityMode im,
AddressExpression *identity_expression,
std::vector<Address> &as,
std::vector<AddressExpression> &es)
{
identity_expression->clear();
if (im == IdentityMode::NONE) return;
// Copy id, id-mfct, id-mfct-v-t to identity_expression from the last address.
identity_expression->trimToIdentity(im, as.back());
// Is this identity expression already in the list of address expressions?
if (std::find(es.begin(), es.end(), *identity_expression) == es.end())
{
// No, then add it at the end.
es.push_back(*identity_expression);
}
}
bool AddressExpression::operator==(const AddressExpression&ae) const
{
return id == ae.id &&
has_wildcard == ae.has_wildcard&&
mbus_primary == ae.mbus_primary &&
mfct == ae.mfct &&
version == ae.version &&
type == ae.type &&
filter_out == ae.filter_out;
}

117
src/address.h 100644
Wyświetl plik

@ -0,0 +1,117 @@
/*
Copyright (C) 2017-2022 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/>.
*/
#ifndef ADDRESS_H_
#define ADDRESS_H_
#include "util.h"
#include <string>
/**
IdentityMode:
@ID: The default, only the id groups the meter content.
@ID_MFCT: Used when you have two meters with the same id but different manufacturers.
@FULL: Used when you want to fully separate meter content on id.mft.v.t
@NONE: Do not separate any meters! This might lead to telegrams overwriting each others state.
Use this when no state is to be kept in the wmbusmeters object.
@INVALID: Cannot parse cmdline.
*/
enum class IdentityMode
{
ID,
ID_MFCT,
FULL,
NONE,
INVALID
};
const char *toString(IdentityMode im);
IdentityMode toIdentityMode(const char *s);
struct Address
{
std::string id; // p1 or 12345678 or non-compliant hex: 1234abcd
uint16_t mfct {};
uchar type {};
uchar version {};
void decodeMfctFirst(const std::vector<uchar>::iterator &pos);
void decodeIdFirst(const std::vector<uchar>::iterator &pos);
std::string str();
static std::string concat(std::vector<Address> &addresses);
};
struct AddressExpression
{
// An address expression is used to select which telegrams to decode for a driver.
// An address expression is also used to select a specific meter to poll for data.
// Example address: 12345678
// Or fully qualified: 12345678.M=PII.T=1b.V=01
// which means manufacturer triplet PII, type/media=0x1b, version=0x01
// Or wildcards in id: 12*.T=16
// which matches all cold water meters whose ids start with 12.
// Or negated tests: 12345678.V!=66
// which will decode all telegrams from 12345678 except those where the version is 0x66.
// Or every telegram which is does not start with 12 and is not from ABB:
// !12*.M!=ABB
std::string id; // p1 or 12345678 or non-compliant hex: 1234abcd
bool has_wildcard {}; // The id contains a *
bool mbus_primary {}; // Signals that the id is 0-250
uint16_t mfct { 0xffff }; // If 0xffff then any mfct matches this address.
uchar version { 0xff }; // If 0xff then any version matches this address.
uchar type { 0xff }; // If 0xff then any type matches this address.
bool filter_out {}; // Telegrams matching this rule should be filtered out!
bool required {}; // If true, then this address expression must be matched!
AddressExpression() {}
AddressExpression(Address &a) : id(a.id), mfct(a.mfct), version(a.version), type(a.type) { }
bool operator==(const AddressExpression&) const;
void clear();
void trimToIdentity(IdentityMode im, Address &a);
bool parse(const std::string &s);
bool match(const std::string &id, uint16_t mfct, uchar version, uchar type);
std::string str();
static std::string concat(std::vector<AddressExpression> &address_expressions);
static void appendIdentity(IdentityMode im,
AddressExpression *identity_expression,
std::vector<Address> &as,
std::vector<AddressExpression> &es);
};
/**
isValidSequenceOfAddressExpressions:
Valid sequenes look like this:
12345678
12345678,22334455,34*
12*.T=16,!*.M=XYZ
!*.V=33
*/
bool isValidSequenceOfAddressExpressions(const std::string& s);
std::vector<AddressExpression> splitAddressExpressions(const std::string &aes);
bool flagToManufacturer(const char *s, uint16_t *out_mfct);
std::string manufacturerFlag(int m_field);
bool doesTelegramMatchExpressions(std::vector<Address> &addresses,
std::vector<AddressExpression>& address_expressions,
bool *used_wildcard);
#endif

Wyświetl plik

@ -75,7 +75,6 @@ private:
// Then check if the rtl_sdr and/or rtl_wmbus and/or rtl_433 is available.
bool rtlsdr_found_ = false;
bool rtlwmbus_found_ = false;
bool rtl433_found_ = false;
// Remember devices that were not detected as wmbus devices.
// To avoid probing them again and again.

Wyświetl plik

@ -617,6 +617,15 @@ static shared_ptr<Configuration> parseNormalCommandLine(Configuration *c, int ar
i++;
continue;
}
if (!strncmp(argv[i], "--identitymode=", 15) && strlen(argv[i]) > 15) {
c->identity_mode = toIdentityMode(argv[i]+15);
if (c->identity_mode == IdentityMode::INVALID)
{
error("Not a valid identity mode. \"%s\"\n", argv[i]+15);
}
i++;
continue;
}
if (!strncmp(argv[i], "--resetafter=", 13) && strlen(argv[i]) > 13) {
c->resetafter = parseTime(argv[i]+13);
if (c->resetafter <= 0) {
@ -728,50 +737,31 @@ static shared_ptr<Configuration> parseNormalCommandLine(Configuration *c, int ar
string bus;
string name = argv[m*4+i+0];
string driver = argv[m*4+i+1];
string id = argv[m*4+i+2];
string address_expressions = argv[m*4+i+2];
string key = argv[m*4+i+3];
MeterInfo mi;
mi.parse(name, driver, id, key);
if (!isValidSequenceOfAddressExpressions(address_expressions))
{
error("Not a valid meter id nor a valid sequence of match expression \"%s\"\n", address_expressions.c_str());
}
mi.parse(name, driver, address_expressions, key);
mi.poll_interval = c->pollinterval;
mi.identity_mode = c->identity_mode;
if (!isValidKey(key, mi))
{
error("Not a valid meter key \"%s\"\n", key.c_str());
}
if (mi.driver_name.str() == "")
{
error("Not a valid meter driver \"%s\"\n", driver.c_str());
}
//LinkModeSet default_modes = toMeterLinkModeSet(mi.driver);
/*
if (default_modes.has(LinkMode::MBUS))
{
// MBus primary address 0-250
// secondary hex address iiiiiiiimmmmvvmm
}
else
{
// WMBus ids are 8 hex digits iiiiiiii
if (!isValidMatchExpressions(id, true)) error("Not a valid id nor a valid meter match expression \"%s\"\n", id.c_str());
}
if (!isValidKey(key, mi)) error("Not a valid meter key \"%s\"\n", key.c_str());
*/
c->meters.push_back(mi);
// Check if the devices can listen to the meter link mode(s).
/*
Ignore this check for now until all meters have been refactored.
if (!default_modes.hasAll(mi.link_modes))
{
string want = mi.link_modes.hr();
string has = default_modes.hr();
error("(cmdline) cannot set link modes to: %s because meter %s only transmits on: %s\n",
want.c_str(), mi.driverName().str().c_str(), has.c_str());
}
string modeshr = mi.link_modes.hr();
debug("(cmdline) setting link modes to %s for meter %s\n",
mi.link_modes.hr().c_str(), name.c_str());
*/
}
return shared_ptr<Configuration>(c);

Wyświetl plik

@ -53,10 +53,11 @@ void parseMeterConfig(Configuration *c, vector<char> &buf, string file)
string bus;
string name;
string driver = "auto";
string id;
string address_expressions;
string key = "";
string linkmodes;
int poll_interval = 0;
IdentityMode identity_mode {};
vector<string> telegram_shells;
vector<string> meter_shells;
vector<string> alarm_shells;
@ -108,7 +109,7 @@ void parseMeterConfig(Configuration *c, vector<char> &buf, string file)
else
if (p.first == "driver") driver = p.second;
else
if (p.first == "id") id = p.second;
if (p.first == "id") address_expressions = p.second;
else
if (p.first == "key")
{
@ -129,6 +130,15 @@ void parseMeterConfig(Configuration *c, vector<char> &buf, string file)
}
}
else
if (p.first == "identitymode") {
identity_mode = toIdentityMode(p.second.c_str());
if (identity_mode == IdentityMode::INVALID)
{
error("Invalid identity mode: \"%s\"!\n", p.second.c_str());
}
}
else
if (p.first == "shell") {
telegram_shells.push_back(p.second);
}
@ -176,37 +186,28 @@ void parseMeterConfig(Configuration *c, vector<char> &buf, string file)
MeterInfo mi;
mi.parse(name, driver, id, key); // sets driver, extras, name, bus, bps, link_modes, ids, name, key
mi.poll_interval = poll_interval;
/*
Ignore link mode checking until all drivers have been refactored.
LinkModeSet default_modes = toMeterLinkModeSet(mi.driver);
if (!default_modes.hasAll(mi.link_modes))
if (!isValidSequenceOfAddressExpressions(address_expressions))
{
string want = mi.link_modes.hr();
string has = default_modes.hr();
error("(cmdline) cannot set link modes to: %s because meter %s only transmits on: %s\n",
want.c_str(), mi.driverName().str().c_str(), has.c_str());
}
string modeshr = mi.link_modes.hr();
debug("(cmdline) setting link modes to %s for meter %s\n",
mi.link_modes.hr().c_str(), name.c_str());
*/
if (!isValidMatchExpressions(id, true)) {
warning("Not a valid meter id nor a valid meter match expression \"%s\"\n", id.c_str());
warning("In config, not a valid meter id nor a valid sequence of match expression \"%s\"\n", address_expressions.c_str());
use = false;
}
if (!isValidKey(key, mi)) {
warning("Not a valid meter key \"%s\"\n", key.c_str());
mi.parse(name, driver, address_expressions, key); // sets driver, extras, name, bus, bps, link_modes, ids, name, key
mi.poll_interval = poll_interval;
mi.identity_mode = identity_mode;
if (!isValidKey(key, mi))
{
warning("In config, not a valid meter key in config \"%s\"\n", key.c_str());
use = false;
}
if (use) {
if (use)
{
mi.extra_constant_fields = extra_constant_fields;
mi.extra_calculated_fields = extra_calculated_fields;
mi.shells = telegram_shells;
mi.meter_shells = meter_shells;
mi.idsc = toIdsCommaSeparated(mi.ids);
mi.selected_fields = selected_fields;
c->meters.push_back(mi);
}

Wyświetl plik

@ -99,6 +99,7 @@ struct Configuration
bool json {};
bool pretty_print_json {};
int pollinterval {}; // Time between polling of mbus meters.
IdentityMode identity_mode {}; // How to group meters identities into state objects.
bool fields {};
char separator { ';' };
std::vector<std::string> telegram_shells;

Wyświetl plik

@ -46,7 +46,7 @@ namespace
"Total cumulative active imported energy.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -58,7 +58,7 @@ namespace
"Total cumulative active imported energy per tariff.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -71,7 +71,7 @@ namespace
"Total cumulative active exported energy.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -85,7 +85,7 @@ namespace
"Total cumulative active exported energy per tariff.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -99,7 +99,7 @@ namespace
"Active tariff.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("01FF9300")),
Unit::NUMBER
@ -110,7 +110,7 @@ namespace
"Current transformer ratio (numerator).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FFA015")),
Unit::FACTOR
@ -121,7 +121,7 @@ namespace
"Voltage transformer ratio (numerator).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FFA115")),
Unit::FACTOR
@ -132,7 +132,7 @@ namespace
"Current transformer ratio (denominator).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FFA215")),
Unit::FACTOR
@ -143,7 +143,7 @@ namespace
"Voltage transformer ratio (denominator).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FFA315")),
Unit::FACTOR
@ -157,7 +157,7 @@ namespace
.set(MeasurementType::Instantaneous)
.set(DifVifKey("07FFA600")),
Translate::Lookup()
.add(Translate::Rule("ERROR_FLAGS", Translate::Type::BitToString)
.add(Translate::Rule("ERROR_FLAGS", Translate::MapType::BitToString)
.set(MaskBits(0xffffffffffffffff))
.set(DefaultMessage("OK"))
));
@ -170,7 +170,7 @@ namespace
.set(MeasurementType::Instantaneous)
.set(DifVifKey("07FFA700")),
Translate::Lookup()
.add(Translate::Rule("WARNING_FLAGS", Translate::Type::BitToString)
.add(Translate::Rule("WARNING_FLAGS", Translate::MapType::BitToString)
.set(MaskBits(0xffffffffffffffff))
.set(DefaultMessage("OK"))
));
@ -183,7 +183,7 @@ namespace
.set(MeasurementType::Instantaneous)
.set(DifVifKey("07FFA800")),
Translate::Lookup()
.add(Translate::Rule("INFORMATION_FLAGS", Translate::Type::BitToString)
.add(Translate::Rule("INFORMATION_FLAGS", Translate::MapType::BitToString)
.set(MaskBits(0xffffffffffffffff))
.set(DefaultMessage(""))
));
@ -196,7 +196,7 @@ namespace
.set(MeasurementType::Instantaneous)
.set(DifVifKey("07FFA900")),
Translate::Lookup()
.add(Translate::Rule("ALARM_FLAGS", Translate::Type::BitToString)
.add(Translate::Rule("ALARM_FLAGS", Translate::MapType::BitToString)
.set(MaskBits(0xfffffffffffffff))
.set(DefaultMessage("OK"))
));
@ -209,7 +209,7 @@ namespace
.set(MeasurementType::Instantaneous)
.set(DifVifKey("01FFAD00")),
Translate::Lookup()
.add(Translate::Rule("UNKNOWN", Translate::Type::BitToString)
.add(Translate::Rule("UNKNOWN", Translate::MapType::BitToString)
.set(MaskBits(0xff))
.set(DefaultMessage("OK"))
));
@ -236,7 +236,7 @@ namespace
"Power fail counter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FF9800"))
);
@ -246,7 +246,7 @@ namespace
"Instantaneous total active imported power.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -258,7 +258,7 @@ namespace
"Instantaneous active imported power for L1 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -271,7 +271,7 @@ namespace
"Instantaneous active imported power for L2 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -284,7 +284,7 @@ namespace
"Instantaneous active imported power for L3 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -297,7 +297,7 @@ namespace
"Instantaneous total reactive imported power.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -310,7 +310,7 @@ namespace
"Instantaneous reactive imported power for L1 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -324,7 +324,7 @@ namespace
"Instantaneous reactive imported power for L2 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -338,7 +338,7 @@ namespace
"Instantaneous reactive imported power for L3 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -352,7 +352,7 @@ namespace
"Instantaneous total apparent imported power.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -365,7 +365,7 @@ namespace
"Instantaneous apparent imported power for L1 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -379,7 +379,7 @@ namespace
"Instantaneous apparent imported power for L2 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -393,7 +393,7 @@ namespace
"Instantaneous apparent imported power for L3 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -407,7 +407,7 @@ namespace
"Instantaneous voltage between L1 and neutral.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
@ -420,7 +420,7 @@ namespace
"Instantaneous voltage between L2 and neutral.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
@ -433,7 +433,7 @@ namespace
"Instantaneous voltage between L3 and neutral.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
@ -446,7 +446,7 @@ namespace
"Instantaneous voltage between L1 and L2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
@ -459,7 +459,7 @@ namespace
"Instantaneous voltage between L2 and L3.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
@ -472,7 +472,7 @@ namespace
"Instantaneous voltage between L3 and L1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
@ -485,7 +485,7 @@ namespace
"Instantaneous current in the L1 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Amperage)
@ -498,7 +498,7 @@ namespace
"Instantaneous current in the L2 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Amperage)
@ -511,7 +511,7 @@ namespace
"Instantaneous current in the L3 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Amperage)
@ -524,7 +524,7 @@ namespace
"Frequency of AC",
DEFAULT_PRINT_PROPERTIES,
Quantity::Frequency,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("0AFFD900")),
Unit::HZ,
@ -536,7 +536,7 @@ namespace
"Power factor.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("02FFE000")),
Unit::FACTOR,
@ -548,7 +548,7 @@ namespace
"Power factor for phase L1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("02FFE0FF8100")),
Unit::FACTOR,
@ -560,7 +560,7 @@ namespace
"Power factor for phase L2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("02FFE0FF8200")),
Unit::FACTOR,
@ -572,7 +572,7 @@ namespace
"Power factor.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("02FFE0FF8300")),
Unit::FACTOR,
@ -584,7 +584,7 @@ namespace
"Total power phase angle.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Angle,
VifScaling::NoneSigned,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("02FFD200")),
Unit::DEGREE,
@ -596,7 +596,7 @@ namespace
"Power phase angle for phase L1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Angle,
VifScaling::NoneSigned,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("02FFD2FF8100")),
Unit::DEGREE,
@ -608,7 +608,7 @@ namespace
"Power phase angle for phase L2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Angle,
VifScaling::NoneSigned,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("02FFD2FF8200")),
Unit::DEGREE,
@ -620,7 +620,7 @@ namespace
"Power phase angle for phase L3.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Angle,
VifScaling::NoneSigned,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("02FFD2FF8300")),
Unit::DEGREE,
@ -632,7 +632,7 @@ namespace
"Total cumulative reactive kvarh imported energy.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Reactive_Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -646,7 +646,7 @@ namespace
"Total cumulative reactive kvarh imported energy per tariff.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -660,7 +660,7 @@ namespace
"Total cumulative reactive kvarh exported energy.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Reactive_Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -674,7 +674,7 @@ namespace
"Total cumulative reactive kvarh exported energy per tariff.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -688,7 +688,7 @@ namespace
"The quadrant in which the current is measured.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("01FF9700")),
Unit::NUMBER
@ -699,7 +699,7 @@ namespace
"The quadrant in which the current is measured for phase L1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("01FF97FF8100")),
Unit::NUMBER
@ -710,7 +710,7 @@ namespace
"The quadrant in which the current is measured for phase L2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("01FF97FF8200")),
Unit::NUMBER
@ -721,7 +721,7 @@ namespace
"The quadrant in which the current is measured for phase L3.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("01FF97FF8300")),
Unit::NUMBER
@ -739,7 +739,7 @@ namespace
.set(SubUnitNr(1),SubUnitNr(2))
.add(VIFCombinableRaw(0)),
Translate::Lookup()
.add(Translate::Rule("OUTPUT", Translate::Type::BitToString)
.add(Translate::Rule("OUTPUT", Translate::MapType::BitToString)
.set(MaskBits(0xff))
));
@ -753,7 +753,7 @@ namespace
.set(SubUnitNr(3),SubUnitNr(4))
.add(VIFCombinableRaw(0)),
Translate::Lookup()
.add(Translate::Rule("INPUT", Translate::Type::BitToString)
.add(Translate::Rule("INPUT", Translate::MapType::BitToString)
.set(MaskBits(0xff))
));
@ -768,7 +768,7 @@ namespace
.set(SubUnitNr(3),SubUnitNr(4))
.add(VIFCombinableRaw(0)),
Translate::Lookup()
.add(Translate::Rule("INPUT", Translate::Type::BitToString)
.add(Translate::Rule("INPUT", Translate::MapType::BitToString)
.set(MaskBits(0xff))
));
@ -777,7 +777,7 @@ namespace
"Number of times input 1-2 counted a 1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(SubUnitNr(3),SubUnitNr(4))
@ -790,7 +790,7 @@ namespace
"Resettable cumulative active imported energy.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -803,7 +803,7 @@ namespace
"Resettable cumulative active exported energy.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -817,7 +817,7 @@ namespace
"Resettable cumulative reactive imported energy.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -831,7 +831,7 @@ namespace
"Resettable cumulative reactive exported energy.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -845,7 +845,7 @@ namespace
"Number of times the resettable energy imported value has been reset.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRaw(0x7f71))
@ -857,7 +857,7 @@ namespace
"Number of times the resettable active energy exported value has been reset.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRaw(0x7f71))
@ -870,7 +870,7 @@ namespace
"Number of times the resettable reactive energy imported value has been reset.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRaw(0x7f71))
@ -883,7 +883,7 @@ namespace
"Number of times the resettable reactive energy exported value has been reset.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRaw(0x7f71))
@ -896,7 +896,7 @@ namespace
"Energy in co2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Mass,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("0EFFF9C400")),
Unit::KG,
@ -908,7 +908,7 @@ namespace
"CO2 conversion factor (kg * 10-3 /kWh).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FFA400")),
Unit::FACTOR
@ -919,7 +919,7 @@ namespace
"Energy in currency.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("0EFFF9C900"))
);
@ -929,7 +929,7 @@ namespace
"Currency conversion factor (curr * 10-3 /kWh).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FFA500")),
Unit::FACTOR
@ -940,7 +940,7 @@ namespace
"Total cumulative apparent kvah imported energy.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Apparent_Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -954,7 +954,7 @@ namespace
"Total cumulative apparent kvah exported energy.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Apparent_Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -968,7 +968,7 @@ namespace
"Total imported active energy for L1 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -981,7 +981,7 @@ namespace
"Total imported active energy for L2 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -994,7 +994,7 @@ namespace
"Total imported active energy for L3 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1007,7 +1007,7 @@ namespace
"Total imported reactive energy for L1 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1021,7 +1021,7 @@ namespace
"Total imported reactive energy for L2 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1035,7 +1035,7 @@ namespace
"Total imported reactive energy for L3 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1049,7 +1049,7 @@ namespace
"Total imported apparent energy for L1 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1063,7 +1063,7 @@ namespace
"Total imported apparent energy for L2 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1077,7 +1077,7 @@ namespace
"Total imported apparent energy for L3 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1091,7 +1091,7 @@ namespace
"Total exported active energy for L1 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1105,7 +1105,7 @@ namespace
"Total exported active energy for L2 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1119,7 +1119,7 @@ namespace
"Total exported active energy for L3 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1133,7 +1133,7 @@ namespace
"Total exported reactive energy for L1 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1147,7 +1147,7 @@ namespace
"Total exported reactive energy for L2 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1161,7 +1161,7 @@ namespace
"Total exported reactive energy for L3 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1175,7 +1175,7 @@ namespace
"Total exported apparent energy for L1 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1189,7 +1189,7 @@ namespace
"Total exported apparent energy for L2 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1203,7 +1203,7 @@ namespace
"Total exported apparent energy for L3 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1217,7 +1217,7 @@ namespace
"Active net energy total.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1230,7 +1230,7 @@ namespace
"Active net energy total for phase L1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1244,7 +1244,7 @@ namespace
"Active net energy total for phase L2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1258,7 +1258,7 @@ namespace
"Active net energy total for phase L3.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1272,7 +1272,7 @@ namespace
"Active net energy total.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1286,7 +1286,7 @@ namespace
"Active net reactive energy total for phase L1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1301,7 +1301,7 @@ namespace
"Active net reactive energy total for phase L2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1316,7 +1316,7 @@ namespace
"Active net reactive energy total for phase L3.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1331,7 +1331,7 @@ namespace
"Active net energy total.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1345,7 +1345,7 @@ namespace
"Active net apparent energy total for phase L1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1360,7 +1360,7 @@ namespace
"Active net apparent energy total for phase L2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -1375,7 +1375,7 @@ namespace
"Active net apparent energy total for phase L3.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)

Wyświetl plik

@ -41,7 +41,7 @@ namespace
"The total gas consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -53,7 +53,7 @@ namespace
"The current gas flow.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow)
@ -64,7 +64,7 @@ namespace
"The current temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::FlowTemperature)
@ -75,7 +75,7 @@ namespace
"Date time when previous billing period ended.",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::DateTime)
@ -87,7 +87,7 @@ namespace
"The total gas consumption recorded when the previous billing period ended.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)

Wyświetl plik

@ -43,7 +43,7 @@ namespace
"The total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -54,7 +54,7 @@ namespace
"Current power consumption.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::PowerW)
@ -65,7 +65,7 @@ namespace
"The total energy production recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("0E833C"))
);
@ -75,7 +75,7 @@ namespace
"Current power production.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("0BAB3C"))
);
@ -85,7 +85,7 @@ namespace
"Voltage at phase L1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("0AFDC9FC01"))
);
@ -95,7 +95,7 @@ namespace
"Voltage at phase L2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("0AFDC9FC02"))
);
@ -105,7 +105,7 @@ namespace
"Voltage at phase L3.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("0AFDC9FC03"))
);
@ -124,7 +124,7 @@ namespace
"The total energy consumption recorded by this meter on tariff 1.",
DEFAULT_PRINT_PROPERTIES, // ,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -136,7 +136,7 @@ namespace
"The total energy consumption recorded by this meter on tariff 2.",
DEFAULT_PRINT_PROPERTIES, // ,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -148,7 +148,7 @@ namespace
"The total energy consumption recorded by this meter on tariff 3.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -160,7 +160,7 @@ namespace
"The total energy production recorded by this meter on tariff 1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("8E10833C"))
);
@ -170,7 +170,7 @@ namespace
"The total energy production recorded by this meter on tariff 2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("8E20833C"))
);
@ -180,7 +180,7 @@ namespace
"The total energy production recorded by this meter on tariff 3.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("8E30833C"))
);
@ -190,7 +190,7 @@ namespace
"The maximum demand indicator (maximum 15-min average power consumption recorded this month).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::AnyPowerVIF)

Wyświetl plik

@ -48,7 +48,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
@ -75,7 +75,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"",
{
@ -95,7 +95,7 @@ namespace
"The current heat cost allocation.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -106,7 +106,7 @@ namespace
"Heat cost allocation at the most recent billing period date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -118,7 +118,7 @@ namespace
"The heat cost allocation at set date #.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)

Wyświetl plik

@ -49,7 +49,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
@ -69,7 +69,7 @@ namespace
"The total water consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -80,7 +80,7 @@ namespace
"Water consumption at the # billing period date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -100,7 +100,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"",
{

Wyświetl plik

@ -72,7 +72,7 @@ namespace
"The total heat energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -83,7 +83,7 @@ namespace
"The total heating media volume recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -101,7 +101,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::DecimalsToString,
Translate::MapType::DecimalsToString,
AlwaysTrigger, MaskBits(9999),
"OK",
{
@ -152,7 +152,7 @@ namespace
"The total heat energy consumption recorded at end of previous month.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(StorageNr(32+i))
@ -169,7 +169,7 @@ namespace
tostrprintf("Previous month %d last date.", i+1),
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(StorageNr(32+i))
@ -184,7 +184,7 @@ namespace
"The total heat energy consumption at the due date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(StorageNr(8))
@ -206,7 +206,7 @@ namespace
"The current heat media volume flow.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow)
@ -217,7 +217,7 @@ namespace
"The current power consumption.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::PowerW)
@ -228,7 +228,7 @@ namespace
"The total heat energy consumption recorded at end of last month.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(StorageNr(32))
@ -249,7 +249,7 @@ namespace
"Maximum power consumption last month.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(StorageNr(32))
@ -262,7 +262,7 @@ namespace
"The current forward heat media temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::FlowTemperature)
@ -273,7 +273,7 @@ namespace
"The current return heat media temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ReturnTemperature)
@ -284,17 +284,17 @@ namespace
// Test: Heat c5isf 55445555 NOKEY
// telegram=|E544496A55554455880D7A320200002F2F_04060000000004130000000002FD17240084800106000000008280016C2124C480010600000080C280016CFFFF84810106000000808281016CFFFFC481010600000080C281016CFFFF84820106000000808282016CFFFFC482010600000080C282016CFFFF84830106000000808283016CFFFFC483010600000080C283016CFFFF84840106000000808284016CFFFFC484010600000080C284016CFFFF84850106000000808285016CFFFFC485010600000080C285016CFFFF84860106000000808286016CFFFFC486010600000080C286016CFFFF|
// {"media":"heat/cooling load","meter":"c5isf","name":"Heat","id":"55445555","total_energy_consumption_kwh":0,"total_volume_m3":0,"status":"ERROR REVERSE_FLOW SUPPLY_SENSOR_INTERRUPTED","prev_1_month":"2017-04-01","prev_2_month":"2127-15-31","prev_3_month":"2127-15-31","prev_4_month":"2127-15-31","prev_5_month":"2127-15-31","prev_6_month":"2127-15-31","prev_7_month":"2127-15-31","prev_8_month":"2127-15-31","prev_9_month":"2127-15-31","prev_10_month":"2127-15-31","prev_11_month":"2127-15-31","prev_12_month":"2127-15-31","prev_13_month":"2127-15-31","prev_14_month":"2127-15-31","prev_1_month_kwh":0,"prev_2_month_kwh":2147483648,"prev_3_month_kwh":2147483648,"prev_4_month_kwh":2147483648,"prev_5_month_kwh":2147483648,"prev_6_month_kwh":2147483648,"prev_7_month_kwh":2147483648,"prev_8_month_kwh":2147483648,"prev_9_month_kwh":2147483648,"prev_10_month_kwh":2147483648,"prev_11_month_kwh":2147483648,"prev_12_month_kwh":2147483648,"prev_13_month_kwh":2147483648,"prev_14_month_kwh":2147483648,"total_energy_consumption_last_month_kwh":0,"timestamp":"1111-11-11T11:11:11Z"}
// {"media":"heat/cooling load","meter":"c5isf","name":"Heat","id":"55445555","total_energy_consumption_kwh":0,"total_volume_m3":0,"status":"ERROR REVERSE_FLOW SUPPLY_SENSOR_INTERRUPTED","prev_1_month":"2017-04-01","prev_2_month":"2127-15-31","prev_3_month":"2127-15-31","prev_4_month":"2127-15-31","prev_5_month":"2127-15-31","prev_6_month":"2127-15-31","prev_7_month":"2127-15-31","prev_8_month":"2127-15-31","prev_9_month":"2127-15-31","prev_10_month":"2127-15-31","prev_11_month":"2127-15-31","prev_12_month":"2127-15-31","prev_13_month":"2127-15-31","prev_14_month":"2127-15-31","prev_1_month_kwh":0,"prev_2_month_kwh":-2147483648,"prev_3_month_kwh":-2147483648,"prev_4_month_kwh":-2147483648,"prev_5_month_kwh":-2147483648,"prev_6_month_kwh":-2147483648,"prev_7_month_kwh":-2147483648,"prev_8_month_kwh":-2147483648,"prev_9_month_kwh":-2147483648,"prev_10_month_kwh":-2147483648,"prev_11_month_kwh":-2147483648,"prev_12_month_kwh":-2147483648,"prev_13_month_kwh":-2147483648,"prev_14_month_kwh":-2147483648,"total_energy_consumption_last_month_kwh":0,"timestamp":"1111-11-11T11:11:11Z"}
// |Heat;55445555;0;0;ERROR REVERSE_FLOW SUPPLY_SENSOR_INTERRUPTED;1111-11-11 11:11.11
// Type T1A2 telegram:
// telegram=|DA44496A5555445588077A320200002F2F_04140000000084800114000000008280016C2124C480011400000080C280016CFFFF84810114000000808281016CFFFFC481011400000080C281016CFFFF84820114000000808282016CFFFFC482011400000080C282016CFFFF84830114000000808283016CFFFFC483011400000080C283016CFFFF84840114000000808284016CFFFFC484011400000080C284016CFFFF84850114000000808285016CFFFFC485011400000080C285016CFFFF84860114000000808286016CFFFFC486011400000080C286016CFFFF|
// {"id": "55445555","media": "water","meter": "c5isf","name": "Heat","prev_10_month": "2127-15-31","prev_10_month_kwh": 2147483648,"prev_10_month_m3": 21474836.48,"prev_11_month": "2127-15-31","prev_11_month_kwh": 2147483648,"prev_11_month_m3": 21474836.48,"prev_12_month": "2127-15-31","prev_12_month_kwh": 2147483648,"prev_12_month_m3": 21474836.48,"prev_13_month": "2127-15-31","prev_13_month_kwh": 2147483648,"prev_13_month_m3": 21474836.48,"prev_14_month": "2127-15-31","prev_14_month_kwh": 2147483648,"prev_14_month_m3": 21474836.48,"prev_1_month": "2017-04-01","prev_1_month_kwh": 0,"prev_1_month_m3": 0,"prev_2_month": "2127-15-31","prev_2_month_kwh": 2147483648,"prev_2_month_m3": 21474836.48,"prev_3_month": "2127-15-31","prev_3_month_kwh": 2147483648,"prev_3_month_m3": 21474836.48,"prev_4_month": "2127-15-31","prev_4_month_kwh": 2147483648,"prev_4_month_m3": 21474836.48,"prev_5_month": "2127-15-31","prev_5_month_kwh": 2147483648,"prev_5_month_m3": 21474836.48,"prev_6_month": "2127-15-31","prev_6_month_kwh": 2147483648,"prev_6_month_m3": 21474836.48,"prev_7_month": "2127-15-31","prev_7_month_kwh": 2147483648,"prev_7_month_m3": 21474836.48,"prev_8_month": "2127-15-31","prev_8_month_kwh": 2147483648,"prev_8_month_m3": 21474836.48,"prev_9_month": "2127-15-31","prev_9_month_kwh": 2147483648,"prev_9_month_m3": 21474836.48,"status": "ERROR","timestamp": "1111-11-11T11:11:11Z","total_energy_consumption_kwh": 0,"total_energy_consumption_last_month_kwh": 0,"total_volume_m3": 0}
// {"id": "55445555","media": "water","meter": "c5isf","name": "Heat","prev_10_month": "2127-15-31","prev_10_month_kwh":-2147483648,"prev_10_month_m3":-21474836.48,"prev_11_month": "2127-15-31","prev_11_month_kwh":-2147483648,"prev_11_month_m3":-21474836.48,"prev_12_month": "2127-15-31","prev_12_month_kwh":-2147483648,"prev_12_month_m3":-21474836.48,"prev_13_month": "2127-15-31","prev_13_month_kwh":-2147483648,"prev_13_month_m3":-21474836.48,"prev_14_month": "2127-15-31","prev_14_month_kwh":-2147483648,"prev_14_month_m3":-21474836.48,"prev_1_month": "2017-04-01","prev_1_month_kwh": 0,"prev_1_month_m3": 0,"prev_2_month": "2127-15-31","prev_2_month_kwh":-2147483648,"prev_2_month_m3":-21474836.48,"prev_3_month": "2127-15-31","prev_3_month_kwh":-2147483648,"prev_3_month_m3":-21474836.48,"prev_4_month": "2127-15-31","prev_4_month_kwh":-2147483648,"prev_4_month_m3":-21474836.48,"prev_5_month": "2127-15-31","prev_5_month_kwh":-2147483648,"prev_5_month_m3":-21474836.48,"prev_6_month": "2127-15-31","prev_6_month_kwh":-2147483648,"prev_6_month_m3":-21474836.48,"prev_7_month": "2127-15-31","prev_7_month_kwh":-2147483648,"prev_7_month_m3":-21474836.48,"prev_8_month": "2127-15-31","prev_8_month_kwh":-2147483648,"prev_8_month_m3":-21474836.48,"prev_9_month": "2127-15-31","prev_9_month_kwh":-2147483648,"prev_9_month_m3":-21474836.48,"status": "ERROR","timestamp": "1111-11-11T11:11:11Z","total_energy_consumption_kwh": 0,"total_energy_consumption_last_month_kwh": 0,"total_volume_m3": 0}
// |Heat;55445555;0;0;ERROR;1111-11-11 11:11.11
// Type T1B telegram:
// telegram=|5E44496A5555445588047A0A0050052F2F_04061A0000000413C20800008404060000000082046CC121043BA4000000042D1900000002591216025DE21002FD17000084800106000000008280016CC121948001AE25000000002F2F2F2F2F2F|
// {"due_date": "2022-01-01","due_energy_consumption_kwh": 0,"flow_temperature_c": 56.5,"id": "55445555","max_power_last_month_kw": 0,"media": "heat","meter": "c5isf","name": "Heat","power_kw": 2.5,"prev_10_month": "2127-15-31","prev_10_month_kwh": 2147483648,"prev_10_month_m3": 21474836.48,"prev_11_month": "2127-15-31","prev_11_month_kwh": 2147483648,"prev_11_month_m3": 21474836.48,"prev_12_month": "2127-15-31","prev_12_month_kwh": 2147483648,"prev_12_month_m3": 21474836.48,"prev_13_month": "2127-15-31","prev_13_month_kwh": 2147483648,"prev_13_month_m3": 21474836.48,"prev_14_month": "2127-15-31","prev_14_month_kwh": 2147483648,"prev_14_month_m3": 21474836.48,"prev_1_month": "2022-01-01","prev_1_month_kwh": 0,"prev_1_month_m3": 0,"prev_2_month": "2127-15-31","prev_2_month_kwh": 2147483648,"prev_2_month_m3": 21474836.48,"prev_3_month": "2127-15-31","prev_3_month_kwh": 2147483648,"prev_3_month_m3": 21474836.48,"prev_4_month": "2127-15-31","prev_4_month_kwh": 2147483648,"prev_4_month_m3": 21474836.48,"prev_5_month": "2127-15-31","prev_5_month_kwh": 2147483648,"prev_5_month_m3": 21474836.48,"prev_6_month": "2127-15-31","prev_6_month_kwh": 2147483648,"prev_6_month_m3": 21474836.48,"prev_7_month": "2127-15-31","prev_7_month_kwh": 2147483648,"prev_7_month_m3": 21474836.48,"prev_8_month": "2127-15-31","prev_8_month_kwh": 2147483648,"prev_8_month_m3": 21474836.48,"prev_9_month": "2127-15-31","prev_9_month_kwh": 2147483648,"prev_9_month_m3": 21474836.48,"return_temperature_c": 43.22,"status": "OK","timestamp": "1111-11-11T11:11:11Z","total_energy_consumption_kwh": 26,"total_energy_consumption_last_month_kwh": 0,"total_volume_m3": 2.242,"volume_flow_m3h": 0.164}
// {"due_date": "2022-01-01","due_energy_consumption_kwh": 0,"flow_temperature_c": 56.5,"id": "55445555","max_power_last_month_kw": 0,"media": "heat","meter": "c5isf","name": "Heat","power_kw": 2.5,"prev_10_month": "2127-15-31","prev_10_month_kwh":-2147483648,"prev_10_month_m3":-21474836.48,"prev_11_month": "2127-15-31","prev_11_month_kwh":-2147483648,"prev_11_month_m3":-21474836.48,"prev_12_month": "2127-15-31","prev_12_month_kwh":-2147483648,"prev_12_month_m3":-21474836.48,"prev_13_month": "2127-15-31","prev_13_month_kwh":-2147483648,"prev_13_month_m3":-21474836.48,"prev_14_month": "2127-15-31","prev_14_month_kwh":-2147483648,"prev_14_month_m3":-21474836.48,"prev_1_month": "2022-01-01","prev_1_month_kwh": 0,"prev_1_month_m3": 0,"prev_2_month": "2127-15-31","prev_2_month_kwh":-2147483648,"prev_2_month_m3":-21474836.48,"prev_3_month": "2127-15-31","prev_3_month_kwh":-2147483648,"prev_3_month_m3":-21474836.48,"prev_4_month": "2127-15-31","prev_4_month_kwh":-2147483648,"prev_4_month_m3":-21474836.48,"prev_5_month": "2127-15-31","prev_5_month_kwh":-2147483648,"prev_5_month_m3":-21474836.48,"prev_6_month": "2127-15-31","prev_6_month_kwh":-2147483648,"prev_6_month_m3":-21474836.48,"prev_7_month": "2127-15-31","prev_7_month_kwh":-2147483648,"prev_7_month_m3":-21474836.48,"prev_8_month": "2127-15-31","prev_8_month_kwh":-2147483648,"prev_8_month_m3":-21474836.48,"prev_9_month": "2127-15-31","prev_9_month_kwh":-2147483648,"prev_9_month_m3":-21474836.48,"return_temperature_c": 43.22,"status": "OK","timestamp": "1111-11-11T11:11:11Z","total_energy_consumption_kwh": 26,"total_energy_consumption_last_month_kwh": 0,"total_volume_m3": 2.242,"volume_flow_m3h": 0.164}
// |Heat;55445555;26;2.242;OK;1111-11-11 11:11.11
// Test: Heat c5isf 32002044 NOKEY

Wyświetl plik

@ -51,7 +51,7 @@ namespace
"The current temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ExternalTemperature)
@ -62,7 +62,7 @@ namespace
"The average temperature over the last hour.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ExternalTemperature)
@ -77,7 +77,7 @@ namespace
.set(MeasurementType::Instantaneous)
.set(VIFRange::DigitalInput),
Translate::Lookup()
.add(Translate::Rule("BATTERY", Translate::Type::BitToString)
.add(Translate::Rule("BATTERY", Translate::MapType::BitToString)
.set(MaskBits(0xffff)))
);
}

Wyświetl plik

@ -47,7 +47,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
@ -61,7 +61,7 @@ namespace
"The total water consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)

Wyświetl plik

@ -30,16 +30,22 @@ void check_detection_triplets(DriverInfo *di, string file);
string check_field_name(const char *name, DriverDynamic *dd);
Quantity check_field_quantity(const char *quantity_s, DriverDynamic *dd);
VifScaling check_vif_scaling(const char *vif_scaling_s, DriverDynamic *dd);
DifSignedness check_dif_signedness(const char *dif_signedness_s, DriverDynamic *dd);
PrintProperties check_print_properties(const char *print_properties_s, DriverDynamic *dd);
string get_translation(XMQDoc *doc, XMQNode *node, string name, string lang);
string check_calculate(const char *formula, DriverDynamic *dd);
Unit check_display_unit(const char *display_unit, DriverDynamic *dd);
bool checked_set_difvifkey(const char *difvifkey_s, FieldMatcher *fm, DriverDynamic *dd);
void checked_set_measurement_type(const char *measurement_type_s, FieldMatcher *fm, DriverDynamic *dd);
void checked_set_vif_range(const char *vif_range_s, FieldMatcher *fm, DriverDynamic *dd);
void checked_set_storagenr_range(const char *storagenr_range_s, FieldMatcher *fm, DriverDynamic *dd);
void checked_set_tariffnr_range(const char *tariffnr_range_s, FieldMatcher *fm, DriverDynamic *dd);
void checked_set_subunitnr_range(const char *subunitnr_range_s, FieldMatcher *fm, DriverDynamic *dd);
Translate::MapType checked_map_type(const char *map_type_s, DriverDynamic *dd);
uint64_t checked_mask_bits(const char *mask_bits_s, DriverDynamic *dd);
uint64_t checked_value(const char *value_s, DriverDynamic *dd);
TestBit checked_test_type(const char *test_s, DriverDynamic *dd);
void checked_add_vif_combinable(const char *vif_range_s, FieldMatcher *fm, DriverDynamic *dd);
const char *line = "-------------------------------------------------------------------------------";
@ -59,12 +65,12 @@ bool DriverDynamic::load(DriverInfo *di, const string &file_name, const char *co
if (!content)
{
ok = xmqParseFile(doc, file.c_str(), NULL);
ok = xmqParseFile(doc, file.c_str(), NULL, 0);
}
else
{
file = "builtin";
ok = xmqParseBuffer(doc, content, content+strlen(content), NULL);
ok = xmqParseBuffer(doc, content, content+strlen(content), NULL, 0);
}
if (!ok) {
@ -78,13 +84,13 @@ bool DriverDynamic::load(DriverInfo *di, const string &file_name, const char *co
try
{
string name = check_driver_name(xmqGetString(doc, NULL, "/driver/name"), file);
string name = check_driver_name(xmqGetString(doc, "/driver/name"), file);
di->setName(name);
MeterType meter_type = check_meter_type(xmqGetString(doc, NULL, "/driver/meter_type"), file);
MeterType meter_type = check_meter_type(xmqGetString(doc, "/driver/meter_type"), file);
di->setMeterType(meter_type);
string default_fields = check_default_fields(xmqGetString(doc, NULL, "/driver/default_fields"), file);
string default_fields = check_default_fields(xmqGetString(doc, "/driver/default_fields"), file);
di->setDefaultFields(default_fields);
if (!content)
@ -94,7 +100,7 @@ bool DriverDynamic::load(DriverInfo *di, const string &file_name, const char *co
di->setDynamic(file, doc);
xmqForeach(doc, NULL, "/driver/detect/mvt", (XMQNodeCallback)add_detect, di);
xmqForeach(doc, "/driver/detect/mvt", (XMQNodeCallback)add_detect, di);
check_detection_triplets(di, file);
@ -104,6 +110,8 @@ bool DriverDynamic::load(DriverInfo *di, const string &file_name, const char *co
}
catch (...)
{
xmqFreeDoc(doc);
di->setDynamic(file, NULL);
return false;
}
}
@ -111,20 +119,22 @@ bool DriverDynamic::load(DriverInfo *di, const string &file_name, const char *co
DriverDynamic::DriverDynamic(MeterInfo &mi, DriverInfo &di) :
MeterCommonImplementation(mi, di), file_name_(di.getDynamicFileName())
{
XMQDoc *doc = NULL;
try
{
XMQDoc *doc = di.getDynamicDriver();
doc = di.getDynamicDriver();
assert(doc);
verbose("(driver) constructing driver %s from already loaded file %s\n",
di.name().str().c_str(),
fileName().c_str());
xmqForeach(doc, NULL, "/driver/use", (XMQNodeCallback)add_use, this);
xmqForeach(doc, NULL, "/driver/field", (XMQNodeCallback)add_field, this);
xmqForeach(doc, "/driver/use", (XMQNodeCallback)add_use, this);
xmqForeach(doc, "/driver/field", (XMQNodeCallback)add_field, this);
}
catch(...)
{
xmqFreeDoc(doc);
}
}
@ -134,7 +144,7 @@ DriverDynamic::~DriverDynamic()
XMQProceed DriverDynamic::add_detect(XMQDoc *doc, XMQNode *detect, DriverInfo *di)
{
string mvt = xmqGetString(doc, detect, ".");
string mvt = xmqGetStringRel(doc, ".", detect);
auto fields = splitString(mvt, ',');
if (fields.size() != 3)
@ -147,7 +157,7 @@ XMQProceed DriverDynamic::add_detect(XMQDoc *doc, XMQNode *detect, DriverInfo *d
mvt.c_str(),
line,
line);
throw 1;
return XMQ_CONTINUE;
}
string mfct = fields[0];
@ -172,7 +182,7 @@ XMQProceed DriverDynamic::add_detect(XMQDoc *doc, XMQNode *detect, DriverInfo *d
mfct.c_str(),
line,
line);
throw 1;
return XMQ_CONTINUE;
}
mfct_code = toMfctCode(a, b, c);
}
@ -190,7 +200,7 @@ XMQProceed DriverDynamic::add_detect(XMQDoc *doc, XMQNode *detect, DriverInfo *d
mfct.c_str(),
line,
line);
throw 1;
return XMQ_CONTINUE;
}
}
@ -204,7 +214,7 @@ XMQProceed DriverDynamic::add_detect(XMQDoc *doc, XMQNode *detect, DriverInfo *d
version,
line,
line);
throw 1;
return XMQ_CONTINUE;
}
if (type > 255 || type < 0)
@ -217,7 +227,7 @@ XMQProceed DriverDynamic::add_detect(XMQDoc *doc, XMQNode *detect, DriverInfo *d
type,
line,
line);
throw 1;
return XMQ_CONTINUE;
}
string mfct_flag = manufacturerFlag(mfct_code);
@ -233,7 +243,7 @@ XMQProceed DriverDynamic::add_detect(XMQDoc *doc, XMQNode *detect, DriverInfo *d
XMQProceed DriverDynamic::add_use(XMQDoc *doc, XMQNode *field, DriverDynamic *dd)
{
string name = xmqGetString(doc, field, ".");
string name = xmqGetStringRel(doc, ".", field);
bool ok = dd->addOptionalLibraryFields(name);
if (!ok)
{
@ -248,37 +258,55 @@ XMQProceed DriverDynamic::add_use(XMQDoc *doc, XMQNode *field, DriverDynamic *dd
XMQProceed DriverDynamic::add_field(XMQDoc *doc, XMQNode *field, DriverDynamic *dd)
{
// The field name must be supplied without a unit ie total (not total_m3) since units are managed by wmbusmeters.
string name = check_field_name(xmqGetString(doc, field, "name"), dd);
string name = check_field_name(xmqGetStringRel(doc, "name", field), dd);
// The quantity ie Volume, gives the default unit (m3) for the field. The unit can be overriden with display_unit.
Quantity quantity = check_field_quantity(xmqGetString(doc, field, "quantity"), dd);
Quantity quantity = check_field_quantity(xmqGetStringRel(doc, "quantity", field), dd);
// Text fields are either version strings or lookups from status bits.
// All other fields are numeric, ie they have a unit. This also includes date and datetime.
bool is_numeric = quantity != Quantity::Text;
// The vif scaling is by default Auto but can be overriden for pesky fields.
VifScaling vif_scaling = check_vif_scaling(xmqGetString(doc, field, "vif_scaling"), dd);
VifScaling vif_scaling = check_vif_scaling(xmqGetStringRel(doc, "vif_scaling", field), dd);
// The dif signedness is by default Signed but can be overriden for pesky fields.
DifSignedness dif_signedness = check_dif_signedness(xmqGetStringRel(doc, "dif_signedness", field), dd);
// The properties are by default empty but can be specified for specific fields.
PrintProperties properties = check_print_properties(xmqGetString(doc, field, "attributes"), dd);
PrintProperties properties = check_print_properties(xmqGetStringRel(doc, "attributes", field), dd);
// The about fields explains what the value is for. Ie. is storage 1 the previous day or month value etc.
string info = get_translation(doc, field, "about", language());
// The calculate formula is optional.
string calculate = check_calculate(xmqGetString(doc, field, "calculate"), dd);
string calculate = check_calculate(xmqGetStringRel(doc, "calculate", field), dd);
// The display unit is usually based on the quantity. But you can override it.
Unit display_unit = check_display_unit(xmqGetString(doc, field, "display_unit"), dd);
Unit display_unit = check_display_unit(xmqGetStringRel(doc, "display_unit", field), dd);
// Now find all matchers.
FieldMatcher match = FieldMatcher::build();
dd->tmp_matcher_ = &match;
int num_matches = xmqForeach(doc, field, "match", (XMQNodeCallback)add_match, dd);
int num_matches = xmqForeachRel(doc, "match", (XMQNodeCallback)add_match, dd, field);
// Check if there were any matches at all, if not, then disable the matcher.
match.active = num_matches > 0;
// Now find all matchers.
Translate::Lookup lookup = Translate::Lookup();
/*
.add(Translate::Rule("ERROR_FLAGS", Translate::Type::BitToString)
.set(MaskBits(0x000f))
.set(DefaultMessage("OK"))
.add(Translate::Map(0x01 ,"DRY", TestBit::Set))
.add(Translate::Map(0x02 ,"REVERSE", TestBit::Set))
.add(Translate::Map(0x04 ,"LEAK", TestBit::Set))
.add(Translate::Map(0x08 ,"BURST", TestBit::Set))
));
*/
dd->tmp_lookup_ = &lookup;
int num_lookups = xmqForeachRel(doc, "lookup", (XMQNodeCallback)add_lookup, dd, field);
if (is_numeric)
{
if (calculate == "")
@ -289,6 +317,7 @@ XMQProceed DriverDynamic::add_field(XMQDoc *doc, XMQNode *field, DriverDynamic *
properties,
quantity,
vif_scaling,
dif_signedness,
match,
display_unit
);
@ -322,12 +351,25 @@ XMQProceed DriverDynamic::add_field(XMQDoc *doc, XMQNode *field, DriverDynamic *
}
else
{
dd->addStringFieldWithExtractor(
name,
info,
properties,
match
);
if (num_lookups > 0)
{
dd->addStringFieldWithExtractorAndLookup(
name,
info,
properties,
match,
lookup
);
}
else
{
dd->addStringFieldWithExtractor(
name,
info,
properties,
match
);
}
}
return XMQ_CONTINUE;
}
@ -336,13 +378,17 @@ XMQProceed DriverDynamic::add_match(XMQDoc *doc, XMQNode *match, DriverDynamic *
{
FieldMatcher *fm = dd->tmp_matcher_;
checked_set_measurement_type(xmqGetString(doc, match, "measurement_type"), fm, dd);
if (checked_set_difvifkey(xmqGetStringRel(doc, "difvifkey", match), fm, dd)) return XMQ_CONTINUE;
checked_set_vif_range(xmqGetString(doc, match, "vif_range"), fm, dd);
checked_set_measurement_type(xmqGetStringRel(doc, "measurement_type", match), fm, dd);
checked_set_storagenr_range(xmqGetString(doc, match, "storage_nr"), fm, dd);
checked_set_vif_range(xmqGetStringRel(doc, "vif_range", match), fm, dd);
xmqForeach(doc, match, "add_combinable", (XMQNodeCallback)add_combinable, dd);
checked_set_storagenr_range(xmqGetStringRel(doc, "storage_nr", match), fm, dd);
checked_set_tariffnr_range(xmqGetStringRel(doc, "tariff_nr", match), fm, dd);
checked_set_subunitnr_range(xmqGetStringRel(doc, "subunit_nr", match), fm, dd);
xmqForeachRel(doc, "add_combinable", (XMQNodeCallback)add_combinable, dd, match);
return XMQ_CONTINUE;
}
@ -351,7 +397,62 @@ XMQProceed DriverDynamic::add_combinable(XMQDoc *doc, XMQNode *match, DriverDyna
{
FieldMatcher *fm = dd->tmp_matcher_;
checked_add_vif_combinable(xmqGetString(doc, match, "."), fm, dd);
checked_add_vif_combinable(xmqGetStringRel(doc, ".", match), fm, dd);
return XMQ_CONTINUE;
}
/**
add_map:
Add a mapping from a value (bits,index,decimal) to a string name.
map {
name = SURGE
info = 'Unexpected increase in pressure in relation to average pressure.'
value = 0x02
test = set
}
*/
XMQProceed DriverDynamic::add_map(XMQDoc *doc, XMQNode *map, DriverDynamic *dd)
{
const char *name = xmqGetStringRel(doc, "name", map);
uint64_t value = checked_value(xmqGetStringRel(doc, "value", map), dd);
TestBit test_type = checked_test_type(xmqGetStringRel(doc, "test", map), dd);
dd->tmp_rule_->add(Translate::Map(value, name, test_type));
return XMQ_CONTINUE;
}
/**
add_lookup:
Add a lookup from bits,index or decimal to a sequence of string tokens.
Or fallback to the name (ERROR_FLAGS_8) suffixed by the untranslateable bits.
lookup {
name = ERROR_FLAGS
map_type = BitToString
mask_bits = 0xffff
default_message = OK
map { } map {}
}
*/
XMQProceed DriverDynamic::add_lookup(XMQDoc *doc, XMQNode *lookup, DriverDynamic *dd)
{
const char *name = xmqGetStringRel(doc, "name", lookup);
Translate::MapType map_type = checked_map_type(xmqGetStringRel(doc, "map_type", lookup), dd);
uint64_t mask_bits = checked_mask_bits(xmqGetStringRel(doc, "mask_bits", lookup), dd);
const char *default_message = xmqGetStringRel(doc, "default_message", lookup);
Translate::Rule rule = Translate::Rule(name, map_type);
dd->tmp_rule_ = &rule;
rule.set(MaskBits(mask_bits));
rule.set(DefaultMessage(default_message));
xmqForeachRel(doc, "map", (XMQNodeCallback)add_map, dd, lookup);
dd->tmp_lookup_->add(rule);
return XMQ_CONTINUE;
}
@ -541,12 +642,12 @@ VifScaling check_vif_scaling(const char *vif_scaling_s, DriverDynamic *dd)
warning("(driver) error in %s, bad vif scaling: %s\n",
"%s\n"
"Available vif scalings:\n"
"%s\n"
"Auto\n"
"None\n"
"%s\n",
dd->fileName().c_str(),
vif_scaling_s,
line,
"???",
line);
throw 1;
}
@ -554,6 +655,33 @@ VifScaling check_vif_scaling(const char *vif_scaling_s, DriverDynamic *dd)
return vif_scaling;
}
DifSignedness check_dif_signedness(const char *dif_signedness_s, DriverDynamic *dd)
{
if (!dif_signedness_s)
{
return DifSignedness::Signed;
}
DifSignedness dif_signedness = toDifSignedness(dif_signedness_s);
if (dif_signedness == DifSignedness::Unknown)
{
warning("(driver) error in %s, bad dif signedness: %s\n",
"%s\n"
"Available dif signedness:\n"
"Signed\n"
"Unsigned\n"
"%s\n",
dd->fileName().c_str(),
dif_signedness_s,
line,
line);
throw 1;
}
return dif_signedness;
}
PrintProperties check_print_properties(const char *print_properties_s, DriverDynamic *dd)
{
if (!print_properties_s)
@ -576,11 +704,11 @@ PrintProperties check_print_properties(const char *print_properties_s, DriverDyn
string get_translation(XMQDoc *doc, XMQNode *node, string name, string lang)
{
string xpath = name+"/"+lang;
const char *txt = xmqGetString(doc, node, xpath.c_str());
const char *txt = xmqGetStringRel(doc, xpath.c_str(), node);
if (!txt)
{
xpath = name+"/en";
txt = xmqGetString(doc, node, xpath.c_str());
txt = xmqGetStringRel(doc, xpath.c_str(), node);
if (!txt)
{
txt = "";
@ -619,6 +747,31 @@ Unit check_display_unit(const char *display_unit_s, DriverDynamic *dd)
return u;
}
bool checked_set_difvifkey(const char *difvifkey_s, FieldMatcher *fm, DriverDynamic *dd)
{
if (!difvifkey_s) return false;
bool invalid_hex = false;
bool hex = isHexStringStrict(difvifkey_s, &invalid_hex);
if (!hex || invalid_hex)
{
warning("(driver) error in %s, bad divfikey: %s\n"
"%s\n"
"Should be all hex.\n"
"%s\n",
dd->fileName().c_str(),
difvifkey_s,
line,
line);
throw 1;
}
fm->set(DifVifKey(difvifkey_s));
return true;
}
void checked_set_measurement_type(const char *measurement_type_s, FieldMatcher *fm, DriverDynamic *dd)
{
if (!measurement_type_s)
@ -730,6 +883,69 @@ void checked_set_storagenr_range(const char *storagenr_range_s, FieldMatcher *fm
}
}
void checked_set_tariffnr_range(const char *tariffnr_range_s, FieldMatcher *fm, DriverDynamic *dd)
{
if (!tariffnr_range_s) return;
auto fields = splitString(tariffnr_range_s, ',');
bool ok = isNumber(fields[0]);
if (fields.size() > 1)
{
ok &= isNumber(fields[1]);
}
if (!ok || fields.size() > 2)
{
warning("(driver) error in %s, bad tariffnr_range: %s\n"
"%s\n",
dd->fileName().c_str(),
tariffnr_range_s,
line);
throw 1;
}
if (fields.size() == 1)
{
fm->set(TariffNr(atoi(fields[0].c_str())));
}
else
{
fm->set(TariffNr(atoi(fields[0].c_str())),
TariffNr(atoi(fields[1].c_str())));
}
}
void checked_set_subunitnr_range(const char *subunitnr_range_s, FieldMatcher *fm, DriverDynamic *dd)
{
if (!subunitnr_range_s) return;
auto fields = splitString(subunitnr_range_s, ',');
bool ok = isNumber(fields[0]);
if (fields.size() > 1)
{
ok &= isNumber(fields[1]);
}
if (!ok || fields.size() > 2)
{
warning("(driver) error in %s, bad subunitnr_range: %s\n"
"%s\n",
dd->fileName().c_str(),
subunitnr_range_s,
line);
throw 1;
}
if (fields.size() == 1)
{
fm->set(SubUnitNr(atoi(fields[0].c_str())));
}
else
{
fm->set(SubUnitNr(atoi(fields[0].c_str())),
SubUnitNr(atoi(fields[1].c_str())));
}
}
void checked_add_vif_combinable(const char *vif_combinable_s, FieldMatcher *fm, DriverDynamic *dd)
{
if (!vif_combinable_s) return;
@ -753,3 +969,118 @@ void checked_add_vif_combinable(const char *vif_combinable_s, FieldMatcher *fm,
fm->add(vif_combinable);
}
Translate::MapType checked_map_type(const char *map_type_s, DriverDynamic *dd)
{
if (!map_type_s)
{
warning("(driver) error in %s, cannot find: driver/field/lookup/map_type\n"
"%s\n"
"Remember to add for example: lookup { map_type = BitToString ... }\n"
"Available map types:\n"
"BitToString\n"
"IndexToString\n"
"DecimalsToString\n"
"%s\n",
dd->fileName().c_str(),
line,
line);
throw 1;
}
Translate::MapType map_type = toMapType(map_type_s);
if (map_type == Translate::MapType::Unknown)
{
warning("(driver) error in %s, bad map_type: %s\n"
"%s\n"
"Available map types:\n"
"BitToString\n"
"IndexToString\n"
"DecimalToString\n"
"%s\n",
dd->fileName().c_str(),
map_type_s,
line,
line);
throw 1;
}
return map_type;
}
uint64_t checked_mask_bits(const char *mask_bits_s, DriverDynamic *dd)
{
if (!mask_bits_s)
{
warning("(driver) error in %s, cannot find: driver/field/lookup/mask_bitse\n"
"%s\n"
"Remember to add for example: lookup { mask_bits = 0x00ff ... }\n"
"%s\n",
dd->fileName().c_str(),
line,
line);
throw 1;
}
uint64_t mask = strtol(mask_bits_s, NULL, 16);
return mask;
}
uint64_t checked_value(const char *value_s, DriverDynamic *dd)
{
if (!value_s)
{
warning("(driver) error in %s, cannot find: driver/field/lookup/map/value\n"
"%s\n"
"Remember to add for example: lookup { map { ... value = 0x01 ... }}\n"
"%s\n",
dd->fileName().c_str(),
line,
line);
throw 1;
}
uint64_t value = strtol(value_s, NULL, 16);
return value;
}
TestBit checked_test_type(const char *test_s, DriverDynamic *dd)
{
if (!test_s)
{
warning("(driver) error in %s, cannot find: driver/field/lookup/map/test\n"
"%s\n"
"Remember to add for example: lookup { map { test = Set } }\n"
"Available test types:\n"
"Set\n"
"NotSet\n"
"%s\n",
dd->fileName().c_str(),
line,
line);
throw 1;
}
TestBit test_type = toTestBit(test_s);
if (test_type == TestBit::Unknown)
{
warning("(driver) error in %s, bad test: %s\n"
"%s\n"
"Available test types:\n"
"Set\n"
"NotSet\n"
"%s\n",
dd->fileName().c_str(),
test_s,
line,
line);
throw 1;
}
return test_type;
}

Wyświetl plik

@ -1,5 +1,5 @@
/*
Copyright (C) 2023 Fredrik Öhrström (gpl-3.0-or-later)
Copyright (C) 2023-2024 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
@ -31,12 +31,17 @@ struct DriverDynamic : public virtual MeterCommonImplementation
static XMQProceed add_match(XMQDoc *doc, XMQNode *match, DriverDynamic *dd);
static XMQProceed add_combinable(XMQDoc *doc, XMQNode *match, DriverDynamic *dd);
static XMQProceed add_lookup(XMQDoc *doc, XMQNode *lookup, DriverDynamic *dd);
static XMQProceed add_map(XMQDoc *doc, XMQNode *map, DriverDynamic *dd);
const string &fileName() { return file_name_; }
private:
string file_name_;
FieldMatcher *tmp_matcher_;
Translate::Lookup *tmp_lookup_;
Translate::Rule *tmp_rule_;
};
#endif

Wyświetl plik

@ -41,7 +41,7 @@ namespace
"The total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -52,7 +52,7 @@ namespace
"Current power consumption at phase 1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04A9FF01"))
);
@ -62,7 +62,7 @@ namespace
"Current power consumption at phase 2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04A9FF02"))
);
@ -72,7 +72,7 @@ namespace
"Current power consumption at phase 3.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04A9FF03"))
);
@ -92,7 +92,7 @@ namespace
"Calculated sum of power consumption of all phases.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)

Wyświetl plik

@ -47,7 +47,7 @@ namespace
"The total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -58,7 +58,7 @@ namespace
"Current power consumption.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -69,7 +69,7 @@ namespace
"The total energy production recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)

Wyświetl plik

@ -38,7 +38,7 @@ namespace
{
setMfctTPLStatusBits(
Translate::Lookup()
.add(Translate::Rule("TPL_STS", Translate::Type::BitToString)
.add(Translate::Rule("TPL_STS", Translate::MapType::BitToString)
.set(MaskBits(0xe0))
.set(DefaultMessage("OK"))
.add(Translate::Map(0x04 ,"RTC_INVALID", TestBit::Set))));
@ -54,7 +54,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
@ -90,7 +90,7 @@ namespace
"Number of times the smoke alarm has triggered.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(SubUnitNr(1))
@ -121,7 +121,7 @@ namespace
"Time the smoke alarm has been removed.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Time,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(SubUnitNr(1))
@ -145,7 +145,7 @@ namespace
"Number of times the smoke alarm has been removed.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(SubUnitNr(1))
@ -169,7 +169,7 @@ namespace
"Number of times the test button has been pressed.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(SubUnitNr(1))
@ -208,7 +208,7 @@ namespace
{
{
"DUST",
Translate::Type::IndexToString,
Translate::MapType::IndexToString,
AlwaysTrigger, MaskBits(0x1f),
"",
{
@ -228,7 +228,7 @@ namespace
{
{
"BATTERY_VOLTAGE",
Translate::Type::IndexToString,
Translate::MapType::IndexToString,
AlwaysTrigger, MaskBits(0x0f00),
"",
{
@ -267,7 +267,7 @@ namespace
{
{
"OBSTACLE_DISTANCE",
Translate::Type::IndexToString,
Translate::MapType::IndexToString,
AlwaysTrigger, MaskBits(0x700000),
"",
{
@ -297,7 +297,7 @@ namespace
{
{
"HEAD_STATUS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xff8ff0e0),
"OK",
{

Wyświetl plik

@ -45,7 +45,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffffffff),
"OK",
{
@ -69,7 +69,7 @@ namespace
"The total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -80,7 +80,7 @@ namespace
"Current power consumption.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::PowerW)
@ -91,7 +91,7 @@ namespace
"Total volume of heat media.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -102,7 +102,7 @@ namespace
"The total energy consumption recorded at the target date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -114,7 +114,7 @@ namespace
"The flow temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::FlowTemperature)
@ -125,7 +125,7 @@ namespace
"The return temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ReturnTemperature)
@ -136,7 +136,7 @@ namespace
"The external temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ExternalTemperature)
@ -147,7 +147,7 @@ namespace
"How long the meter has been collecting data.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Time,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::OperatingTime)
@ -167,7 +167,7 @@ namespace
"Battery voltage.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)

Wyświetl plik

@ -53,7 +53,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xff),
"OK",
{
@ -80,7 +80,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xff),
"",
{
@ -101,7 +101,7 @@ namespace
"The total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -112,7 +112,7 @@ namespace
"Power measured by this meter at the moment.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -123,7 +123,7 @@ namespace
"The total energy backward (production) recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -135,7 +135,7 @@ namespace
"The reactive total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Reactive_Energy,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FB8275"))
);
@ -145,7 +145,7 @@ namespace
"The total reactive energy backward (production) recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Reactive_Energy,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(DifVifKey("04FB82F53C"))
@ -177,7 +177,7 @@ namespace
"Amperage at phase L1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FDD9FC01"))
);
@ -187,7 +187,7 @@ namespace
"Amperage at phase L2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FDD9FC02"))
);
@ -197,7 +197,7 @@ namespace
"Amperage at phase L3.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FDD9FC03"))
);
@ -207,7 +207,7 @@ namespace
"Voltage at phase L1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FDC8FC01"))
);
@ -217,7 +217,7 @@ namespace
"Voltage at phase L2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FDC8FC02"))
);
@ -227,7 +227,7 @@ namespace
"Voltage at phase L3.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FDC8FC03"))
);
@ -237,7 +237,7 @@ namespace
"Frequency in 0.1 Hz",
DEFAULT_PRINT_PROPERTIES | PrintProperty::HIDE,
Quantity::Frequency,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("02FB2E"))
);

Wyświetl plik

@ -42,7 +42,7 @@ namespace
"The total water consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -53,7 +53,7 @@ namespace
"The target water consumption recorded at previous period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)

Wyświetl plik

@ -45,7 +45,7 @@ namespace
"The total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -56,7 +56,7 @@ namespace
"The energy consumption recorded by this meter at the set date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -68,7 +68,7 @@ namespace
"The active power consumption.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -79,7 +79,7 @@ namespace
"The flow of water.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow)
@ -90,7 +90,7 @@ namespace
"The maximum forward flow of water since the last set date?",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::VolumeFlow)
@ -101,7 +101,7 @@ namespace
"The forward temperature of the water.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::FlowTemperature)
@ -112,7 +112,7 @@ namespace
"The return temperature of the water.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ReturnTemperature)
@ -123,7 +123,7 @@ namespace
"The temperature difference forward-return for the water.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::TemperatureDifference)
@ -134,7 +134,7 @@ namespace
"The total amount of water that has passed through this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -145,7 +145,7 @@ namespace
"The amount of water that had passed through this meter at the set date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -157,7 +157,7 @@ namespace
"The amount of water that has passed through subunit 1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -169,7 +169,7 @@ namespace
"The amount of water that had passed through the subunit 1 at the set date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -182,7 +182,7 @@ namespace
"The current heat cost allocation for subunit 1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -194,7 +194,7 @@ namespace
"The heat cost allocation for subunit 1 at the target date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -207,7 +207,7 @@ namespace
"The current heat cost allocation for subunit 2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -219,7 +219,7 @@ namespace
"The heat cost allocation for subunit 2 at the target date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)

Wyświetl plik

@ -46,7 +46,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xff),
"OK",
{
@ -78,7 +78,7 @@ namespace
"The water consumption at the last billing period date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -95,7 +95,7 @@ namespace
info,
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)

Wyświetl plik

@ -53,7 +53,7 @@ namespace
"The total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -64,7 +64,7 @@ namespace
"Calculated sum of power consumption of all phases.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -75,7 +75,7 @@ namespace
"The total energy production recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -87,7 +87,7 @@ namespace
"The total energy consumption recorded by this meter on tariff 1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -99,7 +99,7 @@ namespace
"The total energy consumption recorded by this meter on tariff 2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -111,7 +111,7 @@ namespace
"Current power consumption phase 1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04A9FF01"))
);
@ -121,7 +121,7 @@ namespace
"Current power consumption phase 2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04A9FF02"))
);
@ -131,7 +131,7 @@ namespace
"Current power consumption phase 3.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04A9FF03"))
);

Wyświetl plik

@ -50,7 +50,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
@ -78,7 +78,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
@ -98,7 +98,7 @@ namespace
"The current heat cost allocation.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -109,7 +109,7 @@ namespace
"The heat cost allocation at set date #.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -121,7 +121,7 @@ namespace
"Deprecated field.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)

Wyświetl plik

@ -42,7 +42,7 @@ namespace
"The total water consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -53,7 +53,7 @@ namespace
"The target water consumption recorded at previous period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)

Wyświetl plik

@ -49,7 +49,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
@ -67,7 +67,7 @@ namespace
"The total water consumption at the most recent billing period date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -89,7 +89,7 @@ namespace
"The total water consumption at the second most recent billing period date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -111,7 +111,7 @@ namespace
"Maximum water flow since date time.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::VolumeFlow)
@ -133,7 +133,7 @@ namespace
"The total water consumption at the historic date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -145,7 +145,7 @@ namespace
"Reference date for history.",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Date)

Wyświetl plik

@ -50,7 +50,7 @@ namespace
"The current heat cost allocation.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
);
@ -69,7 +69,7 @@ namespace
"Heat cost allocation at the most recent billing period date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(StorageNr(1))
@ -89,7 +89,7 @@ namespace
"Heat cost allocation at the most recent billing period date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(StorageNr(1))
@ -109,7 +109,7 @@ namespace
"Heat cost allocation at the 8 billing period date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(StorageNr(8))

Wyświetl plik

@ -51,7 +51,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffffffff),
"OK",
{
@ -71,7 +71,7 @@ namespace
"The total water consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -82,7 +82,7 @@ namespace
"The total water consumption recorded at the beginning of this month.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -104,7 +104,7 @@ namespace
"The current flow of water through the meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow)
@ -115,7 +115,7 @@ namespace
"The water temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Minimum)
.set(VIFRange::FlowTemperature)
@ -127,7 +127,7 @@ namespace
"The maximum water temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::FlowTemperature)
@ -139,7 +139,7 @@ namespace
"The external temperature outside of the meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Minimum)
.set(VIFRange::ExternalTemperature)
@ -151,7 +151,7 @@ namespace
"The maximum flow recorded during previous period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::VolumeFlow)
@ -163,7 +163,7 @@ namespace
"The minimum flow recorded during previous period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Minimum)
.set(VIFRange::VolumeFlow)
@ -175,7 +175,7 @@ namespace
"The maximum temperature recorded during previous period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::ExternalTemperature)
@ -187,7 +187,7 @@ namespace
"The minimum flow recorded during previous period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Minimum)
.set(VIFRange::ExternalTemperature)
@ -199,7 +199,7 @@ namespace
"The maximum flow recorded during previous period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::VolumeFlow)
@ -216,7 +216,7 @@ namespace
{
{
"DRY",
Translate::Type::IndexToString,
Translate::MapType::IndexToString,
AlwaysTrigger, MaskBits(0x0070),
"",
{
@ -243,7 +243,7 @@ namespace
{
{
"REVERSED",
Translate::Type::IndexToString,
Translate::MapType::IndexToString,
AlwaysTrigger, MaskBits(0x0380),
"",
{
@ -270,7 +270,7 @@ namespace
{
{
"LEAKING",
Translate::Type::IndexToString,
Translate::MapType::IndexToString,
AlwaysTrigger, MaskBits(0x1c00),
"",
{
@ -297,7 +297,7 @@ namespace
{
{
"BURSTING",
Translate::Type::IndexToString,
Translate::MapType::IndexToString,
AlwaysTrigger, MaskBits(0xe000),
"",
{

Wyświetl plik

@ -70,7 +70,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger,
AutoMask,
"OK",
@ -85,7 +85,7 @@ namespace
},
{
"ERROR_FLAGS_SINGLE_PHASE",
Translate::Type::BitToString,
Translate::MapType::BitToString,
TriggerBits(0x01020000),
AutoMask,
"OK",
@ -99,7 +99,7 @@ namespace
},
{
"ERROR_FLAGS_THREE_PHASE",
Translate::Type::BitToString,
Translate::MapType::BitToString,
TriggerBits(0x01010000),
AutoMask,
"OK",
@ -124,7 +124,7 @@ namespace
{
{
"INFO_FLAGS",
Translate::Type::IndexToString,
Translate::MapType::IndexToString,
AlwaysTrigger,
AutoMask,
"",
@ -141,7 +141,7 @@ namespace
"The total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -152,7 +152,7 @@ namespace
"The total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -164,7 +164,7 @@ namespace
"Last day?",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::DateTime)
@ -176,7 +176,7 @@ namespace
"Last day energy consumption?",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -188,7 +188,7 @@ namespace
"Last day energy consumption for tariff?",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -201,7 +201,7 @@ namespace
"Device date time when telegram was sent.",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::DateTime)
@ -212,7 +212,7 @@ namespace
"Voltage for single phase meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
@ -224,7 +224,7 @@ namespace
"Voltage at phase L#.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
@ -236,7 +236,7 @@ namespace
"Amperage for single phase meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Amperage)
@ -248,7 +248,7 @@ namespace
"Amperage at phase L#.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Amperage)
@ -260,7 +260,7 @@ namespace
"Raw input to frequency.",
DEFAULT_PRINT_PROPERTIES | PrintProperty::HIDE,
Quantity::Frequency,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("02FB2D"))
);

Wyświetl plik

@ -100,5 +100,5 @@ namespace
// Test: Wateroo gwfwater 20221031 NOKEY
// telegram=|3144E61E31102220010E8C04F47ABE0420452F2F_037410000004133E0000004413FFFFFFFF426CFFFF0F0120012F2F2F2F2F|
// {"actuality_duration_s": 16,"battery_y": 0,"id": "20221031","media": "bus/system component","meter": "gwfwater","name": "Wateroo","power_mode": "SAVING","status": "BATTERY_LOW POWER_LOW","target_date": "2128-03-31","target_m3": 4294967.295,"timestamp": "1111-11-11T11:11:11Z","total_m3": 0.062}
// {"actuality_duration_s": 16,"battery_y": 0,"id": "20221031","media": "bus/system component","meter": "gwfwater","name": "Wateroo","power_mode": "SAVING","status": "BATTERY_LOW POWER_LOW","target_date": "2128-03-31","target_m3": -0.001,"timestamp": "1111-11-11T11:11:11Z","total_m3": 0.062}
// |Wateroo;20221031;0.062;1111-11-11 11:11.11

Wyświetl plik

@ -49,7 +49,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
@ -69,7 +69,7 @@ namespace
"The current heat cost allocation.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -80,7 +80,7 @@ namespace
"The heat cost allocation at set date #.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -92,7 +92,7 @@ namespace
"Deprecated field.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)

Wyświetl plik

@ -39,7 +39,7 @@ namespace
{
setMfctTPLStatusBits(
Translate::Lookup()
.add(Translate::Rule("TPL_STS", Translate::Type::BitToString)
.add(Translate::Rule("TPL_STS", Translate::MapType::BitToString)
.set(MaskBits(0xe0))
.set(DefaultMessage("OK"))
.add(Translate::Map(0x80 ,"SABOTAGE_ENCLOSURE", TestBit::Set))));
@ -55,7 +55,7 @@ namespace
"The total heating energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -67,7 +67,7 @@ namespace
"The date time when the recording was made.",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::DateTime)
@ -78,7 +78,7 @@ namespace
"The total cooling energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -90,7 +90,7 @@ namespace
"Total heating volume of media.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -102,7 +102,7 @@ namespace
"Total cooling volume of media.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -114,7 +114,7 @@ namespace
"Supply c1 volume.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -126,7 +126,7 @@ namespace
"Return c2 volume.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -138,7 +138,7 @@ namespace
"The supply t1 pipe temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::FlowTemperature)
@ -150,7 +150,7 @@ namespace
"The return t2 pipe temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ReturnTemperature)

Wyświetl plik

@ -45,7 +45,7 @@ namespace
"The current heat cost allocation.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)

Wyświetl plik

@ -44,7 +44,7 @@ namespace
"The total water consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -55,7 +55,7 @@ namespace
"Meter timestamp for measurement.",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::DateTime),

Wyświetl plik

@ -57,7 +57,7 @@ namespace
"The total water consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -68,7 +68,7 @@ namespace
"The total water consumption recorded on tariff # by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -80,7 +80,7 @@ namespace
"The total water consumption recorded on tariff # by this meter at billing date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -93,7 +93,7 @@ namespace
"The current water flow.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow));
@ -103,7 +103,7 @@ namespace
"The total water consumption recorded at date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -115,7 +115,7 @@ namespace
"The last billing period date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Date)
@ -128,7 +128,7 @@ namespace
"The total water consumption recorded at the end of last month.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -140,7 +140,7 @@ namespace
"The end of last month.",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::DateTime)
@ -152,7 +152,7 @@ namespace
"Remaining battery life in years.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Time,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::RemainingBattery),

Plik diff jest za duży Load Diff

Wyświetl plik

@ -60,7 +60,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffffff),
"OK",
{
@ -75,7 +75,7 @@ namespace
"The total water consumption recorded at the end of previous billing period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -102,7 +102,7 @@ namespace
{
{
"WOOTA",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffffffff),
"",
{
@ -122,7 +122,7 @@ namespace
{
{
"WOOTB",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"",
{
@ -156,4 +156,3 @@ namespace
// telegram=|3A4497269820362300167AF60020A52F2F_04132E100000066D03260DE12B007413FEFEFEFE426C1F01047F1600060C027F9A2A0E79187103002300|
// {"enhanced_id": "002300037118", "id": "23362098", "media": "cold water", "meter": "itron", "meter_datetime": "2023-11-01 13:38:03", "name": "ColdWaterMeter", "status": "OK", "target_date": "2000-01-31", "timestamp": "1111-11-11T11:11:11Z", "total_m3": 4.142,"unknown_a": "WOOTA_C060016","unknown_b": "WOOTB_2A9A" }
// |ColdWaterMeter;23362098;4.142;null;1111-11-11 11:11.11

Wyświetl plik

@ -1,5 +1,5 @@
/*
Copyright (C) 2018-2022 Fredrik Öhrström (gpl-3.0-or-later)
Copyright (C) 2018-2024 Fredrik Öhrström (gpl-3.0-or-later)
Copyright (C) 2020 Eric Bus (gpl-3.0-or-later)
Copyright (C) 2022 thecem (gpl-3.0-or-later)
@ -74,7 +74,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffffffff),
"OK",
{
@ -120,7 +120,7 @@ namespace
"The total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -131,7 +131,7 @@ namespace
"The volume of water (3/68/Volume V1).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -142,7 +142,7 @@ namespace
"The actual amount of water that pass through this meter (8/74/Flow V1 actual).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow)
@ -153,7 +153,7 @@ namespace
"The current power flowing.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -164,7 +164,7 @@ namespace
"The maximum power supplied.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::AnyPowerVIF)
@ -175,7 +175,7 @@ namespace
"The forward temperature of the water (6/86/t2 actual 2 decimals).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::FlowTemperature)
@ -186,7 +186,7 @@ namespace
"The return temperature of the water (7/87/t2 actual 2 decimals).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ReturnTemperature)
@ -197,7 +197,7 @@ namespace
"The maximum flow of water that passed through this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::VolumeFlow)
@ -208,7 +208,7 @@ namespace
"The forward energy of the water (4/97/Energy E8).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FF07")),
Unit::M3C);
@ -218,7 +218,7 @@ namespace
"The return energy of the water (5/110/Energy E9).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FF08")),
Unit::M3C);
@ -237,7 +237,7 @@ namespace
"The energy consumption recorded by this meter at the set date (11/60/Heat energy E1/026C).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -249,7 +249,7 @@ namespace
"The amount of water that had passed through this meter at the set date (13/68/Volume V1).",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -271,7 +271,7 @@ namespace
"How long the meter has been collecting data.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Time,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::OperatingTime)
@ -314,11 +314,11 @@ namespace
// Test: My403Cooling multical403 78780102 NOKEY
// telegram=|88442D2C02017878340A8D208D529C132037FC78_040E2D0A000004FF07F8FF000004FF08401801000413C1900500844014000000008480401400000000043BED0000000259BC06025DCD07142DE7FFFFFF84100E0000000084200E0000000004FF2200000000026C9228440E5F0300004413960D0200C4401400000000C480401400000000426C8128|
// {"forward_energy_m3c": 65528,"id": "78780102","max_power_kw": 429496727.1,"media": "cooling load volume at outlet","meter": "kamheat","meter_date": "2020-08-18","name": "My403Cooling","return_energy_m3c": 71744,"status": "OK","t1_temperature_c": 17.24,"t2_temperature_c": 19.97,"target_date": "2020-08-01","target_energy_kwh": 239.722222,"target_volume_m3": 134.55,"timestamp": "1111-11-11T11:11:11Z","total_energy_consumption_kwh": 723.611111,"total_volume_m3": 364.737,"volume_flow_m3h": 0.237}
// {"forward_energy_m3c": 65528,"id": "78780102","max_power_kw": -2.5,"media": "cooling load volume at outlet","meter": "kamheat","meter_date": "2020-08-18","name": "My403Cooling","return_energy_m3c": 71744,"status": "OK","t1_temperature_c": 17.24,"t2_temperature_c": 19.97,"target_date": "2020-08-01","target_energy_kwh": 239.722222,"target_volume_m3": 134.55,"timestamp": "1111-11-11T11:11:11Z","total_energy_consumption_kwh": 723.611111,"total_volume_m3": 364.737,"volume_flow_m3h": 0.237}
// |My403Cooling;78780102;723.611111;364.737;OK;1111-11-11 11:11.11
// telegram=|5B442D2C02017878340A8D2096809C1320EF2B7934147ED7_2D0A0000FAFF000043180100CE9005000000000000000000EE000000BA06CB07E7FFFFFF00000000000000000000000092285F030000960D020000000000000000008128|
// {"forward_energy_m3c": 65530,"id": "78780102","max_power_kw": 429496727.1,"media": "cooling load volume at outlet","meter": "kamheat","meter_date": "2020-08-18","name": "My403Cooling","return_energy_m3c": 71747,"status": "OK","t1_temperature_c": 17.22,"t2_temperature_c": 19.95,"target_date": "2020-08-01","target_energy_kwh": 239.722222,"target_volume_m3": 134.55,"timestamp": "1111-11-11T11:11:11Z","total_energy_consumption_kwh": 723.611111,"total_volume_m3": 364.75,"volume_flow_m3h": 0.238}
// {"forward_energy_m3c": 65530,"id": "78780102","max_power_kw": -2.5,"media": "cooling load volume at outlet","meter": "kamheat","meter_date": "2020-08-18","name": "My403Cooling","return_energy_m3c": 71747,"status": "OK","t1_temperature_c": 17.22,"t2_temperature_c": 19.95,"target_date": "2020-08-01","target_energy_kwh": 239.722222,"target_volume_m3": 134.55,"timestamp": "1111-11-11T11:11:11Z","total_energy_consumption_kwh": 723.611111,"total_volume_m3": 364.75,"volume_flow_m3h": 0.238}
// |My403Cooling;78780102;723.611111;364.75;OK;1111-11-11 11:11.11
// Test: Heato multical602 78152801 NOKEY
@ -354,3 +354,8 @@ namespace
// telegram=|68c9c96808e672323232322d2c35041900000004fB006083000004ff074006010004ff08299400000416984e010084401400000000848040140000000004225043000034221c0000000259c91f025d4f1102617a0e042e30020000142e65030000043c24050000143ce308000004ff2200000000046d2e2B0f3144fB00007d000044ff07Bdf9000044ff08308d00004416B73f0100c4401400000000c480401400000000542ed9020000543ce8090000426c013102ff1a011B0c783032858404ff16e5841e0004ff17c1d5B400a516|
// {"fabrication_no": "84853230", "flow_return_temperature_difference_c": 37.06, "forward_energy_m3c": 67136, "id": "32323232", "max_flow_m3h": 22.75, "max_power_kw": 869, "media": "heat", "meter": "kamheat", "meter_datetime": "2024-01-15 11:46", "name": "Kamstrup_MC603_mbus", "on_time_at_error_h": 28, "on_time_h": 17232, "power_kw": 560, "return_energy_m3c": 37929, "status": "OK", "t1_temperature_c": 81.37, "t2_temperature_c": 44.31, "target_date": "2024-01-01", "target_energy_kwh": 3200000, "target_volume_m3": 81847, "timestamp": "1111-11-11T11:11:11Z", "total_energy_consumption_kwh": 3363200, "total_volume_m3": 85656, "volume_flow_m3h": 13.16}
// |Kamstrup_MC603_mbus;32323232;3363200;85656;OK;1111-11-11 11:11.11
// Test: KMHEAT kamheat 85412440 NOKEY
// telegram=|5e442d2c4024418535047ae10050252f2f04fB091300000004167500000004ff2200000000043ca301000002599c1d025dB00e844014000000008480401400000000042eB9000000026c0534426c013444fB0900000000543c000000002f2f|
// {"id": "85412440","media": "heat","meter": "kamheat","meter_date": "2024-04-05","name": "KMHEAT","power_kw": 185,"status": "OK","t1_temperature_c": 75.8,"t2_temperature_c": 37.6,"target_date": "2024-04-01","target_energy_kwh": 0,"timestamp": "1111-11-11T11:11:11Z","total_energy_consumption_kwh": 5277.777778,"total_volume_m3": 117,"volume_flow_m3h": 4.19}
// |KMHEAT;85412440;5277.777778;117;OK;1111-11-11 11:11.11

Wyświetl plik

@ -1,130 +0,0 @@
/*
Copyright (C) 2022 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"meters_common_implementation.h"
namespace
{
struct Driver : public virtual MeterCommonImplementation
{
Driver(MeterInfo &mi, DriverInfo &di);
};
static bool ok = registerDriver([](DriverInfo&di)
{
di.setName("kampress");
di.setDefaultFields("name,id,status,pressure_bar,max_pressure_bar,min_pressure_bar,timestamp");
di.setMeterType(MeterType::PressureSensor);
di.addLinkMode(LinkMode::C1);
di.addDetection(MANUFACTURER_KAM, 0x18, 0x01);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
});
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
addStringFieldWithExtractorAndLookup(
"status",
"Status and error flags.",
DEFAULT_PRINT_PROPERTIES | INCLUDE_TPL_STATUS,
FieldMatcher::build()
.set(VIFRange::ErrorFlags),
{
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
{ 0x01, "DROP" }, // Unexpected drop in pressure in relation to average pressure.
{ 0x02, "SURGE" }, // Unexpected increase in pressure in relation to average pressure.
{ 0x04, "HIGH" }, // Average pressure has reached configurable limit. Default 15 bar
{ 0x08, "LOW" }, // Average pressure has reached configurable limit. Default 1.5 bar
{ 0x10, "TRANSIENT" }, // Pressure changes quickly over short timeperiods. Average is fluctuating.
{ 0x20, "COMM_ERROR" } // Cannot measure properly or bad internal communication.
}
},
},
});
addNumericFieldWithExtractor(
"pressure",
"The measured pressure.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Pressure,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Pressure)
);
addNumericFieldWithExtractor(
"max_pressure",
"The maximum pressure measured during ?.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Pressure,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::Pressure)
);
addNumericFieldWithExtractor(
"min_pressure",
"The minimum pressure measured during ?.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Pressure,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Minimum)
.set(VIFRange::Pressure)
);
addNumericFieldWithExtractor(
"alfa",
"We do not know what this is.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
FieldMatcher::build()
.set(DifVifKey("05FF09"))
);
addNumericFieldWithExtractor(
"beta",
"We do not know what this is.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
FieldMatcher::build()
.set(DifVifKey("05FF0A"))
);
}
}
// Test: Pressing kampress 77000317 NOKEY
// telegram=|32442D2C1703007701188D280080E39322DB8F78_22696600126967000269660005FF091954A33A05FF0A99BD823A02FD170800|
// {"media":"pressure","meter":"kampress","name":"Pressing","id":"77000317","status":"LOW","pressure_bar":1.02,"max_pressure_bar":1.03,"min_pressure_bar":1.02,"alfa_counter":0.001246,"beta_counter":0.000997,"timestamp":"1111-11-11T11:11:11Z"}
// |Pressing;77000317;LOW;1.02;1.03;1.02;1111-11-11 11:11.11
// telegram=|27442D2C1703007701188D280194E393226EC679DE735657_660067006600962B913A21B9423A0800|
// {"media":"pressure","meter":"kampress","name":"Pressing","id":"77000317","status":"LOW","pressure_bar":1.02,"max_pressure_bar":1.03,"min_pressure_bar":1.02,"alfa_counter":0.001108,"beta_counter":0.000743,"timestamp":"1111-11-11T11:11:11Z"}
// |Pressing;77000317;LOW;1.02;1.03;1.02;1111-11-11 11:11.11
// telegram=|27442D2C1703007701188D289554F295224ED579DE73188A_650066006600E80EA43A6B97A3BA0800|
// {"media":"pressure","meter":"kampress","name":"Pressing","id":"77000317","status":"LOW","pressure_bar":1.02,"max_pressure_bar":1.02,"min_pressure_bar":1.01,"alfa_counter":0.001252,"beta_counter":-0.001248,"timestamp":"1111-11-11T11:11:11Z"}
// |Pressing;77000317;LOW;1.02;1.02;1.01;1111-11-11 11:11.11

Wyświetl plik

@ -44,7 +44,7 @@ namespace
.set(MeasurementType::Instantaneous)
.set(VIFRange::DigitalInput),
Translate::Lookup()
.add(Translate::Rule("INPUT_BITS", Translate::Type::IndexToString)
.add(Translate::Rule("INPUT_BITS", Translate::MapType::IndexToString)
.set(MaskBits(0xffff))
.add(Translate::Map(0x11 ,"CLOSED", TestBit::Set))
.add(Translate::Map(0x55 ,"OPEN", TestBit::Set))
@ -58,7 +58,7 @@ namespace
.set(MeasurementType::Instantaneous)
.set(VIFRange::ErrorFlags),
Translate::Lookup()
.add(Translate::Rule("ERROR_FLAGS", Translate::Type::BitToString)
.add(Translate::Rule("ERROR_FLAGS", Translate::MapType::BitToString)
.set(MaskBits(0xffff))
.set(DefaultMessage("OK"))
));
@ -68,7 +68,7 @@ namespace
"How many times the door/window has been opened or closed.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
@ -79,7 +79,7 @@ namespace
"The current number of counted pulses from counter b.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)

Wyświetl plik

@ -39,7 +39,7 @@ namespace
{
setMfctTPLStatusBits(
Translate::Lookup()
.add(Translate::Rule("TPL_STS", Translate::Type::BitToString)
.add(Translate::Rule("TPL_STS", Translate::MapType::BitToString)
.set(MaskBits(0xe0))
.set(DefaultMessage("OK"))
.add(Translate::Map(0x40 ,"SABOTAGE_ENCLOSURE", TestBit::Set))));
@ -60,7 +60,7 @@ namespace
"The current number of counted pulses from counter a.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("0EFD3A"))
);
@ -70,7 +70,7 @@ namespace
"The current number of counted pulses from counter b.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("8E40FD3A"))
);

Wyświetl plik

@ -40,7 +40,7 @@ namespace
{
setMfctTPLStatusBits(
Translate::Lookup()
.add(Translate::Rule("TPL_STS", Translate::Type::BitToString)
.add(Translate::Rule("TPL_STS", Translate::MapType::BitToString)
.set(MaskBits(0xe0))
.set(DefaultMessage("OK"))
.add(Translate::Map(0x04 ,"LOW_BATTERY", TestBit::Set))));
@ -56,7 +56,7 @@ namespace
"Number of total routed messages since power up",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
@ -67,7 +67,7 @@ namespace
"Used router slots (maximum 936)",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
@ -92,7 +92,7 @@ namespace
.set(VIFRange::Dimensionless)
.set(SubUnitNr(2)),
Translate::Lookup()
.add(Translate::Rule("INPUT_BITS", Translate::Type::IndexToString)
.add(Translate::Rule("INPUT_BITS", Translate::MapType::IndexToString)
.set(MaskBits(0x01))
.add(Translate::Map(0x00, "NO", TestBit::Set))
.add(Translate::Map(0x01, "YES", TestBit::Set))
@ -103,7 +103,7 @@ namespace
"Seconds to mode change (Listen -> Sleep or Sleep -> Listen). Maximum 32767 seconds",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
@ -115,7 +115,7 @@ namespace
"Value on parameter 'Listen timer'",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
@ -127,7 +127,7 @@ namespace
"Value on parameter 'Pause timer'",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
@ -143,7 +143,7 @@ namespace
.set(VIFRange::Dimensionless)
.set(StorageNr(3)),
Translate::Lookup()
.add(Translate::Rule("INPUT_BITS", Translate::Type::BitToString)
.add(Translate::Rule("INPUT_BITS", Translate::MapType::BitToString)
.set(MaskBits(0xffff))
.add(Translate::Map(0x01 ,"SU", TestBit::Set))
.add(Translate::Map(0x02 ,"MO", TestBit::Set))
@ -159,7 +159,7 @@ namespace
"Value on parameter 'Start time', shown as minusted after midnight (-1=Not used)",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
@ -180,7 +180,7 @@ namespace
"Battery voltage.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)

Wyświetl plik

@ -49,7 +49,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
@ -69,7 +69,7 @@ namespace
"Unique asynchronous message number.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AccessNumber)
@ -80,7 +80,7 @@ namespace
"Minutes since last manual test.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)

Wyświetl plik

@ -39,7 +39,7 @@ namespace
addOptionalLibraryFields("on_time_h");
setMfctTPLStatusBits(
Translate::Lookup()
.add(Translate::Rule("TPL_STS", Translate::Type::BitToString)
.add(Translate::Rule("TPL_STS", Translate::MapType::BitToString)
.set(MaskBits(0xe0))
.set(DefaultMessage("OK"))
.add(Translate::Map(0x40 ,"SABOTAGE_ENCLOSURE", TestBit::Set))));
@ -55,7 +55,7 @@ namespace
"The current temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ExternalTemperature)
@ -66,7 +66,7 @@ namespace
"The current humidity.",
DEFAULT_PRINT_PROPERTIES,
Quantity::RelativeHumidity,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::RelativeHumidity)
@ -77,7 +77,7 @@ namespace
"The average temperature over the last hour.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ExternalTemperature)
@ -89,7 +89,7 @@ namespace
"The average humidity over the last hour.",
DEFAULT_PRINT_PROPERTIES,
Quantity::RelativeHumidity,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::RelativeHumidity)
@ -101,7 +101,7 @@ namespace
"The average temperature over the last 24 hours.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ExternalTemperature)
@ -113,7 +113,7 @@ namespace
"The average humidity over the last 24 hours.",
DEFAULT_PRINT_PROPERTIES,
Quantity::RelativeHumidity,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::RelativeHumidity)

Wyświetl plik

@ -1,5 +1,5 @@
/*
Copyright (C) 2021-2022 Fredrik Öhrström (gpl-3.0-or-later)
Copyright (C) 2021-2024 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
@ -34,6 +34,7 @@ namespace
di.addDetection(MANUFACTURER_LSE, 0x07, 0x18);
di.addDetection(MANUFACTURER_LSE, 0x07, 0x16);
di.addDetection(MANUFACTURER_LSE, 0x07, 0x17);
di.addDetection(MANUFACTURER_LSE, 0x07, 0xd8);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
});
@ -44,7 +45,7 @@ namespace
"The total water consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -55,7 +56,7 @@ namespace
"The water consumption at the due date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -77,7 +78,7 @@ namespace
"The water consumption at the what date?",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -105,7 +106,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
@ -207,3 +208,8 @@ namespace
// telegram=|2D4465329933961318067ADA000000_0C13567100004C1300000000426CFFFF02BB560000326CFFFF046D2307A12C|
// {"media":"warm water","meter":"lse_07_17","name":"Water","id":"13963399","total_m3":7.156,"due_date_m3":0,"due_date":"2127-15-31","what_date_m3":7,"what_date":"2021-11-30","error_code":"OK","error_date":"2127-15-31","device_date_time":"2021-12-01 07:35","meter_version":"11","timestamp":"1111-11-11T11:11:11Z"}
// |Water;13963399;7.156;0;2127-15-31;OK;2127-15-31;2021-12-01 07:35;1111-11-11 11:11.11
// Test: Water2 lse_07_17 09993623 NOKEY
// telegram=|2d44653223369909d8077a80000000046d130aed2B0c13233332004c1351762700426cdf2c326cffff02BB560000|
// {"device_date_time": "2023-11-13 10:19","due_date": "2022-12-31","due_date_m3": 277.651,"error_code": "OK","error_date": "2127-15-31","id": "09993623","media": "water","meter": "lse_07_17","name": "Water2","timestamp": "1111-11-11T11:11:11Z","total_m3": 323.323}
// |Water2;09993623;323.323;277.651;2022-12-31;OK;2127-15-31;2023-11-13 10:19;1111-11-11 11:11.11

Wyświetl plik

@ -51,7 +51,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xff),
"OK",
{
@ -66,7 +66,7 @@ namespace
"The current heat cost allocation.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -87,7 +87,7 @@ namespace
"Heat cost allocation at the most recent billing period date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -108,7 +108,7 @@ namespace
"Duration since last measurement.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Time,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::DurationSinceReadout)

Wyświetl plik

@ -52,7 +52,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
@ -66,7 +66,7 @@ namespace
"The total heat energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -77,7 +77,7 @@ namespace
"The total heating media volume recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -88,7 +88,7 @@ namespace
"The current heat media volume flow.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow)
@ -99,7 +99,7 @@ namespace
"The current power consumption.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::PowerW)
@ -110,7 +110,7 @@ namespace
"The difference between flow and return media temperatures.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::TemperatureDifference)
@ -121,7 +121,7 @@ namespace
"The most recent billing period date.",
DEFAULT_PRINT_PROPERTIES | PrintProperty::HIDE,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Date)
@ -134,7 +134,7 @@ namespace
"The total water consumption at the historic date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)

Wyświetl plik

@ -51,7 +51,7 @@ namespace
"The total water consumption recorded at the beginning of this month.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -74,7 +74,7 @@ namespace
"The total water consumption recorded at the beginning of this month.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -130,7 +130,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
@ -212,8 +212,8 @@ namespace
// Test: Minowired minomess 57575757 NOKEY
// telegram=|6874746808007257575757496A000712000000_0C7857575757046D2414DE280413000000000C943C000000004413FFFFFFFF426CFFFF840113FFFFFFFF82016CFFFFC40113FFFFFFFFC2016CFFFF840213FFFFFFFF82026CFFFF043B000000000422E62F000004260000000034220000000002FD1700001F5716|
// {"media":"water","meter":"minomess","name":"Minowired","id":"57575757","fabrication_no":"57575757","operating_time_h":0,"on_time_h":12262,"on_time_at_error_h":0,"meter_datetime":"2022-08-30 20:36","total_m3":0,"total_backward_m3":0,"volume_flow_m3h":0,"target_m3":4294967.295,"target_date":"2127-15-31","status":"OK","timestamp":"1111-11-11T11:11:11Z"}
// |Minowired;57575757;0;4294967.295;OK;1111-11-11 11:11.11
// {"media":"water","meter":"minomess","name":"Minowired","id":"57575757","fabrication_no":"57575757","operating_time_h":0,"on_time_h":12262,"on_time_at_error_h":0,"meter_datetime":"2022-08-30 20:36","total_m3":0,"total_backward_m3":0,"volume_flow_m3h":0,"target_m3":-0.001,"target_date":"2127-15-31","status":"OK","timestamp":"1111-11-11T11:11:11Z"}
// |Minowired;57575757;0;-0.001;OK;1111-11-11 11:11.11
// Test: Zenner_cold minomess 21314151 NOKEY
// telegram=|6644496A4425155518377251413121496A0116360050052F2F_0C1355000000026CEC2182046CE1218C0413000000808D0493132C33FE00008000008000008000008000008000008000008000008000008000008000008000008000008000008002FD1700002F2F|

Wyświetl plik

@ -46,7 +46,7 @@ namespace
"The total water consumption recorded at the end of previous year.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -58,7 +58,7 @@ namespace
"Date when previous year ended.",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Date)

Wyświetl plik

@ -46,7 +46,7 @@ namespace
FieldMatcher::build()
.set(DifVifKey("02FF20")),
Translate::Lookup()
.add(Translate::Rule("ERROR_FLAGS", Translate::Type::BitToString)
.add(Translate::Rule("ERROR_FLAGS", Translate::MapType::BitToString)
.set(MaskBits(0x000f))
.set(DefaultMessage("OK"))
.add(Translate::Map(0x01 ,"DRY", TestBit::Set))
@ -60,7 +60,7 @@ namespace
"The total water consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -71,7 +71,7 @@ namespace
"The total water consumption recorded at the beginning of this month.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -83,7 +83,7 @@ namespace
"The water temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Minimum)
.set(VIFRange::FlowTemperature)
@ -95,7 +95,7 @@ namespace
"The external temperature outside of the meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Any)
.set(VIFRange::ExternalTemperature)
@ -108,7 +108,7 @@ namespace
"The lowest external temperature outside of the meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Minimum)
.set(VIFRange::ExternalTemperature)
@ -119,7 +119,7 @@ namespace
"The maximum flow recorded during previous period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::VolumeFlow)
@ -136,7 +136,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0x000f),
"",
{
@ -159,7 +159,7 @@ namespace
{
{
"DRY",
Translate::Type::IndexToString,
Translate::MapType::IndexToString,
AlwaysTrigger, MaskBits(0x0070),
"",
{
@ -186,7 +186,7 @@ namespace
{
{
"REVERSED",
Translate::Type::IndexToString,
Translate::MapType::IndexToString,
AlwaysTrigger, MaskBits(0x0380),
"",
{
@ -213,7 +213,7 @@ namespace
{
{
"LEAKING",
Translate::Type::IndexToString,
Translate::MapType::IndexToString,
AlwaysTrigger, MaskBits(0x1c00),
"",
{
@ -240,7 +240,7 @@ namespace
{
{
"BURSTING",
Translate::Type::IndexToString,
Translate::MapType::IndexToString,
AlwaysTrigger, MaskBits(0xe000),
"",
{

Wyświetl plik

@ -47,7 +47,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
@ -62,7 +62,7 @@ namespace
"The current temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ExternalTemperature)
@ -73,7 +73,7 @@ namespace
"The current relative humidity.",
DEFAULT_PRINT_PROPERTIES,
Quantity::RelativeHumidity,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::RelativeHumidity)

Wyświetl plik

@ -47,7 +47,7 @@ namespace
"Et+ the total 3-phase active positive energy.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -61,7 +61,7 @@ namespace
"P+ the 3-phase active positive power.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -75,7 +75,7 @@ namespace
"Er+ the total 3-phase reactive positive energy.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -89,7 +89,7 @@ namespace
"Q+ the 3-phase reactive positive power.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -103,7 +103,7 @@ namespace
"Part Et+ the total 3-phase active partial energy.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -117,7 +117,7 @@ namespace
"P- the 3-phase active negative power.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -131,7 +131,7 @@ namespace
"Part Er+ the total 3-phase reactive partial energy.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -145,7 +145,7 @@ namespace
"Q- the 3-phase reactive negative power.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -159,7 +159,7 @@ namespace
"PF the power factor.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless),
@ -174,7 +174,7 @@ namespace
.set(MeasurementType::Instantaneous)
.set(VIFRange::ErrorFlags),
Translate::Lookup()
.add(Translate::Rule("ERROR_FLAGS", Translate::Type::BitToString)
.add(Translate::Rule("ERROR_FLAGS", Translate::MapType::BitToString)
.set(MaskBits(0xff))
.set(DefaultMessage("OK"))
));
@ -186,7 +186,7 @@ namespace
"I1 Amperage for L1 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Amperage)
@ -198,7 +198,7 @@ namespace
"I2 Amperage for L2 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Amperage)
@ -210,7 +210,7 @@ namespace
"I3 Amperage for L3 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Amperage)
@ -222,7 +222,7 @@ namespace
"L1-N Voltage for L1 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
@ -234,7 +234,7 @@ namespace
"L2-N Voltagefor L2 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
@ -246,7 +246,7 @@ namespace
"L3-N Voltage for L3 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
@ -260,7 +260,7 @@ namespace
"P1 Power for L1 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -273,7 +273,7 @@ namespace
"P2 Power for L2 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -286,7 +286,7 @@ namespace
"P3 Power for L3 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -299,7 +299,7 @@ namespace
"Q1 Power for L1 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -312,7 +312,7 @@ namespace
"Q2 Power for L2 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -325,7 +325,7 @@ namespace
"Q3 Power for L3 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -338,7 +338,7 @@ namespace
"PF1 the power factor for L1 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
@ -351,7 +351,7 @@ namespace
"PF2 the power factor for L2 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
@ -364,7 +364,7 @@ namespace
"PF3 the power factor for L3 phase.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
@ -377,7 +377,7 @@ namespace
"L1-L2 Voltage between phases.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
@ -389,7 +389,7 @@ namespace
"L2-L3 Voltage between phases.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
@ -401,7 +401,7 @@ namespace
"L3-L1 Voltage between phases.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
@ -413,7 +413,7 @@ namespace
"I Neutral amperage.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Amperage)
@ -426,7 +426,7 @@ namespace
"Frequency in 0.1 Hz",
DEFAULT_PRINT_PROPERTIES | PrintProperty::HIDE,
Quantity::Frequency,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("05FF5A"))
);

Wyświetl plik

@ -64,7 +64,7 @@ namespace
"The total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -75,7 +75,7 @@ namespace
"The total energy backward (production) recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -87,7 +87,7 @@ namespace
"The current power consumption.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -98,7 +98,7 @@ namespace
"The current power production.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)

Wyświetl plik

@ -48,7 +48,7 @@ namespace
"The current temperature.",
PrintProperty::REQUIRED,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ExternalTemperature)
@ -59,7 +59,7 @@ namespace
"The average temperature over the last hour.",
PrintProperty::REQUIRED,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ExternalTemperature)
@ -71,7 +71,7 @@ namespace
"The average temperature over the last 24 hours.",
PrintProperty::REQUIRED,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ExternalTemperature)
@ -83,7 +83,7 @@ namespace
"The current relative humidity.",
PrintProperty::REQUIRED,
Quantity::RelativeHumidity,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::RelativeHumidity)
@ -94,7 +94,7 @@ namespace
"The average relative humidity over the last hour.",
PrintProperty::REQUIRED,
Quantity::RelativeHumidity,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::RelativeHumidity)
@ -106,7 +106,7 @@ namespace
"The average relative humidity over the last 24 hours.",
PrintProperty::REQUIRED,
Quantity::RelativeHumidity,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::RelativeHumidity)

Wyświetl plik

@ -48,7 +48,7 @@ namespace
"The total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -59,7 +59,7 @@ namespace
"The total amount of water that has passed through this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -70,7 +70,7 @@ namespace
"The active power consumption.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -81,7 +81,7 @@ namespace
"The flow of water.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow)
@ -92,7 +92,7 @@ namespace
"The forward temperature of the water.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::FlowTemperature)
@ -103,7 +103,7 @@ namespace
"The return temperature of the water.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ReturnTemperature)
@ -124,7 +124,7 @@ namespace
"The energy consumption recorded by this meter at the set date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -136,7 +136,7 @@ namespace
"The amount of water that had passed through this meter at the set date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -148,7 +148,7 @@ namespace
"The maximum forward temperature of the water.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::FlowTemperature)
@ -160,7 +160,7 @@ namespace
"The maximum return temperature of the water.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::ReturnTemperature)
@ -172,7 +172,7 @@ namespace
"The maximum forward flow of water through this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::VolumeFlow)

Wyświetl plik

@ -59,7 +59,7 @@ namespace
"The total water consumption at the end of the previous billing period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -71,7 +71,7 @@ namespace
"The total media volume flowing forward at the end of previous billing period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -84,7 +84,7 @@ namespace
"The total media volume flowing backward at the end of the previous billing period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -97,7 +97,7 @@ namespace
"Percentage of battery remaining.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("01FD74")),
Unit::PERCENTAGE
@ -118,5 +118,5 @@ namespace
// Test: M q400 05829163 NOKEY
// telegram=|544409076391820510077ABF100000046D2A0DC62C0420E80F430104130000000004933B0000000004933C00000000023B00000259F0D8446D0000C12C44130000000044933B0000000044933C0000000001FD7461|
// {"backward_at_set_date_m3": 0,"battery_pct": 97,"consumption_at_set_date_m3": 0,"flow_temperature_c": 555.36,"forward_at_set_date_m3": 0,"id": "05829163","media": "water","meter": "q400","meter_datetime": "2022-12-06 13:42","name": "M","on_time_h": 5881.166667,"set_datetime": "2022-12-01 00:00","status": "TEMPORARY_ERROR","timestamp": "1111-11-11T11:11:11Z","total_backward_m3": 0,"total_forward_m3": 0,"total_m3": 0,"volume_flow_m3h": 0}
// {"backward_at_set_date_m3": 0,"battery_pct": 97,"consumption_at_set_date_m3": 0,"flow_temperature_c": -100,"forward_at_set_date_m3": 0,"id": "05829163","media": "water","meter": "q400","meter_datetime": "2022-12-06 13:42","name": "M","on_time_h": 5881.166667,"set_datetime": "2022-12-01 00:00","status": "TEMPORARY_ERROR","timestamp": "1111-11-11T11:11:11Z","total_backward_m3": 0,"total_forward_m3": 0,"total_m3": 0,"volume_flow_m3h": 0}
// |M;05829163;0;1111-11-11 11:11.11

Wyświetl plik

@ -59,7 +59,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xff),
"OK",
{
@ -74,7 +74,7 @@ namespace
"The current heat cost allocation.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -95,7 +95,7 @@ namespace
"Heat cost allocation at the most recent billing period date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -117,7 +117,7 @@ namespace
"Heat cost allocation at the most recent billing period date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -139,7 +139,7 @@ namespace
"Heat cost allocation at the 8 billing period date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -161,7 +161,7 @@ namespace
"Heat cost allocation at the 17 billing period date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -200,7 +200,7 @@ namespace
"Forward media temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::FlowTemperature)

Wyświetl plik

@ -54,7 +54,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
@ -85,7 +85,7 @@ namespace
"The total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -106,7 +106,7 @@ namespace
"The total energy consumption recorded at the last day of the previous month.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(StorageNr(17))
@ -128,7 +128,7 @@ namespace
"The total energy consumption recorded at the last day of the previous year.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(StorageNr(1))
@ -160,8 +160,11 @@ namespace
vector<uchar> v;
auto entry = it->second.second;
hex2bin(entry.value.substr(0, 8), &v);
t->addId(v.begin());
std::string info = "*** " + entry.value.substr(0, 8) + " tpl-id (" + t->ids.back() + ")";
// FIXME PROBLEM
Address a;
a.id = tostrprintf("%02x%02x%02x%02x", v[3], v[2], v[1], v[0]);
t->addresses.push_back(a);
std::string info = "*** " + entry.value.substr(0, 8) + " tpl-id (" + t->addresses.back().id + ")";
t->addSpecialExplanation(entry.offset, 4, KindOfData::CONTENT, Understanding::FULL, info.c_str());
v.clear();

Wyświetl plik

@ -63,7 +63,7 @@ namespace
"The total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -89,7 +89,7 @@ namespace
"The total energy consumption recorded at key (billing) date",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -121,7 +121,7 @@ namespace
info,
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -136,7 +136,7 @@ namespace
"The time between the measurement and the sending of this telegram.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Time,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ActualityDuration)
@ -147,7 +147,7 @@ namespace
"How long the meter has been in an error state and unable to measure values, while powered up.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Time,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::AtError)
.set(VIFRange::OnTime)

Wyświetl plik

@ -49,7 +49,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
@ -73,7 +73,7 @@ namespace
"Number of times the smoke alarm has triggered.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Unsigned,
FieldMatcher::build()
.set(DifVifKey("81037C034C4123"))
);
@ -102,7 +102,7 @@ namespace
"Number of times the test button has been pressed.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("81027C03495523"))
);
@ -112,7 +112,7 @@ namespace
"Transmission counter?",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None,
VifScaling::None, DifSignedness::Unsigned,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AccessNumber)
@ -132,7 +132,7 @@ namespace
"What does this mean?",
DEFAULT_PRINT_PROPERTIES,
Quantity::Time,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("02FDAC7E"))
);

Wyświetl plik

@ -53,7 +53,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffffffff),
"OK",
{
@ -69,7 +69,7 @@ namespace
"The total heating energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -81,7 +81,7 @@ namespace
"The total cooling energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -93,7 +93,7 @@ namespace
"The current power consumption.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -114,7 +114,7 @@ namespace
"The heating energy consumption recorded at the end of the previous billing period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -127,7 +127,7 @@ namespace
"The cooling energy consumption recorded at the end of the previous billing period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)

Wyświetl plik

@ -1,5 +1,5 @@
/*
Copyright (C) 2022 Fredrik Öhrström (gpl-3.0-or-later)
Copyright (C) 2022-2024 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
@ -42,6 +42,7 @@ namespace
di.addDetection(MANUFACTURER_QDS, 0x07, 0x16);
di.addDetection(MANUFACTURER_QDS, 0x06, 0x18);
di.addDetection(MANUFACTURER_QDS, 0x07, 0x18);
di.addDetection(MANUFACTURER_QDS, 0x07, 0x19);
di.addDetection(MANUFACTURER_QDS, 0x06, 0x35);
di.addDetection(MANUFACTURER_QDS, 0x07, 0x35);
di.usesProcessContent();
@ -65,7 +66,7 @@ namespace
"The water consumption at the due date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -77,7 +78,7 @@ namespace
"The due date for billing date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Date)
@ -90,7 +91,7 @@ namespace
"The water consumption at the 17 due date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -102,7 +103,7 @@ namespace
"The due date for billing date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Date)
@ -115,7 +116,7 @@ namespace
"Media volume flow when duration exceeds lower last.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow)
@ -127,7 +128,7 @@ namespace
"The date the error occurred at. If no error, reads 2127-15-31 (FFFF).",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::AtError)
.set(VIFRange::Date),
@ -195,3 +196,9 @@ void Driver::processContent(Telegram *t) {
// telegram=|49449344123456781606780DFF5F3500824E00007F0007C113FFFF63961300DF2C82731200FE2463811300A400F200D100A900DD00E000E90006011601EA0027010F012F046D0211F225|
// {"due_17_date": "2023-04-30","due_17_date_m3": 138.163,"due_date": "2022-12-31","due_date_m3": 127.382,"id": "78563412","media": "warm water","meter": "qwater","meter_datetime": "2023-05-18 17:02","name": "QWooo","status": "OK","timestamp": "1111-11-11T11:11:11Z","total_m3": 139.663}
// |QWooo;78563412;139.663;127.382;2022-12-31;OK;1111-11-11 11:11.11
// Test: QWaaa qwater 51220588 NOKEY
// Comment:
// telegram=|4944934488052251190778_0DFF5F350082930000810007C113FFFF91670400FF2C265402001E34332204000000EE00F201A501DB01C1015401B70178019701B901C9012F046D06091D35|
// {"due_17_date": "2024-04-30","due_17_date_m3": 42.233,"due_date": "2023-12-31","due_date_m3": 25.426,"id": "51220588","media": "water","meter": "qwater","meter_datetime": "2024-05-29 09:06","name": "QWaaa","status": "OK","timestamp": "1111-11-11T11:11:11Z","total_m3": 46.791}
// |QWaaa;51220588;46.791;25.426;2023-12-31;OK;1111-11-11 11:11.11

Wyświetl plik

@ -47,7 +47,7 @@ namespace
"The current temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ExternalTemperature)
@ -58,7 +58,7 @@ namespace
"The average temperature over the last hour.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ExternalTemperature)
@ -70,7 +70,7 @@ namespace
"The average temperature over the last 24 hours.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ExternalTemperature)
@ -82,7 +82,7 @@ namespace
"The maximum temperature over the last hour.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::ExternalTemperature)
@ -93,7 +93,7 @@ namespace
"The maximum temperature over the last 24 hours.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::ExternalTemperature)
@ -105,7 +105,7 @@ namespace
"The minimum temperature over the last hour.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Minimum)
.set(VIFRange::ExternalTemperature)
@ -116,7 +116,7 @@ namespace
"The minimum temperature over the last 24 hours.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Minimum)
.set(VIFRange::ExternalTemperature)
@ -128,7 +128,7 @@ namespace
"The current relative humidity.",
DEFAULT_PRINT_PROPERTIES,
Quantity::RelativeHumidity,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::RelativeHumidity)
@ -139,7 +139,7 @@ namespace
"The average relative humidity over the last hour.",
DEFAULT_PRINT_PROPERTIES,
Quantity::RelativeHumidity,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::RelativeHumidity)
@ -151,7 +151,7 @@ namespace
"The average relative humidity over the last 24 hours.",
DEFAULT_PRINT_PROPERTIES,
Quantity::RelativeHumidity,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::RelativeHumidity)
@ -163,7 +163,7 @@ namespace
"The maximum relative humidity over the last hour.",
DEFAULT_PRINT_PROPERTIES,
Quantity::RelativeHumidity,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::RelativeHumidity)
@ -174,7 +174,7 @@ namespace
"The maximum relative humidity over the last 24 hours.",
DEFAULT_PRINT_PROPERTIES,
Quantity::RelativeHumidity,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::RelativeHumidity)
@ -186,7 +186,7 @@ namespace
"The minimum relative humidity over the last hour.",
DEFAULT_PRINT_PROPERTIES,
Quantity::RelativeHumidity,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Minimum)
.set(VIFRange::RelativeHumidity)
@ -197,7 +197,7 @@ namespace
"The minimum relative humidity over the last 24 hours.",
DEFAULT_PRINT_PROPERTIES,
Quantity::RelativeHumidity,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Minimum)
.set(VIFRange::RelativeHumidity)
@ -209,7 +209,7 @@ namespace
"The meters date time.",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::DateTime)

Wyświetl plik

@ -43,7 +43,7 @@ namespace
"The total water consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)

Wyświetl plik

@ -51,7 +51,7 @@ namespace
"The total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -62,7 +62,7 @@ namespace
"The active power consumption.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -73,7 +73,7 @@ namespace
"The maximum power consumption over ?period?.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::AnyPowerVIF)
@ -84,7 +84,7 @@ namespace
"The flow of water.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow)
@ -95,7 +95,7 @@ namespace
"The maximum forward flow of water over a ?period?.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::VolumeFlow)
@ -106,7 +106,7 @@ namespace
"The forward temperature of the water.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::FlowTemperature)
@ -117,7 +117,7 @@ namespace
"The return temperature of the water.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ReturnTemperature)
@ -128,7 +128,7 @@ namespace
"The temperature difference forward-return for the water.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::TemperatureDifference)
@ -139,7 +139,7 @@ namespace
"The total amount of water that has passed through this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -155,7 +155,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xff),
"OK",
{
@ -188,7 +188,7 @@ namespace
"The energy consumption at the last billing period date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -205,7 +205,7 @@ namespace
info,
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -220,8 +220,14 @@ namespace
// {"media":"heat","meter":"sensostar","name":"Heat","id":"20480057","meter_timestamp":"2022-04-28 13:44","total_kwh":0,"power_kw":0,"power_max_kw":0,"flow_water_m3h":0,"flow_water_max_m3h":0,"forward_c":20,"return_c":21,"difference_c":-0.38,"total_water_m3":0,"current_status":"ERROR_FLOW_MEASUREMENT_SYSTEM_ERROR","reporting_date":"2000-00-00","energy_consumption_at_reporting_date_kwh":0,"consumption_1_months_ago_kwh":0,"timestamp":"1111-11-11T11:11:11Z"}
// |Heat;20480057;0;0;ERROR_FLOW_MEASUREMENT_SYSTEM_ERROR;2000-00-00;0;1111-11-11 11:11.11
// Test: WMZ sensostar 02752560 NOKEY
// Comment: from "Sensostar U"
//Test: WMZ sensostar 02752560 NOKEY
//Comment: from "Sensostar U"
//telegram=a444c5146025750200047ac20000202f2f046d2e26c62a040643160000041310f0050001fd1700426cbf2c4406570e00008401061f160000840206f6150000840306f5150000840406f3150000840506ea150000840606bf1500008407065214000084080692120000840906c5100000840a06570e0000840b06ca0b0000840c06da090000840d06ca080000840e06c8080000840f06c608000003fd0c05010002fd0b2111
//{"media":"heat","meter":"sensostar","name":"WMZ","id":"02752560","meter_timestamp":"2022-10-06 06:46","total_kwh":5699,"total_water_m3":389.136,"current_status":"OK","reporting_date":"2021-12-31","energy_consumption_at_reporting_date_kwh":3671,"consumption_1_months_ago_kwh":5663,"consumption_2_months_ago_kwh":5622,"consumption_3_months_ago_kwh":5621,"consumption_4_months_ago_kwh":5619,"consumption_5_months_ago_kwh":5610,"consumption_6_months_ago_kwh":5567,"consumption_7_months_ago_kwh":5202,"consumption_8_months_ago_kwh":4754,"consumption_9_months_ago_kwh":4293,"consumption_10_months_ago_kwh":3671,"consumption_11_months_ago_kwh":3018,"consumption_12_months_ago_kwh":2522,"consumption_13_months_ago_kwh":2250,"consumption_14_months_ago_kwh":2248,"consumption_15_months_ago_kwh":2246,"timestamp":"1111-11-11 11:11.11"}
//WMZ;02752560;5699;389.136000;OK;1111-11-11 11:11.11
// Test: ABC sensostar 21750444 NOKEY
// Comment: Test negative flow values
// telegram=4944C5144404752100047AC1000020_2F2F046D142D073404068847000001FD170004138E8A4000043BF7FFFFFF042B00000000025B3E00025F360002612F0303FD0C05010002FD0B2011
// {"current_status": "OK","difference_c": 8.15,"flow_water_m3h": -0.009,"forward_c": 62,"id": "21750444","media": "heat","meter": "sensostar","meter_timestamp": "2024-04-07 13:20","name": "ABC","power_kw": 0,"return_c": 54,"timestamp": "1111-11-11T11:11:11Z","total_kwh": 18312,"total_water_m3": 4229.774}
// |ABC;21750444;18312;4229.774;OK;null;null;1111-11-11 11:11.11

Wyświetl plik

@ -51,7 +51,7 @@ namespace
.set(MeasurementType::Instantaneous)
.set(VIFRange::ErrorFlags),
Translate::Lookup()
.add(Translate::Rule("ERROR_FLAGS", Translate::Type::BitToString)
.add(Translate::Rule("ERROR_FLAGS", Translate::MapType::BitToString)
.set(MaskBits(0x0000))
.set(DefaultMessage("OK"))
));
@ -61,7 +61,7 @@ namespace
"The total heat energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -72,7 +72,7 @@ namespace
"The total heat energy consumption recorded by this meter on tariff 1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -84,7 +84,7 @@ namespace
"The total heating media volume recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -95,7 +95,7 @@ namespace
"The total heating media volume recorded by this meter on tariff 2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -107,7 +107,7 @@ namespace
"The current heat media volume flow.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow)
@ -118,7 +118,7 @@ namespace
"The current power consumption.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::PowerW)
@ -129,7 +129,7 @@ namespace
"The current forward heat media temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::FlowTemperature)
@ -140,7 +140,7 @@ namespace
"The current return heat media temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ReturnTemperature)
@ -151,7 +151,7 @@ namespace
"The current return heat media temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::TemperatureDifference)
@ -162,7 +162,7 @@ namespace
"The total heat energy consumption recorded by this meter at the end of the previous billing period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -174,7 +174,7 @@ namespace
"The total heating media volume recorded by this meter at the end of the previous billing period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -186,7 +186,7 @@ namespace
"The last billing period end date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Date)

Wyświetl plik

@ -48,7 +48,7 @@ namespace
"The total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -59,7 +59,7 @@ namespace
"The total cooling energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -71,7 +71,7 @@ namespace
"The total volume recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyVolumeVIF)
@ -82,7 +82,7 @@ namespace
"The total cooling volume recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyVolumeVIF)
@ -94,7 +94,7 @@ namespace
"The current flow.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow)
@ -105,7 +105,7 @@ namespace
"The power.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
@ -116,7 +116,7 @@ namespace
"The flow temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::FlowTemperature)
@ -127,7 +127,7 @@ namespace
"The return temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ReturnTemperature)
@ -138,7 +138,7 @@ namespace
"How long the meter has been collecting data.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Time,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::OperatingTime)
@ -149,7 +149,7 @@ namespace
"How long the meter has been in an error state and not collected data.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Time,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::OperatingTime)
@ -161,7 +161,7 @@ namespace
"The total energy consumption recorded by this meter at the set date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -173,7 +173,7 @@ namespace
"The total cooling energy consumption recorded by this meter at the set date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -186,7 +186,7 @@ namespace
"The last billing set date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Date)

Wyświetl plik

@ -43,7 +43,7 @@ namespace
"The current heat cost allocation for this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -64,7 +64,7 @@ namespace
"Heat cost allocation at the most recent billing period date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
@ -76,7 +76,7 @@ namespace
"The current temperature of the heating element.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::FlowTemperature)
@ -87,7 +87,7 @@ namespace
"The current room temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ExternalTemperature)
@ -98,7 +98,7 @@ namespace
"The maximum temperature so far during this billing period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::FlowTemperature)
@ -110,7 +110,7 @@ namespace
"The maximum temperature during the previous billing period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Maximum)
.set(VIFRange::FlowTemperature)

Wyświetl plik

@ -48,7 +48,7 @@ namespace
.set(MeasurementType::Instantaneous)
.set(VIFRange::ErrorFlags),
Translate::Lookup()
.add(Translate::Rule("ERROR_FLAGS", Translate::Type::BitToString)
.add(Translate::Rule("ERROR_FLAGS", Translate::MapType::BitToString)
.set(MaskBits(0x000f))
.set(DefaultMessage("OK"))
));

Wyświetl plik

@ -49,8 +49,8 @@ namespace
di.setName("topaseskr");
di.setDefaultFields(
"name,id,total_m3,temperature_c,current_flow_m3h,volume_year_period_m3,"
"reverse_volume_year_period_m3,meter_year_period_start_date,volume_month_period_m3,"
"meter_month_period_start_datetime,timestamp");
"reverse_volume_year_period_m3,meter_year_period_end_date,volume_month_period_m3,"
"meter_month_period_end_datetime,timestamp");
di.setMeterType(MeterType::WaterMeter);
di.addLinkMode(LinkMode::T1);
di.addDetection(MANUFACTURER_AMT, 0x06, 0xf1);
@ -67,7 +67,7 @@ namespace
"Current water temperature recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::FlowTemperature));
@ -77,7 +77,7 @@ namespace
"The current water flow.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow));
@ -87,7 +87,7 @@ namespace
"Volume up to end of last year-period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -99,7 +99,7 @@ namespace
"Reverse volume in this year-period (?)",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -109,8 +109,8 @@ namespace
addStringFieldWithExtractor(
"meter_year_period_start_date",
"Meter date for year-period start.",
"meter_year_period_end_date",
"Meter date for year-period end.",
DEFAULT_PRINT_PROPERTIES,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
@ -123,7 +123,7 @@ namespace
"Volume up to end of last month-period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -131,8 +131,8 @@ namespace
);
addStringFieldWithExtractor(
"meter_month_period_start_datetime",
"Meter timestamp for month-period start.",
"meter_month_period_end_datetime",
"Meter timestamp for month-period end.",
DEFAULT_PRINT_PROPERTIES,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
@ -145,7 +145,7 @@ namespace
"Remaining battery life in years.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Time,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::RemainingBattery),
@ -155,10 +155,10 @@ namespace
// Test: Witer topaseskr 78563412 NOKEY
// telegram=|4E44B40512345678F1077A310040052F2F_01FD08040C13991848004C1359423500CC101300000000CC201359423500426C7F2C0B3B00000002FD74DA10025AD300C4016D3B179F27CC011387124600|
// {"media":"water","meter":"topaseskr","name":"Witer","id":"78563412","total_m3":481.899,"access_counter":4,"temperature_c":21.1,"current_flow_m3h":0,"volume_year_period_m3":354.259,"reverse_volume_year_period_m3":0,"meter_year_period_start_date":"2019-12-31","volume_month_period_m3":461.287,"meter_month_period_start_datetime":"2020-07-31 23:59","battery_y":11.811331,"timestamp":"1111-11-11T11:11:11Z"}
// {"media":"water","meter":"topaseskr","name":"Witer","id":"78563412","total_m3":481.899,"access_counter":4,"temperature_c":21.1,"current_flow_m3h":0,"volume_year_period_m3":354.259,"reverse_volume_year_period_m3":0,"meter_year_period_end_date":"2019-12-31","volume_month_period_m3":461.287,"meter_month_period_end_datetime":"2020-07-31 23:59","battery_y":11.811331,"timestamp":"1111-11-11T11:11:11Z"}
// |Witer;78563412;481.899;21.1;0;354.259;0;2019-12-31;461.287;2020-07-31 23:59;1111-11-11 11:11.11
// Test: Woter topaseskr 69190253 NOKEY
// telegram=|4E44B40553021969F1077A0C0040052F2F_01FD08800C13914544004C1393673500CC101300000000CC201393673500426CDF2C0B3B0100F002FD747912025AAE00C4016D3B17FF25CC011325584100|
// {"access_counter": 128,"battery_y": 12.947562,"current_flow_m3h": -0.001,"id": "69190253","media": "water","meter": "topaseskr","meter_month_period_start_datetime": "2023-05-31 23:59","meter_year_period_start_date": "2022-12-31","name": "Woter","reverse_volume_year_period_m3": 0,"temperature_c": 17.4,"timestamp": "1111-11-11T11:11:11Z","total_m3": 444.591,"volume_month_period_m3": 415.825,"volume_year_period_m3": 356.793}
// {"access_counter": 128,"battery_y": 12.947562,"current_flow_m3h": -0.001,"id": "69190253","media": "water","meter": "topaseskr","meter_month_period_end_datetime": "2023-05-31 23:59","meter_year_period_end_date": "2022-12-31","name": "Woter","reverse_volume_year_period_m3": 0,"temperature_c": 17.4,"timestamp": "1111-11-11T11:11:11Z","total_m3": 444.591,"volume_month_period_m3": 415.825,"volume_year_period_m3": 356.793}
// |Woter;69190253;444.591;17.4;-0.001;356.793;0;2022-12-31;415.825;2023-05-31 23:59;1111-11-11 11:11.11

Wyświetl plik

@ -42,7 +42,7 @@ namespace
"The total heat energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -53,7 +53,7 @@ namespace
"The total heating media volume recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -64,7 +64,7 @@ namespace
"The current power consumption.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::PowerW)
@ -75,7 +75,7 @@ namespace
"The current heat media volume flow.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::AutoSigned,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow)
@ -86,7 +86,7 @@ namespace
"The current forward heat media temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::FlowTemperature)
@ -97,7 +97,7 @@ namespace
"The current return heat media temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ReturnTemperature)
@ -114,7 +114,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{

Wyświetl plik

@ -40,7 +40,7 @@ namespace
"The total water consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -51,7 +51,7 @@ namespace
"The total water consumption recorded at the beginning of this month.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -68,7 +68,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffffff),
"OK",
{
@ -92,7 +92,7 @@ namespace
"The total backward water volume recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04933C"))
);

Wyświetl plik

@ -49,7 +49,7 @@ namespace
{
{
"STATUS_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
@ -68,7 +68,7 @@ namespace
{
{
"OTHER_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xff),
"",
{
@ -92,7 +92,7 @@ namespace
"The total gas consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
@ -114,7 +114,7 @@ namespace
"The total gas consumption recorded by this meter at the beginning of this month.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)

Wyświetl plik

@ -44,7 +44,7 @@ namespace
"Total energy consumption at the end of the year",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -56,7 +56,7 @@ namespace
"Date when previous year ended.",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Date)

Wyświetl plik

@ -42,7 +42,7 @@ namespace
"The total energy consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -53,7 +53,7 @@ namespace
"The total energy consumption recorded when?",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -65,7 +65,7 @@ namespace
"The last billing old date?",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Date)
@ -77,7 +77,7 @@ namespace
"The total energy consumption recorded by this meter at the due date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Energy,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyEnergyVIF)
@ -89,7 +89,7 @@ namespace
"The last billing set date.",
DEFAULT_PRINT_PROPERTIES,
Quantity::PointInTime,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Date)

Some files were not shown because too many files have changed in this diff Show More