Add field_ prefix which is equivalent to json_ prefix.

pull/324/head
Fredrik Öhrström 2021-08-01 23:12:52 +02:00
rodzic 2c83c51db1
commit e4d3ec1e7e
15 zmienionych plików z 100 dodań i 37 usunięć

Wyświetl plik

@ -1,4 +1,7 @@
Added the field timestamp_ut to print the existing timestamp field
using unix timestamp seconds since 1970-01-01.
Daniel Glaser added support for the Aventies water meter! Thanks Daniel!
Mblnk added support for Qundis QWater5.5. Thanks Mblnk!

Wyświetl plik

@ -126,11 +126,11 @@ You can add the static json data `"address":"RoadenRd 456","city":"Stockholm"` t
wmbusmeters.conf setting:
```ini
json_address=RoadenRd 456
json_city=Stockholm
field_address=RoadenRd 456
field_city=Stockholm
```
If you add `json_floor=5` to the meter file `MyTapWater`, then you can have the meter tailored static json `"floor":"5"` added to telegrams handled by that particular meter.
If you add `field_floor=5` to the meter file `MyTapWater`, then you can have the meter tailored static json `"floor":"5"` added to telegrams handled by that particular meter. (The old prefix json_ still works.)
If you are running on a Raspberry PI with flash storage and you relay the data to
another computer using a shell command (`mosquitto_pub` or `curl` or similar) then you might want to remove `meterfiles` and `meterfilesaction` to minimize the writes to the local flash file system.

Wyświetl plik

@ -1,2 +1,2 @@
telegram=|2A442D2C998734761B168D2091D37CAC21576C78|02FF207100041308190000441308190000615B7F616713|
{"media":"cold water","meter":"multical21","name":"MyTapWater","id":"76348799","total_m3":6.408,"target_m3":6.408,"max_flow_m3h":0,"flow_temperature_c":127,"external_temperature_c":19,"current_status":"DRY","time_dry":"22-31 days","time_reversed":"","time_leaking":"","time_bursting":"","timestamp":"1111-11-11T11:11:11Z","floor":"5","address":"RoodRd 42"}
{"media":"cold water","meter":"multical21","name":"MyTapWater","id":"76348799","total_m3":6.408,"target_m3":6.408,"max_flow_m3h":0,"flow_temperature_c":127,"external_temperature_c":19,"current_status":"DRY","time_dry":"22-31 days","time_reversed":"","time_leaking":"","time_bursting":"","timestamp":"1111-11-11T11:11:11Z","floor":"5","address":"RoodRd 42","city":"Stockholm"}

Wyświetl plik

