Compare commits

...
Sign in to create a new pull request.

5 commits

Author SHA1 Message Date
Steffen Vogel
4e875d0427 reconfigured buildsystem to C++ 2012-03-12 16:00:12 +01:00
Steffen Vogel
0066f7c0b6 porting to C++ in progress.. (not compiling yet) 2012-03-12 01:20:04 +01:00
Steffen Vogel
8333e319a3 ported header files to c++ classes 2012-02-10 10:04:40 +01:00
Steffen Vogel
b97c5894de Merge branch 'master' into c++-port 2012-02-09 10:03:25 +01:00
Steffen Vogel
8ff2e43d53 ported header files to c++ classes 2012-02-05 18:14:01 +01:00
34 changed files with 1673 additions and 1368 deletions

View file

@ -134,6 +134,9 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
@ -182,6 +185,7 @@ abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@

1081
configure vendored

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@ AC_PREREQ([2.67])
AC_INIT([vzlogger], [0.3.3], [http://bugs.volkszaehler.org])
AM_INIT_AUTOMAKE([vzlogger], [0.3.3])
AC_CONFIG_SRCDIR([src/meter.c])
AC_CONFIG_SRCDIR([src/meter.cpp])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([
Makefile
@ -16,7 +16,7 @@ AC_CONFIG_FILES([
])
# Checks for programs.
AC_PROG_CC
AC_PROG_CXX
# We use per target compiler flags
AM_PROG_CC_C_O

View file

@ -80,6 +80,9 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
@ -128,6 +131,7 @@ abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@

View file

@ -31,27 +31,25 @@
#include <pthread.h>
#include <sys/time.h>
#include "meter.h"
#include "reading.h"
#include "list.h"
typedef struct {
reading_t *tail;
reading_t *head;
reading_t *sent;
class Buffer : public List<Reading> {
int size; /* number of readings currently in the buffer */
int keep; /* number of readings to cache for local interface */
public:
Buffer();
virtual ~Buffer();
Iterator push(Reading data);
Reading pop();
void shrink(size_t keep);
char * dump(char *dump, size_t len);
protected:
Iterator sent;
pthread_mutex_t mutex;
} buffer_t;
/* prototypes */
void buffer_init(buffer_t *buf);
reading_t * buffer_push(buffer_t *buf, reading_t *rd);
void buffer_free(buffer_t *buf);
void buffer_clean(buffer_t *buf);
void buffer_clear(buffer_t *buf);
char * buffer_dump(buffer_t *buf, char *dump, size_t len);
};
#endif /* _BUFFER_H_ */

View file

@ -28,26 +28,28 @@
#include <pthread.h>
#include "meter.h"
#include "vzlogger.h"
#include "reading.h"
#include "buffer.h"
typedef struct channel {
char id[5]; /* only for internal usage & debugging */
class Channel {
reading_id_t identifier; /* channel identifier (OBIS, string) */
reading_t last; /* most recent reading */
buffer_t buffer; /* circular queue to buffer readings */
public:
Channel(const char *pUuid, const char *pMiddleware, ReadingIdentifier *pIdentifier);
virtual ~Channel();
protected:
static int instances;
int id; /* only for internal usage & debugging */
ReadingIdentifier *identifier; /* channel identifier (OBIS, string) */
Reading last; /* most recent reading */
Buffer buffer; /* circular queue to buffer readings */
pthread_cond_t condition; /* pthread syncronization to notify logging thread and local webserver */
pthread_t thread; /* pthread for asynchronus logging */
char *middleware; /* url to middleware */
char *uuid; /* unique identifier for middleware */
} channel_t;
/* prototypes */
void channel_init(channel_t *ch, const char *uuid, const char *middleware, reading_id_t identifier);
void channel_free(channel_t *ch);
};
#endif /* _CHANNEL_H_ */

View file

@ -3,6 +3,8 @@
#include <stdarg.h>
#include "../config.h" /* GNU buildsystem config */
/* enumerations */
typedef enum {
log_error = -1,
@ -16,14 +18,6 @@ typedef enum {
typedef unsigned char bool;
/* constants */
#ifndef TRUE
# define TRUE 1
#endif
#ifndef FALSE
# define FALSE 0
#endif
#define SUCCESS 0
#define ERR -1
#define ERR_NOT_FOUND -2

36
include/exception.h Normal file
View file

@ -0,0 +1,36 @@
/**
* Exceptions
*
* @package vzlogger
* @copyright Copyright (c) 2011, The volkszaehler.org project
* @license http://www.gnu.org/licenses/gpl.txt GNU Public License
* @author Steffen Vogel <info@steffenvogel.de>
*/
/*
* This file is part of volkzaehler.org
*
* volkzaehler.org 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
* any later version.
*
* volkzaehler.org 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 volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _EXCEPTION_H_
#define _EXCEPTION_H_
class Exception {
public:
Exception(const char * msg);
};
#endif /* _EXCEPTION_H_ */

View file

@ -1,5 +1,5 @@
/**
* Generic linked list
* Single linked list
*
* @package vzlogger
* @copyright Copyright (c) 2011, The volkszaehler.org project
@ -26,91 +26,105 @@
#ifndef _LIST_H_
#define _LIST_H_
#include <stdlib.h>
#include "exception.h"
#define CONCAT2(a, b) a ## b
#define CONCAT(a, b) CONCAT2(a, b)
#define UNIQUE(prefix) CONCAT(__ ## prefix ## _, __LINE__ )
template<class T>
class List {
#define foreach(list, value, type) \
__list_item_t *UNIQUE(it) = (list).head; \
for( \
type * (value) = UNIQUE(it)->data; \
({ \
if (UNIQUE(it)) { \
(value) = UNIQUE(it)->data; \
} \
; UNIQUE(it) != NULL; \
}); \
UNIQUE(it) = UNIQUE(it)->next \
) \
protected:
class Node; /* protected forward declaration */
typedef struct __list_item {
void *data;
struct __list_item *prev;
struct __list_item *next;
} __list_item_t;
public:
class Iterator; /* public forward declaration */
typedef Iterator iterator;
typedef struct {
List() : size(0), head(NULL), tail(NULL) { };
~List() { clear(); };
Iterator push(T data) {
Node *newNode = new Node;
if (newNode == NULL) {
throw new Exception("Out of memory!");
}
newNode->data = data;
newNode->next = NULL;
if (head == NULL) { /* empty list */
newNode->prev = NULL;
head = newNode;
}
else {
newNode->prev = tail;
tail->next = newNode;
}
tail = newNode;
size++;
return Iterator(newNode);
}
T pop() {
Node *oldNode = head;
T data = head->data;
if (oldNode == NULL) {
throw new Exception("List is empty!");
}
head = oldNode->next;
size--;
delete oldNode;
return data;
}
size_t length() const { return size; };
void clear() { while (size > 0) { pop(); } };
/* Iterators */
Iterator begin() { return Iterator(head); };
Iterator end() { return Iterator(NULL); };
protected:
size_t size;
__list_item_t *head;
__list_item_t *tail;
} list_t;
Node *head, *tail;
};
inline void list_init(list_t *list) {
list->size = 0;
list->head = list->tail = NULL;
}
template<class T>
class List<T>::Node {
friend class List<T>;
friend class List<T>::Iterator;
inline size_t list_push(list_t *list, void *data) {
__list_item_t *new = malloc(sizeof(__list_item_t));
protected:
T data;
Node *next, *prev;
};
if (new == NULL) return -1; /* cannot allocate memory */
template<class T>
class List<T>::Iterator {
friend class List<T>;
new->data = data;
new->prev = list->tail;
new->next = NULL;
public:
Iterator() : cur(NULL) { };
if (list->tail == NULL) {
list->head = new;
}
else {
list->tail->next = new;
}
bool operator==(Iterator const& i) const { return (cur == i.cur); };
bool operator!=(Iterator const& i) const { return (cur != i.cur); };
list->tail = new;
list->size = list->size + 1;
T* operator->() const { return &cur->data; };
T& operator*() const { return cur->data; };
return list->size;
}
Iterator operator++() {
cur = cur->next;
return *this;
};
inline void * list_pop(list_t *list) {
__list_item_t *old = list->tail;
protected:
Iterator(Node *node) : cur(node) { };
if (old == NULL) {
return NULL;
}
void *data = old->data;
list->tail = old->prev;
list->size--;
free(old);
return data;
}
inline void list_free(list_t *list) {
while (list->head != NULL) {
__list_item_t *old = list->head;
list->head = old->next;
free(old->data);
free(old);
}
list_init(list);
}
Node *cur;
};
#endif /* _LIST_H_ */

View file

@ -1,5 +1,5 @@
/**
* Protocol interface
* Meter interface
*
* @package vzlogger
* @copyright Copyright (c) 2011, The volkszaehler.org project
@ -26,61 +26,40 @@
#ifndef _METER_H_
#define _METER_H_
/**
* We have 2 diffrent protocol types:
* - sensors: a readout is triggered in equidistant intervals by calling
* the read function with an POSIX timer.
* The interval is set in the configuration.
* - meters: the meter itselfs triggers a readout.
* The pointer to the read function shoul be NULL.
* The 'interval' column in the configuration as no meaning.
*/
#include "../config.h" /* GNU buildsystem config */
#include "common.h"
#include "list.h"
#include "reading.h"
#include "options.h"
#include "channel.h"
/* meter protocols */
#include "protocols/file.h"
#include "protocols/exec.h"
#include "protocols/random.h"
#include "protocols/s0.h"
#include "protocols/d0.h"
#include "protocols/fluksov2.h"
#ifdef SML_SUPPORT
#include "protocols/sml.h"
#endif /* SML_SUPPORT */
using namespace std;
typedef enum meter_procotol {
meter_protocol_file = 1,
meter_protocol_exec,
meter_protocol_random,
meter_protocol_s0,
meter_protocol_d0,
meter_protocol_sml,
meter_protocol_fluksov2
} meter_protocol_t;
class Meter {
public:
virtual ~Meter();
virtual int open() = 0;
virtual int close() = 0;
virtual size_t read(Reading *rds, size_t n);
int getInterval();
protected:
Meter(OptionList options);
static int instances;
int id;
typedef struct meter {
char id[5];
int interval;
meter_protocol_t protocol;
List<Channel> channels;
union {
meter_handle_file_t file;
meter_handle_exec_t exec;
meter_handle_random_t random;
meter_handle_s0_t s0;
meter_handle_d0_t d0;
meter_handle_fluksov2_t fluksov2;
#ifdef SML_SUPPORT
meter_handle_sml_t sml;
#endif /* SML_SUPPORT */
} handle;
} meter_t;
pthread_t thread;
};
typedef enum {
sml, d0
} meter_protocol_t;
typedef struct {
meter_protocol_t id;
@ -88,69 +67,12 @@ typedef struct {
char *desc; /* more detailed description */
size_t max_readings; /* how many readings can be read with 1 call */
int periodic:1; /* does this meter has be triggered periodically? */
/* function pointers */
int (*init_func)(meter_t *mtr, list_t options);
void (*free_func)(meter_t *mtr);
int (*open_func)(meter_t *mtr);
int (*close_func)(meter_t *mtr);
size_t (*read_func)(meter_t *mtr, reading_t *rds, size_t n);
} meter_details_t;
/* prototypes */
/**
* Get list of available meter types
*/
const meter_details_t * meter_get_protocols();
const meter_details_t * meter_get_details(meter_protocol_t protocol);
/**
* Initialize meter
*
* @param mtr the meter structure to initialze
* @param list of key, value pairs of options
* @return 0 on success, -1 on error
*/
int meter_init(meter_t *mtr, list_t options);
/**
* Freeing all memory which has been allocated during the initialization
*
* @param mtr the meter structure
*/
void meter_free(meter_t *mtr);
/**
* Dispatcher for blocking read from meters of diffrent types
*
* rds has to point to an array with space for at least n readings!
*
* @param mtr the meter structure
* @param rds the array to store the readings to
* @param n the size of the array
* @return number of readings
*/
size_t meter_read(meter_t *mtr, reading_t rds[], size_t n);
/**
* Dispatcher for opening meters of diffrent types,
*
* Establish connection, initialize meter etc.
*
* @param mtr the meter structure
* @return 0 on success, -1 on error
*/
int meter_open(meter_t *mtr);
/**
* Dispatcher for closing meters of diffrent types
*
* Reset ports, shutdown meter etc.
*
* @param mtr the meter structure
* @return 0 on success, -1 on error
*/
int meter_close(meter_t *mtr);
#endif /* _METER_H_ */

View file

@ -26,35 +26,44 @@
#ifndef _OBIS_H_
#define _OBIS_H_
#include <string.h>
#include "reading.h"
#define OBIS_STR_LEN (6*3+5+1)
/* regex: A-BB:CC.DD.EE([*&]FF)? */
typedef union {
class Obis {
public:
Obis(unsigned char *pRaw = NULL);
static Obis lookup(const char *alias);
/* regex: A-BB:CC.DD.EE([*&]FF)? */
void parse(const char *str);
void unparse(char *buffer, size_t n) const;
bool operator==(Obis const &cmp) const;
bool isManufacturerSpecific() const;
bool isNull() const;
protected:
unsigned char raw[6];
struct {
unsigned char media, channel, indicator, mode, quantities;
unsigned char storage; /* not used in Germany */
} groups;
} obis_id_t;
typedef struct {
obis_id_t id;
char *name;
char *desc;
} obis_alias_t;
typedef struct {
unsigned char raw[6];
char *name;
char *desc;
} ObisAlias;
/* prototypes */
obis_id_t * obis_init(obis_id_t *id, unsigned char *raw);
static ObisAlias aliases[];
};
const obis_alias_t * obis_get_aliases();
int obis_parse(const char *str, obis_id_t *id);
int obis_lookup_alias(const char *alias, obis_id_t *id);
int obis_unparse(obis_id_t id, char *buffer, size_t n);
int obis_compare(obis_id_t a, obis_id_t b);
class ObisIdentifier : public ReadingIdentifier, public Obis {
int obis_is_manufacturer_specific(obis_id_t id);
int obis_is_null(obis_id_t id);
public:
bool operator==(ObisIdentifier &cmp);
void parse(const char *string);
size_t unparse(char *buffer, size_t n);
};
#endif /* _OBIS_H_ */

View file

@ -3,42 +3,50 @@
#include "list.h"
typedef union {
const char *string;
int integer;
double floating;
int boolean:1;
} option_value_t;
class Option {
/* subset of json_type's */
typedef enum {
option_type_boolean = 1,
option_type_double,
option_type_int,
option_type_string = 6
} option_type_t;
public:
Option(char *key, char *value);
Option(char *key, int value);
Option(char *key, double value);
Option(char *key, bool value);
virtual ~Option();
operator char *();
operator int();
operator double();
operator bool();
protected:
Option(char *key);
typedef struct {
char *key;
option_type_t type;
option_value_t value;
} option_t;
/**
* Lookup option by key in a list of options
*
* @param list_t the list of options
* @param char *key the key you are looking for
* @return int success or error (CFG_* constants)
*/
int options_lookup(list_t options, char *key, void *value, option_type_t type);
union {
const char *string;
int integer;
double floating;
int boolean:1;
} value;
/**
* Type specific wrapper functions for config_lookup_type()
*/
int options_lookup_string(list_t options, char *key, char **value);
int options_lookup_int(list_t options, char *key, int *value);
int options_lookup_double(list_t options, char *key, double *value);
int options_lookup_boolean(list_t options, char *key, int *value);
/* subset of json_type's */
enum {
type_boolean = 1,
type_double,
type_int,
type_string = 6
} type;
};
class OptionList : public List<Option> {
public:
Option& lookup(char *key);
void parse();
protected:
};
#endif /* _OPTIONS_H_ */

View file

@ -33,32 +33,36 @@
#include <termios.h>
typedef struct {
#include "meter.h"
using namespace std;
class MeterD0 : public Meter {
public:
MeterD0(map<string, Option> options);
virtual ~MeterD0();
int open();
int close();
int read(reading_t *rds, size_t n);
protected:
char *host;
char *device;
int baudrate;
int fd; /* file descriptor of port */
struct termios oldtio; /* required to reset port */
} meter_handle_d0_t;
/* forward declarations */
struct meter;
struct reading;
int meter_init_d0(struct meter *mtr, list_t options);
void meter_free_d0(struct meter *mtr);
int meter_open_d0(struct meter *mtr);
int meter_close_d0(struct meter *mtr);
size_t meter_read_d0(struct meter *mtr, struct reading *rds, size_t n);
/**
* Open socket
*
* @param node the hostname or ASCII encoded IP address
* @param the ASCII encoded portnum or service as in /etc/services
* @return file descriptor, <0 on error
*/
int meter_d0_open_socket(const char *node, const char *service);
/**
* Open socket
*
* @param node the hostname or ASCII encoded IP address
* @param the ASCII encoded portnum or service as in /etc/services
* @return file descriptor, <0 on error
*/
int openSocket(const char *node, const char *service)
};
#endif /* _D0_H_ */

View file

@ -26,21 +26,23 @@
#ifndef _EXEC_H_
#define _EXEC_H_
#include <stdio.h>
#include "meter.h"
typedef struct {
using namespace std;
class MeterExec : public Meter {
public:
MeterExec(map<string, Option> options);
virtual MeterExec();
int open();
int close();
int read(reading_t *rds, size_t n);
protected:
char *command;
char *format;
} meter_handle_exec_t;
/* forward declarations */
struct meter;
struct reading;
int meter_init_exec(struct meter *mtr, list_t options);
void meter_free_exec(struct meter *mtr);
int meter_open_exec(struct meter *mtr);
int meter_close_exec(struct meter *mtr);
size_t meter_read_exec(struct meter *mtr, struct reading *rds, size_t n);
};
#endif /* _EXEC_H_ */

View file

@ -26,24 +26,26 @@
#ifndef _FILE_H_
#define _FILE_H_
#include <stdio.h>
#include "meter.h"
typedef struct {
using namespace std;
class MeterFile : public Meter {
public:
MeterFile(map<string, Option> options);
virtual ~MeterFile();
int open();
int close();
int read(reading_t *rds, size_t n);
protected:
char *path;
char *format;
int rewind;
FILE *fd;
} meter_handle_file_t;
/* forward declarations */
struct meter;
struct reading;
int meter_init_file(struct meter *mtr, list_t options);
void meter_free_file(struct meter *mtr);
int meter_open_file(struct meter *mtr);
int meter_close_file(struct meter *mtr);
size_t meter_read_file(struct meter *mtr, struct reading *rds, size_t n);
};
#endif /* _FILE_H_ */

View file

@ -22,26 +22,29 @@
* You should have received a copy of the GNU General Public License
* along with volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _FLUKSOV2_H_
#define _FLUKSOV2_H_
#define FLUKSOV2_DEFAULT_FIFO "/var/run/spid/delta/out"
#include "meter.h"
typedef struct {
using namespace std;
class MeterFluksoV2 : public Meter {
public:
MeterFluksoV2(map<string, Option> options);
virtual ~MeterFluksoV2();
int open();
int close();
int read(reading_t *rds, size_t n);
protected:
char *fifo;
int fd; /* file descriptor of fifo */
} meter_handle_fluksov2_t;
/* forward declarations */
struct meter;
struct reading;
int meter_init_fluksov2(struct meter *mtr, list_t options);
void meter_free_fluksov2(struct meter *mtr);
int meter_open_fluksov2(struct meter *mtr);
int meter_close_fluksov2(struct meter *mtr);
size_t meter_read_fluksov2(struct meter *mtr, struct reading *rds, size_t n);
const char *DEFAULT_FIFO = "/var/run/spid/delta/out";
};
#endif /* _FLUKSOV2_H_ */

View file

@ -26,21 +26,25 @@
#ifndef _RANDOM_H_
#define _RANDOM_H_
typedef struct {
#include "meter.h"
using namespace std;
double ltqnorm(double p); /* forward declaration */
class MeterRandom : public Meter {
public:
Random(map<string, Option> options);
virtual ~Random();
int open();
int close();
int read(reading_t *rds, size_t n);
protected:
double min, max;
double last;
} meter_handle_random_t;
/* forward declarations */
struct meter;
struct reading;
double ltqnorm(double p);
int meter_init_random(struct meter *mtr, list_t options);
void meter_free_random(struct meter *mtr);
int meter_open_random(struct meter *mtr);
int meter_close_random(struct meter *mtr);
size_t meter_read_random(struct meter *mtr, struct reading *rds, size_t n);
};
#endif /* _RANDOM_H_ */

View file

@ -28,22 +28,26 @@
#include <termios.h>
typedef struct {
#include "meter.h"
using namespace std;
class MeterS0 : public Meter {
public:
MeterS0(map<string, Option> options);
virtual ~MeterS0();
int open();
int close();
int read(reading_t *rds, size_t n);
protected:
char *device;
int resolution;
int fd; /* file descriptor of port */
struct termios old_tio; /* required to reset port */
} meter_handle_s0_t;
/* forward declarations */
struct meter;
struct reading;
int meter_init_s0(struct meter *mtr, list_t options);
void meter_free_s0(struct meter *mtr);
int meter_open_s0(struct meter *mtr);
int meter_close_s0(struct meter *mtr);
size_t meter_read_s0(struct meter *mtr, struct reading *rds, size_t n);
};
#endif /* _S0_H_ */

View file

@ -30,97 +30,63 @@
#ifndef _SML_H_
#define _SML_H_
#define SML_BUFFER_LEN 8096
#include <sml/sml_file.h>
#include <sml/sml_value.h>
#include <termios.h>
#include "meter.h"
#include "obis.h"
typedef struct {
using namespace std;
class MeterSML : public Meter {
public:
MeterSML(map<string, Option> options);
virtual ~MeterSML();
int open();
int close();
int read(reading_t *rds, size_t n);
protected:
char *host;
char *device;
speed_t baudrate;
int fd; /* file descriptor of port */
struct termios old_tio; /* required to reset port */
} meter_handle_sml_t;
/* forward declarations */
struct meter;
struct reading;
const int BUFFER_LEN = 8192;
/**
* Initialize meter structure with a list of options
*
* @param mtr the meter structure
* @param options a list of options
* @return 0 on success, <0 on error
*/
int meter_init_sml(struct meter *mtr, list_t options);
/**
* Parses SML list entry and stores it in reading pointed by rd
*
* @param list the list entry
* @param rd the reading to store to
*/
void parse(sml_list *list, struct reading *rd);
/**
* Freeing allocated resources during initialization
*
* @param mtr the meter structure
*/
void meter_free_sml(struct meter *mtr);
/**
* Open serial port by device
*
* @param device the device path, usually /dev/ttyS*
* @param old_config pointer to termios structure, will be filled with old port configuration
* @param baudrate the baudrate
* @return file descriptor, <0 on error
*/
int openDevice(const char *device, struct termios *old_config, speed_t baudrate);
/**
* Open connection via serial port or socket to meter
*
* @param mtr the meter structure
* @return 0 on success, <0 on error
*/
int meter_open_sml(struct meter *mtr);
/**
* Open socket
*
* @param node the hostname or ASCII encoded IP address
* @param the ASCII encoded portnum or service as in /etc/services
* @return file descriptor, <0 on error
*/
int openSocket(const char *node, const char *service);
};
/**
* Reset port/socket and freeing handle
*
* @param mtr the meter structure
*/
int meter_close_sml(struct meter *mtr);
/**
* Blocking read on meter
*
* Most EDL conform meters periodically send data every
* 3-4 seconds.
*
* @param mtr the meter structure
* @param rds pointer to array of readings with size n
* @param n size of the rds array
* @return number of readings stored to rds
*/
size_t meter_read_sml(struct meter *mtr, struct reading *rds, size_t n);
/**
* Parses SML list entry and stores it in reading pointed by rd
*
* @param list the list entry
* @param rd the reading to store to
*/
void meter_sml_parse(sml_list *list, struct reading *rd);
/**
* Open serial port by device
*
* @param device the device path, usually /dev/ttyS*
* @param old_config pointer to termios structure, will be filled with old port configuration
* @param baudrate the baudrate
* @return file descriptor, <0 on error
*/
int meter_sml_open_device(const char *device, struct termios *old_config, speed_t baudrate);
/**
* Open socket
*
* @param node the hostname or ASCII encoded IP address
* @param the ASCII encoded portnum or service as in /etc/services
* @return file descriptor, <0 on error
*/
int meter_sml_open_socket(const char *node, const char *service);
#endif /* _SML_H_ */

View file

@ -28,66 +28,50 @@
#include <sys/time.h>
#include "obis.h"
#define MAX_IDENTIFIER_LEN 255
typedef union reading_id {
obis_id_t obis;
char *string;
char *uuid;
int channel;
} reading_id_t;
/* Identifiers */
class ReadingIdentifier {
public:
virtual bool operator==(ReadingIdentifier &cmp) = 0;
virtual void parse(const char *string) = 0;
virtual size_t unparse(char *buffer, size_t n) = 0;
};
class StringIdentifier : public ReadingIdentifier {
public:
bool operator==(ReadingIdentifier &cmp);
void parse(const char *string);
size_t unparse(char *buffer, size_t n);
~StringIdentifier();
protected:
char *string;
};
class ChannelIdentifier : public ReadingIdentifier {
public:
bool operator==(ReadingIdentifier &cmp);
void parse(const char *string);
size_t unparse(char *buffer, size_t n);
protected:
int channel;
};
class Reading {
public:
static double tvtod(struct timeval tv);
static struct timeval dtotv(double ts);
typedef struct reading {
double value;
struct timeval time;
reading_id_t identifier;
struct reading *next; /* pointer for linked list */
} reading_t;
/* prototypes */
enum meter_procotol; /* forward declaration */
/**
* Parse two reading identifiers in a given protocol context
*
* @return result like in strcmp()
*/
int reading_id_compare(enum meter_procotol prot, reading_id_t a, reading_id_t b);
/**
* Parse identifier by a given string and protocol
*
* @param protocol the given protocol context in which the string should be parsed
* @param string the string-encoded identifier
* @return 0 on success, < 0 on error
*/
int reading_id_parse(enum meter_procotol protocol, reading_id_t *id, const char *string);
/**
* Print identifier to buffer for debugging/dump
*
* @return the amount of bytes used in buffer
*/
size_t reading_id_unparse(enum meter_procotol protocol, reading_id_t identifier, char *buffer, size_t n);
/**
* Converts timeval structure to double
*
* @param tv the timeval structure
* @return the double value
*/
double tvtod(struct timeval tv);
/**
* Converts double to timeval structure
*
* @param ts the double value
* @return the timeval strucure
*/
struct timeval dtotv(double ts);
ReadingIdentifier *identifier;
};
#endif /* _READING_H_ */

View file

@ -27,23 +27,13 @@
#define _VZLOGGER_H_
#include <pthread.h>
#include "../config.h" /* GNU buildsystem config */
#include <vector>
#include "config.h"
#include "meter.h"
#include "common.h"
#include "list.h"
#include "channel.h"
/**
* Type for mapping channels to meters
*/
typedef struct map {
meter_t meter;
list_t channels;
pthread_t thread;
} map_t;
using namespace std;
/* prototypes */
void quit(int sig);

View file

@ -4,17 +4,19 @@ AM_LDFLAGS =
bin_PROGRAMS = vzlogger
vzlogger_SOURCES = vzlogger.c channel.c api.c config.c threads.c buffer.c
vzlogger_SOURCES += meter.c ltqnorm.c obis.c options.c reading.c
vzlogger_SOURCES = test.cpp buffer.cpp reading.cpp obis.cpp exception.cpp
#vzlogger_SOURCES = vzlogger.c channel.c api.c config.c threads.c buffer.c
#vzlogger_SOURCES += meter.c ltqnorm.c obis.c options.c reading.c
# Protocols (add your own here)
vzlogger_SOURCES += \
protocols/s0.c \
protocols/d0.c \
protocols/fluksov2.c \
protocols/file.c \
protocols/exec.c \
protocols/random.c
#vzlogger_SOURCES += \
# protocols/s0.c \
# protocols/d0.c \
# protocols/fluksov2.c \
# protocols/file.c \
# protocols/exec.c \
# protocols/random.c
vzlogger_LDADD =
vzlogger_LDFLAGS = -lpthread -lm $(DEPS_VZ_LIBS)
@ -22,7 +24,7 @@ vzlogger_LDFLAGS = -lpthread -lm $(DEPS_VZ_LIBS)
# SML support
####################################################################
if SML_SUPPORT
vzlogger_SOURCES += protocols/sml.c
#vzlogger_SOURCES += protocols/sml.c
vzlogger_LDADD += $(DEPS_SML_LIBS)
AM_CFLAGS += $(DEPS_SML_CFLAGS)
endif
@ -30,7 +32,7 @@ endif
# local interface support
####################################################################
if LOCAL_SUPPORT
vzlogger_SOURCES += local.c
#vzlogger_SOURCES += local.c
vzlogger_LDADD += $(DEPS_LOCAL_LIBS)
AM_CFLAGS += $(DEPS_LOCAL_CFLAGS)
endif

View file

@ -36,15 +36,15 @@ bin_PROGRAMS = vzlogger$(EXEEXT)
# SML support
####################################################################
@SML_SUPPORT_TRUE@am__append_1 = protocols/sml.c
@SML_SUPPORT_TRUE@am__append_2 = $(DEPS_SML_LIBS)
@SML_SUPPORT_TRUE@am__append_3 = $(DEPS_SML_CFLAGS)
#vzlogger_SOURCES += protocols/sml.c
@SML_SUPPORT_TRUE@am__append_1 = $(DEPS_SML_LIBS)
@SML_SUPPORT_TRUE@am__append_2 = $(DEPS_SML_CFLAGS)
# local interface support
####################################################################
@LOCAL_SUPPORT_TRUE@am__append_4 = local.c
@LOCAL_SUPPORT_TRUE@am__append_5 = $(DEPS_LOCAL_LIBS)
@LOCAL_SUPPORT_TRUE@am__append_6 = $(DEPS_LOCAL_CFLAGS)
#vzlogger_SOURCES += local.c
@LOCAL_SUPPORT_TRUE@am__append_3 = $(DEPS_LOCAL_LIBS)
@LOCAL_SUPPORT_TRUE@am__append_4 = $(DEPS_LOCAL_CFLAGS)
subdir = src
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@ -57,37 +57,26 @@ CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)"
PROGRAMS = $(bin_PROGRAMS)
am__vzlogger_SOURCES_DIST = vzlogger.c channel.c api.c config.c \
threads.c buffer.c meter.c ltqnorm.c obis.c options.c \
reading.c protocols/s0.c protocols/d0.c protocols/fluksov2.c \
protocols/file.c protocols/exec.c protocols/random.c \
protocols/sml.c local.c
@SML_SUPPORT_TRUE@am__objects_1 = sml.$(OBJEXT)
@LOCAL_SUPPORT_TRUE@am__objects_2 = local.$(OBJEXT)
am_vzlogger_OBJECTS = vzlogger.$(OBJEXT) channel.$(OBJEXT) \
api.$(OBJEXT) config.$(OBJEXT) threads.$(OBJEXT) \
buffer.$(OBJEXT) meter.$(OBJEXT) ltqnorm.$(OBJEXT) \
obis.$(OBJEXT) options.$(OBJEXT) reading.$(OBJEXT) \
s0.$(OBJEXT) d0.$(OBJEXT) fluksov2.$(OBJEXT) file.$(OBJEXT) \
exec.$(OBJEXT) random.$(OBJEXT) $(am__objects_1) \
$(am__objects_2)
am_vzlogger_OBJECTS = test.$(OBJEXT) buffer.$(OBJEXT) \
reading.$(OBJEXT) obis.$(OBJEXT) exception.$(OBJEXT)
vzlogger_OBJECTS = $(am_vzlogger_OBJECTS)
am__DEPENDENCIES_1 =
@SML_SUPPORT_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
@LOCAL_SUPPORT_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
vzlogger_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3)
vzlogger_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(vzlogger_LDFLAGS) \
$(LDFLAGS) -o $@
vzlogger_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
$(vzlogger_LDFLAGS) $(LDFLAGS) -o $@
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX)
CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
-o $@
SOURCES = $(vzlogger_SOURCES)
DIST_SOURCES = $(am__vzlogger_SOURCES_DIST)
DIST_SOURCES = $(vzlogger_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@ -102,6 +91,9 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
@ -150,6 +142,7 @@ abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@ -188,22 +181,28 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AM_CFLAGS = -Wall -D_REENTRANT -std=gnu99 $(DEPS_VZ_CFLAGS) \
$(am__append_3) $(am__append_6)
$(am__append_2) $(am__append_4)
AM_CPPFLAGS = -I $(top_srcdir)/include
AM_LDFLAGS =
vzlogger_SOURCES = test.cpp buffer.cpp reading.cpp obis.cpp exception.cpp
#vzlogger_SOURCES = vzlogger.c channel.c api.c config.c threads.c buffer.c
#vzlogger_SOURCES += meter.c ltqnorm.c obis.c options.c reading.c
# Protocols (add your own here)
vzlogger_SOURCES = vzlogger.c channel.c api.c config.c threads.c \
buffer.c meter.c ltqnorm.c obis.c options.c reading.c \
protocols/s0.c protocols/d0.c protocols/fluksov2.c \
protocols/file.c protocols/exec.c protocols/random.c \
$(am__append_1) $(am__append_4)
vzlogger_LDADD = $(am__append_2) $(am__append_5)
#vzlogger_SOURCES += \
# protocols/s0.c \
# protocols/d0.c \
# protocols/fluksov2.c \
# protocols/file.c \
# protocols/exec.c \
# protocols/random.c
vzlogger_LDADD = $(am__append_1) $(am__append_3)
vzlogger_LDFLAGS = -lpthread -lm $(DEPS_VZ_LIBS)
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
.SUFFIXES: .cpp .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
@ -281,137 +280,25 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/api.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/d0.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exec.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fluksov2.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ltqnorm.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/meter.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exception.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/obis.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reading.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/s0.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sml.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threads.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vzlogger.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.cpp.o:
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
s0.o: protocols/s0.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT s0.o -MD -MP -MF $(DEPDIR)/s0.Tpo -c -o s0.o `test -f 'protocols/s0.c' || echo '$(srcdir)/'`protocols/s0.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/s0.Tpo $(DEPDIR)/s0.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='protocols/s0.c' object='s0.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o s0.o `test -f 'protocols/s0.c' || echo '$(srcdir)/'`protocols/s0.c
s0.obj: protocols/s0.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT s0.obj -MD -MP -MF $(DEPDIR)/s0.Tpo -c -o s0.obj `if test -f 'protocols/s0.c'; then $(CYGPATH_W) 'protocols/s0.c'; else $(CYGPATH_W) '$(srcdir)/protocols/s0.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/s0.Tpo $(DEPDIR)/s0.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='protocols/s0.c' object='s0.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o s0.obj `if test -f 'protocols/s0.c'; then $(CYGPATH_W) 'protocols/s0.c'; else $(CYGPATH_W) '$(srcdir)/protocols/s0.c'; fi`
d0.o: protocols/d0.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT d0.o -MD -MP -MF $(DEPDIR)/d0.Tpo -c -o d0.o `test -f 'protocols/d0.c' || echo '$(srcdir)/'`protocols/d0.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/d0.Tpo $(DEPDIR)/d0.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='protocols/d0.c' object='d0.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o d0.o `test -f 'protocols/d0.c' || echo '$(srcdir)/'`protocols/d0.c
d0.obj: protocols/d0.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT d0.obj -MD -MP -MF $(DEPDIR)/d0.Tpo -c -o d0.obj `if test -f 'protocols/d0.c'; then $(CYGPATH_W) 'protocols/d0.c'; else $(CYGPATH_W) '$(srcdir)/protocols/d0.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/d0.Tpo $(DEPDIR)/d0.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='protocols/d0.c' object='d0.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o d0.obj `if test -f 'protocols/d0.c'; then $(CYGPATH_W) 'protocols/d0.c'; else $(CYGPATH_W) '$(srcdir)/protocols/d0.c'; fi`
fluksov2.o: protocols/fluksov2.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fluksov2.o -MD -MP -MF $(DEPDIR)/fluksov2.Tpo -c -o fluksov2.o `test -f 'protocols/fluksov2.c' || echo '$(srcdir)/'`protocols/fluksov2.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/fluksov2.Tpo $(DEPDIR)/fluksov2.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='protocols/fluksov2.c' object='fluksov2.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fluksov2.o `test -f 'protocols/fluksov2.c' || echo '$(srcdir)/'`protocols/fluksov2.c
fluksov2.obj: protocols/fluksov2.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fluksov2.obj -MD -MP -MF $(DEPDIR)/fluksov2.Tpo -c -o fluksov2.obj `if test -f 'protocols/fluksov2.c'; then $(CYGPATH_W) 'protocols/fluksov2.c'; else $(CYGPATH_W) '$(srcdir)/protocols/fluksov2.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/fluksov2.Tpo $(DEPDIR)/fluksov2.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='protocols/fluksov2.c' object='fluksov2.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fluksov2.obj `if test -f 'protocols/fluksov2.c'; then $(CYGPATH_W) 'protocols/fluksov2.c'; else $(CYGPATH_W) '$(srcdir)/protocols/fluksov2.c'; fi`
file.o: protocols/file.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file.o -MD -MP -MF $(DEPDIR)/file.Tpo -c -o file.o `test -f 'protocols/file.c' || echo '$(srcdir)/'`protocols/file.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/file.Tpo $(DEPDIR)/file.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='protocols/file.c' object='file.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file.o `test -f 'protocols/file.c' || echo '$(srcdir)/'`protocols/file.c
file.obj: protocols/file.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file.obj -MD -MP -MF $(DEPDIR)/file.Tpo -c -o file.obj `if test -f 'protocols/file.c'; then $(CYGPATH_W) 'protocols/file.c'; else $(CYGPATH_W) '$(srcdir)/protocols/file.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/file.Tpo $(DEPDIR)/file.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='protocols/file.c' object='file.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file.obj `if test -f 'protocols/file.c'; then $(CYGPATH_W) 'protocols/file.c'; else $(CYGPATH_W) '$(srcdir)/protocols/file.c'; fi`
exec.o: protocols/exec.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT exec.o -MD -MP -MF $(DEPDIR)/exec.Tpo -c -o exec.o `test -f 'protocols/exec.c' || echo '$(srcdir)/'`protocols/exec.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/exec.Tpo $(DEPDIR)/exec.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='protocols/exec.c' object='exec.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o exec.o `test -f 'protocols/exec.c' || echo '$(srcdir)/'`protocols/exec.c
exec.obj: protocols/exec.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT exec.obj -MD -MP -MF $(DEPDIR)/exec.Tpo -c -o exec.obj `if test -f 'protocols/exec.c'; then $(CYGPATH_W) 'protocols/exec.c'; else $(CYGPATH_W) '$(srcdir)/protocols/exec.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/exec.Tpo $(DEPDIR)/exec.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='protocols/exec.c' object='exec.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o exec.obj `if test -f 'protocols/exec.c'; then $(CYGPATH_W) 'protocols/exec.c'; else $(CYGPATH_W) '$(srcdir)/protocols/exec.c'; fi`
random.o: protocols/random.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT random.o -MD -MP -MF $(DEPDIR)/random.Tpo -c -o random.o `test -f 'protocols/random.c' || echo '$(srcdir)/'`protocols/random.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/random.Tpo $(DEPDIR)/random.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='protocols/random.c' object='random.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o random.o `test -f 'protocols/random.c' || echo '$(srcdir)/'`protocols/random.c
random.obj: protocols/random.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT random.obj -MD -MP -MF $(DEPDIR)/random.Tpo -c -o random.obj `if test -f 'protocols/random.c'; then $(CYGPATH_W) 'protocols/random.c'; else $(CYGPATH_W) '$(srcdir)/protocols/random.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/random.Tpo $(DEPDIR)/random.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='protocols/random.c' object='random.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o random.obj `if test -f 'protocols/random.c'; then $(CYGPATH_W) 'protocols/random.c'; else $(CYGPATH_W) '$(srcdir)/protocols/random.c'; fi`
sml.o: protocols/sml.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sml.o -MD -MP -MF $(DEPDIR)/sml.Tpo -c -o sml.o `test -f 'protocols/sml.c' || echo '$(srcdir)/'`protocols/sml.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sml.Tpo $(DEPDIR)/sml.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='protocols/sml.c' object='sml.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sml.o `test -f 'protocols/sml.c' || echo '$(srcdir)/'`protocols/sml.c
sml.obj: protocols/sml.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sml.obj -MD -MP -MF $(DEPDIR)/sml.Tpo -c -o sml.obj `if test -f 'protocols/sml.c'; then $(CYGPATH_W) 'protocols/sml.c'; else $(CYGPATH_W) '$(srcdir)/protocols/sml.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sml.Tpo $(DEPDIR)/sml.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='protocols/sml.c' object='sml.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sml.obj `if test -f 'protocols/sml.c'; then $(CYGPATH_W) 'protocols/sml.c'; else $(CYGPATH_W) '$(srcdir)/protocols/sml.c'; fi`
.cpp.obj:
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \

View file

@ -1,143 +0,0 @@
/**
* Circular buffer (double linked)
*
* Used to store recent readings and buffer in case of net inconnectivity
*
* @author Steffen Vogel <info@steffenvogel.de>
* @copyright Copyright (c) 2011, The volkszaehler.org project
* @package vzlogger
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/
/*
* This file is part of volkzaehler.org
*
* volkzaehler.org 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
* any later version.
*
* volkzaehler.org 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 volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "buffer.h"
void buffer_init(buffer_t *buf) {
pthread_mutex_init(&buf->mutex, NULL);
pthread_mutex_lock(&buf->mutex);
buf->head = NULL;
buf->tail = NULL;
buf->sent = NULL;
buf->size = 0;
buf->keep = 0;
pthread_mutex_unlock(&buf->mutex);
}
reading_t * buffer_push(buffer_t *buf, reading_t *rd) {
reading_t *new;
/* allocate memory for new reading */
new = malloc(sizeof(reading_t));
/* cannot allocate memory */
if (new == NULL) {
/* => delete old readings (ring buffer) */
if (buf->size > 0) {
new = buf->head;
pthread_mutex_lock(&buf->mutex);
buf->head = new->next;
buf->size--;
pthread_mutex_unlock(&buf->mutex);
}
else { /* giving up :-( */
return NULL;
}
}
memcpy(new, rd, sizeof(reading_t));
pthread_mutex_lock(&buf->mutex);
if (buf->size == 0) { /* empty buffer */
buf->head = new;
}
else {
buf->tail->next = new;
}
new->next = NULL;
buf->tail = new;
buf->size++;
pthread_mutex_unlock(&buf->mutex);
return new;
}
void buffer_clean(buffer_t *buf) {
pthread_mutex_lock(&buf->mutex);
while(buf->size > buf->keep && buf->head != buf->sent) {
reading_t *pop = buf->head;
buf->head = buf->head->next;
buf->size--;
free(pop);
}
pthread_mutex_unlock(&buf->mutex);
}
char * buffer_dump(buffer_t *buf, char *dump, size_t len) {
size_t pos = 0;
dump[pos++] = '{';
for (reading_t *rd = buf->head; rd != NULL; rd = rd->next) {
if (pos < len) {
pos += snprintf(dump+pos, len-pos, "%.2f", rd->value);
}
/* indicate last sent reading */
if (pos < len && buf->sent == rd) {
dump[pos++] = '!';
}
/* add seperator between values */
if (pos < len && rd->next != NULL) {
dump[pos++] = ',';
}
}
if (pos+1 < len) {
dump[pos++] = '}';
dump[pos] = '\0'; /* zero terminated string */
}
return (pos < len) ? dump : NULL; /* buffer full? */
}
void buffer_free(buffer_t *buf) {
pthread_mutex_destroy(&buf->mutex);
reading_t *rd = buf->head;
if (rd) do {
reading_t *tmp = rd;
rd = rd->next;
free(tmp);
} while (rd);
buf->head = NULL;
buf->tail = NULL;
buf->sent = NULL;
buf->size = 0;
buf->keep = 0;
}

88
src/buffer.cpp Normal file
View file

@ -0,0 +1,88 @@
/**
* Circular buffer (double linked)
*
* Used to store recent readings and buffer in case of net inconnectivity
*
* @author Steffen Vogel <info@steffenvogel.de>
* @copyright Copyright (c) 2011, The volkszaehler.org project
* @package vzlogger
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/
/*
* This file is part of volkzaehler.org
*
* volkzaehler.org 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
* any later version.
*
* volkzaehler.org 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 volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "buffer.h"
Buffer::Buffer() : List<Reading>() {
pthread_mutex_init(&mutex, NULL);
}
Buffer::Iterator Buffer::push(Reading data) {
Iterator it;
pthread_mutex_lock(&mutex);
it = push(data);
pthread_mutex_unlock(&mutex);
return it;
}
void Buffer::shrink(size_t keep) {
pthread_mutex_lock(&mutex);
// while(size > keep && begin() != sent) {
// pop();
// }
pthread_mutex_unlock(&mutex);
}
char * Buffer::dump(char *dump, size_t len) {
size_t pos = 0;
dump[pos++] = '{';
for (Iterator it = begin(); it != end(); ++it) {
if (pos < len) {
pos += snprintf(dump+pos, len-pos, "%.2f", it->value);
}
/* indicate last sent reading */
if (pos < len && it == sent) {
dump[pos++] = '!';
}
/* add seperator between values */
if (pos < len) {
dump[pos++] = ',';
}
}
if (pos+1 < len) {
dump[pos++] = '}';
dump[pos] = '\0'; /* zero terminated string */
}
return (pos < len) ? dump : NULL; /* buffer full? */
}
Buffer::~Buffer() {
pthread_mutex_destroy(&mutex);
}

View file

@ -30,27 +30,28 @@
#include "channel.h"
void channel_init(channel_t *ch, const char *uuid, const char *middleware, reading_id_t identifier) {
static int instances; /* static to generate channel ids */
snprintf(ch->id, 5, "ch%i", instances++);
Channel::instances = 0;
ch->identifier = identifier;
Channel::Channel(const char *pUuid, const char *pMiddleware, reading_id_t pIdentifier) {
id = instances++;
ch->uuid = strdup(uuid);
ch->middleware = strdup(middleware);
identifier = pIdentifier;
buffer_init(&ch->buffer); /* initialize buffer */
pthread_cond_init(&ch->condition, NULL); /* initialize thread syncronization helpers */
uuid = strdup(pUuid);
middleware = strdup(pMiddleware);
buffer_init(&buffer); /* initialize buffer */
pthread_cond_init(&condition, NULL); /* initialize thread syncronization helpers */
}
/**
* Free all allocated memory recursivly
*/
void channel_free(channel_t *ch) {
buffer_free(&ch->buffer);
pthread_cond_destroy(&ch->condition);
Channel::~Channel() {
buffer_free(&buffer);
pthread_cond_destroy(&condition);
free(ch->uuid);
free(ch->middleware);
free(uuid);
free(middleware);
}

34
src/exception.cpp Normal file
View file

@ -0,0 +1,34 @@
/**
* Exceptions
*
* Used to store recent readings and buffer in case of net inconnectivity
*
* @author Steffen Vogel <info@steffenvogel.de>
* @copyright Copyright (c) 2011, The volkszaehler.org project
* @package vzlogger
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/
/*
* This file is part of volkzaehler.org
*
* volkzaehler.org 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
* any later version.
*
* volkzaehler.org 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 volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdio>
#include "exception.h"
Exception::Exception(const char *msg) {
printf("Exception: %s", msg);
}

View file

@ -29,12 +29,12 @@
#include "meter.h"
#include "options.h"
#define METER_DETAIL(NAME, DESC, MAX_RDS, PERIODIC) { meter_protocol_##NAME, #NAME, DESC, MAX_RDS, PERIODIC, meter_init_##NAME, meter_free_##NAME, meter_open_##NAME, meter_close_##NAME, meter_read_##NAME }
#define METER_DETAIL(NAME, DESC, MAX_RDS, PERIODIC) { meter_protocol_##NAME, #NAME, DESC, MAX_RDS, PERIODIC, meter_init_##NAME }
static const meter_details_t protocols[] = {
/* alias description max_rds periodic
===============================================================================================*/
METER_DETAIL(file, "Read from file or fifo", 32, TRUE),
METER_DETAIL( file, "Read from file or fifo", 32, TRUE),
//METER_DETAIL(exec, "Parse program output", 32, TRUE),
METER_DETAIL(random, "Generate random values with a random walk", 1, TRUE),
METER_DETAIL(fluksov2, "Read from Flukso's onboard SPI fifo", 16, FALSE),
@ -46,9 +46,8 @@ METER_DETAIL(sml, "Smart Message Language as used by EDL-21, eHz and SyM²", 32,
{} /* stop condition for iterator */
};
int meter_init(meter_t *mtr, list_t options) {
static int instances; /* static to generate unique channel ids */
snprintf(mtr->id, 5, "mtr%i", instances++); /* set/increment id */
Meter::Meter(list_t pOptions) {
id = instances++;
/* protocol */
char *protocol_str;
@ -57,44 +56,26 @@ int meter_init(meter_t *mtr, list_t options) {
return ERR;
}
if (meter_lookup_protocol(protocol_str, &mtr->protocol) != SUCCESS) {
if (meter_lookup_protocol(protocol_str, &protocol) != SUCCESS) {
print(log_error, "Invalid protocol: %s", mtr, protocol_str);
return ERR; /* skipping this meter */
}
/* interval */
mtr->interval = -1; /* indicates unknown interval */
if (options_lookup_int(options, "interval", &mtr->interval) == ERR_INVALID_TYPE) {
if (options_lookup_int(options, "interval", &interval) == ERR_INVALID_TYPE) {
print(log_error, "Invalid type for interval", mtr);
return ERR;
}
const meter_details_t *details = meter_get_details(mtr->protocol);
const meter_details_t *details = meter_get_details(protocol);
if (details->periodic == TRUE && mtr->interval < 0) {
print(log_error, "Interval has to be positive!", mtr);
}
return details->init_func(mtr, options);
}
void meter_free(meter_t *mtr) {
const meter_details_t *details = meter_get_details(mtr->protocol);
return details->free_func(mtr);
}
Meter::~Meter() {
int meter_open(meter_t *mtr) {
const meter_details_t *details = meter_get_details(mtr->protocol);
return details->open_func(mtr);
}
int meter_close(meter_t *mtr) {
const meter_details_t *details = meter_get_details(mtr->protocol);
return details->close_func(mtr);
}
size_t meter_read(meter_t *mtr, reading_t rds[], size_t n) {
const meter_details_t *details = meter_get_details(mtr->protocol);
return details->read_func(mtr, rds, n);
}
int meter_lookup_protocol(const char* name, meter_protocol_t *protocol) {

View file

@ -33,7 +33,7 @@
#define DC 0xff // wildcard, dont care
static const obis_alias_t aliases[] = {
const Obis::aliases[] = {
/* A B C D E F alias description
====================================================================*/
@ -91,19 +91,17 @@ const obis_alias_t * obis_get_aliases() {
return aliases;
}
obis_id_t * obis_init(obis_id_t *id, unsigned char *raw) {
if (raw == NULL) {
Obis(unsigned char *pRaw) {
if (pRaw == NULL) {
// TODO why not initialize with DC fields to accept all readings?
memset(id->raw, 0, 6); /* initialize with zeros */
memset(raw, 0, 6); /* initialize with zeros */
}
else {
memcpy(id->raw, raw, 6);
memcpy(raw, pRaw, 6);
}
return id;
}
int obis_parse(const char *str, obis_id_t *id) {
int Obis::parse(const char *str) {
enum { A = 0, B, C, D, E, F };
char byte; /* currently processed byte */
@ -153,7 +151,7 @@ int obis_parse(const char *str, obis_id_t *id) {
return (field < D) ? ERR : SUCCESS;
}
int obis_lookup_alias(const char *alias, obis_id_t *id) {
static Obis Obis::lookupAlias(const char *alias) {
for (const obis_alias_t *it = aliases; it != NULL; it++) {
if (strcmp(it->name, alias) == 0) {
*id = it->id;
@ -163,7 +161,7 @@ int obis_lookup_alias(const char *alias, obis_id_t *id) {
return ERR_NOT_FOUND;
}
int obis_unparse(obis_id_t id, char *buffer, size_t n) {
size_t Obis::unparse(char *buffer, size_t n) {
return snprintf(buffer, n, "%i-%i:%i.%i.%i*%i",
id.groups.media,
id.groups.channel,
@ -174,7 +172,7 @@ int obis_unparse(obis_id_t id, char *buffer, size_t n) {
);
}
int obis_compare(obis_id_t a, obis_id_t b) {
bool Obis::operator==(Obis &cmp) {
for (int i = 0; i < 6; i++) {
if (a.raw[i] == b.raw[i] || a.raw[i] == 0xff || b.raw[i] == 0xff ) {
continue; /* skip on wildcard or equal */
@ -190,7 +188,7 @@ int obis_compare(obis_id_t a, obis_id_t b) {
return 0; /* equal */
}
int obis_is_null(obis_id_t id) {
int Obis::isNull() {
return !(
id.raw[0] ||
id.raw[1] ||
@ -201,7 +199,7 @@ int obis_is_null(obis_id_t id) {
);
}
int obis_is_manufacturer_specific(obis_id_t id) {
int Obis::isManufacturerSpecific() {
return (
(id.groups.channel >= 128 && id.groups.channel <= 199) ||
(id.groups.indicator >= 128 && id.groups.indicator <= 199) ||
@ -212,3 +210,21 @@ int obis_is_manufacturer_specific(obis_id_t id) {
);
}
/*
bool ObisIdentifier::operator==(ReadingIdentifier &cmp) {
return (obis_compare(a.obis, b.obis) == 0);
}
void ObisIdentifier::parse(const char *string) {
if (obis_parse(string, &id->obis) != SUCCESS) {
if (obis_lookup_alias(string, &id->obis) != SUCCESS) {
throw new Exception("Failed to parse OBIS id");
}
}
}
size_t ObisIdentifier::unparse(char *buffer, size_t n) {
return obis_unparse(id.obis, buffer, n);
}
*/

View file

@ -26,10 +26,67 @@
#include <string.h>
#include "options.h"
#include "common.h"
int options_lookup(list_t options, char *key, void *value, option_type_t type) {
option_t * option = NULL;
Option::Option(char *pKey, char *pValue) { Option(pKey);
value.string = strdup(pValue);
type = type_string;
}
Option::Option(char *pKey, int pValue) { Option(pKey);
value.integer = pValue;
type = type_int;
}
Option::Option(char *pKey, double pValue) { Option(pKey);
value.floating = pValue;
type = type_double;
}
Option::Option(char *pKey, bool pValue) { Option(pKey);
value.boolean = pValue;
type = type_boolean;
}
Option::Option(char *pKey) {
key = strdup(pKey);
}
Option::~Option() {
if (key != NULL) {
free(key);
}
if (value.string != NULL && type == type_string) {
free(value.string);
}
}
Option::operator (char *)() {
if (type != type_string) throw Exception("Invalid type");
return value.string;
}
Option::operator int() {
if (type != type_int) throw Exception("Invalid type");
return value.integer;
}
Option::operator double() {
if (type != type_double) throw Exception("Invalid type");
return value.floating;
}
Option::operator bool() {
if (type != type_boolean) throw Exception("Invalid type");
return value.boolean;
}
Option& OptionList::lookup(List<Option> options, char *key) {
Option &option;
/* linear search */
foreach(options, val, option_t) {
@ -38,27 +95,10 @@ int options_lookup(list_t options, char *key, void *value, option_type_t type) {
}
}
/* checks */
if (option == NULL) {
return ERR_NOT_FOUND;
}
else if (option->type == type) {
size_t n = 0;
switch (option->type) {
case option_type_boolean: n = sizeof(option->value.integer); break; /* boolean is a bitfield: int boolean:1; */
case option_type_double: n = sizeof(option->value.floating); break;
case option_type_int: n = sizeof(option->value.integer); break;
case option_type_string: n = sizeof(option->value.string); break;
}
memcpy(value, &option->value, n);
return SUCCESS;
}
else {
return ERR_INVALID_TYPE;
if (option == options.end()) {
throw Exception("Option not found");
}
return option;
}
int options_lookup_boolean(list_t o, char *k, int *v) { return options_lookup(o, k, v, option_type_boolean); }
int options_lookup_int(list_t o, char *k, int *v) { return options_lookup(o, k, v, option_type_int); }
int options_lookup_string(list_t o, char *k, char **v) { return options_lookup(o, k, v, option_type_string); }
int options_lookup_double(list_t o, char *k, double *v) { return options_lookup(o, k, v, option_type_double); }

View file

@ -41,14 +41,12 @@
#include <netdb.h>
#include <sys/socket.h>
#include "meter.h"
#include "protocols/d0.h"
#include "obis.h"
#include "options.h"
int meter_init_d0(meter_t *mtr, list_t options) {
meter_handle_d0_t *handle = &mtr->handle.d0;
int MeterD0::MeterD0(map<string, Option> options) {
/* connection */
char *host, *device;
if (options_lookup_string(options, "host", &host) == SUCCESS) {
@ -94,25 +92,19 @@ int meter_init_d0(meter_t *mtr, list_t options) {
print(log_error, "Failed to parse the baudrate", mtr);
return ERR;
}
return SUCCESS;
}
void meter_free_d0(meter_t *mtr) {
meter_handle_d0_t *handle = &mtr->handle.d0;
if (handle->device != NULL) {
free(handle->device);
MeterD0::~MeterD0() {
if (device != NULL) {
free(device);
}
if (handle->host != NULL) {
free(handle->host);
if (host != NULL) {
free(host);
}
}
int meter_open_d0(meter_t *mtr) {
meter_handle_d0_t *handle = &mtr->handle.d0;
int MeterD0::open() {
if (handle->device != NULL) {
print(log_error, "TODO: implement serial interface", mtr);
return ERR;
@ -128,13 +120,11 @@ int meter_open_d0(meter_t *mtr) {
return (handle->fd < 0) ? ERR : SUCCESS;
}
int meter_close_d0(meter_t *mtr) {
meter_handle_d0_t *handle = &mtr->handle.d0;
int MeterD0::close() {
return close(handle->fd);
}
size_t meter_read_d0(meter_t *mtr, reading_t rds[], size_t max_readings) {
size_t MeterD0::read(reading_t rds[], size_t max_readings) {
meter_handle_d0_t *handle = &mtr->handle.d0;
enum { START, VENDOR, BAUDRATE, IDENTIFICATION, START_LINE, OBIS_CODE, VALUE, UNIT, END_LINE, END } context;
@ -280,7 +270,7 @@ error:
return 0;
}
int meter_d0_open_socket(const char *node, const char *service) {
int MeterD0::openSocket(const char *node, const char *service) {
struct sockaddr_in sin;
struct addrinfo *ais;
int fd; /* file descriptor */

View file

@ -1,133 +0,0 @@
/**
* Reading related functions
*
* @package vzlogger
* @copyright Copyright (c) 2011, The volkszaehler.org project
* @license http://www.gnu.org/licenses/gpl.txt GNU Public License
* @author Steffen Vogel <info@steffenvogel.de>
*/
/*
* This file is part of volkzaehler.org
*
* volkzaehler.org 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
* any later version.
*
* volkzaehler.org 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 volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <math.h>
#include "reading.h"
#include "meter.h"
int reading_id_compare(meter_protocol_t protocol, reading_id_t a, reading_id_t b) {
switch (protocol) {
case meter_protocol_d0:
case meter_protocol_sml:
return obis_compare(a.obis, b.obis);
case meter_protocol_fluksov2:
return !(a.channel == b.channel);
case meter_protocol_file:
case meter_protocol_exec:
return strcmp(a.string, b.string);
default:
/* no channel id, adding all readings to buffer */
return 0; /* equal */
}
}
int reading_id_parse(meter_protocol_t protocol, reading_id_t *id, const char *string) {
switch (protocol) {
case meter_protocol_d0:
case meter_protocol_sml:
if (obis_parse(string, &id->obis) != SUCCESS) {
if (obis_lookup_alias(string, &id->obis) != SUCCESS) {
return ERR;
}
}
break;
case meter_protocol_fluksov2: {
char type[13];
int channel;
int ret = sscanf(string, "sensor%u/%12s", &channel, type);
if (ret != 2) {
return ERR;
}
id->channel = channel + 1; /* increment by 1 to distinguish between +0 and -0 */
if (strcmp(type, "consumption") == 0) {
id->channel *= -1;
}
else if (strcmp(type, "power") != 0) {
return ERR;
}
break;
}
case meter_protocol_file:
case meter_protocol_exec:
id->string = strdup(string); // TODO free() elsewhere
break;
default: /* ignore other protocols which do not provide id's */
break;
}
return SUCCESS;
}
size_t reading_id_unparse(meter_protocol_t protocol, reading_id_t id, char *buffer, size_t n) {
switch (protocol) {
case meter_protocol_d0:
case meter_protocol_sml:
obis_unparse(id.obis, buffer, n);
break;
case meter_protocol_fluksov2:
snprintf(buffer, n, "sensor%u/%s", abs(id.channel) - 1, (id.channel > 0) ? "power" : "consumption");
break;
case meter_protocol_file:
case meter_protocol_exec:
if (id.string != NULL) {
strncpy(buffer, id.string, n);
break;
}
default:
buffer[0] = '\0';
}
return strlen(buffer);
}
double tvtod(struct timeval tv) {
return tv.tv_sec + tv.tv_usec / 1e6;
}
struct timeval dtotv(double ts) {
double integral;
double fraction = modf(ts, &integral);
struct timeval tv = {
.tv_usec = (long int) (fraction * 1e6),
.tv_sec = (long int) integral
};
return tv;
}

94
src/reading.cpp Normal file
View file

@ -0,0 +1,94 @@
/**
* Reading related functions
*
* @package vzlogger
* @copyright Copyright (c) 2011, The volkszaehler.org project
* @license http://www.gnu.org/licenses/gpl.txt GNU Public License
* @author Steffen Vogel <info@steffenvogel.de>
*/
/*
* This file is part of volkzaehler.org
*
* volkzaehler.org 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
* any later version.
*
* volkzaehler.org 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 volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "exception.h"
#include "reading.h"
/* StringIdentifier */
bool StringIdentifier::operator==(ReadingIdentifier &cmp) {
return (strcmp(string, cmp.string) == 0);
}
void StringIdentifier::parse(const char *string) {
string = strdup(string);
}
size_t StringIdentifier::unparse(char *buffer, size_t n) {
strncpy(buffer, string, n);
return strlen(buffer);
}
StringIdentifier::~StringIdentifier() {
free(string);
}
/* ChannelIdentifier */
bool ChannelIdentifier::operator==(ReadingIdentifier &cmp) {
return (channel == cmp.channel);
}
void ChannelIdentifier::parse(const char *string) {
char type[13];
int channel;
int ret = sscanf(string, "sensor%u/%12s", &channel, type);
if (ret != 2) {
throw new Exception("Failed to parse channel identifier");
}
id->channel = channel + 1; /* increment by 1 to distinguish between +0 and -0 */
if (strcmp(type, "consumption") == 0) {
id->channel *= -1;
}
else if (strcmp(type, "power") != 0) {
throw new Exception("Invalid channel type");
}
}
size_t ChannelIdentifier::unparse(char *buffer, size_t n) {
return snprintf(buffer, n, "sensor%u/%s", abs(id.channel) - 1, (id.channel > 0) ? "power" : "consumption");
}
/* Reading */
double Reading::tvtod(struct timeval tv) {
return tv.tv_sec + tv.tv_usec / 1e6;
}
struct timeval Reading::dtotv(double ts) {
double integral;
double fraction = modf(ts, &integral);
struct timeval tv;
tv.tv_usec = (long int) (fraction * 1e6);
tv.tv_sec = (long int) integral;
return tv;
}

61
src/test.cpp Normal file
View file

@ -0,0 +1,61 @@
// just for testing
#include <cstdio>
#include "list.h"
#include "buffer.h"
void test_list() {
List<int> li;
for (int i = 0; i < 10; i++) {
li.push(i);
}
for (List<int>::iterator it = li.begin(); it != li.end(); ++it) {
printf("%i\n", *it);
}
printf("popped %i\n", li.pop());
printf("popped %i\n", li.pop());
for (List<int>::iterator it = li.begin(); it != li.end(); ++it) {
printf("%i\n", *it);
}
}
void test_buffer() {
Buffer buf;
struct timeval tv;
StringIdentifier id;
gettimeofday(&tv, NULL);
for (int i = 0; i < 10; i++) {
Reading rd;
rd.value = 11*i;
rd.time = tv;
rd.identifier = &id;
buf.push(rd);
}
for (Buffer::iterator it = buf.begin(); it != buf.end(); ++it) {
printf("%i\n", it->value);
}
printf("popped %i\n", buf.pop().value);
printf("popped %i\n", buf.pop().value);
for (Buffer::iterator it = buf.begin(); it != buf.end(); ++it) {
printf("%i\n", it->value);
}
}
int main() {
test_buffer();
return 0;
}