Porównaj commity

...

213 Commity

Autor SHA1 Wiadomość Data
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
Fredrik Öhrström 569efa3af2 Version 1.16.1 2024-02-22 2024-02-22 18:46:05 +01:00
Fredrik Öhrström 58dd9d32ff
Merge pull request #1186 from testuser7/docker-tag
Fix docker tag creation
2024-02-22 18:45:13 +01:00
testuser7 7f7f7e4df4 Fix docker tag creation 2024-02-22 18:39:41 +01:00
Fredrik Öhrström af83f15ca9 Version 1.16.0 2024-02-22 2024-02-22 17:49:53 +01:00
Fredrik Öhrström 0587c6d1dd
Merge pull request #1185 from jsreynaud/patch-1
Update README.md
2024-02-22 17:46:34 +01:00
Jean-Samuel Reynaud dd45c14970
Update README.md
Fix an inconstancy between code that use --driverslib and doc that say --dirverlib...
2024-02-22 16:28:14 +01:00
Fredrik Öhrström 097f91fac0 Add dynaic driver add_combinable and storage_nr. 2024-02-15 11:40:30 +01:00
Fredrik Öhrström dbd99698b8 Version 1.15.0 2024-02-14 2024-02-14 17:52:32 +01:00
Fredrik Öhrström 40605ebb40 Version 1.15.0-RC2 2024-02-14 2024-02-14 16:56:39 +01:00
Fredrik Öhrström 74e6c89af1
Merge pull request #1178 from testuser7/rtl_reset
Do not install librtlsdr-dev and rtl-sdr packages
2024-02-14 14:04:50 +01:00
testuser7 4634431c59 Do not install librtlsdr-dev and rtl-sdr packages 2024-02-13 23:47:09 +01:00
Fredrik Öhrström c3d1b6f3c5
Merge pull request #1167 from testuser7/rtl_reset
Update docker image, add rtl_reset, rtl_sdr
2024-02-13 17:08:28 +01:00
Fredrik Öhrström 4b55407aa9 Version 1.15.0-RC1 2024-02-13 2024-02-13 15:26:07 +01:00
testuser7 97f2082dbc Add rtl_reset to docker image 2024-02-12 22:05:26 +01:00
testuser7 a5f4f43375 Build librtlsdr from source 2024-02-12 22:05:26 +01:00
testuser7 000e4f89ad Use latest docker alpine image 2024-02-12 22:05:26 +01:00
Fredrik Öhrström 14ca481c63 Fix rtl_wmbus -f detection. 2024-02-12 14:07:53 +01:00
Fredrik Öhrström 0d0338c9a4 Add on_time_h,battery_pct to q400 driver, not qualcosonic driver. 2024-02-12 10:06:09 +01:00
Fredrik Öhrström 4d3e306f30 Add on_time_h and batter_pct to qualcosonic driver. Add Percentage unit. Add 'keep open' tag and update workflow. 2024-02-12 09:34:59 +01:00
Fredrik Öhrström 378c367475 Fix typo. 2024-02-12 01:22:42 +01:00
Fredrik Öhrström 004d8b751f Do not try to load the builtin driver if --driver=<file> has been used already. 2024-02-12 01:16:34 +01:00
Fredrik Öhrström 72ecb86b91 Add use=<field> to use optional field from library. 2024-02-12 00:55:04 +01:00
Fredrik Öhrström 24b47fbd48 Temporarily avoid building xmq when testing after deb build. 2024-02-12 00:13:13 +01:00
Fredrik Öhrström 8efad28289 Remove xslt1 from docker since no tests are performed. 2024-02-11 23:40:41 +01:00
Fredrik Öhrström 46fc3995bd Remove xslt1 from docker run deps since it is only used for building. 2024-02-11 23:35:26 +01:00
Fredrik Öhrström 9b6c84d2f2 Remove xslt1 from stage package since it is only used for building. 2024-02-11 23:32:17 +01:00
Fredrik Öhrström 54a8930918 Add necessary libxslt deps. 2024-02-11 23:27:52 +01:00
Fredrik Öhrström f446efa11d Clone xmq from correct url. 2024-02-11 23:18:51 +01:00
Fredrik Öhrström 2610af43b8 Updated CHANGES 2024-02-11 23:12:53 +01:00
Fredrik Öhrström fefbf507fe Add elster,iperl text based drivers. 2024-02-11 23:06:59 +01:00
Fredrik Öhrström 04ed4d7628 Add --driverdir=<dir> and --driver=<file> for loading drivers from text files. 2024-02-11 00:12:31 +01:00
Fredrik Öhrström 440ea263b1 Use mktemp in a way that is supported by busybox. 2024-01-31 20:47:06 +01:00
Fredrik Öhrström 8aabcdaca0
Merge pull request #1156 from wmbusmeters/dependabot/github_actions/peter-evans/dockerhub-description-4
Bump peter-evans/dockerhub-description from 3 to 4
2024-01-31 20:43:49 +01:00
Fredrik Öhrström a9862be62c
Merge pull request #1157 from wmbusmeters/dependabot/github_actions/peter-evans/repository-dispatch-3
Bump peter-evans/repository-dispatch from 2 to 3
2024-01-31 20:43:35 +01:00
dependabot[bot] 4d89d119da
Bump peter-evans/repository-dispatch from 2 to 3
Bumps [peter-evans/repository-dispatch](https://github.com/peter-evans/repository-dispatch) from 2 to 3.
- [Release notes](https://github.com/peter-evans/repository-dispatch/releases)
- [Commits](https://github.com/peter-evans/repository-dispatch/compare/v2...v3)

---
updated-dependencies:
- dependency-name: peter-evans/repository-dispatch
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-25 21:19:15 +00:00
dependabot[bot] eea8307f22
Bump peter-evans/dockerhub-description from 3 to 4
Bumps [peter-evans/dockerhub-description](https://github.com/peter-evans/dockerhub-description) from 3 to 4.
- [Release notes](https://github.com/peter-evans/dockerhub-description/releases)
- [Commits](https://github.com/peter-evans/dockerhub-description/compare/v3...v4)

---
updated-dependencies:
- dependency-name: peter-evans/dockerhub-description
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-25 21:19:09 +00:00
Fredrik Öhrström 03e03905ec Add missing cstdint since gcc 13 is more picky. 2024-01-24 12:33:59 +01:00
Fredrik Öhrström fe04152246
Merge pull request #1150 from wmbusmeters/BIBOLV-patch-2
Update Dockerfile
2024-01-24 11:51:00 +01:00
BIBO f33a676dee
Update Dockerfile
Rolling back to build rtl_433 from source as requested in https://github.com/wmbusmeters/wmbusmeters/issues/1149
2024-01-21 22:03:18 +02:00
Fredrik Öhrström 12cb6c9d17
Merge pull request #1146 from petr-svarc/patch-1
added missing closing bracket
2024-01-18 18:19:01 +01:00
Petr Švarc 6641def49f
added missing closing bracket 2024-01-18 18:05:12 +01:00
Fredrik Öhrström 3d1319bd78
Merge pull request #1121 from wmbusmeters/BIBOLV-patch-3
Update Dockerfile
2024-01-18 17:37:57 +01:00
Fredrik Öhrström 1ab3368b8c
Merge pull request #1119 from wmbusmeters/dependabot/github_actions/actions/stale-9
Bump actions/stale from 8 to 9
2024-01-18 15:50:53 +01:00
Fredrik Öhrström b6b6fe85d0
Merge pull request #1129 from Andi252/fb_fix_test_mkradio3
Added output for text_t1_meters.sh, when test failed
2024-01-18 15:49:57 +01:00
Fredrik Öhrström b49309bce3 Add missing && in docker file. 2024-01-18 15:47:03 +01:00
Fredrik Öhrström 42511190e7 Do not test rtl_wmbus for -f option if CMD is overridden. 2024-01-18 15:40:15 +01:00
Fredrik Öhrström 4f21c04804 Add warning when rtl_wmbus data flow freezes. Improve README. 2024-01-18 15:24:42 +01:00
Fredrik Öhrström 9a0a818fee Update CHANGES 2024-01-18 15:04:58 +01:00
Fredrik Öhrström abad0c8d74 Use new rtl_wmbus option -f to add flow control. If rtl_sdr stops sending samples to rtl_wmbus it will not exit with an error message. Wmbusmeters detects this and restarts the pipeline. Errors from rtl_sdr can be found in a /tmp/tmp....wmbusmeters_rtlsdr file. 2024-01-18 14:56:21 +01:00
Fredrik Öhrström 704e715582 Merge branch 'AddRTLWMBUSFlowCheck' 2024-01-18 11:00:35 +01:00
Fredrik Öhrström 866df740ad Add energy MWh VIF 7b00-7b01 and improve kamheat driver. 2024-01-15 15:29:43 +01:00
Andreas Horrer cbc422ac94 Merge remote-tracking branch 'origin/master' into fb_fix_test_mkradio3 2024-01-12 20:48:43 +01:00
Fredrik Öhrström 295053ebd6 Add more fields to the iem3000 driver. 2024-01-11 21:01:08 +01:00
Fredrik Öhrström b6878b503c Add iem3000 driver. 2024-01-11 20:36:10 +01:00
Fredrik Öhrström 7af4db244d Update test with new vif ranges: Medium Manufacturer. 2024-01-11 20:26:17 +01:00
Fredrik Öhrström fd0a4b6d63 Skip test for MacOS that does not use bash. 2024-01-11 20:24:40 +01:00
Fredrik Öhrström cddcc9ae26 Add iem3000 driver. 2024-01-11 18:34:46 +01:00
Fredrik Öhrström c08bf05521 Fix 2023-2024 in tests and update xmq.c 2024-01-09 23:31:41 +01:00
Andreas Horrer 757b56d2c8 change data for problem with year encoding in mkradio3 2024-01-01 20:40:41 +01:00
Andreas Horrer f69f9d6aa7 Changed test data due to problems with date encoding 2024-01-01 20:31:45 +01:00
Andreas Horrer dd2df53280 Added output for test_t1_meter.sh to see which test failed 2024-01-01 20:31:13 +01:00
BIBO dc783e1e87
Update Dockerfile
Changing alpine repo where latest version is available. 
With latest version also latest rtl-sdr is available (0.8.0-r0), also rtl_433 is available as package, so no need to build it from source. 
Tested raspi 32 and 64bit with rtl-sdr, HA tests are not done.
2023-12-09 22:15:49 +02:00
dependabot[bot] d22701f978
Bump actions/stale from 8 to 9
Bumps [actions/stale](https://github.com/actions/stale) from 8 to 9.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/v8...v9)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-07 21:53:47 +00:00
Fredrik Öhrström 331c5a4018 Correct test that expects a Repeater in the list of meter types. 2023-12-04 13:12:16 +01:00
Fredrik Öhrström 73bb7ef096 Test uses 'echo -n' which needs bash. 2023-12-04 13:03:36 +01:00
Fredrik Öhrström 10fbac056b Add test case to iwmtx5 driver. 2023-12-04 12:10:39 +01:00
Fredrik Öhrström aff37db2c1
Merge pull request #1095 from sunflowerenergias/master
Update driver_iwmtx5.cc
2023-12-04 12:01:24 +01:00
Fredrik Öhrström b011505d7b
Merge pull request #1047 from simonr-de/master
Update driver_sharky
2023-12-04 11:45:51 +01:00
Fredrik Öhrström b0cb4fa44b
Merge pull request #1114 from pimlie/fix-date-format
fix: date format should use semicolon as time separator
2023-12-04 11:44:31 +01:00
Fredrik Öhrström 044a522399 Update CHANGES. 2023-12-04 11:40:01 +01:00
Fredrik Öhrström 47f3256a50 Add test case to kamheat. 2023-12-04 11:39:25 +01:00
Fredrik Öhrström 0c3fa02d4f
Merge pull request #1109 from Jacman777/master
Update driver_kamheat.cc
2023-12-04 11:33:35 +01:00
Fredrik Öhrström 8077791846
Merge pull request #1115 from pimlie/feat-add-driver-lansen-repeater
feat: add driver for lansen repeater (0x0b)
2023-12-04 11:23:23 +01:00
Fredrik Öhrström 2605ff9cb3
Merge pull request #1113 from pimlie/feat-exec-shell-on-meter-add
feat: add support to run shell script when meter is first seen
2023-12-04 11:17:02 +01:00
pimlie 6a9cfcee21 test: add test for lansenrp driver 2023-11-29 20:34:24 +01:00
pimlie efea401f6a feat: add driver for lansen repeater (0x0b) 2023-11-29 19:32:02 +01:00
pimlie 4c194ba802 fix: date format should use semicolon as time separator 2023-11-29 11:17:21 +01:00
pimlie db37acbcdc feat: add support to run shell script when meter is first seen 2023-11-29 10:49:37 +01:00
Jacman777 92fb04e246
Update driver_kamheat.cc
Adding Kamstrup Multical 402 Heat Meter
2023-11-25 02:07:49 +01:00
Fredrik Öhrström b32236f600 Rename woot to target_m3 and target_datetime for hydrus driver. Where target is the total consumption at the end of the previous month. 2023-11-16 11:51:36 +01:00
Sergio Catalan 64602a079f Update driver_iwmtx5.cc
Update driver iwmtx5
2023-11-16 08:10:54 +01:00
Fredrik Öhrström 162658a29a
Merge pull request #1090 from Andi252/fb_add_itron_coldwatermeter_id
Added cold water meter type to itron driver
2023-11-12 19:37:40 +01:00
Fredrik Öhrström 9fbb49b0fc Change name of unknown field in hydrus to total_at_woot_m3 this will prevent overlap with total_at_date_m3. 2023-11-12 18:19:21 +01:00
Fredrik Öhrström 82234acd21 Add cmath for macosx. 2023-11-12 17:54:14 +01:00
Fredrik Öhrström c4b9f0d104 Always detect negative BCD values. Also detect BCD values with all F and treat them as missing data, ie. null in fields and not printed in json. 2023-11-12 15:29:30 +01:00
Fredrik Öhrström 9a99daf0ed You can now do: wmbusmeters --analyze=driver.xmq <hex> 2023-11-12 13:41:35 +01:00
Fredrik Öhrström 3696118db1 Add more loadable driver features. 2023-11-12 13:23:37 +01:00
Fredrik Öhrström 92090073cb Use macros for debug/verbose/trace to avoid calculation of args if debug/verbose/trace are not enabled. 2023-11-12 13:16:51 +01:00
Fredrik Öhrström c5dc2ada51 Add more loadable driver features. 2023-11-12 12:36:22 +01:00
Andreas Horrer f4299e2d6f Added itron cold water meter 2023-11-11 13:23:59 +01:00
Fredrik Öhrström a385737984 Better error messages when trying to load a driver file with errors. 2023-11-10 21:33:09 +01:00
Fredrik Öhrström 22d6880385 Add test for non-existant driver. 2023-11-06 21:04:40 +01:00
Fredrik Öhrström b9306be914 Only try loading driver from disk if the driver name ends with .xmq and is a valid file. 2023-11-06 20:41:30 +01:00
Fredrik Öhrström 3a097388f5 Update README.md with wmbusmeters usage of librtlsdr. 2023-10-31 10:17:41 +01:00
Fredrik Öhrström b2dd2801db
Merge pull request #1045 from geraldhuber/patch-1
Update README.md with paragraph about SDR naming (swradio0...255)
2023-10-31 10:12:04 +01:00
Fredrik Öhrström 6f0773ae7a Add missing include for int64_t etc. 2023-10-14 16:28:16 +02:00
Fredrik Öhrström 128aa77b78 Add libxml2 dependency. 2023-10-14 16:21:50 +02:00
Fredrik Öhrström 872bc53ace
Merge pull request #1052 from wmbusmeters/AddConfigFiles
Initial support for loadable drivers.
2023-10-14 16:10:57 +02:00
Fredrik Öhrström a1f0911a57 Add missing loadable driver files. 2023-10-14 15:58:29 +02:00
Fredrik Öhrström f017694d78 Initial support for loadable drivers. 2023-10-14 15:55:55 +02:00
Fredrik Öhrström 6e3bac97d4 Handle amb8465 dongle with command mode enabled for incoming telegrams. 2023-10-11 17:07:39 +02:00
simonr-de 7c5949d6b1
Update driver_sharky.cc
Changed VifScaling to AutoSigned to fix problem with negative values.
2023-10-09 16:12:35 +02:00
geraldhuber eb6311fec3
Update README.md with paragraph about SDR naming (swradio0...255) 2023-10-07 20:30:33 +02:00
Fredrik Öhrström ce6e2822e5
Merge pull request #1028 from wmbusmeters/dependabot/github_actions/docker/setup-qemu-action-3
Bump docker/setup-qemu-action from 2 to 3
2023-09-15 09:23:02 +02:00
Fredrik Öhrström eb9c90bd2d
Merge pull request #1029 from wmbusmeters/dependabot/github_actions/docker/login-action-3
Bump docker/login-action from 2 to 3
2023-09-15 09:22:41 +02:00
Fredrik Öhrström a8040e5eae
Merge pull request #1030 from wmbusmeters/dependabot/github_actions/docker/setup-buildx-action-3
Bump docker/setup-buildx-action from 2 to 3
2023-09-15 09:22:22 +02:00
Fredrik Öhrström 099fc1472c
Merge pull request #1031 from wmbusmeters/dependabot/github_actions/docker/metadata-action-5
Bump docker/metadata-action from 4 to 5
2023-09-15 09:22:00 +02:00
Fredrik Öhrström c6d0b79984
Merge pull request #1032 from wmbusmeters/dependabot/github_actions/docker/build-push-action-5
Bump docker/build-push-action from 4 to 5
2023-09-15 09:21:44 +02:00
dependabot[bot] 3c7b37a14b
Bump docker/build-push-action from 4 to 5
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4 to 5.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-12 21:54:17 +00:00
dependabot[bot] 143f4f2ff0
Bump docker/metadata-action from 4 to 5
Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 4 to 5.
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Upgrade guide](https://github.com/docker/metadata-action/blob/master/UPGRADE.md)
- [Commits](https://github.com/docker/metadata-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: docker/metadata-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-12 21:54:11 +00:00
dependabot[bot] bc90cf36d3
Bump docker/setup-buildx-action from 2 to 3
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-12 21:54:01 +00:00
dependabot[bot] 108712be3b
Bump docker/login-action from 2 to 3
Bumps [docker/login-action](https://github.com/docker/login-action) from 2 to 3.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-12 21:53:54 +00:00
dependabot[bot] c4a4d05e46
Bump docker/setup-qemu-action from 2 to 3
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 2 to 3.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-12 21:53:48 +00:00
Fredrik Öhrström 239a39de0e
Merge pull request #1025 from wmbusmeters/dependabot/github_actions/actions/checkout-4
Bump actions/checkout from 3 to 4
2023-09-05 14:40:32 +02:00
dependabot[bot] be3c413664
Bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-04 21:48:53 +00:00
Fredrik Öhrström 0b852fb420 Generate proper names for string fields depending on eg tariff_counter etc. 2023-08-27 22:18:27 +02:00
Fredrik Öhrström 9084a0323f Update tests to accomodate new json ordering of keys. 2023-08-27 21:36:17 +02:00
Fredrik Öhrström e577c0b30c Update tests to accomodate new json ordering of keys. 2023-08-27 21:10:18 +02:00
Fredrik Öhrström 71fe4b4392 Store numeric values based on name+unit instead of name+quantity. 2023-08-27 17:33:32 +02:00
Fredrik Öhrström 94d4ddce16 Migrate from post-process-print to pre-process-store then print store. 2023-08-27 16:48:40 +02:00
Fredrik Öhrström 86ba358c7d Adding more fields to abbb23 driver. 2023-08-27 08:52:27 +02:00
Fredrik Öhrström 906c288298 Add more fields to abbb23. 2023-08-26 20:08:47 +02:00
Fredrik Öhrström a920e25d45 Add new units for phase angle: deg rad. Add more fields to abbb23. 2023-08-26 17:05:52 +02:00
Fredrik Öhrström 414e55a17a Adding more fields to abbb23 driver. 2023-08-26 09:21:22 +02:00
Fredrik Öhrström 1faabb7526 Adding more fields to abbb23 driver. 2023-08-22 22:28:04 +02:00
Fredrik Öhrström a41bce1145 Accept +1 and +0 in comparison to help test pass on slow machines. 2023-08-16 21:56:50 +02:00
Fredrik Öhrström d0f9ffc820 Added test case for hydrodigit driver. 2023-08-16 21:37:06 +02:00
Fredrik Öhrström b8ac245aeb
Merge pull request #1013 from PovilasID/master
Adding: 0x17 version to 0x06 to hydrodigit device
2023-08-16 21:33:19 +02:00
Fredrik Öhrström b368647c73 Reset rtlwmbus pipeline if rtl_wmbus reports loss of flow of data. 2023-08-16 19:56:23 +02:00
Fredrik Öhrström 81505354fc Add correct option to rtl_wmbus for flow checking. 2023-08-16 18:07:34 +02:00
Fredrik Öhrström bd0747eefe Enable stderr output from rtl_sdr in --debug log and enable data flow check in rtl_wmbus to abort if incoming data stops flowing. 2023-08-16 16:22:01 +02:00
PovilasID c43b8da2bf
Adding: 0x17 version to 0x06 device 2023-08-10 16:31:46 +03:00
Fredrik Öhrström 765f38cdc4
Merge pull request #1005 from bordeux/master
Add support to Makefile for Darwin/MacOS platform
2023-07-31 11:15:32 +02:00
Chris Bednarczyk 1c960475ca Add support to Makefile for Darwin/MacOS platform 2023-07-30 20:03:02 +02:00
Chris Bednarczyk 95a4e15baa Add support to Makefile for Darwin/MacOS platform 2023-07-30 19:53:58 +02:00
Chris Bednarczyk f7b70e4c64 Add support to Makefile for Darwin/MacOS platform 2023-07-30 19:44:41 +02:00
Fredrik Öhrström 217f0a25fe Add another Itron water meter version. 2023-07-21 10:41:24 +02:00
Fredrik Öhrström ab9d612b63 Version 1.14.0 2023-07-02 2023-07-02 11:43:08 +02:00
Fredrik Öhrström 2bc88ba1bf Version 1.14.0-RC1 2023-07-02 2023-07-02 10:16:53 +02:00
Fredrik Öhrström b9e6f3f028 Update CHANGES and README. 2023-07-02 10:16:09 +02:00
Fredrik Öhrström a13104125a Added test case for topaseskr with negative flow. 2023-06-28 12:26:15 +02:00
Fredrik Öhrström b64c3e7ccd
Merge pull request #973 from cguedel/patch-1
[Topas ES KR] Handle negative values for flow
2023-06-28 12:06:52 +02:00
Fredrik Öhrström 1611f12753
Merge pull request #971 from stigger/qds_walkby
QDS walk-by: check length before attempting to parse the proprietary …
2023-06-28 12:06:31 +02:00
Fredrik Öhrström 876b5ce0af Adjust install script to create dirs before realpath. 2023-06-28 10:46:50 +02:00
Fredrik Öhrström c1be4b6c34
Merge pull request #974 from travnick/master
Stop installation script on error
2023-06-28 09:49:59 +02:00
Mikołaj Milej 77ad8410eb
Break instalation script on error 2023-06-05 11:44:28 +02:00
Christian Güdel c63cb1ef01
Handle negative values for flow 2023-06-04 22:07:33 +02:00
Vyacheslav Karpukhin 13d18ef711 QDS walk-by: check length before attempting to parse the proprietary fields 2023-06-01 02:55:18 +02:00
Fredrik Öhrström 53c589ed11 Added more fields to em24 driver. 2023-05-29 08:27:52 +02:00
Fredrik Öhrström 17791e5fb2 Fix nc test to run on computers without dns hostname. 2023-05-27 12:08:23 +02:00
Fredrik Öhrström f377ade8c7 Improve defines checks for support for listing ttys. 2023-05-27 11:49:25 +02:00
Fredrik Öhrström c85fd3691c Added another mfct/type/version combo to em42 driver and the power_kw field. 2023-05-26 08:27:05 +02:00
Fredrik Öhrström ccac483b1e Update CHANGES and README. 2023-05-23 15:06:05 +02:00
Fredrik Öhrström c14b7dd8f9 Fix test. 2023-05-23 14:42:33 +02:00
Fredrik Öhrström 14aded94ca
Merge pull request #963 from stigger/qds_walkby
Add partial support for proprietary Q walk-by telegrams (qheat, qwate…
2023-05-23 14:30:49 +02:00
Fredrik Öhrström f174e98423 Fix test. 2023-05-23 13:10:04 +02:00
Fredrik Öhrström 572d8f3a27
Merge pull request #968 from pvagner/patch1
lansenth driver: parse temperature as AutoSigned in order to see negative values
2023-05-23 12:55:34 +02:00
Peter Vágner f11e72cfdf Also interpret average temperature values as signed integers + add telegram output for testing 2023-05-23 09:34:26 +02:00
Peter Vágner 86c39e5570 lansenth driver: parse temperature as AutoSigned in order to see negative values 2023-05-22 15:41:46 +02:00
Fredrik Öhrström f26b56caff Add more fields to ultraheat driver and a new test case. 2023-05-20 13:03:19 +02:00
Fredrik Öhrström 247829d9a6
Merge pull request #966 from demetz/patch-1
consider negative values for flow and power
2023-05-20 12:45:43 +02:00
demetz d9476f114e
consider negative values for flow and power
flow can be negative
power can also be negative, for example if return temperature > supply temperature or flow is reversed
2023-05-20 12:39:41 +02:00
Vyacheslav Karpukhin 0a7f8a8e2b Add partial support for proprietary Q walk-by telegrams (qheat, qwater drivers) 2023-05-19 03:46:29 +02:00
Fredrik Öhrström 6a14bb8c77 Add testdriver for wme5. 2023-05-13 08:58:57 +02:00
Fredrik Öhrström f5e4606778 Add range check to aldreadyDecryptedCBC. 2023-05-12 21:32:40 +02:00
Fredrik Öhrström 205b5593a8 Print warning if decode of zero length telegram is attempted. 2023-05-12 21:05:36 +02:00
Fredrik Öhrström 006c88239f Restore proper register sizes for apator162. 2023-05-12 20:19:56 +02:00
Fredrik Öhrström 6fcdaca8ad Log the correct expected length when the length byte is wrong. 2023-05-12 19:58:08 +02:00
Fredrik Öhrström 2983957e32 Add warning when a telegram with a bad length byte is used. 2023-05-12 19:42:32 +02:00
Fredrik Öhrström f1858c028f Add new driver iwmtx5. 2023-05-12 11:08:28 +02:00
Fredrik Öhrström 3dd7c0c2c1 Remove unnecessary flags in new driver. 2023-05-12 10:54:29 +02:00
Fredrik Öhrström 217ab96f98
Merge pull request #956 from BIBOLV/master
Add file - driver_hcae2.cc
2023-05-12 10:52:27 +02:00
Fredrik Öhrström 39ed3d2a52 Reduce risk of slow test computer failing test. 2023-05-12 10:02:38 +02:00
Fredrik Öhrström 54012a0f30 Improve error reporting for failed registers. 2023-05-12 09:45:25 +02:00
Fredrik Öhrström 15aba2318f Add three more register sizes in the apator162 driver. 2023-05-12 09:28:41 +02:00
BIBO 4ce0834ac6
Add files via upload 2023-05-09 14:09:21 +03:00
Fredrik Öhrström acaf159f33 Check if installed netcat is the right version. Skip nc tests if not. 2023-05-08 20:09:40 +02:00
Fredrik Öhrström 88a811d434 Correct spelling errors. 2023-05-08 14:38:39 +02:00
Fredrik Öhrström b0bca78c78 Update copyright file. 2023-05-08 12:56:20 +02:00
Fredrik Öhrström 3fdd0fb4fe
Merge pull request #954 from BIBOLV/master
Delete repository.json
2023-05-07 18:15:16 +02:00
BIBOLV fd1d8daff9 Delete repository.json
Remove residual ha-addon file.
2023-05-07 18:49:30 +03:00
Fredrik Öhrström 262c731aca Update config.guess and deb build. 2023-05-07 17:21:38 +02:00
Fredrik Öhrström 14bf9868cc Update deb build. 2023-05-07 17:12:57 +02:00
Fredrik Öhrström 9afc8c85fd Version 1.13.1 2023-05-07 2023-05-07 12:35:42 +02:00
199 zmienionych plików z 24669 dodań i 4041 usunięć

Wyświetl plik

@ -7,12 +7,12 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- id: INSTALL_ADDITIONAL_BUILD_DEPENDENCIES
run: |
sudo apt install -y eatmydata
sudo eatmydata apt install -y devscripts debhelper
sudo eatmydata apt build-dep -y . || sudo eatmydata apt install -y librtlsdr-dev adduser
sudo eatmydata apt build-dep -y . || sudo eatmydata apt install -y librtlsdr-dev libxml2-dev libxslt1-dev adduser
- id: PREPARE_SOURCE
run: |
ln -s deb debian

Wyświetl plik

@ -8,56 +8,111 @@ on:
- '[0-9]+\.[0-9]+\.[0-9]+'
- '[0-9]+\.[0-9]+\.[0-9]+-RC[0-9]+'
env:
DOCKERHUB_IMAGE: ${{ github.repository }}
IMAGE_TAG: |
${{ github.ref_type == 'tag' && format('{0}-{1}', (contains(github.ref_name, '-RC') &&
'candidate' || 'release'), github.ref_name) || 'latest' }}
jobs:
docker:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm/v7
- linux/arm64
steps:
-
name: Prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
-
name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
-
name: Docker meta
id: meta
uses: docker/metadata-action@v4
uses: docker/metadata-action@v5
with:
images: wmbusmeters/wmbusmeters
tags: type=ref,event=tag
-
name: Set up QEMU
uses: docker/setup-qemu-action@v2
tags: |
${{ env.IMAGE_TAG }}
images: |
${{ env.DOCKERHUB_IMAGE }}
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
-
name: Login to DockerHub
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PAT }}
-
name: Build and push not tagged release
if: ${{ !steps.meta.outputs.tags }}
uses: docker/build-push-action@v4
name: Build and push
uses: docker/build-push-action@v5
id: docker_build
with:
context: docker/
platforms: linux/amd64,linux/arm64,linux/armhf
push: true
tags: wmbusmeters/wmbusmeters:latest
platforms: ${{ matrix.platform }}
provenance: false
outputs: |
type=image,name=${{ env.DOCKERHUB_IMAGE }},push-by-digest=true,name-canonical=true,push=true
-
name: Build and push candidate
if: ${{ steps.meta.outputs.tags && contains(steps.meta.outputs.tags, '-RC') }}
uses: docker/build-push-action@v4
with:
context: docker/
platforms: linux/amd64,linux/arm64,linux/armhf
push: true
tags: wmbusmeters/wmbusmeters:candidate-${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}
name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.docker_build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
-
name: Build and push tagged release
if: ${{ steps.meta.outputs.tags && !contains(steps.meta.outputs.tags, '-RC') }}
uses: docker/build-push-action@v4
name: Upload digest
uses: actions/upload-artifact@v4
with:
context: docker/
platforms: linux/amd64,linux/arm64,linux/armhf
push: true
tags: wmbusmeters/wmbusmeters:release-${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
runs-on: ubuntu-latest
needs:
- build
steps:
-
name: Download digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
tags: |
${{ env.IMAGE_TAG }}
images: |
${{ env.DOCKERHUB_IMAGE }}
-
name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PAT }}
-
name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.DOCKERHUB_IMAGE }}@sha256:%s ' *)
-
name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.DOCKERHUB_IMAGE }}:${{ steps.meta.outputs.version }}

Wyświetl plik

@ -7,7 +7,7 @@ jobs:
build:
runs-on: macOS-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- id: INSTALL_ADDITIONAL_BUILD_DEPENDENCIES
run: brew install librtlsdr libusb
- id: CONFIGURE

Wyświetl plik

@ -20,14 +20,14 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
-
name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
-
name: Docker meta
id: meta
uses: docker/metadata-action@v4
uses: docker/metadata-action@v5
with:
images: wmbusmeters/wmbusmeters
tags: type=ref,event=tag

Wyświetl plik

@ -7,11 +7,11 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- id: INSTALL_ADDITIONAL_BUILD_DEPENDENCIES
run: |
sudo apt install -y eatmydata
sudo eatmydata apt-get install librtlsdr-dev libusb-dev
sudo eatmydata apt-get install librtlsdr-dev libusb-dev libxml2-dev libxslt1-dev
- id: CONFIGURE
run: eatmydata ./configure
- id: MAKE

Wyświetl plik

@ -10,13 +10,13 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v8
- uses: actions/stale@v9
with:
stale-issue-message: 'This issue is stale because it has been open for 2 month with no activity. Remove stale label or comment or this will be closed in 1 month.'
close-issue-message: 'This issue was closed because it has been stalled for 1 month with no activity.'
days-before-stale: 60
days-before-close: 30
operations-per-run: 1000
exempt-issue-labels: 'enhancement, Work in progress, Planned'
exempt-issue-labels: 'enhancement, work in progress, planned, keep open'
days-before-pr-stale: -1
days-before-pr-close: -1

Wyświetl plik

@ -10,9 +10,9 @@ jobs:
dockerHubDescription:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Docker Hub Description
uses: peter-evans/dockerhub-description@v3
uses: peter-evans/dockerhub-description@v4
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PAT }}

Wyświetl plik

@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- run: git fetch --prune --unshallow
- name: Get wmbusmeters version
@ -28,7 +28,7 @@ jobs:
- name: Trigger build for edge release
if: ${{ github.ref_name == 'master' }}
uses: peter-evans/repository-dispatch@v2
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.HA_PAT }}
repository: wmbusmeters/wmbusmeters-ha-addon
@ -37,7 +37,7 @@ jobs:
- name: Trigger build for stable release
if: ${{ github.ref_name != 'master' }}
uses: peter-evans/repository-dispatch@v2
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.HA_PAT }}
repository: wmbusmeters/wmbusmeters-ha-addon

