just to much to describe it ;)
- added new structure - added SML support
This commit is contained in:
parent
47f5ee3e2d
commit
c217a9f1d7
51 changed files with 3854 additions and 1408 deletions
12
Makefile
12
Makefile
|
@ -36,7 +36,7 @@ subdir = .
|
|||
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
|
||||
$(srcdir)/Makefile.in $(srcdir)/config.h.in \
|
||||
$(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
|
||||
depcomp install-sh missing
|
||||
compile depcomp install-sh missing
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
|
@ -137,10 +137,12 @@ CPPFLAGS =
|
|||
CYGPATH_W = echo
|
||||
DEFS = -DHAVE_CONFIG_H
|
||||
DEPDIR = .deps
|
||||
DEPS_CFLAGS = -I/usr/include/json
|
||||
DEPS_LIBS = -ljson -lcurl
|
||||
DEPS_LOCAL_CFLAGS =
|
||||
DEPS_LOCAL_LIBS =
|
||||
DEPS_SML_CFLAGS = -I/usr/include/sml -I/usr/include/uuid
|
||||
DEPS_SML_LIBS = -lsml -luuid
|
||||
DEPS_VZ_CFLAGS = -I/usr/include/json
|
||||
DEPS_VZ_LIBS = -ljson -lcurl
|
||||
ECHO_C =
|
||||
ECHO_N = -n
|
||||
ECHO_T =
|
||||
|
@ -170,6 +172,7 @@ PATH_SEPARATOR = :
|
|||
PKG_CONFIG = /usr/bin/pkg-config
|
||||
PKG_CONFIG_LIBDIR =
|
||||
PKG_CONFIG_PATH =
|
||||
RANLIB = ranlib
|
||||
SET_MAKE =
|
||||
SHELL = /bin/bash
|
||||
STRIP =
|
||||
|
@ -217,7 +220,7 @@ top_build_prefix =
|
|||
top_builddir = .
|
||||
top_srcdir = .
|
||||
sysconf_DATA = etc/vzlogger.conf
|
||||
SUBDIRS = src docs
|
||||
SUBDIRS = src bin/vzlogger
|
||||
all: config.h
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-recursive
|
||||
|
||||
|
@ -725,6 +728,7 @@ uninstall-am: uninstall-sysconfDATA
|
|||
mostlyclean-generic pdf pdf-am ps ps-am tags tags-recursive \
|
||||
uninstall uninstall-am uninstall-sysconfDATA
|
||||
|
||||
# bin/reader docs
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
sysconf_DATA = etc/vzlogger.conf
|
||||
|
||||
SUBDIRS = src docs
|
||||
SUBDIRS = src bin/vzlogger
|
||||
# bin/reader docs
|
||||
|
|
484
bin/reader/Makefile
Normal file
484
bin/reader/Makefile
Normal file
|
@ -0,0 +1,484 @@
|
|||
# Makefile.in generated by automake 1.11.1 from Makefile.am.
|
||||
# bin/reader/Makefile. Generated from Makefile.in by configure.
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
|
||||
# Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
|
||||
|
||||
pkgdatadir = $(datadir)/vzlogger
|
||||
pkgincludedir = $(includedir)/vzlogger
|
||||
pkglibdir = $(libdir)/vzlogger
|
||||
pkglibexecdir = $(libexecdir)/vzlogger
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
bin_PROGRAMS = smlreader$(EXEEXT)
|
||||
subdir = bin/reader
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am__smlreader_SOURCES_DIST = smlreader.c
|
||||
am_smlreader_OBJECTS = \
|
||||
smlreader-smlreader.$(OBJEXT)
|
||||
smlreader_OBJECTS = $(am_smlreader_OBJECTS)
|
||||
am__DEPENDENCIES_1 =
|
||||
smlreader_DEPENDENCIES = $(am__DEPENDENCIES_1)
|
||||
smlreader_LINK = $(CCLD) $(smlreader_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
|
||||
$(LDFLAGS) -o $@
|
||||
DEFAULT_INCLUDES = -I. -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 $@
|
||||
SOURCES = $(smlreader_SOURCES)
|
||||
DIST_SOURCES = $(am__smlreader_SOURCES_DIST)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = ${SHELL} /home/stv0g/workspace/volkszaehler.org/vzlogger/missing --run aclocal-1.11
|
||||
AMTAR = ${SHELL} /home/stv0g/workspace/volkszaehler.org/vzlogger/missing --run tar
|
||||
AUTOCONF = ${SHELL} /home/stv0g/workspace/volkszaehler.org/vzlogger/missing --run autoconf
|
||||
AUTOHEADER = ${SHELL} /home/stv0g/workspace/volkszaehler.org/vzlogger/missing --run autoheader
|
||||
AUTOMAKE = ${SHELL} /home/stv0g/workspace/volkszaehler.org/vzlogger/missing --run automake-1.11
|
||||
AWK = gawk
|
||||
CC = gcc
|
||||
CCDEPMODE = depmode=gcc3
|
||||
CFLAGS = -g -O2
|
||||
CPP = gcc -E
|
||||
CPPFLAGS =
|
||||
CYGPATH_W = echo
|
||||
DEFS = -DHAVE_CONFIG_H
|
||||
DEPDIR = .deps
|
||||
DEPS_LOCAL_CFLAGS =
|
||||
DEPS_LOCAL_LIBS =
|
||||
DEPS_SML_CFLAGS = -I/usr/include/sml -I/usr/include/uuid
|
||||
DEPS_SML_LIBS = -lsml -luuid
|
||||
DEPS_VZ_CFLAGS = -I/usr/include/json
|
||||
DEPS_VZ_LIBS = -ljson -lcurl
|
||||
ECHO_C =
|
||||
ECHO_N = -n
|
||||
ECHO_T =
|
||||
EGREP = /bin/grep -E
|
||||
EXEEXT =
|
||||
GREP = /bin/grep
|
||||
INSTALL = /usr/bin/install -c
|
||||
INSTALL_DATA = ${INSTALL} -m 644
|
||||
INSTALL_PROGRAM = ${INSTALL}
|
||||
INSTALL_SCRIPT = ${INSTALL}
|
||||
INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
|
||||
LDFLAGS =
|
||||
LIBOBJS =
|
||||
LIBS =
|
||||
LTLIBOBJS =
|
||||
MAKEINFO = ${SHELL} /home/stv0g/workspace/volkszaehler.org/vzlogger/missing --run makeinfo
|
||||
MKDIR_P = /bin/mkdir -p
|
||||
OBJEXT = o
|
||||
PACKAGE = vzlogger
|
||||
PACKAGE_BUGREPORT = http://bugs.volkszaehler.org
|
||||
PACKAGE_NAME = vzlogger
|
||||
PACKAGE_STRING = vzlogger 0.2
|
||||
PACKAGE_TARNAME = vzlogger
|
||||
PACKAGE_URL =
|
||||
PACKAGE_VERSION = 0.2
|
||||
PATH_SEPARATOR = :
|
||||
PKG_CONFIG = /usr/bin/pkg-config
|
||||
PKG_CONFIG_LIBDIR =
|
||||
PKG_CONFIG_PATH =
|
||||
RANLIB = ranlib
|
||||
SET_MAKE =
|
||||
SHELL = /bin/bash
|
||||
STRIP =
|
||||
VERSION = 0.2
|
||||
abs_builddir = /home/stv0g/workspace/volkszaehler.org/vzlogger/bin/reader
|
||||
abs_srcdir = /home/stv0g/workspace/volkszaehler.org/vzlogger/bin/reader
|
||||
abs_top_builddir = /home/stv0g/workspace/volkszaehler.org/vzlogger
|
||||
abs_top_srcdir = /home/stv0g/workspace/volkszaehler.org/vzlogger
|
||||
ac_ct_CC = gcc
|
||||
am__include = include
|
||||
am__leading_dot = .
|
||||
am__quote =
|
||||
am__tar = ${AMTAR} chof - "$$tardir"
|
||||
am__untar = ${AMTAR} xf -
|
||||
bindir = ${exec_prefix}/bin
|
||||
build_alias =
|
||||
builddir = .
|
||||
datadir = ${datarootdir}
|
||||
datarootdir = ${prefix}/share
|
||||
docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
|
||||
dvidir = ${docdir}
|
||||
exec_prefix = ${prefix}
|
||||
host_alias =
|
||||
htmldir = ${docdir}
|
||||
includedir = ${prefix}/include
|
||||
infodir = ${datarootdir}/info
|
||||
install_sh = ${SHELL} /home/stv0g/workspace/volkszaehler.org/vzlogger/install-sh
|
||||
libdir = ${exec_prefix}/lib
|
||||
libexecdir = ${exec_prefix}/libexec
|
||||
localedir = ${datarootdir}/locale
|
||||
localstatedir = ${prefix}/var
|
||||
mandir = ${datarootdir}/man
|
||||
mkdir_p = /bin/mkdir -p
|
||||
oldincludedir = /usr/include
|
||||
pdfdir = ${docdir}
|
||||
prefix = /usr/local
|
||||
program_transform_name = s,x,x,
|
||||
psdir = ${docdir}
|
||||
sbindir = ${exec_prefix}/sbin
|
||||
sharedstatedir = ${prefix}/com
|
||||
srcdir = .
|
||||
sysconfdir = ${prefix}/etc
|
||||
target_alias =
|
||||
top_build_prefix = ../../
|
||||
top_builddir = ../..
|
||||
top_srcdir = ../..
|
||||
|
||||
# what flags you want to pass to the C compiler & linker
|
||||
AM_CFLAGS = -Wall -D_REENTRANT -std=gnu99 $(DEPS_CFLAGS)
|
||||
AM_LDFLAGS =
|
||||
smlreader_SOURCES = smlreader.c
|
||||
smlreader_LDADD = -lm $(DEPS_SML_LIBS)
|
||||
smlreader_CFLAGS = $(AM_CFLAGS) $(DEPS_SML_CFLAGS)
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu bin/reader/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu bin/reader/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed 's/$(EXEEXT)$$//' | \
|
||||
while read p p1; do if test -f $$p; \
|
||||
then echo "$$p"; echo "$$p"; else :; fi; \
|
||||
done | \
|
||||
sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
|
||||
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
|
||||
sed 'N;N;N;s,\n, ,g' | \
|
||||
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
|
||||
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
|
||||
if ($$2 == $$4) files[d] = files[d] " " $$1; \
|
||||
else { print "f", $$3 "/" $$4, $$1; } } \
|
||||
END { for (d in files) print "f", d, files[d] }' | \
|
||||
while read type dir files; do \
|
||||
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
|
||||
test -z "$$files" || { \
|
||||
echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
|
||||
$(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
|
||||
} \
|
||||
; done
|
||||
|
||||
uninstall-binPROGRAMS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
files=`for p in $$list; do echo "$$p"; done | \
|
||||
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
|
||||
-e 's/$$/$(EXEEXT)/' `; \
|
||||
test -n "$$list" || exit 0; \
|
||||
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
|
||||
cd "$(DESTDIR)$(bindir)" && rm -f $$files
|
||||
|
||||
clean-binPROGRAMS:
|
||||
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
|
||||
smlreader$(EXEEXT): $(smlreader_OBJECTS) $(smlreader_DEPENDENCIES)
|
||||
@rm -f smlreader$(EXEEXT)
|
||||
$(smlreader_LINK) $(smlreader_OBJECTS) $(smlreader_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
include ./$(DEPDIR)/smlreader-smlreader.Po
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
# source='$<' object='$@' libtool=no \
|
||||
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
|
||||
# $(COMPILE) -c $<
|
||||
|
||||
.c.obj:
|
||||
$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
# source='$<' object='$@' libtool=no \
|
||||
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
|
||||
# $(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
smlreader-smlreader.o: smlreader.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(smlreader_CFLAGS) $(CFLAGS) -MT smlreader-smlreader.o -MD -MP -MF $(DEPDIR)/smlreader-smlreader.Tpo -c -o smlreader-smlreader.o `test -f 'smlreader.c' || echo '$(srcdir)/'`smlreader.c
|
||||
$(am__mv) $(DEPDIR)/smlreader-smlreader.Tpo $(DEPDIR)/smlreader-smlreader.Po
|
||||
# source='smlreader.c' object='smlreader-smlreader.o' libtool=no \
|
||||
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
|
||||
# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(smlreader_CFLAGS) $(CFLAGS) -c -o smlreader-smlreader.o `test -f 'smlreader.c' || echo '$(srcdir)/'`smlreader.c
|
||||
|
||||
smlreader-smlreader.obj: smlreader.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(smlreader_CFLAGS) $(CFLAGS) -MT smlreader-smlreader.obj -MD -MP -MF $(DEPDIR)/smlreader-smlreader.Tpo -c -o smlreader-smlreader.obj `if test -f 'smlreader.c'; then $(CYGPATH_W) 'smlreader.c'; else $(CYGPATH_W) '$(srcdir)/smlreader.c'; fi`
|
||||
$(am__mv) $(DEPDIR)/smlreader-smlreader.Tpo $(DEPDIR)/smlreader-smlreader.Po
|
||||
# source='smlreader.c' object='smlreader-smlreader.obj' libtool=no \
|
||||
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
|
||||
# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(smlreader_CFLAGS) $(CFLAGS) -c -o smlreader-smlreader.obj `if test -f 'smlreader.c'; then $(CYGPATH_W) 'smlreader.c'; else $(CYGPATH_W) '$(srcdir)/smlreader.c'; fi`
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(PROGRAMS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(bindir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am: install-binPROGRAMS
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-binPROGRAMS
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
|
||||
clean-generic ctags distclean distclean-compile \
|
||||
distclean-generic distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-binPROGRAMS \
|
||||
install-data install-data-am install-dvi install-dvi-am \
|
||||
install-exec install-exec-am install-html install-html-am \
|
||||
install-info install-info-am install-man install-pdf \
|
||||
install-pdf-am install-ps install-ps-am install-strip \
|
||||
installcheck installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
|
||||
uninstall-am uninstall-binPROGRAMS
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
13
bin/reader/Makefile.am
Normal file
13
bin/reader/Makefile.am
Normal file
|
@ -0,0 +1,13 @@
|
|||
# what flags you want to pass to the C compiler & linker
|
||||
AM_CFLAGS = -Wall -D_REENTRANT -std=gnu99 $(DEPS_CFLAGS)
|
||||
AM_LDFLAGS =
|
||||
|
||||
# SML
|
||||
####################################################################
|
||||
if SML_SUPPORT
|
||||
bin_PROGRAMS = smlreader
|
||||
smlreader_SOURCES = smlreader.c
|
||||
smlreader_LDADD = -lm $(DEPS_SML_LIBS)
|
||||
smlreader_CFLAGS = $(AM_CFLAGS) $(DEPS_SML_CFLAGS)
|
||||
endif
|
||||
|
153
bin/reader/smlreader.c
Normal file
153
bin/reader/smlreader.c
Normal file
|
@ -0,0 +1,153 @@
|
|||
/**
|
||||
* SML protocol parsing
|
||||
*
|
||||
* @package vzlogger
|
||||
* @copyright Copyright (c) 2011, The volkszaehler.org project
|
||||
* @copyright Copyright (c) 2011, Juri Glass, Mathias Runge, Nadim El Sayed, DAI-Labor, TU-Berlin
|
||||
* @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 <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include <sml/sml_file.h>
|
||||
#include <sml/sml_transport.h>
|
||||
|
||||
#include "obis.h"
|
||||
#include "unit.h"
|
||||
|
||||
obis_id_t filter;
|
||||
|
||||
void transport_receiver(unsigned char *buffer, size_t buffer_len) {
|
||||
/* strip escape sequences */
|
||||
sml_file *file = sml_file_parse(buffer + 8, buffer_len - 16);
|
||||
|
||||
for (int i = 0; i < file->messages_len; i++) {
|
||||
sml_message *message = file->messages[i];
|
||||
|
||||
if (*message->message_body->tag == SML_MESSAGE_GET_LIST_RESPONSE) {
|
||||
sml_list *entry;
|
||||
sml_get_list_response *body;
|
||||
|
||||
body = (sml_get_list_response *) message->message_body->data;
|
||||
|
||||
printf("new message from: %*s\n", body->server_id->len, body->server_id->str);
|
||||
|
||||
for (entry = body->val_list; entry != NULL; entry = entry->next) { /* linked list */
|
||||
obis_id_t id = obis_init(entry->obj_name->str);
|
||||
|
||||
if (memcmp(&id, &filter, sizeof(obis_id_t)) == 0) {
|
||||
struct timeval time;
|
||||
int unit = (entry->unit) ? *entry->unit : 0;
|
||||
int scaler = (entry->scaler) ? *entry->scaler : 1;
|
||||
double value;
|
||||
|
||||
switch (entry->value->type) {
|
||||
case 0x51: value = *entry->value->data.int8; break;
|
||||
case 0x52: value = *entry->value->data.int16; break;
|
||||
case 0x54: value = *entry->value->data.int32; break;
|
||||
case 0x58: value = *entry->value->data.int64; break;
|
||||
case 0x61: value = *entry->value->data.uint8; break;
|
||||
case 0x62: value = *entry->value->data.uint16; break;
|
||||
case 0x64: value = *entry->value->data.uint32; break;
|
||||
case 0x68: value = *entry->value->data.uint64; break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unknown value type: %x", type);
|
||||
value = 0;
|
||||
}
|
||||
|
||||
/* apply scaler */
|
||||
value *= pow(10, scaler);
|
||||
|
||||
|
||||
/* get time */
|
||||
if (entry->val_time) { // TODO handle SML_TIME_SEC_INDEX
|
||||
time.tv_sec = *entry->val_time->data.timestamp;
|
||||
time.tv_usec = 0;
|
||||
}
|
||||
else {
|
||||
gettimeofday(&time, NULL);
|
||||
}
|
||||
|
||||
printf("%lu.%lu\t%.2f %s\n", time.tv_sec, time.tv_usec, value, dlms_get_unit(unit));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// free the malloc'd memory
|
||||
sml_file_free(file);
|
||||
}
|
||||
|
||||
int open_socket(char *host, char *port) {
|
||||
struct sockaddr_in sin;
|
||||
struct addrinfo *ais;
|
||||
int fd;
|
||||
|
||||
getaddrinfo(host, port, NULL, &ais);
|
||||
memcpy(&sin, ais->ai_addr, ais->ai_addrlen);
|
||||
|
||||
printf("Opening socket\n");
|
||||
fd = socket(PF_INET, SOCK_STREAM, 0);
|
||||
|
||||
printf("Conntecting to %s:%s\n", host, port);
|
||||
if (connect(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
|
||||
perror(host);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char *host, *port, *obis;
|
||||
char buffer[16];
|
||||
int fd;
|
||||
|
||||
host = (argc >= 2) ? argv[1] : "localhost";
|
||||
port = (argc >= 3) ? argv[2] : "7331";
|
||||
obis = (argc >= 4) ? argv[3] : "1-0:1.7.0"; /* total power */
|
||||
|
||||
filter = obis_parse(obis);
|
||||
|
||||
obis_unparse(filter, buffer);
|
||||
printf("Using OBIS Id: %s\n", buffer);
|
||||
|
||||
fd = open_socket(host, port);
|
||||
|
||||
if (fd > 0) {
|
||||
sml_transport_listen(fd, &transport_receiver);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
494
bin/vzlogger/Makefile
Normal file
494
bin/vzlogger/Makefile
Normal file
|
@ -0,0 +1,494 @@
|
|||
# Makefile.in generated by automake 1.11.1 from Makefile.am.
|
||||
# bin/vzlogger/Makefile. Generated from Makefile.in by configure.
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
|
||||
# Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
|
||||
|
||||
pkgdatadir = $(datadir)/vzlogger
|
||||
pkgincludedir = $(includedir)/vzlogger
|
||||
pkglibdir = $(libdir)/vzlogger
|
||||
pkglibexecdir = $(libexecdir)/vzlogger
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
bin_PROGRAMS = vzlogger$(EXEEXT)
|
||||
|
||||
# local interface support
|
||||
####################################################################
|
||||
#am__append_1 = local.c
|
||||
#am__append_2 = $(DEPS_LOCAL_LIBS)
|
||||
#am__append_3 = $(DEPS_LOCAL_CFLAGS)
|
||||
|
||||
# sml support
|
||||
####################################################################
|
||||
am__append_4 = $(DEPS_SML_LIBS)
|
||||
am__append_5 = $(DEPS_SML_CFLAGS)
|
||||
subdir = bin/vzlogger
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am__vzlogger_SOURCES_DIST = vzlogger.c channel.c api.c options.c \
|
||||
list.c buffer.c local.c
|
||||
#am__objects_1 = local.$(OBJEXT)
|
||||
am_vzlogger_OBJECTS = vzlogger.$(OBJEXT) channel.$(OBJEXT) \
|
||||
api.$(OBJEXT) options.$(OBJEXT) list.$(OBJEXT) \
|
||||
buffer.$(OBJEXT) $(am__objects_1)
|
||||
vzlogger_OBJECTS = $(am_vzlogger_OBJECTS)
|
||||
am__DEPENDENCIES_1 =
|
||||
#am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
|
||||
am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
|
||||
vzlogger_DEPENDENCIES = ../../src/libmeter.a ../../src/libobis.a \
|
||||
$(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3)
|
||||
vzlogger_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(vzlogger_LDFLAGS) \
|
||||
$(LDFLAGS) -o $@
|
||||
DEFAULT_INCLUDES = -I. -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 $@
|
||||
SOURCES = $(vzlogger_SOURCES)
|
||||
DIST_SOURCES = $(am__vzlogger_SOURCES_DIST)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = ${SHELL} /home/stv0g/workspace/volkszaehler.org/vzlogger/missing --run aclocal-1.11
|
||||
AMTAR = ${SHELL} /home/stv0g/workspace/volkszaehler.org/vzlogger/missing --run tar
|
||||
AUTOCONF = ${SHELL} /home/stv0g/workspace/volkszaehler.org/vzlogger/missing --run autoconf
|
||||
AUTOHEADER = ${SHELL} /home/stv0g/workspace/volkszaehler.org/vzlogger/missing --run autoheader
|
||||
AUTOMAKE = ${SHELL} /home/stv0g/workspace/volkszaehler.org/vzlogger/missing --run automake-1.11
|
||||
AWK = gawk
|
||||
CC = gcc
|
||||
CCDEPMODE = depmode=gcc3
|
||||
CFLAGS = -g -O2
|
||||
CPP = gcc -E
|
||||
CPPFLAGS =
|
||||
CYGPATH_W = echo
|
||||
DEFS = -DHAVE_CONFIG_H
|
||||
DEPDIR = .deps
|
||||
DEPS_LOCAL_CFLAGS =
|
||||
DEPS_LOCAL_LIBS =
|
||||
DEPS_SML_CFLAGS = -I/usr/include/sml -I/usr/include/uuid
|
||||
DEPS_SML_LIBS = -lsml -luuid
|
||||
DEPS_VZ_CFLAGS = -I/usr/include/json
|
||||
DEPS_VZ_LIBS = -ljson -lcurl
|
||||
ECHO_C =
|
||||
ECHO_N = -n
|
||||
ECHO_T =
|
||||
EGREP = /bin/grep -E
|
||||
EXEEXT =
|
||||
GREP = /bin/grep
|
||||
INSTALL = /usr/bin/install -c
|
||||
INSTALL_DATA = ${INSTALL} -m 644
|
||||
INSTALL_PROGRAM = ${INSTALL}
|
||||
INSTALL_SCRIPT = ${INSTALL}
|
||||
INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
|
||||
LDFLAGS =
|
||||
LIBOBJS =
|
||||
LIBS =
|
||||
LTLIBOBJS =
|
||||
MAKEINFO = ${SHELL} /home/stv0g/workspace/volkszaehler.org/vzlogger/missing --run makeinfo
|
||||
MKDIR_P = /bin/mkdir -p
|
||||
OBJEXT = o
|
||||
PACKAGE = vzlogger
|
||||
PACKAGE_BUGREPORT = http://bugs.volkszaehler.org
|
||||
PACKAGE_NAME = vzlogger
|
||||
PACKAGE_STRING = vzlogger 0.2
|
||||
PACKAGE_TARNAME = vzlogger
|
||||
PACKAGE_URL =
|
||||
PACKAGE_VERSION = 0.2
|
||||
PATH_SEPARATOR = :
|
||||
PKG_CONFIG = /usr/bin/pkg-config
|
||||
PKG_CONFIG_LIBDIR =
|
||||
PKG_CONFIG_PATH =
|
||||
RANLIB = ranlib
|
||||
SET_MAKE =
|
||||
SHELL = /bin/bash
|
||||
STRIP =
|
||||
VERSION = 0.2
|
||||
abs_builddir = /home/stv0g/workspace/volkszaehler.org/vzlogger/bin/vzlogger
|
||||
abs_srcdir = /home/stv0g/workspace/volkszaehler.org/vzlogger/bin/vzlogger
|
||||
abs_top_builddir = /home/stv0g/workspace/volkszaehler.org/vzlogger
|
||||
abs_top_srcdir = /home/stv0g/workspace/volkszaehler.org/vzlogger
|
||||
ac_ct_CC = gcc
|
||||
am__include = include
|
||||
am__leading_dot = .
|
||||
am__quote =
|
||||
am__tar = ${AMTAR} chof - "$$tardir"
|
||||
am__untar = ${AMTAR} xf -
|
||||
bindir = ${exec_prefix}/bin
|
||||
build_alias =
|
||||
builddir = .
|
||||
datadir = ${datarootdir}
|
||||
datarootdir = ${prefix}/share
|
||||
docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
|
||||
dvidir = ${docdir}
|
||||
exec_prefix = ${prefix}
|
||||
host_alias =
|
||||
htmldir = ${docdir}
|
||||
includedir = ${prefix}/include
|
||||
infodir = ${datarootdir}/info
|
||||
install_sh = ${SHELL} /home/stv0g/workspace/volkszaehler.org/vzlogger/install-sh
|
||||
libdir = ${exec_prefix}/lib
|
||||
libexecdir = ${exec_prefix}/libexec
|
||||
localedir = ${datarootdir}/locale
|
||||
localstatedir = ${prefix}/var
|
||||
mandir = ${datarootdir}/man
|
||||
mkdir_p = /bin/mkdir -p
|
||||
oldincludedir = /usr/include
|
||||
pdfdir = ${docdir}
|
||||
prefix = /usr/local
|
||||
program_transform_name = s,x,x,
|
||||
psdir = ${docdir}
|
||||
sbindir = ${exec_prefix}/sbin
|
||||
sharedstatedir = ${prefix}/com
|
||||
srcdir = .
|
||||
sysconfdir = ${prefix}/etc
|
||||
target_alias =
|
||||
top_build_prefix = ../../
|
||||
top_builddir = ../..
|
||||
top_srcdir = ../..
|
||||
AM_CFLAGS = -Wall -D_REENTRANT -std=gnu99 $(DEPS_VZ_CFLAGS) \
|
||||
$(am__append_3) $(am__append_5)
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
vzlogger_SOURCES = vzlogger.c channel.c api.c options.c list.c \
|
||||
buffer.c $(am__append_1)
|
||||
vzlogger_LDADD = ../../src/libmeter.a ../../src/libobis.a \
|
||||
$(am__append_2) $(am__append_4)
|
||||
vzlogger_LDFLAGS = -lpthread -lm $(DEPS_VZ_LIBS)
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu bin/vzlogger/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu bin/vzlogger/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed 's/$(EXEEXT)$$//' | \
|
||||
while read p p1; do if test -f $$p; \
|
||||
then echo "$$p"; echo "$$p"; else :; fi; \
|
||||
done | \
|
||||
sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
|
||||
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
|
||||
sed 'N;N;N;s,\n, ,g' | \
|
||||
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
|
||||
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
|
||||
if ($$2 == $$4) files[d] = files[d] " " $$1; \
|
||||
else { print "f", $$3 "/" $$4, $$1; } } \
|
||||
END { for (d in files) print "f", d, files[d] }' | \
|
||||
while read type dir files; do \
|
||||
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
|
||||
test -z "$$files" || { \
|
||||
echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
|
||||
$(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
|
||||
} \
|
||||
; done
|
||||
|
||||
uninstall-binPROGRAMS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
files=`for p in $$list; do echo "$$p"; done | \
|
||||
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
|
||||
-e 's/$$/$(EXEEXT)/' `; \
|
||||
test -n "$$list" || exit 0; \
|
||||
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
|
||||
cd "$(DESTDIR)$(bindir)" && rm -f $$files
|
||||
|
||||
clean-binPROGRAMS:
|
||||
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
|
||||
vzlogger$(EXEEXT): $(vzlogger_OBJECTS) $(vzlogger_DEPENDENCIES)
|
||||
@rm -f vzlogger$(EXEEXT)
|
||||
$(vzlogger_LINK) $(vzlogger_OBJECTS) $(vzlogger_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
include ./$(DEPDIR)/api.Po
|
||||
include ./$(DEPDIR)/buffer.Po
|
||||
include ./$(DEPDIR)/channel.Po
|
||||
include ./$(DEPDIR)/list.Po
|
||||
include ./$(DEPDIR)/local.Po
|
||||
include ./$(DEPDIR)/options.Po
|
||||
include ./$(DEPDIR)/vzlogger.Po
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
# source='$<' object='$@' libtool=no \
|
||||
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
|
||||
# $(COMPILE) -c $<
|
||||
|
||||
.c.obj:
|
||||
$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
# source='$<' object='$@' libtool=no \
|
||||
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
|
||||
# $(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(PROGRAMS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(bindir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am: install-binPROGRAMS
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-binPROGRAMS
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
|
||||
clean-generic ctags distclean distclean-compile \
|
||||
distclean-generic distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-binPROGRAMS \
|
||||
install-data install-data-am install-dvi install-dvi-am \
|
||||
install-exec install-exec-am install-html install-html-am \
|
||||
install-info install-info-am install-man install-pdf \
|
||||
install-pdf-am install-ps install-ps-am install-strip \
|
||||
installcheck installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
|
||||
uninstall-am uninstall-binPROGRAMS
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
22
bin/vzlogger/Makefile.am
Normal file
22
bin/vzlogger/Makefile.am
Normal file
|
@ -0,0 +1,22 @@
|
|||
AM_CFLAGS = -Wall -D_REENTRANT -std=gnu99 $(DEPS_VZ_CFLAGS)
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
|
||||
bin_PROGRAMS = vzlogger
|
||||
vzlogger_SOURCES = vzlogger.c channel.c api.c options.c list.c buffer.c
|
||||
vzlogger_LDADD = ../../src/libmeter.a ../../src/libobis.a
|
||||
vzlogger_LDFLAGS = -lpthread -lm $(DEPS_VZ_LIBS)
|
||||
|
||||
# local interface support
|
||||
####################################################################
|
||||
if LOCAL_SUPPORT
|
||||
vzlogger_SOURCES += local.c
|
||||
vzlogger_LDADD += $(DEPS_LOCAL_LIBS)
|
||||
AM_CFLAGS += $(DEPS_LOCAL_CFLAGS)
|
||||
endif
|
||||
|
||||
# sml support
|
||||
####################################################################
|
||||
if SML_SUPPORT
|
||||
vzlogger_LDADD += $(DEPS_SML_LIBS)
|
||||
AM_CFLAGS += $(DEPS_SML_CFLAGS)
|
||||
endif
|
|
@ -27,16 +27,21 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <reading.h>
|
||||
|
||||
#include "api.h"
|
||||
#include "main.h"
|
||||
#include "vzlogger.h"
|
||||
#include "options.h"
|
||||
|
||||
extern options_t opts;
|
||||
|
||||
/**
|
||||
* Reformat CURLs debugging output
|
||||
*/
|
||||
int curl_custom_debug_callback(CURL *curl, curl_infotype type, char *data, size_t size, void *ch) {
|
||||
int curl_custom_debug_callback(CURL *curl, curl_infotype type, char *data, size_t size, void *arg) {
|
||||
channel_t *ch = (channel_t *) ch;
|
||||
char *end = strchr(data, '\n');
|
||||
|
||||
if (data == end) return 0; /* skip empty line */
|
||||
|
@ -45,17 +50,17 @@ int curl_custom_debug_callback(CURL *curl, curl_infotype type, char *data, size_
|
|||
case CURLINFO_TEXT:
|
||||
case CURLINFO_END:
|
||||
if (end) *end = '\0'; /* terminate without \n */
|
||||
print(3, "CURL: %.*s", (channel_t *) ch, (int) size, data);
|
||||
print(7, "CURL: %.*s", ch, (int) size, data);
|
||||
break;
|
||||
|
||||
case CURLINFO_SSL_DATA_IN:
|
||||
case CURLINFO_DATA_IN:
|
||||
print(6, "CURL: Received %lu bytes", (channel_t *) ch, (unsigned long) size);
|
||||
print(9, "CURL: Received %lu bytes", ch, (unsigned long) size);
|
||||
break;
|
||||
|
||||
case CURLINFO_SSL_DATA_OUT:
|
||||
case CURLINFO_DATA_OUT:
|
||||
print(6, "CURL: Sent %lu bytes.. ", (channel_t *) ch, (unsigned long) size);
|
||||
print(9, "CURL: Sent %lu bytes.. ", ch, (unsigned long) size);
|
||||
break;
|
||||
|
||||
case CURLINFO_HEADER_IN:
|
||||
|
@ -83,33 +88,32 @@ size_t curl_custom_write_callback(void *ptr, size_t size, size_t nmemb, void *da
|
|||
return realsize;
|
||||
}
|
||||
|
||||
json_object * api_json_tuples(channel_t *ch, bool_t all) {
|
||||
reading_t rd;
|
||||
double api_tvtof(struct timeval tv) {
|
||||
return round(tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create JSON object of tuples
|
||||
*
|
||||
* @param buf the buffer our readings are stored in (required for mutex)
|
||||
* @param start the first tuple of our linked list which should be encoded
|
||||
*/
|
||||
json_object * api_json_tuples(buffer_t *buf, meter_reading_t *start) {
|
||||
json_object *json_tuples = json_object_new_array();
|
||||
|
||||
size_t index = ch->queue.read_p;
|
||||
size_t end = (all) ? ch->queue.read_p : ch->queue.write_p;
|
||||
do {
|
||||
pthread_mutex_lock(&ch->mutex);
|
||||
queue_get(&ch->queue, index, &rd);
|
||||
pthread_mutex_unlock(&ch->mutex);
|
||||
for (meter_reading_t *rd = start; rd != NULL; rd = rd->next) {
|
||||
struct json_object *json_tuple = json_object_new_array();
|
||||
|
||||
if (rd.tv.tv_sec) { /* skip empty buffers */
|
||||
struct json_object *json_tuple = json_object_new_array();
|
||||
pthread_mutex_lock(&buf->mutex);
|
||||
double timestamp = api_tvtof(rd->tv); // TODO use long int of new json-c version
|
||||
double value = rd->value;
|
||||
pthread_mutex_unlock(&buf->mutex);
|
||||
|
||||
double timestamp = rd.tv.tv_sec * 1000.0 + rd.tv.tv_usec / 1000.0;
|
||||
json_object_array_add(json_tuple, json_object_new_double(timestamp));
|
||||
json_object_array_add(json_tuple, json_object_new_double(value));
|
||||
|
||||
json_object_array_add(json_tuple, json_object_new_double(timestamp));
|
||||
json_object_array_add(json_tuple, json_object_new_double(rd.value));
|
||||
|
||||
json_object_array_add(json_tuples, json_tuple);
|
||||
}
|
||||
|
||||
index++;
|
||||
index %= ch->queue.size; /* increment pointer */
|
||||
|
||||
} while (index != end);
|
||||
json_object_array_add(json_tuples, json_tuple);
|
||||
}
|
||||
|
||||
return json_tuples;
|
||||
}
|
||||
|
@ -119,7 +123,7 @@ CURL * api_curl_init(channel_t *ch) {
|
|||
struct curl_slist *header = NULL;
|
||||
char url[255], agent[255];
|
||||
|
||||
/* prepare header & url */
|
||||
/* prepare header, uuid & url */
|
||||
sprintf(agent, "User-Agent: %s/%s (%s)", PACKAGE, VERSION, curl_version()); /* build user agent */
|
||||
sprintf(url, "%s/data/%s.json", ch->middleware, ch->uuid); /* build url */
|
||||
|
||||
|
@ -152,7 +156,7 @@ void api_parse_exception(CURLresponse response, char *err) {
|
|||
json_obj = json_object_object_get(json_obj, "exception");
|
||||
|
||||
if (json_obj) {
|
||||
sprintf(err, "[%s] %s",
|
||||
sprintf(err, "%s: %s",
|
||||
json_object_get_string(json_object_object_get(json_obj, "type")),
|
||||
json_object_get_string(json_object_object_get(json_obj, "message"))
|
||||
);
|
||||
|
@ -179,30 +183,28 @@ void * api_thread(void *arg) {
|
|||
CURL *curl;
|
||||
channel_t *ch = (channel_t *) arg; /* casting argument */
|
||||
|
||||
print(1, "Started logging thread", ch);
|
||||
|
||||
curl = api_curl_init(ch);
|
||||
|
||||
do { /* start thread mainloop */
|
||||
while (TRUE) { /* start thread mainloop */
|
||||
CURLresponse response;
|
||||
json_object *json_obj;
|
||||
char *json_str;
|
||||
const char *json_str;
|
||||
long int http_code, curl_code;
|
||||
|
||||
/* initialize response */
|
||||
response.data = NULL;
|
||||
response.size = 0;
|
||||
|
||||
pthread_mutex_lock(&ch->mutex);
|
||||
while (queue_is_empty(&ch->queue)) { /* detect spurious wakeups */
|
||||
pthread_cond_wait(&ch->condition, &ch->mutex); /* sleep until new data has been read */
|
||||
pthread_mutex_lock(&ch->buffer.mutex);
|
||||
while (ch->buffer.sent == NULL) { /* detect spurious wakeups */
|
||||
pthread_cond_wait(&ch->condition, &ch->buffer.mutex); /* sleep until new data has been read */
|
||||
}
|
||||
pthread_mutex_unlock(&ch->mutex);
|
||||
pthread_mutex_unlock(&ch->buffer.mutex);
|
||||
|
||||
json_obj = api_json_tuples(ch, FALSE);
|
||||
json_obj = api_json_tuples(&ch->buffer, ch->buffer.sent);
|
||||
json_str = json_object_to_json_string(json_obj);
|
||||
|
||||
print(8, "JSON request body: %s", ch, json_str);
|
||||
print(10, "JSON request body: %s", ch, json_str);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_str);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_custom_write_callback);
|
||||
|
@ -211,9 +213,10 @@ void * api_thread(void *arg) {
|
|||
curl_code = curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
|
||||
|
||||
/* check response */
|
||||
if (curl_code == CURLE_OK && http_code == 200) { /* everything is ok */
|
||||
print(3, "Request succeeded with code: %i", ch, http_code);
|
||||
queue_clear(&ch->queue);
|
||||
print(4, "Request succeeded with code: %i", ch, http_code);
|
||||
ch->buffer.sent = NULL;
|
||||
}
|
||||
else { /* error */
|
||||
if (curl_code != CURLE_OK) {
|
||||
|
@ -222,19 +225,22 @@ void * api_thread(void *arg) {
|
|||
else if (http_code != 200) {
|
||||
char err[255];
|
||||
api_parse_exception(response, err);
|
||||
print(-1, "Invalid middlware response: %s", ch, err);
|
||||
print(-1, "Error from middleware: %s", ch, err);
|
||||
}
|
||||
|
||||
print(2, "Sleeping %i seconds due to previous failure", ch, RETRY_PAUSE);
|
||||
sleep(RETRY_PAUSE);
|
||||
}
|
||||
|
||||
|
||||
/* householding */
|
||||
free(response.data);
|
||||
json_object_put(json_obj);
|
||||
|
||||
pthread_testcancel(); /* test for cancelation request */
|
||||
} while (opts.daemon);
|
||||
|
||||
if (!opts.daemon) {
|
||||
break;
|
||||
}
|
||||
else if (curl_code != CURLE_OK || http_code != 200) {
|
||||
print(2, "Sleeping %i seconds due to previous failure", ch, RETRY_PAUSE);
|
||||
sleep(RETRY_PAUSE);
|
||||
}
|
||||
}
|
||||
|
||||
curl_easy_cleanup(curl); /* always cleanup */
|
||||
|
|
@ -29,9 +29,9 @@
|
|||
#include <stddef.h>
|
||||
#include <curl/curl.h>
|
||||
#include <json/json.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "protocol.h"
|
||||
#include "buffer.h"
|
||||
|
||||
typedef struct {
|
||||
char *data;
|
||||
|
@ -42,7 +42,8 @@ typedef struct {
|
|||
int curl_custom_debug_callback(CURL *curl, curl_infotype type, char *data, size_t size, void *custom);
|
||||
size_t curl_custom_write_callback(void *ptr, size_t size, size_t nmemb, void *data);
|
||||
|
||||
json_object * api_json_tuples(channel_t *ch, bool_t all);
|
||||
json_object * api_json_tuples(buffer_t *buf, meter_reading_t *start);
|
||||
void * api_thread(void *arg);
|
||||
double api_tvtof(struct timeval tv);
|
||||
|
||||
#endif /* _API_H_ */
|
123
bin/vzlogger/buffer.c
Normal file
123
bin/vzlogger/buffer.c
Normal file
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
* 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, int mem) {
|
||||
pthread_mutex_init(&buf->mutex, NULL);
|
||||
|
||||
pthread_mutex_lock(&buf->mutex);
|
||||
buf->last = NULL;
|
||||
buf->start = NULL;
|
||||
buf->sent = NULL;
|
||||
buf->size = 0;
|
||||
buf->memory = mem;
|
||||
pthread_mutex_unlock(&buf->mutex);
|
||||
}
|
||||
|
||||
int buffer_push(buffer_t *buf, meter_reading_t rd) {
|
||||
meter_reading_t *new = malloc(sizeof(meter_reading_t));
|
||||
|
||||
if (!new) {
|
||||
return 0; /* cannot allocate memory */
|
||||
}
|
||||
|
||||
memcpy(new, &rd, sizeof(meter_reading_t));
|
||||
|
||||
pthread_mutex_lock(&buf->mutex);
|
||||
if (buf->last == NULL) { /* empty buffer */
|
||||
buf->start = new;
|
||||
}
|
||||
else {
|
||||
buf->last->next = new;
|
||||
}
|
||||
|
||||
if (buf->sent == NULL) { /* add reading to send queue */
|
||||
buf->sent = new;
|
||||
}
|
||||
|
||||
new->next = NULL;
|
||||
buf->last = new;
|
||||
buf->size++;
|
||||
pthread_mutex_unlock(&buf->mutex);
|
||||
|
||||
buffer_clean(buf);
|
||||
|
||||
return buf->size;
|
||||
}
|
||||
|
||||
void buffer_clean(buffer_t *buf) {
|
||||
pthread_mutex_lock(&buf->mutex);
|
||||
while(buf->size > buf->memory && buf->start != buf->sent) {
|
||||
meter_reading_t *pop = buf->start;
|
||||
|
||||
buf->start = buf->start->next;
|
||||
buf->size--;
|
||||
|
||||
free(pop);
|
||||
}
|
||||
pthread_mutex_unlock(&buf->mutex);
|
||||
}
|
||||
|
||||
char * buffer_dump(buffer_t *buf, char *dump, int len) {
|
||||
strcpy(dump, "|");
|
||||
|
||||
for (meter_reading_t *rd = buf->start; rd != NULL; rd = rd->next) {
|
||||
char tmp[16];
|
||||
sprintf(tmp, "%.2f|", rd->value);
|
||||
|
||||
if (strlen(dump)+strlen(tmp) < len) {
|
||||
if (buf->sent == rd) { /* indicate last sent reading */
|
||||
strcat(dump, "!");
|
||||
}
|
||||
|
||||
strcat(dump, tmp);
|
||||
}
|
||||
else {
|
||||
return NULL; /* dump buffer is full! */
|
||||
}
|
||||
}
|
||||
|
||||
return dump;
|
||||
}
|
||||
|
||||
void buffer_free(buffer_t *buf) {
|
||||
pthread_mutex_destroy(&buf->mutex);
|
||||
|
||||
meter_reading_t *rd = buf->start;
|
||||
do {
|
||||
meter_reading_t *tmp = rd;
|
||||
rd = rd->next;
|
||||
free(tmp);
|
||||
} while (rd);
|
||||
|
||||
memset(buf, 0, sizeof(buffer_t));
|
||||
}
|
57
bin/vzlogger/buffer.h
Normal file
57
bin/vzlogger/buffer.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Circular buffer (double linked, threadsafe)
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef _BUFFER_H_
|
||||
#define _BUFFER_H_
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <reading.h>
|
||||
|
||||
typedef struct {
|
||||
meter_reading_t *last;
|
||||
meter_reading_t *start;
|
||||
meter_reading_t *sent;
|
||||
|
||||
int size; /* number of readings currently in the buffer */
|
||||
int memory; /* number of readings to keep in mind for local interface */
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
} buffer_t;
|
||||
|
||||
/* Prototypes */
|
||||
void buffer_init(buffer_t *buf, int mem);
|
||||
int buffer_push(buffer_t *buf, meter_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, int len);
|
||||
|
||||
|
||||
#endif /* _BUFFER_H_ */
|
||||
|
91
bin/vzlogger/channel.c
Normal file
91
bin/vzlogger/channel.c
Normal file
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* Channel class
|
||||
*
|
||||
* @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 <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "vzlogger.h"
|
||||
#include "api.h"
|
||||
#include "channel.h"
|
||||
#include "options.h"
|
||||
|
||||
extern options_t opts;
|
||||
|
||||
void reading_thread(void *arg) {
|
||||
channel_t *ch = (channel_t *) arg;
|
||||
|
||||
while (1) {
|
||||
meter_reading_t rd = meter_read(&ch->meter);
|
||||
print(1, "Value read: %.2f at %.0f", ch, rd.value, api_tvtof(rd.tv));
|
||||
|
||||
buffer_push(&ch->buffer, rd);
|
||||
pthread_mutex_lock(&ch->buffer.mutex);
|
||||
pthread_cond_broadcast(&ch->condition); /* notify webserver and logging thread */
|
||||
pthread_mutex_unlock(&ch->buffer.mutex);
|
||||
|
||||
/* Debugging */
|
||||
if (opts.verbose >= 10) {
|
||||
char dump[1024];
|
||||
buffer_dump(&ch->buffer, dump, 1024);
|
||||
print(10, "Buffer dump: %s (size=%i, memory=%i)", ch, dump, ch->buffer.size, ch->buffer.memory);
|
||||
}
|
||||
|
||||
if (ch->meter.type->periodical) {
|
||||
print(8, "Next reading in %i seconds", ch, ch->interval);
|
||||
sleep(ch->interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void channel_init(channel_t *ch, char *uuid, char *middleware, unsigned long interval, char *options, meter_type_t *type) {
|
||||
static int instances; /* static to generate channel ids */
|
||||
|
||||
int buffer_size = (type->periodical) ? (BUFFER_DURATION / interval) + 1 : BUFFER_LENGTH;
|
||||
|
||||
ch->id = instances++;
|
||||
ch->interval = interval;
|
||||
ch->uuid = strdup(uuid);
|
||||
ch->middleware = strdup(middleware);
|
||||
ch->options = strdup(options);
|
||||
|
||||
meter_init(&ch->meter, type, options);
|
||||
buffer_init(&ch->buffer, buffer_size); /* initialize buffer */
|
||||
|
||||
pthread_cond_init(&ch->condition, NULL); /* initialize thread syncronization helpers */
|
||||
}
|
||||
|
||||
/**
|
||||
* Free all allocated memory recursivly
|
||||
*/
|
||||
void channel_free(channel_t *ch) {
|
||||
buffer_free(&ch->buffer);
|
||||
meter_free(&ch->meter);
|
||||
pthread_cond_destroy(&ch->condition);
|
||||
|
||||
free(ch->uuid);
|
||||
free(ch->options);
|
||||
free(ch->middleware);
|
||||
}
|
60
bin/vzlogger/channel.h
Normal file
60
bin/vzlogger/channel.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* Channel handling
|
||||
*
|
||||
* @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 _CHANNEL_H_
|
||||
#define _CHANNEL_H_
|
||||
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <meter.h>
|
||||
|
||||
#include "buffer.h"
|
||||
|
||||
typedef struct channel {
|
||||
unsigned int id; /* only for internal usage & debugging */
|
||||
char *middleware; /* url to middleware */
|
||||
char *options; /* protocols specific configuration */
|
||||
char *uuid; /* unique identifier for middleware */
|
||||
|
||||
unsigned long interval; /* polling interval (for sensors only) */
|
||||
|
||||
meter_t meter; /* handle to store connection status */
|
||||
buffer_t buffer; /* circular queue to buffer readings */
|
||||
|
||||
pthread_t logging_thread; /* pthread for asynchronus logging */
|
||||
pthread_t reading_thread; /* pthread for asynchronus reading */
|
||||
pthread_cond_t condition; /* pthread syncronization to notify logging thread and local webserver */
|
||||
|
||||
struct channel *next; /* pointer for linked list */
|
||||
} channel_t;
|
||||
|
||||
/* Prototypes */
|
||||
void channel_init(channel_t *ch, char *uuid, char *middleware, unsigned long interval, char *options, meter_type_t *type);
|
||||
void channel_free(channel_t *ch);
|
||||
|
||||
void reading_thread(void *arg);
|
||||
|
||||
#endif /* _CHANNEL_H_ */
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Circular queue to buffer readings
|
||||
* Linked list to manage channels
|
||||
*
|
||||
* @package vzlogger
|
||||
* @copyright Copyright (c) 2011, The volkszaehler.org project
|
||||
|
@ -22,38 +22,47 @@
|
|||
* 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 _QUEUE_H_
|
||||
#define _QUEUE_H_
|
||||
|
||||
#include "protocol.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#include "list.h"
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
void list_init(list_t *ls) {
|
||||
ls->start = NULL;
|
||||
ls->size = 0;
|
||||
}
|
||||
|
||||
typedef char bool_t;
|
||||
int list_push(list_t *ls, channel_t ch) {
|
||||
channel_t *new = malloc(sizeof(channel_t));
|
||||
|
||||
typedef struct {
|
||||
size_t size;
|
||||
|
||||
size_t read_p;
|
||||
size_t write_p;
|
||||
|
||||
reading_t *buf;
|
||||
} queue_t;
|
||||
if (!new) {
|
||||
return 0; /* cannot allocate memory */
|
||||
}
|
||||
|
||||
bool_t queue_init(queue_t *q, size_t size);
|
||||
bool_t queue_is_empty(queue_t *q);
|
||||
bool_t queue_get(queue_t *q, size_t index, reading_t *rd);
|
||||
bool_t queue_push(queue_t *q, reading_t rd);
|
||||
void queue_clear(queue_t *q);
|
||||
void queue_free(queue_t *q);
|
||||
char * queue_print(queue_t *q);
|
||||
memcpy(new, &ch, sizeof(channel_t));
|
||||
|
||||
#endif /* _QUEUE_H_ */
|
||||
if (ls->start == NULL) { /* empty list */
|
||||
new->next = NULL;
|
||||
}
|
||||
else {
|
||||
new->next = ls->start;
|
||||
}
|
||||
|
||||
ls->start = new;
|
||||
ls->size++;
|
||||
|
||||
return ls->size;
|
||||
}
|
||||
|
||||
void list_free(list_t *ls) {
|
||||
channel_t *ch = ls->start;
|
||||
do {
|
||||
channel_t *tmp = ch;
|
||||
ch = ch->next;
|
||||
channel_free(tmp);
|
||||
} while (ch);
|
||||
|
||||
ls->start = NULL;
|
||||
ls->size = 0;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Generate pseudo random data series with a random walk
|
||||
* Linked list to manage channels
|
||||
*
|
||||
* @package vzlogger
|
||||
* @copyright Copyright (c) 2011, The volkszaehler.org project
|
||||
|
@ -23,19 +23,19 @@
|
|||
* along with volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _RANDOM_H_
|
||||
#define _RANDOM_H_
|
||||
#ifndef _LIST_H_
|
||||
#define _LIST_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
#include "channel.h"
|
||||
|
||||
typedef struct {
|
||||
float min, max, last;
|
||||
} random_state_t;
|
||||
channel_t *start;
|
||||
int size;
|
||||
} list_t;
|
||||
|
||||
double ltqnorm(double p);
|
||||
/* Prototypes */
|
||||
void list_init(list_t *ls);
|
||||
int list_push(list_t *ls, channel_t ch);
|
||||
void list_free(list_t *ls);
|
||||
|
||||
void * random_init(char *port);
|
||||
void random_close(void *handle);
|
||||
reading_t random_get(void *handle);
|
||||
|
||||
#endif /* _RANDOM_H_ */
|
||||
#endif /* _LIST_H_ */
|
|
@ -26,39 +26,50 @@
|
|||
#include <json/json.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "vzlogger.h"
|
||||
#include "local.h"
|
||||
#include "options.h"
|
||||
#include "api.h"
|
||||
|
||||
extern channel_t chans[MAX_CHANNELS];
|
||||
extern list_t chans;
|
||||
extern options_t opts;
|
||||
|
||||
int handle_request(void *cls, struct MHD_Connection *connection, const char *url, const char *method,
|
||||
const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls) {
|
||||
const char * json_str;
|
||||
|
||||
int ret;
|
||||
int num_chans = *(int *) cls;
|
||||
print(2, "Local request received: %s %s %s", NULL, version, method, url);
|
||||
const char *json_str;
|
||||
const char *uuid = url+1;
|
||||
|
||||
struct timespec ts;
|
||||
struct timeval tp;
|
||||
|
||||
struct MHD_Response *response;
|
||||
|
||||
struct json_object *json_obj = json_object_new_object();
|
||||
struct json_object *json_data = json_object_new_object();
|
||||
|
||||
for (int i = 0; i < num_chans; i++) {
|
||||
channel_t *ch = &chans[i];
|
||||
reading_t rd;
|
||||
print(2, "Local request received: %s %s %s", NULL, version, method, url);
|
||||
|
||||
if (strcmp(url, "/") == 0 || strcmp(ch->uuid, url + 1) == 0) {
|
||||
pthread_mutex_lock(&ch->mutex);
|
||||
/* wait for new data comet-like blocking of HTTP response */
|
||||
pthread_cond_wait(&ch->condition, &ch->mutex); // TODO use pthread_cond_timedwait()
|
||||
pthread_mutex_unlock(&ch->mutex);
|
||||
for (channel_t *ch = chans.start; ch != NULL; ch = ch->next) {
|
||||
if (strcmp(url, "/") == 0 || strcmp(ch->uuid, uuid) == 0) {
|
||||
/* convert from timeval to timespec */
|
||||
gettimeofday(&tp, NULL);
|
||||
ts.tv_sec = tp.tv_sec;
|
||||
ts.tv_nsec = tp.tv_usec * 1000;
|
||||
ts.tv_sec += COMET_TIMEOUT;
|
||||
|
||||
struct json_object *json_tuples = api_json_tuples(ch, TRUE);
|
||||
/* blocking until new data arrives (comet-like blocking of HTTP response) */
|
||||
pthread_mutex_lock(&ch->buffer.mutex);
|
||||
pthread_cond_timedwait(&ch->condition, &ch->buffer.mutex, &ts);
|
||||
pthread_mutex_unlock(&ch->buffer.mutex);
|
||||
|
||||
json_object_object_add(json_data, "uuid", json_object_new_string(ch->uuid));
|
||||
json_object_object_add(json_data, "interval", json_object_new_int(ch->interval));
|
||||
|
||||
struct json_object *json_tuples = api_json_tuples(&ch->buffer, ch->buffer.start);
|
||||
json_object_object_add(json_data, "tuples", json_tuples);
|
||||
}
|
||||
}
|
231
bin/vzlogger/options.c
Normal file
231
bin/vzlogger/options.c
Normal file
|
@ -0,0 +1,231 @@
|
|||
/**
|
||||
* Parsing commandline options and channel list
|
||||
*
|
||||
* @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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include "../../config.h"
|
||||
|
||||
#include "list.h"
|
||||
#include "options.h"
|
||||
#include "channel.h"
|
||||
#include "vzlogger.h"
|
||||
|
||||
extern meter_type_t meter_types[];
|
||||
|
||||
options_t opts = { /* setting default options */
|
||||
"/etc/vzlogger.conf", /* config file */
|
||||
8080, /* port for local interface */
|
||||
0, /* verbosity level */
|
||||
0, /* daemon mode */
|
||||
0 /* local interface */
|
||||
};
|
||||
|
||||
/**
|
||||
* Command line options
|
||||
*/
|
||||
struct option long_options[] = {
|
||||
{"config", required_argument, 0, 'c'},
|
||||
{"daemon", required_argument, 0, 'd'},
|
||||
#ifdef LOCAL_SUPPORT
|
||||
{"local", no_argument, 0, 'l'},
|
||||
{"local-port", required_argument, 0, 'p'},
|
||||
#endif /* LOCAL_SUPPORT */
|
||||
{"verbose", optional_argument, 0, 'v'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"version", no_argument, 0, 'V'},
|
||||
{} /* stop condition for iterator */
|
||||
};
|
||||
|
||||
/**
|
||||
* Descriptions vor command line options
|
||||
*/
|
||||
char *long_options_descs[] = {
|
||||
"config file with channel -> uuid mapping",
|
||||
"run as daemon",
|
||||
#ifdef LOCAL_SUPPORT
|
||||
"activate local interface (tiny webserver)",
|
||||
"TCP port for local interface",
|
||||
#endif /* LOCAL_SUPPORT */
|
||||
"enable verbose output",
|
||||
"show this help",
|
||||
"show version of vzlogger",
|
||||
"" /* stop condition for iterator */
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse options from command line
|
||||
*/
|
||||
void parse_options(int argc, char * argv[], options_t * opts) {
|
||||
while (1) {
|
||||
/* getopt_long stores the option index here. */
|
||||
int option_index = 0;
|
||||
|
||||
int c = getopt_long(argc, argv, "i:c:p:lhVdv::", long_options, &option_index);
|
||||
|
||||
/* detect the end of the options. */
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'v':
|
||||
opts->verbose = (optarg == NULL) ? 1 : atoi(optarg);
|
||||
break;
|
||||
|
||||
#ifdef LOCAL_SUPPORT
|
||||
case 'l':
|
||||
opts->local = 1;
|
||||
break;
|
||||
|
||||
case 'p': /* port for local interface */
|
||||
opts->port = atoi(optarg);
|
||||
break;
|
||||
#endif /* LOCAL_SUPPORT */
|
||||
|
||||
case 'd':
|
||||
opts->daemon = 1;
|
||||
break;
|
||||
|
||||
case 'c': /* read config file */
|
||||
opts->config = (char *) malloc(strlen(optarg)+1);
|
||||
strcpy(opts->config, optarg);
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
printf("%s\n", VERSION);
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
usage(argv);
|
||||
exit((c == '?') ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void parse_channels(char *filename, list_t *chans) {
|
||||
FILE *file = fopen(filename, "r"); /* open configuration */
|
||||
|
||||
if (!filename) { /* nothing found */
|
||||
print(-1, "No config file found! Please specify with --config!\n", NULL);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (file == NULL) {
|
||||
perror(filename); /* why didn't the file open? */
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else {
|
||||
print(2, "Start parsing configuration from %s", NULL, filename);
|
||||
}
|
||||
|
||||
int lineno = 1;
|
||||
char *buffer = malloc(256);
|
||||
char *tokens[5];
|
||||
char *line;
|
||||
|
||||
/* compile regular expressions */
|
||||
regex_t re_uuid, re_middleware;
|
||||
regcomp(&re_uuid, "^[a-f0-9]{8}-([a-f0-9]{4}-){3,3}[a-f0-9]{12}$", REG_EXTENDED | REG_ICASE | REG_NOSUB);
|
||||
regcomp(&re_middleware, "^https?://[a-z0-9.-]+\\.[a-z]{2,6}(/\\S*)?$", REG_EXTENDED | REG_ICASE | REG_NOSUB);
|
||||
|
||||
/*regerror(err, &re_uuid, buffer, 256);
|
||||
printf("Error analyzing regular expression: %s.\n", buffer);*/
|
||||
|
||||
while ((line = fgets(buffer, 256, file)) != NULL) { /* read a line */
|
||||
line[strcspn(line, "\n\r;")] = '\0'; /* strip newline and comments */
|
||||
if (strlen(line) == 0) continue; /* skip empty lines */
|
||||
|
||||
/* channel properties */
|
||||
char *middleware, *options, *uuid;
|
||||
unsigned long interval;
|
||||
channel_t ch;
|
||||
meter_type_t *type;
|
||||
|
||||
/* parse tokens (required) */
|
||||
memset(tokens, 0, 5);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
do {
|
||||
tokens[i] = strsep(&line, " \t");
|
||||
} while (tokens[i] == NULL && line != NULL);
|
||||
}
|
||||
|
||||
/* protocol (required) */
|
||||
for (type = meter_types; type->name != NULL; type++) { /* linear search */
|
||||
if (strcmp(type->name, tokens[0]) == 0) break;
|
||||
}
|
||||
|
||||
if (type->name == NULL) { /* reached end */
|
||||
print(-1, "Invalid protocol: %s in %s:%i", NULL, tokens[0], filename, lineno);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* middleware (required) */
|
||||
middleware = tokens[1];
|
||||
if (regexec(&re_middleware, middleware, 0, NULL, 0) == 0) {
|
||||
print(-1, "Invalid interval: %s in %s:%i", NULL, tokens[1], filename, lineno);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* uuid (required) */
|
||||
uuid = tokens[2];
|
||||
if (regexec(&re_uuid, uuid, 0, NULL, 0) != 0) {
|
||||
print(-1, "Invalid uuid: %s in %s:%i", NULL, tokens[2], filename, lineno);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* interval (only if protocol is sensor) */
|
||||
if (type->periodical) {
|
||||
interval = strtol(tokens[3], (char **) NULL, 10);
|
||||
if (errno == EINVAL || errno == ERANGE) {
|
||||
print(-1, "Invalid interval: %s in %s:%i", NULL, tokens[3], filename, lineno);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
interval = 0;
|
||||
}
|
||||
|
||||
/* options (optional) */
|
||||
options = tokens[type->periodical ? 4 : 3];
|
||||
|
||||
channel_init(&ch, uuid, middleware, interval, options, type);
|
||||
print(1, "Parsed (protocol=%s interval=%i uuid=%s middleware=%s options=%s)", &ch, type->name, interval, uuid, middleware, options);
|
||||
|
||||
list_push(chans, ch);
|
||||
lineno++;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
free(buffer);
|
||||
regfree(&re_middleware);
|
||||
regfree(&re_uuid);
|
||||
}
|
48
bin/vzlogger/options.h
Normal file
48
bin/vzlogger/options.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Parsing commandline options and channel list
|
||||
*
|
||||
* @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/>.
|
||||
*/
|
||||
|
||||
#ifndef _OPTIONS_H_
|
||||
#define _OPTIONS_H_
|
||||
|
||||
#include "list.h"
|
||||
|
||||
/**
|
||||
* Options from command line
|
||||
*/
|
||||
typedef struct {
|
||||
char *config; /* path to config file */
|
||||
unsigned int port; /* tcp port for local interface */
|
||||
int verbose; /* verbosity level */
|
||||
|
||||
/* boolean bitfields, at the end of struct */
|
||||
int daemon:1;
|
||||
int local:1; /* enable local interface */
|
||||
} options_t;
|
||||
|
||||
/* Prototypes */
|
||||
void parse_options(int argc, char *argv[], options_t *opts);
|
||||
void parse_channels(char *filename, list_t *chans);
|
||||
|
||||
#endif /* _OPTIONS_H_ */
|
BIN
bin/vzlogger/vzlogger
Executable file
BIN
bin/vzlogger/vzlogger
Executable file
Binary file not shown.
192
bin/vzlogger/vzlogger.c
Normal file
192
bin/vzlogger/vzlogger.c
Normal file
|
@ -0,0 +1,192 @@
|
|||
/**
|
||||
* Main source file
|
||||
*
|
||||
* @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 <stdio.h> /* for print() */
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "vzlogger.h"
|
||||
|
||||
#include "list.h"
|
||||
#include "buffer.h"
|
||||
#include "channel.h"
|
||||
#include "api.h"
|
||||
#include "options.h"
|
||||
|
||||
#ifdef LOCAL_SUPPORT
|
||||
#include <microhttpd.h>
|
||||
#include "local.h"
|
||||
#endif /* LOCAL_SUPPORT */
|
||||
|
||||
/* global variables */
|
||||
list_t chans;
|
||||
extern options_t opts;
|
||||
extern char *long_options_descs[];
|
||||
extern struct option long_options[];
|
||||
extern meter_type_t meter_types[];
|
||||
|
||||
/**
|
||||
* Print available options and some other usefull information
|
||||
*/
|
||||
void usage(char *argv[]) {
|
||||
char **desc = long_options_descs;
|
||||
struct option *op = long_options;
|
||||
meter_type_t *type = meter_types;
|
||||
|
||||
printf("Usage: %s [options]\n\n", argv[0]);
|
||||
printf(" following options are available:\n");
|
||||
|
||||
while (op->name && *desc) {
|
||||
printf("\t-%c, --%-12s\t%s\n", op->val, op->name, *desc);
|
||||
op++; desc++;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf(" following protocol types are supported:\n");
|
||||
|
||||
while (type->name) {
|
||||
printf("\t%-12s\t%s\n", type->name, type->desc);
|
||||
type++;
|
||||
}
|
||||
|
||||
printf("\n%s - volkszaehler.org logging utility\n", PACKAGE_STRING);
|
||||
printf("by Steffen Vogel <stv0g@0l.de>\n");
|
||||
printf("send bugreports to %s\n", PACKAGE_BUGREPORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to log notices and errors
|
||||
*
|
||||
* @param ch could be NULL for general messages
|
||||
* @todo integrate into syslog
|
||||
*/
|
||||
void print(int level, char * format, channel_t *ch, ... ) {
|
||||
va_list args;
|
||||
|
||||
struct timeval now;
|
||||
struct tm * timeinfo;
|
||||
char buffer[1024] = "[", *pos = buffer+1;
|
||||
|
||||
if (level <= opts.verbose) {
|
||||
gettimeofday(&now, NULL);
|
||||
timeinfo = localtime(&now.tv_sec);
|
||||
pos += strftime(pos, 16, "%b %d %H:%M:%S", timeinfo);
|
||||
|
||||
pos += sprintf(pos, ".%03lu] ", now.tv_usec / 1000);
|
||||
|
||||
if (ch != NULL) {
|
||||
pos += sprintf(pos, "[ch#%i] ", ch->id);
|
||||
}
|
||||
|
||||
va_start(args, ch);
|
||||
pos += vsprintf(pos, format, args);
|
||||
va_end(args);
|
||||
|
||||
fprintf((level > 0) ? stdout : stderr, "%s\n", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel threads
|
||||
*
|
||||
* Threads gets joined in main()
|
||||
*/
|
||||
void quit(int sig) {
|
||||
print(2, "Closing connections to terminate", NULL);
|
||||
for (channel_t *ch = chans.start; ch != NULL; ch = ch->next) {
|
||||
pthread_cancel(ch->logging_thread);
|
||||
pthread_cancel(ch->reading_thread);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The main loop
|
||||
*/
|
||||
int main(int argc, char *argv[]) {
|
||||
/* bind signal handler */
|
||||
struct sigaction action;
|
||||
sigemptyset(&action.sa_mask);
|
||||
action.sa_flags = 0;
|
||||
action.sa_handler = quit;
|
||||
sigaction(SIGINT, &action, NULL);
|
||||
|
||||
list_init(&chans);
|
||||
parse_options(argc, argv, &opts); /* parse command line arguments */
|
||||
parse_channels(opts.config, &chans); /* parse channels from configuration */
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL); /* global intialization for all threads */
|
||||
|
||||
for (channel_t *ch = chans.start; ch != NULL; ch = ch->next) {
|
||||
print(5, "Opening connection to meter", ch);
|
||||
meter_open(&ch->meter);
|
||||
|
||||
print(5, "Starting threads", ch);
|
||||
pthread_create(&ch->logging_thread, NULL, &api_thread, (void *) ch);
|
||||
pthread_create(&ch->reading_thread, NULL, &reading_thread, (void *) ch);
|
||||
}
|
||||
|
||||
#ifdef LOCAL_SUPPORT
|
||||
struct MHD_Daemon *httpd_handle = NULL;
|
||||
if (opts.local) { /* start webserver for local interface */
|
||||
print(5, "Starting local interface HTTPd on port %i", NULL, opts.port);
|
||||
httpd_handle = MHD_start_daemon(
|
||||
MHD_USE_THREAD_PER_CONNECTION,
|
||||
opts.port,
|
||||
NULL, NULL,
|
||||
handle_request,
|
||||
NULL,
|
||||
MHD_OPTION_END
|
||||
);
|
||||
}
|
||||
#endif /* LOCAL_SUPPORT */
|
||||
|
||||
/* wait for all threads to terminate */
|
||||
for (channel_t *ch = chans.start; ch != NULL; ch = ch->next) {
|
||||
pthread_join(ch->logging_thread, NULL);
|
||||
pthread_join(ch->reading_thread, NULL);
|
||||
|
||||
meter_close(&ch->meter); /* closing connection */
|
||||
}
|
||||
|
||||
#ifdef LOCAL_SUPPORT
|
||||
/* stop webserver */
|
||||
if (httpd_handle) {
|
||||
print(8, "Stopping local interface HTTPd on port %i", NULL, opts.port);
|
||||
MHD_stop_daemon(httpd_handle);
|
||||
}
|
||||
#endif /* LOCAL_SUPPORT */
|
||||
|
||||
/* householding */
|
||||
list_free(&chans);
|
||||
curl_global_cleanup();
|
||||
|
||||
print(10, "Bye bye!", NULL);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
45
bin/vzlogger/vzlogger.h
Normal file
45
bin/vzlogger/vzlogger.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* Main header file
|
||||
*
|
||||
* @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 _VZLOGGER_H_
|
||||
#define _VZLOGGER_H_
|
||||
|
||||
#include "../../config.h"
|
||||
|
||||
#include <meter.h>
|
||||
|
||||
#include "channel.h"
|
||||
|
||||
/* some hard coded configuration */
|
||||
#define RETRY_PAUSE 10 //600 /* seconds to wait after failed request */
|
||||
#define BUFFER_DURATION 60 /* in seconds */
|
||||
#define BUFFER_LENGTH 256 /* in readings */
|
||||
#define COMET_TIMEOUT 30 /* seconds */
|
||||
|
||||
/* Prototypes */
|
||||
void print(int level, char *format, channel_t *ch, ... );
|
||||
void usage(char ** argv);
|
||||
|
||||
#endif /* _VZLOGGER_H_ */
|
|
@ -73,7 +73,10 @@
|
|||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Local interface */
|
||||
#undef LOCAL
|
||||
#undef LOCAL_SUPPORT
|
||||
|
||||
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
|
||||
#undef NO_MINUS_C_MINUS_O
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
@ -96,6 +99,9 @@
|
|||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Smart Messaging Language */
|
||||
#undef SML_SUPPORT
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
|
|
37
configure.ac
37
configure.ac
|
@ -4,15 +4,26 @@
|
|||
AC_PREREQ([2.67])
|
||||
AC_INIT([vzlogger], [0.2], [http://bugs.volkszaehler.org])
|
||||
AM_INIT_AUTOMAKE(vzlogger, 0.2)
|
||||
AC_CONFIG_SRCDIR([src/main.c])
|
||||
AC_CONFIG_SRCDIR([src/meter.c])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_FILES([Makefile src/Makefile docs/Makefile])
|
||||
AC_CONFIG_FILES([Makefile
|
||||
docs/Makefile
|
||||
src/Makefile
|
||||
bin/reader/Makefile
|
||||
bin/vzlogger/Makefile
|
||||
])
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
|
||||
# We want to build a lib
|
||||
AC_PROG_RANLIB
|
||||
|
||||
# We use per target compiler flags
|
||||
AM_PROG_CC_C_O
|
||||
|
||||
# Checks for libraries.
|
||||
PKG_CHECK_MODULES([DEPS], [json >= 0.9 libcurl >= 7.21.0])
|
||||
PKG_CHECK_MODULES([DEPS_VZ], [json >= 0.9 libcurl >= 7.21.0])
|
||||
|
||||
# Checks for header files.
|
||||
AC_CHECK_HEADERS([fcntl.h stddef.h stdint.h stdlib.h string.h sys/time.h termios.h unistd.h])
|
||||
|
@ -27,17 +38,31 @@ AC_FUNC_REALLOC
|
|||
AC_FUNC_STRERROR_R
|
||||
AC_CHECK_FUNCS([gettimeofday memset sqrt strchr strtol])
|
||||
|
||||
# SML support
|
||||
AC_ARG_ENABLE(
|
||||
[sml],
|
||||
[AS_HELP_STRING([--enable-sml], [enable support for smart messaging language (def=no)])],
|
||||
[sml=true],
|
||||
[sml=false]
|
||||
)
|
||||
|
||||
AM_CONDITIONAL([SML_SUPPORT], [test x"$sml" = x"true"])
|
||||
if test x"$sml" = x"true"; then
|
||||
AC_DEFINE([SML_SUPPORT], [], [Smart Messaging Language])
|
||||
PKG_CHECK_MODULES([DEPS_SML], [sml >= 0.1])
|
||||
fi
|
||||
|
||||
# local interface support
|
||||
AC_ARG_ENABLE(
|
||||
[local-interface],
|
||||
[local],
|
||||
[AS_HELP_STRING([--enable-local], [enable support for local HTTPd (def=no)])],
|
||||
[local=true],
|
||||
[local=false]
|
||||
)
|
||||
|
||||
AM_CONDITIONAL([LOCAL], [test x$local = xtrue])
|
||||
AM_CONDITIONAL([LOCAL_SUPPORT], [test x"$local" = x"true"])
|
||||
if test x"$local" = x"true"; then
|
||||
AC_DEFINE([LOCAL],[],[Local interface])
|
||||
AC_DEFINE([LOCAL_SUPPORT], [], [Local interface])
|
||||
PKG_CHECK_MODULES([DEPS_LOCAL], [libmicrohttpd >= 0.9.3])
|
||||
fi
|
||||
|
||||
|
|
|
@ -83,10 +83,12 @@ CPPFLAGS =
|
|||
CYGPATH_W = echo
|
||||
DEFS = -DHAVE_CONFIG_H
|
||||
DEPDIR = .deps
|
||||
DEPS_CFLAGS = -I/usr/include/json
|
||||
DEPS_LIBS = -ljson -lcurl
|
||||
DEPS_LOCAL_CFLAGS =
|
||||
DEPS_LOCAL_LIBS =
|
||||
DEPS_SML_CFLAGS = -I/usr/include/sml -I/usr/include/uuid
|
||||
DEPS_SML_LIBS = -lsml -luuid
|
||||
DEPS_VZ_CFLAGS = -I/usr/include/json
|
||||
DEPS_VZ_LIBS = -ljson -lcurl
|
||||
ECHO_C =
|
||||
ECHO_N = -n
|
||||
ECHO_T =
|
||||
|
@ -116,6 +118,7 @@ PATH_SEPARATOR = :
|
|||
PKG_CONFIG = /usr/bin/pkg-config
|
||||
PKG_CONFIG_LIBDIR =
|
||||
PKG_CONFIG_PATH =
|
||||
RANLIB = ranlib
|
||||
SET_MAKE =
|
||||
SHELL = /bin/bash
|
||||
STRIP =
|
||||
|
|
|
@ -2,9 +2,13 @@
|
|||
; use tabs, spaces as delimiter
|
||||
; use ; to introduce a comment
|
||||
|
||||
;prot intval uuid middleware options
|
||||
1wire 10 371dd700-beb3-11e0-8dda-b961518a06f4 http://demo.volkszaehler.org/middleware.php /mnt/1wire/10.12E6D3000800/temperature
|
||||
;obis 10 ef0e9adf-cd9e-4d9a-92c5-b4fb4c89ff98 http://volkszaehler.org/demo/middleware.php /dev/ttyS0
|
||||
;rawS0 10 27a1b4c0-8f8a-11e0-ad82-db6efbc4ba2e http://volkszaehler.org/demo/middleware.php /dev/ttyUSB2
|
||||
random 5 e4ff8f70-9f79-11e0-b44c-d1ce78df8288 http://localhost/workspace/volkszaehler.org/htdocs/middleware 40
|
||||
;prot middleware uuid intval options
|
||||
;1wire http://demo.volkszaehler.org/middleware.php 371dd700-beb3-11e0-8dda-b961518a06f4 10 /mnt/1wire/10.12E6D3000800/temperature
|
||||
;obis http://volkszaehler.org/demo/middleware.php ef0e9adf-cd9e-4d9a-92c5-b4fb4c89ff98 10 /dev/ttyS0
|
||||
;rawS0 http://volkszaehler.org/demo/middleware.php 27a1b4c0-8f8a-11e0-ad82-db6efbc4ba2e 10 /dev/ttyUSB2
|
||||
;random http://localhost/workspace/volkszaehler.org/volkszaehler.org/htdocs/middleware fde8f1d0-c5d0-11e0-856e-f9e4360ced10 5 40
|
||||
sml http://localhost/workspace/volkszaehler.org/volkszaehler.org/htdocs/middleware c853d890-daf3-11e0-86c4-875e5bd610cf 76h9vv5835w5.dyndns.info:7331:power
|
||||
;sml http://localhost/workspace/volkszaehler.org/volkszaehler.org/htdocs/middleware 5584d3e0-daf5-11e0-a1c8-3930962bdbf4 76h9vv5835w5.dyndns.info:7331:power-l1
|
||||
;sml http://localhost/workspace/volkszaehler.org/volkszaehler.org/htdocs/middleware 6d17cd80-daf5-11e0-916c-bfb24b4b6f01 76h9vv5835w5.dyndns.info:7331:power-l2
|
||||
;sml http://localhost/workspace/volkszaehler.org/volkszaehler.org/htdocs/middleware 78c09290-daf5-11e0-81e9-2f2eb65081d7 76h9vv5835w5.dyndns.info:7331:power-l3
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/**
|
||||
* OBIS protocol parser
|
||||
* Plaintext protocol according to DIN EN 62056-21
|
||||
*
|
||||
* This is our example protocol. Use this skeleton to add your own
|
||||
* protocols and meters.
|
||||
* This protocol uses OBIS to identify the readout data
|
||||
* And is also sometimes called "D0"
|
||||
*
|
||||
* @package vzlogger
|
||||
* @copyright Copyright (c) 2011, The volkszaehler.org project
|
||||
|
@ -26,20 +26,20 @@
|
|||
* along with volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _OBIS_H_
|
||||
#define _OBIS_H_
|
||||
#ifndef _D0_H_
|
||||
#define _D0_H_
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
#include "../protocol.h"
|
||||
#include "reading.h"
|
||||
|
||||
typedef struct {
|
||||
int fd; /* file descriptor of port */
|
||||
struct termios oldtio; /* required to reset port */
|
||||
} obis_state_t;
|
||||
} meter_handle_d0_t;
|
||||
|
||||
void * obis_init(char *port);
|
||||
void obis_close(void *handle);
|
||||
reading_t obis_get(void *handle);
|
||||
int meter_d0_open(meter_handle_d0_t *handle, char *options);
|
||||
void meter_d0_close(meter_handle_d0_t *handle);
|
||||
meter_reading_t meter_d0_read(meter_handle_d0_t *handle);
|
||||
|
||||
#endif /* _OBIS_H_ */
|
||||
#endif /* _D0_H_ */
|
90
include/meter.h
Normal file
90
include/meter.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* Protocol interface
|
||||
*
|
||||
* @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 _METER_H_
|
||||
#define _METER_H_
|
||||
|
||||
/**
|
||||
* We have 2 diffrent protocol types:
|
||||
* - SENSOR: a readout is triggered in equidistant intervals by calling
|
||||
* the read function with an POSIX timer.
|
||||
* The interval is set in the configuration.
|
||||
* - METER: 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"
|
||||
#include "reading.h"
|
||||
|
||||
/* meter types */
|
||||
#include "random.h"
|
||||
#include "s0.h"
|
||||
#include "d0.h"
|
||||
#include "onewire.h"
|
||||
#ifdef SML_SUPPORT
|
||||
#include "sml.h"
|
||||
#endif /* SML_SUPPORT */
|
||||
|
||||
typedef enum {
|
||||
S0,
|
||||
D0,
|
||||
ONEWIRE,
|
||||
RANDOM,
|
||||
#ifdef SML_SUPPORT
|
||||
SML
|
||||
#endif /* SML_SUPPORT */
|
||||
} meter_tag_t;
|
||||
|
||||
typedef struct {
|
||||
meter_tag_t tag;
|
||||
char *name; /* short identifier for protocol */
|
||||
char *desc; /* more detailed description */
|
||||
int periodical:1; /* does this meter has be triggered periodically? */
|
||||
} meter_type_t;
|
||||
|
||||
typedef struct {
|
||||
meter_type_t *type;
|
||||
char *options;
|
||||
union {
|
||||
meter_handle_s0_t s0;
|
||||
meter_handle_d0_t d0;
|
||||
meter_handle_onewire_t onewire;
|
||||
meter_handle_random_t random;
|
||||
#ifdef SML_SUPPORT
|
||||
meter_handle_sml_t sml;
|
||||
#endif /* SML_SUPPORT */
|
||||
} handle;
|
||||
} meter_t;
|
||||
|
||||
/* prototypes */
|
||||
void meter_init(meter_t *meter, meter_type_t *type, char *options);
|
||||
void meter_free(meter_t *meter);
|
||||
meter_reading_t meter_read(meter_t *meter);
|
||||
|
||||
int meter_open(meter_t *meter);
|
||||
void meter_close(meter_t *meter);
|
||||
|
||||
#endif /* _METER_H_ */
|
118
include/obis.h
Normal file
118
include/obis.h
Normal file
|
@ -0,0 +1,118 @@
|
|||
/**
|
||||
* OBIS IDs as specified in DIN EN 62056-61
|
||||
*
|
||||
* @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 _OBIS_H_
|
||||
#define _OBIS_H_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef enum {
|
||||
ABSTRACT = 0,
|
||||
ELECTRIC = 1,
|
||||
HEAT_COST = 4,
|
||||
COOLING = 5,
|
||||
HEATING = 6,
|
||||
GAS = 7,
|
||||
WATER_COLD = 8,
|
||||
WATER_HOT = 9
|
||||
} obis_media_t;
|
||||
|
||||
typedef union {
|
||||
enum {
|
||||
GENERAL_PURPOSE = 0,
|
||||
ACTIVE_POWER_IN = 1,
|
||||
ACTIVE_POWER_OUT = 2,
|
||||
REACTIVE_POWER_IN = 3,
|
||||
REACTIVE_POWER_OUT = 4,
|
||||
REACTIVE_POWER_Q1 = 5,
|
||||
REACTIVE_POWER_Q2 = 6,
|
||||
REACTIVE_POWER_Q3 = 7,
|
||||
REACTIVE_POWER_Q4 = 8,
|
||||
APPARENT_POWER_IN = 9,
|
||||
APPARENT_POWER_OUT = 10,
|
||||
CURRENT_ANY = 11,
|
||||
VOLTAGE_ANY = 12,
|
||||
POWER_FACTOR_OUT = 13,
|
||||
SUPPLY_FREQUENCY = 14,
|
||||
ACTIVE_POWER_Q1 = 17,
|
||||
ACTIVE_POWER_Q2 = 18,
|
||||
ACTIVE_POWER_Q3 = 19,
|
||||
ACTIVE_POWER_Q4 = 20,
|
||||
|
||||
L1_ACTIVE_POWER_INT = 21,
|
||||
L1_ACTIVE_POWER_OUT = 22,
|
||||
|
||||
ANGLES = 81,
|
||||
UNITLESS = 82,
|
||||
LOSS = 83,
|
||||
|
||||
L1_POWER_FACTOR_OUT = 85,
|
||||
L2_POWER_FACTOR_OUT = 86,
|
||||
L3_POWER_FACTOR_OUT = 87,
|
||||
|
||||
AMPERE_SQUARE_HOURS = 88,
|
||||
VOLT_SQUARE_HOURS = 89,
|
||||
|
||||
SERVICE = 96,
|
||||
ERROR = 97,
|
||||
LIST = 98,
|
||||
DATA_PROFILE = 99
|
||||
|
||||
} electric;
|
||||
|
||||
int gas; /* as defined in DIN EN 13757-1 */
|
||||
} obis_indicator_t;
|
||||
|
||||
/* regex: A-BB:CC.DD.EE(*FF)? */
|
||||
typedef union {
|
||||
unsigned char raw[6];
|
||||
struct {
|
||||
unsigned char media;
|
||||
unsigned char channel;
|
||||
unsigned char indicator;
|
||||
unsigned char mode;
|
||||
unsigned char 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;
|
||||
|
||||
/* prototypes */
|
||||
obis_id_t obis_init(unsigned char *raw);
|
||||
obis_id_t obis_parse(char *str);
|
||||
int obis_unparse(obis_id_t id, char *buffer);
|
||||
char obis_is_manufacturer_specific(obis_id_t id);
|
||||
|
||||
/* inline functions */
|
||||
inline int obis_compare(obis_id_t a, obis_id_t b) {
|
||||
return memcmp(&a, &b, sizeof(obis_id_t));
|
||||
}
|
||||
|
||||
#endif /* _OBIS_H_ */
|
41
include/onewire.h
Normal file
41
include/onewire.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* Wrapper to read Dallas 1-wire Sensors via the 1-wire Filesystem (owfs)
|
||||
*
|
||||
* @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 _ONEWIRE_H_
|
||||
#define _ONEWIRE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "reading.h"
|
||||
|
||||
typedef struct {
|
||||
FILE *file;
|
||||
} meter_handle_onewire_t;
|
||||
|
||||
int meter_onewire_open(meter_handle_onewire_t *handle, char *options);
|
||||
void meter_onewire_close(meter_handle_onewire_t *handle);
|
||||
meter_reading_t meter_onewire_read(meter_handle_onewire_t *handle);
|
||||
|
||||
#endif /* _ONEWIRE_H_ */
|
41
include/random.h
Normal file
41
include/random.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* Generate pseudo random data series by a random walk
|
||||
*
|
||||
* @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 _RANDOM_H_
|
||||
#define _RANDOM_H_
|
||||
|
||||
#include "reading.h"
|
||||
|
||||
typedef struct {
|
||||
double min, max, last;
|
||||
} meter_handle_random_t;
|
||||
|
||||
double ltqnorm(double p); /* forward declaration */
|
||||
|
||||
int meter_random_open(meter_handle_random_t *handle, char *options);
|
||||
void meter_random_close(meter_handle_random_t *handle);
|
||||
meter_reading_t meter_random_read(meter_handle_random_t *handle);
|
||||
|
||||
#endif /* _RANDOM_H_ */
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Wrapper to read Dallas 1-wire Sensors via the 1-wire Filesystem (owfs)
|
||||
* Meter readings
|
||||
*
|
||||
* @package vzlogger
|
||||
* @copyright Copyright (c) 2011, The volkszaehler.org project
|
||||
|
@ -22,14 +22,17 @@
|
|||
* 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 _1WIRE_H_
|
||||
#define _1WIRE_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
#ifndef _READING_H_
|
||||
#define _READING_H_
|
||||
|
||||
void * onewire_init(char *port);
|
||||
void onewire_close(void *handle);
|
||||
reading_t onewire_get(void *handle);
|
||||
#include <sys/time.h>
|
||||
|
||||
#endif /* _1WIRE_H_ */
|
||||
typedef struct meter_reading {
|
||||
float value;
|
||||
struct timeval tv;
|
||||
|
||||
struct meter_reading *next, *prev; /* pointers for linked list */
|
||||
} meter_reading_t;
|
||||
|
||||
#endif /* _READING_H_ */
|
|
@ -23,20 +23,20 @@
|
|||
* along with volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _RAWS0_H_
|
||||
#define _RAWS0_H_
|
||||
#ifndef _S0_H_
|
||||
#define _S0_H_
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
#include "../protocol.h"
|
||||
#include "reading.h"
|
||||
|
||||
typedef struct {
|
||||
int fd; /* file descriptor of port */
|
||||
struct termios oldtio; /* required to reset port */
|
||||
} rawS0_state_t;
|
||||
} meter_handle_s0_t;
|
||||
|
||||
void * rawS0_init(char *port);
|
||||
void rawS0_close(void *handle);
|
||||
reading_t rawS0_get(void *handle);
|
||||
int meter_s0_open(meter_handle_s0_t *handle, char *options);
|
||||
void meter_s0_close(meter_handle_s0_t *handle);
|
||||
meter_reading_t meter_s0_read(meter_handle_s0_t *handle);
|
||||
|
||||
#endif /* _RAWS0_H_ */
|
||||
#endif /* _S0_H_ */
|
|
@ -30,17 +30,27 @@
|
|||
#ifndef _SML_H_
|
||||
#define _SML_H_
|
||||
|
||||
#include "../protocol.h"
|
||||
#define SML_BUFFER_LEN 8096
|
||||
|
||||
#include <sml/sml_file.h>
|
||||
|
||||
#include "reading.h"
|
||||
#include "obis.h"
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
obis_id_t id; /* which OBIS we want to log */
|
||||
float counter; /* Zählerstand */
|
||||
// termios etc..
|
||||
} sml_state_t;
|
||||
} meter_handle_sml_t;
|
||||
|
||||
void * sml_init(char *port);
|
||||
void sml_close(void *handle);
|
||||
reading_t sml_get(void *handle);
|
||||
int sml_open_port(char *device);
|
||||
void sml_transport_receiver(unsigned char *buffer, size_t buffer_len);
|
||||
int meter_sml_open(meter_handle_sml_t *handle, char *options);
|
||||
void meter_sml_close(meter_handle_sml_t *handle);
|
||||
meter_reading_t meter_sml_read(meter_handle_sml_t *handle);
|
||||
|
||||
meter_reading_t meter_sml_parse(sml_file *file, obis_id_t which);
|
||||
|
||||
int meter_sml_open_port(char *device);
|
||||
int meter_sml_open_socket(char *node, char *service);
|
||||
|
||||
#endif /* _SML_H_ */
|
115
include/unit.h
Normal file
115
include/unit.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
* DLMS Units as specified in ISO EN 62056-62 and used by SML
|
||||
*
|
||||
* @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/>.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char code;
|
||||
char *unit;
|
||||
} dlms_unit_t;
|
||||
|
||||
/**
|
||||
* Static lookup table
|
||||
*/
|
||||
dlms_unit_t dlms_units[] = {
|
||||
// code, unit // Quantity Unit name SI definition (comment)
|
||||
//=====================================================================================================
|
||||
{1, "a"}, // time year 52*7*24*60*60 s
|
||||
{2, "mo"}, // time month 31*24*60*60 s
|
||||
{3, "wk"}, // time week 7*24*60*60 s
|
||||
{4, "d"}, // time day 24*60*60 s
|
||||
{5, "h"}, // time hour 60*60 s
|
||||
{6, "min."}, // time min 60 s
|
||||
{7, "s"}, // time (t) second s
|
||||
{8, "°"}, // (phase) angle degree rad*180/π
|
||||
{9, "°C"}, // temperature (T) degree celsius K-273.15
|
||||
{10, "currency"}, // (local) currency
|
||||
{11, "m"}, // length (l) metre m
|
||||
{12, "m/s"}, // speed (v) metre per second m/s
|
||||
{13, "m³"}, // volume (V) cubic metre m³
|
||||
{14, "m³"}, // corrected volume cubic metre m³
|
||||
{15, "m³/h"}, // volume flux cubic metre per hour m³/(60*60s)
|
||||
{16, "m³/h"}, // corrected volume flux cubic metre per hour m³/(60*60s)
|
||||
{17, "m³/d"}, // volume flux m³/(24*60*60s)
|
||||
{18, "m³/d"}, // corrected volume flux m³/(24*60*60s)
|
||||
{19, "l"}, // volume litre 10-3 m³
|
||||
{20, "kg"}, // mass (m) kilogram
|
||||
{21, "N"}, // force (F) newton
|
||||
{22, "Nm"}, // energy newtonmeter J = Nm = Ws
|
||||
{23, "Pa"}, // pressure (p) pascal N/m²
|
||||
{24, "bar"}, // pressure (p) bar 10⁵ N/m²
|
||||
{25, "J"}, // energy joule J = Nm = Ws
|
||||
{26, "J/h"}, // thermal power joule per hour J/(60*60s)
|
||||
{27, "W"}, // active power (P) watt W = J/s
|
||||
{28, "VA"}, // apparent power (S) volt-ampere
|
||||
{29, "var"}, // reactive power (Q) var
|
||||
{30, "Wh"}, // active energy watt-hour W*(60*60s)
|
||||
{31, "VAh"}, // apparent energy volt-ampere-hour VA*(60*60s)
|
||||
{32, "varh"}, // reactive energy var-hour var*(60*60s)
|
||||
{33, "A"}, // current (I) ampere A
|
||||
{34, "C"}, // electrical charge (Q) coulomb C = As
|
||||
{35, "V"}, // voltage (U) volt V
|
||||
{36, "V/m"}, // electr. field strength (E) volt per metre
|
||||
{37, "F"}, // capacitance (C) farad C/V = As/V
|
||||
{38, "Ω"}, // resistance (R) ohm Ω = V/A
|
||||
{39, "Ωm²/m"}, // resistivity (ρ) Ωm
|
||||
{40, "Wb"}, // magnetic flux (Φ) weber Wb = Vs
|
||||
{41, "T"}, // magnetic flux density (B) tesla Wb/m2
|
||||
{42, "A/m"}, // magnetic field strength (H) ampere per metre A/m
|
||||
{43, "H"}, // inductance (L) henry H = Wb/A
|
||||
{44, "Hz"}, // frequency (f, ω) hertz 1/s
|
||||
{45, "1/(Wh)"}, // R_W (Active energy meter constant or pulse value)
|
||||
{46, "1/(varh)"}, // R_B (reactive energy meter constant or pulse value)
|
||||
{47, "1/(VAh)"}, // R_S (apparent energy meter constant or pulse value)
|
||||
{48, "V²h"}, // volt-squared hour volt-squaredhours V²(60*60s)
|
||||
{49, "A²h"}, // ampere-squared hour ampere-squaredhours A²(60*60s)
|
||||
{50, "kg/s"}, // mass flux kilogram per second kg/s
|
||||
{51, "S, mho"}, // conductance siemens 1/Ω
|
||||
{52, "K"}, // temperature (T) kelvin
|
||||
{53, "1/(V²h)"}, // R_U²h (Volt-squared hour meter constant or pulse value)
|
||||
{54, "1/(A²h)"}, // R_I²h (Ampere-squared hour meter constant or pulse value)
|
||||
{55, "1/m³"}, // R_V, meter constant or pulse value (volume)
|
||||
{56, "%"}, // percentage %
|
||||
{57, "Ah"}, // ampere-hours ampere-hour
|
||||
{60, "Wh/m³"}, // energy per volume 3,6*103 J/m³
|
||||
{61, "J/m³"}, // calorific value, wobbe
|
||||
{62, "Mol %"}, // molar fraction of mole percent (Basic gas composition unit)
|
||||
// gas composition
|
||||
{63, "g/m³"}, // mass density, quantity of material (Gas analysis, accompanying elements)
|
||||
{64, "Pa s"}, // dynamic viscosity pascal second (Characteristic of gas stream)
|
||||
{253, "(reserved)"}, // reserved
|
||||
{254, "(other)"}, // other unit
|
||||
{255, "(unitless)"}, // no unit, unitless, count
|
||||
{} // stop condition for iterator
|
||||
};
|
||||
|
||||
char * dlms_get_unit(unsigned char code) {
|
||||
dlms_unit_t *it = dlms_units;
|
||||
do { /* linear search */
|
||||
if (it->code == code) {
|
||||
return it->unit;
|
||||
}
|
||||
} while ((++it)->code);
|
||||
|
||||
return NULL; /* not found */
|
||||
}
|
214
src/Makefile
214
src/Makefile
|
@ -32,10 +32,12 @@ POST_INSTALL = :
|
|||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
bin_PROGRAMS = vzlogger$(EXEEXT)
|
||||
#am__append_1 = local.c
|
||||
#am__append_2 = $(DEPS_LOCAL_LIBS)
|
||||
#am__append_3 = $(DEPS_LOCAL_CFLAGS)
|
||||
#libobis_a_HEADERS = obis.h
|
||||
|
||||
# SML support
|
||||
####################################################################
|
||||
am__append_1 = sml.c
|
||||
am__append_2 = $(DEPS_SML_CFLAGS)
|
||||
subdir = src
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
|
@ -46,20 +48,22 @@ mkinstalldirs = $(install_sh) -d
|
|||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am__vzlogger_SOURCES_DIST = main.c buffer.c api.c channel.c ltqnorm.c \
|
||||
options.c protocols/onewire.c protocols/din62056.c \
|
||||
protocols/rawS0.c protocols/random.c local.c
|
||||
#am__objects_1 = local.$(OBJEXT)
|
||||
am_vzlogger_OBJECTS = main.$(OBJEXT) buffer.$(OBJEXT) api.$(OBJEXT) \
|
||||
channel.$(OBJEXT) ltqnorm.$(OBJEXT) options.$(OBJEXT) \
|
||||
onewire.$(OBJEXT) din62056.$(OBJEXT) rawS0.$(OBJEXT) \
|
||||
random.$(OBJEXT) $(am__objects_1)
|
||||
vzlogger_OBJECTS = $(am_vzlogger_OBJECTS)
|
||||
am__DEPENDENCIES_1 =
|
||||
#am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
|
||||
vzlogger_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
|
||||
LIBRARIES = $(noinst_LIBRARIES)
|
||||
AR = ar
|
||||
ARFLAGS = cru
|
||||
libmeter_a_AR = $(AR) $(ARFLAGS)
|
||||
libmeter_a_DEPENDENCIES = libobis.a
|
||||
am__libmeter_a_SOURCES_DIST = meter.c d0.c s0.c random.c onewire.c \
|
||||
ltqnorm.c sml.c
|
||||
am__objects_1 = sml.$(OBJEXT)
|
||||
am_libmeter_a_OBJECTS = meter.$(OBJEXT) d0.$(OBJEXT) s0.$(OBJEXT) \
|
||||
random.$(OBJEXT) onewire.$(OBJEXT) ltqnorm.$(OBJEXT) \
|
||||
$(am__objects_1)
|
||||
libmeter_a_OBJECTS = $(am_libmeter_a_OBJECTS)
|
||||
libobis_a_AR = $(AR) $(ARFLAGS)
|
||||
libobis_a_LIBADD =
|
||||
am_libobis_a_OBJECTS = obis.$(OBJEXT)
|
||||
libobis_a_OBJECTS = $(am_libobis_a_OBJECTS)
|
||||
DEFAULT_INCLUDES = -I. -I$(top_builddir)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
|
@ -68,8 +72,8 @@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
|||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
SOURCES = $(vzlogger_SOURCES)
|
||||
DIST_SOURCES = $(am__vzlogger_SOURCES_DIST)
|
||||
SOURCES = $(libmeter_a_SOURCES) $(libobis_a_SOURCES)
|
||||
DIST_SOURCES = $(am__libmeter_a_SOURCES_DIST) $(libobis_a_SOURCES)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
@ -87,10 +91,12 @@ CPPFLAGS =
|
|||
CYGPATH_W = echo
|
||||
DEFS = -DHAVE_CONFIG_H
|
||||
DEPDIR = .deps
|
||||
DEPS_CFLAGS = -I/usr/include/json
|
||||
DEPS_LIBS = -ljson -lcurl
|
||||
DEPS_LOCAL_CFLAGS =
|
||||
DEPS_LOCAL_LIBS =
|
||||
DEPS_SML_CFLAGS = -I/usr/include/sml -I/usr/include/uuid
|
||||
DEPS_SML_LIBS = -lsml -luuid
|
||||
DEPS_VZ_CFLAGS = -I/usr/include/json
|
||||
DEPS_VZ_LIBS = -ljson -lcurl
|
||||
ECHO_C =
|
||||
ECHO_N = -n
|
||||
ECHO_T =
|
||||
|
@ -120,6 +126,7 @@ PATH_SEPARATOR = :
|
|||
PKG_CONFIG = /usr/bin/pkg-config
|
||||
PKG_CONFIG_LIBDIR =
|
||||
PKG_CONFIG_PATH =
|
||||
RANLIB = ranlib
|
||||
SET_MAKE =
|
||||
SHELL = /bin/bash
|
||||
STRIP =
|
||||
|
@ -166,15 +173,15 @@ target_alias =
|
|||
top_build_prefix = ../
|
||||
top_builddir = ..
|
||||
top_srcdir = ..
|
||||
|
||||
# what flags you want to pass to the C compiler & linker
|
||||
AM_CFLAGS = -Wall -D_REENTRANT -std=gnu99 $(DEPS_CFLAGS) \
|
||||
$(am__append_3)
|
||||
AM_CFLAGS = -Wall -D_REENTRANT -std=gnu99 $(am__append_2)
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
AM_LDFLAGS =
|
||||
vzlogger_SOURCES = main.c buffer.c api.c channel.c ltqnorm.c options.c \
|
||||
protocols/onewire.c protocols/din62056.c protocols/rawS0.c \
|
||||
protocols/random.c $(am__append_1)
|
||||
vzlogger_LDADD = -lpthread -lm $(DEPS_LIBS) $(am__append_2)
|
||||
noinst_LIBRARIES = libmeter.a libobis.a
|
||||
libmeter_a_SOURCES = meter.c d0.c s0.c random.c onewire.c ltqnorm.c \
|
||||
$(am__append_1)
|
||||
#libmeter_a_HEADERS = meter.h
|
||||
libobis_a_SOURCES = obis.c
|
||||
libmeter_a_LIBADD = libobis.a
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
|
@ -209,46 +216,17 @@ $(top_srcdir)/configure: $(am__configure_deps)
|
|||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed 's/$(EXEEXT)$$//' | \
|
||||
while read p p1; do if test -f $$p; \
|
||||
then echo "$$p"; echo "$$p"; else :; fi; \
|
||||
done | \
|
||||
sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
|
||||
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
|
||||
sed 'N;N;N;s,\n, ,g' | \
|
||||
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
|
||||
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
|
||||
if ($$2 == $$4) files[d] = files[d] " " $$1; \
|
||||
else { print "f", $$3 "/" $$4, $$1; } } \
|
||||
END { for (d in files) print "f", d, files[d] }' | \
|
||||
while read type dir files; do \
|
||||
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
|
||||
test -z "$$files" || { \
|
||||
echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
|
||||
$(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
|
||||
} \
|
||||
; done
|
||||
|
||||
uninstall-binPROGRAMS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
files=`for p in $$list; do echo "$$p"; done | \
|
||||
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
|
||||
-e 's/$$/$(EXEEXT)/' `; \
|
||||
test -n "$$list" || exit 0; \
|
||||
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
|
||||
cd "$(DESTDIR)$(bindir)" && rm -f $$files
|
||||
|
||||
clean-binPROGRAMS:
|
||||
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
|
||||
vzlogger$(EXEEXT): $(vzlogger_OBJECTS) $(vzlogger_DEPENDENCIES)
|
||||
@rm -f vzlogger$(EXEEXT)
|
||||
$(LINK) $(vzlogger_OBJECTS) $(vzlogger_LDADD) $(LIBS)
|
||||
clean-noinstLIBRARIES:
|
||||
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
|
||||
libmeter.a: $(libmeter_a_OBJECTS) $(libmeter_a_DEPENDENCIES)
|
||||
-rm -f libmeter.a
|
||||
$(libmeter_a_AR) libmeter.a $(libmeter_a_OBJECTS) $(libmeter_a_LIBADD)
|
||||
$(RANLIB) libmeter.a
|
||||
libobis.a: $(libobis_a_OBJECTS) $(libobis_a_DEPENDENCIES)
|
||||
-rm -f libobis.a
|
||||
$(libobis_a_AR) libobis.a $(libobis_a_OBJECTS) $(libobis_a_LIBADD)
|
||||
$(RANLIB) libobis.a
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
@ -256,17 +234,14 @@ mostlyclean-compile:
|
|||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
include ./$(DEPDIR)/api.Po
|
||||
include ./$(DEPDIR)/buffer.Po
|
||||
include ./$(DEPDIR)/channel.Po
|
||||
include ./$(DEPDIR)/din62056.Po
|
||||
include ./$(DEPDIR)/local.Po
|
||||
include ./$(DEPDIR)/d0.Po
|
||||
include ./$(DEPDIR)/ltqnorm.Po
|
||||
include ./$(DEPDIR)/main.Po
|
||||
include ./$(DEPDIR)/meter.Po
|
||||
include ./$(DEPDIR)/obis.Po
|
||||
include ./$(DEPDIR)/onewire.Po
|
||||
include ./$(DEPDIR)/options.Po
|
||||
include ./$(DEPDIR)/random.Po
|
||||
include ./$(DEPDIR)/rawS0.Po
|
||||
include ./$(DEPDIR)/s0.Po
|
||||
include ./$(DEPDIR)/sml.Po
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
|
@ -282,62 +257,6 @@ include ./$(DEPDIR)/rawS0.Po
|
|||
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
|
||||
# $(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
onewire.o: protocols/onewire.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT onewire.o -MD -MP -MF $(DEPDIR)/onewire.Tpo -c -o onewire.o `test -f 'protocols/onewire.c' || echo '$(srcdir)/'`protocols/onewire.c
|
||||
$(am__mv) $(DEPDIR)/onewire.Tpo $(DEPDIR)/onewire.Po
|
||||
# source='protocols/onewire.c' object='onewire.o' libtool=no \
|
||||
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
|
||||
# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o onewire.o `test -f 'protocols/onewire.c' || echo '$(srcdir)/'`protocols/onewire.c
|
||||
|
||||
onewire.obj: protocols/onewire.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT onewire.obj -MD -MP -MF $(DEPDIR)/onewire.Tpo -c -o onewire.obj `if test -f 'protocols/onewire.c'; then $(CYGPATH_W) 'protocols/onewire.c'; else $(CYGPATH_W) '$(srcdir)/protocols/onewire.c'; fi`
|
||||
$(am__mv) $(DEPDIR)/onewire.Tpo $(DEPDIR)/onewire.Po
|
||||
# source='protocols/onewire.c' object='onewire.obj' libtool=no \
|
||||
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
|
||||
# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o onewire.obj `if test -f 'protocols/onewire.c'; then $(CYGPATH_W) 'protocols/onewire.c'; else $(CYGPATH_W) '$(srcdir)/protocols/onewire.c'; fi`
|
||||
|
||||
din62056.o: protocols/din62056.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT din62056.o -MD -MP -MF $(DEPDIR)/din62056.Tpo -c -o din62056.o `test -f 'protocols/din62056.c' || echo '$(srcdir)/'`protocols/din62056.c
|
||||
$(am__mv) $(DEPDIR)/din62056.Tpo $(DEPDIR)/din62056.Po
|
||||
# source='protocols/din62056.c' object='din62056.o' libtool=no \
|
||||
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
|
||||
# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o din62056.o `test -f 'protocols/din62056.c' || echo '$(srcdir)/'`protocols/din62056.c
|
||||
|
||||
din62056.obj: protocols/din62056.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT din62056.obj -MD -MP -MF $(DEPDIR)/din62056.Tpo -c -o din62056.obj `if test -f 'protocols/din62056.c'; then $(CYGPATH_W) 'protocols/din62056.c'; else $(CYGPATH_W) '$(srcdir)/protocols/din62056.c'; fi`
|
||||
$(am__mv) $(DEPDIR)/din62056.Tpo $(DEPDIR)/din62056.Po
|
||||
# source='protocols/din62056.c' object='din62056.obj' libtool=no \
|
||||
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
|
||||
# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o din62056.obj `if test -f 'protocols/din62056.c'; then $(CYGPATH_W) 'protocols/din62056.c'; else $(CYGPATH_W) '$(srcdir)/protocols/din62056.c'; fi`
|
||||
|
||||
rawS0.o: protocols/rawS0.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rawS0.o -MD -MP -MF $(DEPDIR)/rawS0.Tpo -c -o rawS0.o `test -f 'protocols/rawS0.c' || echo '$(srcdir)/'`protocols/rawS0.c
|
||||
$(am__mv) $(DEPDIR)/rawS0.Tpo $(DEPDIR)/rawS0.Po
|
||||
# source='protocols/rawS0.c' object='rawS0.o' libtool=no \
|
||||
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
|
||||
# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rawS0.o `test -f 'protocols/rawS0.c' || echo '$(srcdir)/'`protocols/rawS0.c
|
||||
|
||||
rawS0.obj: protocols/rawS0.c
|
||||
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rawS0.obj -MD -MP -MF $(DEPDIR)/rawS0.Tpo -c -o rawS0.obj `if test -f 'protocols/rawS0.c'; then $(CYGPATH_W) 'protocols/rawS0.c'; else $(CYGPATH_W) '$(srcdir)/protocols/rawS0.c'; fi`
|
||||
$(am__mv) $(DEPDIR)/rawS0.Tpo $(DEPDIR)/rawS0.Po
|
||||
# source='protocols/rawS0.c' object='rawS0.obj' libtool=no \
|
||||
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
|
||||
# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rawS0.obj `if test -f 'protocols/rawS0.c'; then $(CYGPATH_W) 'protocols/rawS0.c'; else $(CYGPATH_W) '$(srcdir)/protocols/rawS0.c'; fi`
|
||||
|
||||
random.o: protocols/random.c
|
||||
$(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__mv) $(DEPDIR)/random.Tpo $(DEPDIR)/random.Po
|
||||
# source='protocols/random.c' object='random.o' libtool=no \
|
||||
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
|
||||
# $(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
|
||||
$(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__mv) $(DEPDIR)/random.Tpo $(DEPDIR)/random.Po
|
||||
# source='protocols/random.c' object='random.obj' libtool=no \
|
||||
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
|
||||
# $(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`
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
|
@ -422,11 +341,8 @@ distdir: $(DISTFILES)
|
|||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(PROGRAMS)
|
||||
all-am: Makefile $(LIBRARIES)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(bindir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
|
@ -454,7 +370,7 @@ maintainer-clean-generic:
|
|||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
|
||||
clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
|
@ -480,7 +396,7 @@ install-dvi: install-dvi-am
|
|||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am: install-binPROGRAMS
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
|
@ -519,22 +435,22 @@ ps: ps-am
|
|||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-binPROGRAMS
|
||||
uninstall-am:
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
|
||||
clean-generic ctags distclean distclean-compile \
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
|
||||
clean-noinstLIBRARIES ctags distclean distclean-compile \
|
||||
distclean-generic distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-binPROGRAMS \
|
||||
install-data install-data-am install-dvi install-dvi-am \
|
||||
install-exec install-exec-am install-html install-html-am \
|
||||
install-info install-info-am install-man install-pdf \
|
||||
install-pdf-am install-ps install-ps-am install-strip \
|
||||
installcheck installcheck-am installdirs maintainer-clean \
|
||||
html-am info info-am install install-am install-data \
|
||||
install-data-am install-dvi install-dvi-am install-exec \
|
||||
install-exec-am install-html install-html-am install-info \
|
||||
install-info-am install-man install-pdf install-pdf-am \
|
||||
install-ps install-ps-am install-strip installcheck \
|
||||
installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
|
||||
uninstall-am uninstall-binPROGRAMS
|
||||
uninstall-am
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
# what flags you want to pass to the C compiler & linker
|
||||
AM_CFLAGS = -Wall -D_REENTRANT -std=gnu99 $(DEPS_CFLAGS)
|
||||
AM_CFLAGS = -Wall -D_REENTRANT -std=gnu99
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
AM_LDFLAGS =
|
||||
|
||||
# this lists the binaries to produce, the (non-PHONY, binary) targets in
|
||||
# the previous manual Makefile
|
||||
bin_PROGRAMS = vzlogger
|
||||
noinst_LIBRARIES = libmeter.a libobis.a
|
||||
|
||||
vzlogger_SOURCES = main.c api.c queue.c ltqnorm.c protocols/1wire.c protocols/obis.c protocols/rawS0.c protocols/random.c
|
||||
vzlogger_LDADD = -lpthread -lm $(DEPS_LIBS)
|
||||
libmeter_a_SOURCES = meter.c d0.c s0.c random.c onewire.c ltqnorm.c
|
||||
#libmeter_a_HEADERS = meter.h
|
||||
|
||||
if LOCAL
|
||||
vzlogger_SOURCES += local.c
|
||||
vzlogger_LDADD += $(DEPS_LOCAL_LIBS)
|
||||
AM_CFLAGS += $(DEPS_LOCAL_CFLAGS)
|
||||
libobis_a_SOURCES = obis.c
|
||||
#libobis_a_HEADERS = obis.h
|
||||
|
||||
# SML support
|
||||
####################################################################
|
||||
if SML_SUPPORT
|
||||
libmeter_a_SOURCES += sml.c
|
||||
libmeter_a_LIBADD = libobis.a
|
||||
AM_CFLAGS += $(DEPS_SML_CFLAGS)
|
||||
endif
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/**
|
||||
* OBIS protocol parser
|
||||
* Plaintext protocol according to DIN EN 62056-21
|
||||
*
|
||||
* This protocol uses OBIS to identify the readout data
|
||||
*
|
||||
* This is our example protocol. Use this skeleton to add your own
|
||||
* protocols and meters.
|
||||
|
@ -33,14 +35,21 @@
|
|||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "obis.h"
|
||||
#include "../include/d0.h"
|
||||
|
||||
void * obis_init(char *port) {
|
||||
int meter_d0_open(meter_handle_d0_t *handle, char *options) {
|
||||
struct termios tio;
|
||||
int *fd = malloc(sizeof(int));
|
||||
|
||||
memset(&tio, 0, sizeof(tio));
|
||||
|
||||
|
||||
/* open serial port */
|
||||
handle->fd = open(options, O_RDWR); // | O_NONBLOCK);
|
||||
|
||||
if (handle->fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO save oldtio
|
||||
|
||||
tio.c_iflag = 0;
|
||||
tio.c_oflag = 0;
|
||||
tio.c_cflag = CS7|CREAD|CLOCAL; // 7n1, see termios.h for more information
|
||||
|
@ -48,26 +57,22 @@ void * obis_init(char *port) {
|
|||
tio.c_cc[VMIN] = 1;
|
||||
tio.c_cc[VTIME] = 5;
|
||||
|
||||
*fd = open(port, O_RDWR); // | O_NONBLOCK);
|
||||
cfsetospeed(&tio, B9600); // 9600 baud
|
||||
cfsetispeed(&tio, B9600); // 9600 baud
|
||||
|
||||
return (void *) fd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void obis_close(void *handle) {
|
||||
int *fd = (int *) handle;
|
||||
|
||||
close(*fd);
|
||||
free(handle);
|
||||
void meter_d0_close(meter_handle_d0_t *handle) {
|
||||
close(handle->fd);
|
||||
}
|
||||
|
||||
reading_t obis_get(void *handle) {
|
||||
reading_t rd;
|
||||
|
||||
meter_reading_t meter_d0_read(meter_handle_d0_t *handle) {
|
||||
meter_reading_t rd;
|
||||
|
||||
rd.value = 33.3334;
|
||||
gettimeofday(&rd.tv, NULL);
|
||||
|
||||
|
||||
return rd;
|
||||
}
|
||||
|
464
src/main.c
464
src/main.c
|
@ -1,464 +0,0 @@
|
|||
/**
|
||||
* Main source file
|
||||
*
|
||||
* @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 <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <curl/curl.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#ifdef LOCAL
|
||||
#include <microhttpd.h>
|
||||
#include "local.h"
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
#include "queue.h"
|
||||
#include "api.h"
|
||||
|
||||
#include "protocols/obis.h"
|
||||
#include "protocols/1wire.h"
|
||||
#include "protocols/rawS0.h"
|
||||
#include "protocols/random.h"
|
||||
|
||||
/**
|
||||
* List of available protocols
|
||||
* incl. function pointers
|
||||
*/
|
||||
static protocol_t protocols[] = {
|
||||
{"1wire", "Dallas 1-Wire sensors (via OWFS)", onewire_get, onewire_init, onewire_close, SENSOR},
|
||||
// {"obis", "Plaintext OBIS", obis_get, obis_init, obis_close, SENSOR},
|
||||
{"random", "Random walk", random_get, random_init, random_close, SENSOR},
|
||||
{"rawS0", "S0 on RS232", rawS0_get, rawS0_init, rawS0_close, METER},
|
||||
// {"sml", "Smart Meter Language", sml_get, sml_init, sml_close, SENSOR},
|
||||
// {"fluksousb", "FluksoUSB board", flukso_get, flukso_init, flukso_close, SENSOR},
|
||||
{NULL} /* stop condition for iterator */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Command line options
|
||||
*/
|
||||
static struct option long_options[] = {
|
||||
{"config", required_argument, 0, 'c'},
|
||||
{"daemon", required_argument, 0, 'd'},
|
||||
#ifdef LOCAL
|
||||
{"local", no_argument, 0, 'l'},
|
||||
{"local-port", required_argument, 0, 'p'},
|
||||
#endif /* LOCAL */
|
||||
{"verbose", optional_argument, 0, 'v'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"version", no_argument, 0, 'V'},
|
||||
{NULL} /* stop condition for iterator */
|
||||
};
|
||||
|
||||
/**
|
||||
* Descriptions vor command line options
|
||||
*/
|
||||
static char *long_options_descs[] = {
|
||||
"config file with channel -> uuid mapping",
|
||||
"run as daemon",
|
||||
#ifdef LOCAL
|
||||
"activate local interface (tiny webserver)",
|
||||
"TCP port for local interface",
|
||||
#endif /* LOCAL */
|
||||
"enable verbose output",
|
||||
"show this help",
|
||||
"show version of vzlogger",
|
||||
NULL /* stop condition for iterator */
|
||||
};
|
||||
|
||||
/*
|
||||
* Global variables
|
||||
*/
|
||||
channel_t chans[MAX_CHANNELS]; // TODO use dynamic allocation
|
||||
options_t opts = { /* setting default options */
|
||||
NULL, /* config file */
|
||||
8080, /* port for local interface */
|
||||
0, /* debug level / verbosity */
|
||||
FALSE, /* daemon mode */
|
||||
FALSE /* local interface */
|
||||
};
|
||||
|
||||
/**
|
||||
* Print available options and some other usefull information
|
||||
*/
|
||||
void usage(char * argv[]) {
|
||||
char ** desc = long_options_descs;
|
||||
struct option * op = long_options;
|
||||
protocol_t * prot = protocols;
|
||||
|
||||
printf("Usage: %s [options]\n\n", argv[0]);
|
||||
printf(" following options are available:\n");
|
||||
|
||||
while (op->name && desc) {
|
||||
printf("\t-%c, --%-12s\t%s\n", op->val, op->name, *desc);
|
||||
op++;
|
||||
desc++;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf(" following protocol types are supported:\n");
|
||||
|
||||
while (prot->name) {
|
||||
printf("\t%-12s\t%s\n", prot->name, prot->desc);
|
||||
prot++;
|
||||
}
|
||||
|
||||
printf("\n%s - volkszaehler.org logging utility\n", PACKAGE_STRING);
|
||||
printf("by Steffen Vogel <stv0g@0l.de>\n");
|
||||
printf("send bugreports to %s\n", PACKAGE_BUGREPORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to log notices and errors
|
||||
*
|
||||
* @param ch could be NULL for general messages
|
||||
* @todo integrate into syslog
|
||||
*/
|
||||
void print(int level, char * format, channel_t *ch, ... ) {
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
va_list args;
|
||||
|
||||
struct timeval now;
|
||||
struct tm * timeinfo;
|
||||
char buffer[16];
|
||||
|
||||
if (level <= (signed int) opts.verbose) {
|
||||
gettimeofday(&now, NULL);
|
||||
timeinfo = localtime(&now.tv_sec);
|
||||
|
||||
strftime(buffer, 16, "%b %d %H:%M:%S", timeinfo);
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
fprintf((level > 0) ? stdout : stderr, "[%s.%3lu]", buffer, now.tv_usec / 1000);
|
||||
|
||||
if (ch != NULL) {
|
||||
fprintf((level > 0) ? stdout : stderr, "[ch#%i]\t", ch->id);
|
||||
}
|
||||
else {
|
||||
fprintf((level > 0) ? stdout : stderr, "\t\t");
|
||||
}
|
||||
|
||||
va_start(args, ch);
|
||||
vfprintf((level > 0) ? stdout : stderr, format, args);
|
||||
va_end(args);
|
||||
fprintf((level > 0) ? stdout : stderr, "\n");
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse options from command line
|
||||
*/
|
||||
void parse_options(int argc, char * argv[], options_t * opts) {
|
||||
while (TRUE) {
|
||||
/* getopt_long stores the option index here. */
|
||||
int option_index = 0;
|
||||
|
||||
int c = getopt_long(argc, argv, "i:c:p:lhVdv::", long_options, &option_index);
|
||||
|
||||
/* detect the end of the options. */
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'v':
|
||||
opts->verbose = (optarg == NULL) ? 1 : atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
opts->local = TRUE;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
opts->daemon = TRUE;
|
||||
break;
|
||||
|
||||
case 'p': /* port for local interface */
|
||||
opts->port = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'c': /* read config file */
|
||||
opts->config = (char *) malloc(strlen(optarg)+1);
|
||||
strcpy(opts->config, optarg);
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
printf("%s\n", VERSION);
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
usage(argv);
|
||||
exit((c == '?') ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
if (opts->config == NULL) { /* search for config file */
|
||||
if (access("vzlogger.conf", R_OK) == 0) {
|
||||
opts->config = "vzlogger.conf";
|
||||
}
|
||||
else if (access("/etc/vzlogger.conf", R_OK) == 0) {
|
||||
opts->config = "/etc/vzlogger.conf";
|
||||
}
|
||||
else { /* search in home directory */
|
||||
char *home_config = malloc(255);
|
||||
strcat(home_config, getenv("HOME")); /* get home dir */
|
||||
strcat(home_config, "/.vzlogger.conf"); /* append my filename */
|
||||
|
||||
if (access(home_config, R_OK) == 0) {
|
||||
opts->config = home_config;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int parse_channels(char *filename, channel_t *chans) {
|
||||
FILE *file = fopen(filename, "r"); /* open configuration */
|
||||
|
||||
if (!filename) { /* nothing found */
|
||||
print(-1, "No config file found! Please specify with --config!\n", NULL);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (file == NULL) {
|
||||
perror(filename); /* why didn't the file open? */
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else {
|
||||
print(2, "Start parsing configuration from %s", NULL, filename);
|
||||
}
|
||||
|
||||
char line[256];
|
||||
int chan_num = 0, line_num = 1;
|
||||
|
||||
while (chan_num < MAX_CHANNELS && fgets(line, sizeof line, file) != NULL) { /* read a line */
|
||||
if (line[0] == ';' || line[0] == '\n') continue; /* skip comments */
|
||||
|
||||
channel_t ch = {
|
||||
chan_num,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
protocols
|
||||
};
|
||||
|
||||
char *tok = strtok(line, " \t");
|
||||
|
||||
for (int i = 0; i < 7 && tok != NULL; i++) {
|
||||
size_t len = strlen(tok);
|
||||
|
||||
switch(i) {
|
||||
case 0: /* protocol */
|
||||
while (ch.prot->name && strcmp(ch.prot->name, tok) != 0) ch.prot++; /* linear search */
|
||||
|
||||
if (ch.prot == NULL) {
|
||||
print(-1, "Invalid protocol: %s in %s:%i", NULL, tok, filename, line_num);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: /* interval */
|
||||
ch.interval = strtol(tok, (char **) NULL, 10);
|
||||
|
||||
if (errno == EINVAL || errno == ERANGE) {
|
||||
print(-1, "Invalid interval: %s in %s:%i", NULL, tok, filename, line_num);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* uuid */
|
||||
if (len == 0) { // TODO add uuid validation
|
||||
print(-1, "Missing uuid in %s:%i", NULL, filename, line_num);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ch.uuid = (char *) malloc(len+1); /* including string termination */
|
||||
strcpy(ch.uuid, tok);
|
||||
break;
|
||||
|
||||
case 3: /* middleware */
|
||||
if (len == 0) { // TODO add uuid validation
|
||||
print(-1, "Missing middleware in %s:%i", NULL, filename, line_num);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ch.middleware = (char *) malloc(len+1); /* including string termination */
|
||||
strcpy(ch.middleware, tok);
|
||||
break;
|
||||
|
||||
case 4: /* options */
|
||||
ch.options = (char *) malloc(len);
|
||||
strncpy(ch.options, tok, len-1);
|
||||
ch.options[len-1] = '\0'; /* replace \n by \0 */
|
||||
break;
|
||||
}
|
||||
|
||||
tok = strtok(NULL, " \t");
|
||||
}
|
||||
|
||||
print(1, "Parsed ch#%i (protocol=%s interval=%i uuid=%s middleware=%s options=%s)", &ch, ch.id, ch.prot->name, ch.interval, ch.uuid, ch.middleware, ch.options);
|
||||
chans[chan_num] = ch;
|
||||
|
||||
chan_num++;
|
||||
line_num++;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
return chan_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read thread
|
||||
*
|
||||
* Aquires reading from meters/sensors
|
||||
*/
|
||||
void *read_thread(void *arg) {
|
||||
channel_t *ch = (channel_t *) arg; /* casting argument */
|
||||
print(1, "Started reading thread", ch);
|
||||
|
||||
/* initalize channel */
|
||||
ch->handle = ch->prot->init_func(ch->options); /* init sensor/meter */
|
||||
|
||||
do {
|
||||
/**
|
||||
* Aquire reading,
|
||||
* may be blocking if interpreter == METER
|
||||
*/
|
||||
reading_t rd = ch->prot->read_func(ch->handle);
|
||||
|
||||
pthread_mutex_lock(&ch->mutex);
|
||||
if (!queue_push(&ch->queue, rd)) {
|
||||
print(6, "Warning queue is full, discarding first tuple!", ch);
|
||||
}
|
||||
pthread_cond_broadcast(&ch->condition); /* notify webserver and logging thread */
|
||||
pthread_mutex_unlock(&ch->mutex);
|
||||
|
||||
print(1, "Value read: %.1f", ch, rd.value);
|
||||
|
||||
/* Debugging */
|
||||
if (opts.verbose >= 10) {
|
||||
char *queue_str = queue_print(&ch->queue);
|
||||
print(10, "Queue dump: %s write_p = %lu\t read_p = %lu", ch, queue_str, ch->queue.write_p, ch->queue.read_p);
|
||||
free(queue_str);
|
||||
}
|
||||
|
||||
if (ch->prot->interpreter != METER) { /* for meters, the read_func call is blocking */
|
||||
print(5, "Next reading in %i seconds", ch, ch->interval);
|
||||
sleep(ch->interval); /* else sleep and restart aquisition */
|
||||
}
|
||||
|
||||
pthread_testcancel(); /* test for cancelation request */
|
||||
} while (opts.daemon || opts.local);
|
||||
|
||||
/* close channel */
|
||||
ch->prot->close_func(ch->handle);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main loop
|
||||
*/
|
||||
int main(int argc, char *argv[]) {
|
||||
int num_chans;
|
||||
|
||||
#ifdef LOCAL
|
||||
struct MHD_Daemon *httpd_handle = NULL;
|
||||
#endif /* LOCAL */
|
||||
|
||||
parse_options(argc, argv, &opts); /* parse command line arguments */
|
||||
num_chans = parse_channels(opts.config, chans); /* parse channels from configuration */
|
||||
|
||||
print(1, "Started %s with verbosity level %i", NULL, argv[0], opts.verbose);
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL); /* global intialization for all threads */
|
||||
|
||||
for (int i = 0; i < num_chans; i++) {
|
||||
channel_t *ch = &chans[i];
|
||||
|
||||
/* initialize queue to buffer data */
|
||||
queue_init(&ch->queue, (BUFFER_LENGTH / ch->interval) + 1);
|
||||
|
||||
/* initialize thread syncronization helpers */
|
||||
pthread_mutex_init(&ch->mutex, NULL);
|
||||
pthread_cond_init(&ch->condition, NULL);
|
||||
|
||||
/* start threads */
|
||||
pthread_create(&ch->reading_thread, NULL, read_thread, (void *) ch);
|
||||
pthread_create(&ch->logging_thread, NULL, api_thread, (void *) ch);
|
||||
}
|
||||
|
||||
#ifdef LOCAL
|
||||
/* start webserver for local interface */
|
||||
if (opts.local) {
|
||||
httpd_handle = MHD_start_daemon(
|
||||
MHD_USE_THREAD_PER_CONNECTION,
|
||||
opts.port,
|
||||
NULL, NULL,
|
||||
handle_request,
|
||||
&num_chans,
|
||||
MHD_OPTION_END
|
||||
);
|
||||
}
|
||||
#endif /* LOCAL */
|
||||
|
||||
/* wait for all threads to terminate */
|
||||
// TODO bind signal for termination
|
||||
for (int i = 0; i < num_chans; i++) {
|
||||
channel_t * ch = &chans[i];
|
||||
|
||||
pthread_join(ch->reading_thread, NULL);
|
||||
pthread_join(ch->logging_thread, NULL);
|
||||
|
||||
// TODO close protocol handles
|
||||
|
||||
free(ch->middleware);
|
||||
free(ch->uuid);
|
||||
free(ch->options);
|
||||
queue_free(&ch->queue);
|
||||
|
||||
pthread_cond_destroy(&ch->condition);
|
||||
pthread_mutex_destroy(&ch->mutex);
|
||||
}
|
||||
|
||||
#ifdef LOCAL
|
||||
/* stop webserver */
|
||||
if (httpd_handle) {
|
||||
MHD_stop_daemon(httpd_handle);
|
||||
}
|
||||
#endif /* LOCAL */
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
92
src/main.h
92
src/main.h
|
@ -1,92 +0,0 @@
|
|||
/**
|
||||
* Main header file
|
||||
*
|
||||
* @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 _MAIN_H_
|
||||
#define _MAIN_H_
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
#include "protocol.h"
|
||||
#include "queue.h"
|
||||
|
||||
#define MAX_CHANNELS 16
|
||||
|
||||
#define RETRY_PAUSE 10 //600 /* seconds to wait after failed request */
|
||||
#define BUFFER_LENGTH 60 //600 /* in seconds */
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Datatype for every channel
|
||||
*/
|
||||
typedef struct {
|
||||
int id; /* only for internal usage & debugging */
|
||||
|
||||
char *middleware;
|
||||
char *uuid;
|
||||
char *options;
|
||||
|
||||
unsigned int interval;
|
||||
|
||||
void *handle; /* handle to store connection status */
|
||||
protocol_t *prot; /* pointer to protocol */
|
||||
queue_t queue; /* circular queue to buffer readings */
|
||||
|
||||
pthread_t reading_thread; /* pthread for asynchronus reading */
|
||||
pthread_t logging_thread; /* pthread for asynchronus logging */
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t condition;
|
||||
} channel_t;
|
||||
|
||||
/**
|
||||
* Options from command line
|
||||
*/
|
||||
typedef struct {
|
||||
char * config; /* path to config file */
|
||||
unsigned int port; /* tcp port for local interface */
|
||||
unsigned int verbose; /* verbosity level */
|
||||
|
||||
/* boolean bitfields, at the end of struct */
|
||||
int daemon:1;
|
||||
int local:1; /* enable local interface */
|
||||
} options_t;
|
||||
|
||||
/* Prototypes */
|
||||
void parse_options(int argc, char * argv[], options_t *opts);
|
||||
int parse_channels(char * filename, channel_t *chans);
|
||||
void print(int level, char * format, channel_t *ch, ... );
|
||||
void usage(char ** argv);
|
||||
|
||||
#endif /* _MAIN_H_ */
|
126
src/meter.c
Normal file
126
src/meter.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
/**
|
||||
* Protocol interface
|
||||
*
|
||||
* @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 <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../include/meter.h"
|
||||
|
||||
/* List of available meter types */
|
||||
meter_type_t meter_types[] = {
|
||||
{ONEWIRE, "onewire", "Dallas 1-Wire sensors (via OWFS)", 1},
|
||||
{RANDOM, "random", "Random walk", 1},
|
||||
{S0, "S0", "S0 on RS232", 0},
|
||||
// {D0, "D0", "On-site plaintext protocol (DIN EN 62056-21)", 0},
|
||||
#ifdef SML_SUPPORT
|
||||
{SML, "sml", "Smart Meter Language", 0},
|
||||
#endif /* SML_SUPPORT */
|
||||
{} /* stop condition for iterator */
|
||||
};
|
||||
|
||||
void meter_init(meter_t *meter, meter_type_t *type, char *options) {
|
||||
meter->type = type;
|
||||
meter->options = strdup(options);
|
||||
}
|
||||
|
||||
void meter_free(meter_t *meter) {
|
||||
free(meter->options);
|
||||
}
|
||||
|
||||
int meter_open(meter_t *meter) {
|
||||
switch (meter->type->tag) {
|
||||
case RANDOM:
|
||||
return meter_random_open(&meter->handle.random, meter->options);
|
||||
|
||||
case S0:
|
||||
return meter_s0_open(&meter->handle.s0, meter->options);
|
||||
|
||||
case D0:
|
||||
return meter_d0_open(&meter->handle.d0, meter->options);
|
||||
|
||||
#ifdef SML_SUPPORT
|
||||
case SML:
|
||||
return meter_sml_open(&meter->handle.sml, meter->options);
|
||||
#endif /* SML_SUPPORT */
|
||||
|
||||
case ONEWIRE:
|
||||
return meter_onewire_open(&meter->handle.onewire, meter->options);
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void meter_close(meter_t *meter) {
|
||||
switch (meter->type->tag) {
|
||||
case RANDOM:
|
||||
meter_random_close(&meter->handle.random);
|
||||
break;
|
||||
|
||||
case S0:
|
||||
meter_s0_close(&meter->handle.s0);
|
||||
break;
|
||||
|
||||
case D0:
|
||||
meter_d0_close(&meter->handle.d0);
|
||||
break;
|
||||
|
||||
#ifdef SML_SUPPORT
|
||||
case SML:
|
||||
meter_sml_close(&meter->handle.sml);
|
||||
break;
|
||||
#endif /* SML_SUPPORT */
|
||||
|
||||
case ONEWIRE:
|
||||
meter_onewire_close(&meter->handle.onewire);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
meter_reading_t meter_read(meter_t *meter) {
|
||||
meter_reading_t rd;
|
||||
|
||||
switch (meter->type->tag) {
|
||||
case RANDOM:
|
||||
return meter_random_read(&meter->handle.random);
|
||||
|
||||
case S0:
|
||||
return meter_s0_read(&meter->handle.s0);
|
||||
|
||||
case D0:
|
||||
return meter_d0_read(&meter->handle.d0);
|
||||
|
||||
#ifdef SML_SUPPORT
|
||||
case SML:
|
||||
return meter_sml_read(&meter->handle.sml);
|
||||
#endif /* SML_SUPPORT */
|
||||
|
||||
case ONEWIRE:
|
||||
return meter_onewire_read(&meter->handle.onewire);
|
||||
|
||||
default:
|
||||
return rd;
|
||||
}
|
||||
}
|
110
src/obis.c
Normal file
110
src/obis.c
Normal file
|
@ -0,0 +1,110 @@
|
|||
/**
|
||||
* OBIS IDs as specified in DIN EN 62056-61
|
||||
*
|
||||
* @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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include "../include/obis.h"
|
||||
|
||||
obis_alias_t obis_aliases[] = {
|
||||
// A B C D E F abbreviation description
|
||||
//=====================================================================================
|
||||
{{"\x81\x81\xC7\x82\x03\xFF"}, "voltage", ""},
|
||||
{{"\x81\x81\xC7\x82\x03\xFF"}, "current", ""},
|
||||
{{"\x81\x81\xC7\x82\x03\xFF"}, "frequency", ""},
|
||||
{{"\x81\x81\xC7\x82\x03\xFF"}, "powerfactor", ""},
|
||||
|
||||
/* ESYQ3B (Easymeter Q3B) */
|
||||
{{"\x81\x81\xC7\x82\x03\xFF"}, "vendor", "vendor specific"},
|
||||
{{"\x01\x00\x01\x08\x00\xFF"}, "counter", "Active Power Counter Total"},
|
||||
{{"\x01\x00\x01\x08\x01\xFF"}, "counter-tarif1","Active Power Counter Tariff 1"},
|
||||
{{"\x01\x00\x01\x08\x02\xFF"}, "counter-tarif2","Active Power Counter Tariff 2"},
|
||||
{{"\x01\x00\x01\x07\x00\xFF"}, "power", "Active Power Instantaneous value Total"},
|
||||
{{"\x01\x00\x15\x07\x00\xFF"}, "power-l1", "L1 Active Power Instantaneous value Total"},
|
||||
{{"\x01\x00\x29\x07\x00\xFF"}, "power-l2", "L1 Active Power Instantaneous value Total"},
|
||||
{{"\x01\x00\x3D\x07\x00\xFF"}, "power-l2", "L3 Active Power Instantaneous value Total"},
|
||||
{{"\x01\x00\x60\x05\x05\xFF"}, "status", "Meter status flag"},
|
||||
{} /* stop condition for iterator */
|
||||
};
|
||||
|
||||
obis_id_t obis_init(unsigned char *raw) {
|
||||
obis_id_t id;
|
||||
memcpy(id.raw, raw, 6);
|
||||
return id;
|
||||
}
|
||||
|
||||
obis_id_t obis_parse(char *str) {
|
||||
obis_id_t id;
|
||||
regex_t expr;
|
||||
regmatch_t matches[7];
|
||||
|
||||
regcomp(&expr, "^([0-9])-([a-f0-9]{,2}):([a-f0-9]{,2})\\.([a-f0-9]{,2})\\.([a-f0-9]{,2})(\\*[a-f0-9]{,2})?$", REG_EXTENDED | REG_ICASE);
|
||||
|
||||
if (regexec(&expr, str, 7, matches, 0) == 0) { /* found string in OBIS notation */
|
||||
for (int i=0; i<6; i++) {
|
||||
if (matches[i+1].rm_so != -1) {
|
||||
id.raw[i] = strtoul(str+matches[i+1].rm_so, NULL, 16);
|
||||
}
|
||||
else {
|
||||
id.raw[i] = 0xff; /* default value */
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* looking for alias */
|
||||
obis_alias_t *it = obis_aliases;
|
||||
do { /* linear search */
|
||||
if (strcmp(it->name, str) == 0) {
|
||||
return it->id;
|
||||
}
|
||||
} while ((++it)->name);
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
char obis_is_manufacturer_specific(obis_id_t id) {
|
||||
return (
|
||||
(id.groups.channel >= 128 && id.groups.channel <= 199) ||
|
||||
(id.groups.indicator >= 128 && id.groups.indicator <= 199) ||
|
||||
(id.groups.indicator == 240) ||
|
||||
(id.groups.mode >= 128 && id.groups.mode <= 254) ||
|
||||
(id.groups.quantities >= 128 && id.groups.quantities <= 254) ||
|
||||
(id.groups.storage >= 128 && id.groups.storage <= 254)
|
||||
);
|
||||
}
|
||||
|
||||
int obis_unparse(obis_id_t id, char *buffer) {
|
||||
return sprintf(buffer, "%x-%x:%x.%x.%x*%x",
|
||||
id.groups.media,
|
||||
id.groups.channel,
|
||||
id.groups.indicator,
|
||||
id.groups.mode,
|
||||
id.groups.quantities,
|
||||
id.groups.storage
|
||||
);
|
||||
}
|
||||
|
|
@ -23,12 +23,9 @@
|
|||
* along with volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../main.h"
|
||||
#include "../protocol.h"
|
||||
#include "1wire.h"
|
||||
#include "../include/onewire.h"
|
||||
|
||||
/**
|
||||
* Initialize sensor
|
||||
|
@ -36,35 +33,27 @@
|
|||
* @param address path to the sensor in the owfs
|
||||
* @return pointer to file descriptor
|
||||
*/
|
||||
void * onewire_init(char *address) {
|
||||
FILE * fd = fopen(address, "r");
|
||||
int meter_onewire_open(meter_handle_onewire_t *handle, char *options) {
|
||||
handle->file = fopen(options, "r");
|
||||
|
||||
if (fd == NULL) {
|
||||
perror(address);
|
||||
print(-1, "Failed to open sensor: %s", NULL, address);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return (void *) fd;
|
||||
return (handle->file == NULL) ? -1 : 0;
|
||||
}
|
||||
|
||||
void onewire_close(void *handle) {
|
||||
fclose((FILE *) handle);
|
||||
void meter_onewire_close(meter_handle_onewire_t *handle) {
|
||||
fclose(handle->file);
|
||||
}
|
||||
|
||||
reading_t onewire_get(void *handle) {
|
||||
reading_t rd;
|
||||
meter_reading_t meter_onewire_read(meter_handle_onewire_t *handle) {
|
||||
meter_reading_t rd;
|
||||
char buffer[16];
|
||||
int bytes;
|
||||
|
||||
do {
|
||||
rewind((FILE *) handle);
|
||||
bytes = fread(buffer, 1, 16, (FILE *) handle);
|
||||
rewind(handle->file);
|
||||
bytes = fread(buffer, 1, 16, handle->file);
|
||||
buffer[bytes] = '\0'; /* zero terminated, required? */
|
||||
|
||||
if (bytes) {
|
||||
print(4, "Read from sensor file: %s", NULL, buffer);
|
||||
|
||||
rd.value = strtof(buffer, NULL);
|
||||
gettimeofday(&rd.tv, NULL);
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
#ifndef _PROTOCOL_H_
|
||||
#define _PROTOCOL_H_
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
typedef struct {
|
||||
float value;
|
||||
struct timeval tv;
|
||||
} reading_t;
|
||||
|
||||
typedef void *(*ifp_t)(char *options);
|
||||
typedef void (*cfp_t)(void *handle);
|
||||
typedef reading_t (*rfp_t)(void *handle);
|
||||
|
||||
typedef enum {
|
||||
MODE_METER,
|
||||
MODE_SENSOR
|
||||
} mode_t;
|
||||
|
||||
typedef struct {
|
||||
char * name; /* short identifier for protocol */
|
||||
char * desc; /* more detailed description */
|
||||
rfp_t read_func; /* function pointer to read data */
|
||||
ifp_t init_func; /* function pointer to init a channel */
|
||||
cfp_t close_func; /* function pointer to close a channel */
|
||||
mode_t mode; /* should we wait for next pulse? */
|
||||
} protocol_t;
|
||||
|
||||
#endif /* _PROTOCOL_H_ */
|
|
@ -1,99 +0,0 @@
|
|||
/**
|
||||
* S0 Hutschienenzähler directly connected to an rs232 port
|
||||
*
|
||||
* @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 <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../main.h"
|
||||
#include "../protocol.h"
|
||||
#include "rawS0.h"
|
||||
|
||||
/**
|
||||
* Setup serial port
|
||||
*/
|
||||
void * rawS0_init(char *port) {
|
||||
rawS0_state_t *state;
|
||||
struct termios newtio;
|
||||
|
||||
/* initialize handle */
|
||||
state = malloc(sizeof(rawS0_state_t));
|
||||
|
||||
state->fd = open(port, O_RDWR | O_NOCTTY);
|
||||
if (state->fd < 0) {
|
||||
char err[255];
|
||||
strerror_r(errno, err, 255);
|
||||
print(-1, "%s: %s", NULL, port, err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
tcgetattr(state->fd, &state->oldtio); /* save current port settings */
|
||||
|
||||
|
||||
/* configure port */
|
||||
memset(&newtio, 0, sizeof(struct termios));
|
||||
|
||||
newtio.c_cflag = B300 | CS8 | CLOCAL | CREAD;
|
||||
newtio.c_iflag = IGNPAR;
|
||||
newtio.c_oflag = 0;
|
||||
newtio.c_lflag = 0; /* set input mode (non-canonical, no echo,...) */
|
||||
newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
|
||||
newtio.c_cc[VMIN] = 1; /* blocking read until data is received */
|
||||
|
||||
/* apply configuration */
|
||||
tcsetattr(state->fd, TCSANOW, &newtio);
|
||||
|
||||
return (void *) state;
|
||||
}
|
||||
|
||||
void rawS0_close(void *handle) {
|
||||
rawS0_state_t *state = (rawS0_state_t *) handle;
|
||||
|
||||
tcsetattr(state->fd, TCSANOW, &state->oldtio);
|
||||
|
||||
close(state->fd);
|
||||
free(handle);
|
||||
}
|
||||
|
||||
reading_t rawS0_get(void *handle) {
|
||||
char buf[255];
|
||||
|
||||
rawS0_state_t *state = (rawS0_state_t *) handle;
|
||||
reading_t rd;
|
||||
|
||||
rd.value = 1;
|
||||
|
||||
tcflush(state->fd, TCIOFLUSH);
|
||||
|
||||
read(state->fd, buf, 255); /* blocking until one character/pulse is read */
|
||||
gettimeofday(&rd.tv, NULL);
|
||||
|
||||
/* wait some ms for debouncing */
|
||||
usleep(30000);
|
||||
|
||||
return rd;
|
||||
}
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
/**
|
||||
* Wrapper around libsml
|
||||
*
|
||||
* @package vzlogger
|
||||
* @copyright Copyright (c) 2011, The volkszaehler.org project
|
||||
* @copyright Copyright (c) 2011, DAI-Labor, TU-Berlin
|
||||
* @license http://www.gnu.org/licenses/gpl.txt GNU Public License
|
||||
* @author Steffen Vogel <info@steffenvogel.de>
|
||||
* @author Juri Glass
|
||||
* @author Mathias Runge
|
||||
* @author Nadim El Sayed
|
||||
*/
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <termios.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <sml/sml_file.h>
|
||||
#include <sml/sml_transport.h>
|
||||
|
||||
int sml_init(char *device) {
|
||||
sml_state_t *state;
|
||||
|
||||
/* initialize handle */
|
||||
state = malloc(sizeof(sml_state_t));
|
||||
|
||||
/* this example assumes that a EDL21 meter sending SML messages via a
|
||||
* serial device. Adjust as needed. */
|
||||
int fd = serial_port_open(device);
|
||||
|
||||
if (fd > 0) {
|
||||
// start thread
|
||||
|
||||
/* listen on the serial device, this call is blocking */
|
||||
sml_transport_listen(fd, &transport_receiver);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
void sml_close(void *handle) {
|
||||
|
||||
}
|
||||
|
||||
reading_t sml_get(void *handle) {
|
||||
|
||||
}
|
||||
|
||||
void sml_transport_receiver(unsigned char *buffer, size_t buffer_len) {
|
||||
// the buffer contains the whole message, with transport escape sequences.
|
||||
// these escape sequences are stripped here.
|
||||
sml_file *file = sml_file_parse(buffer + 8, buffer_len - 16);
|
||||
// the sml file is parsed now
|
||||
|
||||
// read here some values ..
|
||||
|
||||
// this prints some information about the file
|
||||
sml_file_print(file);
|
||||
|
||||
// free the malloc'd memory
|
||||
sml_file_free(file);
|
||||
}
|
||||
|
||||
int sml_open_port(char *device) {
|
||||
int bits;
|
||||
struct termios config;
|
||||
memset(&config, 0, sizeof(config));
|
||||
|
||||
int fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
if (fd < 0) {
|
||||
printf("error: open(%s): %s\n", device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// set RTS
|
||||
ioctl(fd, TIOCMGET, &bits);
|
||||
bits |= TIOCM_RTS;
|
||||
ioctl(fd, TIOCMSET, &bits);
|
||||
|
||||
tcgetattr( fd, &config ) ;
|
||||
|
||||
// set 8-N-1
|
||||
config.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
|
||||
config.c_oflag &= ~OPOST;
|
||||
config.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
|
||||
config.c_cflag &= ~(CSIZE | PARENB | PARODD | CSTOPB);
|
||||
config.c_cflag |= CS8;
|
||||
|
||||
// set speed to 9600 baud
|
||||
cfsetispeed( &config, B9600);
|
||||
cfsetospeed( &config, B9600);
|
||||
|
||||
tcsetattr(fd, TCSANOW, &config);
|
||||
return fd;
|
||||
}
|
63
src/queue.c
63
src/queue.c
|
@ -1,63 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "queue.h"
|
||||
|
||||
bool_t queue_init(queue_t *q, size_t size) {
|
||||
q->buf = malloc(sizeof(reading_t) * size); /* keep one slot open */
|
||||
|
||||
if (q->buf) {
|
||||
q->size = size;
|
||||
q->read_p = q->write_p = 0; /* queue is empty */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else { /* cannot allocate memory */
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
bool_t queue_is_empty(queue_t *q) {
|
||||
return (q->read_p == q->write_p);
|
||||
}
|
||||
|
||||
void queue_free(queue_t *q) {
|
||||
queue_clear(q);
|
||||
free(q->buf);
|
||||
}
|
||||
|
||||
void queue_clear(queue_t *q) {
|
||||
q->read_p = q->write_p;
|
||||
}
|
||||
|
||||
bool_t queue_push(queue_t *q, reading_t rd) {
|
||||
q->buf[q->write_p] = rd; /* copy data to buffer */
|
||||
q->write_p++; /* increment write pointer */
|
||||
q->write_p %= q->size;
|
||||
|
||||
if (q->read_p == q->write_p) { /* queue full */
|
||||
q->read_p++; /* discarding first tuple */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool_t queue_get(queue_t *q, size_t index, reading_t *rd) {
|
||||
*rd = q->buf[index];
|
||||
|
||||
return (index < q->size);
|
||||
}
|
||||
|
||||
char * queue_print(queue_t *q) {
|
||||
char *buf = malloc(q->size * 6);
|
||||
char *ret = buf;
|
||||
|
||||
buf += sprintf(buf, "[%.1f", q->buf[0].value);
|
||||
for (int i = 1; i < q->size; i++) {
|
||||
buf += sprintf(buf, "|%.2f", q->buf[i].value);
|
||||
}
|
||||
buf += sprintf(buf, "]");
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -22,52 +22,42 @@
|
|||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "../main.h"
|
||||
#include "../protocol.h"
|
||||
#include "random.h"
|
||||
#include "../include/random.h"
|
||||
|
||||
/**
|
||||
* Initialize prng
|
||||
* @return random_state_t
|
||||
*/
|
||||
void * random_init(char *options) {
|
||||
random_state_t *state;
|
||||
state = malloc(sizeof(random_state_t));
|
||||
int meter_random_open(meter_handle_random_t *handle, char *options) {
|
||||
srand(time(NULL)); /* initialize PNRG */
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
state->min = 0; // TODO parse from options
|
||||
state->max = strtof(options, NULL);
|
||||
state->last = state->max * ((float) rand() / RAND_MAX); /* start value */
|
||||
|
||||
return (void *) state;
|
||||
handle->min = 0; // TODO parse from options
|
||||
handle->max = strtof(options, NULL);
|
||||
handle->last = handle->max * ((float) rand() / RAND_MAX); /* start value */
|
||||
|
||||
return 0; /* always succeeds */
|
||||
}
|
||||
|
||||
void random_close(void *handle) {
|
||||
free(handle);
|
||||
void meter_random_close(meter_handle_random_t *handle) {
|
||||
/* nothing todo */
|
||||
}
|
||||
|
||||
reading_t random_get(void *handle) {
|
||||
random_state_t *state = (random_state_t *) handle;
|
||||
reading_t rd;
|
||||
|
||||
state->last += ltqnorm((float) rand() / RAND_MAX);
|
||||
|
||||
meter_reading_t meter_random_read(meter_handle_random_t *handle) {
|
||||
meter_reading_t rd;
|
||||
|
||||
handle->last += ltqnorm((float) rand() / RAND_MAX);
|
||||
|
||||
/* check bounaries */
|
||||
if (state->last > state->max) {
|
||||
state->last = state->max;
|
||||
if (handle->last > handle->max) {
|
||||
handle->last = handle->max;
|
||||
}
|
||||
else if (state->last < state->min) {
|
||||
state->last = state->min;
|
||||
else if (handle->last < handle->min) {
|
||||
handle->last = handle->min;
|
||||
}
|
||||
|
||||
rd.value = state->last;
|
||||
|
||||
rd.value = handle->last;
|
||||
gettimeofday(&rd.tv, NULL);
|
||||
|
||||
|
||||
return rd;
|
||||
}
|
91
src/s0.c
Normal file
91
src/s0.c
Normal file
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* S0 Hutschienenzähler directly connected to an rs232 port
|
||||
*
|
||||
* @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 <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../include/s0.h"
|
||||
|
||||
/**
|
||||
* Setup serial port
|
||||
*/
|
||||
int meter_s0_open(meter_handle_s0_t *handle, char *options) {
|
||||
/* open port */
|
||||
handle->fd = open(options, O_RDWR | O_NOCTTY);
|
||||
|
||||
if (handle->fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* save current port settings */
|
||||
tcgetattr(handle->fd, &handle->oldtio);
|
||||
|
||||
|
||||
/* configure port */
|
||||
struct termios tio;
|
||||
memset(&tio, 0, sizeof(struct termios));
|
||||
|
||||
tio.c_cflag = B300 | CS8 | CLOCAL | CREAD;
|
||||
tio.c_iflag = IGNPAR;
|
||||
tio.c_oflag = 0;
|
||||
tio.c_lflag = 0; /* set input mode (non-canonical, no echo,...) */
|
||||
tio.c_cc[VTIME] = 0; /* inter-character timer unused */
|
||||
tio.c_cc[VMIN] = 1; /* blocking read until data is received */
|
||||
|
||||
/* apply configuration */
|
||||
tcsetattr(handle->fd, TCSANOW, &tio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void meter_s0_close(meter_handle_s0_t *handle) {
|
||||
/* reset serial port */
|
||||
tcsetattr(handle->fd, TCSANOW, &handle->oldtio);
|
||||
|
||||
/* close serial port */
|
||||
close(handle->fd);
|
||||
}
|
||||
|
||||
meter_reading_t meter_s0_read(meter_handle_s0_t *handle) {
|
||||
char buf[8];
|
||||
|
||||
meter_reading_t rd;
|
||||
|
||||
rd.value = 1;
|
||||
|
||||
tcflush(handle->fd, TCIOFLUSH);
|
||||
|
||||
read(handle->fd, buf, 8); /* blocking until one character/pulse is read */
|
||||
gettimeofday(&rd.tv, NULL);
|
||||
|
||||
/* wait some ms for debouncing */
|
||||
usleep(30000);
|
||||
|
||||
return rd;
|
||||
}
|
||||
|
191
src/sml.c
Normal file
191
src/sml.c
Normal file
|
@ -0,0 +1,191 @@
|
|||
/**
|
||||
* Wrapper around libsml
|
||||
*
|
||||
* @package vzlogger
|
||||
* @copyright Copyright (c) 2011, The volkszaehler.org project
|
||||
* @copyright Copyright (c) 2011, DAI-Labor, TU-Berlin
|
||||
* @license http://www.gnu.org/licenses/gpl.txt GNU Public License
|
||||
* @author Steffen Vogel <info@steffenvogel.de>
|
||||
* @author Juri Glass
|
||||
* @author Mathias Runge
|
||||
* @author Nadim El Sayed
|
||||
*/
|
||||
/*
|
||||
* 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 <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
/* serial port */
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
|
||||
/* socket */
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
/* sml stuff */
|
||||
#include <sml/sml_file.h>
|
||||
#include <sml/sml_transport.h>
|
||||
|
||||
#include "../include/sml.h"
|
||||
#include "../include/obis.h"
|
||||
|
||||
int meter_sml_open(meter_handle_sml_t *handle, char *options) {
|
||||
char *node = strsep(&options, ":");
|
||||
char *service = strsep(&options, ":");
|
||||
|
||||
handle->id = obis_parse(options);
|
||||
handle->fd = meter_sml_open_socket(node, service);
|
||||
//handle->fd = meter_sml_open_port(options);
|
||||
|
||||
return (handle->fd < 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
void meter_sml_close(meter_handle_sml_t *handle) {
|
||||
// TODO reset serial port
|
||||
close(handle->fd);
|
||||
}
|
||||
|
||||
meter_reading_t meter_sml_read(meter_handle_sml_t *handle) {
|
||||
unsigned char buffer[SML_BUFFER_LEN];
|
||||
size_t bytes;
|
||||
sml_file *sml_file;
|
||||
meter_reading_t rd;
|
||||
|
||||
/* blocking read from fd */
|
||||
bytes = sml_transport_read(handle->fd, buffer, SML_BUFFER_LEN);
|
||||
|
||||
/* sml parsing & stripping escape sequences */
|
||||
sml_file = sml_file_parse(buffer + 8, bytes - 16);
|
||||
|
||||
/* extraction of readings */
|
||||
rd = meter_sml_parse(sml_file, handle->id);
|
||||
|
||||
/* free the malloc'd memory */
|
||||
sml_file_free(sml_file);
|
||||
|
||||
return rd;
|
||||
}
|
||||
|
||||
int meter_sml_open_socket(char *node, char *service) {
|
||||
struct sockaddr_in sin;
|
||||
struct addrinfo *ais;
|
||||
int fd, res;
|
||||
|
||||
getaddrinfo(node, service, NULL, &ais);
|
||||
memcpy(&sin, ais->ai_addr, ais->ai_addrlen);
|
||||
|
||||
fd = socket(PF_INET, SOCK_STREAM, 0);
|
||||
|
||||
res = connect(fd, (struct sockaddr *) &sin, sizeof(sin));
|
||||
|
||||
return (res < 0) ? -1 : fd;
|
||||
}
|
||||
|
||||
int meter_sml_open_port(char *device) {
|
||||
int bits;
|
||||
struct termios config;
|
||||
memset(&config, 0, sizeof(config));
|
||||
|
||||
int fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
if (fd < 0) {
|
||||
printf("error: open(%s): %s\n", device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// set RTS
|
||||
ioctl(fd, TIOCMGET, &bits);
|
||||
bits |= TIOCM_RTS;
|
||||
ioctl(fd, TIOCMSET, &bits);
|
||||
|
||||
tcgetattr( fd, &config ) ;
|
||||
|
||||
// set 8-N-1
|
||||
config.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
|
||||
config.c_oflag &= ~OPOST;
|
||||
config.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
|
||||
config.c_cflag &= ~(CSIZE | PARENB | PARODD | CSTOPB);
|
||||
config.c_cflag |= CS8;
|
||||
|
||||
// set speed to 9600 baud
|
||||
cfsetispeed( &config, B9600);
|
||||
cfsetospeed( &config, B9600);
|
||||
|
||||
tcsetattr(fd, TCSANOW, &config);
|
||||
return fd;
|
||||
}
|
||||
|
||||
meter_reading_t meter_sml_parse(sml_file *file, obis_id_t which) {
|
||||
meter_reading_t rd;
|
||||
|
||||
for (int i = 0; i < file->messages_len; i++) {
|
||||
sml_message *message = file->messages[i];
|
||||
|
||||
if (*message->message_body->tag == SML_MESSAGE_GET_LIST_RESPONSE) {
|
||||
sml_list *entry;
|
||||
sml_get_list_response *body;
|
||||
|
||||
body = (sml_get_list_response *) message->message_body->data;
|
||||
|
||||
for (entry = body->val_list; entry != NULL; entry = entry->next) { /* linked list */
|
||||
obis_id_t id = obis_init(entry->obj_name->str);
|
||||
|
||||
if (obis_compare(which, id) == 0) {
|
||||
//int unit = (entry->unit) ? *entry->unit : 0;
|
||||
int scaler = (entry->scaler) ? *entry->scaler : 1;
|
||||
|
||||
switch (entry->value->type) {
|
||||
case 0x51: rd.value = *entry->value->data.int8; break;
|
||||
case 0x52: rd.value = *entry->value->data.int16; break;
|
||||
case 0x54: rd.value = *entry->value->data.int32; break;
|
||||
case 0x58: rd.value = *entry->value->data.int64; break;
|
||||
case 0x61: rd.value = *entry->value->data.uint8; break;
|
||||
case 0x62: rd.value = *entry->value->data.uint16; break;
|
||||
case 0x64: rd.value = *entry->value->data.uint32; break;
|
||||
case 0x68: rd.value = *entry->value->data.uint64; break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unknown value type: %x", entry->value->type);
|
||||
}
|
||||
|
||||
/* apply scaler */
|
||||
rd.value *= pow(10, scaler);
|
||||
|
||||
|
||||
/* get time */
|
||||
if (entry->val_time) { // TODO handle SML_TIME_SEC_INDEX
|
||||
rd.tv.tv_sec = *entry->val_time->data.timestamp;
|
||||
rd.tv.tv_usec = 0;
|
||||
}
|
||||
else {
|
||||
gettimeofday(&rd.tv, NULL);
|
||||
}
|
||||
|
||||
return rd; /* skipping rest */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rd;
|
||||
}
|
Loading…
Add table
Reference in a new issue