@ -440,16 +440,22 @@ shared_ptr<Configuration> parseCommandLine(int argc, char **argv) {
i++;
continue;
}
if (!strncmp(argv[i], "--json_", 7))
if (!strncmp(argv[i], "--json_", 7) ||
!strncmp(argv[i], "--field_", 8))
{
// For example: --json_floor=42
string json = string(argv[i]+7);
if (json == "") {
error("The json command cannot be empty.\n");
// or --field_floor=42
// they are equivalent.
int off = 7;
if (!strncmp(argv[i], "--field_", 8)) { off = 8; }
string extra_constant_field = string(argv[i]+off);
if (extra_constant_field == "") {
error("The extra constant field command cannot be empty.\n");
}
// The extra "floor"="42" will be pushed to the json.
debug("Added json %s\n", json.c_str());
c->jsons.push_back(json);
debug("Added extra constant field %s\n", extra_constant_field.c_str());
c->extra_constant_fields.push_back(extra_constant_field);
i++;
continue;
}

Wyświetl plik

@ -58,7 +58,7 @@ void parseMeterConfig(Configuration *c, vector<char> &buf, string file)
int bps {};
vector<string> telegram_shells;
vector<string> alarm_shells;
vector<string> jsons;
vector<string> extra_constant_fields;
debug("(config) loading meter file %s\n", file.c_str());
for (;;) {
@ -118,10 +118,13 @@ void parseMeterConfig(Configuration *c, vector<char> &buf, string file)
alarm_shells.push_back(p.second);
}
else
if (startsWith(p.first, "json_"))
if (startsWith(p.first, "json_") ||
startsWith(p.first, "field_"))
{
string keyvalue = p.first.substr(5)+"="+p.second;
jsons.push_back(keyvalue);
int off = 5;
if (startsWith(p.first, "field_")) { off = 6; }
string keyvalue = p.first.substr(off)+"="+p.second;
extra_constant_fields.push_back(keyvalue);
}
else
warning("Found invalid key \"%s\" in meter config file\n", p.first.c_str());
@ -182,7 +185,7 @@ void parseMeterConfig(Configuration *c, vector<char> &buf, string file)
}
if (use) {
vector<string> ids = splitMatchExpressions(id);
c->meters.push_back(MeterInfo(bus, name, mt, "", ids, key, modes, bps, telegram_shells, jsons));
c->meters.push_back(MeterInfo(bus, name, mt, "", ids, key, modes, bps, telegram_shells, extra_constant_fields));
}
return;
@ -562,6 +565,19 @@ void handleSelectedFields(Configuration *c, string s)
}
}
void handleAddedFields(Configuration *c, string s)
{
char buf[s.length()+1];
strcpy(buf, s.c_str());
char *saveptr {};
const char *tok = strtok_r(buf, ",", &saveptr);
while (tok != NULL)
{
c->added_fields.push_back(tok);
tok = strtok_r(NULL, ",", &saveptr);
}
}
void handleShell(Configuration *c, string cmdline)
{
c->telegram_shells.push_back(cmdline);
@ -572,9 +588,9 @@ void handleAlarmShell(Configuration *c, string cmdline)
c->alarm_shells.push_back(cmdline);
}
void handleJson(Configuration *c, string json)
void handleExtraConstantField(Configuration *c, string field)
{
c->jsons.push_back(json);
c->extra_constant_fields.push_back(field);
}
shared_ptr<Configuration> loadConfiguration(string root, string device_override, string listento_override)
@ -620,14 +636,18 @@ shared_ptr<Configuration> loadConfiguration(string root, string device_override,
else if (p.first == "addconversions") handleConversions(c, p.second);
else if (p.first == "logtimestamps") handleLogTimestamps(c, p.second);
else if (p.first == "selectfields") handleSelectedFields(c, p.second);
else if (p.first == "addfields") handleAddedFields(c, p.second);
else if (p.first == "shell") handleShell(c, p.second);
else if (p.first == "resetafter") handleResetAfter(c, p.second);
else if (p.first == "alarmshell") handleAlarmShell(c, p.second);
else if (startsWith(p.first, "json_"))
else if (startsWith(p.first, "json_") ||
startsWith(p.first, "field_"))
{
string s = p.first.substr(5);
int off = 5;
if (startsWith(p.first, "field_")) { off = 6; }
string s = p.first.substr(off);
string keyvalue = s+"="+p.second;
handleJson(c, keyvalue);
handleExtraConstantField(c, keyvalue);
}
else
{

Wyświetl plik

@ -110,8 +110,10 @@ struct Configuration
bool no_init {};
std::vector<Unit> conversions;
std::vector<std::string> selected_fields;
std::vector<std::string> added_fields;
std::vector<MeterInfo> meters;
std::vector<std::string> jsons; // Additional jsons to always add.
std::vector<std::string> extra_constant_fields; // Additional constant fields to always add to json.
// These extra constant fields can also be part of selected with selectfields or added with addfields.
~Configuration() = default;
};
@ -120,6 +122,7 @@ shared_ptr<Configuration> loadConfiguration(string root, string device_override,
void handleConversions(Configuration *c, string s);
void handleSelectedFields(Configuration *c, string s);
void handleAddedFields(Configuration *c, string s);
bool handleDevice(Configuration *c, string devicefile);
enum class LinkModeCalculationResultType

Wyświetl plik

@ -187,8 +187,9 @@ void list_shell_envs(Configuration *config, string meter_driver)
&ignore2, config->separator,
&ignore3,
&envs,
&config->jsons,
&config->selected_fields);
&config->extra_constant_fields,
&config->selected_fields,
&config->added_fields);
for (auto &e : envs)
{
@ -219,7 +220,11 @@ void list_fields(Configuration *config, string meter_driver)
string meterr = padLeft("meter", width);
printf("%s Meter driver.\n", meterr.c_str());
string timestamp = padLeft("timestamp", width);
printf("%s Timestamp when wmbusmeters received the telegram.\n", timestamp.c_str());
printf("%s Timestamp when wmbusmeters received the telegram. Local time for hr/fields UTC for json.\n", timestamp.c_str());
string timestamp_ut = padLeft("timestamp_ut", width);
printf("%s Unix timestamp when wmbusmeters received the telegram.\n", timestamp_ut.c_str());
string timestamp_lt = padLeft("timestamp_l", width);
printf("%s Unix timestamp when wmbusmeters received the telegram.\n", timestamp_ut.c_str());
string device = padLeft("device", width);
printf("%s The wmbus device that received the telegram.\n", device.c_str());
string rssi = padLeft("rssi_dbm", width);
@ -401,7 +406,7 @@ bool start(Configuration *config)
meter_manager_->whenMeterUpdated(
[&](Telegram *t,Meter *meter)
{
printer_->print(t, meter, &config->jsons, &config->selected_fields);
printer_->print(t, meter, &config->extra_constant_fields, &config->selected_fields, &config->added_fields);
oneshot_check(config, t, meter);
}
);

Wyświetl plik

@ -404,7 +404,7 @@ string MeterCommonImplementation::unixTimestampOfUpdate()
{
char ut[40];
memset(ut, 0, sizeof(ut));
sprintf(ut, "%zu", datetime_of_update_);
snprintf(ut, sizeof(ut)-1, "%zu", datetime_of_update_);
return string(ut);
}
@ -650,6 +650,16 @@ string concatFields(Meter *m, Telegram *t, char c, vector<Print> &prints, vector
s += m->datetimeOfUpdateHumanReadable() + c;
continue;
}
if (field == "timestamp_lt")
{
s += m->datetimeOfUpdateHumanReadable() + c;
continue;
}
if (field == "timestamp_utc")
{
s += m->datetimeOfUpdateRobot() + c;
continue;
}
if (field == "timestamp_ut")
{
s += m->unixTimestampOfUpdate() + c;
@ -767,7 +777,8 @@ void MeterCommonImplementation::printMeter(Telegram *t,
string *json,
vector<string> *envs,
vector<string> *more_json,
vector<string> *selected_fields)
vector<string> *selected_fields,
vector<string> *added_fields)
{
*human_readable = concatFields(this, t, '\t', prints_, conversions_, true, selected_fields);
*fields = concatFields(this, t, separator, prints_, conversions_, false, selected_fields);
@ -853,6 +864,9 @@ void MeterCommonImplementation::printMeter(Telegram *t,
envs->push_back(string("METER_MEDIA=")+media);
envs->push_back(string("METER_TYPE=")+meterDriver());
envs->push_back(string("METER_TIMESTAMP=")+datetimeOfUpdateRobot());
envs->push_back(string("METER_TIMESTAMP_UTC=")+datetimeOfUpdateRobot());
envs->push_back(string("METER_TIMESTAMP_UT=")+unixTimestampOfUpdate());
envs->push_back(string("METER_TIMESTAMP_LT=")+datetimeOfUpdateHumanReadable());
if (t->about.device != "")
{
envs->push_back(string("METER_DEVICE=")+t->about.device);

Wyświetl plik

@ -230,7 +230,8 @@ struct Meter
string *json,
vector<string> *envs,
vector<string> *more_json,
vector<string> *selected_fields) = 0;
vector<string> *selected_fields,
vector<string> *added_fields) = 0;
// The handleTelegram expects an input_frame where the DLL crcs have been removed.
// Returns true of this meter handled this telegram!

Wyświetl plik

@ -89,7 +89,8 @@ protected:
string *json,
vector<string> *envs,
vector<string> *more_json, // Add this json "key"="value" strings.
vector<string> *selected_fields); // Only print these fields. Json always everything.
vector<string> *selected_fields, // Only print these fields. Json always everything.
vector<string> *added_fields); // Added these fields for printing.
virtual void processContent(Telegram *t) = 0;

