2019-03-15 12:05:54 +00:00
/*
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"
using namespace std ;
struct MeterApator162 : public virtual WaterMeter , public virtual MeterCommonImplementation {
2019-05-21 12:19:54 +00:00
MeterApator162 ( WMBus * bus , MeterInfo & mi ) ;
2019-03-15 12:05:54 +00:00
// Total water counted through the meter
2019-05-04 15:38:10 +00:00
double totalWaterConsumption ( Unit u ) ;
2019-03-15 12:05:54 +00:00
bool hasTotalWaterConsumption ( ) ;
private :
2019-05-04 18:52:05 +00:00
2019-03-15 12:05:54 +00:00
void processContent ( Telegram * t ) ;
2019-05-04 18:52:05 +00:00
double total_water_consumption_m3_ { } ;
2019-03-15 12:05:54 +00:00
} ;
2019-05-21 12:19:54 +00:00
unique_ptr < WaterMeter > createApator162 ( WMBus * bus , MeterInfo & mi )
2019-05-04 18:52:05 +00:00
{
2019-05-21 12:19:54 +00:00
return unique_ptr < WaterMeter > ( new MeterApator162 ( bus , mi ) ) ;
2019-05-04 18:52:05 +00:00
}
2019-05-21 12:19:54 +00:00
MeterApator162 : : MeterApator162 ( WMBus * bus , MeterInfo & mi ) :
2019-06-06 15:28:20 +00:00
MeterCommonImplementation ( bus , mi , MeterType : : APATOR162 , MANUFACTURER_APA )
2019-03-15 12:05:54 +00:00
{
2019-05-04 18:52:05 +00:00
setEncryptionMode ( EncryptionMode : : AES_CBC ) ;
2019-03-15 12:05:54 +00:00
addMedia ( 0x06 ) ;
addMedia ( 0x07 ) ;
2019-05-04 17:56:17 +00:00
2019-06-06 15:28:20 +00:00
addLinkMode ( LinkMode : : T1 ) ;
addLinkMode ( LinkMode : : C1 ) ;
2019-05-04 17:56:17 +00:00
setExpectedVersion ( 0x05 ) ;
2019-05-04 18:52:05 +00:00
addPrint ( " total " , Quantity : : Volume ,
[ & ] ( Unit u ) { return totalWaterConsumption ( u ) ; } ,
" The total water consumption recorded by this meter. " ,
true , true ) ;
2019-03-15 12:05:54 +00:00
MeterCommonImplementation : : bus ( ) - > onTelegram ( calll ( this , handleTelegram , Telegram * ) ) ;
}
2019-05-04 15:38:10 +00:00
double MeterApator162 : : totalWaterConsumption ( Unit u )
2019-03-15 12:05:54 +00:00
{
2019-07-07 20:04:06 +00:00
assertQuantity ( u , Quantity : : Volume ) ;
return convert ( total_water_consumption_m3_ , Unit : : M3 , u ) ;
2019-03-15 12:05:54 +00:00
}
2019-05-04 18:52:05 +00:00
bool MeterApator162 : : hasTotalWaterConsumption ( )
2019-03-15 12:05:54 +00:00
{
2019-05-04 18:52:05 +00:00
return true ;
2019-03-15 12:05:54 +00:00
}
void MeterApator162 : : processContent ( Telegram * t )
{
// Meter record:
map < string , pair < int , DVEntry > > values ;
parseDV ( t , t - > content , t - > content . begin ( ) , t - > content . size ( ) , & values ) ;
2019-03-19 17:51:57 +00:00
// Unfortunately, the at-wmbus-16-2 is mostly a proprieatary protocol
// simple wrapped inside a wmbus telegram. Thus the parsing above ends
// immediately with a 0x0f dif which means: from now on, its vendor specific
// data structures.
// By examining some telegrams though, it looks like the total consumption
2019-08-12 09:47:39 +00:00
// counter is on offset 25 or 14. So we can fake a parse here, to make it easier
2019-03-19 17:51:57 +00:00
// to extract using the existing tools.
map < string , pair < int , DVEntry > > vendor_values ;
string total ;
2019-08-12 09:47:39 +00:00
// Current assumption of this proprietary protocol is that byte 13 tells
// us where the current total water consumption is located.
2019-09-06 16:38:35 +00:00
int o = 0 ;
if ( ( t - > content [ 13 ] & 0x80 ) = = 0x80 )
{
o = 25 ;
2019-08-12 09:47:39 +00:00
}
2019-09-06 16:38:35 +00:00
else
if ( ( t - > content [ 13 ] & 0x40 ) = = 0x40 )
{
o = 22 ;
2019-08-12 09:47:39 +00:00
}
2019-09-06 16:38:35 +00:00
else
if ( ( t - > content [ 13 ] & 0x10 ) = = 0x10 )
{
o = 14 ;
}
else
{
warning ( " (apator162) Unknown value in proprietary(unknown) apator162 protocol. Ignoring telegram. Found 0x%02x expected bit 0x10, 0x40 or 0x80 to be set. \n " , t - > content [ 13 ] ) ;
return ;
}
strprintf ( total , " %02x%02x%02x%02x " , t - > content [ o ] , t - > content [ o + 1 ] , t - > content [ o + 2 ] , t - > content [ o + 3 ] ) ;
debug ( " (apator162) Guessing offset to be %d from byte 0x%02x: total %s \n " , o , t - > content [ 13 ] , total . c_str ( ) ) ;
2019-10-14 18:26:31 +00:00
vendor_values [ " 0413 " ] = { 25 , DVEntry ( MeasurementType : : Instantaneous , 0x13 , 0 , 0 , 0 , total ) } ;
2019-03-15 12:05:54 +00:00
int offset ;
string key ;
2019-10-14 18:26:31 +00:00
if ( findKey ( MeasurementType : : Unknown , ValueInformation : : Volume , 0 , & key , & vendor_values ) ) {
2019-05-04 18:52:05 +00:00
extractDVdouble ( & vendor_values , key , & offset , & total_water_consumption_m3_ ) ;
2019-08-12 09:47:39 +00:00
//Adding explanation have to wait since it assumes that the dvparser could do something, but it could not here.
//t->addMoreExplanation(offset, " total consumption (%f m3)", total_water_consumption_m3_);
2019-03-15 12:05:54 +00:00
}
}