diff --git a/.github/workflows/promote_snap.yml b/.github/workflows/promote_snap.yml new file mode 100644 index 0000000..acf465f --- /dev/null +++ b/.github/workflows/promote_snap.yml @@ -0,0 +1,26 @@ +name: Promote snap from edge to stable channel +on: + push: + tags: + - '*' + +jobs: + initial_sleep: + runs-on: ubuntu-latest + steps: + - name: Sleep for 30 minutes + uses: jakejarvis/wait-action@master + with: + time: '30m' + promote: + needs: initial_sleep + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - run: git fetch --prune --unshallow + - name: Install Snapcraft + uses: samuelmeuli/action-snapcraft@v1 + with: + snapcraft_token: ${{ secrets.snapcraft_token }} + - name: Run promote script + run: bash snap/promote_snap.sh \ No newline at end of file diff --git a/CHANGES b/CHANGES index 07fdd07..8628e37 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,12 @@ + +Avandorp added support for the AquaMetro / Integra Topas Es Kr water meter. +Thanks Avandorp! + +IzeCube added the Techem Compact V heatmeter! +Thanks IzeCube! Though we still need an example telegram for +testing this meter to prevent regressions. So it is currently +not as well supported as the other meters. + Version 0.9.35: 2020-08-23 Added support for alarms (shell command triggered) diff --git a/Makefile b/Makefile index aa14302..e2bdd16 100644 --- a/Makefile +++ b/Makefile @@ -139,6 +139,7 @@ METER_OBJS:=\ $(BUILD)/meter_rfmamb.o \ $(BUILD)/meter_rfmtx1.o \ $(BUILD)/meter_supercom587.o \ + $(BUILD)/meter_topaseskr.o \ $(BUILD)/meter_vario451.o \ $(BUILD)/meter_waterstarm.o \ $(BUILD)/printer.o \ diff --git a/README.md b/README.md index 5200487..199584c 100644 --- a/README.md +++ b/README.md @@ -222,34 +222,36 @@ rtl_wmbus (rtlwmbus) rtl_433 (rtl433) Supported water meters: +Apator at-wmbus-08 (apator08) (non-standard protocol) +Apator at-wmbus-16-2 (apator162) (non-standard protocol) +Aquametro/Integra Topas Es Kr (topaseskr) +Bmeters Hydrodigit (hydrodigit) (partly non-standard protocol) +Diehl/Sappel IZAR RC 868 I R4 PL (izar) (non-standard protocol) +Diehl HYDRUS (hydrus) +Honeywell Q400 (q400) Kamstrup Multical 21 (multical21) Kamstrup flowIQ 3100 (flowiq3100) Sontex Supercom 587 (supercom587) Sensus iPERL (iperl) -Apator at-wmbus-08 (apator08) (non-standard protocol) -Apator at-wmbus-16-2 (apator162) (non-standard protocol) Techem MK Radio 3 (mkradio3) (non-standard protocol) -Diehl/Sappel IZAR RC 868 I R4 PL (izar) (non-standard protocol) -Diehl HYDRUS (hydrus) -Bmeters Hydrodigit (hydrodigit) (partly non-standard protocol) -Honeywell Q400 (q400) Waterstar M (waterstarm) Supported heat cost allocators: -Qundis Q caloric (qcaloric) Innotas EurisII (eurisii) +Qundis Q caloric (qcaloric) Techem FHKV data II/III (fhkvdataiii) Supported heat meter: Heat meter Techem Compact V (compact5) (non-standard protocol) +(compact5 is unfortunately not quite supported since we lack a test telegram to prevent regressions) Heat meter Techem Vario 4 (vario451) (non-standard protocol) Heat meter Kamstrup Multical 302 (multical302) (in C1 mode, please open issue for T1 mode) Heat and Cooling meter Kamstrup Multical 403 (multical403) (in C1 mode) Supported room sensors: -Lansen Thermometer/Hygrometer (lansenth) Bmeters RFM-AMB Thermometer/Hygrometer (rfmamb) Elvaco CMa12w Thermometer (cma12w) +Lansen Thermometer/Hygrometer (lansenth) Supported smoke detectors: Lansen Smoke Detector (lansensm) @@ -261,10 +263,10 @@ Supported pulse counter: Lansen Pulse Counter (lansenpu) Supported electricity meters: -Tauron Amiplus (amiplus) (includes vendor apator and echelon) -EMH Metering (ehzp) Easy Meter ESYS-WM20 (esyswm) eBZ wMB-E01 (ebzwmbe) +EMH Metering (ehzp) +Tauron Amiplus (amiplus) (includes vendor apator and echelon) ``` The wmbus dongles imst871a can listen to one type of wmbus telegrams diff --git a/simulations/simulation_t1.txt b/simulations/simulation_t1.txt index b12a3df..bcbb974 100644 --- a/simulations/simulation_t1.txt +++ b/simulations/simulation_t1.txt @@ -153,3 +153,9 @@ telegram=|4644B4097172737405077AA5000610|1115F78184AB0F1D1E200000005904103103208 telegram=|3944FA122162092002067A3600202567C94D48D00DC47B11213E23383DB51968A705AAFA60C60E263D50CD259D7C9A03FD0C08000002FD0B0011| {"media":"warm water","meter":"waterstarm","name":"Woter","id":"20096221","meter_timestamp":"2020-07-30 10:40","total_m3":0.106,"total_backwards_m3":0,"current_status":"OK","meter_version":"000008","parameter_set":"1100","timestamp":"1111-11-11T11:11:11Z"} |Woter;20096221;0.106000;0.000000;OK;1111-11-11 11:11.11 + +# Test topaseskr water meter + +telegram=|4E44B40512345678F1077A310040052F2F|01FD08040C13991848004C1359423500CC101300000000CC201359423500426C7F2C0B3B00000002FD74DA10025AD300C4016D3B179F27CC011387124600| +{"media":"water","meter":"topaseskr","name":"Witer","id":"78563412","total_m3":481.899,"temperature_c":21.1,"current_flow_m3h":0,"battery_life_days_remaining_remaining":"4314","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","timestamp":"1111-11-11T11:11:11Z"} +|Witer;78563412;481.899000;21.100000;0.000000;354.259000;0.000000;2019-12-31;461.287000;2020-07-31 23:59;1111-11-11 11:11.11 diff --git a/snap/promote_snap.sh b/snap/promote_snap.sh new file mode 100644 index 0000000..9c74e54 --- /dev/null +++ b/snap/promote_snap.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +SNAP_NAME="wmbusmeters" +ARCH_LIST="arm64 armhf amd64" + +if [ -n "$(git describe --tags | grep -)" ]; then + GIT_REV="$(git describe --tags | cut -f1,2 -d'-')" + echo "$GIT_REV is branch not tag release, exiting.." + exit 1 +else + GIT_VER="$(git describe --tags)" + echo "This is release - $GIT_VER" +fi + +for arch in $ARCH_LIST +do + snap_build_version="$(snapcraft status --arch $arch $SNAP_NAME | grep edge | awk '{print $2}')" + + c=0 + while [[ "$GIT_VER" != "$snap_build_version" && $c -lt 10 ]]; do + echo "GIT release version "$GIT_VER" != snap latest edge version at snapcraft for $arch "$snap_build_version", iter : $c"; + ((c = $c + 1)); + sleep 300; + snap_build_version="$(snapcraft status --arch $arch $SNAP_NAME | grep edge | awk '{print $2}')" + done + + if [[ "$GIT_VER" != "$snap_build_version" ]]; then + echo "GIT release version "$GIT_VER" != snap latest edge version on snapcraft for $arch "$snap_build_version", exiting.."; + exit 1 + fi +done + +for arch in $ARCH_LIST +do + snap_build_id="$(snapcraft status --arch $arch $SNAP_NAME | grep edge | awk '{print $3}')" + echo "Snap build id for arch $arch - $snap_build_id, promoting to stable release" + snapcraft release $SNAP_NAME $snap_build_id stable +done diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 5411965..0a5ac80 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -35,7 +35,7 @@ parts: source-type: git override-pull: | snapcraftctl pull - if [ -n $(git describe --tags | grep -) ]; then + if [ -n "$(git describe --tags | grep -)" ]; then GIT_REV="$(git describe --tags | cut -f1,2 -d'-')" snapcraftctl set-version "$GIT_REV" snapcraftctl set-grade devel diff --git a/src/meter_topaseskr.cc b/src/meter_topaseskr.cc new file mode 100644 index 0000000..bccadb4 --- /dev/null +++ b/src/meter_topaseskr.cc @@ -0,0 +1,191 @@ +/* + Copyright (C) 2017-2020 Fredrik Öhrström + 2020 Avandorp + + 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 . +*/ + +#include"dvparser.h" +#include"meters.h" +#include"meters_common_implementation.h" +#include"wmbus.h" +#include"wmbus_utils.h" +#include"util.h" + +using namespace std; + +/* + AquaMetro / Integra water meter "TOPAS ES KR" + Models TOPAS ES KR 95077 95056 95345 95490 95373 95059 95065 95068 95071 95074 should be compatible. Only 95059 in one configuration tested. + Identifies itself with Manufacturer "AMT" and Version "f1" + Product leaflet and observation says the following values are sent: + Current total volume + Total volume at end of year-period day (that means: current total volume - total volume at end of year-period day = current year-periods volume up until now) + Total backward volume on end of year-period day or total backward volume in current year-period. Backward volume remains untested (luckily only 0 values encountered). + Date of end of last year-period day + Total volume at end of last month-period dateTime + DateTime of end of last month-period + Current flow rate + Battery life (days left) + Water temperature + + Example telegram: + telegram=|4E44B40512345678F1077A310040052F2F|01FD08040C13991848004C1359423500CC101300000000CC201359423500426C7F2C0B3B00000002FD74DA10025AD300C4016D3B179F27CC011387124600|+2 +*/ +struct MeterTopasEsKr : public virtual WaterMeter, public virtual MeterCommonImplementation { + MeterTopasEsKr(MeterInfo &mi); + + double totalWaterConsumption(Unit u); + bool hasTotalWaterConsumption(); + + double flowTemperature(Unit u); + bool hasFlowTemperature(); + +private: + void processContent(Telegram *t); + + double total_water_consumption_m3_ {}; + double flow_temperature_ {}; + double current_flow_m3h_ {}; + string battery_life_days_remaining_ {}; + double volume_year_period_m3_ {}; + double reverse_volume_year_period_m3_ {}; + double volume_month_period_m3_ {}; + string meter_yearly_period_date_; + string meter_month_period_datetime_; +}; + +unique_ptr createTopasEsKr(MeterInfo &mi) +{ + return unique_ptr(new MeterTopasEsKr(mi)); +} + +MeterTopasEsKr::MeterTopasEsKr(MeterInfo &mi) : + MeterCommonImplementation(mi, MeterType::TOPASESKR, MANUFACTURER_AMT) +{ + setExpectedTPLSecurityMode(TPLSecurityMode::AES_CBC_IV); + + addMedia(0x06); // specified temperature range is 0°C to 50 °C, not sure it ever reports 0x06 for warm water, possibly configurable + addMedia(0x07); + + addLinkMode(LinkMode::T1); + + addExpectedVersion(0xf1); + + addPrint("total", Quantity::Volume, + [&](Unit u){ return totalWaterConsumption(u); }, + "The total water consumption recorded by this meter.", + true, true); + addPrint("temperature", Quantity::Temperature, + [&](Unit u){ return flowTemperature(u); }, + "Current water temperature recorded by this meter.", + true, true); + addPrint("current_flow", Quantity::Flow, + [&](Unit u){ return current_flow_m3h_; }, + "Current flow.", + true, true); + addPrint("battery_life_days_remaining_remaining", Quantity::Text, + [&](){ return battery_life_days_remaining_; }, + "Battery life [days remaining].", + false, true); + addPrint("volume_year_period", Quantity::Volume, + [&](Unit u){ return volume_year_period_m3_; }, + "Volume up to end of last year-period.", + true, true); + addPrint("reverse_volume_year_period", Quantity::Volume, + [&](Unit u){ return reverse_volume_year_period_m3_; }, + "Reverse volume in this year-period (?).", + true, true); + addPrint("meter_year_period_start_date", Quantity::Text, + [&](){ return meter_yearly_period_date_; }, + "Meter date for year-period start.", + true, true); + addPrint("volume_month_period", Quantity::Volume, + [&](Unit u){ return volume_month_period_m3_; }, + "Volume up to end of last month-period.", + true, true); + addPrint("meter_month_period_start_datetime", Quantity::Text, + [&](){ return meter_month_period_datetime_; }, + "Meter timestamp for month-period start.", + true, true); + +} + +void MeterTopasEsKr::processContent(Telegram *t) +{ + int offset; + string key; + + if(findKey(MeasurementType::Unknown, ValueInformation::Volume, 0, 0, &key, &t->values)) { + extractDVdouble(&t->values, key, &offset, &total_water_consumption_m3_); + t->addMoreExplanation(offset, " total consumption (%f m3)", total_water_consumption_m3_); + } + if(findKey(MeasurementType::Unknown, ValueInformation::FlowTemperature, 0, 0, &key, &t->values)) { + extractDVdouble(&t->values, key, &offset, &flow_temperature_); + t->addMoreExplanation(offset, " water temperature (%f °C)", flow_temperature_); + } + if(findKey(MeasurementType::Unknown, ValueInformation::VolumeFlow, 0, 0, &key, &t->values)) { + extractDVdouble(&t->values, key, &offset, ¤t_flow_m3h_); + t->addMoreExplanation(offset, " current flow (%f m3/h)", current_flow_m3h_); + } + + extractDVdouble(&t->values, "4C13", &offset, &volume_year_period_m3_); + t->addMoreExplanation(offset, " volume up to end of last year-period (%f m3)", volume_year_period_m3_); + + extractDVdouble(&t->values, "CC1013", &offset, &reverse_volume_year_period_m3_); + t->addMoreExplanation(offset, " reverse volume in this year-period (?) (%f m3)", reverse_volume_year_period_m3_); + + struct tm date; + extractDVdate(&t->values, "426C", &offset, &date); + meter_yearly_period_date_ = strdate(&date); + t->addMoreExplanation(offset, " meter_start_year_period_date (%s)", meter_yearly_period_date_.c_str()); + + extractDVdouble(&t->values, "CC0113", &offset, &volume_month_period_m3_); + t->addMoreExplanation(offset, " volume up to end of last month-period (%f m3)", volume_month_period_m3_); + + struct tm datetime; + extractDVdate(&t->values, "C4016D", &offset, &datetime); + meter_month_period_datetime_ = strdatetime(&datetime); + t->addMoreExplanation(offset, " meter_start_month_period_datetime (%s)", meter_month_period_datetime_.c_str()); + + uint16_t tmp16; + extractDVuint16(&t->values, "02FD74", &offset, &tmp16); + strprintf(battery_life_days_remaining_, "%u", (unsigned int)tmp16); + t->addMoreExplanation(offset, " battery life (%s days remaining)", battery_life_days_remaining_.c_str()); + + vector data; + t->extractMfctData(&data); +} + +double MeterTopasEsKr::totalWaterConsumption(Unit u) +{ + assertQuantity(u, Quantity::Volume); + return convert(total_water_consumption_m3_, Unit::M3, u); +} + +bool MeterTopasEsKr::hasTotalWaterConsumption() +{ + return true; +} + +double MeterTopasEsKr::flowTemperature(Unit u) +{ + assertQuantity(u, Quantity::Temperature); + return convert(flow_temperature_, Unit::C, u); +} + +bool MeterTopasEsKr::hasFlowTemperature() +{ + return true; +} diff --git a/src/meters.h b/src/meters.h index caea2c2..939a624 100644 --- a/src/meters.h +++ b/src/meters.h @@ -57,6 +57,8 @@ X(supercom587,T1_bit, Water, SUPERCOM587, Supercom587) \ X(vario451, T1_bit, Heat, VARIO451, Vario451) \ X(waterstarm, C1_bit|T1_bit, Water,WATERSTARM, WaterstarM) \ + X(topaseskr, T1_bit, Water, TOPASESKR, TopasEsKr) \ + enum class MeterType { @@ -254,6 +256,7 @@ unique_ptr createRfmTX1(MeterInfo &m); unique_ptr createEHZP(MeterInfo &m); unique_ptr createESYSWM(MeterInfo &m); unique_ptr createEBZWMBE(MeterInfo &m); +unique_ptr createTopasEsKr(MeterInfo &m); GenericMeter *createGeneric(MeterInfo &m); #endif diff --git a/tests/test_listen_to_all.sh b/tests/test_listen_to_all.sh index 254cfa2..b8015b0 100755 --- a/tests/test_listen_to_all.sh +++ b/tests/test_listen_to_all.sh @@ -105,6 +105,9 @@ Received telegram from: 74737271 Received telegram from: 20096221 manufacturer: (DWZ) Lorenz, Germany device type: Warm Water (30°C-90°C) meter +Received telegram from: 78563412 + manufacturer: (AMT) INTEGRA METERING + device type: Water meter EOF RES=$($PROG --logfile=$LOGFILE --t1 simulations/simulation_t1.txt 2>&1) diff --git a/tests/test_t1_meters.sh b/tests/test_t1_meters.sh index 245b026..7365b89 100755 --- a/tests/test_t1_meters.sh +++ b/tests/test_t1_meters.sh @@ -32,7 +32,8 @@ METERS="MyWarmWater supercom587 12345678 NOKEY Elen3 ehzp 55995599 NOKEY Vatten apator08 004444dd NOKEY Wasser rfmtx1 74737271 NOKEY - Woter waterstarm 20096221 BEDB81B52C29B5C143388CBB0D15A051" + Woter waterstarm 20096221 BEDB81B52C29B5C143388CBB0D15A051 + Witer topaseskr 78563412 NOKEY" cat simulations/simulation_t1.txt | grep '^{' > $TEST/test_expected.txt $PROG --format=json simulations/simulation_t1.txt $METERS > $TEST/test_output.txt