1
.gitignore vendored
Wyświetl plik

@ -6,6 +6,7 @@ packaging/
testaes/
testoutput/
tests_tmp/
3rdparty/
*~
config.log
autom4te.cache/

119
CHANGES
Wyświetl plik

@ -1,3 +1,122 @@
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.
Version 1.16.0 2024-02-22
New build to trigger proper docker versioning.
Version 1.15.0 2024-02-14
Version 1.15.0-RC2 2024-02-14
Update wmbusmeters-ha-addon with new dockerfile.
Version 1.15.0-RC1 2024-02-13
For the daemon you can now drop a driver file (such as iperl.xmq) in /etc/wmbusmeters.driver.d
and it will automatically be used (overriding any builtin iperl driver).
From the command line you can also load a driver file with --driver=file.xmq
or load a whole directory with --driverdir=/drivers or in a tuple just use
a file name ending with xmq. E.g. "Water driver.xmq 12345678 NOKEY"
The two first builtin text drivers are elster and iperl.
ATTENTION! Wmbusmeters now use new -f option when starting rtl_wmbus. There is a
warning if rtl_wmbus does not support the -f option and an upgrade is recommended.
This option will cause rtl_wmbus to exit with an error if the rtl_sdr dongle stops sending data.
This in turn will cause wmbusmeters to restart the pipeline.
Up till now, the stderr from rtl_sdr has been sent to /dev/null. This is a problem
since we cannot see any errors from rtl_sdr that could have caused it to stall.
However the reason for /dev/null was this bug in rtl_sdr.
https://github.com/osmocom/rtl-sdr/commit/142325a93c6ad70f851f43434acfdf75e12dfe03
which prevented us from sending the rtl_sdr stderr to wmbusmeters.
If we did, rtl_sdr went into a 100% cpu hang when we restarted a wmbusmeters daemon.
A temporary workaround has been found that both sends the stderr output to wmbusmeters
and permits the restart of the daemon. Stderr from rtl_sdr is now sent to
/tmp/tmp.XXXXXXX_wmbusmeters_rtlsdr and then tailed into wmbusmeters.
This is a temporary solution until the real rtl_sdr bugfix has propagated into enough distributions.
Add second extension energy MWh VIF 7b00-7b01.
Sunflowerenergias improved the iwmtx5 driver! Thanks Sunflowerenergias!
Jacman777 improved the kamheat driver! Thanks Jacman777!
Pim added a --metershell setting which will invoke a shell command line
when a meter is seen for the first time. This can be used to trigger extra
commands in HA and other systems, to add the new meter. Thanks Pim!
Pim added support for the Lansen repeater which sends its own status messages!
Pim also fixed a small typo in the human readable date timestamp format!
Thanks Pim!
ATTENTION! The hydrus driver could report the wrong value for total_at_date_m3
if an at_date had not been reached yet. This is fixed.
Added initial support for drivers that can be loaded from config files.
Properly receive telegrams from amb8465 which is in command mode.
Chris Bednarczyk improved the build process for Darwin/MacOS platform. Thanks Chris!
PovilasID added another Hydrodigit version. Thanks PovilasID!
Added new units for phase angle: deg rad.
Added more fields to the abbb23.
Version 1.14.0 2023-07-02
Version 1.14.0-RC1 2023-07-02
Added more fields to em24 driver.
Added another mfct/type/version combo to em42 driver and the power_kw field.
Mikołaj Milej imporved the installation script! Thanks Mikołaj!
Christian Güdel improved the topaseskr driver to consider negative flows. Thanks Christian!
Peter Vágner improved the lansenth driver to consider negative temperatures. Thanks Peter!
Dennis Metz improved the ultraheat driver to consider negative flow and temperatures. Thanks Dennis!
Bibo added support for the hcae2 driver. Thanks Bibo!
Improve error messages when telegrams with bad length byte are read.
Improve the apator162 driver.
Added the iwmtx5 driver.
Vyacheslav Karpukhin improved the qheat driver to decode proprietary format telegrams. Thanks Vyacheslav!
pvagner improved the lansenth driver to handle negative values. Thanks pvagner!
demetz imporproved ultraheat driver to handle negative values. Thanks demetz!
Version 1.13.1 2023-05-07
Version 1.13.1-RC1 2023-05-07
Fix make install to not trigger a new build.

