kopia lustrzana https://github.com/weetmuts/wmbusmeters
				
				
				
			Initial work on config files and daemon mode.
							rodzic
							
								
									eceef17499
								
							
						
					
					
						commit
						05e33c32c3
					
				
							
								
								
									
										8
									
								
								CHANGES
								
								
								
								
							
							
						
						
									
										8
									
								
								CHANGES
								
								
								
								
							|  | @ -1,4 +1,12 @@ | |||
| 
 | ||||
| Version 0.8.4: 2019-02-23 | ||||
| 
 | ||||
| Add config files support and daemon mode. | ||||
| 
 | ||||
| Version 0.8.3: 2019-02-17 | ||||
| 
 | ||||
| Add experimental support for qcaloric. | ||||
| 
 | ||||
| Version 0.8.2: 2019-01-27 | ||||
| 
 | ||||
| Properly supports short C1 frames after it has received a long frame. | ||||
|  |  | |||
							
								
								
									
										5
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										5
									
								
								Makefile
								
								
								
								
							|  | @ -44,7 +44,7 @@ endif | |||
| 
 | ||||
| $(shell mkdir -p $(BUILD)) | ||||
| 
 | ||||
| CXXFLAGS := $(DEBUG_FLAGS) -fPIC -fmessage-length=0 -std=c++11 -Wall -Wno-maybe-uninitialized -Wno-unused-function "-DWMBUSMETERS_VERSION=\"0.8.1\"" | ||||
| CXXFLAGS := $(DEBUG_FLAGS) -fPIC -fmessage-length=0 -std=c++11 -Wall -Wno-maybe-uninitialized -Wno-unused-function "-DWMBUSMETERS_VERSION=\"0.8.4\"" | ||||
| 
 | ||||
| $(BUILD)/%.o: %.cc $(wildcard %.h) | ||||
| 	$(CXX) $(CXXFLAGS) $< -c -o $@ | ||||
|  | @ -52,6 +52,7 @@ $(BUILD)/%.o: %.cc $(wildcard %.h) | |||
| METERS_OBJS:=\
 | ||||
| 	$(BUILD)/aes.o \
 | ||||
| 	$(BUILD)/cmdline.o \
 | ||||
| 	$(BUILD)/config.o \
 | ||||
| 	$(BUILD)/dvparser.o \
 | ||||
| 	$(BUILD)/meters.o \
 | ||||
| 	$(BUILD)/meter_multical21.o \
 | ||||
|  | @ -72,6 +73,8 @@ METERS_OBJS:=\ | |||
| 
 | ||||
| all: $(BUILD)/wmbusmeters $(BUILD)/testinternals | ||||
| 	@$(STRIP_BINARY) | ||||
| 	@rm -f $(BUILD)/wmbusmetersd | ||||
| 	@cp $(BUILD)/wmbusmeters $(BUILD)/wmbusmetersd | ||||
| 
 | ||||
| dist: wmbusmeters_0.8.1_$(DEBARCH).deb | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										37
									
								
								cmdline.cc
								
								
								
								
							
							
						
						
									
										37
									
								
								cmdline.cc
								
								
								
								
							|  | @ -19,6 +19,8 @@ | |||
| #include"meters.h" | ||||
| #include"util.h" | ||||
| 
 | ||||