Wyświetl plik

@ -42,13 +42,14 @@ Printer::Printer(bool json, bool fields, char separator,
void Printer::print(Telegram *t, Meter *meter,
vector<string> *more_json,
vector<string> *selected_fields)
vector<string> *selected_fields,
vector<string> *added_fields)
{
string human_readable, fields, json;
vector<string> envs;
bool printed = false;
meter->printMeter(t, &human_readable, &fields, separator_, &json, &envs, more_json, selected_fields);
meter->printMeter(t, &human_readable, &fields, separator_, &json, &envs, more_json, selected_fields, added_fields);
if (shell_cmdlines_.size() > 0 || meter->shellCmdlines().size() > 0) {
printShells(meter, envs);

Wyświetl plik

@ -32,7 +32,7 @@ struct Printer {
MeterFileNaming naming,
MeterFileTimestamp timestamp);
void print(Telegram *t, Meter *meter, vector<string> *more_json, vector<string> *selected_fields);
void print(Telegram *t, Meter *meter, vector<string> *more_json, vector<string> *selected_fields, vector<string> *added_fields);
private:

Wyświetl plik

@ -2,5 +2,7 @@ loglevel=debug
device=must_be_overriden
logtelegrams=false
format=json
shell=echo METER =="$METER_JSON"== =="$METER_address"== =="$METER_floor"== > /tmp/wmbusmeters_meter_additional_json_test
json_address=RoodRd 42
shell=echo METER =="$METER_JSON"== =="$METER_address"== =="$METER_city"== =="$METER_floor"== =="$METER_elevator"== > /tmp/wmbusmeters_meter_additional_json_test
# The json_ prefix and field_ prefix are equivalent.
json_address=RoodRd 42
field_city=Stockholm

Wyświetl plik

@ -3,3 +3,4 @@ type=supercom587
id=12345678
key=
json_floor=5
field_elevator=ABC

Wyświetl plik

@ -8,7 +8,7 @@ TESTNAME="Test additional json from cmdline"
TESTRESULT="ERROR"
cat simulations/simulation_additional_json.txt | grep '^{' > $TEST/test_expected.txt
$PROG --format=json --json_floor=5 --json_address="RoodRd 42" simulations/simulation_additional_json.txt \
$PROG --format=json --json_floor=5 --json_address="RoodRd 42" --field_city="Stockholm" simulations/simulation_additional_json.txt \
MyTapWater multical21 76348799 "" \
> $TEST/test_output.txt 2> $TEST/test_stderr.txt
@ -41,6 +41,9 @@ METER_NAME
METER_MEDIA
METER_TYPE
METER_TIMESTAMP
METER_TIMESTAMP_UTC
METER_TIMESTAMP_UT
METER_TIMESTAMP_LT
METER_DEVICE
METER_RSSI_DBM
METER_TOTAL_M3
@ -69,16 +72,19 @@ if [ "$TESTRESULT" = "ERROR" ]; then echo ERROR: $TESTNAME; exit 1; fi
TESTNAME="Test additional json from wmbusmeters.conf and from meter file"
TESTRESULT="ERROR"
$PROG --useconfig=tests/config6 --device=simulations/simulation_shell.txt > $TEST/test_output.txt 2> $TEST/test_stderr.txt
$PROG --debug --useconfig=tests/config6 --device=simulations/simulation_shell.txt > $TEST/test_output.txt 2> $TEST/test_stderr.txt
if [ "$?" = "0" ]
then
INFO=$(cat /tmp/wmbusmeters_meter_additional_json_test | sed 's/"timestamp":"....-..-..T..:..:..Z"/"timestamp":"1111-11-11T11:11:11Z"/')
EXPECTED=$(echo 'METER =={"media":"warm water","meter":"supercom587","name":"Water","id":"12345678","total_m3":5.548,"timestamp":"1111-11-11T11:11:11Z","floor":"5","address":"RoodRd 42"}== ==RoodRd 42== ==5==')
EXPECTED=$(echo 'METER =={"media":"warm water","meter":"supercom587","name":"Water","id":"12345678","total_m3":5.548,"timestamp":"1111-11-11T11:11:11Z","floor":"5","elevator":"ABC","address":"RoodRd 42","city":"Stockholm"}== ==RoodRd 42== ==Stockholm== ==5== ==ABC==')
if [ "$INFO" = "$EXPECTED" ]
then
echo "OK: $TESTNAME"
TESTRESULT="OK"
else
echo "INFO =>$INFO<"
echo "EXPECTED=>$EXPECTED<"
fi
fi