Wyświetl plik

@ -1,4 +1,4 @@
# Copyright (C) 2017-2022 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
@ -138,16 +138,27 @@ ifeq ($(shell uname -s),FreeBSD)
USBLIB = -lusb
endif
ifeq ($(shell uname -s),Darwin)
CXXFLAGS += -I$(shell brew --prefix)/include
LDFLAGS += -L$(shell brew --prefix)/lib
endif
$(BUILD)/%.o: src/%.cc $(wildcard src/%.h)
$(CXX) $(CXXFLAGS) $< -c -E > $@.src
$(CXX) $(CXXFLAGS) $< -MMD -c -o $@
$(BUILD)/%.o: src/%.c $(wildcard src/%.h)
$(CXX) -I/usr/include/libxml2 $(CXXFLAGS) $< -c -E > $@.src
$(CXX) -I/usr/include/libxml2 -fpermissive $(CXXFLAGS) $< -MMD -c -o $@
PROG_OBJS:=\
$(BUILD)/address.o \
$(BUILD)/aes.o \
$(BUILD)/aescmac.o \
$(BUILD)/bus.o \
$(BUILD)/cmdline.o \
$(BUILD)/config.o \
$(BUILD)/drivers.o \
$(BUILD)/dvparser.o \
$(BUILD)/formula.o \
$(BUILD)/mbus_rawtty.o \
@ -173,6 +184,7 @@ PROG_OBJS:=\
$(BUILD)/wmbus_rawtty.o \
$(BUILD)/wmbus_rc1180.o \
$(BUILD)/wmbus_utils.o \
$(BUILD)/xmq.o \
$(BUILD)/lora_iu880b.o \
# If you run: "make DRIVER=minomess" then only driver_minomess.cc will be compiled into wmbusmeters.
@ -182,33 +194,13 @@ ifeq ($(DRIVER),)
DRIVER_OBJS:=$(wildcard src/meter_*.cc) $(wildcard src/driver_*.cc)
else
$(info Building a single driver $(DRIVER))
DRIVER_OBJS:=src/driver_auto.cc src/driver_unknown.cc $(wildcard src/meter_*.cc) src/driver_$(DRIVER).cc
DRIVER_OBJS:=src/driver_auto.cc src/driver_unknown.cc src/driver_dynamic.cc $(wildcard src/meter_*.cc) src/driver_$(DRIVER).cc
endif
DRIVER_OBJS:=$(patsubst src/%.cc,$(BUILD)/%.o,$(DRIVER_OBJS))
all: $(BUILD)/wmbusmeters $(BUILD)/wmbusmetersd $(BUILD)/wmbusmeters.g $(BUILD)/testinternals
deb_release:
@if [ "$(RELEASE)" = "" ] ; then echo "Usage: make deb RELEASE=1.2.3" ; exit 1 ; fi
@if [ "$$(cat deb/changelog | grep wmbusmeters\ \( | grep -o $(RELEASE))" != "$(RELEASE)" ]; then \
echo "Changelog not updated with this release! It says:" ; \
head -n 1 deb/changelog ; \
exit 1 ; \
fi
@rm -rf packaging
@mkdir -p packaging
@echo "Checking out tag $(RELEASE)..."
@(cd packaging ; git clone $(PWD) wmbusmeters-$(RELEASE) ; cd wmbusmeters-$(RELEASE) ; git -c advice.detachedHead=false checkout tags/$(RELEASE) )
@(cd packaging/wmbusmeters-$(RELEASE) ; git show -s --format=%ct > ../release_date )
@echo "Removing git history..."
@(cd packaging ; rm -rf wmbusmeters-$(RELEASE)/.git )
@echo "Setting file timestamps to commit date..."
@(cd packaging ; export UT=$$(cat ./release_date) ; find . -exec touch -d "@$$UT" \{\} \; )
@echo "Creating orig archive..."
@(cd packaging ; tar czf ./wmbusmeters_$(RELEASE).orig.tar.gz wmbusmeters-$(RELEASE) )
@echo "Running debbuild..."
@(cd packaging/wmbusmeters-$(RELEASE) ; cp -a deb debian; debuild )
# Create a local binary only package.
deb_local:
@rm -rf packaging
@mkdir -p packaging
@ -270,7 +262,7 @@ $(BUILD)/authors.h:
# Build binary with debug information. ~15M size binary.
$(BUILD)/wmbusmeters.g: $(PROG_OBJS) $(DRIVER_OBJS) $(BUILD)/main.o $(BUILD)/short_manual.h
$(CXX) -o $(BUILD)/wmbusmeters.g $(PROG_OBJS) $(DRIVER_OBJS) $(BUILD)/main.o $(LDFLAGS) -lrtlsdr $(USBLIB) -lpthread
$(CXX) -o $(BUILD)/wmbusmeters.g $(PROG_OBJS) $(DRIVER_OBJS) $(BUILD)/main.o $(LDFLAGS) -lrtlsdr -lxml2 $(USBLIB) -lpthread
# Production build will have debug information stripped. ~1.5M size binary.
# DEBUG=true builds, which has address sanitizer code, will always keep the debug information.
@ -293,10 +285,10 @@ testinternals: $(BUILD)/testinternals
$(BUILD)/testinternals.o: $(PROG_OBJS) $(DRIVER_OBJS) $(wildcard src/*.h)
$(BUILD)/testinternals: $(BUILD)/testinternals.o
$(CXX) -o $(BUILD)/testinternals $(PROG_OBJS) $(DRIVER_OBJS) $(BUILD)/testinternals.o $(LDFLAGS) -lrtlsdr $(USBLIB) -lpthread
$(CXX) -o $(BUILD)/testinternals $(PROG_OBJS) $(DRIVER_OBJS) $(BUILD)/testinternals.o $(LDFLAGS) -lrtlsdr -lxml2 $(USBLIB) -lpthread
$(BUILD)/fuzz: $(PROG_OBJS) $(DRIVER_OBJS) $(BUILD)/fuzz.o
$(CXX) -o $(BUILD)/fuzz $(PROG_OBJS) $(DRIVER_OBJS) $(BUILD)/fuzz.o $(LDFLAGS) -lrtlsdr -lpthread
$(CXX) -o $(BUILD)/fuzz $(PROG_OBJS) $(DRIVER_OBJS) $(BUILD)/fuzz.o $(LDFLAGS) -lrtlsdr -lxml2 -lpthread
clean_executables:
rm -rf build/wmbusmeters* build_arm/wmbusmeters* build_debug/wmbusmeters* build_arm_debug/wmbusmeters* *~
@ -333,16 +325,16 @@ lcov:
(cd build_debug; genhtml lcov.info)
xdg-open build_debug/src/index.html
test:
test: build/xmq
@./test.sh build/wmbusmeters
testd:
testd: build/xmq
@./test.sh build_debug/wmbusmeters
testdriver:
testdriver: build/xmq
@./tests/test_drivers.sh build/wmbusmeters driver_${DRIVER}.cc
testdriverd:
testdriverd: build/xmq
@./tests/test_drivers.sh build_debug/wmbusmeters driver_${DRIVER}.cc
update_manufacturers:
@ -461,6 +453,15 @@ deploy:
collect_copyrights:
./scripts/collect_copyrights.sh deb/copyright
3rdparty/xmq/build/default/release/xmq: $(wildcard 3rdparty/xmq/src/main/c/* 3rdparty/xmq/src/main/c/parts/*)
@mkdir -p 3rdparty
@(cd 3rdparty; git clone --depth 1 https://github.com/libxmq/xmq.git; cd xmq; ./configure)
@cat 3rdparty/xmq/build/default/spec.mk
@if [ "$$(cat 3rdparty/xmq/build/default/spec.mk | grep CC)" = "CC:=gcc" ]; then (cd 3rdparty/xmq; make VERBOSE=) ; else rm -f $@ ; mkdir -p $$(dirname $@); touch $@ ; echo "Could not build xmq." ; fi
build/xmq: 3rdparty/xmq/build/default/release/xmq
@cp $< $@
# Include dependency information generated by gcc in a previous compile.
include $(wildcard $(patsubst %.o,%.d,$(PROG_OBJS) $(DRIVER_OBJS)))

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.
@ -64,6 +91,11 @@ wmbus dongles when wmbusmeters startup.
If the serial device (ttyUSB0) might change you can also use `device=im871a:c1,t1`
which will probe all serial devices but only scans for im871a which also speeds it up.
Note that the rtl-sdr devices are not found under the tty devices (e.g. `/dev/tty...`).
Instead the rtl-sdr devices are accessed through character device special files named `/dev/swradio0` to `/dev/swradio255`[^kernel_docs_sdr]. Wmbusmeters uses librtsldr to probe these devices.
[^kernel_docs_sdr]: https://docs.kernel.org/userspace-api/media/v4l/dev-sdr.html?highlight=sdr#software-defined-radio-interface-sdr
If you have to scan serial devices, then remember that some Raspberry PIs are upset when
random data is sent to `/dev/ttyAMA0` when it is configured in bluetooth mode.
To solve this, add `donotprobe=/dev/ttyAMA0`
@ -125,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
@ -168,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
```
@ -212,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
@ -390,7 +430,7 @@ depending on if you are running as a daemon or not.
# Running without config files, good for experimentation and test.
```
wmbusmeters version: 1.13.0
wmbusmeters version: 1.15.0
Usage: wmbusmeters {options} [device] { [meter_name] [meter_driver] [meter_id] [meter_key] }*
wmbusmeters {options} [hex] { [meter_name] [meter_driver] [meter_id] [meter_key] }*
wmbusmetersd {options} [pid_file]
@ -409,9 +449,12 @@ As {options} you can use:
--calculate_flow_f=flow_temperature_c
--debug for a lot of information
--donotprobe=<tty> do not auto-probe this tty. Use multiple times for several ttys or specify "all" for all ttys.
--driver=<file> load a driver
--driversdir=<dir> load all drivers in dir
--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
@ -430,6 +473,7 @@ As {options} you can use:
--meterfilesnaming=(name|id|name-id) the meter file is the meter's: name, id or name-id
--meterfilestimestamp=(never|day|hour|minute|micros) the meter file is suffixed with a
timestamp (localtime) with the given resolution.
--metershell=<cmdline> invokes cmdline with env variables the first time a meter is seen since startup
--nodeviceexit if no wmbus devices are found, then exit immediately
--normal for normal logging
--oneshot wait for an update from each meter, then quit
@ -473,10 +517,24 @@ These telegrams are expected to have the data link layer crc bytes removed alrea
`MAIN=/dev/ttyUSB0:mbus:2400`, assume ttyUSB0 is an serial to mbus-master converter. The speed is set to 2400 bps.
`rtlwmbus`, to spawn the background process: `rtl_sdr -f 868.625M -s 1600000 - 2>/dev/null | rtl_wmbus -s`
`rtlwmbus`, to spawn the background process: `rtl_sdr -f 868.625M -s 1600000 - 2>/dev/null | rtl_wmbus -f -s`
for each attached rtlsdr dongle. This will listen to S1,T1 and C1 meters in parallel.
Note that this uses a noticeable amount of CPU time by rtl_wmbus.
For the moment, it is necessary to send the stderr to a file (/dev/null) because of a bug:
https://github.com/osmocom/rtl-sdr/commit/142325a93c6ad70f851f43434acfdf75e12dfe03
Until this bug fix has propagated into Debian/Fedora etc, wmbusmeters uses a tmp file
to see the stderr output from rtl_sdr. This tmp file is created in /tmp and will
generate 420 bytes of data once ever 23 hours.
The current command line used by wmbusmeters to start the rtl_wmbus pipeline is therefore a bit longer:
```
ERRFILE=$(mktemp --suffix=_wmbusmeters_rtlsdr) ;
echo ERRFILE=$ERRFILE ; date -Iseconds > $ERRFILE ;
tail -f $ERRFILE & /usr/bin/rtl_sdr -d 0 -f 868.625M -s 1.6e6 - 2>>$ERRFILE | /usr/bin/rtl_wmbus -s -f
```
Note that the standard -s option uses a noticeable amount of CPU time by rtl_wmbus.
You can therefore use a tailored rtl_wmbus command that is more suitable for your needs.
`rtlwmbus:CMD(<command line>)`, to specify the entire background
@ -486,9 +544,10 @@ The command line cannot contain parentheses.
Likewise for rtl433.
Here is an example command line that reduces the rtl_wmbus CPU usage if you only need T1/C1 telegrams.
It disable S1 decoding (`-p s`) and trades lower cpu usage for reception performance (`-a`):
It disable S1 decoding (`-p s`) and trades lower cpu usage for reception performance (`-a`).
You should always add the `-f` option to enable detection if rtl_sdr has stalled:
`rtlwmbus:CMD(rtl_sdr -f 868.95M -s 1600000 - 2>/dev/null | rtl_wmbus -p s -a)`
`rtlwmbus:CMD(rtl_sdr -f 868.95M -s 1600000 - 2>/dev/null | rtl_wmbus -p s -a -f)`
`rtlwmbus(ppm=17)`, to tune your rtlsdr dongle accordingly.
Use this to tune your dongle and at the same time listen to S1,T1 and C1.
@ -552,6 +611,7 @@ Apator Ultrimis (ultrimis)
Aquametro/Integra Topas Es Kr (topaseskr)
Axioma W1 (q400)
Bmeters Hydrodigit (hydrodigit) (partly non-standard protocol)
Bmeters GSD8-I with IWM-TX5 module (iwmtx5)
Diehl/Sappel IZAR RC 868 I R4 PL and R3 (izar) (non-standard protocol)
Diehl HYDRUS (hydrus)
Diehl IZAR RC I G4 (dme_07)
@ -574,6 +634,7 @@ Zenner Minomess (minomess)
Supported heat cost allocators:
Apator E-ITN 30.51 (apatoreitn)
Engelmann HCA e2 (hcae2)
Innotas EurisII (eurisii)
Qundis Q caloric (qcaloric)
Sontex 868 (sontex868)
@ -789,12 +850,12 @@ wmbusmeters --format=json --meterfiles /dev/ttyUSB0:im871a:c1 MyTapWater multica
# Using wmbusmeters in a pipe
```shell
rtl_sdr -f 868.625M -s 1600000 - 2>/dev/null | rtl_wmbus -s | wmbusmeters --format=json stdin:rtlwmbus MyMeter auto 12345678 NOKEY | ...more processing...
rtl_sdr -f 868.625M -s 1600000 - 2>/dev/null | rtl_wmbus -f -s | wmbusmeters --format=json stdin:rtlwmbus MyMeter auto 12345678 NOKEY | ...more processing...
```
Or you can send rtl_wmbus formatted telegrams using nc over UDP to wmbusmeters.
```shell
rtl_sdr -f 868.95M -s 1600000 - 2>/dev/null | rtl_wmbus -p s -a | nc -u localhost 4444
rtl_sdr -f 868.95M -s 1600000 - 2>/dev/null | rtl_wmbus -f -p s -a | nc -u localhost 4444
```
And receive the telegrams with nc spawned by wmbusmeters.
@ -807,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,

1500
autoconf/config.guess vendored

Plik diff jest za duży Load Diff

2855
autoconf/config.sub vendored

Plik diff jest za duży Load Diff

47
configure vendored
Wyświetl plik

@ -2969,6 +2969,53 @@ else $as_nop
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for xmlFreeDoc in -lxml2" >&5
printf %s "checking for xmlFreeDoc in -lxml2... " >&6; }
if test ${ac_cv_lib_xml2_xmlFreeDoc+y}
then :
printf %s "(cached) " >&6
else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lxml2 $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
namespace conftest {
extern "C" int xmlFreeDoc ();
}
int
main (void)
{
return conftest::xmlFreeDoc ();
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_link "$LINENO"
then :
ac_cv_lib_xml2_xmlFreeDoc=yes
else $as_nop
ac_cv_lib_xml2_xmlFreeDoc=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xml2_xmlFreeDoc" >&5
printf "%s\n" "$ac_cv_lib_xml2_xmlFreeDoc" >&6; }
if test "x$ac_cv_lib_xml2_xmlFreeDoc" = xyes
then :
printf "%s\n" "#define HAVE_LIBXML2 1" >>confdefs.h
LIBS="-lxml2 $LIBS"
else $as_nop
as_fn_error $? "Could not find libxml2 library. Try: sudo apt install libxml2-dev" "$LINENO" 5
fi
ac_config_files="$ac_config_files $OUTPUT_ROOT/spec.gmk:$SRC_ROOT/autoconf/spec.gmk.in"
ac_config_files="$ac_config_files $OUTPUT_ROOT/Makefile:$SRC_ROOT/autoconf/Makefile.in"

Wyświetl plik

@ -53,6 +53,11 @@ AC_CHECK_LIB(rtlsdr, rtlsdr_get_device_count, [],
AC_MSG_ERROR([Could not find rtlsdr library. Try: sudo apt install librtlsdr-dev])
])
AC_CHECK_LIB(xml2, xmlFreeDoc, [],
[
AC_MSG_ERROR([Could not find libxml2 library. Try: sudo apt install libxml2-dev])
])
AC_CONFIG_FILES([$OUTPUT_ROOT/spec.gmk:$SRC_ROOT/autoconf/spec.gmk.in])
AC_CONFIG_FILES([$OUTPUT_ROOT/Makefile:$SRC_ROOT/autoconf/Makefile.in])

Wyświetl plik

@ -1,6 +1,5 @@
wmbusmeters (1.10.2-1) unstable; urgency=medium
wmbusmeters (0.0.0-1) unstable; urgency=medium
* First package upload (Closes: #998721).
* Upload sponsored by Petter Reinholdtsen.
* Test build
-- Fredrik Öhrström <oehrstroem@gmail.com> Sat, 26 Jun 2021 12:39:00 +0100
-- No User <nouser@nowhere.zzz> Sat, 26 Jun 2021 12:39:00 +0100

Wyświetl plik

@ -15,6 +15,11 @@ Files: src/aes.h
Copyright: 2019 kokke
License: CC0
Files: src/driver_apatoreitn.cc
Copyright: 2023 Fredrik Öhrström
2022 Kajetan Krykwiński
License: GPL-3+
Files: src/driver_emerlin868.cc
Copyright: 2022 Fredrik Öhrström
2018 David Mallon
@ -25,25 +30,26 @@ Copyright: 2022 Fredrik Öhrström
2018 David Mallon
License: GPL-3+
Files: src/driver_iperl.cc
Files: src/driver_hydrus.cc
Copyright: 2023 Fredrik Öhrström
2021 Vincent Privat
License: GPL-3+
Files: src/driver_izar.cc
Copyright: 2019 Jacek Tomasiak
2023 Fredrik Öhrström
2021 Vincent Privat
License: GPL-3+
Files: src/driver_kamheat.cc
Copyright: 2022 Fredrik Öhrström
2018 David Mallon
2020 Eric Bus
2022 thecem
License: GPL-3+
Files: src/driver_minomess.cc
Copyright: 2021 Olli Salonen
2022 Fredrik Öhrström
License: GPL-3+
Files: src/driver_multical303.cc
Copyright: 2022 thecem
2022 Fredrik Öhrström
License: GPL-3+
Files: src/driver_multical603.cc
Copyright: 2022 Fredrik Öhrström
2020 Eric Bus
2022 thecem
2023 Fredrik Öhrström
License: GPL-3+
Files: src/driver_sensostar.cc
@ -61,6 +67,11 @@ Copyright: 2021 Vincent Privat
2022 Fredrik Öhrström
License: GPL-3+
Files: src/driver_topaseskr.cc
Copyright: 2022 Fredrik Öhrström
2020 Avandorp
License: GPL-3+
Files: src/manufacturer_specificities.cc
Copyright: 2019 Jacek Tomasiak
2021 Vincent Privat
@ -71,38 +82,6 @@ Copyright: 2019 Jacek Tomasiak
2021 Vincent Privat
License: GPL-3+
Files: src/meter_hydrus.cc
Copyright: 2020 Fredrik Öhrström
2021 Vincent Privat
License: GPL-3+
Files: src/meter_izar.cc
Copyright: 2019 Jacek Tomasiak
2020 Fredrik Öhrström
2021 Vincent Privat
License: GPL-3+
Files: src/meter_multical403.cc
Copyright: 2020 Fredrik Öhrström
2020 Eric Bus
License: GPL-3+
Files: src/meter_multical602.cc
Copyright: 2021 Fredrik Öhrström
2020 Eric Bus
License: GPL-3+
Files: src/meter_multical803.cc
Copyright: 2020 Fredrik Öhrström
2020 Eric Bus
2020 Nikodem Jędrzejczak
License: GPL-3+
Files: src/meter_topaseskr.cc
Copyright: 2020 Fredrik Öhrström
2020 Avandorp
License: GPL-3+
Files: src/sha256.cc
Copyright: 2013 Tom St Denis <tomstdenis@gmail.com>
2013 WaterJuice <waterjuice.org>
@ -122,6 +101,25 @@ License: GPL-3+
On Debian systems, the complete text of the GNU General Public License
version 3 can be found in file "/usr/share/common-licenses/GPL-3".
License: MIT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
License: CC0
The authors, and therefore would be copyright holders, have as much
as possible relinguished their copyright to the public domain.

Wyświetl plik

@ -15,3 +15,10 @@ export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
%:
dh $@
LPAR=(
RPAR=)
CHANGELOG_RELEASE=$(shell cat debian/changelog | head -n 1 | grep -o '$(LPAR).*$(RPAR)' | tr -d '$(LPAR)$(RPAR)' )
override_dh_auto_build:
$(MAKE) COMMIT_HASH= TAG=$(CHANGELOG_RELEASE) BRANCH= CHANGES=

Wyświetl plik

@ -1 +1 @@
3.0 (quilt)
1.0

Wyświetl plik

@ -1,22 +1,41 @@
FROM multiarch/alpine:${TARGETARCH}${TARGETVARIANT}-latest-stable AS build
RUN apk add --no-cache alpine-sdk gcc linux-headers librtlsdr-dev cmake libusb-dev bash
RUN git clone https://github.com/wmbusmeters/wmbusmeters.git && \
FROM alpine AS build
RUN apk add --no-cache alpine-sdk gcc linux-headers libxml2-dev cmake libusb-dev bash samurai
ADD https://api.github.com/repos/wmbusmeters/wmbusmeters/git/refs/heads/master version.json
RUN git clone https://github.com/steve-m/librtlsdr.git && \
git clone https://github.com/wmbusmeters/wmbusmeters.git && \
git clone https://github.com/weetmuts/rtl-wmbus.git && \
git clone https://github.com/merbanan/rtl_433.git
git clone https://github.com/merbanan/rtl_433.git && \
git clone https://github.com/ED6E0F17/rtl_reset.git
WORKDIR /librtlsdr
RUN cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=MinSizeRel \
-DCMAKE_INSTALL_PREFIX:PATH=/usr \
-DDETACH_KERNEL_DRIVER=ON \
-Wno-dev && \
cmake --build build && \
cmake --install build
WORKDIR /wmbusmeters
RUN make
WORKDIR /rtl-wmbus
RUN make release && chmod 755 build/rtl_wmbus
WORKDIR /rtl_433
RUN mkdir build && cd build && cmake ../ && make
RUN cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=MinSizeRel && \
cmake --build build
WORKDIR /rtl_reset
RUN make
FROM multiarch/alpine:${TARGETARCH}${TARGETVARIANT}-latest-stable as scratch
ENV QEMU_EXECVE=1
RUN apk add --no-cache mosquitto-clients libstdc++ curl libusb rtl-sdr netcat-openbsd
FROM alpine as scratch
RUN apk add --no-cache mosquitto-clients libstdc++ curl libusb libxml2 netcat-openbsd
WORKDIR /wmbusmeters
COPY --from=build /librtlsdr/build/src/librtlsdr.so.* /usr/lib/
COPY --from=build /librtlsdr/rtl-sdr.rules /usr/lib/udev/rules.d/rtl-sdr.rules
COPY --from=build /librtlsdr/build/src/rtl_* /usr/bin/
COPY --from=build /wmbusmeters/build/wmbusmeters /wmbusmeters/wmbusmeters
COPY --from=build /rtl-wmbus/build/rtl_wmbus /usr/bin/rtl_wmbus
COPY --from=build /rtl_433/build/src/rtl_433 /usr/bin/rtl_433
COPY --from=build /rtl_reset/rtl_reset /usr/bin/rtl_reset
COPY --from=build /wmbusmeters/docker/docker-entrypoint.sh /wmbusmeters/docker-entrypoint.sh
VOLUME /wmbusmeters_data/
CMD ["sh", "/wmbusmeters/docker-entrypoint.sh"]
CMD ["sh", "/wmbusmeters/docker-entrypoint.sh"]

Wyświetl plik

@ -44,19 +44,22 @@ do
esac
done
SRC=$SRC ROOT=$ROOT /bin/sh ./scripts/install_binaries.sh
SRC=$SRC ROOT=$ROOT /bin/sh ./scripts/install_binaries.sh || exit $?
ROOT=$ROOT /bin/sh ./scripts/install_manpage.sh
ROOT=$ROOT /bin/sh ./scripts/install_manpage.sh || exit $?
if [ "$ADDUSER" = "true" ]
then
ROOT=$ROOT /bin/sh ./scripts/add_wmbusmeters_user.sh
ROOT=$ROOT /bin/sh ./scripts/add_wmbusmeters_user.sh || exit $?
fi
ROOT=$ROOT /bin/sh ./scripts/prepare_logfiles.sh
ROOT=$ROOT /bin/sh ./scripts/prepare_logfiles.sh || exit $?
ROOT=$ROOT /bin/sh ./scripts/install_default_configuration.sh
ROOT=$ROOT /bin/sh ./scripts/install_default_configuration.sh || exit $?
ROOT=$ROOT /bin/sh ./scripts/install_systemd_service.sh
ROOT=$ROOT /bin/sh ./scripts/install_systemd_service.sh || exit $?
ROOT=$ROOT /bin/sh ./scripts/add_myself_to_dialout.sh
ROOT=$ROOT /bin/sh ./scripts/add_myself_to_dialout.sh || exit $?
echo
echo "wmbusmeters sucessfully installed."

Wyświetl plik

@ -1,5 +0,0 @@
{
"name": "Wmbusmeters",
"url": "https://github.com/weetmuts/wmbusmeters/",
"maintainer": "weetmuts"
}

Wyświetl plik

@ -44,6 +44,9 @@ do
elif grep -q -i "CC0" $f
then
license="CC0"
elif grep -q -i "MIT" $f
then
license="MIT"
else
echo "Unknown license in file: "+$f
exit 1
@ -70,6 +73,25 @@ License: GPL-3+
On Debian systems, the complete text of the GNU General Public License
version 3 can be found in file "/usr/share/common-licenses/GPL-3".
License: MIT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
License: CC0
The authors, and therefore would be copyright holders, have as much
as possible relinguished their copyright to the public domain.

Wyświetl plik

@ -13,7 +13,7 @@ then
exit 1
fi
(cd src; grep -Eo "Copyright \(C\) (....-)?.... [^\(]+ \(.+\)" * | cut -f 2 -d ':' | tr -s ' ' | sed 's/(C) \([0-9][0-9][0-9][0-9]\) /(C) \1-\1 /' > $TMP)
(cd src; grep -Eo ".*Copyright \(C\) (....-)?.... [^\(]+ \(.+\)" * | cut -f 2 -d ':' | tr -s ' ' | sed 's/(C) \([0-9][0-9][0-9][0-9]\) /(C) \1-\1 /' > $TMP)
echo 'R"AUTHORS(' > $OUT

Wyświetl plik

@ -1,10 +1,26 @@
# Copyright (C) 2021-2023 Fredrik Öhrström (gpl-3.0-or-later)
rm -f "$ROOT"/usr/bin/wmbusmeters "$ROOT"/usr/sbin/wmbusmetersd
mkdir -p "$ROOT"/usr/bin
mkdir -p "$ROOT"/usr/sbin
cp "$SRC" "$ROOT"/usr/bin/wmbusmeters
# Command binary /usr/bin/wmbusmeters
wmbusmeters_dir="${ROOT}/usr/bin"
wmbusmeters_path="${wmbusmeters_dir}/wmbusmeters"
(cd "$ROOT"/usr/sbin; ln -s ../bin/wmbusmeters wmbusmetersd)
# Daemon /usr/sbin/wmbusmetersd which is a symlink to the command binary.
wmbusmetersd_dir="${ROOT}/usr/sbin"
wmbusmetersd_path="${wmbusmetersd_dir}/wmbusmetersd"
echo "binaries: installed $ROOT/usr/bin/wmbusmeters $ROOT/usr/sbin/wmbusmetersd"
# Remove any existing installed components.
rm -f "$wmbusmeters_path" "$wmbusmetersd_path" || exit $?
# Install the command binary and create the bin directory if necessary.
install -D -m 755 "$SRC" "$wmbusmeters_path" || exit $?
# Create the sbin directory if necessary.
mkdir -p "$wmbusmetersd_dir" || exit $?
# Calculate the relative symlink from sbin to bin.
wmbusmetersd_target="$(realpath -s --relative-to="${wmbusmetersd_dir}" "${wmbusmeters_path}")"
# Create the actual link.
ln -s "$wmbusmetersd_target" "$wmbusmetersd_path" || exit $?
echo "binaries: installed ${wmbusmeters_path} ${wmbusmetersd_path}"

Wyświetl plik

@ -50,3 +50,18 @@ then
else
echo "conf dir: $ROOT/etc/wmbusmeters.d unchanged"
fi
####################################################################
##
## Create /etc/wmbusmeters.drivers.d
##
if [ ! -d "$ROOT"/etc/wmbusmeters.drivers.d ]
then
# Create the drivers directory
mkdir -p "$ROOT"/etc/wmbusmeters.drivers.d
chmod -R 755 "$ROOT"/etc/wmbusmeters.drivers.d
echo "conf dir: created $ROOT/etc/wmbusmeters.drivers.d"
else
echo "conf dir: $ROOT/etc/wmbusmeters.drivers.d unchanged"
fi

Wyświetl plik

@ -44,6 +44,7 @@ then
postrotate
/bin/kill -HUP \`cat /run/wmbusmeters/wmbusmeters.pid 2> /dev/null\` 2> /dev/null || true
endscript
}
EOF
echo "logrotate: created $ROOT/etc/logrotate.d/wmbusmeters"
else

Wyświetl plik

@ -60,3 +60,13 @@ telegram=|6E4401062020202705077A3D0060852F2F|0F|151794|94|0A0200|43|0403|81|D87F
telegram=|3E4401061405410305077A190030852F2F|0F|86B4B8|95|290200|40|C6C1|B4|F0F3F3|41|5559|42|FA701000|F0|01010000|10|BC780000|FFFFFFFFFFFFFFFFFFFFFF2483|
{"media":"water","meter":"apator162","name":"MyTapWaterf","id":"03410514","total_m3":30.908,"timestamp":"1111-11-11T11:11:11Z"}
|MyTapWaterf;03410514;30.908;1111-11-11 11:11.11
# Yet another
telegram=|3C4401061111441105077A280030852F2F|0F|064CB597180200|43|A0068300055A2D69610156BB0C101B1208007101A60AC5AA6DE6A5F0880E9ADD08393C|
{"id": "11441111", "media": "water", "meter": "apator162", "name": "MyTapWaterg", "timestamp": "1111-11-11T11:11:11Z", "total_m3": 528.923}
|MyTapWaterg;11441111;528.923;1111-11-11 11:11.11
# Yet another
telegram=|3E4401060403820305077A090030852F2F0F9B5B229700000044C2DED310A25500007201C64A0000853C000094310000A0464B1904FFFFFFFFFFFFFFFF2ED6|
{"id": "03820304", "media": "water", "meter": "apator162", "name": "MyTapWaterh", "timestamp": "1111-11-11T11:11:11Z", "total_m3": 21.922 }
|MyTapWaterh;03820304;21.922;1111-11-11 11:11.11

Wyświetl plik

@ -55,4 +55,4 @@ telegram=|494468509494949495377286868686A85CFE07A90030052F2F_0413100000000F52FCF
# Test Zenner Minomess C1 water meter
telegram=|6644496A1064035514377251345015496A0007EE0050052F2F_0C1359000000026CBE2B82046CA12B8C0413FFFFFFFF8D0493132CFBFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02FD1700002F2F|
{"media":"water","meter":"minomess","name":"Mino","id":"15503451","meter_date":"2021-11-30","total_m3":0.059,"target_m3":244444.442,"target_date":"2021-11-01","status":"OK","timestamp":"1111-11-11T11:11:11Z"}
{"media":"water","meter":"minomess","name":"Mino","id":"15503451","meter_date":"2021-11-30","total_m3":0.059,"target_date":"2021-11-01","status":"OK","timestamp":"1111-11-11T11:11:11Z"}

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

@ -8,7 +8,8 @@ telegram=|6893936808007275404810C514000431270000#04786BF99F00046D040F632B0415E02
# Test ultraheat heat meter sent over mbus.
telegram=|68F8F86808007200464470A7320404270000000974040970040C0E082303000C14079519000B2D0500000B3B0808000A5B52000A5F51000A6206004C14061818004C0E490603000C7800464470891071609B102D020100DB102D0201009B103B6009009A105B78009A105F74000C22726701003C22000000007C2200000000426C01018C2006000000008C3006000000008C80100600000000CC200600000000CC300600000000CC801006000000009A115B64009A115F63009B113B5208009B112D020100BC0122000000008C010E490603008C2106000000008C3106000000008C811006000000008C011406181800046D310ACA210F21040010A0C116|
{"media":"heat","meter":"ultraheat","name":"MyUltra","id":"70444600","heat_kwh":8974.444444,"volume_m3":1995.07,"power_kw":0.5,"flow_m3h":0.808,"flow_c":52,"return_c":51,"timestamp":"1111-11-11T11:11:11Z"}
{"media":"heat","meter":"ultraheat","name":"MyUltra","id":"70444600","heat_kwh":8974.444444,"volume_m3":1995.07,"power_kw":0.5,"flow_m3h":0.808,"flow_c":52,"return_c":51,"fabrication_no":"70444600","meter_datetime":"2022-01-10 10:49","status":"OK","timestamp":"1111-11-11T11:11:11Z"}
# Test multical 403 heat meter sent over mbus.

Wyświetl plik

@ -0,0 +1,4 @@
telegram=|A244EE4D785634123C067A8F000000|0C1348550000426CE1F14C130000000082046C21298C0413330000008D04931E3A3CFE3300000033000000330000003300000033000000330000003300000033000000330000003300000033000000330000004300000034180000046D0D0B5C2B03FD6C5E150082206C5C290BFD0F0200018C4079678885238310FD3100000082106C01018110FD610002FD66020002FD170000|
{"media":"warm water","meter":"supercom587","name":"MyWarmWater","id":"12345678","total_m3":5.548,"timestamp":"1111-11-11T11:11:11Z"}
telegram=|A244EE4D785634123C067A8F000000|0C1348560000426CE1F14C130000000082046C21298C0413330000008D04931E3A3CFE3300000033000000330000003300000033000000330000003300000033000000330000003300000033000000330000004300000034180000046D0D0B5C2B03FD6C5E150082206C5C290BFD0F0200018C4079678885238310FD3100000082106C01018110FD610002FD66020002FD170000|
{"media":"warm water","meter":"supercom587","name":"MyWarmWater","id":"12345678","total_m3":6.548,"timestamp":"1111-11-11T11:11:11Z"}

Wyświetl plik

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

Wyświetl plik

@ -43,8 +43,8 @@ telegram=|5E44B6105843250000027A2A005005_2F2F0C7835221400066D404708AC2A400E03202
# 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=|2F446850313233347462A2_069F255900B029310000000306060906030609070606050509050505050407040605070500|
{"media":"warm water","meter":"mkradio3","name":"Duschen","id":"34333231","total_m3":13.8,"target_m3":8.9,"current_date":"2023-04-27T02:00:00Z","prev_date":"2018-12-31T02:00:00Z","timestamp":"1111-11-11T11:11:11Z"}
|Duschen;34333231;13.8;8.9;2023-04-27T02:00:00Z;2018-12-31T02:00:00Z;1111-11-11 11:11.11
{"media":"warm water","meter":"mkradio3","name":"Duschen","id":"34333231","total_m3":13.8,"target_m3":8.9,"current_date":"2024-04-27T02:00:00Z","prev_date":"2018-12-31T02:00:00Z","timestamp":"1111-11-11T11:11:11Z"}
|Duschen;34333231;13.8;8.9;2024-04-27T02:00:00Z;2018-12-31T02:00:00Z;1111-11-11 11:11.11
# Test MKRadio4 T1 telegrams
@ -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
@ -122,13 +122,13 @@ telegram=|5744b40988227711101b7ab20800000265a00842658f088201659f08226589081265a0
# Test Hydrus water meter telegram
telegram=|4E44A5116464646470077AED004005_2F2F01FD08300C13741100007C1300000000FC101300000000FC201300000000726C00000B3B00000002FD748713025A6800C4016D3B177F2ACC011300020000|
{"at_datetime": "2019-10-31 23:59","flow_m3h": 0,"flow_temperature_c": 10.4,"id": "64646464","media": "water","meter": "hydrus","name": "HydrusWater","remaining_battery_life_y": 13.686797,"status": "OK","timestamp": "1111-11-11T11:11:11Z","total_at_date_m3": 0.2,"total_m3": 1.174}
|HydrusWater;64646464;1.174;0.2;OK;1111-11-11 11:11.11
{"target_datetime": "2019-10-31 23:59","flow_m3h": 0,"flow_temperature_c": 10.4,"id": "64646464","media": "water","meter": "hydrus","name": "HydrusWater","remaining_battery_life_y": 13.686797,"status": "OK","timestamp": "1111-11-11T11:11:11Z","target_m3": 0.2,"total_m3": 1.174}
|HydrusWater;64646464;1.174;null;OK;1111-11-11 11:11.11
# Test Hydrus new version water meter telegram
telegram=|3E44A5116565656570067AFB0030052F2F_0C13503400000DFD110A383731303134423032410B3B00000002FD74DC15C4016D3B178D29CC0113313400002F2F|
{"at_datetime": "2020-09-13 23:59","customer": "A20B410178","flow_m3h": 0,"id": "65656565","media": "warm water","meter": "hydrus","name": "HydrusVater","remaining_battery_life_y": 15.321328,"status": "OK","timestamp": "1111-11-11T11:11:11Z","total_at_date_m3": 3.431,"total_m3": 3.45}
|HydrusVater;65656565;3.45;3.431;OK;1111-11-11 11:11.11
{"target_datetime": "2020-09-13 23:59","customer": "A20B410178","flow_m3h": 0,"id": "65656565","media": "warm water","meter": "hydrus","name": "HydrusVater","remaining_battery_life_y": 15.321328,"status": "OK","timestamp": "1111-11-11T11:11:11Z","target_m3": 3.431,"total_m3": 3.45}
|HydrusVater;65656565;3.45;null;OK;1111-11-11 11:11.11
# Test Hydrus with default AES encryption
telegram=||6644242328001081640E7266567464A51170071F0050052C411A08674048DD6BA82A0DF79FFD401309179A893A1BE3CE8EDC50C2A45CD7AFEC3B4CE765820BE8056C124A17416C3722985FFFF7FCEB7094901AB3A16294B511B9A740C9F9911352B42A72FB3B0C|
@ -152,7 +152,7 @@ telegram=|2E4409077272727210077AD71020052F2F_046D040D742C041377000000446D0000612
# Test Axioma W1 telegram with additional fields compared to the older q400 meter.
telegram=|5E4409077372727210077A710050052F2F_046D0110A92704130000000004933B0000000004933C00000000023B000002592A0A446D0000A12744130000000044933B0000000044933C0000000001FD74622F2F2F2F2F2F2F2F2F2F2F2F2F2F|
{"media":"water","meter":"q400","name":"AxiomaWater","id":"72727273","meter_datetime":"2021-07-09 16:01","total_m3":0,"total_forward_m3":0,"total_backward_m3":0,"flow_temperature_c":26.02,"volume_flow_m3h":0,"status":"OK","set_datetime":"2021-07-01 00:00","consumption_at_set_date_m3":0,"forward_at_set_date_m3":0,"backward_at_set_date_m3":0,"timestamp":"1111-11-11T11:11:11Z"}
{"media":"water","meter":"q400","name":"AxiomaWater","id":"72727273","meter_datetime":"2021-07-09 16:01","total_m3":0,"total_forward_m3":0,"total_backward_m3":0,"flow_temperature_c":26.02,"volume_flow_m3h":0,"status":"OK","set_datetime":"2021-07-01 00:00","consumption_at_set_date_m3":0,"forward_at_set_date_m3":0,"backward_at_set_date_m3":0,"battery_pct":98,"timestamp":"1111-11-11T11:11:11Z"}
|AxiomaWater;72727273;0;1111-11-11 11:11.11
# Test electricity meter with eBZ wMB E01.
@ -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

Wyświetl plik

@ -49,6 +49,8 @@ parts:
- g++
- make
- librtlsdr-dev
- libxml2-dev
- libxslt1-dev
stage-packages:
- mosquitto-clients
- curl
@ -56,6 +58,7 @@ parts:
- sysvinit-utils
- libusb-1.0-0
- rtl-sdr
- libxml2
prime:
- sbin/
- usr/bin/

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

@ -25,7 +25,6 @@
#include"shell.h"
#include"threads.h"
#include"util.h"
#include"version.h"
#include"wmbus.h"
#include <algorithm>

Wyświetl plik

@ -16,6 +16,7 @@
*/
#include"cmdline.h"
#include"drivers.h"
#include"meters.h"
#include"util.h"
@ -59,27 +60,58 @@ shared_ptr<Configuration> parseCommandLine(int argc, char **argv)
return parseNormalCommandLine(c, argc, argv);
}
void enableEarlyLoggingFromCommandLine(int argc, char **argv)
{
int i = 1;
// First find all logging flags, --silent --verbose --normal --debug
while (argv[i] && argv[i][0] == '-')
{
if (!strcmp(argv[i], "--silent")) {
i++;
silentLogging(true);
continue;
}
if (!strcmp(argv[i], "--verbose")) {
verboseEnabled(true);
i++;
continue;
}
if (!strcmp(argv[i], "--normal")) {
i++;
continue;
}
if (!strcmp(argv[i], "--debug")) {
verboseEnabled(true);
debugEnabled(true);
i++;
continue;
}
if (!strcmp(argv[i], "--trace")) {
verboseEnabled(true);
debugEnabled(true);
traceEnabled(true);
i++;
continue;
}
i++;
}
}
static shared_ptr<Configuration> parseNormalCommandLine(Configuration *c, int argc, char **argv)
{
int i = 1;
// First find all logging flags, --silent --verbose --normal --debug
while (argv[i] && argv[i][0] == '-')
{
if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) {
c->need_help = true;
return shared_ptr<Configuration>(c);
}
if (!strncmp(argv[i], "--device=", 9) || // Deprecated
!strncmp(argv[i], "--overridedevice=", 17))
{
error("You can only use --overridedevice=xyz with --useconfig=xyz\n");
}
if (!strcmp(argv[i], "--silent")) {
c->silent = true;
i++;
silentLogging(true);
continue;
}
if (!strcmp(argv[i], "--verbose")) {
c->verbose = true;
verboseEnabled(true);
i++;
continue;
}
@ -91,6 +123,48 @@ static shared_ptr<Configuration> parseNormalCommandLine(Configuration *c, int ar
i++;
continue;
}
if (!strcmp(argv[i], "--debug")) {
c->debug = true;
verboseEnabled(true);
debugEnabled(true);
i++;
continue;
}
if (!strcmp(argv[i], "--trace")) {
c->debug = true;
c->trace = true;
verboseEnabled(true);
debugEnabled(true);
traceEnabled(true);
i++;
continue;
}
i++;
}
// Now do the rest of the arguments.
i = 1;
while (argv[i] && argv[i][0] == '-')
{
if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) {
c->need_help = true;
return shared_ptr<Configuration>(c);
}
if (!strcmp(argv[i], "--silent") ||
!strcmp(argv[i], "--verbose") ||
!strcmp(argv[i], "--normal") ||
!strcmp(argv[i], "--debug") ||
!strcmp(argv[i], "--trace"))
{
// Handled already.
i++;
continue;
}
if (!strncmp(argv[i], "--device=", 9) || // Deprecated
!strncmp(argv[i], "--overridedevice=", 17))
{
error("You can only use --overridedevice=xyz with --useconfig=xyz\n");
}
if (!strcmp(argv[i], "--version")) {
c->version = true;
return shared_ptr<Configuration>(c);
@ -162,18 +236,6 @@ static shared_ptr<Configuration> parseNormalCommandLine(Configuration *c, int ar
i++;
continue;
}
if (!strcmp(argv[i], "--debug")) {
c->debug = true;
i++;
continue;
}
if (!strcmp(argv[i], "--trace")) {
c->debug = true;
c->trace = true;
i++;
continue;
}
if (!strncmp(argv[i], "--logtimestamps=", 16))
{
string ts = string(argv[i]+16);
@ -451,6 +513,15 @@ static shared_ptr<Configuration> parseNormalCommandLine(Configuration *c, int ar
i++;
continue;
}
if (!strncmp(argv[i], "--metershell=", 13)) {
string cmd = string(argv[i]+13);
if (cmd == "") {
error("The meter shell command cannot be empty.\n");
}
c->meter_shells.push_back(cmd);
i++;
continue;
}
if (!strncmp(argv[i], "--alarmshell=", 13)) {
string cmd = string(argv[i]+13);
if (cmd == "") {
@ -546,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) {
@ -572,6 +652,31 @@ static shared_ptr<Configuration> parseNormalCommandLine(Configuration *c, int ar
i++;
continue;
}
if (!strncmp(argv[i], "--driversdir=", 13))
{
size_t len = strlen(argv[i]) - 13;
c->drivers_dir = string(argv[i]+13, len);
if (!checkIfDirExists(c->drivers_dir.c_str()))
{
error("You must supply a valid directory to --driversdir=<dir>\n");
}
i++;
loadDriversFromDir(c->drivers_dir);
continue;
}
if (!strncmp(argv[i], "--driver=", 9))
{
size_t len = strlen(argv[i]) - 9;
string file_name = string(argv[i]+9, len);
if (!checkFileExists(file_name.c_str()))
{
error("You must supply a valid file to --driver=<file>\n");
}
i++;
loadDriver(file_name, NULL);
continue;
}
error("Unknown option \"%s\"\n", argv[i]);
}
@ -632,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

@ -27,5 +27,6 @@
using namespace std;
shared_ptr<Configuration> parseCommandLine(int argc, char **argv);
void enableEarlyLoggingFromCommandLine(int argc, char **argv);
#endif

Wyświetl plik

@ -16,6 +16,7 @@
*/
#include"config.h"
#include"drivers.h"
#include"meters.h"
#include"units.h"
@ -52,11 +53,13 @@ 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;
vector<string> extra_constant_fields;
vector<string> extra_calculated_fields;
@ -106,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")
{
@ -127,10 +130,23 @@ 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);
}
else
if (p.first == "metershell") {
meter_shells.push_back(p.second);
}
else
if (p.first == "alarmshell") {
alarm_shells.push_back(p.second);
}
@ -170,36 +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.idsc = toIdsCommaSeparated(mi.ids);
mi.meter_shells = meter_shells;
mi.selected_fields = selected_fields;
c->meters.push_back(mi);
}
@ -636,6 +644,11 @@ void handleShell(Configuration *c, string cmdline)
c->telegram_shells.push_back(cmdline);
}
void handleMeterShell(Configuration *c, string cmdline)
{
c->meter_shells.push_back(cmdline);
}
void handleAlarmShell(Configuration *c, string cmdline)
{
c->alarm_shells.push_back(cmdline);
@ -668,12 +681,14 @@ shared_ptr<Configuration> loadConfiguration(string root, ConfigOverrides overrid
string conf_dir = root;
string conf_file = root+"/etc/wmbusmeters.conf";
string conf_meter_dir = root+"/etc/wmbusmeters.d";
string conf_drivers_dir = root+"/etc/wmbusmeters.drivers.d";
if (!checkFileExists(conf_file.c_str()))
{
conf_dir = root+"/etc";
conf_file = root+"/wmbusmeters.conf";
conf_meter_dir = root+"/wmbusmeters.d";
conf_drivers_dir = root+"/wmbusmeters.drivers.d";
}
debug("(config) loading %s\n", conf_file.c_str());
@ -714,6 +729,7 @@ shared_ptr<Configuration> loadConfiguration(string root, ConfigOverrides overrid
else if (p.first == "selectfields") handleSelectedFields(c, p.second);
else if (p.first == "shell") handleShell(c, p.second);
else if (p.first == "resetafter") handleResetAfter(c, p.second);
else if (p.first == "metershell") handleMeterShell(c, p.second);
else if (p.first == "alarmshell") handleAlarmShell(c, p.second);
else if (startsWith(p.first, "json_") ||
startsWith(p.first, "field_"))
@ -793,6 +809,8 @@ shared_ptr<Configuration> loadConfiguration(string root, ConfigOverrides overrid
handleLogfile(c, overrides.logfile_override);
}
loadDriversFromDir(conf_drivers_dir);
return shared_ptr<Configuration>(c);
}

Wyświetl plik

@ -68,6 +68,7 @@ struct Configuration
ConfigOverrides overrides;
bool useconfig {};
std::string config_root;
std::string drivers_dir;
bool need_help {};
bool silent {};
bool verbose {};
@ -98,9 +99,11 @@ 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;
std::vector<std::string> meter_shells;
std::vector<std::string> alarm_shells;
int alarm_timeout {}; // Maximum number of seconds between dongle receiving two telegrams.
std::string alarm_expected_activity; // Only warn when within these time periods.

Plik diff jest za duży Load Diff

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

@ -56,12 +56,14 @@ namespace
vector<uchar> content;
t->extractPayload(&content);
if (content.size() < 4) return;
map<string,pair<int,DVEntry>> vendor_values;
string total;
strprintf(&total, "%02x%02x%02x%02x", content[0], content[1], content[2], content[3]);
vendor_values["0413"] = { 25, DVEntry(25, DifVifKey("0413"), MeasurementType::Instantaneous, 0x13, {}, 0, 0, 0, total) };
vendor_values["0413"] = { 25, DVEntry(25, DifVifKey("0413"), MeasurementType::Instantaneous, 0x13, {}, {}, 0, 0, 0, total) };
int offset;
string key;
if(findKey(MeasurementType::Instantaneous, VIFRange::Volume, 0, 0, &key, &vendor_values))

Wyświetl plik

@ -80,7 +80,7 @@ namespace
// 0F - Spcial function / packet
// next 4B : Date - In default frame
// next 3B : Faults - In default frame example: please see description of 0x01 register
size_t i=8;
while (i < content.size())
{
@ -89,7 +89,7 @@ namespace
if (c == 0xff) break; // An FF signals end of telegram padded to encryption boundary,
// FFFFFFF623A where 4 last are perhaps crc or counter?
i++;
if (size == -1 || i+size >= content.size())
if (size == -1 || i+size > content.size())
{
vector<uchar> frame;
t->extractFrame(&frame);
@ -97,9 +97,19 @@ namespace
if (t->beingAnalyzed() == false)
{
warning("(apator162) telegram contains a register (%02x) with unknown size.\n"
"Please open an issue at https://github.com/wmbusmeters/wmbusmeters/\n"
"and report this telegram: %s\n", c, hex.c_str());
if (size == -1)
{
warning("(apator162) telegram contains a register (%02x) with unknown size.\n"
"Please open an issue at https://github.com/wmbusmeters/wmbusmeters/\n"
"and report this telegram: %s\n", c, hex.c_str());
}
else
{
warning("(apator162) telegram decoding fails since last register (%02x size %d) does not\n"
"align with telegram size %zu > %zu.\n"
"Please open an issue at https://github.com/wmbusmeters/wmbusmeters/\n"
"and report this telegram: %s\n", c, size, i+size, content.size(), hex.c_str());
}
}
break;
}
@ -109,7 +119,7 @@ namespace
string total;
strprintf(&total, "%02x%02x%02x%02x", content[i+0], content[i+1], content[i+2], content[i+3]);
int offset = i-1+t->header_size;
vendor_values["0413"] = {offset, DVEntry(offset, DifVifKey("0413"), MeasurementType::Instantaneous, 0x13, {}, 0, 0, 0, total) };
vendor_values["0413"] = {offset, DVEntry(offset, DifVifKey("0413"), MeasurementType::Instantaneous, 0x13, {}, {}, 0, 0, 0, total) };
double total_water_consumption_m3 {};
extractDVdouble(&vendor_values, "0413", &offset, &total_water_consumption_m3);
total = "*** 10-"+total+" total consumption (%f m3)";
@ -135,14 +145,14 @@ namespace
// which also means dif = manufacturer data follows.
// After 0x0F there is always:
// next 4B : Date - In default frame
// next 3B : Faults - In default frame
case 0x00: return 4; // Date
// next 3B : Faults - In default frame
case 0x00: return 4; // Date
case 0x01: return 3; // Faults - In default frame f.ex. 0F 09 4D A1 97 18 02 00 -> 18 02 00 -> 00 02 18 -> 0x0218
case 0xA1:
case 0x10: return 4; // Total volume - In default frame
case 0x11: return 2; // Flow
case 0x40: return 6; // Detectors
@ -150,49 +160,52 @@ namespace
case 0x42: return 4; // Energy
case 0x43: return 2; // Life days - In default frame f.ex. 43 6E 0A -> 2670 days from first run
case 0x71: return 9;
case 0x44: return 3;
case 0x71: return 1+2*4; // ?
case 0x72: return 1+3*4; // ?
case 0x73: return 1+4*4; // Historical data
case 0x75: return 1+6*4; // Historical data
case 0x7B: return 1+12*4; // Historical data
case 0x80:
case 0x81:
case 0x82:
case 0x83:
case 0x84:
case 0x86:
case 0x80:
case 0x81:
case 0x82:
case 0x83:
case 0x84:
case 0x86:
case 0x87: return 10; // Events
case 0x85:
case 0x88:
case 0x88:
case 0x8F: return 11; // Events
case 0x8A: return 9; // Events
case 0x8B:
case 0x8C: return 6; // Events
case 0x8E: return 7; // Events
case 0xA0: return 4;
case 0xA2: return 1;
case 0xA3: return 7;
case 0xA4: return 4;
case 0xA5:
case 0xA9:
case 0xAF: return 1;
case 0xA6: return 3;
case 0xA7:
case 0xA8:
case 0xAA:
case 0xAB:
case 0xAC:
case 0xAB:
case 0xAC:
case 0xAD: return 2;
case 0xB0: return 5;
@ -201,7 +214,7 @@ namespace
case 0xB3: return 8;
case 0xB4: return 2;
case 0xB5: return 16;
// Unknown
case 0xB6: return 3;
case 0xB7: return 3;

Wyświetl plik

@ -64,7 +64,7 @@ namespace
string total;
strprintf(&total, "%02x%02x%02x%02x", content[i+0], content[i+1], content[i+2], content[i+3]);
int offset = i-1+t->header_size;
vendor_values["0413"] = {offset, DVEntry(offset, DifVifKey("0413"), MeasurementType::Instantaneous, 0x13, {}, 0, 0, 0, total) };
vendor_values["0413"] = {offset, DVEntry(offset, DifVifKey("0413"), MeasurementType::Instantaneous, 0x13, {}, {}, 0, 0, 0, total) };
double tmp = 0;
extractDVdouble(&vendor_values, "0413", &offset, &tmp);
// Single tick seems to be 1/3 of a m3. Divide by 3 and keep a single decimal.

Wyświetl plik

@ -114,7 +114,7 @@ namespace
uchar season_start_date_lo = content[1];
uchar season_start_date_hi = content[0];
string season_start_date = dateToString(season_start_date_lo, season_start_date_hi);
setStringValue("season_start_date", season_start_date);
setStringValue("season_start_date", season_start_date, NULL);
// Previous season total allocation
uchar prev_lo = content[4];
@ -126,7 +126,7 @@ namespace
uchar esb_date_lo = content[6];
uchar esb_date_hi = content[7];
string esb_date = dateToString(esb_date_lo, esb_date_hi);
setStringValue("esb_date", esb_date);
setStringValue("esb_date", esb_date, NULL);
// Current season allocation
uchar curr_lo = content[8];
@ -138,7 +138,7 @@ namespace
uchar date_curr_lo = content[10];
uchar date_curr_hi = content[11];
string current_date = dateToString(date_curr_lo, date_curr_hi);
setStringValue("current_date", current_date);
setStringValue("current_date", current_date, NULL);
// Previous season average temperature
double temp_room_prev_avg_frac = content[12];

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

@ -125,7 +125,7 @@ namespace
t->addSpecialExplanation(4+t->header_size, 2, KindOfData::CONTENT, Understanding::FULL, msg.c_str());
string device_date = tostrprintf("20%02x-%02x-%02x", content[39], content[39-1], content[39-2]);
setStringValue("device_date", device_date);
setStringValue("device_date", device_date, NULL);
msg = tostrprintf("*** %02X%02X%02X \"device_date\":\"%s\"", content[39-2], content[39-1], content[39],
device_date.c_str());

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,21 +284,20 @@ 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|
// {"media":"water","meter":"c5isf","name":"Heat","id":"55445555","total_energy_consumption_kwh":0,"total_volume_m3":0,"status":"ERROR","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_m3":0,"prev_2_month_m3":21474836.48,"prev_3_month_m3":21474836.48,"prev_4_month_m3":21474836.48,"prev_5_month_m3":21474836.48,"prev_6_month_m3":21474836.48,"prev_7_month_m3":21474836.48,"prev_8_month_m3":21474836.48,"prev_9_month_m3":21474836.48,"prev_10_month_m3":21474836.48,"prev_11_month_m3":21474836.48,"prev_12_month_m3":21474836.48,"prev_13_month_m3":21474836.48,"prev_14_month_m3":21474836.48,"total_energy_consumption_last_month_kwh":0,"timestamp":"1111-11-11T11:11:11Z"}
// {"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|
// {"media":"heat","meter":"c5isf","name":"Heat","id":"55445555","total_energy_consumption_kwh":26,"total_volume_m3":2.242,"status":"OK","prev_1_month":"2022-01-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,"prev_2_month_m3":21474836.48,"prev_3_month_m3":21474836.48,"prev_4_month_m3":21474836.48,"prev_5_month_m3":21474836.48,"prev_6_month_m3":21474836.48,"prev_7_month_m3":21474836.48,"prev_8_month_m3":21474836.48,"prev_9_month_m3":21474836.48,"prev_10_month_m3":21474836.48,"prev_11_month_m3":21474836.48,"prev_12_month_m3":21474836.48,"prev_13_month_m3":21474836.48,"prev_14_month_m3":21474836.48,"due_energy_consumption_kwh":0,"due_date":"2022-01-01","volume_flow_m3h":0.164,"power_kw":2.5,"total_energy_consumption_last_month_kwh":0,"max_power_last_month_kw":0,"flow_temperature_c":56.5,"return_temperature_c":43.22,"timestamp":"1111-11-11T11:11:11Z"}
// {"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
// Test telegram with max_power_last_month_kwh which is non-zero
// telegram=|5E44496A4420003288047AFC0050052F2F_0406D00E00000413B28A05008404060000000082046CC121043B00000000042D000000000259E719025D051402FD17000084800106C00C00008280016CC125948001AE25090000002F2F2F2F2F2F|
// {"media":"heat","meter":"c5isf","name":"Heat","id":"32002044","total_energy_consumption_kwh":3792,"total_volume_m3":363.186,"status":"OK","prev_1_month":"2022-05-01","prev_1_month_kwh":3264,"due_energy_consumption_kwh":0,"due_date":"2022-01-01","volume_flow_m3h":0,"power_kw":0,"total_energy_consumption_last_month_kwh":3264,"max_power_last_month_kw":9,"flow_temperature_c":66.31,"return_temperature_c":51.25,"timestamp":"1111-11-11T11:11:11Z"}

Wyświetl plik

@ -39,7 +39,7 @@ namespace
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
addOptionalCommonFields("software_version");
addOptionalLibraryFields("software_version");
addStringField(
"status",
@ -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

@ -80,7 +80,7 @@ namespace
string prevs;
strprintf(&prevs, "%02x%02x", prev_lo, prev_hi);
int offset = t->parsed.size()+3;
vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x15, {}, 0, 0, 0, prevs) };
vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x15, {}, {}, 0, 0, 0, prevs) };
Explanation pe(offset, 2, prevs, KindOfData::CONTENT, Understanding::FULL);
t->explanations.push_back(pe);
t->addMoreExplanation(offset, " energy used in previous billing period (%f KWH)", prev);
@ -92,7 +92,7 @@ namespace
string currs;
strprintf(&currs, "%02x%02x", curr_lo, curr_hi);
offset = t->parsed.size()+7;
vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x15, {}, 0, 0, 0, currs) };
vendor_values["0215"] = { offset, DVEntry(offset, DifVifKey("0215"), MeasurementType::Instantaneous, 0x15, {}, {}, 0, 0, 0, currs) };
Explanation ce(offset, 2, currs, KindOfData::CONTENT, Understanding::FULL);
t->explanations.push_back(ce);
t->addMoreExplanation(offset, " energy used in current billing period (%f KWH)", curr);

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)

