ReadingIdentifier::Ptr reading_id_parse(meter_protocol_t protocol, const char *string) { ReadingIdentifier::Ptr rid; switch (protocol) { case meter_protocol_d0: case meter_protocol_sml: case meter_protocol_oms: rid = ReadingIdentifier::Ptr(new ObisIdentifier(Obis(string))); break; case meter_protocol_fluksov2: { char type[13]; int channel; int ret = sscanf(string, "sensor%u/%12s", &channel, type); if (ret != 2) { throw vz::VZException("meter-fluksov4 failed"); } rid = ReadingIdentifier::Ptr(new ChannelIdentifier(channel+1)); //id->channel = channel + 1; /* increment by 1 to distinguish between +0 and -0 */ #if 0 if (strcmp(type, "consumption") == 0) { id->channel *= -1; } else if (strcmp(type, "power") != 0) { throw std::exception("type not found"); //return ERR; } #endif break; } case meter_protocol_file: case meter_protocol_exec: case meter_protocol_s0: case meter_protocol_ocr: case meter_protocol_modbus: case meter_protocol_w1therm: rid = ReadingIdentifier::Ptr(new StringIdentifier(string)); break; default: /* ignore other protocols which do not provide id's */ rid = ReadingIdentifier::Ptr(new NilIdentifier()); break; } return rid; }
TEST(Obis, Obis_strparsing) { Obis o1(0x1, 0x1, 97, 97, 0xff, 0xff); // 97 = SC_F Obis o2("1-1:F.F"); ASSERT_EQ(o1, o2); Obis o3(0x1, 0x1, 96, 98, 0xff, 0xff); // 96 = SC_C, 98 = SC_L Obis o4("1-1:C.L"); ASSERT_EQ(o3, o4); Obis o5(0x1, 0x1, 96, 99, 0xff, 0xff); // 96 = SC_C, 99 = SC_P Obis o6("1-1:C.P"); ASSERT_EQ(o5, o6); ASSERT_THROW(Obis o7("1-1:x:y"), vz::VZException); Obis o8("power-l1"); ASSERT_EQ(Obis("1-0:21.7"), o8); }
bool Obis::isAllNotGiven() const { return *this == Obis(); // compare this one with empty one from default constructor }
#include "common.h" #include <VZException.hpp> #define DC 0xff // not specified/not given #define SC_C 96 // special character "C" has obis code 96 according to http://www.mayor.de/lian98/doc.de/pdf/vdew-lh-lastgangzaehler-2127b3.pdf #define SC_F 97 #define SC_L 98 #define SC_P 99 //const Obis::aliases[] = { static obis_alias_t aliases[] = { // A B C D E F alias description // ==================================================================== // general {Obis( 1, 0, 1, 7, DC, DC), "power", "Wirkleistung (Summe)"}, {Obis( 1, 0, 21, 7, DC, DC), "power-l1", "Wirkleistung (Phase 1)"}, {Obis( 1, 0, 41, 7, DC, DC), "power-l2", "Wirkleistung (Phase 2)"}, {Obis( 1, 0, 61, 7, DC, DC), "power-l3", "Wirkleistung (Phase 3)"}, {Obis( 1, 0, 12, 7, DC, DC), "voltage", "Spannung (Mittelwert)"}, {Obis( 1, 0, 32, 7, DC, DC), "voltage-l1", "Spannung (Phase 1)"}, {Obis( 1, 0, 52, 7, DC, DC), "voltage-l2", "Spannung (Phase 2)"}, {Obis( 1, 0, 72, 7, DC, DC), "voltage-l3", "Spannung (Phase 3)"}, {Obis( 1, 0, 11, 7, DC, DC), "current", "Stromstaerke (Summe)"}, {Obis( 1, 0, 31, 7, DC, DC), "current-l1", "Stromstaerke (Phase 1)"}, {Obis( 1, 0, 51, 7, DC, DC), "current-l2", "Stromstaerke (Phase 2)"}, {Obis( 1, 0, 71, 7, DC, DC), "current-l3", "Stromstaerke (Phase 3)"}, {Obis( 1, 0, 14, 7, 0, DC), "frequency", "Netzfrequenz"},
TEST(MeterSML, EMH_basic) { char tempfilename[L_tmpnam+1]; ASSERT_NE(tmpnam_r(tempfilename), (char*)0); std::list<Option> options; options.push_back(Option("device", tempfilename)); MeterSML m(options); ASSERT_STREQ(m.device(), tempfilename) << "devicename not eq " << tempfilename; ASSERT_EQ(0, mkfifo(tempfilename, S_IRUSR|S_IWUSR)); int fd = open(tempfilename, O_RDWR); ASSERT_NE(-1, fd); ASSERT_NE(-1, m.open()); // now we can simulate some input by simply writing into fd std::vector<Reading> rds; rds.resize(10); // write one good data set writes_hex(fd, "1B1B1B1B010101017607003600001AFA6200620072630101760101070036044808FE09303232383038313601016331ED007607003600001AFB62006200726307017701093032323830383136017262016504487D897677078181C78203FF0101010104454D480177070100000000FF010101010930323238303831360177070100010801FF63018001621E52FF560008D1CF1B0177070100010802FF63018001621E52FF560000004E9C01770700006001FFFF010101010B303030323238303831360177070100010700FF0101621B52FF550000007001010163D201007607003600001AFC6200620072630201710163077A00001B1B1B1B1A019D37"); /* * manual parsing of input data: * 1B1B1B1B * 01010101 * 76 TL Field list of.., len = 6 * 07 1. list element, TL Field : octet string, len 6 (why not 7?) * 003600001AFA =transaction id * 62 00 2nd list element, TL field: u8, val=0 =group id * 62 00 3rd list element, TL field: u8, val=0 =abort on error * 72 4th list element, TL list of, len = 2 =message body * 630101 1st elem, TL u16, val=101 =tag ("public open req") * 76 2nd elem, TL list of, len = 6 * 01 opt codepage * 01 opt clientid * 07 str, len 6= 0036044808FE reqFileId * 09 3032323830383136 serverId * 01 opt time * 01 opt version * 63 5th elem, u16, val = 31ED =crc16 * 00 6th elem EndOfSMLMsg * 76 list of, len=6 * 07 tl octet string, len 6 = 003600001AFB = transaction id * 62 u8, 00 =groupid * 62 u8, 00 =abort on error * 72 list, len=2 = message body * 63 0701 =tag (get list response) * 77 = message body data list with 7 elements * 01 opt clientid * 09 str, len 8 =3032323830383136 serverId * 01 opt listname * 72 actSensorTime * 62 u8, val=01 * 65 u32, val=04487D89 * 76 valList * 77 * 07 str, l 6 =8181C78203FF objName 129-129:xC7... -> error code * 01 opt status * 01 opt valTime * 01 opt unit * 01 opt scaler * 04 str, l3 =454D48 value * 01 opt valueSignature * 77 * 07 str, l 6 =0100000000FF objName 1-0:0.0.0*FF * 01 * 01 * 01 * 01 * 09 str, l 8 =3032323830383136 "02280816" Eigentumsnr? * 01 * 77 * 07 str, l 6 =0100010801FF objName 1-0:1.8.1*FF * 63 u16 =0180 status * 01 * 62 u8, =1E unit -> Wh * 52 s8, =FF scaler (-> 10⁻1) * 56 signed int len 5 byte 0008D1CF1B * 01 * 77 * 07 str l 6 =0100010802FF objName 1-0:1.8.2*FF * 63 u16 =0180 * 01 * 62 u8 =1E * 52 s8 = FF * 56 s int, len 5 byte 0000004E9C * 01 * 77 * 07 str l 6 =00006001FFFF 0-0:96.1.FF*FF * 01 * 01 * 01 * 01 * 0B str l 10 = 30303032323830383136 "0002280816" * 01 * 77 * 07 str l 6 =0100010700FF objName 1-0:1.7.0*FF * 01 * 01 * 62 u8 = 1B unit * 52 s8 = FF scaler-> 10⁻1 * 55 s int32 = 00000070 -> 112 -> 11.2 * 01 * 01 opt listSignature * 01 opt actGatewayTime * 63 u16 =D201 crc16 * 00 EndOfSMLMsg * 76 * 07 str l 6 = 003600001AFC * 62 u8 = 00 * 62 u8 = 00 * 72 * 63 u16 = 0201 * 71 * 01 * 63 u16 = 077A crc * 00 EndOfSMLMsg * 00 * 1B1B1B1B * 1A019D37 */ // now read 3 readings: (currently the string values get's ignored. See MeterSML::_parse EXPECT_EQ(3, m.read(rds, 3)); // check obis data: ReadingIdentifier *p = rds[0].identifier().get(); double value = rds[0].value(); EXPECT_LE(abs(14796777.1-value), 0.1); ObisIdentifier *o = dynamic_cast<ObisIdentifier*>(p); ASSERT_NE((ObisIdentifier*)0, o); EXPECT_TRUE(Obis(1, 0, 1, 8, 1, 255)==(o->obis())); o = dynamic_cast<ObisIdentifier*>(rds[1].identifier().get()); ASSERT_NE((ObisIdentifier*)0, o); value = rds[1].value(); EXPECT_EQ(2012.4, value); EXPECT_TRUE(Obis(1, 0, 1, 8, 2, 255)==(o->obis())); o = dynamic_cast<ObisIdentifier*>(rds[2].identifier().get()); ASSERT_NE((ObisIdentifier*)0, o); value = rds[2].value(); EXPECT_LE(abs(11.2-value), 0.1); EXPECT_TRUE(Obis(1, 0, 1, 7, 0, 255)==(o->obis())); EXPECT_EQ(0, m.close()); EXPECT_EQ(0, close(fd)); EXPECT_EQ(0, unlink(tempfilename)); }