just to much to describe it ;)

- added new structure
- added SML support
This commit is contained in:
Steffen Vogel 2011-09-10 00:00:26 +02:00
parent 47f5ee3e2d
commit c217a9f1d7
51 changed files with 3854 additions and 1408 deletions

View file

@ -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.

View file

@ -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
View 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
View 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
View 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
View 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
View 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

View file

@ -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 */

View file

@ -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
View 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
View 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
View 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
View 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_ */

View file

@ -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;
}

View file

@ -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_ */

View file

@ -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
View 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
View 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

Binary file not shown.

192
bin/vzlogger/vzlogger.c Normal file
View 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
View 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_ */

View file

@ -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

696
configure vendored

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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 =

View file

@ -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

View file

@ -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
View 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
View 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
View 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
View 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_ */

View file

@ -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_ */

View file

@ -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_ */

View file

@ -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
View 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, ""}, // volume (V) cubic metre m³
{14, ""}, // 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 */
}

View file

@ -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.

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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
View 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
View 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
);
}

View file

@ -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);
}

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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
View 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
View 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;
}