Merge branch 'master' of github.com:volkszaehler/volkszaehler.org

Conflicts:
	misc/controller/vzlogger/etc/vzlogger.conf
	misc/controller/vzlogger/src/protocols/1wire.c
This commit is contained in:
Steffen Vogel 2011-08-05 01:31:08 +02:00
commit 98bde59791
16 changed files with 376 additions and 195 deletions

View file

@ -139,6 +139,8 @@ DEFS = @DEFS@
DEPDIR = @DEPDIR@
DEPS_CFLAGS = @DEPS_CFLAGS@
DEPS_LIBS = @DEPS_LIBS@
DEPS_LOCAL_CFLAGS = @DEPS_LOCAL_CFLAGS@
DEPS_LOCAL_LIBS = @DEPS_LOCAL_LIBS@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@

View file

@ -72,8 +72,8 @@
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* No-debug Mode */
#undef NDEBUG
/* Local interface */
#undef LOCAL
/* Name of package */
#undef PACKAGE

192
configure vendored
View file

@ -2,7 +2,7 @@
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.67 for vzlogger 0.2.
#
# Report bugs to <info@steffenvogel.de>.
# Report bugs to <http://bugs.volkszaehler.org>.
#
#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@ -231,10 +231,10 @@ fi
$as_echo "$0: be upgraded to zsh 4.3.4 or later."
else
$as_echo "$0: Please tell bug-autoconf@gnu.org and
$0: info@steffenvogel.de about your system, including any
$0: error possibly output before this message. Then install
$0: a modern shell, or manually run the script under such a
$0: shell if you do have one."
$0: http://bugs.volkszaehler.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
fi
exit 1
fi
@ -554,7 +554,7 @@ PACKAGE_NAME='vzlogger'
PACKAGE_TARNAME='vzlogger'
PACKAGE_VERSION='0.2'
PACKAGE_STRING='vzlogger 0.2'
PACKAGE_BUGREPORT='info@steffenvogel.de'
PACKAGE_BUGREPORT='http://bugs.volkszaehler.org'
PACKAGE_URL=''
ac_unique_file="src/main.c"
@ -597,6 +597,10 @@ ac_includes_default="\
ac_subst_vars='am__EXEEXT_FALSE
am__EXEEXT_TRUE
LTLIBOBJS
DEPS_LOCAL_LIBS
DEPS_LOCAL_CFLAGS
LOCAL_FALSE
LOCAL_TRUE
LIBOBJS
EGREP
GREP
@ -687,6 +691,7 @@ ac_subst_files=''
ac_user_opts='
enable_option_checking
enable_dependency_tracking
enable_local_interface
enable_debug
'
ac_precious_vars='build_alias
@ -702,7 +707,9 @@ PKG_CONFIG_PATH
PKG_CONFIG_LIBDIR
DEPS_CFLAGS
DEPS_LIBS
CPP'
CPP
DEPS_LOCAL_CFLAGS
DEPS_LOCAL_LIBS'
# Initialize some variables set by options.
@ -1321,6 +1328,8 @@ Optional Features:
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--disable-dependency-tracking speeds up one-time build
--enable-dependency-tracking do not reject slow dependency extractors
--enable-local-interface
enable support for local HTTPd (def=no)
--enable-debug enable debug data generation (def=no)
Some influential environment variables:
@ -1339,11 +1348,15 @@ Some influential environment variables:
DEPS_CFLAGS C compiler flags for DEPS, overriding pkg-config
DEPS_LIBS linker flags for DEPS, overriding pkg-config
CPP C preprocessor
DEPS_LOCAL_CFLAGS
C compiler flags for DEPS_LOCAL, overriding pkg-config
DEPS_LOCAL_LIBS
linker flags for DEPS_LOCAL, overriding pkg-config
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
Report bugs to <info@steffenvogel.de>.
Report bugs to <http://bugs.volkszaehler.org>.
_ACEOF
ac_status=$?
fi
@ -1565,9 +1578,9 @@ $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
( $as_echo "## ----------------------------------- ##
## Report this to info@steffenvogel.de ##
## ----------------------------------- ##"
( $as_echo "## ------------------------------------------- ##
## Report this to http://bugs.volkszaehler.org ##
## ------------------------------------------- ##"
) | sed "s/^/$as_me: WARNING: /" >&2
;;
esac
@ -3846,12 +3859,12 @@ if test -n "$DEPS_CFLAGS"; then
pkg_cv_DEPS_CFLAGS="$DEPS_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3\""; } >&5
($PKG_CONFIG --exists --print-errors "json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3") 2>&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"json >= 0.9 libcurl >= 7.21.0\""; } >&5
($PKG_CONFIG --exists --print-errors "json >= 0.9 libcurl >= 7.21.0") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_DEPS_CFLAGS=`$PKG_CONFIG --cflags "json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3" 2>/dev/null`
pkg_cv_DEPS_CFLAGS=`$PKG_CONFIG --cflags "json >= 0.9 libcurl >= 7.21.0" 2>/dev/null`
else
pkg_failed=yes
fi
@ -3862,12 +3875,12 @@ if test -n "$DEPS_LIBS"; then
pkg_cv_DEPS_LIBS="$DEPS_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3\""; } >&5
($PKG_CONFIG --exists --print-errors "json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3") 2>&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"json >= 0.9 libcurl >= 7.21.0\""; } >&5
($PKG_CONFIG --exists --print-errors "json >= 0.9 libcurl >= 7.21.0") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_DEPS_LIBS=`$PKG_CONFIG --libs "json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3" 2>/dev/null`
pkg_cv_DEPS_LIBS=`$PKG_CONFIG --libs "json >= 0.9 libcurl >= 7.21.0" 2>/dev/null`
else
pkg_failed=yes
fi
@ -3887,14 +3900,14 @@ else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
DEPS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3" 2>&1`
DEPS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "json >= 0.9 libcurl >= 7.21.0" 2>&1`
else
DEPS_PKG_ERRORS=`$PKG_CONFIG --print-errors "json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3" 2>&1`
DEPS_PKG_ERRORS=`$PKG_CONFIG --print-errors "json >= 0.9 libcurl >= 7.21.0" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$DEPS_PKG_ERRORS" >&5
as_fn_error $? "Package requirements (json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3) were not met:
as_fn_error $? "Package requirements (json >= 0.9 libcurl >= 7.21.0) were not met:
$DEPS_PKG_ERRORS
@ -4604,28 +4617,135 @@ fi
done
# debug compilation support
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build with debug information" >&5
$as_echo_n "checking whether to build with debug information... " >&6; }
# Check whether --enable-debug was given.
if test "${enable_debug+set}" = set; then :
enableval=$enable_debug; debugit="$enableval"
# local interface support
# Check whether --enable-local-interface was given.
if test "${enable_local_interface+set}" = set; then :
enableval=$enable_local_interface; local=true
else
debugit=no
local=false
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $debugit" >&5
$as_echo "$debugit" >&6; }
if test x"$debugit" = x"yes"; then
if test x$local = xtrue; then
LOCAL_TRUE=
LOCAL_FALSE='#'
else
LOCAL_TRUE='#'
LOCAL_FALSE=
fi
if test x"$local" = x"true"; then
$as_echo "#define LOCAL /**/" >>confdefs.h
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DEPS_LOCAL" >&5
$as_echo_n "checking for DEPS_LOCAL... " >&6; }
if test -n "$DEPS_LOCAL_CFLAGS"; then
pkg_cv_DEPS_LOCAL_CFLAGS="$DEPS_LOCAL_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libmicrohttpd >= 0.9.3\""; } >&5
($PKG_CONFIG --exists --print-errors "libmicrohttpd >= 0.9.3") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_DEPS_LOCAL_CFLAGS=`$PKG_CONFIG --cflags "libmicrohttpd >= 0.9.3" 2>/dev/null`
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test -n "$DEPS_LOCAL_LIBS"; then
pkg_cv_DEPS_LOCAL_LIBS="$DEPS_LOCAL_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libmicrohttpd >= 0.9.3\""; } >&5
($PKG_CONFIG --exists --print-errors "libmicrohttpd >= 0.9.3") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_DEPS_LOCAL_LIBS=`$PKG_CONFIG --libs "libmicrohttpd >= 0.9.3" 2>/dev/null`
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test $pkg_failed = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
DEPS_LOCAL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libmicrohttpd >= 0.9.3" 2>&1`
else
DEPS_LOCAL_PKG_ERRORS=`$PKG_CONFIG --print-errors "libmicrohttpd >= 0.9.3" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$DEPS_LOCAL_PKG_ERRORS" >&5
as_fn_error $? "Package requirements (libmicrohttpd >= 0.9.3) were not met:
$DEPS_LOCAL_PKG_ERRORS
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
Alternatively, you may set the environment variables DEPS_LOCAL_CFLAGS
and DEPS_LOCAL_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details." "$LINENO" 5
elif test $pkg_failed = untried; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.
Alternatively, you may set the environment variables DEPS_LOCAL_CFLAGS
and DEPS_LOCAL_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
To get pkg-config, see <http://pkg-config.freedesktop.org/>.
See \`config.log' for more details" "$LINENO" 5 ; }
else
DEPS_LOCAL_CFLAGS=$pkg_cv_DEPS_LOCAL_CFLAGS
DEPS_LOCAL_LIBS=$pkg_cv_DEPS_LOCAL_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
fi
fi
# debug compilation support
# Check whether --enable-debug was given.
if test "${enable_debug+set}" = set; then :
enableval=$enable_debug; debug=true
else
debug=false
fi
if test x"$debug" = x"true"; then
$as_echo "#define DEBUG /**/" >>confdefs.h
AM_CXXFLAGS="$AM_CXXFLAGS -g -Wall -Werror -Wno-uninitialized -O0"
else
$as_echo "#define NDEBUG /**/" >>confdefs.h
AM_CXXFLAGS="$AM_CXXFLAGS -O3"
fi
@ -4743,6 +4863,10 @@ if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${LOCAL_TRUE}" && test -z "${LOCAL_FALSE}"; then
as_fn_error $? "conditional \"LOCAL\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
: ${CONFIG_STATUS=./config.status}
ac_write_fail=0
@ -5211,7 +5335,7 @@ $config_headers
Configuration commands:
$config_commands
Report bugs to <info@steffenvogel.de>."
Report bugs to <http://bugs.volkszaehler.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1

View file

@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.67])
AC_INIT(vzlogger, 0.2, info@steffenvogel.de)
AC_INIT([vzlogger], [0.2], [http://bugs.volkszaehler.org])
AM_INIT_AUTOMAKE(vzlogger, 0.2)
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
@ -12,7 +12,7 @@ AC_CONFIG_FILES([Makefile src/Makefile docs/Makefile])
AC_PROG_CC
# Checks for libraries.
PKG_CHECK_MODULES([DEPS], [json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3])
PKG_CHECK_MODULES([DEPS], [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,20 +27,32 @@ AC_FUNC_REALLOC
AC_FUNC_STRERROR_R
AC_CHECK_FUNCS([gettimeofday memset sqrt strchr strtol])
# debug compilation support
AC_MSG_CHECKING([whether to build with debug information])
AC_ARG_ENABLE([debug],
[AS_HELP_STRING([--enable-debug],
[enable debug data generation (def=no)])],
[debugit="$enableval"],
[debugit=no])
AC_MSG_RESULT([$debugit])
# local interface support
AC_ARG_ENABLE(
[local-interface],
[AS_HELP_STRING([--enable-local-interface], [enable support for local HTTPd (def=no)])],
[local=true],
[local=false]
)
if test x"$debugit" = x"yes"; then
AM_CONDITIONAL([LOCAL], [test x$local = xtrue])
if test x"$local" = x"true"; then
AC_DEFINE([LOCAL],[],[Local interface])
PKG_CHECK_MODULES([DEPS_LOCAL], [libmicrohttpd >= 0.9.3])
fi
# debug compilation support
AC_ARG_ENABLE(
[debug],
[AS_HELP_STRING([--enable-debug], [enable debug data generation (def=no)])],
[debug=true],
[debug=false]
)
if test x"$debug" = x"true"; then
AC_DEFINE([DEBUG],[],[Debug Mode])
AM_CXXFLAGS="$AM_CXXFLAGS -g -Wall -Werror -Wno-uninitialized -O0"
else
AC_DEFINE([NDEBUG],[],[No-debug Mode])
AM_CXXFLAGS="$AM_CXXFLAGS -O3"
fi

7
debian/changelog vendored
View file

@ -1,3 +1,10 @@
vzlogger (0.2-1) stable; urgency=low
* Fixed some bugs after porting to armel architecture
* Improved init script
-- Steffen Vogel <info@steffenvogel.de> Thu, 04 Aug 2011 20:00:25 +0200
vzlogger (0.2) unstable; urgency=low
* Initial Release.

1
debian/control vendored
View file

@ -9,6 +9,7 @@ Vcs-Git: git://github.com/volkszaehler/volkszaehler.org.git
Vcs-Browser: http://github.com/volkszaehler/volkszaehler.org/tree/master/misc/controller/vzlogger/
Package: vzlogger
Version: 0.2-1
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: program for logging measurements to an volkszaehler.org middelware

View file

@ -14,8 +14,8 @@
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC=vzlogger # Introduce a short description here
NAME=vzlogger # Introduce the short server's name here
DAEMON=/usr/sbin/vzlogger # Introduce the server's location here
DAEMON_ARGS="" # Arguments to run the daemon with
DAEMON=/usr/bin/vzlogger # Introduce the server's location here
DAEMON_ARGS="-d" # Arguments to run the daemon with
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
@ -41,9 +41,9 @@ do_start()
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
start-stop-daemon --background --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
start-stop-daemon --background --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
$DAEMON_ARGS \
|| return 2
# Add code here, if necessary, that waits for the process to be ready

View file

@ -85,6 +85,8 @@ DEFS = @DEFS@
DEPDIR = @DEPDIR@
DEPS_CFLAGS = @DEPS_CFLAGS@
DEPS_LIBS = @DEPS_LIBS@
DEPS_LOCAL_CFLAGS = @DEPS_LOCAL_CFLAGS@
DEPS_LOCAL_LIBS = @DEPS_LOCAL_LIBS@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@

View file

@ -3,10 +3,8 @@
; use ; to introduce a comment
;prot intval uuid middleware options
;1wire 3 52960fe0-8882-11e0-b356-85eba28c1922 http://localhost/workspace/volkszaehler.org/htdocs/middleware /mnt/1wire/10.12E6D3000800/temperature
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 3 52960fe0-8882-11e0-b356-85eba28c1922 http://localhost/workspace/volkszaehler.org/htdocs/middleware 40
;random 7 473d35b0-945b-11e0-beb1-918e8c2ce5a0 http://volkszaehler.org/demo/middleware.php 10
random 5 e4ff8f70-9f79-11e0-b44c-d1ce78df8288 http://localhost/workspace/volkszaehler.org/htdocs/middleware 40

View file

@ -6,5 +6,11 @@ AM_LDFLAGS =
# the previous manual Makefile
bin_PROGRAMS = vzlogger
vzlogger_SOURCES = main.c api.c local.c queue.c ltqnorm.c protocols/1wire.c protocols/obis.c protocols/rawS0.c protocols/random.c
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)
if LOCAL
vzlogger_SOURCES += local.c
vzlogger_LDADD += $(DEPS_LOCAL_LIBS)
AM_CFLAGS += $(DEPS_LOCAL_CFLAGS)
endif

View file

@ -33,6 +33,9 @@ NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
bin_PROGRAMS = vzlogger$(EXEEXT)
@LOCAL_TRUE@am__append_1 = local.c
@LOCAL_TRUE@am__append_2 = $(DEPS_LOCAL_LIBS)
@LOCAL_TRUE@am__append_3 = $(DEPS_LOCAL_CFLAGS)
subdir = src
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@ -45,12 +48,17 @@ CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)"
PROGRAMS = $(bin_PROGRAMS)
am_vzlogger_OBJECTS = main.$(OBJEXT) api.$(OBJEXT) local.$(OBJEXT) \
queue.$(OBJEXT) ltqnorm.$(OBJEXT) 1wire.$(OBJEXT) \
obis.$(OBJEXT) rawS0.$(OBJEXT) random.$(OBJEXT)
am__vzlogger_SOURCES_DIST = main.c api.c queue.c ltqnorm.c \
protocols/1wire.c protocols/obis.c protocols/rawS0.c \
protocols/random.c local.c
@LOCAL_TRUE@am__objects_1 = local.$(OBJEXT)
am_vzlogger_OBJECTS = main.$(OBJEXT) api.$(OBJEXT) queue.$(OBJEXT) \
ltqnorm.$(OBJEXT) 1wire.$(OBJEXT) obis.$(OBJEXT) \
rawS0.$(OBJEXT) random.$(OBJEXT) $(am__objects_1)
vzlogger_OBJECTS = $(am_vzlogger_OBJECTS)
am__DEPENDENCIES_1 =
vzlogger_DEPENDENCIES = $(am__DEPENDENCIES_1)
@LOCAL_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
vzlogger_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@ -60,7 +68,7 @@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(vzlogger_SOURCES)
DIST_SOURCES = $(vzlogger_SOURCES)
DIST_SOURCES = $(am__vzlogger_SOURCES_DIST)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@ -80,6 +88,8 @@ DEFS = @DEFS@
DEPDIR = @DEPDIR@
DEPS_CFLAGS = @DEPS_CFLAGS@
DEPS_LIBS = @DEPS_LIBS@
DEPS_LOCAL_CFLAGS = @DEPS_LOCAL_CFLAGS@
DEPS_LOCAL_LIBS = @DEPS_LOCAL_LIBS@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
@ -157,10 +167,13 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
# 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 $(DEPS_CFLAGS) \
$(am__append_3)
AM_LDFLAGS =
vzlogger_SOURCES = main.c api.c local.c queue.c ltqnorm.c protocols/1wire.c protocols/obis.c protocols/rawS0.c protocols/random.c
vzlogger_LDADD = -lpthread -lm $(DEPS_LIBS)
vzlogger_SOURCES = main.c api.c queue.c ltqnorm.c protocols/1wire.c \
protocols/obis.c protocols/rawS0.c protocols/random.c \
$(am__append_1)
vzlogger_LDADD = -lpthread -lm $(DEPS_LIBS) $(am__append_2)
all: all-am
.SUFFIXES:

View file

@ -38,48 +38,48 @@ extern options_t opts;
*/
int curl_custom_debug_callback(CURL *curl, curl_infotype type, char *data, size_t size, void *ch) {
char *end = strchr(data, '\n');
if (data == end) return 0; /* skip empty line */
switch (type) {
case CURLINFO_TEXT:
case CURLINFO_END:
if (end) *end = '\0'; /* terminate without \n */
print(3, "CURL: %.*s", (channel_t *) 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);
break;
case CURLINFO_SSL_DATA_OUT:
case CURLINFO_DATA_OUT:
print(6, "CURL: Sent %lu bytes.. ", (channel_t *) ch, (unsigned long) size);
break;
case CURLINFO_HEADER_IN:
case CURLINFO_HEADER_OUT:
break;
}
return 0;
}
size_t curl_custom_write_callback(void *ptr, size_t size, size_t nmemb, void *data) {
size_t realsize = size * nmemb;
CURLresponse *response = (CURLresponse *) data;
response->data = realloc(response->data, response->size + realsize + 1);
if (response->data == NULL) { /* out of memory! */
if (response->data == NULL) { /* out of memory! */
print(-1, "Not enough memory", NULL);
exit(EXIT_FAILURE);
}
memcpy(&(response->data[response->size]), ptr, realsize);
response->size += realsize;
response->data[response->size] = 0;
return realsize;
}
@ -87,30 +87,30 @@ json_object * api_json_tuples(channel_t *ch, bool_t all) {
reading_t rd;
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);
if (rd.tv.tv_sec) { /* skip empty buffers */
struct json_object *json_tuple = json_object_new_array();
unsigned long timestamp = rd.tv.tv_sec * 1000 + rd.tv.tv_usec / 1000;
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(rd.value));
json_object_array_add(json_tuples, json_tuple);
}
index++;
index %= ch->queue.size; /* increment pointer */
} while (index != end);
return json_tuples;
}
@ -118,11 +118,11 @@ CURL * api_curl_init(channel_t *ch) {
CURL *curl;
struct curl_slist *header = NULL;
char url[255], agent[255];
/* prepare header & url */
sprintf(agent, "User-Agent: vzlogger/%s (%s)", VZ_VERSION, curl_version()); /* build user agent */
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 */
header = curl_slist_append(header, "Content-type: application/json");
header = curl_slist_append(header, "Accept: application/json");
header = curl_slist_append(header, agent);
@ -132,9 +132,9 @@ CURL * api_curl_init(channel_t *ch) {
print(-1, "CURL: cannot create handle", ch);
exit(EXIT_FAILURE);
}
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
curl_easy_setopt(curl, CURLOPT_VERBOSE, (int) opts.verbose);
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_custom_debug_callback);
curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *) ch);
@ -150,10 +150,10 @@ void api_parse_exception(CURLresponse response, char *err) {
json_obj = json_tokener_parse_ex(json_tok, response.data, response.size);
if (json_tok->err == json_tokener_success) {
json_obj = json_object_object_get(json_obj, "exception");
if (json_obj) {
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, "type")),
json_object_get_string(json_object_object_get(json_obj, "message"))
);
}
@ -164,7 +164,7 @@ void api_parse_exception(CURLresponse response, char *err) {
else {
strcpy(err, json_tokener_errors[json_tok->err]);
}
json_tokener_free(json_tok);
}
@ -177,36 +177,36 @@ void api_parse_exception(CURLresponse response, char *err) {
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);
curl = api_curl_init(ch);
do { /* start thread mainloop */
CURLresponse response;
long int http_code, curl_code;
char *json_str;
/* 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_unlock(&ch->mutex);
json_str = json_object_to_json_string(api_json_tuples(ch, FALSE));
print(1, "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);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &response);
curl_code = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
if (curl_code == CURLE_OK && http_code == 200) { /* everything is ok */
print(1, "Request succeeded with code: %i", ch, http_code);
queue_clear(&ch->queue);
@ -220,7 +220,7 @@ void * api_thread(void *arg) {
api_parse_exception(response, err);
print(-1, "Invalid middlware response: %s", ch, err);
}
print(2, "Sleeping %i seconds due to previous failure", ch, RETRY_PAUSE);
sleep(RETRY_PAUSE);
}
@ -229,11 +229,11 @@ void * api_thread(void *arg) {
free(json_str);
// TODO free json objects
free(response.data);
pthread_testcancel(); /* test for cancelation request */
} while (opts.daemon);
curl_easy_cleanup(curl); /* always cleanup */
return NULL;
}

View file

@ -25,9 +25,8 @@
#include <json/json.h>
#include <string.h>
#include <stdio.h>
#include "main.h"
#include "local.h"
@ -40,22 +39,22 @@ int handle_request(void *cls, struct MHD_Connection *connection, const char *url
int ret;
int num_chans = *(int *) cls;
print(2, "Local request received: %s %s %s", NULL, version, method, url);
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;
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);
struct json_object *json_tuples = api_json_tuples(ch, TRUE);
json_object_object_add(json_data, "uuid", json_object_new_string(ch->uuid));
@ -63,18 +62,18 @@ int handle_request(void *cls, struct MHD_Connection *connection, const char *url
json_object_object_add(json_data, "tuples", json_tuples);
}
}
json_object_object_add(json_obj, "version", json_object_new_string(VZ_VERSION));
json_object_object_add(json_obj, "generator", json_object_new_string("vzlogger"));
json_object_object_add(json_obj, "version", json_object_new_string(VERSION));
json_object_object_add(json_obj, "generator", json_object_new_string(PACKAGE));
json_object_object_add(json_obj, "data", json_data);
json_str = json_object_to_json_string(json_obj);
response = MHD_create_response_from_data(strlen(json_str), (void *) json_str, FALSE, TRUE);
MHD_add_response_header(response, "Content-type", "application/json");
ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response (response);
return ret;

View file

@ -22,21 +22,25 @@
* 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 <getopt.h>
#include <stdarg.h>
#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 <math.h>
#include <stdint.h>
#include <microhttpd.h>
#include <getopt.h>
#ifdef LOCAL
#include <microhttpd.h>
#include "local.h"
#endif
#include "main.h"
#include "queue.h"
#include "api.h"
#include "local.h"
#include "protocols/obis.h"
#include "protocols/1wire.h"
@ -64,8 +68,10 @@ static protocol_t protocols[] = {
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'},
@ -78,8 +84,10 @@ static struct option long_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",
@ -91,11 +99,11 @@ static char *long_options_descs[] = {
*/
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 */
NULL, /* config file */
8080, /* port for local interface */
0, /* debug level / verbosity */
FALSE, /* daemon mode */
FALSE /* local interface */
};
/**
@ -108,23 +116,24 @@ void usage(char * argv[]) {
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("\nvzlogger - volkszaehler.org logging utility %s\n", VZ_VERSION);
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);
}
/**
@ -136,11 +145,11 @@ void usage(char * argv[]) {
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);
@ -156,7 +165,7 @@ void print(int level, char * format, channel_t *ch, ... ) {
else {
fprintf((level > 0) ? stdout : stderr, "\t\t");
}
va_start(args, ch);
vfprintf((level > 0) ? stdout : stderr, format, args);
va_end(args);
@ -183,15 +192,15 @@ void parse_options(int argc, char * argv[], options_t * opts) {
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;
@ -200,9 +209,9 @@ void parse_options(int argc, char * argv[], options_t * opts) {
opts->config = (char *) malloc(strlen(optarg)+1);
strcpy(opts->config, optarg);
break;
case 'V':
printf("%s\n", VZ_VERSION);
printf("%s\n", VERSION);
exit(EXIT_SUCCESS);
break;
@ -212,7 +221,7 @@ void parse_options(int argc, char * argv[], options_t * opts) {
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";
@ -224,7 +233,7 @@ void parse_options(int argc, char * argv[], options_t * opts) {
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;
}
@ -237,7 +246,7 @@ int parse_channels(char *filename, channel_t *chans) {
fprintf(stderr, "No config file found! Please specify with --config!\n");
exit(EXIT_FAILURE);
}
FILE *file = fopen(filename, "r"); /* open configuration */
if (file == NULL) {
@ -247,10 +256,10 @@ int parse_channels(char *filename, channel_t *chans) {
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 */
@ -263,76 +272,76 @@ int parse_channels(char *filename, channel_t *chans) {
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) {
@ -341,41 +350,41 @@ void *read_thread(void *arg) {
/* initalize channel */
ch->handle = ch->prot->init_func(ch->options); /* init sensor/meter */
do {
/**
* Aquire reading,
* may be blocking if mode == MODE_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->mode != MODE_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;
}
@ -384,21 +393,24 @@ void *read_thread(void *arg) {
*/
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);
@ -407,7 +419,8 @@ int main(int argc, char *argv[]) {
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(
@ -419,30 +432,33 @@ int main(int argc, char *argv[]) {
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

@ -30,10 +30,11 @@
#include <pthread.h>
#include <errno.h>
#include "../config.h"
#include "protocol.h"
#include "queue.h"
#define VZ_VERSION "0.2"
#define MAX_CHANNELS 16
#define RETRY_PAUSE 10 //600 /* seconds to wait after failed request */
@ -56,13 +57,13 @@ typedef struct {
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;
@ -79,7 +80,7 @@ typedef struct {
/* boolean bitfields, at the end of struct */
int daemon:1;
int local:1; /* enable local interface */
int local:1; /* enable local interface */
} options_t;
/* Prototypes */

View file

@ -22,7 +22,7 @@
* 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>
@ -38,13 +38,13 @@
*/
void * onewire_init(char *address) {
FILE * fd = fopen(address, "r");
if (fd == NULL) {
perror(address);
print(-1, "Failed to open sensor: %s", NULL, address);
exit(EXIT_FAILURE);
}
return (void *) fd;
}
@ -57,10 +57,10 @@ reading_t onewire_get(void *handle) {
char buffer[16];
int bytes;
do {
rewind((FILE *) handle);
bytes = fread(buffer, 1, 16, (FILE *) handle);
buffer[bytes] = '\0'; /* zero terminated, required? */
if (bytes) {
print(4, "Read from sensor file: %s", NULL, buffer);