Now supply the configuration on the command line instead of hard coded in main.

pull/5/head
weetmuts 2017-08-30 14:10:23 +02:00
rodzic d075beac50
commit 45f535692f
4 zmienionych plików z 91 dodań i 26 usunięć

76
main.cc
Wyświetl plik

@ -27,36 +27,76 @@
#include<string.h>
using namespace std;
void printMeter(Meter *meter) {
printf("%s\t%s\t% 3.3f m3\t%s\n",
meter->name().c_str(),
meter->id().c_str(),
meter->totalWaterConsumption(),
meter->datetimeOfUpdate().c_str());
}
int main(int argc, char **argv)
{
if (argc > 1) {
if (!strcmp(argv[1], "--verbose")) {
verboseEnabled(true);
} else {
printf("wmbusmeters version: " WMBUSMETERS_VERSION "\n\n");
printf("Usage: wmbusmeters [--verbose]\n");
exit(0);
}
if (argc < 2) {
printf("wmbusmeters version: " WMBUSMETERS_VERSION "\n\n");
printf("Usage: wmbusmeters [--verbose] [usbdevice] { [meter_name] [meter_id] [meter_key] }* \n");
exit(0);
}
int i=1;
if (!strcmp(argv[i], "--verbose")) {
verboseEnabled(true);
i++;
}
char *usbdevice = argv[i];
i++;
if (!usbdevice) error("You must supply the usb device to which the wmbus dongle is connected.\n");
verbose("Using usbdevice: %s\n", usbdevice);
if ((argc-i) % 3 != 0) {
error("For each meter you must supply a: name,id and key.\n");
}
int num_meters = (argc-i)/3;
verbose("Number of meters: %d\n", num_meters);
auto manager = createSerialCommunicationManager();
onExit(call(manager,stop));
auto wmbus = openIM871A("/dev/ttyUSB0", manager);
auto wmbus = openIM871A(usbdevice, manager);
wmbus->setLinkMode(C1a);
if (wmbus->getLinkMode()!=C1a) error("Could not set link mode to C1a\n");
auto house = createMultical21(wmbus, "MyHouseWater", "12345678", "00112233445566778899AABBCCDDEEFF");
if (num_meters > 0) {
Meter *meters[num_meters];
house->onUpdate([](Meter*meter){
printf("%s\t%s\t% 3.3f m3\t%s\n",
meter->name().c_str(),
meter->id().c_str(),
meter->totalWaterConsumption(),
meter->datetimeOfUpdate().c_str());
});
for (int m=0; m<num_meters; ++m) {
char *name = argv[m*3+i+0];
char *id = argv[m*3+i+1];
char *key = argv[m*3+i+2];
if (!isValidId(id)) error("Not a valid meter id \"%s\"\n", id);
if (!isValidKey(key)) error("Not a valid meter key \"%s\"\n", key);
verbose("Configuring meter: \"%s\" \"%s\" \"%s\"\n", name, id, key);
meters[m] = createMultical21(wmbus, name, id, key);
meters[m]->onUpdate(printMeter);
}
} else {
printf("No meters configured. Printing id:s of all telegrams heard! Add --verbose to get more data.\n");
printf("To configure a meter, add a triplet to the command line: name id key\n");
printf("Where name is your string identifying the meter.\n");
printf(" id is the 8 digits printed on the meter.\n");
printf(" key is 32 hex digits with the aes key.\n\n");
wmbus->onTelegram([](Telegram *t){
printf("Received telegram from id: %02x%02x%02x%02x \n",
t->a_field_address[0], t->a_field_address[1], t->a_field_address[2], t->a_field_address[3]);
});
}
manager->waitForStop();
}

Wyświetl plik

@ -101,12 +101,14 @@ void MeterMultical21::handleTelegram(Telegram *t) {
t->a_field_address[1] != id_[1] ||
t->a_field_address[0] != id_[0]) {
verbose("Ignoring meter %02x %02x %02x %02x \n",
t->a_field_address[3], t->a_field_address[2], t->a_field_address[1], t->a_field_address[0]);
verbose("Meter %s ignores message with id %02x%02x%02x%02x \n",
name_.c_str(),
t->a_field_address[0], t->a_field_address[1], t->a_field_address[2], t->a_field_address[3]);
return;
} else {
verbose("Update from meter %02x %02x %02x %02x!\n",
t->a_field_address[3], t->a_field_address[2], t->a_field_address[1], t->a_field_address[0]);
verbose("Meter %s receives update with id %02x%02x%02x%02x!\n",
name_.c_str(),
t->a_field_address[0], t->a_field_address[1], t->a_field_address[2], t->a_field_address[3]);
}
int cc_field = t->payload[0];

27
util.cc
Wyświetl plik

@ -23,6 +23,7 @@
#include<signal.h>
#include<stdarg.h>
#include<stddef.h>
#include<string.h>
#include<string>
using namespace std;
@ -73,17 +74,21 @@ int char2int(char input)
return -1;
}
void hex2bin(const char* src, vector<uchar> *target)
bool hex2bin(const char* src, vector<uchar> *target)
{
if (!src) return;
if (!src) return false;
while(*src && src[1]) {
if (*src == ' ') {
src++;
} else {
target->push_back(char2int(*src)*16 + char2int(src[1]));
int hi = char2int(*src);
int lo = char2int(src[1]);
if (hi<0 || lo<0) return false;
target->push_back(hi*16 + lo);
src += 2;
}
}
return true;
}
char const hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A','B','C','D','E','F'};
@ -126,3 +131,19 @@ void verbose(const char* fmt, ...) {
va_end(args);
}
}
bool isValidId(char *id)
{
if (strlen(id) != 8) return false;
for (int i=0; i<8; ++i) {
if (id[i]<'0' || id[i]>'9') return false;
}
return true;
}
bool isValidKey(char *key)
{
if (strlen(key) != 32) return false;
vector<uchar> tmp;
return hex2bin(key, &tmp);
}

4
util.h
Wyświetl plik

@ -32,7 +32,7 @@ typedef unsigned char uchar;
#define call(A,B) ([A](){A->B();})
#define calll(A,B,T) ([A](T t){A->B(t);})
void hex2bin(const char* src, std::vector<uchar> *target);
bool hex2bin(const char* src, std::vector<uchar> *target);
std::string bin2hex(std::vector<uchar> &target);
void xorit(uchar *srca, uchar *srcb, uchar *dest, int len);
@ -42,6 +42,8 @@ void verbose(const char* fmt, ...);
void verboseEnabled(bool b);
bool isValidId(char *id);
bool isValidKey(char *key);
#endif