kopia lustrzana https://github.com/weetmuts/wmbusmeters
				
				
				
			
		
			
				
	
	
		
			192 wiersze
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			192 wiersze
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
/*
 | 
						|
 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 <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;
 | 
						|
}
 |