kopia lustrzana https://github.com/weetmuts/wmbusmeters
Add --driverdir=<dir> and --driver=<file> for loading drivers from text files.
rodzic
440ea263b1
commit
04ed4d7628
1
Makefile
1
Makefile
|
@ -157,6 +157,7 @@ PROG_OBJS:=\
|
|||
$(BUILD)/bus.o \
|
||||
$(BUILD)/cmdline.o \
|
||||
$(BUILD)/config.o \
|
||||
$(BUILD)/drivers.o \
|
||||
$(BUILD)/dvparser.o \
|
||||
$(BUILD)/formula.o \
|
||||
$(BUILD)/mbus_rawtty.o \
|
||||
|
|
|
@ -414,6 +414,8 @@ As {options} you can use:
|
|||
--calculate_flow_f=flow_temperature_c
|
||||
--debug for a lot of information
|
||||
--donotprobe=<tty> do not auto-probe this tty. Use multiple times for several ttys or specify "all" for all ttys.
|
||||
--driver=<file> load a driver
|
||||
--driverdir=<dir> load all drivers in dir
|
||||
--exitafter=<time> exit program after time, eg 20h, 10m 5s
|
||||
--format=<hr/json/fields> for human readable, json or semicolon separated fields
|
||||
--help list all options
|
||||
|
|
|
@ -50,3 +50,18 @@ then
|
|||
else
|
||||
echo "conf dir: $ROOT/etc/wmbusmeters.d unchanged"
|
||||
fi
|
||||
|
||||
####################################################################
|
||||
##
|
||||
## Create /etc/wmbusmeters.drivers.d
|
||||
##
|
||||
|
||||
if [ ! -d "$ROOT"/etc/wmbusmeters.drivers.d ]
|
||||
then
|
||||
# Create the drivers directory
|
||||
mkdir -p "$ROOT"/etc/wmbusmeters.drivers.d
|
||||
chmod -R 755 "$ROOT"/etc/wmbusmeters.drivers.d
|
||||
echo "conf dir: created $ROOT/etc/wmbusmeters.drivers.d"
|
||||
else
|
||||
echo "conf dir: $ROOT/etc/wmbusmeters.drivers.d unchanged"
|
||||
fi
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
|
||||
#include"cmdline.h"
|
||||
#include"drivers.h"
|
||||
#include"meters.h"
|
||||
#include"util.h"
|
||||
|
||||
|
@ -62,17 +63,9 @@ shared_ptr<Configuration> parseCommandLine(int argc, char **argv)
|
|||
static shared_ptr<Configuration> parseNormalCommandLine(Configuration *c, int argc, char **argv)
|
||||
{
|
||||
int i = 1;
|
||||
// First find all logging flags, --silent --verbose --normal --debug
|
||||
while (argv[i] && argv[i][0] == '-')
|
||||
{
|
||||
if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) {
|
||||
c->need_help = true;
|
||||
return shared_ptr<Configuration>(c);
|
||||
}
|
||||
if (!strncmp(argv[i], "--device=", 9) || // Deprecated
|
||||
!strncmp(argv[i], "--overridedevice=", 17))
|
||||
{
|
||||
error("You can only use --overridedevice=xyz with --useconfig=xyz\n");
|
||||
}
|
||||
if (!strcmp(argv[i], "--silent")) {
|
||||
c->silent = true;
|
||||
i++;
|
||||
|
@ -93,6 +86,48 @@ static shared_ptr<Configuration> parseNormalCommandLine(Configuration *c, int ar
|
|||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[i], "--debug")) {
|
||||
c->debug = true;
|
||||
verboseEnabled(true);
|
||||
debugEnabled(true);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[i], "--trace")) {
|
||||
c->debug = true;
|
||||
c->trace = true;
|
||||
verboseEnabled(true);
|
||||
debugEnabled(true);
|
||||
traceEnabled(true);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// Now do the rest of the arguments.
|
||||
i = 1;
|
||||
while (argv[i] && argv[i][0] == '-')
|
||||
{
|
||||
if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) {
|
||||
c->need_help = true;
|
||||
return shared_ptr<Configuration>(c);
|
||||
}
|
||||
if (!strcmp(argv[i], "--silent") ||
|
||||
!strcmp(argv[i], "--verbose") ||
|
||||
!strcmp(argv[i], "--normal") ||
|
||||
!strcmp(argv[i], "--debug") ||
|
||||
!strcmp(argv[i], "--trace"))
|
||||
{
|
||||
// Handled already.
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(argv[i], "--device=", 9) || // Deprecated
|
||||
!strncmp(argv[i], "--overridedevice=", 17))
|
||||
{
|
||||
error("You can only use --overridedevice=xyz with --useconfig=xyz\n");
|
||||
}
|
||||
if (!strcmp(argv[i], "--version")) {
|
||||
c->version = true;
|
||||
return shared_ptr<Configuration>(c);
|
||||
|
@ -164,23 +199,6 @@ static shared_ptr<Configuration> parseNormalCommandLine(Configuration *c, int ar
|
|||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[i], "--debug")) {
|
||||
c->debug = true;
|
||||
verboseEnabled(true);
|
||||
debugEnabled(true);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[i], "--trace")) {
|
||||
c->debug = true;
|
||||
c->trace = true;
|
||||
verboseEnabled(true);
|
||||
debugEnabled(true);
|
||||
traceEnabled(true);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(argv[i], "--logtimestamps=", 16))
|
||||
{
|
||||
string ts = string(argv[i]+16);
|
||||
|
@ -588,6 +606,31 @@ static shared_ptr<Configuration> parseNormalCommandLine(Configuration *c, int ar
|
|||
i++;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(argv[i], "--driversdir=", 13))
|
||||
{
|
||||
size_t len = strlen(argv[i]) - 13;
|
||||
c->drivers_dir = string(argv[i]+13, len);
|
||||
if (!checkIfDirExists(c->drivers_dir.c_str()))
|
||||
{
|
||||
error("You must supply a valid directory to --driversdir=<dir>\n");
|
||||
}
|
||||
i++;
|
||||
loadDriversFromDir(c->drivers_dir);
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(argv[i], "--driver=", 9))
|
||||
{
|
||||
size_t len = strlen(argv[i]) - 9;
|
||||
string driver = string(argv[i]+9, len);
|
||||
if (!checkFileExists(driver.c_str()))
|
||||
{
|
||||
error("You must supply a valid file to --driver=<file>\n");
|
||||
}
|
||||
i++;
|
||||
loadDriver(driver);
|
||||
continue;
|
||||
}
|
||||
|
||||
error("Unknown option \"%s\"\n", argv[i]);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
|
||||
#include"config.h"
|
||||
#include"drivers.h"
|
||||
#include"meters.h"
|
||||
#include"units.h"
|
||||
|
||||
|
@ -679,12 +680,14 @@ shared_ptr<Configuration> loadConfiguration(string root, ConfigOverrides overrid
|
|||
string conf_dir = root;
|
||||
string conf_file = root+"/etc/wmbusmeters.conf";
|
||||
string conf_meter_dir = root+"/etc/wmbusmeters.d";
|
||||
string conf_drivers_dir = root+"/etc/wmbusmeters.drivers.d";
|
||||
|
||||
if (!checkFileExists(conf_file.c_str()))
|
||||
{
|
||||
conf_dir = root+"/etc";
|
||||
conf_file = root+"/wmbusmeters.conf";
|
||||
conf_meter_dir = root+"/wmbusmeters.d";
|
||||
conf_drivers_dir = root+"/wmbusmeters.drivers.d";
|
||||
}
|
||||
|
||||
debug("(config) loading %s\n", conf_file.c_str());
|
||||
|
@ -805,6 +808,8 @@ shared_ptr<Configuration> loadConfiguration(string root, ConfigOverrides overrid
|
|||
handleLogfile(c, overrides.logfile_override);
|
||||
}
|
||||
|
||||
loadDriversFromDir(conf_drivers_dir);
|
||||
|
||||
return shared_ptr<Configuration>(c);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ struct Configuration
|
|||
ConfigOverrides overrides;
|
||||
bool useconfig {};
|
||||
std::string config_root;
|
||||
std::string drivers_dir;
|
||||
bool need_help {};
|
||||
bool silent {};
|
||||
bool verbose {};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2023 Fredrik Öhrström (gpl-3.0-or-later)
|
||||
Copyright (C) 2023-2024 Fredrik Öhrström (gpl-3.0-or-later)
|
||||
|
||||
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
|
||||
|
@ -67,7 +67,7 @@ bool DriverDynamic::load(DriverInfo *di, const string &file)
|
|||
string default_fields = check_default_fields(xmqGetString(doc, NULL, "/driver/default_fields"), file);
|
||||
di->setDefaultFields(default_fields);
|
||||
|
||||
verbose("(driver) loading driver %s\n", name.c_str());
|
||||
verbose("(driver) loading driver %s from file %s\n", name.c_str(), file.c_str());
|
||||
|
||||
di->setDynamic(file, doc);
|
||||
|
||||
|
@ -90,7 +90,7 @@ DriverDynamic::DriverDynamic(MeterInfo &mi, DriverInfo &di) :
|
|||
{
|
||||
XMQDoc *doc = di.getDynamicDriver();
|
||||
|
||||
verbose("(driver) constructing driver %s from file %s\n",
|
||||
verbose("(driver) constructing driver %s from already loaded file %s\n",
|
||||
di.name().str().c_str(),
|
||||
fileName().c_str());
|
||||
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
Copyright (C) 2024 Fredrik Öhrström (gpl-3.0-or-later)
|
||||
|
||||
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<vector>
|
||||
#include<string>
|
||||
|
||||
#include"util.h"
|
||||
#include"drivers.h"
|
||||
#include"meters.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void loadDriversFromDir(std::string dir)
|
||||
{
|
||||
if (!checkIfDirExists(dir.c_str())) return;
|
||||
|
||||
vector<string> drivers;
|
||||
listFiles(dir, &drivers);
|
||||
|
||||
verbose("(drivers) scanning dir %s\n", dir.c_str());
|
||||
|
||||
for (string &file : drivers)
|
||||
{
|
||||
string filename = dir+"/"+file;
|
||||
string s = loadDriver(filename);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
Copyright (C) 2024 Fredrik Öhrström (gpl-3.0-or-later)
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#ifndef DRIVERS_H_
|
||||
#define DRIVERS_H_
|
||||
|
||||
#include<string>
|
||||
|
||||
void loadDriversFromDir(std::string dir);
|
||||
|
||||
#endif
|
|
@ -18,6 +18,7 @@
|
|||
#include"bus.h"
|
||||
#include"cmdline.h"
|
||||
#include"config.h"
|
||||
#include"drivers.h"
|
||||
#include"meters.h"
|
||||
#include"printer.h"
|
||||
#include"rtlsdr.h"
|
||||
|
@ -311,11 +312,17 @@ void list_meters(Configuration *config)
|
|||
{
|
||||
string mname = di->name().str();
|
||||
const char *info = toString(di->type());
|
||||
const char *where = "";
|
||||
const string f = di->getDynamicFileName();
|
||||
if (f != "")
|
||||
{
|
||||
where = f.c_str();
|
||||
}
|
||||
|
||||
if (config->list_meters_search == "" || \
|
||||
stringFoundCaseIgnored(info, config->list_meters_search) || \
|
||||
stringFoundCaseIgnored(mname.c_str(), config->list_meters_search)) \
|
||||
printf("%-14s %s\n", mname.c_str(), info);
|
||||
printf("%-14s %s %s\n", mname.c_str(), info, where);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,21 @@ vector<DriverInfo*> &allDrivers()
|
|||
return *registered_drivers_list_;
|
||||
}
|
||||
|
||||
void removeDriver(const string &name)
|
||||
{
|
||||
for (auto i = registered_drivers_list_->begin(); i != registered_drivers_list_->end(); i++)
|
||||
{
|
||||
if ((*i)->name().str() == name)
|
||||
{
|
||||
registered_drivers_list_->erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
registered_drivers_->erase(name);
|
||||
assert(registered_drivers_->count(name) == 0);
|
||||
}
|
||||
|
||||
void addRegisteredDriver(DriverInfo di)
|
||||
{
|
||||
verifyDriverLookupCreated();
|
||||
|
@ -192,13 +207,22 @@ string loadDriver(const string &file)
|
|||
{
|
||||
error("Failed to load driver from file: %s\n", file.c_str());
|
||||
}
|
||||
// Check that the driver name has not been registered before!
|
||||
if (lookupDriver(di.name().str()) != NULL)
|
||||
|
||||
// Check if the driver name has been registered before....
|
||||
DriverInfo *old = lookupDriver(di.name().str());
|
||||
if (old != NULL)
|
||||
{
|
||||
debug("Ignoring loaded driver %s %s since it is already registered!\n",
|
||||
di.name().str().c_str(),
|
||||
file.c_str());
|
||||
return di.name().str();
|
||||
if (old->getDynamicFileName() != "")
|
||||
{
|
||||
error("Newly loaded driver file %s tries to register the same name %s as driver file %s has already taken!\n",
|
||||
file.c_str(), di.name().str().c_str(), old->getDynamicFileName().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
verbose("(drivers) newly loaded driver %s overrides builtin driver\n",
|
||||
file.c_str(), di.name().str().c_str());
|
||||
removeDriver(di.name().str());
|
||||
}
|
||||
}
|
||||
|
||||
// Check that no other driver also triggers on the same detection values.
|
||||
|
@ -209,8 +233,30 @@ string loadDriver(const string &file)
|
|||
bool foo = p->detect(d.mfct, d.type, d.version);
|
||||
if (foo)
|
||||
{
|
||||
error("Newly loaded driver %s tries to register the same auto detect combo as driver %s alread has taken!\n",
|
||||
di.name().str().c_str(), p->name().str().c_str());
|
||||
string mfct = manufacturerFlag(d.mfct);
|
||||
if (p->getDynamicFileName() != "")
|
||||
{
|
||||
// It is not ok to override an previously file loaded driver!
|
||||
error("Newly loaded driver %s tries to register the same "
|
||||
"auto detect combo as driver %s alread has taken! mvt=%s,%02x,%02x\n",
|
||||
di.name().str().c_str(),
|
||||
p->name().str().c_str(),
|
||||
mfct.c_str(),
|
||||
d.version,
|
||||
d.type);
|
||||
}
|
||||
else
|
||||
{
|
||||
// It is ok to override a built in driver!
|
||||
verbose("(driver) newly loaded driver %s forces removal of builtin "
|
||||
"driver %s since it auto-detects the same combo! mvt=%s,%02x,%02x\n",
|
||||
di.name().str().c_str(),
|
||||
p->name().str().c_str(),
|
||||
mfct.c_str(),
|
||||
d.version,
|
||||
d.type);
|
||||
removeDriver(p->name().str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -236,6 +236,8 @@ DriverInfo pickMeterDriver(Telegram *t);
|
|||
// Return true for mbus and S2/C2/T2 drivers.
|
||||
bool driverNeedsPolling(DriverName& dn);
|
||||
|
||||
string loadDriver(const string &file);
|
||||
|
||||
vector<DriverInfo*>& allDrivers();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
195
src/xmq.h
195
src/xmq.h
|
@ -86,6 +86,7 @@ typedef struct XMQParseCallbacks XMQParseCallbacks;
|
|||
@XMQ_CONTENT_XML: xml detected
|
||||
@XMQ_CONTENT_HTML: html detected
|
||||
@XMQ_CONTENT_JSON: json detected
|
||||
@XMQ_CONTENT_TEXT: valid utf8 text input/output is selected
|
||||
|
||||
Specify the file/buffer content type.
|
||||
*/
|
||||
|
@ -97,7 +98,8 @@ typedef enum
|
|||
XMQ_CONTENT_HTMQ = 3,
|
||||
XMQ_CONTENT_XML = 4,
|
||||
XMQ_CONTENT_HTML = 5,
|
||||
XMQ_CONTENT_JSON = 6
|
||||
XMQ_CONTENT_JSON = 6,
|
||||
XMQ_CONTENT_TEXT = 7
|
||||
} XMQContentType;
|
||||
|
||||
/**
|
||||
|
@ -143,76 +145,37 @@ typedef enum
|
|||
} XMQTrimType;
|
||||
|
||||
/**
|
||||
XMQColorType: The normal coloring options for xmq.
|
||||
@COLORTYPE_xmq_c: Comments
|
||||
@COLORTYPE_xmq_q: Standalone quote.
|
||||
@COLORTYPE_xmq_e: Entity
|
||||
@COLORTYPE_xmq_ens: Element Namespace
|
||||
@COLORTYPE_xmq_en: Element Name
|
||||
@COLORTYPE_xmq_ek: Element Key
|
||||
@COLORTYPE_xmq_ekv: Element Key Value
|
||||
@COLORTYPE_xmq_ans: Attribute NameSpace
|
||||
@COLORTYPE_xmq_ak: Attribute Key
|
||||
@COLORTYPE_xmq_akv: Attribute Key Value
|
||||
@COLORTYPE_xmq_cp: Compound Parentheses
|
||||
@COLORTYPE_xmq_uw: Unicode Whitespace
|
||||
@COLORTYPE_xmq_tw: Tab Whitespace
|
||||
XMQSyntax:
|
||||
@SYNTAX_C: Comments
|
||||
@SYNTAX_Q: Standalone quote.
|
||||
@SYNTAX_E: Entity
|
||||
@SYNTAX_ENS: Element Namespace
|
||||
@SYNTAX_EN: Element Name
|
||||
@SYNTAX_EK: Element Key
|
||||
@SYNTAX_EKV: Element Key Value
|
||||
@SYNTAX_ANS: Attribute NameSpace
|
||||
@SYNTAX_AK: Attribute Key
|
||||
@SYNTAX_AKV: Attribute Key Value
|
||||
@SYNTAX_CP: Compound Parentheses
|
||||
@SYNTAX_NDC: Namespace declaration
|
||||
@SYNTAX_UW: Unicode Whitespace
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
COLORTYPE_xmq_c = 0, // Comments
|
||||
COLORTYPE_xmq_q = 1, // Standalone quote.
|
||||
COLORTYPE_xmq_e = 2, // Entity
|
||||
COLORTYPE_xmq_ens = 3, // Element Namespace
|
||||
COLORTYPE_xmq_en = 4, // Element Name
|
||||
COLORTYPE_xmq_ek = 5, // Element Key
|
||||
COLORTYPE_xmq_ekv = 6, // Element Key Value
|
||||
COLORTYPE_xmq_ans = 7, // Attribute NameSpace
|
||||
COLORTYPE_xmq_ak = 8, // Attribute Key
|
||||
COLORTYPE_xmq_akv = 9, // Attribute Key Value
|
||||
COLORTYPE_xmq_cp = 10, // Compound Parentheses
|
||||
COLORTYPE_xmq_uw = 11, // Unicode Whitespace
|
||||
} XMQColorType;
|
||||
|
||||
/**
|
||||
XMQColor:
|
||||
|
||||
Map token type into color index.
|
||||
*/
|
||||
typedef enum XMQColor {
|
||||
COLOR_none,
|
||||
COLOR_whitespace,
|
||||
COLOR_unicode_whitespace,
|
||||
COLOR_indentation_whitespace,
|
||||
COLOR_equals,
|
||||
COLOR_brace_left,
|
||||
COLOR_brace_right,
|
||||
COLOR_apar_left,
|
||||
COLOR_apar_right,
|
||||
COLOR_cpar_left,
|
||||
COLOR_cpar_right,
|
||||
COLOR_quote,
|
||||
COLOR_entity,
|
||||
COLOR_comment,
|
||||
COLOR_comment_continuation,
|
||||
COLOR_ns_colon,
|
||||
COLOR_element_ns,
|
||||
COLOR_element_name,
|
||||
COLOR_element_key,
|
||||
COLOR_element_value_text,
|
||||
COLOR_element_value_quote,
|
||||
COLOR_element_value_entity,
|
||||
COLOR_element_value_compound_quote,
|
||||
COLOR_element_value_compound_entity,
|
||||
COLOR_attr_ns,
|
||||
COLOR_attr_ns_declaration,
|
||||
COLOR_attr_key,
|
||||
COLOR_attr_value_text,
|
||||
COLOR_attr_value_quote,
|
||||
COLOR_attr_value_entity,
|
||||
COLOR_attr_value_compound_quote,
|
||||
COLOR_attr_value_compound_entity,
|
||||
} XMQColor;
|
||||
SYNTAX_C = 0, // Comments
|
||||
SYNTAX_Q = 1, // Standalone quote.
|
||||
SYNTAX_E = 2, // Entity
|
||||
SYNTAX_ENS = 3, // Element Namespace
|
||||
SYNTAX_EN = 4, // Element Name
|
||||
SYNTAX_EK = 5, // Element Key
|
||||
SYNTAX_EKV = 6, // Element Key Value
|
||||
SYNTAX_ANS = 7, // Attribute NameSpace
|
||||
SYNTAX_AK = 8, // Attribute Key
|
||||
SYNTAX_AKV = 9, // Attribute Key Value
|
||||
SYNTAX_CP = 10, // Compound Parentheses
|
||||
SYNTAX_NDC = 11, // Namespace declaration
|
||||
SYNTAX_UW = 12, // Unicode Whitespace
|
||||
} XMQSyntax;
|
||||
|
||||
/**
|
||||
XMQReader:
|
||||
|
@ -281,21 +244,6 @@ typedef enum
|
|||
*/
|
||||
typedef XMQProceed (*XMQNodeCallback)(XMQDoc *doc, XMQNode *node, void *user_data);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////// FUNCTIONS /////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
xmqDetectContentType:
|
||||
@start: points to first byte of buffer to scan for content type
|
||||
@stop: points to byte after buffer
|
||||
|
||||
Detect the content type xmq/xml/html/json by examining a few leading
|
||||
non-whitespace words/characters.
|
||||
*/
|
||||
XMQContentType xmqDetectContentType(const char *start, const char *stop);
|
||||
|
||||
/**
|
||||
XMQParseError:
|
||||
@XMQ_ERROR_CANNOT_READ_FILE: file not found or cannot be opened for reading.
|
||||
|
@ -331,6 +279,7 @@ XMQContentType xmqDetectContentType(const char *start, const char *stop);
|
|||
*/
|
||||
typedef enum
|
||||
{
|
||||
XMQ_ERROR_NONE = 0,
|
||||
XMQ_ERROR_CANNOT_READ_FILE = 1,
|
||||
XMQ_ERROR_OOM = 2,
|
||||
XMQ_ERROR_NOT_XMQ = 3,
|
||||
|
@ -359,25 +308,43 @@ typedef enum
|
|||
XMQ_ERROR_EXPECTED_HTML = 26,
|
||||
XMQ_ERROR_EXPECTED_JSON = 27,
|
||||
XMQ_ERROR_PARSING_XML = 28,
|
||||
XMQ_ERROR_PARSING_HTML = 29
|
||||
XMQ_ERROR_PARSING_HTML = 29,
|
||||
XMQ_WARNING_QUOTES_NEEDED = 100
|
||||
} XMQParseError;
|
||||
|
||||
|
||||
const char *xmqParseErrorToString(XMQParseError e);
|
||||
|
||||
/** Allocate an empty XMQParseCallback structure. All callbacks are NULL and none will be called. */
|
||||
XMQParseCallbacks *xmqNewParseCallbacks();
|
||||
|
||||
/** Free the XMQParseCallback structure. */
|
||||
void xmqFreeParseCallbacks(XMQParseCallbacks *cb);
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////// FUNCTIONS /////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
xmqSetupParseCallbacksNoopTokens:
|
||||
xmqDetectContentType:
|
||||
@start: points to first byte of buffer to scan for content type
|
||||
@stop: points to byte after buffer
|
||||
|
||||
When tokenizing only, for coloring or debugging, you can
|
||||
use the setup functions below for a few standardized handlers.
|
||||
Detect the content type xmq/xml/html/json by examining a few leading
|
||||
non-whitespace words/characters.
|
||||
*/
|
||||
XMQContentType xmqDetectContentType(const char *start, const char *stop);
|
||||
|
||||
/**
|
||||
xmqParseErrorToString:
|
||||
@e: Translate this error to a human readable string.
|
||||
*/
|
||||
void xmqSetupParseCallbacksNoopTokens(XMQParseCallbacks *state);
|
||||
const char *xmqParseErrorToString(XMQParseError e);
|
||||
|
||||
/**
|
||||
xmqNewParseCallbacks:
|
||||
|
||||
Allocate an empty XMQParseCallback structure. All callbacks are NULL and none will be called.
|
||||
*/
|
||||
XMQParseCallbacks *xmqNewParseCallbacks();
|
||||
|
||||
/**
|
||||
xmqFreeParseCallbacks:
|
||||
|
||||
Free the XMQParseCallback structure.
|
||||
*/
|
||||
void xmqFreeParseCallbacks(XMQParseCallbacks *cb);
|
||||
|
||||
/**
|
||||
xmqSetupParseCallbacksColorizeTokens:
|
||||
|
@ -469,6 +436,20 @@ XMQDoc *xmqNewDoc();
|
|||
*/
|
||||
void xmqSetDocSourceName(XMQDoc *doq, const char *source_name);
|
||||
|
||||
/**
|
||||
xmqGetOriginalContentType:
|
||||
|
||||
If available, return the original content type (xmq/htmq/xml/html/json/text) of this document.
|
||||
*/
|
||||
XMQContentType xmqGetOriginalContentType(XMQDoc *doq);
|
||||
|
||||
/**
|
||||
xmqGetOriginalSize:
|
||||
|
||||
If available, return the size of the original content, ie the loaded file size.
|
||||
*/
|
||||
size_t xmqGetOriginalSize(XMQDoc *doq);
|
||||
|
||||
/**
|
||||
xmqGetRootNode:
|
||||
|
||||
|
@ -542,10 +523,10 @@ void xmqSetUseColor(XMQOutputSettings *os, bool use_color);
|
|||
void xmqSetEscapeNewlines(XMQOutputSettings *os, bool escape_newlines);
|
||||
void xmqSetEscapeNon7bit(XMQOutputSettings *os, bool escape_non_7bit);
|
||||
void xmqSetOutputFormat(XMQOutputSettings *os, XMQContentType output_format);
|
||||
//void xmqSetColoring(XMQOutputSettings *os, XMQColoring coloring);
|
||||
void xmqSetRenderFormat(XMQOutputSettings *os, XMQRenderFormat render_to);
|
||||
void xmqSetRenderRaw(XMQOutputSettings *os, bool render_raw);
|
||||
void xmqSetRenderOnlyStyle(XMQOutputSettings *os, bool only_style);
|
||||
void xmqSetRenderStyle(XMQOutputSettings *os, const char *render_style);
|
||||
void xmqSetWriterContent(XMQOutputSettings *os, XMQWriter content);
|
||||
void xmqSetWriterError(XMQOutputSettings *os, XMQWriter error);
|
||||
|
||||
|
@ -729,27 +710,21 @@ void xmqRenderHtmlSettings(XMQOutputSettings *settings,
|
|||
const char *use_class);
|
||||
|
||||
/**
|
||||
xmqOverrideColorType:
|
||||
xmqOverrideColor:
|
||||
@settings:
|
||||
@render_style: Use "" for the default render_style
|
||||
@sc: The syntax element you want to change the color for.
|
||||
|
||||
Change the color strings for the given color type. You have to run xmqSetupDefaultColors first.
|
||||
*/
|
||||
void xmqOverrideColorType(XMQOutputSettings *settings,
|
||||
XMQColorType ct,
|
||||
const char *pre,
|
||||
const char *post,
|
||||
const char *ns);
|
||||
|
||||
/**
|
||||
xmqOverrideColor:
|
||||
|
||||
Change the color strings for the given color. You have to run xmqSetupDefaultColors first.
|
||||
*/
|
||||
void xmqOverrideColor(XMQOutputSettings *settings,
|
||||
XMQColor c,
|
||||
const char *render_style,
|
||||
XMQSyntax sc,
|
||||
const char *pre,
|
||||
const char *post,
|
||||
const char *ns);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
_hideRBfromEditor
|
||||
#endif
|
||||
|
|
|
@ -16,10 +16,10 @@ mkdir -p $TEST
|
|||
TESTNAME="Test config override with oneshot"
|
||||
TESTRESULT="ERROR"
|
||||
|
||||
cat simulations/serial_aes.msg | grep '^{' | jq --sort-keys . | tr -d '#' > $TEST/test_expected.txt
|
||||
cat simulations/serial_aes.msg | grep '^{' | jq . --sort-keys | tr -d '#' > $TEST/test_expected.txt
|
||||
cat simulations/serial_aes.msg | grep '^[CT]' | tr -d '#' > $TEST/test_input.txt
|
||||
|
||||
cat $TEST/test_input.txt | $PROG --useconfig=tests/config9 --overridedevice=stdin:rtlwmbus --oneshot 2> $TEST/test_stderr.txt | jq --sort-keys . > $TEST/test_output.txt
|
||||
cat $TEST/test_input.txt | $PROG --useconfig=tests/config9 --overridedevice=stdin:rtlwmbus --oneshot 2> $TEST/test_stderr.txt | jq . --sort-keys > $TEST/test_output.txt
|
||||
|
||||
if ! grep -q "(main) all meters have received at least one update, stopping." $TEST/test_stderr.txt
|
||||
then
|
||||
|
@ -35,6 +35,10 @@ then
|
|||
echo "OK: $TESTNAME"
|
||||
TESTRESULT="OK"
|
||||
else
|
||||
if [ "$USE_MELD" = "true" ]
|
||||
then
|
||||
meld $TEST/test_expected.txt $TEST/test_response.txt
|
||||
fi
|
||||
echo "ERROR: $TESTNAME"
|
||||
exit 1
|
||||
fi
|
||||
|
@ -42,11 +46,11 @@ fi
|
|||
TESTNAME="Test config override with exitafter"
|
||||
TESTRESULT="ERROR"
|
||||
|
||||
cat simulations/serial_aes.msg | grep '^{' | jq --sort-keys . | tr -d '#' > $TEST/test_expected.txt
|
||||
cat simulations/serial_aes.msg | grep '^{' | jq . --sort-keys | tr -d '#' > $TEST/test_expected.txt
|
||||
cat simulations/serial_aes.msg | grep '^[CT]' | tr -d '#' > $TEST/test_input.txt
|
||||
|
||||
# Read from stdin
|
||||
{ cat $TEST/test_input.txt ; sleep 4; } | $PROG --useconfig=tests/config9 --overridedevice=stdin:rtlwmbus --exitafter=1s 2> $TEST/test_stderr.txt | jq --sort-keys . > $TEST/test_output.txt
|
||||
{ cat $TEST/test_input.txt ; sleep 4; } | $PROG --useconfig=tests/config9 --overridedevice=stdin:rtlwmbus --exitafter=1s 2> $TEST/test_stderr.txt | jq . --sort-keys > $TEST/test_output.txt
|
||||
|
||||
if ! grep -q "(serial) exit after " $TEST/test_stderr.txt
|
||||
then
|
||||
|
|
Ładowanie…
Reference in New Issue