1021
src/driver_dynamic.cc 100644

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,47 @@
/*
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
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 DRIVER_LOADER_H_
#define DRIVER_LOADER_H_
#include "meters_common_implementation.h"
struct DriverDynamic : public virtual MeterCommonImplementation
{
DriverDynamic(MeterInfo &mi, DriverInfo &di);
~DriverDynamic();
static bool load(DriverInfo *di, const string &name, const char *content);
static XMQProceed add_detect(XMQDoc *doc, XMQNode *detect, DriverInfo *di);
static XMQProceed add_use(XMQDoc *doc, XMQNode *field, DriverDynamic *dd);
static XMQProceed add_field(XMQDoc *doc, XMQNode *field, DriverDynamic *dd);
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

@ -40,14 +40,14 @@ namespace
"Meter status. Includes both meter error field and tpl status field.",
PrintProperty::STATUS | PrintProperty::INCLUDE_TPL_STATUS);
addOptionalCommonFields("on_time_h");
addOptionalLibraryFields("on_time_h");
addNumericFieldWithExtractor(
"total_energy_consumption",
"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

@ -36,6 +36,7 @@ namespace
di.setMeterType(MeterType::ElectricityMeter);
di.addLinkMode(LinkMode::C1);
di.addDetection(MANUFACTURER_KAM, 0x02, 0x33);
di.addDetection(MANUFACTURER_GAV, 0x02, 0x00);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
});
@ -52,7 +53,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xff),
"OK",
{
@ -79,7 +80,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xff),
"",
{
@ -100,18 +101,29 @@ 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)
);
addNumericFieldWithExtractor(
"power",
"Power measured by this meter at the moment.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Power,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::AnyPowerVIF)
);
addNumericFieldWithExtractor(
"total_energy_production",
"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)
@ -123,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"))
);
@ -133,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"))
@ -160,10 +172,96 @@ namespace
(total_reactive_energy_production_kvarh * total_reactive_energy_production_kvarh) )
)STR");
addNumericFieldWithExtractor(
"amperage_at_phase_1",
"Amperage at phase L1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FDD9FC01"))
);
addNumericFieldWithExtractor(
"amperage_at_phase_2",
"Amperage at phase L2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FDD9FC02"))
);
addNumericFieldWithExtractor(
"amperage_at_phase_3",
"Amperage at phase L3.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Amperage,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FDD9FC03"))
);
addNumericFieldWithExtractor(
"voltage_at_phase_1",
"Voltage at phase L1.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FDC8FC01"))
);
addNumericFieldWithExtractor(
"voltage_at_phase_2",
"Voltage at phase L2.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FDC8FC02"))
);
addNumericFieldWithExtractor(
"voltage_at_phase_3",
"Voltage at phase L3.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("04FDC8FC03"))
);
addNumericFieldWithExtractor(
"raw_frequency",
"Frequency in 0.1 Hz",
DEFAULT_PRINT_PROPERTIES | PrintProperty::HIDE,
Quantity::Frequency,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(DifVifKey("02FB2E"))
);
addNumericFieldWithCalculator(
"frequency",
"Frequency of AC.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Frequency,
"raw_frequency_hz / 10 counter");
}
}
// Test: Elen em24 66666666 NOKEY
// telegram=|35442D2C6666666633028D2070806A0520B4D378_0405F208000004FB82753F00000004853C0000000004FB82F53CCA01000001FD1722|
// {"media":"electricity","meter":"em24","name":"Elen","id":"66666666","status":"I_3_OVERFLOW V_2_OVERFLOW","error":"I_3_OVERFLOW V_2_OVERFLOW","total_energy_consumption_kwh":229,"total_energy_production_kwh":0,"total_reactive_energy_consumption_kvarh":63,"total_reactive_energy_production_kvarh":458,"total_apparent_energy_consumption_kvah":237.507895,"total_apparent_energy_production_kvah":458,"timestamp":"1111-11-11T11:11:11Z"}
// {"media":"electricity","meter":"em24","name":"Elen","id":"66666666","status":"I_3_OVERFLOW V_2_OVERFLOW","error":"I_3_OVERFLOW V_2_OVERFLOW","total_energy_consumption_kwh":229,"total_energy_production_kwh":0,"total_reactive_energy_consumption_kvarh":63,"total_reactive_energy_production_kvarh":458,"total_apparent_energy_consumption_kvah":237.507895,"total_apparent_energy_production_kvah":458,"frequency_hz":null,"timestamp":"1111-11-11T11:11:11Z"}
// |Elen;66666666;229;0;63;458;237.507895;458;1111-11-11 11:11.11
// Test: Elen2 em24 02020202 NOKEY
// telegram=|4144361C0202020200028C209A7A9A0030252F2F_04050100000004FB82750000000004FB82F53C00000000042A0000000001FD17002F2F2F2F2F2F2F2F2F2F2F2F2F|
// {"error": "","id": "02020202","media": "electricity","meter": "em24","name": "Elen2","power_kw": 0,"status": "OK","timestamp": "1111-11-11T11:11:11Z","total_apparent_energy_consumption_kvah": 0.1,"total_apparent_energy_production_kvah": null,"total_energy_consumption_kwh": 0.1,"total_reactive_energy_consumption_kvarh": 0,"total_reactive_energy_production_kvarh": 0,"frequency_hz":null}
// |Elen2;02020202;0.1;null;0;0;0.1;null;1111-11-11 11:11.11
// telegram=|8144361C0202020200028C20357A351070252F2F_04050100000004FB82750000000004FB82F53C00000000042A0000000004FB140000000004FB943C0000000004FDD9FC010000000004FDD9FC020000000004FDD9FC030000000004FDC8FC011709000004FDC8FC02EC04000004FDC8FC03EC04000002FB2EF40101FD17002F2F2F|
// {"amperage_at_phase_1_a": 0,"amperage_at_phase_2_a": 0,"amperage_at_phase_3_a": 0,"error": "","frequency_hz": 50,"id": "02020202","media": "electricity","meter": "em24","name": "Elen2","power_kw": 0,"status": "OK","timestamp": "1111-11-11T11:11:11Z","total_apparent_energy_consumption_kvah": 0.1,"total_apparent_energy_production_kvah": null,"total_energy_consumption_kwh": 0.1,"total_reactive_energy_consumption_kvarh": 0,"total_reactive_energy_production_kvarh": 0,"voltage_at_phase_1_v": 232.7,"voltage_at_phase_2_v": 126,"voltage_at_phase_3_v": 126}
// |Elen2;02020202;0.1;null;0;0;0.1;null;1111-11-11 11:11.11

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)
@ -237,7 +237,7 @@ namespace
.set(StorageNr(1))
);
addOptionalCommonFields("operating_time_h,on_time_h,meter_datetime");
addOptionalLibraryFields("operating_time_h,on_time_h,meter_datetime");
}
}

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

@ -37,7 +37,7 @@ namespace
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
addOptionalCommonFields("fabrication_no,enhanced_id,location");
addOptionalLibraryFields("fabrication_no,enhanced_id,location");
addStringFieldWithExtractor(
"location_hex",
@ -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

@ -40,7 +40,7 @@ namespace
addStringFieldWithExtractorAndLookup(
"current_status",
"Status of meter.",
DEFAULT_PRINT_PROPERTIES
DEFAULT_PRINT_PROPERTIES
| PrintProperty::STATUS | PrintProperty::INCLUDE_TPL_STATUS,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
@ -49,7 +49,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
@ -59,15 +59,15 @@ namespace
},
});
addOptionalCommonFields("fabrication_no");
addOptionalFlowRelatedFields("total_m3");
addOptionalLibraryFields("fabrication_no");
addOptionalLibraryFields("total_m3");
addNumericFieldWithExtractor(
"consumption_at_set_date",
"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

@ -105,7 +105,7 @@ namespace
leadingZeroString(month_prev) + "-" +
leadingZeroString(day_prev) + "T02:00:00Z";
setStringValue("previous_date", previous_date);
setStringValue("previous_date", previous_date, NULL);
string bytes = tostrprintf("%02x%02x", content[1], content[2]);
string info = "*** "+bytes+" previous_date = %s";
@ -147,7 +147,7 @@ namespace
leadingZeroString(month_curr) + "-" +
leadingZeroString(day_curr) + "T02:00:00Z";
setStringValue("current_date", current_date);
setStringValue("current_date", current_date, NULL);
bytes = tostrprintf("%02x%02x", content[5], content[6]);
info = "*** "+bytes+" current_date = %s";

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)
@ -148,10 +148,10 @@ namespace
addNumericFieldWithExtractor(
"max_flow",
"The maxium flow recorded during previous period.",
"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)
@ -172,10 +172,10 @@ namespace
addNumericFieldWithExtractor(
"max_external_temperature",
"The maxium temperature recorded during previous period.",
"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)
@ -196,10 +196,10 @@ namespace
addNumericFieldWithExtractor(
"max_flow",
"The maxium flow recorded during previous period.",
"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,10 +70,10 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger,
AutoMask,
"",
"OK",
{
{ 0x0001, "METER_HARDWARE_ERROR" },
{ 0x0002, "RTC_ERROR" },
@ -85,10 +85,10 @@ namespace
},
{
"ERROR_FLAGS_SINGLE_PHASE",
Translate::Type::BitToString,
Translate::MapType::BitToString,
TriggerBits(0x01020000),
AutoMask,
"",
"OK",
{
{ 0x0008, "DEVICE_NOT_CONFIGURED" },
{ 0x0010, "INTERNAL_ERROR" },
@ -99,10 +99,10 @@ namespace
},
{
"ERROR_FLAGS_THREE_PHASE",
Translate::Type::BitToString,
Translate::MapType::BitToString,
TriggerBits(0x01010000),
AutoMask,
"",
"OK",
{
{ 0x0008, "CALIBRATION_EEPROM_ERROR" },
{ 0x0010, "NETWORK_INTERFERENCE" },
@ -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

@ -38,8 +38,8 @@ namespace
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
addOptionalCommonFields("actuality_duration_s");
addOptionalFlowRelatedFields("total_m3,target_m3,target_date");
addOptionalLibraryFields("actuality_duration_s");
addOptionalLibraryFields("total_m3,target_m3,target_date");
addStringField(
"status",
@ -77,7 +77,7 @@ namespace
if (type != 1)
{
setStringValue("mfct_status", tostrprintf("UKNOWN_MFCT_STATUS=%02x%02x%02x", type, a, b));
setStringValue("mfct_status", tostrprintf("UKNOWN_MFCT_STATUS=%02x%02x%02x", type, a, b), NULL);
return;
}
@ -89,9 +89,9 @@ namespace
if (a & 0x40) info += "BACKFLOW ";
if (info.size() > 0) info.pop_back();
setStringValue("mfct_status", info);
setStringValue("mfct_status", info, NULL);
setStringValue("power_mode", (b & 0x01) ? "SAVING" : "NORMAL");
setStringValue("power_mode", (b & 0x01) ? "SAVING" : "NORMAL", NULL);
double battery_semesters = (b >> 3); // Half years.
setNumericValue("battery", Unit::Year, battery_semesters/2.0);
@ -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

115
src/driver_hcae2.cc 100644
Wyświetl plik

@ -0,0 +1,115 @@
/*
Copyright (C) 2019-2023 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("hcae2");
di.setDefaultFields("name,id,current_consumption_hca,status,timestamp");
di.setMeterType(MeterType::HeatCostAllocationMeter);
di.addLinkMode(LinkMode::T1);
di.addDetection(MANUFACTURER_EFE, 0x08, 0x31);
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",
"Meter status from error flags and tpl status field.",
DEFAULT_PRINT_PROPERTIES |
PrintProperty::STATUS | PrintProperty::INCLUDE_TPL_STATUS,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ErrorFlags),
Translate::Lookup(
{
{
{
"ERROR_FLAGS",
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"OK",
{
{ 0x0001, "MEASUREMENT" },
{ 0x0002, "SABOTAGE" },
{ 0x0004, "BATTERY" },
{ 0x0008, "CS" },
{ 0x0010, "HF" },
{ 0x0020, "RESET" }
}
},
},
}));
addNumericFieldWithExtractor(
"current_consumption",
"The current heat cost allocation.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
);
addNumericFieldWithExtractor(
"consumption_at_set_date_{storage_counter}",
"The heat cost allocation at set date #.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
.set(StorageNr(1),StorageNr(17))
);
addNumericFieldWithExtractor(
"consumption_at_set_date",
"Deprecated field.",
DEFAULT_PRINT_PROPERTIES,
Quantity::HCA,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::HeatCostAllocation)
.set(StorageNr(1))
);
}
}
// Test: HeatMeter hcae2 88018801 NOKEY
// telegram=|7644C52501880188550872_01880188C5255508010000002F2F0B6E332211426E110182016E1102C2016E110382026E1104C2026E110582036E1106C2036E110782046E1108C2046E110982056E1110C2056E111182066E1112C2066E111382076E1114C2076E111582086E1116C2086E111702FD172100|
// {"media":"heat cost allocation","meter":"hcae2","name":"HeatMeter","id":"88018801","status":"MEASUREMENT RESET","current_consumption_hca":112233,"consumption_at_set_date_hca":273,"consumption_at_set_date_1_hca":273,"consumption_at_set_date_2_hca":529,"consumption_at_set_date_3_hca":785,"consumption_at_set_date_4_hca":1041,"consumption_at_set_date_5_hca":1297,"consumption_at_set_date_6_hca":1553,"consumption_at_set_date_7_hca":1809,"consumption_at_set_date_8_hca":2065,"consumption_at_set_date_9_hca":2321,"consumption_at_set_date_10_hca":4113,"consumption_at_set_date_11_hca":4369,"consumption_at_set_date_12_hca":4625,"consumption_at_set_date_13_hca":4881,"consumption_at_set_date_14_hca":5137,"consumption_at_set_date_15_hca":5393,"consumption_at_set_date_16_hca":5649,"consumption_at_set_date_17_hca":5905,"timestamp":"1111-11-11T11:11:11Z"}
// |HeatMeter;88018801;112233;MEASUREMENT RESET;1111-11-11 11:11.11
// Test: HeatMeter2 hcae2 60200770 NOKEY
// telegram=|76442D4870072060550872700720602D485508280060052F2F_0B6E320100426E550082016E3500C2016E1F0082026E1F00C2026E130082036E1300C2036E130082046E1300C2046E120082056E7D01C2056E440182066E0601C2066EB80082076E7F00C2076E320082086E1C00C2086E1C0002FD170000
// {"media":"heat cost allocation","meter":"hcae2","name":"HeatMeter2","id":"60200770","status":"OK","current_consumption_hca":132,"consumption_at_set_date_4_hca":31,"consumption_at_set_date_5_hca":19,"consumption_at_set_date_6_hca":19,"consumption_at_set_date_2_hca":53,"consumption_at_set_date_14_hca":127,"consumption_at_set_date_8_hca":19,"consumption_at_set_date_1_hca":85,"consumption_at_set_date_10_hca":381,"consumption_at_set_date_17_hca":28,"consumption_at_set_date_13_hca":184,"consumption_at_set_date_11_hca":324,"consumption_at_set_date_3_hca":31,"consumption_at_set_date_9_hca":18,"consumption_at_set_date_15_hca":50,"consumption_at_set_date_16_hca":28,"consumption_at_set_date_7_hca":19,"consumption_at_set_date_12_hca":262,"consumption_at_set_date_hca":85,"timestamp":"1111-11-11T11:11:11Z"}
// |HeatMeter2;60200770;132;OK;1111-11-11 11:11.11

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

@ -1,5 +1,5 @@
/*
Copyright (C) 2019-2022 Fredrik Öhrström (gpl-3.0-or-later)
Copyright (C) 2019-2023 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,6 +31,7 @@ namespace
di.setMeterType(MeterType::WaterMeter);
di.addLinkMode(LinkMode::T1);
di.addDetection(MANUFACTURER_BMT, 0x06, 0x13);
di.addDetection(MANUFACTURER_BMT, 0x06, 0x17);
di.addDetection(MANUFACTURER_BMT, 0x07, 0x13);
di.addDetection(MANUFACTURER_BMT, 0x07, 0x15);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
@ -43,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)
@ -54,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),
@ -67,3 +68,8 @@ namespace
// telegram=|4E44B4098686868613077AF0004005_2F2F0C1366380000046D27287E2A0F150E00000000C10000D10000E60000FD00000C01002F0100410100540100680100890000A00000B30000002F2F2F2F2F2F|
// {"media":"water","meter":"hydrodigit","name":"HydrodigitWater","id":"86868686","total_m3":3.866,"meter_datetime":"2019-10-30 08:39","timestamp":"1111-11-11T11:11:11Z"}
// |HydrodigitWater;86868686;3.866;2019-10-30 08:39;1111-11-11 11:11.11
// Test: HydridigitWaterr hydrodigit 03245501 NOKEY
// telegram=|2444B4090155240317068C00487AC0000000_0C1335670000046D172EEA280F030000000000|
// {"id": "03245501","media": "warm water","meter": "hydrodigit","meter_datetime": "2023-08-10 14:23","name": "HydridigitWaterr","timestamp": "1111-11-11T11:11:11Z","total_m3": 6.735}
// |HydridigitWaterr;03245501;6.735;2023-08-10 14:23;1111-11-11 11:11.11

Wyświetl plik

@ -44,8 +44,8 @@ namespace
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
addOptionalCommonFields("operating_time_h,actuality_duration_s,meter_datetime,customer");
addOptionalFlowRelatedFields("flow_temperature_c,external_temperature_c");
addOptionalLibraryFields("operating_time_h,actuality_duration_s,meter_datetime,customer");
addOptionalLibraryFields("flow_temperature_c,external_temperature_c");
addStringField(
"status",
@ -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)
@ -124,11 +124,11 @@ namespace
);
addNumericFieldWithExtractor(
"total_at_date",
"Fix this! The total water consumption recorded at last day. Perhaps?",
"target",
"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)
@ -136,11 +136,11 @@ namespace
);
addNumericFieldWithExtractor(
"at",
"Fix this! The last billing period date last day. Perhaps?",
"target",
"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),
@ -163,14 +163,14 @@ namespace
// Test: HydrusWater hydrus 64646464 NOKEY
// Comment:
// telegram=|4E44A5116464646470077AED004005_2F2F01FD08300C13741100007C1300000000FC101300000000FC201300000000726C00000B3B00000002FD748713025A6800C4016D3B177F2ACC011300020000|
// {"media":"water","meter":"hydrus","name":"HydrusWater","id":"64646464","total_m3":1.174,"flow_m3h":0,"flow_temperature_c":10.4,"remaining_battery_life_y":13.686797,"status":"OK","at_datetime":"2019-10-31 23:59","total_at_date_m3": 0.2,"timestamp":"1111-11-11T11:11:11Z"}
// |HydrusWater;64646464;1.174;0.2;OK;1111-11-11 11:11.11
// {"media":"water","meter":"hydrus","name":"HydrusWater","id":"64646464","total_m3":1.174,"flow_m3h":0,"flow_temperature_c":10.4,"remaining_battery_life_y":13.686797,"status":"OK","target_datetime":"2019-10-31 23:59","target_m3": 0.2,"timestamp":"1111-11-11T11:11:11Z"}
// |HydrusWater;64646464;1.174;null;OK;1111-11-11 11:11.11
// Test: HydrusVater hydrus 65656565 NOKEY
// Comment:
// telegram=|3E44A5116565656570067AFB0030052F2F_0C13503400000DFD110A383731303134423032410B3B00000002FD74DC15C4016D3B178D29CC0113313400002F2F|
// {"media":"warm water","meter":"hydrus","name":"HydrusVater","id":"65656565","flow_m3h":0,"customer": "A20B410178","total_m3":3.45,"total_at_date_m3":3.431,"remaining_battery_life_y":15.321328,"at_datetime":"2020-09-13 23:59","total_at_date_m3": 3.431,"status":"OK","timestamp":"1111-11-11T11:11:11Z"}
// |HydrusVater;65656565;3.45;3.431;OK;1111-11-11 11:11.11
// {"media":"warm water","meter":"hydrus","name":"HydrusVater","id":"65656565","flow_m3h":0,"customer": "A20B410178","total_m3":3.45,"remaining_battery_life_y":15.321328,"target_datetime":"2020-09-13 23:59","target_m3": 3.431,"status":"OK","timestamp":"1111-11-11T11:11:11Z"}
// |HydrusVater;65656565;3.45;null;OK;1111-11-11 11:11.11
// Test: HydrusAES hydrus 64745666 NOKEY
// Comment:
@ -189,3 +189,9 @@ namespace
// telegram=|1E4424238B06204790607A2A0010D8_0413DDC00000426CBF23441382BB0000|
// {"media":"warm water","meter":"hydrus","name":"HydrusIzarRSWarm","id":"60904720","total_m3":49.373,"total_at_date_m3":48.002,"at_date":"2021-03-31","status":"OK","timestamp":"1111-11-11T11:11:11Z"}
// |HydrusIzarRSWarm;60904720;49.373;48.002;OK;1111-11-11 11:11.11
// Test: HydrusFoo hydrus 64641820 NOKEY
// Comment: Negative power values.
// telegram=|6344A5112018646470078C00D7900F002C256AB59B00F0F13032019092DE7A6A004007102F2F0C13896729004C1323462400CC101300000000CC201323462400426CDF2C0B3B0200F002FD742F0D025AC100C4016D3B17FE29CC01132841290001FD089F|
// {"at_date": "2022-12-31","target_datetime": "2023-09-30 23:59","flow_m3h": -0.002,"flow_temperature_c": 19.3,"id": "64641820","media": "water","meter": "hydrus","name": "HydrusFoo","remaining_battery_life_y": 9.240436,"status": "OK","timestamp": "1111-11-11T11:11:11Z","total_at_date_m3":244.623,"target_m3": 294.128,"total_m3": 296.789,"total_tariff1_at_date_m3": 0,"total_tariff2_at_date_m3": 244.623}
// |HydrusFoo;64641820;296.789;244.623;OK;1111-11-11 11:11.11

1661
src/driver_iem3000.cc 100644

Plik diff jest za duży Load Diff

Wyświetl plik

@ -1,75 +0,0 @@
/*
Copyright (C) 2017-2022 Fredrik Öhrström (gpl-3.0-or-later)
Copyright (C) 2018 David Mallon (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("iperl");
di.setDefaultFields("name,id,total_m3,max_flow_m3h,timestamp");
di.setMeterType(MeterType::WaterMeter);
di.addLinkMode(LinkMode::T1);
di.addDetection(MANUFACTURER_SEN, 0x06, 0x68);
di.addDetection(MANUFACTURER_SEN, 0x07, 0x68);
di.addDetection(MANUFACTURER_SEN, 0x07, 0x7c);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
});
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
addNumericFieldWithExtractor(
"total",
"The total water consumption recorded by this meter.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Volume,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Volume)
);
addNumericFieldWithExtractor(
"max_flow",
"The maxium flow recorded during previous period.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Flow,
VifScaling::Auto,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::VolumeFlow));
}
}
// Test: MoreWater iperl 12345699 NOKEY
// Comment: Test iPerl T1 telegram, that after decryption, has 2f2f markers.
// 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
// Test: WaterWater iperl 33225544 NOKEY
// Comment: Test iPerl T1 telegram not encrypted, which has no 2f2f markers.
// 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

Wyświetl plik

@ -1,5 +1,5 @@
/*
Copyright (C) 2022 Fredrik Öhrström (gpl-3.0-or-later)
Copyright (C) 2022-2023 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
@ -30,8 +30,10 @@ namespace
di.setDefaultFields("name,id,total_m3,target_m3,timestamp");
di.setMeterType(MeterType::WaterMeter);
di.addLinkMode(LinkMode::T1);
di.addDetection(MANUFACTURER_ITW, 0x07, 0x00);
di.addDetection(MANUFACTURER_ITW, 0x07, 0x03);
di.addDetection(MANUFACTURER_ITW, 0x07, 0x33);
di.addDetection(MANUFACTURER_ITW, 0x16, 0x00);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
});
@ -43,8 +45,8 @@ namespace
addLinkMode(LinkMode::T1);
addOptionalCommonFields("enhanced_id,meter_datetime");
addOptionalFlowRelatedFields("total_m3,total_backward_m3,volume_flow_m3h");
addOptionalLibraryFields("enhanced_id,meter_datetime");
addOptionalLibraryFields("total_m3,total_backward_m3,volume_flow_m3h");
addStringFieldWithExtractorAndLookup(
"status",
@ -58,7 +60,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffffff),
"OK",
{
@ -73,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)
@ -100,7 +102,7 @@ namespace
{
{
"WOOTA",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffffffff),
"",
{
@ -120,7 +122,7 @@ namespace
{
{
"WOOTB",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffff),
"",
{
@ -143,3 +145,14 @@ namespace
// telegram=|46449726560000183307725600001897263307AF0030052F2F_066D0E1015C82A000C13771252000C933C000000000B3B0400004C1361045200426CC12A03FD971C0000002F2F2F|
// {"media":"water","meter":"itron","name":"MoreWater","id":"18000056","meter_datetime":"2022-10-08 21:16:14","total_m3":521.277,"total_backward_m3":0,"volume_flow_m3h":0.004,"status":"OK","target_m3":520.461,"target_date":"2022-10-01","timestamp":"1111-11-11T11:11:11Z"}
// |MoreWater;18000056;521.277;520.461;1111-11-11 11:11.11
// Test: AnyWater itron 20310959 NOKEY
// telegram=|384497265909312000077a930000a0041360B50100066d101295f427004413ac570100426cdf2c047f0000060c027f6c2a0e79000000000000|
// {"enhanced_id": "000000000000","id": "20310959","media": "water","meter": "itron","meter_datetime": "2023-07-20 21:18:16","name": "AnyWater","status": "OK","target_date": "2022-12-31","target_m3": 87.98,"timestamp": "1111-11-11T11:11:11Z","total_m3": 111.968,"unknown_a": "WOOTA_C060000","unknown_b": "WOOTB_2A6C"}
// |AnyWater;20310959;111.968;87.98;1111-11-11 11:11.11
// Test: ColdWaterMeter itron 23362098 NOKEY
// Comment: Allmess cold water with Itron Module programmed with type 0x16
// 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

@ -0,0 +1,59 @@
/*
Copyright (C) 2023 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("iwmtx5");
di.setDefaultFields("name,id,status,total_m3,timestamp");
di.setMeterType(MeterType::WaterMeter);
di.addLinkMode(LinkMode::T1);
di.addDetection(MANUFACTURER_BMT, 0x07, 0x18);
di.addDetection(MANUFACTURER_BMT, 0x06, 0x18);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
});
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
addOptionalLibraryFields("meter_datetime");
addOptionalLibraryFields("total_m3");
addStringField(
"status",
"Status and error flags.",
PrintProperty::STATUS | PrintProperty::INCLUDE_TPL_STATUS);
}
}
// Test: WaterWater iwmtx5 22917370 00000000000000000000000000000000
// telegram=|5144b4097073912218078c00247a0308400571e9615249ede52eaae09f61908f027c3877f3330ae9079528b23173ce124bcc255393e60b173c0a9f274c42dd92e4b23c14e8a41f042903358df01dd9268ad4|
// {"id": "22917370","media": "water","meter": "iwmtx5","meter_datetime": "2023-05-11 10:38:24","name": "WaterWater","status": "PERMANENT_ERROR","timestamp": "1111-11-11T11:11:11Z","total_m3": 0.025}
// |WaterWater;22917370;PERMANENT_ERROR;0.025;1111-11-11 11:11.11
// Test: WarmWater2 iwmtx5 23329344 NOKEY
// telegram=|4244B4094493322318068C005B7A1C0000000C13072000000F05170000000000000000000000000000000000000000009D0000C20000C20000C8000000000000000000|
// {"id": "23329344","media": "warm water","meter": "iwmtx5","name": "WarmWater2","status": "OK","timestamp": "1111-11-11T11:11:11Z","total_m3": 2.007}
// |WarmWater2;23329344;OK;2.007;1111-11-11 11:11.11

Wyświetl plik

@ -214,11 +214,11 @@ namespace
// get the manufacture year
uint8_t yy = atoi(digits.substr(0, 2).c_str());
int manufacture_year = yy > 70 ? (1900 + yy) : (2000 + yy); // Maybe to adjust in 2070, if this code stills lives :D
setStringValue("manufacture_year", tostrprintf("%d", manufacture_year));
setStringValue("manufacture_year", tostrprintf("%d", manufacture_year), NULL);
// get the serial number
uint32_t serial_number = atoi(digits.substr(2, digits.size()).c_str());
setStringValue("serial_number", tostrprintf("%06d", serial_number));
setStringValue("serial_number", tostrprintf("%06d", serial_number), NULL);
// get letters
uchar supplier_code = '@' + (((origin[9] & 0x0F) << 1) | (origin[8] >> 7));
@ -226,7 +226,7 @@ namespace
uchar diameter = '@' + (((origin[8] & 0x03) << 3) | (origin[7] >> 5));
// build the prefix
string prefix = tostrprintf("%c%02d%c%c", supplier_code, yy, meter_type, diameter);
setStringValue("prefix", prefix);
setStringValue("prefix", prefix, NULL);
}
// get the remaining battery life (in year) and transmission period (in seconds)
@ -252,7 +252,7 @@ namespace
uint8_t h0_month = decoded_content[10] & 0xF;
uint8_t h0_day = decoded_content[9] & 0x1F;
setStringValue("last_month_measure_date", tostrprintf("%d-%02d-%02d", h0_year, h0_month%99, h0_day%99));
setStringValue("last_month_measure_date", tostrprintf("%d-%02d-%02d", h0_year, h0_month%99, h0_day%99), NULL);
// read the alarms:
IzarAlarms alarms {};

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)
@ -43,14 +43,15 @@ namespace
di.addDetection(MANUFACTURER_KAM, 0x0c, 0x30); // 302
di.addDetection(MANUFACTURER_KAM, 0x04, 0x40); // 303
di.addDetection(MANUFACTURER_KAM, 0x0c, 0x40); // 303
di.addDetection(MANUFACTURER_KAM, 0x04, 0x19); // 402
di.addDetection(MANUFACTURER_KAM, 0x04, 0x34); // 403
di.addDetection(MANUFACTURER_KAM, 0x0a, 0x34); // 403
di.addDetection(MANUFACTURER_KAM, 0x0b, 0x34); // 403
di.addDetection(MANUFACTURER_KAM, 0x0c, 0x34); // 403
di.addDetection(MANUFACTURER_KAM, 0x0d, 0x34); // 403
di.addDetection(MANUFACTURER_KAM, 0x04, 0x1c); // 602
di.addDetection(MANUFACTURER_KAM, 0x04, 0x35); // 603
di.addDetection(MANUFACTURER_KAM, 0x0c, 0x35); // 603
di.addDetection(MANUFACTURER_KAM, 0x04, 0x35); // 603
di.addDetection(MANUFACTURER_KAM, 0x0c, 0x35); // 603
di.addDetection(MANUFACTURER_KAM, 0x04, 0x39); // 803
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
@ -58,7 +59,8 @@ namespace
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
addOptionalCommonFields("on_time_h");
addOptionalLibraryFields("fabrication_no,meter_datetime,on_time_h,on_time_at_error_h");
addOptionalLibraryFields("flow_return_temperature_difference_c");
// Technical Description Multical 603 page 116 section 7.7.2 Information code types on serial communication.
addStringFieldWithExtractorAndLookup(
@ -72,7 +74,7 @@ namespace
{
{
"ERROR_FLAGS",
Translate::Type::BitToString,
Translate::MapType::BitToString,
AlwaysTrigger, MaskBits(0xffffffff),
"OK",
{
@ -118,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)
@ -129,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)
@ -140,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)
@ -151,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)
@ -162,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)
@ -173,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)
@ -184,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)
@ -195,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)
@ -206,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);
@ -216,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);
@ -235,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)
@ -247,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)
@ -269,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)
@ -312,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
@ -342,3 +344,18 @@ namespace
// telegram=|68464668084a72447744772d2c3404060000000406ce86000004ff073444020004ff08f8ce0100041411680300043B0f02000002593c19025da41104ff220000000004a5ff21c7d02700d916|
// {"forward_energy_m3c": 148532,"id": "77447744","media": "heat","meter": "kamheat","name": "Kamstrup_403_mbus","return_energy_m3c": 118520,"status": "OK","t1_temperature_c": 64.6,"t2_temperature_c": 45.16,"timestamp": "1111-11-11T11:11:11Z","total_energy_consumption_kwh": 34510,"total_volume_m3": 2232.49,"volume_flow_m3h": 0.527,"operating_time_h": 43489.183333}
// |Kamstrup_403_mbus;77447744;34510;2232.49;OK;1111-11-11 11:11.11
// Test: Kamstrup_402_wmbus kamheat 62215006 NOKEY
// telegram=|40442D2C0650216219048D2083A4E1162306FF78_040F2C3F000004FF07DBA40D0004FF08860B0D000414BA33140002FD170000043B620000000259A21E025DFA1B|
// {"media":"heat","meter":"kamheat","name":"Kamstrup_402_wmbus","id":"62215006","forward_energy_m3c":894171,"return_energy_m3c":854918,"t1_temperature_c":78.42,"t2_temperature_c":71.62,"total_energy_consumption_kwh":44922.222222,"total_volume_m3":13239.62,"volume_flow_m3h":0.098,"status":"OK","timestamp":"1111-11-11T11:11:11Z"}
// |Kamstrup_402_wmbus;62215006;44922.222222;13239.62;OK;1111-11-11 11:11.11
// Test: Kamstrup_MC603_mbus kamheat 32323232 NOKEY
// 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 minumum 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

@ -0,0 +1,198 @@
/*
Copyright (C) 2020-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/>.
@see https://www.lansensystems.com/media/1282/mbus_data_format_lan-wmbus-r4_v11_rev_3.pdf
*/
#include"meters_common_implementation.h"
namespace
{
struct Driver : public virtual MeterCommonImplementation
{
Driver(MeterInfo &mi, DriverInfo &di);
};
static bool ok = registerDriver([](DriverInfo&di)
{
di.setName("lansenrp");
di.setDefaultFields("name,id,status,total_routed_messages_counter,used_router_slots_counter,is_repeater_listening,timestamp");
di.setMeterType(MeterType::Repeater);
di.addLinkMode(LinkMode::C1);
di.addDetection(MANUFACTURER_LAS, 0x32, 0x0b);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
});
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
setMfctTPLStatusBits(
Translate::Lookup()
.add(Translate::Rule("TPL_STS", Translate::MapType::BitToString)
.set(MaskBits(0xe0))
.set(DefaultMessage("OK"))
.add(Translate::Map(0x04 ,"LOW_BATTERY", TestBit::Set))));
addStringField(
"status",
"Meter status from tpl status field.",
DEFAULT_PRINT_PROPERTIES |
PrintProperty::STATUS | PrintProperty::INCLUDE_TPL_STATUS);
addNumericFieldWithExtractor(
"total_routed_messages",
"Number of total routed messages since power up",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
);
addNumericFieldWithExtractor(
"used_router_slots",
"Used router slots (maximum 936)",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
.set(SubUnitNr(1))
);
addStringFieldWithExtractor(
"software_version",
"Software version of repeater",
DEFAULT_PRINT_PROPERTIES,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::SoftwareVersion)
);
addStringFieldWithExtractorAndLookup(
"is_repeater_listening",
"Is the repeater listening (YES/NO)",
DEFAULT_PRINT_PROPERTIES,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
.set(SubUnitNr(2)),
Translate::Lookup()
.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))
));
addNumericFieldWithExtractor(
"seconds_to_mode_change",
"Seconds to mode change (Listen -> Sleep or Sleep -> Listen). Maximum 32767 seconds",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
.set(SubUnitNr(3))
);
addNumericFieldWithExtractor(
"listen_timer_value",
"Value on parameter 'Listen timer'",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
.set(StorageNr(1))
);
addNumericFieldWithExtractor(
"pause_timer_value",
"Value on parameter 'Pause timer'",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
.set(StorageNr(2))
);
addStringFieldWithExtractorAndLookup(
"repeater_listening_on_weekdays",
"Shows which weekday(s) repeater is listening (MO/TU/WE/TH/FR/SA/SU)",
DEFAULT_PRINT_PROPERTIES,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
.set(StorageNr(3)),
Translate::Lookup()
.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))
.add(Translate::Map(0x04 ,"TU", TestBit::Set))
.add(Translate::Map(0x08 ,"WE", TestBit::Set))
.add(Translate::Map(0x10 ,"TH", TestBit::Set))
.add(Translate::Map(0x20 ,"FR", TestBit::Set))
.add(Translate::Map(0x40 ,"SA", TestBit::Set))
));
addNumericFieldWithExtractor(
"start_time_value",
"Value on parameter 'Start time', shown as minusted after midnight (-1=Not used)",
DEFAULT_PRINT_PROPERTIES,
Quantity::Dimensionless,
VifScaling::None, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Dimensionless)
.set(StorageNr(4))
);
addStringFieldWithExtractor(
"meter_datetime",
"Date and time when the meter sent the telegram.",
DEFAULT_PRINT_PROPERTIES,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::DateTime)
);
addNumericFieldWithExtractor(
"battery",
"Battery voltage.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Voltage,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::Voltage)
);
}
}
// Test: REPEAT lansenrp 00035946 NOKEY
// telegram=|54443330465903000B327A2B0000402F2F04FD3A946709008240FD3A600002FD0F9500818040FD3A0084C040FD3A8838000042FD3A28008201FD3A8C05C101FD3A7F8202FD3A3804066D35122EFB2B0002FD46D00C|
// {"media":"reserved","meter":"lansenrp","name":"REPEAT","id":"00035946","battery_v":3.28,"listen_timer_value_counter":40,"pause_timer_value_counter":1420,"seconds_to_mode_change_counter":14472,"start_time_value_counter":1080,"total_routed_messages_counter":616340,"used_router_slots_counter":96,"is_repeater_listening":"NO","meter_datetime":"2023-11-27 14:18:53","repeater_listening_on_weekdays":"FR MO SA SU TH TU WE","software_version":"0095","status":"OK","timestamp":"1111-11-11T11:11:11Z"}
// |REPEAT;00035946;OK;616340;96;NO;1111-11-11 11:11.11
// telegram=|54443330465903000B327A2B0400402F2F04FD3A946709008240FD3A600002FD0F9500818040FD3A0184C040FD3A8838000042FD3A28008201FD3A8C05C101FD3A088202FD3A3804066D35122EFB2B0002FD46D00C|
// {"media":"reserved","meter":"lansenrp","name":"REPEAT","id":"00035946","battery_v":3.28,"listen_timer_value_counter":40,"pause_timer_value_counter":1420,"seconds_to_mode_change_counter":14472,"start_time_value_counter":1080,"total_routed_messages_counter":616340,"used_router_slots_counter":96,"is_repeater_listening":"YES","meter_datetime":"2023-11-27 14:18:53","repeater_listening_on_weekdays":"WE","software_version":"0095","status":"POWER_LOW","timestamp":"1111-11-11T11:11:11Z"}
// |REPEAT;00035946;POWER_LOW;616340;96;YES;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
"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

@ -1,5 +1,5 @@
/*
Copyright (C) 2019-2022 Fredrik Öhrström (gpl-3.0-or-later)
Copyright (C) 2019-2023 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
@ -30,14 +30,16 @@ namespace
di.setDefaultFields("name,id,current_temperature_c,current_relative_humidity_rh,timestamp");
di.setMeterType(MeterType::TempHygroMeter);
di.addDetection(MANUFACTURER_LAS, 0x1b, 0x07);
di.addDetection(MANUFACTURER_LAS, 0x1b, 0x09);
di.setConstructor([](MeterInfo& mi, DriverInfo& di){ return shared_ptr<Meter>(new Driver(mi, di)); });
});
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
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))));
@ -53,7 +55,7 @@ namespace
"The current temperature.",
DEFAULT_PRINT_PROPERTIES,
Quantity::Temperature,
VifScaling::Auto,
VifScaling::Auto, DifSignedness::Signed,
FieldMatcher::build()
.set(MeasurementType::Instantaneous)
.set(VIFRange::ExternalTemperature)
@ -64,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)
@ -75,7 +77,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)
@ -87,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)
@ -99,7 +101,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)
@ -111,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)
@ -126,3 +128,8 @@ namespace
// telegram=|2e44333003020100071b7a634820252f2f0265840842658308820165950802fb1aae0142fb1aae018201fb1aa9012f|
// {"media":"room sensor","meter":"lansenth","name":"Tempoo","id":"00010203","status":"PERMANENT_ERROR SABOTAGE_ENCLOSURE","current_temperature_c":21.8,"current_relative_humidity_rh":43,"average_temperature_1h_c":21.79,"average_relative_humidity_1h_rh":43,"average_temperature_24h_c":21.97,"average_relative_humidity_24h_rh":42.5,"timestamp":"1111-11-11T11:11:11Z"}
// |Tempoo;00010203;21.8;43;1111-11-11 11:11.11
// Test: T2 lansenth 00060041 NOKEY
// telegram=|2E44333041000600091B7AA70020252F2F_0265DBF94265FC04820165610901FB1B2C41FB1B238101FB1B290223BB00|+0
// {"media":"room sensor","meter":"lansenth","name":"T2","id":"00060041","status":"OK","current_temperature_c":-15.73,"current_relative_humidity_rh":44,"average_temperature_1h_c":12.76,"average_relative_humidity_1h_rh":35,"average_temperature_24h_c":24.01,"average_relative_humidity_24h_rh":41,"on_time_h":4488,"timestamp":"1111-11-11T11:11:11Z"}
// |T2;00060041;-15.73;44;1111-11-11 11:11.11

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",
{
@ -117,7 +118,7 @@ namespace
addStringFieldWithExtractor(
"error_date",
"The date the error occured at. If no error, reads 2127-15-31 (FFFF).",
"The date the error occurred at. If no error, reads 2127-15-31 (FFFF).",
DEFAULT_PRINT_PROPERTIES,
FieldMatcher::build()
.set(MeasurementType::AtError)
@ -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

@ -36,8 +36,8 @@ namespace
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
addOptionalCommonFields("meter_datetime,model_version,parameter_set");
addOptionalFlowRelatedFields("flow_temperature_c,return_temperature_c");
addOptionalLibraryFields("meter_datetime,model_version,parameter_set");
addOptionalLibraryFields("flow_temperature_c,return_temperature_c");
addStringFieldWithExtractorAndLookup(
"status",
@ -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

@ -1,6 +1,6 @@
/*
Copyright (C) 2021 Olli Salonen (gpl-3.0-or-later)
Copyright (C) 2022 Fredrik Öhrström (gpl-3.0-or-later)
Copyright (C) 2022-2023 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
@ -39,8 +39,8 @@ namespace
Driver::Driver(MeterInfo &mi, DriverInfo &di) : MeterCommonImplementation(mi, di)
{
addOptionalCommonFields("meter_date,fabrication_no,operating_time_h,on_time_h,on_time_at_error_h,meter_datetime");
addOptionalFlowRelatedFields("total_m3,total_backward_m3,volume_flow_m3h");
addOptionalLibraryFields("meter_date,fabrication_no,operating_time_h,on_time_h,on_time_at_error_h,meter_datetime");
addOptionalLibraryFields("total_m3,total_backward_m3,volume_flow_m3h");
/* If the meter is recently commissioned, the target water consumption value is bogus.
The bits store 0xffffffff. Should we deal with this? Now a very large value is printed in the json.
@ -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",
{
@ -207,13 +207,13 @@ namespace
// Test: Mino minomess 15503451 NOKEY
// telegram=|6644496A1064035514377251345015496A0007EE0050052F2F#0C1359000000026CBE2B82046CA12B8C0413FFFFFFFF8D0493132CFBFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02FD1700002F2F|
// {"media":"water","meter":"minomess","name":"Mino","id":"15503451","meter_date":"2021-11-30","total_m3":0.059,"target_m3":244444.442,"target_date":"2021-11-01","status":"OK","timestamp":"1111-11-11T11:11:11Z"}
// |Mino;15503451;0.059;244444.442;OK;1111-11-11 11:11.11
// {"media":"water","meter":"minomess","name":"Mino","id":"15503451","meter_date":"2021-11-30","total_m3":0.059,"target_date":"2021-11-01","status":"OK","timestamp":"1111-11-11T11:11:11Z"}
// |Mino;15503451;0.059;null;OK;1111-11-11 11:11.11
// 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|
@ -223,4 +223,4 @@ namespace
// Test: Zenner_warm minomess 51413121 NOKEY
// telegram=|6644496A8753155518377221314151496A0106300050052F2F_0C1357000000026CEC2182046CE1218C0413000000808D0493132C33FE00008000008000008000008000008000008000008000008000008000008000008000008000008000008002FD1700002F2F|
// {"media":"warm water","meter":"minomess","name":"Zenner_warm","id":"51413121","meter_date":"2023-01-12","total_m3":0.057,"target_m3":80000,"target_date":"2023-01-01","status":"OK","timestamp":"1111-11-11T11:11:11Z"}
// |Zenner_warm;51413121;0.057;80000;OK;1111-11-11 11:11.11
// |Zenner_warm;51413121;0.057;80000;OK;1111-11-11 11:11.11

Wyświetl plik

@ -107,5 +107,5 @@ namespace
// Comment: 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=|2F446850313233347462A2_069F255900B029310000000306060906030609070606050509050505050407040605070500|
// {"media":"warm water","meter":"mkradio3","name":"Duschen","id":"34333231","total_m3":13.8,"target_m3":8.9,"current_date":"2023-04-27T02:00:00Z","prev_date":"2018-12-31T02:00:00Z","timestamp":"1111-11-11T11:11:11Z"}
// |Duschen;34333231;13.8;8.9;2023-04-27T02:00:00Z;2018-12-31T02:00:00Z;1111-11-11 11:11.11
// {"media":"warm water","meter":"mkradio3","name":"Duschen","id":"34333231","total_m3":13.8,"target_m3":8.9,"current_date":"2024-04-27T02:00:00Z","prev_date":"2018-12-31T02:00:00Z","timestamp":"1111-11-11T11:11:11Z"}
// |Duschen;34333231;13.8;8.9;2024-04-27T02:00:00Z;2018-12-31T02:00:00Z;1111-11-11 11:11.11

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)

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