| #include<string> | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| unique_ptr<CommandLine> parseCommandLine(int argc, char **argv) { | ||||
|  | @ -26,6 +28,14 @@ unique_ptr<CommandLine> parseCommandLine(int argc, char **argv) { | |||
|     CommandLine * c = new CommandLine; | ||||
| 
 | ||||
|     int i=1; | ||||
|     const char *filename = strrchr(argv[0], '/')+1; | ||||
|     if (!strcmp(filename, "wmbusmetersd")) { | ||||
|         c->daemon = true; | ||||
|         if (argc > 1) { | ||||
|             error("Usage error: wmbusmetersd does not accept any arguments.\n"); | ||||
|         } | ||||
|         return unique_ptr<CommandLine>(c); | ||||
|     } | ||||
|     if (argc < 2) { | ||||
|         c->need_help = true; | ||||
|         return unique_ptr<CommandLine>(c); | ||||
|  | @ -73,6 +83,13 @@ unique_ptr<CommandLine> parseCommandLine(int argc, char **argv) { | |||
|             i++; | ||||
|             continue; | ||||
|         } | ||||
|         if (!strcmp(argv[i], "--useconfig")) { | ||||
|             c->useconfig = true; | ||||
|             if (i > 1 || argc > 2) { | ||||
|                 error("Usage error: --useconfig implies no other arguments on the command line.\n"); | ||||
|             } | ||||
|             return unique_ptr<CommandLine>(c); | ||||
|         } | ||||
|         if (!strncmp(argv[i], "--robot", 7)) { | ||||
|             if (strlen(argv[i]) == 7 || | ||||
|                 (strlen(argv[i]) == 12 && | ||||
|  | @ -109,7 +126,7 @@ unique_ptr<CommandLine> parseCommandLine(int argc, char **argv) { | |||
|             if (strlen(argv[i]) > 12 && argv[i][12] == '=') { | ||||
|                 size_t len = strlen(argv[i])-13; | ||||
|                 if (len > 0) { | ||||
|                     c->meterfiles_dir = argv[i]+13; | ||||
|                     c->meterfiles_dir = string(argv[i]+13, len); | ||||
|                 } else { | ||||
|                     c->meterfiles_dir = "/tmp"; | ||||
|                 } | ||||
|  | @ -117,7 +134,7 @@ unique_ptr<CommandLine> parseCommandLine(int argc, char **argv) { | |||
|                 c->meterfiles_dir = "/tmp"; | ||||
|             } | ||||
|             if (!checkIfDirExists(c->meterfiles_dir.c_str())) { | ||||
|                 error("Directory does not exist \"%s\"\n", c->meterfiles_dir.c_str()); | ||||
|                 error("Cannot write meter files into dir \"%s\"\n", c->meterfiles_dir); | ||||
|             } | ||||
|             i++; | ||||
|             continue; | ||||
|  | @ -158,7 +175,7 @@ unique_ptr<CommandLine> parseCommandLine(int argc, char **argv) { | |||
| 
 | ||||
|     c->usb_device = argv[i]; | ||||
|     i++; | ||||
|     if (!c->usb_device) error("You must supply the usb device to which the wmbus dongle is connected.\n"); | ||||
|     if (c->usb_device.length() == 0) error("You must supply the usb device to which the wmbus dongle is connected.\n"); | ||||
| 
 | ||||
|     if ((argc-i) % 4 != 0) { | ||||
|         error("For each meter you must supply a: name,type,id and key.\n"); | ||||
|  | @ -166,16 +183,16 @@ unique_ptr<CommandLine> parseCommandLine(int argc, char **argv) { | |||
|     int num_meters = (argc-i)/4; | ||||
| 
 | ||||
|     for (int m=0; m<num_meters; ++m) { | ||||
|         char *name = argv[m*4+i+0]; | ||||
|         char *type = argv[m*4+i+1]; | ||||
|         char *id = argv[m*4+i+2]; | ||||
|         char *key = argv[m*4+i+3]; | ||||
|         string name = argv[m*4+i+0]; | ||||
|         string type = argv[m*4+i+1]; | ||||
|         string id = argv[m*4+i+2]; | ||||
|         string key = argv[m*4+i+3]; | ||||
| 
 | ||||
|         MeterType mt = toMeterType(type); | ||||
| 
 | ||||
|         if (mt == UNKNOWN_METER) error("Not a valid meter type \"%s\"\n", type); | ||||
|         if (!isValidId(id)) error("Not a valid meter id \"%s\"\n", id); | ||||
|         if (!isValidKey(key)) error("Not a valid meter key \"%s\"\n", key); | ||||
|         if (mt == UNKNOWN_METER) error("Not a valid meter type \"%s\"\n", type.c_str()); | ||||
|         if (!isValidId(id)) error("Not a valid meter id \"%s\"\n", id.c_str()); | ||||
|         if (!isValidKey(key)) error("Not a valid meter key \"%s\"\n", key.c_str()); | ||||
|         c->meters.push_back(MeterInfo(name,type,id,key)); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										39
									
								
								cmdline.h
								
								
								
								
							
							
						
						
									
										39
									
								
								cmdline.h
								
								
								
								
							|  | @ -18,6 +18,7 @@ | |||
| #ifndef CMDLINE_H | ||||
| #define CMDLINE_H | ||||
| 
 | ||||
| #include"config.h" | ||||
| #include"meters.h" | ||||
| #include<memory> | ||||
| #include<string.h> | ||||
|  | @ -25,44 +26,6 @@ | |||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| struct MeterInfo { | ||||
|     char *name; | ||||
|     char *type; | ||||
|     char *id; | ||||
|     char *key; | ||||
| 
 | ||||
|     MeterInfo(char *n, char *t, char *i, char *k) { | ||||
|         name = n; | ||||
|         type = t; | ||||
|         id = i; | ||||
|         key = k; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| struct CommandLine { | ||||
|     bool need_help {}; | ||||
|     bool silence {}; | ||||
|     bool verbose {}; | ||||
|     bool debug {}; | ||||
|     bool logtelegrams {}; | ||||
|     bool meterfiles {}; | ||||
|     string meterfiles_dir; | ||||
|     bool json {}; | ||||
|     bool fields {}; | ||||
|     char separator { ';' }; | ||||
|     vector<string> shells; | ||||
|     bool list_shell_envs {}; | ||||
|     bool oneshot {}; | ||||
|     int  exitafter {}; // Seconds to exit.
 | ||||
|     char *usb_device {}; | ||||
|     LinkMode link_mode {}; | ||||
|     bool link_mode_set {}; | ||||
|     bool no_init {}; | ||||
|     vector<MeterInfo> meters; | ||||
| 
 | ||||
|     ~CommandLine() = default; | ||||
| }; | ||||
| 
 | ||||
| unique_ptr<CommandLine> parseCommandLine(int argc, char **argv); | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -0,0 +1,122 @@ | |||
| /*
 | ||||
|  Copyright (C) 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"config.h" | ||||
| #include"meters.h" | ||||
| 
 | ||||
| #include<vector> | ||||
| #include<string> | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| pair<string,string> getNextKeyValue(vector<char> &buf, vector<char>::iterator &i) | ||||
| { | ||||
|     bool eof, err; | ||||
|     string key, value; | ||||
|     key = eatToSkipWhitespace(buf, i, '=', 64, &eof, &err); | ||||
|     if (eof || err) goto nomore; | ||||
|     value = eatToSkipWhitespace(buf, i, '\n', 4096, &eof, &err); | ||||
|     if (err) goto nomore; | ||||
| 
 | ||||
|     return { key, value }; | ||||
| 
 | ||||
|     nomore: | ||||
| 
 | ||||
|     return { "", "" }; | ||||
| } | ||||
| 
 | ||||
| void parseMeterConfig(CommandLine *c, vector<char> &buf, string file) | ||||
| { | ||||
|     auto i = buf.begin(); | ||||
|     string name; | ||||
|     string type; | ||||
|     string id; | ||||
|     string key; | ||||
| 
 | ||||
|     for (;;) { | ||||
|         auto p = getNextKeyValue(buf, i); | ||||
| 
 | ||||
|         if (p.first == "") break; | ||||
| 
 | ||||
|         if (p.first == "name") name = p.second; | ||||
|         if (p.first == "type") type = p.second; | ||||
|         if (p.first == "id") id = p.second; | ||||
|         if (p.first == "key") key = p.second; | ||||
|     } | ||||
| 
 | ||||
|     MeterType mt = toMeterType(type); | ||||
|     if (mt == UNKNOWN_METER) error("Not a valid meter type \"%s\"\n", type.c_str()); | ||||
|     if (!isValidId(id)) error("Not a valid meter id \"%s\"\n", id.c_str()); | ||||
|     if (!isValidKey(key)) error("Not a valid meter key \"%s\"\n", key.c_str()); | ||||
| 
 | ||||
|     c->meters.push_back(MeterInfo(name, type, id, key)); | ||||
| 
 | ||||
|     return; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| unique_ptr<CommandLine> loadConfiguration() | ||||
| { | ||||
|     CommandLine *c = new CommandLine; | ||||
| 
 | ||||
|     vector<char> global_conf; | ||||
|     loadFile("/etc/wmbusmeters.conf", &global_conf); | ||||
| 
 | ||||
|     auto i = global_conf.begin(); | ||||
|     string loglevel; | ||||
|     string device; | ||||
| 
 | ||||
|     for (;;) { | ||||
|         auto p = getNextKeyValue(global_conf, i); | ||||
| 
 | ||||
|         if (p.first == "") break; | ||||
| 
 | ||||
|         if (p.first == "loglevel") loglevel = p.second; | ||||
|         if (p.first == "device") device = p.second; | ||||
|     } | ||||
| 
 | ||||
|     if (loglevel == "verbose") { | ||||
|         c->verbose = true; | ||||
|     } else | ||||
|     if (loglevel == "debug") { | ||||
|         c->debug = true; | ||||
|     } else | ||||
|     if (loglevel == "silent") { | ||||
|         c->silence = true; | ||||
|     } else | ||||
|     if (loglevel == "normal") { | ||||
|     } else | ||||
|     { | ||||
|         warning("No such log level: \"%s\"\n", loglevel.c_str()); | ||||
|     } | ||||
|     // cmdline->logtelegrams
 | ||||
| 
 | ||||
|     c->usb_device = device; | ||||
| 
 | ||||
|     vector<string> meter_files; | ||||
|     listFiles("/etc/wmbusmeters.d", &meter_files); | ||||
| 
 | ||||
|     for (auto& f : meter_files) | ||||
|     { | ||||
|         vector<char> meter_conf; | ||||
|         string file = string("/etc/wmbusmeters.d/")+f; | ||||
|         loadFile(file.c_str(), &meter_conf); | ||||
|         parseMeterConfig(c, meter_conf, file); | ||||
|     } | ||||
| 
 | ||||
|     return unique_ptr<CommandLine>(c); | ||||
| } | ||||
|  | @ -0,0 +1,69 @@ | |||
| /*
 | ||||
|  Copyright (C) 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/>.
 | ||||
| */ | ||||
| 
 | ||||
| #ifndef CONFIG_H | ||||
| #define CONFIG_H | ||||
| 
 | ||||
| #include"util.h" | ||||
| #include"wmbus.h" | ||||
| #include<vector> | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| struct MeterInfo { | ||||
|     string name; | ||||
|     string type; | ||||
|     string id; | ||||
|     string key; | ||||
| 
 | ||||
|     MeterInfo(string& n, string& t, string& i, string& k) { | ||||
|         name = n; | ||||
|         type = t; | ||||
|         id = i; | ||||
|         key = k; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| struct CommandLine { | ||||
|     bool daemon {}; | ||||
|     bool useconfig {}; | ||||
|     bool need_help {}; | ||||
|     bool silence {}; | ||||
|     bool verbose {}; | ||||
|     bool debug {}; | ||||
|     bool logtelegrams {}; | ||||
|     bool meterfiles {}; | ||||
|     std::string meterfiles_dir; | ||||
|     bool json {}; | ||||
|     bool fields {}; | ||||
|     char separator { ';' }; | ||||
|     std::vector<std::string> shells; | ||||
|     bool list_shell_envs {}; | ||||
|     bool oneshot {}; | ||||
|     int  exitafter {}; // Seconds to exit.
 | ||||
|     string usb_device; | ||||
|     LinkMode link_mode {}; | ||||
|     bool link_mode_set {}; | ||||
|     bool no_init {}; | ||||
|     vector<MeterInfo> meters; | ||||
| 
 | ||||
|     ~CommandLine() = default; | ||||
| }; | ||||
| 
 | ||||
| unique_ptr<CommandLine> loadConfiguration(); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										88
									
								
								main.cc
								
								
								
								
							
							
						
						
									
										88
									
								
								main.cc
								
								
								
								
							|  | @ -16,6 +16,7 @@ | |||
| */ | ||||
| 
 | ||||
| #include"cmdline.h" | ||||
| #include"config.h" | ||||
| #include"meters.h" | ||||
| #include"printer.h" | ||||
| #include"serial.h" | ||||
|  | @ -24,9 +25,22 @@ | |||
| 
 | ||||
| #include<string.h> | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <fcntl.h> | ||||
| #include <errno.h> | ||||
| #include <unistd.h> | ||||
| #include <syslog.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| void oneshotCheck(CommandLine *cmdline, SerialCommunicationManager *manager, Meter *meter, vector<unique_ptr<Meter>> &meters); | ||||
| void startUsingCommandline(CommandLine *cmdline); | ||||
| void startUsingConfigFiles(); | ||||
| void startDaemon(); // Will use config files.
 | ||||
| 
 | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|  | @ -47,7 +61,9 @@ int main(int argc, char **argv) | |||
|         printf("    --shellenvs list the env variables available for the meter.\n"); | ||||
|         printf("    --oneshot wait for an update from each meter, then quit.\n\n"); | ||||
|         printf("    --exitafter=20h program exits after running for twenty hoursh\n" | ||||
|                "        or 10m for ten minutes or 5s for five seconds.\n\n"); | ||||
|                "        or 10m for ten minutes or 5s for five seconds.\n"); | ||||
|         printf("    --useconfig read from /etc/wmbusmeters.conf and /etc/wmbusmeters.d\n"); | ||||
|         printf("        check the man page for how to write the config files.\n\n"); | ||||
|         printf("Specifying auto as the device will automatically look for usb\n"); | ||||
|         printf("wmbus dongles on /dev/im871a and /dev/amb8465\n\n"); | ||||
|         printf("The meter types: multical21,flowiq3100,supercom587,iperl (water meters) are supported.\n" | ||||
|  | @ -56,9 +72,25 @@ int main(int argc, char **argv) | |||
|         exit(0); | ||||
|     } | ||||
| 
 | ||||
|     if (cmdline->daemon) { | ||||
|         startDaemon(); | ||||
|         exit(0); | ||||
|     } | ||||
| 
 | ||||
|     if (cmdline->useconfig) { | ||||
|         startUsingConfigFiles(); | ||||
|         exit(0); | ||||
|     } | ||||
| 
 | ||||
|     // We want the data visible in the log file asap!
 | ||||
|     setbuf(stdout, NULL); | ||||
| 
 | ||||
|     startUsingCommandline(cmdline.get()); | ||||
|     exit(0); | ||||
| } | ||||
| 
 | ||||
| void startUsingCommandline(CommandLine *cmdline) | ||||
| { | ||||
|     warningSilenced(cmdline->silence); | ||||
|     verboseEnabled(cmdline->verbose); | ||||
|     logTelegramsEnabled(cmdline->logtelegrams); | ||||
|  | @ -71,7 +103,7 @@ int main(int argc, char **argv) | |||
|     if (cmdline->meterfiles) { | ||||
|         verbose("(cmdline) store meter files in: \"%s\"\n", cmdline->meterfiles_dir.c_str()); | ||||
|     } | ||||
|     verbose("(cmdline) using usb device: %s\n", cmdline->usb_device); | ||||
|     verbose("(cmdline) using usb device: %s\n", cmdline->usb_device.c_str()); | ||||
|     verbose("(cmdline) number of meters: %d\n", cmdline->meters.size()); | ||||
| 
 | ||||
|     auto manager = createSerialCommunicationManager(cmdline->exitafter); | ||||
|  | @ -172,7 +204,7 @@ int main(int argc, char **argv) | |||
|                                           &ignore2, cmdline->separator, | ||||
|                                           &ignore3, | ||||
|                                           &envs); | ||||
|                 printf("Environment variables provided to shell for meter %s:\n", m.type); | ||||
|                 printf("Environment variables provided to shell for meter %s:\n", m.type.c_str()); | ||||
|                 for (auto &e : envs) { | ||||
|                     int p = e.find('='); | ||||
|                     string key = e.substr(0,p); | ||||
|  | @ -181,7 +213,7 @@ int main(int argc, char **argv) | |||
|                 exit(0); | ||||
|             } | ||||
|             meters.back()->onUpdate(calll(output.get(),print,Meter*)); | ||||
|             meters.back()->onUpdate([&](Meter*meter) { oneshotCheck(cmdline.get(), manager.get(), meter, meters); }); | ||||
|             meters.back()->onUpdate([&](Meter*meter) { oneshotCheck(cmdline, manager.get(), meter, meters); }); | ||||
|         } | ||||
|     } else { | ||||
|         printf("No meters configured. Printing id:s of all telegrams heard!\n\n"); | ||||
|  | @ -206,3 +238,51 @@ void oneshotCheck(CommandLine *cmdline, SerialCommunicationManager *manager, Met | |||
|     // All meters have received at least one update! Stop!
 | ||||
|     manager->stop(); | ||||
| } | ||||
| 
 | ||||
| void startDaemon() | ||||
| { | ||||
|     pid_t pid = fork(); | ||||
|     if (pid < 0) | ||||
|     { | ||||
|         error("Could not fork.\n"); | ||||
|     } | ||||
|     if (pid > 0) | ||||
|     { | ||||
|         // Parent returns to exit nicely.
 | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // Change the file mode mask
 | ||||
|     umask(0); | ||||
| 
 | ||||
|     setlogmask(LOG_UPTO (LOG_NOTICE)); | ||||
|     openlog("wmbusmetersd", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); | ||||
| 
 | ||||
|     syslog(LOG_NOTICE, "wmbusmeters started by User %d", getuid ()); | ||||
| 
 | ||||
|     enableSyslog(); | ||||
| 
 | ||||
|     // Create a new SID for the daemon
 | ||||
|     pid_t sid = setsid(); | ||||
|     if (sid < 0) { | ||||
|         // log
 | ||||
|         exit(-1); | ||||
|     } | ||||
| 
 | ||||
|     if ((chdir("/")) < 0) { | ||||
|         error("Could not change to root as current working directory."); | ||||
|     } | ||||
| 
 | ||||
|     close(STDIN_FILENO); | ||||
|     close(STDOUT_FILENO); | ||||
|     close(STDERR_FILENO); | ||||
| 
 | ||||
|     startUsingConfigFiles(); | ||||
| } | ||||
| 
 | ||||
| void startUsingConfigFiles() | ||||
| { | ||||
|     unique_ptr<CommandLine> cmdline = loadConfiguration(); | ||||
| 
 | ||||
|     startUsingCommandline(cmdline.get()); | ||||
| } | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ | |||
| using namespace std; | ||||
| 
 | ||||
| struct MeterIperl : public virtual WaterMeter, public virtual MeterCommonImplementation { | ||||
|     MeterIperl(WMBus *bus, const char *name, const char *id, const char *key); | ||||
|     MeterIperl(WMBus *bus, string& name, string& id, string& key); | ||||
| 
 | ||||
|     // Total water counted through the meter
 | ||||
|     double totalWaterConsumption(); | ||||
|  | @ -68,7 +68,7 @@ private: | |||
|     double total_water_consumption_ {}; | ||||
| }; | ||||
| 
 | ||||
| MeterIperl::MeterIperl(WMBus *bus, const char *name, const char *id, const char *key) : | ||||
| MeterIperl::MeterIperl(WMBus *bus, string& name, string& id, string& key) : | ||||
|     MeterCommonImplementation(bus, name, id, key, IPERL_METER, MANUFACTURER_SEN, 0x16, LinkModeT1) | ||||
| { | ||||
|     MeterCommonImplementation::bus()->onTelegram(calll(this,handleTelegram,Telegram*)); | ||||
|  | @ -80,7 +80,7 @@ double MeterIperl::totalWaterConsumption() | |||
|     return total_water_consumption_; | ||||
| } | ||||
| 
 | ||||
| unique_ptr<WaterMeter> createIperl(WMBus *bus, const char *name, const char *id, const char *key) | ||||
| unique_ptr<WaterMeter> createIperl(WMBus *bus, string& name, string& id, string& key) | ||||
| { | ||||
|     return unique_ptr<WaterMeter>(new MeterIperl(bus,name,id,key)); | ||||
| } | ||||
|  |  | |||
|  | @ -45,7 +45,7 @@ using namespace std; | |||
| #define INFO_CODE_BURST_SHIFT (4+9) | ||||
| 
 | ||||
| struct MeterMultical21 : public virtual WaterMeter, public virtual MeterCommonImplementation { | ||||
|     MeterMultical21(WMBus *bus, const char *name, const char *id, const char *key, MeterType mt); | ||||
|     MeterMultical21(WMBus *bus, string& name, string& id, string& key, MeterType mt); | ||||
| 
 | ||||
|     // Total water counted through the meter
 | ||||
|     double totalWaterConsumption(); | ||||
|  | @ -103,7 +103,7 @@ private: | |||
|     int expected_version_ {}; // 0x1b for Multical21 and 0x1d for FlowIQ3100
 | ||||
| }; | ||||
| 
 | ||||
| MeterMultical21::MeterMultical21(WMBus *bus, const char *name, const char *id, const char *key, MeterType mt) : | ||||
| MeterMultical21::MeterMultical21(WMBus *bus, string& name, string& id, string& key, MeterType mt) : | ||||
|     MeterCommonImplementation(bus, name, id, key, mt, MANUFACTURER_KAM, 0x16, LinkModeC1) | ||||
| { | ||||
|     if (type() == MULTICAL21_METER) { | ||||
|  | @ -169,7 +169,7 @@ bool MeterMultical21::hasExternalTemperature() | |||
|     return has_external_temperature_; | ||||
| } | ||||
| 
 | ||||
| unique_ptr<WaterMeter> createMultical21(WMBus *bus, const char *name, const char *id, const char *key, MeterType mt) | ||||
| unique_ptr<WaterMeter> createMultical21(WMBus *bus, string& name, string& id, string& key, MeterType mt) | ||||
| { | ||||
|     if (mt != MULTICAL21_METER && mt != FLOWIQ3100_METER) { | ||||
|         error("Internal error! Not a proper meter type when creating a multical21 style meter.\n"); | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ | |||
| #include<vector> | ||||
| 
 | ||||
| struct MeterMultical302 : public virtual HeatMeter, public virtual MeterCommonImplementation { | ||||
|     MeterMultical302(WMBus *bus, const char *name, const char *id, const char *key); | ||||
|     MeterMultical302(WMBus *bus, string& name, string& id, string& key); | ||||
| 
 | ||||
|     double totalEnergyConsumption(); | ||||
|     double currentPowerConsumption(); | ||||
|  | @ -49,7 +49,7 @@ private: | |||
|     double total_volume_ {}; | ||||
| }; | ||||
| 
 | ||||
| MeterMultical302::MeterMultical302(WMBus *bus, const char *name, const char *id, const char *key) : | ||||
| MeterMultical302::MeterMultical302(WMBus *bus, string& name, string& id, string& key) : | ||||
|     MeterCommonImplementation(bus, name, id, key, MULTICAL302_METER, MANUFACTURER_KAM, 0x04, LinkModeC1) | ||||
| { | ||||
|     MeterCommonImplementation::bus()->onTelegram(calll(this,handleTelegram,Telegram*)); | ||||
|  | @ -178,7 +178,7 @@ void MeterMultical302::processContent(Telegram *t) { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| unique_ptr<HeatMeter> createMultical302(WMBus *bus, const char *name, const char *id, const char *key) { | ||||
| unique_ptr<HeatMeter> createMultical302(WMBus *bus, string& name, string& id, string& key) { | ||||
|     return unique_ptr<HeatMeter>(new MeterMultical302(bus,name,id,key)); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ | |||
| #include<vector> | ||||
| 
 | ||||
| struct MeterOmnipower : public virtual ElectricityMeter, public virtual MeterCommonImplementation { | ||||
|     MeterOmnipower(WMBus *bus, const char *name, const char *id, const char *key); | ||||
|     MeterOmnipower(WMBus *bus, string& name, string& id, string& key); | ||||
| 
 | ||||
|     double totalEnergyConsumption(); | ||||
|     double currentPowerConsumption(); | ||||
|  | @ -48,7 +48,7 @@ private: | |||
|     double current_power_ {}; | ||||
| }; | ||||
| 
 | ||||
| MeterOmnipower::MeterOmnipower(WMBus *bus, const char *name, const char *id, const char *key) : | ||||
| MeterOmnipower::MeterOmnipower(WMBus *bus, string& name, string& id, string& key) : | ||||
|     MeterCommonImplementation(bus, name, id, key, OMNIPOWER_METER, MANUFACTURER_KAM, 0x04, LinkModeC1) | ||||
| { | ||||
|     MeterCommonImplementation::bus()->onTelegram(calll(this,handleTelegram,Telegram*)); | ||||
|  | @ -118,7 +118,7 @@ void MeterOmnipower::processContent(Telegram *t) | |||
|     t->addMoreExplanation(offset, " total power (%f kwh)", total_energy_); | ||||
| } | ||||
| 
 | ||||
| unique_ptr<ElectricityMeter> createOmnipower(WMBus *bus, const char *name, const char *id, const char *key) | ||||
| unique_ptr<ElectricityMeter> createOmnipower(WMBus *bus, string& name, string& id, string& key) | ||||
| { | ||||
|     return unique_ptr<ElectricityMeter>(new MeterOmnipower(bus,name,id,key)); | ||||
| } | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ | |||
| #include<vector> | ||||
| 
 | ||||
| struct MeterQCaloric : public virtual HeatCostMeter, public virtual MeterCommonImplementation { | ||||
|     MeterQCaloric(WMBus *bus, const char *name, const char *id, const char *key); | ||||
|     MeterQCaloric(WMBus *bus, string& name, string& id, string& key); | ||||
| 
 | ||||
|     double totalEnergyConsumption(); | ||||
| 
 | ||||
|  | @ -46,7 +46,7 @@ private: | |||
|     double total_energy_ {}; | ||||
| }; | ||||
| 
 | ||||
| MeterQCaloric::MeterQCaloric(WMBus *bus, const char *name, const char *id, const char *key) : | ||||
| MeterQCaloric::MeterQCaloric(WMBus *bus, string& name, string& id, string& key) : | ||||
|     MeterCommonImplementation(bus, name, id, key, QCALORIC_METER, MANUFACTURER_QDS, 0x08, LinkModeC1) | ||||
| { | ||||
|     MeterCommonImplementation::bus()->onTelegram(calll(this,handleTelegram,Telegram*)); | ||||
|  | @ -101,7 +101,7 @@ void MeterQCaloric::processContent(Telegram *t) | |||
|     parseDV(t, t->content, t->content.begin(), t->content.size(), &values); | ||||
| } | ||||
| 
 | ||||
| unique_ptr<HeatCostMeter> createQCaloric(WMBus *bus, const char *name, const char *id, const char *key) | ||||
| unique_ptr<HeatCostMeter> createQCaloric(WMBus *bus, string& name, string& id, string& key) | ||||
| { | ||||
|     return unique_ptr<HeatCostMeter>(new MeterQCaloric(bus,name,id,key)); | ||||
| } | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ | |||
| using namespace std; | ||||
| 
 | ||||
| struct MeterSupercom587 : public virtual WaterMeter, public virtual MeterCommonImplementation { | ||||
|     MeterSupercom587(WMBus *bus, const char *name, const char *id, const char *key); | ||||
|     MeterSupercom587(WMBus *bus, string& name, string& id, string& key); | ||||
| 
 | ||||
|     // Total water counted through the meter
 | ||||
|     double totalWaterConsumption(); | ||||
|  | @ -67,7 +67,7 @@ private: | |||
|     double total_water_consumption_ {}; | ||||
| }; | ||||
| 
 | ||||
| MeterSupercom587::MeterSupercom587(WMBus *bus, const char *name, const char *id, const char *key) : | ||||
| MeterSupercom587::MeterSupercom587(WMBus *bus, string& name, string& id, string& key) : | ||||
|     MeterCommonImplementation(bus, name, id, key, SUPERCOM587_METER, MANUFACTURER_SON, 0x16, LinkModeT1) | ||||
| { | ||||
|     MeterCommonImplementation::bus()->onTelegram(calll(this,handleTelegram,Telegram*)); | ||||
|  | @ -79,7 +79,7 @@ double MeterSupercom587::totalWaterConsumption() | |||
|     return total_water_consumption_; | ||||
| } | ||||
| 
 | ||||
| unique_ptr<WaterMeter> createSupercom587(WMBus *bus, const char *name, const char *id, const char *key) | ||||
| unique_ptr<WaterMeter> createSupercom587(WMBus *bus, string& name, string& id, string& key) | ||||
| { | ||||
|     return unique_ptr<WaterMeter>(new MeterSupercom587(bus,name,id,key)); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										34
									
								
								meters.cc
								
								
								
								
							
							
						
						
									
										34
									
								
								meters.cc
								
								
								
								
							|  | @ -20,7 +20,7 @@ | |||
| 
 | ||||
| #include<memory.h> | ||||
| 
 | ||||
| MeterCommonImplementation::MeterCommonImplementation(WMBus *bus, const char *name, const char *id, const char *key, | ||||
| MeterCommonImplementation::MeterCommonImplementation(WMBus *bus, string& name, string& id, string& key, | ||||
|                                                      MeterType type, int manufacturer, int media, | ||||
|                                                      LinkMode required_link_mode) : | ||||
|     type_(type), manufacturer_(manufacturer), media_(media), name_(name), bus_(bus), | ||||
|  | @ -28,7 +28,7 @@ MeterCommonImplementation::MeterCommonImplementation(WMBus *bus, const char *nam | |||
| { | ||||
|     use_aes_ = true; | ||||
|     hex2bin(id, &id_); | ||||
|     if (strlen(key) == 0) { | ||||
|     if (key.length() == 0) { | ||||
| 	use_aes_ = false; | ||||
|     } else { | ||||
| 	hex2bin(key, &key_); | ||||
|  | @ -97,26 +97,26 @@ string MeterCommonImplementation::datetimeOfUpdateRobot() | |||
|     return string(datetime); | ||||
| } | ||||
| 
 | ||||
| MeterType toMeterType(const char *type) | ||||
| MeterType toMeterType(string& type) | ||||
| { | ||||
|     if (!strcmp(type, "multical21")) return MULTICAL21_METER; | ||||
|     if (!strcmp(type, "flowiq3100")) return FLOWIQ3100_METER; | ||||
|     if (!strcmp(type, "multical302")) return MULTICAL302_METER; | ||||
|     if (!strcmp(type, "omnipower")) return OMNIPOWER_METER; | ||||
|     if (!strcmp(type, "supercom587")) return SUPERCOM587_METER; | ||||
|     if (!strcmp(type, "iperl")) return IPERL_METER; | ||||
|     if (!strcmp(type, "qcaloric")) return QCALORIC_METER; | ||||
|     if (type == "multical21") return MULTICAL21_METER; | ||||
|     if (type == "flowiq3100") return FLOWIQ3100_METER; | ||||
|     if (type == "multical302") return MULTICAL302_METER; | ||||
|     if (type == "omnipower") return OMNIPOWER_METER; | ||||
|     if (type == "supercom587") return SUPERCOM587_METER; | ||||
|     if (type == "iperl") return IPERL_METER; | ||||
|     if (type == "qcaloric") return QCALORIC_METER; | ||||
|     return UNKNOWN_METER; | ||||
| } | ||||
| 
 | ||||
| LinkMode toMeterLinkMode(const char *type) | ||||
| LinkMode toMeterLinkMode(string& type) | ||||
| { | ||||
|     if (!strcmp(type, "multical21")) return LinkModeC1; | ||||
|     if (!strcmp(type, "flowiq3100")) return LinkModeC1; | ||||
|     if (!strcmp(type, "multical302")) return LinkModeC1; | ||||
|     if (!strcmp(type, "omnipower")) return LinkModeC1; | ||||
|     if (!strcmp(type, "supercom587")) return LinkModeT1; | ||||
|     if (!strcmp(type, "iperl")) return LinkModeT1; | ||||
|     if (type == "multical21") return LinkModeC1; | ||||
|     if (type == "flowiq3100") return LinkModeC1; | ||||
|     if (type == "multical302") return LinkModeC1; | ||||
|     if (type == "omnipower") return LinkModeC1; | ||||
|     if (type == "supercom587") return LinkModeT1; | ||||
|     if (type == "iperl") return LinkModeT1; | ||||
| 
 | ||||
|     return UNKNOWN_LINKMODE; | ||||
| } | ||||
|  |  | |||
							
								
								
									
										18
									
								
								meters.h
								
								
								
								
							
							
						
						
									
										18
									
								
								meters.h
								
								
								
								
							|  | @ -106,14 +106,14 @@ struct HeatCostMeter : public virtual Meter { | |||
| struct GenericMeter : public virtual Meter { | ||||
| }; | ||||
| 
 | ||||
| MeterType toMeterType(const char *type); | ||||
| LinkMode toMeterLinkMode(const char *type); | ||||
| unique_ptr<WaterMeter> createMultical21(WMBus *bus, const char *name, const char *id, const char *key, MeterType mt); | ||||
| unique_ptr<HeatMeter> createMultical302(WMBus *bus, const char *name, const char *id, const char *key); | ||||
| unique_ptr<ElectricityMeter> createOmnipower(WMBus *bus, const char *name, const char *id, const char *key); | ||||
| unique_ptr<WaterMeter> createSupercom587(WMBus *bus, const char *name, const char *id, const char *key); | ||||
| unique_ptr<WaterMeter> createIperl(WMBus *bus, const char *name, const char *id, const char *key); | ||||
| unique_ptr<HeatCostMeter> createQCaloric(WMBus *bus, const char *name, const char *id, const char *key); | ||||
| GenericMeter *createGeneric(WMBus *bus, const char *name, const char *id, const char *key); | ||||
| MeterType toMeterType(string& type); | ||||
| LinkMode toMeterLinkMode(string& type); | ||||
| unique_ptr<WaterMeter> createMultical21(WMBus *bus, string& name, string& id, string& key, MeterType mt); | ||||
| unique_ptr<HeatMeter> createMultical302(WMBus *bus, string& name, string& id, string& key); | ||||
| unique_ptr<ElectricityMeter> createOmnipower(WMBus *bus, string& name, string& id, string& key); | ||||
| unique_ptr<WaterMeter> createSupercom587(WMBus *bus, string& name, string& id, string& key); | ||||
| unique_ptr<WaterMeter> createIperl(WMBus *bus, string& name, string& id, string& key); | ||||
| unique_ptr<HeatCostMeter> createQCaloric(WMBus *bus, string& name, string& id, string& key); | ||||
| GenericMeter *createGeneric(WMBus *bus, string& name, string& id, string& key); | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -46,7 +46,7 @@ struct MeterCommonImplementation : public virtual Meter | |||
|     double getRecordAsDouble(std::string record); | ||||
|     uint16_t getRecordAsUInt16(std::string record); | ||||
| 
 | ||||
|     MeterCommonImplementation(WMBus *bus, const char *name, const char *id, const char *key, | ||||
|     MeterCommonImplementation(WMBus *bus, string& name, string& id, string& key, | ||||
|                               MeterType type, int manufacturer, int media, | ||||
|                               LinkMode required_link_mode); | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										152
									
								
								util.cc
								
								
								
								
							
							
						
						
									
										152
									
								
								util.cc
								
								
								
								
							|  | @ -16,6 +16,7 @@ | |||
| */ | ||||
| 
 | ||||
| #include"util.h" | ||||
| #include<dirent.h> | ||||
| #include<functional> | ||||
| #include<signal.h> | ||||
| #include<stdarg.h> | ||||
|  | @ -23,6 +24,10 @@ | |||
| #include<string.h> | ||||
| #include<string> | ||||
| #include<sys/stat.h> | ||||
| #include<syslog.h> | ||||
| #include<unistd.h> | ||||
| #include<sys/types.h> | ||||
| #include<fcntl.h> | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
|  | @ -141,6 +146,7 @@ void error(const char* fmt, ...) { | |||
|     exit(1); | ||||
| } | ||||
| 
 | ||||
| bool syslog_enabled_ = false; | ||||
| bool warning_enabled_ = true; | ||||
| bool verbose_enabled_ = false; | ||||
| bool debug_enabled_ = false; | ||||
|  | @ -150,6 +156,10 @@ void warningSilenced(bool b) { | |||
|     warning_enabled_ = !b; | ||||
| } | ||||
| 
 | ||||
| void enableSyslog() { | ||||
|     syslog_enabled_ = true; | ||||
| } | ||||
| 
 | ||||
| void verboseEnabled(bool b) { | ||||
|     verbose_enabled_ = b; | ||||
| } | ||||
|  | @ -185,7 +195,11 @@ void warning(const char* fmt, ...) { | |||
|     if (warning_enabled_) { | ||||
|         va_list args; | ||||
|         va_start(args, fmt); | ||||
|         vprintf(fmt, args); | ||||
|         if (syslog_enabled_) { | ||||
|             vsyslog(LOG_WARNING, fmt, args); | ||||
|         } else { | ||||
|             vprintf(fmt, args); | ||||
|         } | ||||
|         va_end(args); | ||||
|     } | ||||
| } | ||||
|  | @ -194,7 +208,11 @@ void verbose(const char* fmt, ...) { | |||
|     if (verbose_enabled_) { | ||||
|         va_list args; | ||||
|         va_start(args, fmt); | ||||
|         vprintf(fmt, args); | ||||
|         if (syslog_enabled_) { | ||||
|             vsyslog(LOG_INFO, fmt, args); | ||||
|         } else { | ||||
|             vprintf(fmt, args); | ||||
|         } | ||||
|         va_end(args); | ||||
|     } | ||||
| } | ||||
|  | @ -203,25 +221,28 @@ void debug(const char* fmt, ...) { | |||
|     if (debug_enabled_) { | ||||
|         va_list args; | ||||
|         va_start(args, fmt); | ||||
|         vprintf(fmt, args); | ||||
|         if (syslog_enabled_) { | ||||
|             vsyslog(LOG_INFO, fmt, args); | ||||
|         } else { | ||||
|             vprintf(fmt, args); | ||||
|         } | ||||
|         va_end(args); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool isValidId(char *id) | ||||
| bool isValidId(string& id) | ||||
| { | ||||
|     if (strlen(id) == 0) return true; | ||||
|     if (strlen(id) != 8) return false; | ||||
|     if (id.length() != 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) | ||||
| bool isValidKey(string& key) | ||||
| { | ||||
|     if (strlen(key) == 0) return true; | ||||
|     if (strlen(key) != 32) return false; | ||||
|     if (key.length() == 0) return true; | ||||
|     if (key.length() != 32) return false; | ||||
|     vector<uchar> tmp; | ||||
|     return hex2bin(key, &tmp); | ||||
| } | ||||
|  | @ -438,3 +459,116 @@ bool crc16_CCITT_check(uchar *data, uint16_t length) | |||
|     uint16_t crc = ~crc16_CCITT(data, length); | ||||
|     return crc == CRC16_GOOD_VALUE; | ||||
| } | ||||
| 
 | ||||
| bool listFiles(const char *dir, vector<string> *files) | ||||
| { | ||||
|     DIR *dp = NULL; | ||||
|     struct dirent *dptr = NULL; | ||||
| 
 | ||||
|     if (NULL == (dp = opendir(dir))) | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
|     while(NULL != (dptr = ::readdir(dp))) | ||||
|     { | ||||
|         if (!strcmp(dptr->d_name,".") || | ||||
|             !strcmp(dptr->d_name,"..")) | ||||
|         { | ||||
|             // Ignore . ..  dirs.
 | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         files->push_back(string(dptr->d_name)); | ||||
|     } | ||||
|     closedir(dp); | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool loadFile(const char *file, vector<char> *buf) | ||||
| { | ||||
|     int blocksize = 1024; | ||||
|     char block[blocksize]; | ||||
| 
 | ||||
|     int fd = open(file, O_RDONLY); | ||||
|     if (fd == -1) { | ||||
|         return false; | ||||
|     } | ||||
|     while (true) { | ||||
|         ssize_t n = read(fd, block, sizeof(block)); | ||||
|         if (n == -1) { | ||||
|             if (errno == EINTR) { | ||||
|                 continue; | ||||
|             } | ||||
|             warning("Could not read file %s errno=%d\n", file, errno); | ||||
|             close(fd); | ||||
| 
 | ||||
|             return false; | ||||
|         } | ||||
|         buf->insert(buf->end(), block, block+n); | ||||
|         if (n < (ssize_t)sizeof(block)) { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     close(fd); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| string eatToSkipWhitespace(vector<char> &v, vector<char>::iterator &i, int c, size_t max, bool *eof, bool *err) | ||||
| { | ||||
|     eatWhitespace(v, i, eof); | ||||
|     if (*eof) { | ||||
|         if (c != -1) { | ||||
|             *err = true; | ||||
|         } | ||||
|         return ""; | ||||
|     } | ||||
|     string s = eatTo(v,i,c,max,eof,err); | ||||
|     trimWhitespace(&s); | ||||
|     return s; | ||||
| } | ||||
| 
 | ||||
| string eatTo(vector<char> &v, vector<char>::iterator &i, int c, size_t max, bool *eof, bool *err) | ||||
| { | ||||
|     string s; | ||||
| 
 | ||||
|     *eof = false; | ||||
|     *err = false; | ||||
|     while (max > 0 && i != v.end() && (c == -1 || *i != c)) | ||||
|     { | ||||
|         s += *i; | ||||
|         i++; | ||||
|         max--; | ||||
|     } | ||||
|     if (c != -1 && (i == v.end() || *i != c)) | ||||
|     { | ||||
|         *err = true; | ||||
|     } | ||||
|     if (i != v.end()) | ||||
|     { | ||||
|         i++; | ||||
|     } | ||||
|     if (i == v.end()) { | ||||
|         *eof = true; | ||||
|     } | ||||
|     return s; | ||||
| } | ||||
| 
 | ||||
| void eatWhitespace(vector<char> &v, vector<char>::iterator &i, bool *eof) | ||||
| { | ||||
|     *eof = false; | ||||
|     while (i != v.end() && (*i == ' ' || *i == '\t')) | ||||
|     { | ||||
|         i++; | ||||
|     } | ||||
|     if (i == v.end()) { | ||||
|         *eof = true; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void trimWhitespace(string *s) | ||||
| { | ||||
|     const char *ws = " \t"; | ||||
|     s->erase(0, s->find_first_not_of(ws)); | ||||
|     s->erase(s->find_last_not_of(ws) + 1); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										20
									
								
								util.h
								
								
								
								
							
							
						
						
									
										20
									
								
								util.h
								
								
								
								
							|  | @ -20,6 +20,7 @@ | |||
| 
 | ||||
| #include<signal.h> | ||||
| #include<stdint.h> | ||||
| #include<string> | ||||
| #include<functional> | ||||
| #include<vector> | ||||
| 
 | ||||
|  | @ -38,6 +39,7 @@ void strprintf(std::string &s, const char* fmt, ...); | |||
| 
 | ||||
| void xorit(uchar *srca, uchar *srcb, uchar *dest, int len); | ||||
| 
 | ||||
| void enableSyslog(); | ||||
| void error(const char* fmt, ...); | ||||
| void verbose(const char* fmt, ...); | ||||
| void debug(const char* fmt, ...); | ||||
|  | @ -55,14 +57,16 @@ bool isLogTelegramsEnabled(); | |||
| void debugPayload(std::string intro, std::vector<uchar> &payload); | ||||
| void logTelegram(std::string intro, std::vector<uchar> &header, std::vector<uchar> &content); | ||||
| 
 | ||||
| bool isValidId(char *id); | ||||
| bool isValidKey(char *key); | ||||
| bool isValidId(std::string& id); | ||||
| bool isValidKey(std::string& key); | ||||
| 
 | ||||
| void incrementIV(uchar *iv, size_t len); | ||||
| 
 | ||||
| bool checkCharacterDeviceExists(const char *tty, bool fail_if_not); | ||||
| bool checkIfSimulationFile(const char *file); | ||||
| bool checkIfDirExists(const char *dir); | ||||
| bool listFiles(const char *dir, std::vector<std::string> *files); | ||||
| bool loadFile(const char *file, std::vector<char> *buf); | ||||
| 
 | ||||
| std::string eatTo(std::vector<uchar> &v, std::vector<uchar>::iterator &i, int c, size_t max, bool *eof, bool *err); | ||||
| 
 | ||||
|  | @ -76,4 +80,16 @@ uint16_t crc16_EN13757(uchar *data, size_t len); | |||
| uint16_t crc16_CCITT(uchar *data, uint16_t length); | ||||
| bool     crc16_CCITT_check(uchar *data, uint16_t length); | ||||
| 
 | ||||
| // Eat characters from the vector v, iterating using i, until the end char c is found.
 | ||||
| // If end char == -1, then do not expect any end char, get all until eof.
 | ||||
| // If the end char is not found, return error.
 | ||||
| // If the maximum length is reached without finding the end char, return error.
 | ||||
| std::string eatTo(std::vector<char> &v, std::vector<char>::iterator &i, int c, size_t max, bool *eof, bool *err); | ||||
| // Eat whitespace (space and tab, not end of lines).
 | ||||
| void eatWhitespace(std::vector<char> &v, std::vector<char>::iterator &i, bool *eof); | ||||
| // First eat whitespace, then start eating until c is found or eof. The found string is trimmed from beginning and ending whitespace.
 | ||||
| std::string eatToSkipWhitespace(std::vector<char> &v, std::vector<char>::iterator &i, int c, size_t max, bool *eof, bool *err); | ||||
| // Remove leading and trailing white space
 | ||||
| void trimWhitespace(std::string *s); | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 weetmuts
						weetmuts