|
From: <ma...@us...> - 2012-05-08 20:17:13
|
Revision: 799
http://openautomation.svn.sourceforge.net/openautomation/?rev=799&view=rev
Author: makki1
Date: 2012-05-08 20:17:03 +0000 (Tue, 08 May 2012)
Log Message:
-----------
Add debian-packaging, change to autoconf/make - NO source-changes
Added Paths:
-----------
tools/knxdmxd/Makefile.am
tools/knxdmxd/Makefile.org
tools/knxdmxd/configure.ac
tools/knxdmxd/debian/
tools/knxdmxd/debian/README
tools/knxdmxd/debian/README.Debian
tools/knxdmxd/debian/changelog
tools/knxdmxd/debian/compat
tools/knxdmxd/debian/control
tools/knxdmxd/debian/copyright
tools/knxdmxd/debian/docs
tools/knxdmxd/debian/files
tools/knxdmxd/debian/init.d
tools/knxdmxd/debian/knxdmxd.default
tools/knxdmxd/debian/knxdmxd.install
tools/knxdmxd/debian/rules
tools/knxdmxd/debian/source/
tools/knxdmxd/debian/source/format
tools/knxdmxd/src/
tools/knxdmxd/src/Makefile.am
tools/knxdmxd/src/knxdmxd.cpp
Removed Paths:
-------------
tools/knxdmxd/Makefile
tools/knxdmxd/knxdmxd.c
Deleted: tools/knxdmxd/Makefile
===================================================================
--- tools/knxdmxd/Makefile 2012-05-08 20:07:12 UTC (rev 798)
+++ tools/knxdmxd/Makefile 2012-05-08 20:17:03 UTC (rev 799)
@@ -1,7 +0,0 @@
-CC = g++
-CFLAGS = -Wall -Os
-LIBS = -L. -L/usr/lib -L/home/jan/ola-0.8.18/ola -lpthread -leibclient -lolacommon -lola -ljson
-
-knxdmxd: knxdmxd.c
- $(CC) $(CFLAGS) knxdmxd.c $(LIBS) -o knxdmxd
-
Added: tools/knxdmxd/Makefile.am
===================================================================
--- tools/knxdmxd/Makefile.am (rev 0)
+++ tools/knxdmxd/Makefile.am 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1,2 @@
+AUTOMAKE_OPTIONS = foreign
+SUBDIRS = src
\ No newline at end of file
Copied: tools/knxdmxd/Makefile.org (from rev 797, tools/knxdmxd/Makefile)
===================================================================
--- tools/knxdmxd/Makefile.org (rev 0)
+++ tools/knxdmxd/Makefile.org 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1,7 @@
+CC = g++
+CFLAGS = -Wall -Os
+LIBS = -L. -L/usr/lib -L/home/jan/ola-0.8.18/ola -lpthread -leibclient -lolacommon -lola -ljson
+
+knxdmxd: knxdmxd.c
+ $(CC) $(CFLAGS) knxdmxd.c $(LIBS) -o knxdmxd
+
Added: tools/knxdmxd/configure.ac
===================================================================
--- tools/knxdmxd/configure.ac (rev 0)
+++ tools/knxdmxd/configure.ac 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1,38 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+AC_PREREQ([2.61])
+AC_INIT(knxdmxd)
+AM_INIT_AUTOMAKE(knxdmxd, 0.01)
+
+AC_CONFIG_SRCDIR([src])
+#AC_CONFIG_HEADERS([config.h:config.h.in])
+
+# Checks for programs.
+AC_PROG_CXX
+
+# Checks for libraries.
+AC_CHECK_LIB([eibclient], [EIBClose], ,[AC_MSG_ERROR(
+[Couldn't find libeibclient...try installing the eibclient-dev package] )])
+AC_CHECK_LIB([pthread], [pthread_create])
+AC_CHECK_LIB([json], [json_object_get], ,[AC_MSG_ERROR(
+[Couldn't find libjson0...try installing the libjson0-dev package] )])
+
+dnl ************************************
+dnl Check for libola
+dnl ************************************
+PKG_CHECK_MODULES([OLA], [libola], ,[AC_MSG_ERROR(
+[Couldn't find libola...try installing the ola package] )])
+AC_SUBST(OLA_LIBS)
+
+
+# Checks for header files.
+AC_CHECK_HEADERS([arpa/inet.h fcntl.h stdlib.h string.h syslog.h unistd.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_TYPE_PID_T
+
+# Checks for library functions.
+AC_FUNC_FORK
+
+AC_OUTPUT(src/Makefile Makefile)
+
Added: tools/knxdmxd/debian/README
===================================================================
--- tools/knxdmxd/debian/README (rev 0)
+++ tools/knxdmxd/debian/README 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1,6 @@
+The Debian Package knxdmxd
+----------------------------
+
+Comments regarding the Package
+
+ -- Michael Markstaller <de...@wi...> Wed, 07 Sep 2011 18:04:18 +0200
Added: tools/knxdmxd/debian/README.Debian
===================================================================
--- tools/knxdmxd/debian/README.Debian (rev 0)
+++ tools/knxdmxd/debian/README.Debian 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1,6 @@
+knxdmxd for Debian
+-----------------------
+
+control startup settings through /etc/default/knxdmxd
+
+ -- Michael Markstaller <de...@wi...> Di 08 Mai 2012 16:52:30 CEST
Added: tools/knxdmxd/debian/changelog
===================================================================
--- tools/knxdmxd/debian/changelog (rev 0)
+++ tools/knxdmxd/debian/changelog 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1,5 @@
+knxdmxd (0.1) unstable; urgency=low
+
+ * Initial Release.
+
+ -- Michael Markstaller <de...@wi...> Tue, 08 May 2012 16:53:19 +0200
Added: tools/knxdmxd/debian/compat
===================================================================
--- tools/knxdmxd/debian/compat (rev 0)
+++ tools/knxdmxd/debian/compat 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1 @@
+5
Added: tools/knxdmxd/debian/control
===================================================================
--- tools/knxdmxd/debian/control (rev 0)
+++ tools/knxdmxd/debian/control 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1,14 @@
+Source: knxdmxd
+Section: unknown
+Priority: extra
+Maintainer: Michael Markstaller <de...@wi...>
+Build-Depends: debhelper (>= 5.0), autotools-dev, libeibclient-dev, libjson0-dev
+Standards-Version: 3.9.1
+Homepage: http://sourceforge.net/projects/openautomation/
+
+Package: knxdmxd
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: simple daemon to connect EIB/KNX to DMX using OLA
+ simple daemon to connect EIB/KNX to DMX using OLA
+
Added: tools/knxdmxd/debian/copyright
===================================================================
--- tools/knxdmxd/debian/copyright (rev 0)
+++ tools/knxdmxd/debian/copyright 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1,39 @@
+Format: http://dep.debian.net/deps/dep5
+Upstream-Name: knxdmxd
+Source: <http://sourceforge.net/projects/openautomation/>
+
+Files: *
+Copyright: 2012 Jan N. Klug 2012 <jan...@ru...>
+License: GPL-3.0+
+
+Files: debian/*
+Copyright: 2011 Michael Markstaller <de...@wi...>
+License: GPL-3.0+
+
+License: GPL-3.0+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ .
+ This package is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ .
+ On Debian systems, the complete text of the GNU General
+ Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
+
+# Please choose a license for your packaging work. If the program you package
+# uses a mainstream license, using the same license is the safest choice.
+# Please avoid to pick license terms that are more restrictive than the
+# packaged work, as it may make Debian's contributions unacceptable upstream.
+# If you just want it to be GPL version 3, leave the following line in.
+
+and is licensed under the GPL version 3, see above.
+
+# Please also look if there are files or directories which have a
+# different copyright/license attached and list them here.
Added: tools/knxdmxd/debian/docs
===================================================================
--- tools/knxdmxd/debian/docs (rev 0)
+++ tools/knxdmxd/debian/docs 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1,2 @@
+README
+
Added: tools/knxdmxd/debian/files
===================================================================
--- tools/knxdmxd/debian/files (rev 0)
+++ tools/knxdmxd/debian/files 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1 @@
+knxdmxd_0.1_i386.deb unknown extra
Added: tools/knxdmxd/debian/init.d
===================================================================
--- tools/knxdmxd/debian/init.d (rev 0)
+++ tools/knxdmxd/debian/init.d 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1,152 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides: knxdmxd
+# Required-Start: $network $local_fs
+# Required-Stop:
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: <Enter a short description of the sortware>
+# Description: <Enter a long description of the software>
+# <...>
+# <...>
+### END INIT INFO
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+DESC=knxdmxd # Introduce a short description here
+NAME=knxdmxd # Introduce the short server's name here
+DAEMON=/usr/bin/knxdmxd # Introduce the server's location here
+DAEMON_ARGS="" # Arguments to run the daemon with
+PIDFILE=/var/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/$NAME
+
+# Exit if the package is not installed
+[ -x $DAEMON ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcS variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
+. /lib/lsb/init-functions
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+ # Return
+ # 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 \
+ || return 1
+ start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
+ $DAEMON_ARGS \
+ || return 2
+ # Add code here, if necessary, that waits for the process to be ready
+ # to handle requests from services started subsequently which depend
+ # on this one. As a last resort, sleep for some time.
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+ # Return
+ # 0 if daemon has been stopped
+ # 1 if daemon was already stopped
+ # 2 if daemon could not be stopped
+ # other if a failure occurred
+ start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
+ RETVAL="$?"
+ [ "$RETVAL" = 2 ] && return 2
+ # Wait for children to finish too if this is a daemon that forks
+ # and if the daemon is only ever run from this initscript.
+ # If the above conditions are not satisfied then add some other code
+ # that waits for the process to drop all resources that could be
+ # needed by services started subsequently. A last resort is to
+ # sleep for some time.
+ start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
+ [ "$?" = 2 ] && return 2
+ # Many daemons don't delete their pidfiles when they exit.
+ rm -f $PIDFILE
+ return "$RETVAL"
+}
+
+#
+# Function that sends a SIGHUP to the daemon/service
+#
+do_reload() {
+ #
+ # If the daemon can reload its configuration without
+ # restarting (for example, when it is sent a SIGHUP),
+ # then implement that here.
+ #
+ start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
+ return 0
+}
+
+case "$1" in
+ start)
+ [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME"
+ do_start
+ case "$?" in
+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+ esac
+ ;;
+ stop)
+ [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+ do_stop
+ case "$?" in
+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+ esac
+ ;;
+ status)
+ status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
+ ;;
+ #reload|force-reload)
+ #
+ # If do_reload() is not implemented then leave this commented out
+ # and leave 'force-reload' as an alias for 'restart'.
+ #
+ #log_daemon_msg "Reloading $DESC" "$NAME"
+ #do_reload
+ #log_end_msg $?
+ #;;
+ restart|force-reload)
+ #
+ # If the "reload" option is implemented then remove the
+ # 'force-reload' alias
+ #
+ log_daemon_msg "Restarting $DESC" "$NAME"
+ do_stop
+ case "$?" in
+ 0|1)
+ do_start
+ case "$?" in
+ 0) log_end_msg 0 ;;
+ 1) log_end_msg 1 ;; # Old process is still running
+ *) log_end_msg 1 ;; # Failed to start
+ esac
+ ;;
+ *)
+ # Failed to stop
+ log_end_msg 1
+ ;;
+ esac
+ ;;
+ *)
+ #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+ echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
+ exit 3
+ ;;
+esac
+
+:
Added: tools/knxdmxd/debian/knxdmxd.default
===================================================================
--- tools/knxdmxd/debian/knxdmxd.default (rev 0)
+++ tools/knxdmxd/debian/knxdmxd.default 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1,17 @@
+# Defaults for knxdmxd initscript
+# sourced by /etc/init.d/knxdmxd
+# installed at /etc/default/knxdmxd by the maintainer scripts
+
+#
+# This is a POSIX shell fragment
+#
+
+#Usage: ./knxdmxd
+# -d Run as daemon/No debug output
+# -p <pidfile> PID-filename
+# -u <eib url> URL to contact eibd like local:/tmp/eib or ip:192.168.0.101
+# -c <config-file> Config-File
+
+# Additional options that are passed to the Daemon.
+DAEMON_ARGS="-d -c /etc/knxdmxd.conf -u local:/tmp/eib -p /var/run/knxdmxd.pid"
+
Added: tools/knxdmxd/debian/knxdmxd.install
===================================================================
--- tools/knxdmxd/debian/knxdmxd.install (rev 0)
+++ tools/knxdmxd/debian/knxdmxd.install 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1,2 @@
+knxdmxd.conf etc/
+
Added: tools/knxdmxd/debian/rules
===================================================================
--- tools/knxdmxd/debian/rules (rev 0)
+++ tools/knxdmxd/debian/rules 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1,13 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+%:
+ dh $@
Property changes on: tools/knxdmxd/debian/rules
___________________________________________________________________
Added: svn:executable
+ *
Added: tools/knxdmxd/debian/source/format
===================================================================
--- tools/knxdmxd/debian/source/format (rev 0)
+++ tools/knxdmxd/debian/source/format 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1 @@
+3.0 (native)
Deleted: tools/knxdmxd/knxdmxd.c
===================================================================
--- tools/knxdmxd/knxdmxd.c 2012-05-08 20:07:12 UTC (rev 798)
+++ tools/knxdmxd/knxdmxd.c 2012-05-08 20:17:03 UTC (rev 799)
@@ -1,653 +0,0 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
-/*
- * knxdmxd.c
- * Copyright (C) Jan N. Klug 2012 <jan...@ru...>
- * Daemon skeleton by Michael Markstaller 2011 <de...@wi...>
- *
- * knxdmxd is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * knxdmxd is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <string.h>
-#include <signal.h>
-#include <getopt.h>
-#include <json/json.h>
-
-#include <ola/Logging.h>
-#include <ola/DmxBuffer.h>
-#include <ola/StreamingClient.h>
-#include <ola/StringUtils.h>
-
-//#include <assert.h>
-
-#include <arpa/inet.h>
-//#include <netinet/in.h>
-//#include <sys/socket.h>
-
-#include <pthread.h>
-#include <eibclient.h>
-
-#include <iostream>
-#include <fstream>
-#include <map>
-
-/*#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/xml_parser.hpp>
-#include <boost/foreach.hpp>*/
-
-#define DEBUG 1
-#define DAEMON_NAME "knxdmxd"
-#define USAGESTRING "\n"\
- "\t-d Run as daemon/No debug output\n"\
- "\t-p <pidfile> PID-filename\n"\
- "\t-u <eib url> URL to contact eibd like local:/tmp/eib or ip:192.168.0.101\n"\
- "\t-c <config-file> Config-File\n"
-#define NUM_THREADS 4
-#define MAX_ZONES 31
-#define RETRY_TIME 5
-#define BUFLEN 1024
-#define POLLING_INTERVAL 10
-#define FADING_INTERVAL 50000
-
-using namespace std;
-//namespace bpt = boost::property_tree;
-typedef vector<string> svector;
-
-void daemonShutdown();
-
-eibaddr_t readgaddr (const char *addr) {
- int a, b, c;
- if (sscanf (addr, "%d/%d/%d", &a, &b, &c) == 3)
- return ((a & 0x01f) << 11) | ((b & 0x07) << 8) | ((c & 0xff));
- if (sscanf (addr, "%d/%d", &a, &b) == 2)
- return ((a & 0x01f) << 11) | ((b & 0x7FF));
- if (sscanf (addr, "%x", &a) == 1)
- return a & 0xffff;
- syslog(LOG_WARNING,"invalid group address format %s", addr);
- daemonShutdown();
- return 0;
-}
-
-int readdaddr (const string addr) {
- int universe, channel;
- sscanf( (char*)addr.c_str(), "%d.%d", &universe, &channel);
- if (channel==-1) { // default universe is 1
- channel = universe;
- universe = 1;
- }
- return (universe << 9) + channel;
-}
-
-namespace knxdmxd {
-
-class Fixture {
- public:
- Fixture() {};
- Fixture(const string str);
-
- void Patch(map<int, svector >& patchMap, const string channel, const int DMX, const int KNX);
- void Patch(map<int, svector >& patchMap, const string channel, const string DMX, const string KNX);
- void SetFadeTime(const float t);
- void PatchFadeTime(const int KNX);
- void Update(const int KNX, const int val);
- void Refresh(map<int, ola::DmxBuffer>& output);
- private:
- string name;
- map <string, int> channelKNX;
- map <string, int> channelDMX;
- map <string, int> channelValue;
- map <string, float> channelFloatValue;
- float fadeTime, fadeStep;
- int fadeTimeKNX;
-};
-
-Fixture::Fixture(const string str) {
- name=str;
- syslog(LOG_DEBUG, "Created Fixture '%s'", (char *)str.c_str());
-}
-
-void Fixture::Patch(map<int, svector>& patchMap, const string channel, const int DMX, const int KNX) {
- channelKNX[channel] = KNX;
- channelDMX[channel] = DMX;
-
- syslog(LOG_DEBUG, "Fixture '%s': Patched channel '%s' (KNX %d to DMX %d) ", (char *)name.c_str(), (char *)channel.c_str(), KNX, DMX);
-
- svector assignedChannels = patchMap[KNX]; // check if already patched
- for (vector<string>::iterator i = assignedChannels.begin(); i != assignedChannels.end(); ++i) {
- if ((*i)==name) { // already patched;
- return;
- }
- }
-
- patchMap[KNX].push_back(name); // no, add to patchMap
-
-}
-
-void Fixture::Patch(map<int, svector>& patchMap, const string channel, const string DMX, const string KNX) {
- Patch(patchMap, channel, readdaddr(DMX), readgaddr((char *) KNX.c_str()));
-}
-
-void Fixture::SetFadeTime(const float t) {
- fadeTime = t;
- fadeStep = (t<=0) ? 256 : 256/(t*1e6/FADING_INTERVAL);
- syslog(LOG_DEBUG, "Fixture '%s': Set Fadetime to %.2f s'(%.2f steps/interval)", (char *)name.c_str(), fadeTime, fadeStep);
-}
-
-void Fixture::PatchFadeTime(const int KNX) {
- fadeTimeKNX = KNX;
-}
-
-void Fixture::Update(const int KNX, const int val) {
- for(std::map<string, int>::const_iterator i = channelKNX.begin(); i != channelKNX.end(); ++i) {
- if (i->second == KNX) {
- channelValue[i->first] = val;
- syslog(LOG_DEBUG, "Updated channel '%s' to %d", (char *)i->first.c_str(), val);
- }
- }
-}
-
-void Fixture::Refresh(map<int, ola::DmxBuffer>& output) {
- for(std::map<string, int>::const_iterator i = channelDMX.begin(); i != channelDMX.end(); ++i) {
- int dmxuniverse = (int) (i->second / 512) , dmxchannel = i->second % 512;
- int oldValue = output[dmxuniverse].Get(dmxchannel);
- int newValue = channelValue[i->first];
- if (oldValue<newValue) {
- channelFloatValue[i->first] += fadeStep;
- if (channelFloatValue[i->first]>newValue) {
- channelFloatValue[i->first] = newValue;
- }
- output[dmxuniverse].SetChannel(dmxchannel, (int) channelFloatValue[i->first]);
- }
- if (oldValue>newValue) {
- channelFloatValue[i->first] -= fadeStep;
- if (channelFloatValue[i->first]<newValue) {
- channelFloatValue[i->first] = newValue;
- }
- output[dmxuniverse].SetChannel(dmxchannel, (int) channelFloatValue[i->first]);
- }
- }
-}
-
-}
-
-pthread_mutex_t zonelock = PTHREAD_MUTEX_INITIALIZER;
-pthread_mutex_t initlock = PTHREAD_MUTEX_INITIALIZER;
-pthread_mutex_t standbylock = PTHREAD_MUTEX_INITIALIZER;
-
-string eibd_url = "local:/tmp/eib";
-string conf_file = "knxdmxd.conf";
-int pidFilehandle;
-string pidfilename = "/var/run/dmxknxd.pid";
-
-map<int, ola::DmxBuffer> dmxWriteBuffer;
-map<string, knxdmxd::Fixture> fixtureList;
-map<int, svector> patchMap;
-
-void daemonShutdown() {
- //FIXME: clean exit pthread_exit(NULL); pthread_cancel(..);
- //close(udpSocket);
- syslog(LOG_INFO, "%s daemon exiting", DAEMON_NAME);
- fprintf(stderr, "%s daemon exiting", DAEMON_NAME);
- close(pidFilehandle);
- unlink((char *)pidfilename.c_str());
- exit(EXIT_SUCCESS);
-}
-
-void signal_handler(int sig) {
- switch(sig) {
- case SIGHUP:
- syslog(LOG_WARNING, "Received SIGHUP signal.");
- break;
- case SIGTERM:
- syslog(LOG_WARNING, "Received SIGTERM signal.");
- daemonShutdown();
- break;
- case SIGINT:
- syslog(LOG_WARNING, "Received SIGINT signal.");
- daemonShutdown();
- break;
- default:
- syslog(LOG_WARNING, "Unhandled signal (%d) %s", sig, strsignal(sig));
- break;
- }
-}
-
-/*void *sendKNXdgram(int type, int dpt, eibaddr_t dest, unsigned char val) {
- int len = 0;
- EIBConnection *con;
- unsigned char buf[255] = { 0, 0x80 };
- buf[1] = type; //0x40 response, 0x80 write
- syslog(LOG_DEBUG,"Send KNX dgram Type %d DPT %d dest %d val %d",type,dpt,dest,val);
- con = EIBSocketURL ((char *)eibd_url.c_str());
- if (!con)
- syslog(LOG_WARNING,"sendknxdgram: Open failed");
- if (EIBOpenT_Group (con, dest, 1) == -1)
- syslog(LOG_WARNING,"sendknxdgram: Connect failed");
- switch (dpt)
- {
- case 0:
- len=1;
- //for(i = 0; i < strlen(val)/2; i++)
- //raw value: nothing for now
- break;
- case 1:
- buf[1] |= val & 0x3f;
- len=2;
- break;
- case 3:
- // EIS2/DPT3 4bit dim
- buf[1] |= val & 0x3f;
- len=2;
- break;
- case 5:
- buf[2] = val*255/100;
- len=3;
- break;
- case 51:
- case 5001:
- buf[2] = val;
- len=3;
- break;
- case 6:
- case 6001:
- //FIXME: This is basically wrong but as we get a uchar we expect the sender to know..
- buf[2] = val;
- len=3;
- break;
- }
-
- len = EIBSendAPDU (con, len, buf);
- if (len == -1)
- syslog (LOG_WARNING,"sendknxdram: Request failed");
- EIBClose (con);
- usleep(50*1000); //throttle a little (50ms/max 20tps)
- return 0;
-} */
-
-void sigtime(int signo)
-{
- for(std::map<string, knxdmxd::Fixture>::const_iterator i = fixtureList.begin(); i != fixtureList.end(); ++i) {
- fixtureList[i->first].Refresh(dmxWriteBuffer);
- }
- signal(SIGALRM, sigtime);
-}
-
-void *worker(void *) {
- syslog(LOG_DEBUG, "Internal worker thread started");
-
- signal(SIGALRM, sigtime);
-
- itimerval itm;
- itm.it_interval.tv_sec=0;
- itm.it_value.tv_sec = 0;
- itm.it_interval.tv_usec = FADING_INTERVAL; // 20 ms is enough
- itm.it_value.tv_usec = FADING_INTERVAL;
- setitimer(ITIMER_REAL,&itm,0);
-
- while (1) {
- sleep(POLLING_INTERVAL);
- }
-
- pthread_exit(NULL);
-}
-
-/*void *sendKNXresponse(eibaddr_t dest, int zone, int func) {
- syslog(LOG_DEBUG, "KNX response %d zone %d func %d", dest,zone,func);
- pthread_mutex_lock (&zonelock);
- switch (func) {
- case 0:
- case 20:
- sendKNXdgram (0x40,1,dest,zones[zone].zonepower);
- break;
- case 1:
- case 21:
- sendKNXdgram (0x40,51,dest,zones[zone].srcid);
- break;
- case 2:
- case 22:
- sendKNXdgram (0x40,5,dest,zones[zone].volume*2);
- break;
- case 3:
- case 23:
- if (zones[zone].bass<10)
- sendKNXdgram (0x40,51,dest,zones[zone].bass-10+256);
- else
- sendKNXdgram (0x40,51,dest,zones[zone].bass-10);
- break;
- case 4:
- case 24:
- if (zones[zone].treble<10)
- sendKNXdgram (0x40,51,dest,zones[zone].treble-10+256);
- else
- sendKNXdgram (0x40,51,dest,zones[zone].treble-10);
- break;
- case 5:
- case 25:
- sendKNXdgram (0x40,1,dest,zones[zone].loudness);
- break;
- case 6:
- case 26:
- if (zones[zone].balance<10)
- sendKNXdgram (0x40,51,dest,zones[zone].balance-10+256);
- else
- sendKNXdgram (0x40,51,dest,zones[zone].balance-10);
- break;
- case 27:
- sendKNXdgram (0x40,1,dest,zones[zone].partymode);
- break;
- case 28:
- sendKNXdgram (0x40,1,dest,zones[zone].dnd);
- break;
- case 29:
- sendKNXdgram (0x40,5,dest,zones[zone].onvolume*2);
- break;
- }
- pthread_mutex_unlock (&zonelock);
- return 0;
-}
-*/
-void *handleKNXdgram(eibaddr_t dest, unsigned char* buf, int len){
- unsigned char val;
- switch (buf[1] & 0xC0) {
- case 0x00:
-// sendKNXresponse (dest,zone+(controller*ZONES_PER_CONTROLLER),func);
- break;
- case 0x40:
- //FIXME: response dunno
- break;
- case 0x80:
- if (buf[1] & 0xC0) {
- if (len == 2)
- val = buf[1] & 0x3F;
- else
- val = buf[2];
- svector uFixtures = patchMap.find(dest)->second;
- for (unsigned int i=0; i < uFixtures.size(); i++) {
- fixtureList[uFixtures[i]].Update(dest, val);
- }
- syslog(LOG_DEBUG, "Received %d @ %d, updated %d fixtures", val, dest, (int) uFixtures.size());
- }
- break;
- }
- return 0;
-}
-
-
-void *olahandler(void *) { // thread just reliably sends the data to DMX via OLA
- syslog(LOG_DEBUG, "OLA sender thread started");
-
- ola::InitLogging(ola::OLA_LOG_WARN, ola::OLA_LOG_STDERR);
-
- while (1) { // retry forever
-
- ola::StreamingClient ola_client;
-
- if (!ola_client.Setup()) { // setup client
- syslog(LOG_WARNING, "OLA: Client setup failed");
- sleep(RETRY_TIME);
- continue;
- }
-
- syslog(LOG_INFO, "OLA: Client connected");
-
- while (1) { // loop forever
- int error_flag=0;
- for(std::map<int, ola::DmxBuffer>::const_iterator i = dmxWriteBuffer.begin(); i != dmxWriteBuffer.end(); ++i) {
- int universe = i->first;
- if (!ola_client.SendDmx(universe, i->second)) { // send all universes
- syslog(LOG_WARNING, "OLA: failed to send universe %d", universe);
- error_flag = 1;
- break; // something went wrong
- }
- }
- if (error_flag==1) {
- sleep(RETRY_TIME);
- break;
- }
-
- usleep(20000);
- }
-
- ola_client.Stop(); // close the client
- }
-
- pthread_exit(NULL);
-}
-
-
-void *knxhandler(void *) {
- syslog(LOG_DEBUG, "KNX reader thread started");
- int len;
- EIBConnection *con;
- eibaddr_t dest;
- eibaddr_t src;
- unsigned char buf[255];
-
- while (1) //retry infinite
- {
- con = EIBSocketURL ((char *)eibd_url.c_str());
- if (!con) {
- syslog(LOG_WARNING, "eibd: Open failed");
- sleep(RETRY_TIME);
- continue;
- }
-
- if (EIBOpen_GroupSocket (con, 0) == -1) {
- syslog(LOG_WARNING, "eibd: Connect failed");
- sleep(RETRY_TIME);
- continue;
- }
-
- while (1)
- {
- len = EIBGetGroup_Src (con, sizeof (buf), buf, &src, &dest);
- if (len == -1) {
- syslog(LOG_WARNING, "eibd: Read failed");
- sleep(RETRY_TIME);
- break;
- }
- if (len < 2) {
- syslog(LOG_WARNING, "eibd: Invalid Packet");
- break;
- }
- if (buf[0] & 0x3 || (buf[1] & 0xC0) == 0xC0) {
- syslog(LOG_WARNING, "eibd: Unknown APDU from %d to %d",src,dest);
- break;
- } else {
- if ( patchMap.count(dest)<=0 ) //not for us
- continue;
- handleKNXdgram(dest,buf,len);
- }
- }
- syslog(LOG_WARNING,"eibd: closed connection"); //break in read-loop
- EIBClose (con);
- }
- pthread_exit(NULL);
-}
-
-void load_config() {
-
-/* bpt::ptree config;
-
- read_xml(conf_file, config);
-
- BOOST_FOREACH( bpt::ptree::value_type const& e, config) {
- if( e.first == "fixture" ) {
- string name = e.second.get<std::string>("<xmlattr>.name");
- knxdmxd::Fixture f(name);
- BOOST_FOREACH( bpt::ptree::value_type const& c, e.second) {
- if (c.first == "channel") {
- f.Patch(patchMap, c.second.data(), c.second.get<std::string>("<xmlattr>.dmx"), c.second.get<std::string>("<xmlattr>.knx"));
- }
- if (c.first == "fading") {
- float t;
- string content = c.second.data();
- sscanf((char*) content.c_str(), "%f", &t);
- f.SetFadeTime((int) (t*1.e6));
- }
- }
- fixtureList[name] = f;
- }
-
- } */
- struct json_object *config;
-
- config = json_object_from_file((char *)conf_file.c_str());
- // first all fixtures
- struct json_object *fixtures = json_object_object_get(config, "fixtures");
-
- int fixturenum = json_object_array_length(fixtures);
-
- for (int i=0; i<fixturenum; i++) { // read all
- // get fixture
- struct json_object *fixture = json_object_array_get_idx(fixtures, i);
-
- // get name & create
- string fname(json_object_get_string(json_object_object_get(fixture, "name")));
- knxdmxd::Fixture f(fname);
-
- // get channels & patch them
- struct json_object *channels = json_object_object_get(fixture, "channels");
- int channelnum = json_object_array_length(channels);
- for (int j=0; j<channelnum; j++) { // read all
- // get channel
- struct json_object *channel = json_object_array_get_idx(channels, j);
- string cname(json_object_get_string(json_object_object_get(channel, "name")));
- string cdmx(json_object_get_string(json_object_object_get(channel, "dmx")));
- string cknx(json_object_get_string(json_object_object_get(channel, "knx")));
- f.Patch(patchMap, cname, cdmx, cknx);
- }
-
- // get fading
- struct json_object *fading = json_object_object_get(fixture, "fading");
- float ftime = (fading) ? json_object_get_double(json_object_object_get(fading, "time")) : 0;
- f.SetFadeTime(ftime);
-
- fixtureList[fname] = f;
- }
-
- return;
-}
-
-int main(int argc, char **argv) {
- int daemonize = 0;
- int c;
- //char *p;
- char pidstr[255];
-
- while ((c = getopt (argc, argv, "d:p:u:c:")) != -1)
- switch (c) {
- case 'd':
- daemonize = 1;
- break;
- case 'p':
- pidfilename.assign(optarg);
- break;
- case 'u':
- eibd_url.assign(optarg);
- break;
- case 'c':
- conf_file.assign(optarg);
- break;
- case '?':
- //FIXME: check arguments better, print_usage
- fprintf (stderr, "Unknown option `-%c'.\nUsage: %s %s", optopt, argv[0], USAGESTRING);
- return 1;
- default:
- abort ();
- }
-
- //FIXME: clean shutdown in sub-thread with signals?
- signal(SIGHUP, signal_handler);
- signal(SIGTERM, signal_handler);
- signal(SIGINT, signal_handler);
- signal(SIGQUIT, signal_handler);
-
- if (!daemonize) {
- setlogmask(LOG_UPTO(LOG_DEBUG));
- openlog(DAEMON_NAME, LOG_CONS | LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_USER);
- syslog(LOG_DEBUG, "startup with debug; pidfile: %s, eibd: %s",
- (char *)pidfilename.c_str(), (char *)eibd_url.c_str());
- } else {
- setlogmask(LOG_UPTO(LOG_INFO));
- openlog(DAEMON_NAME, LOG_CONS, LOG_USER);
- }
-
- syslog(LOG_INFO, "using config-file %s", (char *)conf_file.c_str());
-
- load_config();
-
- pid_t pid, sid;
-
- if (daemonize) {
- syslog(LOG_INFO, "starting daemon");
-
- pid = fork();
- if (pid < 0) {
- exit(EXIT_FAILURE);
- }
- if (pid > 0) {
- exit(EXIT_SUCCESS);
- }
- umask(0);
- sid = setsid();
- if (sid < 0) {
- exit(EXIT_FAILURE);
- }
- if ((chdir("/")) < 0) {
- exit(EXIT_FAILURE);
- }
- close(STDIN_FILENO);
- close(STDOUT_FILENO);
- close(STDERR_FILENO);
- }
- //FIXME: output errors to stderr, change order
- pidFilehandle = open((char *)pidfilename.c_str(), O_RDWR|O_CREAT, 0600);
- if (pidFilehandle == -1 )
- {
- syslog(LOG_INFO, "Could not open pidfile %s, exiting", (char *)pidfilename.c_str());
- fprintf(stderr, "Could not open pidfile %s, exiting", (char *)pidfilename.c_str());
- exit(EXIT_FAILURE);
- }
- if (lockf(pidFilehandle,F_TLOCK,0) == -1)
- {
- syslog(LOG_INFO, "Could not lock pidfile %s, exiting", (char *)pidfilename.c_str());
- fprintf(stderr, "Could not lock pidfile %s, exiting", (char *)pidfilename.c_str());
- exit(EXIT_FAILURE);
- }
- sprintf(pidstr,"%d\n",getpid());
- c = write(pidFilehandle, pidstr, strlen(pidstr));
-
- int knxthread, olathread, workerthread;
- pthread_t threads[NUM_THREADS];
- // PTHREAD_CREATE_DETACHED?
- knxthread = pthread_create(&threads[1], NULL, knxhandler, NULL); //id, thread attributes, subroutine, arguments
- olathread = pthread_create(&threads[2], NULL, olahandler, NULL); //id, thread attributes, subroutine, arguments
- workerthread = pthread_create(&threads[3], NULL, worker, NULL); //id, thread attributes, subroutine, arguments
- syslog(LOG_DEBUG,"Threads created: %d %d %d",knxthread, olathread, workerthread);
- //TODO: Maybe another console/TCP-server/Logging thread?
- while (1) {
-// syslog(LOG_DEBUG, "%s daemon running", DAEMON_NAME);
- sleep(POLLING_INTERVAL);
- }
- syslog(LOG_INFO, "%s daemon exiting", DAEMON_NAME);
- // TODO: Free any allocated resources before exiting - we never get here though -> signal handler
- exit(EXIT_SUCCESS);
-}
Added: tools/knxdmxd/src/Makefile.am
===================================================================
--- tools/knxdmxd/src/Makefile.am (rev 0)
+++ tools/knxdmxd/src/Makefile.am 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1,11 @@
+# what flags you want to pass to the C compiler & linker
+#CPPFLAGS = --pedantic -Wall -std=c99 -O2
+#LDFLAGS =
+
+knxdmxd_CXXFLAGS = $(OLA_CFLAGS) $(AM_CXXFLAGS)
+knxdmxd_LDADD = $(OLA_LIBS)
+
+# this lists the binaries to produce, the (non-PHONY, binary) targets in
+# the previous manual Makefile
+bin_PROGRAMS = knxdmxd
+knxdmxd_SOURCES = knxdmxd.cpp
Copied: tools/knxdmxd/src/knxdmxd.cpp (from rev 797, tools/knxdmxd/knxdmxd.c)
===================================================================
--- tools/knxdmxd/src/knxdmxd.cpp (rev 0)
+++ tools/knxdmxd/src/knxdmxd.cpp 2012-05-08 20:17:03 UTC (rev 799)
@@ -0,0 +1,653 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * knxdmxd.c
+ * Copyright (C) Jan N. Klug 2012 <jan...@ru...>
+ * Daemon skeleton by Michael Markstaller 2011 <de...@wi...>
+ *
+ * knxdmxd is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * knxdmxd is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <string.h>
+#include <signal.h>
+#include <getopt.h>
+#include <json/json.h>
+
+#include <ola/Logging.h>
+#include <ola/DmxBuffer.h>
+#include <ola/StreamingClient.h>
+#include <ola/StringUtils.h>
+
+//#include <assert.h>
+
+#include <arpa/inet.h>
+//#include <netinet/in.h>
+//#include <sys/socket.h>
+
+#include <pthread.h>
+#include <eibclient.h>
+
+#include <iostream>
+#include <fstream>
+#include <map>
+
+/*#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/xml_parser.hpp>
+#include <boost/foreach.hpp>*/
+
+#define DEBUG 1
+#define DAEMON_NAME "knxdmxd"
+#define USAGESTRING "\n"\
+ "\t-d Run as daemon/No debug output\n"\
+ "\t-p <pidfile> PID-filename\n"\
+ "\t-u <eib url> URL to contact eibd like local:/tmp/eib or ip:192.168.0.101\n"\
+ "\t-c <config-file> Config-File\n"
+#define NUM_THREADS 4
+#define MAX_ZONES 31
+#define RETRY_TIME 5
+#define BUFLEN 1024
+#define POLLING_INTERVAL 10
+#define FADING_INTERVAL 50000
+
+using namespace std;
+//namespace bpt = boost::property_tree;
+typedef vector<string> svector;
+
+void daemonShutdown();
+
+eibaddr_t readgaddr (const char *addr) {
+ int a, b, c;
+ if (sscanf (addr, "%d/%d/%d", &a, &b, &c) == 3)
+ return ((a & 0x01f) << 11) | ((b & 0x07) << 8) | ((c & 0xff));
+ if (sscanf (addr, "%d/%d", &a, &b) == 2)
+ return ((a & 0x01f) << 11) | ((b & 0x7FF));
+ if (sscanf (addr, "%x", &a) == 1)
+ return a & 0xffff;
+ syslog(LOG_WARNING,"invalid group address format %s", addr);
+ daemonShutdown();
+ return 0;
+}
+
+int readdaddr (const string addr) {
+ int universe, channel;
+ sscanf( (char*)addr.c_str(), "%d.%d", &universe, &channel);
+ if (channel==-1) { // default universe is 1
+ channel = universe;
+ universe = 1;
+ }
+ return (universe << 9) + channel;
+}
+
+namespace knxdmxd {
+
+class Fixture {
+ public:
+ Fixture() {};
+ Fixture(const string str);
+
+ void Patch(map<int, svector >& patchMap, const string channel, const int DMX, const int KNX);
+ void Patch(map<int, svector >& patchMap, const string channel, const string DMX, const string KNX);
+ void SetFadeTime(const float t);
+ void PatchFadeTime(const int KNX);
+ void Update(const int KNX, const int val);
+ void Refresh(map<int, ola::DmxBuffer>& output);
+ private:
+ string name;
+ map <string, int> channelKNX;
+ map <string, int> channelDMX;
+ map <string, int> channelValue;
+ map <string, float> channelFloatValue;
+ float fadeTime, fadeStep;
+ int fadeTimeKNX;
+};
+
+Fixture::Fixture(const string str) {
+ name=str;
+ syslog(LOG_DEBUG, "Created Fixture '%s'", (char *)str.c_str());
+}
+
+void Fixture::Patch(map<int, svector>& patchMap, const string channel, const int DMX, const int KNX) {
+ channelKNX[channel] = KNX;
+ channelDMX[channel] = DMX;
+
+ syslog(LOG_DEBUG, "Fixture '%s': Patched channel '%s' (KNX %d to DMX %d) ", (char *)name.c_str(), (char *)channel.c_str(), KNX, DMX);
+
+ svector assignedChannels = patchMap[KNX]; // check if already patched
+ for (vector<string>::iterator i = assignedChannels.begin(); i != assignedChannels.end(); ++i) {
+ if ((*i)==name) { // already patched;
+ return;
+ }
+ }
+
+ patchMap[KNX].push_back(name); // no, add to patchMap
+
+}
+
+void Fixture::Patch(map<int, svector>& patchMap, const string channel, const string DMX, const string KNX) {
+ Patch(patchMap, channel, readdaddr(DMX), readgaddr((char *) KNX.c_str()));
+}
+
+void Fixture::SetFadeTime(const float t) {
+ fadeTime = t;
+ fadeStep = (t<=0) ? 256 : 256/(t*1e6/FADING_INTERVAL);
+ syslog(LOG_DEBUG, "Fixture '%s': Set Fadetime to %.2f s'(%.2f steps/interval)", (char *)name.c_str(), fadeTime, fadeStep);
+}
+
+void Fixture::PatchFadeTime(const int KNX) {
+ fadeTimeKNX = KNX;
+}
+
+void Fixture::Update(const int KNX, const int val) {
+ for(std::map<string, int>::const_iterator i = channelKNX.begin(); i != channelKNX.end(); ++i) {
+ if (i->second == KNX) {
+ channelValue[i->first] = val;
+ syslog(LOG_DEBUG, "Updated channel '%s' to %d", (char *)i->first.c_str(), val);
+ }
+ }
+}
+
+void Fixture::Refresh(map<int, ola::DmxBuffer>& output) {
+ for(std::map<string, int>::const_iterator i = channelDMX.begin(); i != channelDMX.end(); ++i) {
+ int dmxuniverse = (int) (i->second / 512) , dmxchannel = i->second % 512;
+ int oldValue = output[dmxuniverse].Get(dmxchannel);
+ int newValue = channelValue[i->first];
+ if (oldValue<newValue) {
+ channelFloatValue[i->first] += fadeStep;
+ if (channelFloatValue[i->first]>newValue) {
+ channelFloatValue[i->first] = newValue;
+ }
+ output[dmxuniverse].SetChannel(dmxchannel, (int) channelFloatValue[i->first]);
+ }
+ if (oldValue>newValue) {
+ channelFloatValue[i->first] -= fadeStep;
+ if (channelFloatValue[i->first]<newValue) {
+ channelFloatValue[i->first] = newValue;
+ }
+ output[dmxuniverse].SetChannel(dmxchannel, (int) channelFloatValue[i->first]);
+ }
+ }
+}
+
+}
+
+pthread_mutex_t zonelock = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t initlock = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t standbylock = PTHREAD_MUTEX_INITIALIZER;
+
+string eibd_url = "local:/tmp/eib";
+string conf_file = "knxdmxd.conf";
+int pidFilehandle;
+string pidfilename = "/var/run/dmxknxd.pid";
+
+map<int, ola::DmxBuffer> dmxWriteBuffer;
+map<string, knxdmxd::Fixture> fixtureList;
+map<int, svector> patchMap;
+
+void daemonShutdown() {
+ //FIXME: clean exit pthread_exit(NULL); pthread_cancel(..);
+ //close(udpSocket);
+ syslog(LOG_INFO, "%s daemon exiting", DAEMON_NAME);
+ fprintf(stderr, "%s daemon exiting", DAEMON_NAME);
+ close(pidFilehandle);
+ unlink((char *)pidfilename.c_str());
+ exit(EXIT_SUCCESS);
+}
+
+void signal_handler(int sig) {
+ switch(sig) {
+ case SIGHUP:
+ syslog(LOG_WARNING, "Received SIGHUP signal.");
+ break;
+ case SIGTERM:
+ syslog(LOG_WARNING, "Received SIGTERM signal.");
+ daemonShutdown();
+ break;
+ case SIGINT:
+ syslog(LOG_WARNING, "Received SIGINT signal.");
+ daemonShutdown();
+ break;
+ default:
+ syslog(LOG_WARNING, "Unhandled signal (%d) %s", sig, strsignal(sig));
+ break;
+ }
+}
+
+/*void *sendKNXdgram(int type, int dpt, eibaddr_t dest, unsigned char val) {
+ int len = 0;
+ EIBConnection *con;
+ unsigned char buf[255] = { 0, 0x80 };
+ buf[1] = type; //0x40 response, 0x80 write
+ syslog(LOG_DEBUG,"Send KNX dgram Type %d DPT %d dest %d val %d",type,dpt,dest,val);
+ con = EIBSocketURL ((char *)eibd_url.c_str());
+ if (!con)
+ syslog(LOG_WARNING,"sendknxdgram: Open failed");
+ if (EIBOpenT_Group (con, dest, 1) == -1)
+ syslog(LOG_WARNING,"sendknxdgram: Connect failed");
+ switch (dpt)
+ {
+ case 0:
+ len=1;
+ //for(i = 0; i < strlen(val)/2; i++)
+ //raw value: nothing for now
+ break;
+ case 1:
+ buf[1] |= val & 0x3f;
+ len=2;
+ break;
+ case 3:
+ // EIS2/DPT3 4bit dim
+ buf[1] |= val & 0x3f;
+ len=2;
+ break;
+ case 5:
+ buf[2] = val*255/100;
+ len=3;
+ break;
+ case 51:
+ case 5001:
+ buf[2] = val;
+ len=3;
+ break;
+ case 6:
+ case 6001:
+ //FIXME: This is basically wrong but as we get a uchar we expect the sender to know..
+ buf[2] = val;
+ len=3;
+ break;
+ }
+
+ len = EIBSendAPDU (con, len, buf);
+ if (len == -1)
+ syslog (LOG_WARNING,"sendknxdram: Request failed");
+ EIBClose (con);
+ usleep(50*1000); //throttle a little (50ms/max 20tps)
+ return 0;
+} */
+
+void sigtime(int signo)
+{
+ for(std::map<string, knxdmxd::Fixture>::const_iterator i = fixtureList.begin(); i != fixtureList.end(); ++i) {
+ fixtureList[i->first].Refresh(dmxWriteBuffer);
+ }
+ signal(SIGALRM, sigtime);
+}
+
+void *worker(void *) {
+ syslog(LOG_DEBUG, "Internal worker thread started");
+
+ signal(SIGALRM, sigtime);
+
+ itimerval itm;
+ itm.it_interval.tv_sec=0;
+ itm.it_value.tv_sec = 0;
+ itm.it_interval.tv_usec = FADING_INTERVAL; // 20 ms is enough
+ itm.it_value.tv_usec = FADING_INTERVAL;
+ setitimer(ITIMER_REAL,&itm,0);
+
+ while (1) {
+ sleep(POLLING_INTERVAL);
+ }
+
+ pthread_exit(NULL);
+}
+
+/*void *sendKNXresponse(eibaddr_t dest, int zone, int func) {
+ syslog(LOG_DEBUG, "KNX response %d zone %d func %d", dest,zone,func);
+ pthread_mutex_lock (&zonelock);
+ switch (func) {
+ case 0:
+ case 20:
+ sendKNXdgram (0x40,1,dest,zones[zone].zonepower);
+ break;
+ case 1:
+ case 21:
+ sendKNXdgram (0x40,51,dest,zones[zone].srcid);
+ break;
+ case 2:
+ case 22:
+ sendKNXdgram (0x40,5,dest,zones[zone].volume*2);
+ break;
+ case 3:
+ case 23:
+ if (zones[zone].bass<10)
+ sendKNXdgram (0x40,51,dest,zones[zone].bass-10+256);
+ else
+ sendKNXdgram (0x40,51,dest,zones[zone].bass-10);
+ break;
+ case 4:
+ case 24:
+ if (zones[zone].treble<10)
+ sendKNXdgram (0x40,51,dest,zones[zone].treble-10+256);
+ else
+ sendKNXdgram (0x40,51,dest,zones[zone].treble-10);
+ break;
+ case 5:
+ case 25:
+ sendKNXdgram (0x40,1,dest,zones[zone].loudness);
+ break;
+ case 6:
+ case 26:
+ if (zones[zone].balance<10)
+ sendKNXdgram (0x40,51,dest,zones[zone].balance-10+256);
+ else
+ sendKNXdgram (0x40,51,dest,zones[zone].balance-10);
+ break;
+ case 27:
+ sendKNXdgram (0x40,1,dest,zones[zone].partymode);
+ break;
+ case 28:
+ sendKNXdgram (0x40,1,dest,zones[zone].dnd);
+ break;
+ case 29:
+ sendKNXdgram (0x40,5,dest,zones[zone].onvolume*2);
+ break;
+ }
+ pthread_mutex_unlock (&zonelock);
+ return 0;
+}
+*/
+void *handleKNXdgram(eibaddr_t dest, unsigned char* buf, int len){
+ unsigned char val;
+ switch (buf[1] & 0xC0) {
+ case 0x00:
+// sendKNXresponse (dest,zone+(controller*ZONES_PER_CONTROLLER),func);
+ break;
+ case 0x40:
+ //FIXME: response dunno
+ break;
+ case 0x80:
+ if (buf[1] & 0xC0) {
+ if (len == 2)
+ val = buf[1] & 0x3F;
+ else
+ val = buf[2];
+ svector uFixtures = patchMap.find(dest)->second;
+ for (unsigned int i=0; i < uFixtures.size(); i++) {
+ fixtureList[uFixtures[i]].Update(dest, val);
+ }
+ syslog(LOG_DEBUG, "Received %d @ %d, updated %d fixtures", val, dest, (int) uFixtures.size());
+ }
+ break;
+ }
+ return 0;
+}
+
+
+void *olahandler(void *) { // thread just reliably sends the data to DMX via OLA
+ syslog(LOG_DEBUG, "OLA sender thread started");
+
+ ola::InitLogging(ola::OLA_LOG_WARN, ola::OLA_LOG_STDERR);
+
+ while (1) { // retry forever
+
+ ola::StreamingClient ola_client;
+
+ if (!ola_client.Setup()) { // setup client
+ syslog(LOG_WARNING, "OLA: Client setup failed");
+ sleep(RETRY_TIME);
+ continue;
+ }
+
+ syslog(LOG_INFO, "OLA: Client connected");
+
+ while (1) { // loop forever
+ int error_flag=0;
+ for(std::map<int, ola::DmxBuffer>::const_iterator i = dmxWriteBuffer.begin(); i != dmxWriteBuffer.end(); ++i) {
+ int universe = i->first;
+ if (!ola_client.SendDmx(universe, i->second)) { // send all universes
+ syslog(LOG_WARNING, "OLA: failed to send universe %d", universe);
+ error_flag = 1;
+ break; // something went wrong
+ }
+ }
+ if (error_flag==1) {
+ sleep(RETRY_TIME);
+ break;
+ }
+
+ usleep(20000);
+ }
+
+ ola_client.Stop(); // close the client
+ }
+
+ pthread_exit(NULL);
+}
+
+
+void *knxhandler(void *) {
+ syslog(LOG_DEBUG, "KNX reader thread started");
+ int len;
+ EIBConnection *con;
+ eibaddr_t dest;
+ eibaddr_t src;
+ unsigned char buf[255];
+
+ while (1) //retry infinite
+ {
+ con = EIBSocketURL ((char *)eibd_url.c_str());
+ if (!con) {
+ syslog(LOG_WARNING, "eibd: Open failed");
+ sleep(RETRY_TIME);
+ continue;
+ }
+
+ if (EIBOpen_GroupSocket (con, 0) == -1) {
+ syslog(LOG_WARNING, "eibd: Connect failed");
+ sleep(RETRY_TIME);
+ continue;
+ }
+
+ while (1)
+ {
+ len = EIBGetGroup_Src (con, sizeof (buf), buf, &src, &dest);
+ if (len == -1) {
+ syslog(LOG_WARNING, "eibd: Read failed");
+ sleep(RETRY_TIME);
+ break;
+ }
+ if (len < 2) {
+ syslog(LOG_WARNING, "eibd: Invalid Packet");
+ break;
+ }
+ if (buf[0] & 0x3 || (buf[1] & 0xC0) == 0xC0) {
+ syslog(LOG_WARNING, "eibd: Unknown APDU from %d to %d",src,dest);
+ break;
+ } else {
+ if ( patchMap.count(dest)<=0 ) //not for us
+ continue;
+ handleKNXdgram(dest,buf,len);
+ }
+ }
+ syslog(LOG_WARNING,"eibd: closed connection"); //break in read-loop
+ EIBClose (con);
+ }
+ pthread_exit(NULL);
+}
+
+void load_config() {
+
+/* bpt::ptree config;
+
+ read_xml(conf_file, config);
+
+ BOOST_FOREACH( bpt::ptree::value_type const& e, config) {
+ if( e.first == "fixture" ) {
+ string name = e.second.get<std::string>("<xmlattr>.name");
+ knxdmxd::Fixture f(name);
+ BOOST_FOREACH( bpt::ptree::value_type const& c, e.second) {
+ if (c.first == "channel") {
+ f.Patch(patchMap, c.second.data(), c.second.get<std::string>("<xmlattr>.dmx"), c.second.get<std::string>("<xmlattr>.knx"));
+ }
+ if (c.first == "fading") {
+ float t;
+ string content = c.second.data();
+ sscanf((char*) content.c_str(), "%f", &t);
+ f.SetFadeTime((int) (t*1.e6));
+ }
+ }
+ fixtureList[name] = f;
+ }
+
+ } */
+ struct json_object *config;
+
+ config = json_object_from_file((char *)conf_file.c_str());
+ // first all fixtures
+ struct json_object *fixtures = json_object_object_get(config, "fixtures");
+
+ int fixturenum = json_object_array_length(fixtures);
+
+ for (int i=0; i<fixturenum; i++) { // read all
+ // get fixture
+ struct json_object *fixture = json_object_array_get_idx(fixtures, i);
+
+ // get name & create
+ string fname(json_object_get_string(json_object_object_get(fixture, "name")));
+ knxdmxd::Fixture f(fname);
+
+ // get channels & patch them
+ struct json_object *channels = json_object_object_get(fixture, "channels");
+ int channelnum = json_object_array_length(channels);
+ for (int j=0; j<channelnum; j++) { // read all
+ // get channel
+ struct json_object *channel = json_object_array_get_idx(channels, j);
+ string cname(json_object_get_string(json_object_object_get(channel, "name")));
+ string cdmx(json_object_get_string(json_object_object_get(channel, "dmx")));
+ string cknx(json_object_get_string(json_object_object_get(channel, "knx")));
+ f.Patch(patchMap, cname, cdmx, cknx);
+ }
+
+ // get fading
+ struct json_object *fading = json_object_object_get(fixture, "fading");
+ float ftime = (fading) ? json_object_get_double(json_object_object_get(fading, "time")) : 0;
+ f.SetFadeTime(ftime);
+
+ fixtureList[fname] = f;
+ }
+
+ return;
+}
+
+int main(int argc, char **argv) {
+ int daemonize = 0;
+ int c;
+ //char *p;
+ char pidstr[255];
+
+ while ((c = getopt (argc, argv, "d:p:u:c:")) != -1)
+ switch (c) {
+ case 'd':
+ daemonize = 1;
+ break;
+ case 'p':
+ pidfilename.assign(optarg);
+ break;
+ case 'u':
+ eibd_url.assign(optarg);
+ break;
+ case 'c':
+ conf_file.assign(optarg);
+ break;
+ case '?':
+ //FIXME: check arguments better, print_usage
+ fprintf (stderr, "Unknown option `-%c'.\nUsage: %s %s", optopt, argv[0], USAGESTRING);
+ return 1;
+ default:
+ abort ();
+ }
+
+ //FIXME: clean shutdown in sub-thread with signals?
+ signal(SIGHUP, signal_handler);
+ signal(SIGTERM, signal_handler);
+ signal(SIGINT, signal_handler);
+ signal(SIGQUIT, signal_handler);
+
+ if (!daemonize) {
+ setlogmask(LOG_UPTO(LOG_DEBUG));
+ openlog(DAEMON_NAME, LOG_CONS | LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_USER);
+ syslog(LOG_DEBUG, "startup with debug; pidfile: %s, eibd: %s",
+ (char *)pidfilename.c_str(), (char *)eibd_url.c_str());
+ } else {
+ setlogmask(LOG_UPTO(LOG_INFO));
+ openlog(DAEMON_NAME, LOG_CONS, LOG_USER);
+ }
+
+ syslog(LOG_INFO, "using config-file %s", (char *)conf_file.c_str());
+
+ load_config();
+
+ pid_t pid, sid;
+
+ if (daemonize) {
+ syslog(LOG_INFO, "starting daemon");
+
+ pid = fork();
+ if (pid < 0) {
+ exit(EXIT_FAILURE);
+ }
+ if (pid > 0) {
+ exit(EXIT_SUCCESS);
+ }
+ umask(0);
+ sid = setsid();
+ if (sid < 0) {
+ exit(EXIT_FAILURE);
+ }
+ if ((chdir("/")) < 0) {
+ exit(EXIT_FAILURE);
+ }
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+ }
+ //FIXME: output errors to stderr, change order
+ pidFilehandle = open((char *)pidfilename.c_str(), O_RDWR|O_CREAT, 0600);
+ if (pidFilehandle == -1 )
+ {
+ syslog(LOG_INFO, "Could not open pidfile %s, exiting", (char *)pidfilename.c_str());
+ fprintf(stderr, "Could not open pidfile %s, exiting", (char *)pidfilename.c_str());
+ exit(EXIT_FAILURE);
+ }
+ if (lockf(pidFilehandle,F_TLOCK,0) == -1)
+ {
+ syslog(LOG_INFO, "Could not lock pidfile %s, exiting", (char *)pidfilename.c_str());
+ fprintf(stderr, "Could not lock pidfile %s, exiting", (char *)pidfilename.c_str());
+ exit(EXIT_FAILURE);
+ }
+ sprintf(pidstr,"%d\n",getpid());
+ c = write(pidFilehandle, pidstr, strlen(pidstr));
+
+ int knxthread, olathread, workerthread;
+ pthread_t threads[NUM_THREADS];
+ // PTHREAD_CREATE_DETACHED?
+ knxthread = pthread_create(&threads[1], NULL, knxhandler, NULL); //id, thread attributes, subroutine, arguments
+ olathread = pthread_create(&threads[2], NULL, olahandler, NULL); //id, thread attributes, subroutine, arguments
+ workerthread = pthread_create(&threads[3], NULL, worker, NULL); //id, thread attributes, subroutine, arguments
+ syslog(LOG_DEBUG,"Threads created: %d %d %d",knxthread, olathread, workerthread);
+ //TODO: Maybe another console/TCP-server/Logging thread?
+ while (1) {
+// syslog(LOG_DEBUG, "%s daemon running", DAEMON_NAME);
+ sleep(POLLING_INTERVAL);
+ }
+ syslog(LOG_INFO, "%s daemon exiting", DAEMON_NAME);
+ // TODO: Free any allocated resources before exiting - we never get here though -> signal handler
+ exit(EXIT_SUCCESS);
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|