kopia lustrzana https://github.com/weetmuts/wmbusmeters
				
				
				
			Merge pull request #158 from avandorp/master
Add support for AquaMetro / Integra Topas Es Kr water meterpull/162/head
						commit
						c295bf6fba
					
				
							
								
								
									
										1
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										1
									
								
								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 \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,190 @@
 | 
			
		|||
/*
 | 
			
		||||
 Copyright (C) 2017-2019 Fredrik Öhrström
 | 
			
		||||
 | 
			
		||||
 This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 it under the terms of the GNU General Public License as published by
 | 
			
		||||
 the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
 This program is distributed in the hope that it will be useful,
 | 
			
		||||
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 GNU General Public License for more details.
 | 
			
		||||
 | 
			
		||||
 You should have received a copy of the GNU General Public License
 | 
			
		||||
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include"dvparser.h"
 | 
			
		||||
#include"meters.h"
 | 
			
		||||
#include"meters_common_implementation.h"
 | 
			
		||||
#include"wmbus.h"
 | 
			
		||||
#include"wmbus_utils.h"
 | 
			
		||||
#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(WMBus *bus, 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<WaterMeter> createTopasEsKr(WMBus *bus, MeterInfo &mi)
 | 
			
		||||
{
 | 
			
		||||
    return unique_ptr<WaterMeter>(new MeterTopasEsKr(bus, mi));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MeterTopasEsKr::MeterTopasEsKr(WMBus *bus, MeterInfo &mi) :
 | 
			
		||||
    MeterCommonImplementation(bus, 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<uchar> 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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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<WaterMeter> createRfmTX1(WMBus *bus, MeterInfo &m);
 | 
			
		|||
unique_ptr<ElectricityMeter> createEHZP(WMBus *bus, MeterInfo &m);
 | 
			
		||||
unique_ptr<ElectricityMeter> createESYSWM(WMBus *bus, MeterInfo &m);
 | 
			
		||||
unique_ptr<ElectricityMeter> createEBZWMBE(WMBus *bus, MeterInfo &m);
 | 
			
		||||
unique_ptr<WaterMeter> createTopasEsKr(WMBus *bus, MeterInfo &m);
 | 
			
		||||
GenericMeter *createGeneric(WMBus *bus, MeterInfo &m);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue