+++ /dev/null
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import with_statement
-import os
-import os.path
-import sys
-import threading
-import logging
-import logging.handlers
-import time
-import signal
-import re
-import subprocess
-import ConfigParser
-import traceback
-import json
-import zmq
-
-logger = logging.getLogger()
-logger.setLevel(logging.INFO)
-lh_syslog = logging.handlers.SysLogHandler(address="/dev/log",facility=logging.handlers.SysLogHandler.LOG_LOCAL2)
-lh_syslog.setFormatter(logging.Formatter('bridge-old-sensors.py: %(levelname)s %(message)s'))
-logger.addHandler(lh_syslog)
-lh_stderr = logging.StreamHandler()
-logger.addHandler(lh_stderr)
-
-######## Config File Data Class ############
-
-class UWSConfig:
- def __init__(self,configfile=None):
- #Synchronisation
- self.lock=threading.Lock()
- self.finished_reading=threading.Condition(self.lock)
- self.finished_writing=threading.Condition(self.lock)
- self.currently_reading=0
- self.currently_writing=False
- #Config Data
- self.configfile=configfile
- self.config_parser=ConfigParser.ConfigParser()
- self.config_parser.add_section('sensors')
- self.config_parser.set('sensors','remote_cmd',"ssh -i /flash/tuer/id_rsa -o PasswordAuthentication=no -o StrictHostKeyChecking=no %RHOST% %RSHELL% %RSOCKET%")
- self.config_parser.set('sensors','remote_host',"root@slug.realraum.at")
- self.config_parser.set('sensors','remote_socket',"/var/run/powersensordaemon/cmd.sock")
- self.config_parser.set('sensors','remote_shell',"usocket")
- self.config_parser.add_section('debug')
- self.config_parser.set('debug','enabled',"False")
- self.config_mtime=0
- if not self.configfile is None:
- try:
- cf_handle = open(self.configfile,"r")
- cf_handle.close()
- except IOError:
- self.writeConfigFile()
- else:
- self.checkConfigUpdates()
-
- def guardReading(self):
- with self.lock:
- while self.currently_writing:
- self.finished_writing.wait()
- self.currently_reading+=1
-
- def unguardReading(self):
- with self.lock:
- self.currently_reading-=1
- self.finished_reading.notifyAll()
-
- def guardWriting(self):
- with self.lock:
- self.currently_writing=True
- while self.currently_reading > 0:
- self.finished_reading.wait()
-
- def unguardWriting(self):
- with self.lock:
- self.currently_writing=False
- self.finished_writing.notifyAll()
-
- def checkConfigUpdates(self):
- global logger
- if self.configfile is None:
- return
- logging.debug("Checking Configfile mtime: "+self.configfile)
- try:
- mtime = os.path.getmtime(self.configfile)
- except (IOError,OSError):
- return
- if self.config_mtime < mtime:
- logging.debug("Reading Configfile")
- self.guardWriting()
- try:
- self.config_parser.read(self.configfile)
- self.config_mtime=os.path.getmtime(self.configfile)
- except (ConfigParser.ParsingError, IOError), pe_ex:
- logging.error("Error parsing Configfile: "+str(pe_ex))
- self.unguardWriting()
- self.guardReading()
- if self.config_parser.get('debug','enabled') == "True":
- logger.setLevel(logging.DEBUG)
- else:
- logger.setLevel(logging.INFO)
- self.unguardReading()
-
- def writeConfigFile(self):
- if self.configfile is None:
- return
- logging.debug("Writing Configfile "+self.configfile)
- self.guardReading()
- try:
- cf_handle = open(self.configfile,"w")
- self.config_parser.write(cf_handle)
- cf_handle.close()
- self.config_mtime=os.path.getmtime(self.configfile)
- except IOError, io_ex:
- logging.error("Error writing Configfile: "+str(io_ex))
- self.configfile=None
- self.unguardReading()
-
- def __getattr__(self, name):
- underscore_pos=name.find('_')
- if underscore_pos < 0:
- raise AttributeError
- rv=None
- self.guardReading()
- try:
- rv = self.config_parser.get(name[0:underscore_pos], name[underscore_pos+1:])
- except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
- self.unguardReading()
- raise AttributeError
- self.unguardReading()
- return rv
-
-
-######## r3 ZMQ ############
-
-def sendR3Message(socket, structname, datadict):
- socket.send_multipart([structname, json.dumps(datadict)])
-
-######## Sensor Bridge ############
-tracksensor_running=True
-def trackSensorStatus(uwscfg, zmqsocket):
- global sshp, tracksensor_running
- RE_TEMP = re.compile(r'temp(\d): (\d+\.\d+)')
- RE_PHOTO = re.compile(r'photo(\d): [^0-9]*?(\d+)',re.I)
- RE_MOVEMENT = re.compile(r'movement',re.I)
- RE_BUTTON = re.compile(r'button\d?|PanicButton',re.I)
- RE_ERROR = re.compile(r'Error: (.+)',re.I)
- while tracksensor_running:
- uwscfg.checkConfigUpdates()
- sshp = None
- try:
- cmd = uwscfg.sensors_remote_cmd.replace("%RHOST%",uwscfg.sensors_remote_host).replace("%RSHELL%",uwscfg.sensors_remote_shell).replace("%RSOCKET%",uwscfg.sensors_remote_socket).split(" ")
- logging.debug("trackSensorStatus: Executing: "+" ".join(cmd))
- sshp = subprocess.Popen(cmd, bufsize=1024, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False)
- logging.debug("trackSensorStatus: pid %d: running=%d" % (sshp.pid,sshp.poll() is None))
- if not sshp.poll() is None:
- raise Exception("trackSensorStatus: subprocess %d not started ?, returncode: %d" % (sshp.pid,sshp.returncode))
- #sshp.stdin.write("listen movement\nlisten button\nlisten sensor\n")
- time.sleep(5) #if we send listen bevor usocket is running, we will never get output
- #sshp.stdin.write("listen all\n")
- logging.debug("trackSensorStatus: send: listen movement, etc")
- sshp.stdin.write("listen movement\n")
- sshp.stdin.write("listen button\n")
- sshp.stdin.write("listen sensor\n")
- #sshp.stdin.write("sample temp0\n")
- sshp.stdin.flush()
- while tracksensor_running:
- if not sshp.poll() is None:
- raise Exception("trackSensorStatus: subprocess %d finished, returncode: %d" % (sshp.pid,sshp.returncode))
- line = sshp.stdout.readline()
- if len(line) < 1:
- raise Exception("EOF on Subprocess, daemon seems to have quit, returncode: %d",sshp.returncode)
- logging.debug("trackSensorStatus: Got Line: " + line)
- m = RE_BUTTON.match(line)
- if not m is None:
- sendR3Message(zmqsocket, "BoreDoomButtonPressEvent", {"Ts":int(time.time())})
- continue
- m = RE_MOVEMENT.match(line)
- if not m is None:
- sendR3Message(zmqsocket, "MovementSensorUpdate", {"Sensorindex":0, "Ts":int(time.time())})
- continue
- m = RE_TEMP.match(line)
- if not m is None:
- sendR3Message(zmqsocket, "TempSensorUpdate", {"Sensorindex":int(m.group(1)), "Value":float(m.group(2)), "Ts":int(time.time())})
- continue
- m = RE_PHOTO.match(line)
- if not m is None:
- sendR3Message(zmqsocket, "IlluminationSensorUpdate", {"Sensorindex":int(m.group(1)), "Value":int(m.group(2)), "Ts":int(time.time())})
- continue
- m = RE_ERROR.match(line)
- if not m is None:
- logging.error("trackSensorStatus: got: "+line)
- except Exception, ex:
- logging.error("trackSensorStatus: "+str(ex))
- traceback.print_exc(file=sys.stdout)
- if not sshp is None and sshp.poll() is None:
- if sys.hexversion >= 0x020600F0:
- sshp.terminate()
- else:
- subprocess.call(["kill",str(sshp.pid)])
- time.sleep(1.5)
- if sshp.poll() is None:
- logging.error("trackSensorStatus: subprocess still alive, sending SIGKILL to pid %d" % (sshp.pid))
- if sys.hexversion >= 0x020600F0:
- sshp.kill()
- else:
- subprocess.call(["kill","-9",str(sshp.pid)])
- time.sleep(5)
-
- ############ Main Routine ############
-
-def exitHandler(signum, frame):
- global tracksensor_running, sshp
- logging.info("Bridge stopping")
- tracksensor_running=False
- try:
- if sys.hexversion >= 0x020600F0:
- sshp.terminate()
- else:
- subprocess.call(["kill",str(sshp.pid)])
- except:
- pass
- time.sleep(0.1)
- try:
- zmqpub.close()
- zmqctx.destroy()
- except:
- pass
- sys.exit(0)
-
-#signals proapbly don't work because of readline
-#signal.signal(signal.SIGTERM, exitHandler)
-signal.signal(signal.SIGINT, exitHandler)
-signal.signal(signal.SIGQUIT, exitHandler)
-
-logging.info("Sensor Bridge started")
-
-#option and only argument: path to config file
-if len(sys.argv) > 1:
- uwscfg = UWSConfig(sys.argv[1])
-else:
- uwscfg = UWSConfig()
-
-#Start zmq connection to publish / forward sensor data
-zmqctx = zmq.Context()
-zmqctx.linger = 0
-zmqpub = zmqctx.socket(zmq.PUB)
-zmqpub.connect("tcp://torwaechter.realraum.at:4243")
-
-#listen for sensor data and forward them
-trackSensorStatus(uwscfg, zmqpub)
-
-zmqpub.close()
-zmqctx.destroy()
-
-
+++ /dev/null
-#!/usr/bin/perl -w
-
-use Socket;
-use strict;
-my $fh;
-
-my $zmqclient = "/flash/tuer/door_client_zmq";
-
-my $keys;
-my %good;
-
-open $keys,'/flash/phone';
-while (<$keys>)
-{
- chomp;
- if ($_ =~ /^(\S+)\s+(.+)$/)
- {
- $good{$1}=$2;
- }
-}
-my $id = $ARGV[1];
-$id =~ s/^0/+43/;
-my $action = $ARGV[0];
-if ($good{$id})
-{
- if ($action == 1591)
- {
- send_to_fifo("close Phone ".$good{$id});
- } elsif ($action == 1590) {
- send_to_fifo("open Phone ".$good{$id});
- } elsif ($action == 1592) {
- send_to_fifo("reset Phone ".$good{$id});
- } else {
- send_to_fifo("log invalid action $action, but valid Phone $id");
- }
-} else {
- send_to_fifo("log invalid Phone $id");
-}
-exit 0;
-
-sub send_to_fifo
-{
- open(my $conn, "| ".$zmqclient);
- #socket(my $conn, PF_UNIX, SOCK_STREAM,0) || die "socket: $!";
- #connect($conn, $socketaddr) || die "socket connect: $!";
- print $conn shift(@_)."\n";
- close($conn);
-}
-
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package brain
-
-import "errors"
-
-type informationtuple struct {
- name string
- value interface{}
-}
-
-type informationretrievalpath struct {
- name string
- returnpath chan interface{}
-}
-
-type hippocampus map[string]interface{}
-
-type Brain struct {
- storeTuple chan informationtuple
- retrieveValue chan informationretrievalpath
- shutdown chan bool
-}
-
-func New() *Brain {
- b := new(Brain)
- b.storeTuple = make(chan informationtuple)
- b.retrieveValue = make(chan informationretrievalpath)
- go b.runBrain()
- return b
-}
-
-func (b *Brain) runBrain() {
- var h hippocampus = make(hippocampus)
- for {
- select {
- case newtuple := <- b.storeTuple:
- h[newtuple.name] = newtuple.value
-
- case retrievvalue := <- b.retrieveValue:
- v, e := h[retrievvalue.name]
- if e {
- retrievvalue.returnpath <- v
- } else {
- retrievvalue.returnpath <- nil
- }
-
- case <- b.shutdown:
- break
- }
- }
-}
-
-func (b *Brain) Shutdown() {
- b.shutdown <- true
-}
-
-func (b *Brain) Oboite(name string, value interface{}) {
- b.storeTuple <- informationtuple{name, value}
-}
-
-func (b *Brain) OmoiDashite(name string) (interface{}, error) {
- rc := make(chan interface{})
- b.retrieveValue <- informationretrievalpath{name, rc}
- v := <- rc
- if v == nil {
- return v, errors.New("name not in brain")
- }
- return v, nil
-}
-
-func (b *Brain) OmoiDashiteBool(name string) (bool, error) {
- v, e := b.OmoiDashite(name)
- if e != nil {
- return false, e
- }
- vc, ok := v.(bool)
- if !ok {
- return false, errors.New(name + " does not have type bool")
- }
- return vc, nil
-}
-
-func (b *Brain) OmoiDashiteInt(name string) (int, error) {
- v, e := b.OmoiDashite(name)
- if e != nil {
- return 0, e
- }
- vc, ok := v.(int)
- if !ok {
- return 0, errors.New(name + " does not have type int")
- }
- return vc, nil
-}
-
-func (b *Brain) OmoiDashiteFloat(name string) (float64, error) {
- v, e := b.OmoiDashite(name)
- if e != nil {
- return 0, e
- }
- vc, ok := v.(float64)
- if !ok {
- return 0, errors.New(name + " does not have type float64")
- }
- return vc, nil
-}
-
-func (b *Brain) OmoiDashiteString(name string) (string, error) {
- v, e := b.OmoiDashite(name)
- if e != nil {
- return "", e
- }
- vc, ok := v.(string)
- if !ok {
- return "", errors.New(name + " does not have type string")
- }
- return vc, nil
-}
\ No newline at end of file
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- "fmt"
- "os"
- "flag"
- "log"
- "bufio"
- "bytes"
-)
-
-
-// ---------- Main Code -------------
-
-var (
- cmd_port_ string
- sub_port_ string
- cmd_method_ string
- cmd_user_ string
-)
-
-func init() {
- flag.StringVar(&cmd_port_, "cmdport", "ipc:///run/tuer/door_cmd.ipc", "zmq command socket path")
- flag.StringVar(&sub_port_, "pubport", "tcp://torwaechter.realraum.at:4242", "zmq subscribe/listen socket path")
- flag.StringVar(&cmd_method_, "method", "", "zmq cmd method")
- flag.StringVar(&cmd_user_, "usernick", "", "zmq cmd user identity")
- flag.Parse()
-}
-
-func LineReader(out chan <- [][]byte, stdin * os.File) {
- linescanner := bufio.NewScanner(stdin)
- linescanner.Split(bufio.ScanLines)
- defer close(out)
- for linescanner.Scan() {
- if err := linescanner.Err(); err != nil {
- log.Print(err)
- return
- }
- //text := bytes.Fields(linescanner.Bytes()) //this returns a slice (aka pointer, no array deep-copy here)
- text := bytes.Fields([]byte(linescanner.Text())) //this allocates a string and slices it -> no race-condition with overwriting any data
- if len(text) == 0 {
- continue
- }
- out <- text
- }
-}
-
-func ByteArrayToString(bb [][]byte) string {
- b := bytes.Join(bb, []byte(" "))
- return string(b)
-}
-
-func main() {
- zmqctx, cmd_chans, sub_chans := ZmqsInit(cmd_port_, sub_port_)
- defer cmd_chans.Close()
- defer sub_chans.Close()
- defer zmqctx.Close()
- var listen bool
- var ignore_next uint = 0
-
- user_input_chan := make(chan [][]byte, 1)
- go LineReader(user_input_chan, os.Stdin)
- defer os.Stdin.Close()
-
- for {
- select {
- case input, input_open := (<- user_input_chan):
- if input_open {
- if len(input) == 0 { continue }
- switch string(input[0]) {
- case "help", "?":
- fmt.Println("Available Commands: help, listen, quit. Everything else is passed through to door daemon")
- case "listen":
- listen = true
- fmt.Println("Now listening, @ are broadcasts")
- case "quit":
- os.Exit(0)
- default:
- ignore_next = 2
- cmd_chans.Out() <- input
- reply := <- cmd_chans.In()
- fmt.Println(">",ByteArrayToString(reply))
- }
- } else {
- os.Exit(0)
- }
- case pubsubstuff := <- sub_chans.In():
- if len(pubsubstuff) == 0 { continue}
- if ignore_next > 0 {
- ignore_next--
- continue
- }
- if listen {
- fmt.Println("@",ByteArrayToString(pubsubstuff))
- }
- }
- }
-}
+++ /dev/null
-#!/bin/zsh
-export GO386=387
-export CGO_ENABLED=1
-go-linux-386 clean
-#go-linux-386 build
-#strip ${PWD:t}
-go-linux-386 build -ldflags "-s" && rsync -v --progress ${PWD:t} torwaechter.realraum.at:/flash/tuer/
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- zmq "github.com/vaughan0/go-zmq"
- "time"
- )
-
-// ---------- ZeroMQ Code -------------
-
-func ZmqsInit(cmd_port, sub_port string) (ctx *zmq.Context, cmd_chans, sub_chans *zmq.Channels) {
- var err error
- ctx, err = zmq.NewContext()
- if err != nil {
- panic(err)
- }
- //close only on later panic, otherwise leave open:
- defer func(){ if r:= recover(); r != nil { ctx.Close(); panic(r) } }()
-
- if len(cmd_port) > 0 {
- cmd_sock, err := ctx.Socket(zmq.Req)
- if err != nil {
- panic(err)
- }
- defer func() { if r:= recover(); r != nil { cmd_sock.Close(); panic(r) } }()
-
- cmd_sock.SetRecvTimeout(2 * time.Second)
- cmd_sock.SetSendTimeout(2 * time.Second)
-
- if err = cmd_sock.Connect(cmd_port); err != nil {
- panic(err)
- }
-
- cmd_chans = cmd_sock.ChannelsBuffer(10)
- go zmqsHandleError(cmd_chans)
- } else {
- cmd_chans = nil
- }
-
- if len(sub_port) > 0 {
- sub_sock, err := ctx.Socket(zmq.Sub)
- if err != nil {
- panic(err)
- }
- defer func() { if r:= recover(); r != nil { sub_sock.Close(); panic(r) } }()
-
- sub_sock.Subscribe([]byte{}) //subscribe empty filter -> aka to all messages
-
- if err = sub_sock.Connect(sub_port); err != nil {
- panic(err)
- }
-
- sub_chans = sub_sock.ChannelsBuffer(10)
- go zmqsHandleError(sub_chans)
- } else {
- sub_chans = nil
- }
-
- return
-}
-
-func zmqsHandleError(chans *zmq.Channels) {
- for error := range(chans.Errors()) {
- chans.Close()
- panic(error)
- }
-}
+++ /dev/null
-#!/bin/sh
-clear
-rm /tmp/test.sock 2>/dev/null
-go build && ./door_daemon_go /dev/ttyACM0 || sleep 5
+++ /dev/null
-package main
-import "fmt"
-import "net"
-import "bufio"
-import "strings"
-import "os"
-import "io"
-import "svn.spreadspace.org/realraum/go.svn/termios"
-import "flag"
-import "regexp"
-import "sync"
-import "time"
-
-var lock sync.RWMutex
-
-type DoorConnection struct {
- rw * bufio.ReadWriter
- c net.Conn
- wchan chan string
-}
-
-var DoorConnectionMap = map[uint]DoorConnection {
-}
-
-var cmdHandler = map[string]func([]string,string,*bufio.ReadWriter ) {
- "test":handleCmdTest,
- "open":handleCmdController,
- "close":handleCmdController,
- "toggle":handleCmdController,
-}
-
-
-func readLineSafe(rw *bufio.Reader) (string, error) {
- wasPrefix:=false
- var line string
- for isPrefix:=true;isPrefix; {
- var lineBuf []byte
- var err error
- lineBuf,isPrefix,err = rw.ReadLine()
- if err != nil {
- return "",err
- }
- if isPrefix {
- wasPrefix=true
- } else {
- line=string(lineBuf)
- }
- }
- if wasPrefix {
- fmt.Println("line too long")
- //fmt.Fprintf(rw,"line too long\n")
- //rw.Flush()
- return "",nil
- }
- reg := regexp.MustCompile("\r")
- safe := reg.ReplaceAllString(line, "")
- return safe,nil
-}
-
-func connToReadWriter(c io.Reader,cw io.Writer) (*bufio.ReadWriter) {
- client_r := bufio.NewReaderSize(c,1024)
- client_w := bufio.NewWriterSize(cw,1024)
- return bufio.NewReadWriter(client_r,client_w)
-}
-
-func handleConnection(c net.Conn, client * bufio.ReadWriter, connID uint) () {
- fmt.Println("new connection")
- defer func () {
- lock.Lock()
- delete(DoorConnectionMap,connID)
- lock.Unlock()
- }()
- for {
- line,err:=readLineSafe(bufio.NewReader(client))
- if err != nil {
- if err.Error() != "EOF" {
- fmt.Printf("Error: readLineSafe returned %v\n",err.Error())
- } else {
- fmt.Printf("Connection closed by remote host\n");
- }
- c.Close()
- return
- }
- if line == "" {
- continue
- }
- fmt.Printf("Received: %v\n", line)
- tokens:=strings.Fields(line)
- remainStr:=strings.Join(tokens[1:]," ")
- handleCmd(tokens,remainStr,client)
- }
-}
-
-func handleCmd(tokens []string, remainStr string,client * bufio.ReadWriter) {
- cmd:=tokens[0]
- func_ptr,present := cmdHandler[cmd]
- if present {
- func_ptr(tokens, remainStr,client)
- } else {
- fmt.Printf("Error: unknown Cmd: %v\n", cmd)
- }
-}
-
-func handleCmdTest(tokens []string, remainStr string, client * bufio.ReadWriter) {
- //cmd:=tokens[0]
- fmt.Printf("Test: %v\n", remainStr)
-}
-
-func handleCmdController(tokens []string, remainStr string, client * bufio.ReadWriter) {
- cmd:=tokens[0]
- s_r:=strings.NewReader(cmd)
- char := make([]byte,1)
- s_r.Read(char)
- fmt.Println(string(char))
-}
-
-
-func openTTY(name string) *os.File {
- file, err := os.OpenFile(name,os.O_RDWR ,0600) // For read access.
- if err != nil {
- fmt.Println(err.Error())
- }
- termios.Ttyfd(file.Fd())
- termios.SetRaw()
- return file
-}
-func usage() {
- fmt.Fprintf(os.Stderr, "usage: myprog [inputfile]\n")
- flag.PrintDefaults()
- os.Exit(2)
-}
-
-func SerialWriter(c chan string, serial * os.File ) {
- for {
- serial.WriteString(<-c)
- serial.Sync()
- }
-}
-
-func SerialReader(c chan string , serial * bufio.Reader) {
- for {
- s,err := readLineSafe(serial)
- if (s=="") {
- continue
- }
- if (err!=nil) {
- fmt.Printf("Error in read from serial: %v\n",err.Error())
- os.Exit(1)
- }
- //fmt.Printf("Serial: Read %v\n",s);
- c<-s
- }
-}
-
-func openSerial(filename string) (chan string,chan string) {
- serial:=openTTY(filename)
- in:=make(chan string)
- out:=make(chan string)
- go SerialWriter(out,serial)
- go SerialReader(in,bufio.NewReaderSize(serial,128))
- return in,out
-}
-
-func SerialHandler(serial_i chan string) {
- for {
- line:=<-serial_i
- fmt.Printf("Serial Read: %s\n",line)
- lock.RLock()
- for _, v := range DoorConnectionMap{
- select {
- case v.wchan<-line:
-
- case <-time.After(2):
-
- }
- }
- lock.RUnlock()
- }
-}
-
-func chanWriter(c chan string, w io.Writer) {
- for {
- line := <-c
- w.Write([]byte(line))
- w.Write([]byte("\n"))
- }
-}
-func main() {
-// lock = make(sync.RWMutex)
- flag.Usage = usage
- flag.Parse()
-
- args := flag.Args()
- if len(args) < 1 {
- fmt.Println("Input file is missing.");
- os.Exit(1);
- }
- serial_i,serial_o:=openSerial(args[0])
- go SerialHandler(serial_i)
- serial_o<-"f"
-
- ln, err := net.Listen("unix", "/tmp/test.sock")
- if err != nil {
- fmt.Printf("Error: %s\n",err.Error())
- return
- }
- fmt.Printf("Listener started\n")
-
- var connectionID uint =0
- for {
- conn, err := ln.Accept()
- if err != nil {
- // handle error
- continue
- }
- client:=connToReadWriter(conn,conn)
- connectionID++
- writeChan := make(chan string)
- lock.Lock()
- DoorConnectionMap[connectionID]= DoorConnection{ rw:client,c:conn, wchan:writeChan }
- lock.Unlock()
- go handleConnection(conn,client,connectionID)
- go chanWriter(writeChan,conn)
- }
-}
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- "errors"
- "time"
-)
-
-type DoorCmdHandler struct {
- Checker func([][]byte) error
- FirmwareChar string
-}
-
-var cmdToDoorCmdHandler = map[string]DoorCmdHandler{
- "open": DoorCmdHandler{checkCmdDoorControl, "o"},
- "close": DoorCmdHandler{checkCmdDoorControl, "c"},
- "toggle": DoorCmdHandler{checkCmdDoorControl, "t"},
- "status": DoorCmdHandler{checkCmdNoArgs, "s"},
-}
-
-// ---------- Talk with Firmware directly in response to stuff it sends ------------
-
-// The problem is this:
-// If the key/motor turns just far enough so that the door is unlocked,
-// but still get's blocked on the way (because the door clamped)
-// the firmware will enter state "timeout_after_open" instead of "open"
-// In this state, manual moving the key/cogwheel will not trigger the state "manual_movement"
-// Users however will not notice that the door is in an error state and needs to manually be moved to the real open position,
-// they have after all, already successfully entered the room.
-// Without that information however, the r3-event-broker daemon, cannot tell if the door is being locked manuall from the inside
-// or if someone else is locking the door for other reasons.
-// Thus, if the door has been opened imperfectly and is then closed manually, it will trigger a presence=false event and switch off the lights.
-//
-// As Workaround, the door daemon watches for "timeout_after_open" events.
-// If one is detected and followed by an "door is now ajar" info, we tell the firmware
-// to open the door, causing it to move out of the error state and into the final open key/cogwheel position.
-func WorkaroundFirmware(serial_wr chan string) (in chan [][]byte) {
- in = make(chan [][]byte, 5)
- go func() {
- var last_state_time time.Time
- var last_door_state string
- for firmware_output := range in {
- Debug_.Printf("WorkaroundFirmware Input: %s", firmware_output)
- if len(firmware_output) > 1 && string(firmware_output[0]) == "State:" {
- last_state_time = time.Now()
- last_door_state = string(firmware_output[1])
- }
- if len(firmware_output) == 5 &&
- string(firmware_output[0]) == "Info(ajar):" &&
- string(firmware_output[4]) == "ajar" &&
- time.Now().Sub(last_state_time) < 30*time.Second &&
- last_door_state == "timeout_after_open" {
- //If we were in state "timeout_after_open" and within 30s the door was openend anyway,
- //we send another "open" command
- serial_wr <- cmdToDoorCmdHandler["open"].FirmwareChar
- Syslog_.Print("Telling Firmware to open, since door was ajar'ed after timeout_after_open")
- }
- }
- }()
- return in
-}
-
-// ---------- ZMQ Command Handling Code -------------
-
-func checkCmdDoorControl(tokens [][]byte) error {
- doorctrl_usage := "syntax: <open|close|toggle> <method> <nickname>"
- if len(tokens) < 2 || len(tokens) > 3 {
- return errors.New(doorctrl_usage)
- }
- cmd := string(tokens[0])
- if !(cmd == "open" || cmd == "close" || cmd == "toggle") {
- return errors.New(doorctrl_usage)
- }
- method := string(tokens[1])
- if !(method == "Button" || method == "ssh" || method == "SSH" || method == "Phone") {
- return errors.New("method must be one either Button, SSH or Phone")
- }
- if (len(tokens) == 2 || len(tokens[2]) == 0) && method != "Button" {
- return errors.New("Operator nickname must be given")
- }
- return nil
-}
-
-func checkCmdNoArgs(tokens [][]byte) error {
- if len(tokens) != 1 {
- return errors.New("command does not accept arguments")
- }
- return nil
-}
-
-func HandleCommand(tokens [][]byte, serial_wr chan string, serial_rd chan [][]byte) error {
- if len(tokens) < 1 {
- return errors.New("No Command to handle")
- }
-
- dch, present := cmdToDoorCmdHandler[string(tokens[0])]
- if !present {
- return errors.New("Unknown Command")
- }
-
- if err := dch.Checker(tokens); err != nil {
- return err
- }
-
- serial_wr <- dch.FirmwareChar
- return nil
-}
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import "os"
-import "log"
-import "log/syslog"
-
-type NullWriter struct {}
-func (n *NullWriter) Write(p []byte) (int, error) {return len(p),nil}
-
-var (
- Syslog_ *log.Logger
- Debug_ *log.Logger
-)
-
-func init() {
- Syslog_ = log.New(&NullWriter{}, "", 0)
- Debug_ = log.New(&NullWriter{}, "", 0)
-}
-
-func LogEnableSyslog() {
- var logerr error
- Syslog_, logerr = syslog.NewLogger(syslog.LOG_INFO | (18<<3), 0)
- if logerr != nil { panic(logerr) }
-}
-
-func LogEnableDebuglog() {
- Syslog_ = log.New(os.Stdout, "", log.LstdFlags)
- Debug_ = log.New(os.Stderr, "DEBUG ", log.LstdFlags)
-}
\ No newline at end of file
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- "flag"
- "os"
- "time"
-)
-
-//~ func StringArrayToByteArray(ss []string) [][]byte {
-//~ bb := make([][]byte, len(ss))
-//~ for index, s := range(ss) {
-//~ bb[index] = []byte(s)
-//~ }
-//~ return bb
-//~ }
-
-// ---------- Main Code -------------
-
-var (
- cmd_port_ string
- pub_port_ string
- door_tty_path_ string
- enable_syslog_ bool
- enable_debug_ bool
-)
-
-func init() {
- flag.StringVar(&cmd_port_, "cmdport", "ipc:///run/tuer/door_cmd.ipc", "zmq command socket path")
- flag.StringVar(&pub_port_, "pubport", "tcp://*:4242", "zmq public/listen socket path")
- flag.StringVar(&door_tty_path_, "device", "/dev/door", "door tty device path")
- flag.BoolVar(&enable_syslog_, "syslog", false, "enable logging to syslog")
- flag.BoolVar(&enable_debug_, "debug", false, "enable debug output")
- flag.Parse()
-}
-
-func main() {
- if enable_syslog_ {
- LogEnableSyslog()
- }
- if enable_debug_ {
- LogEnableDebuglog()
- }
- Syslog_.Print("started")
- defer Syslog_.Print("exiting")
-
- zmqctx, cmd_chans, pub_chans := ZmqsInit(cmd_port_, pub_port_)
- defer cmd_chans.Close()
- defer pub_chans.Close()
- defer zmqctx.Close()
-
- serial_wr, serial_rd, err := OpenAndHandleSerial(door_tty_path_, 0)
- defer close(serial_wr)
- if err != nil {
- panic(err)
- }
-
- workaround_in_chan := WorkaroundFirmware(serial_wr)
- defer close(workaround_in_chan)
-
- var next_incoming_serial_is_client_reply bool
- timeout_chan := make(chan bool)
- defer close(timeout_chan)
- for {
- select {
- case incoming_ser_line, is_notclosed := <-serial_rd:
- if is_notclosed {
- //~ if Syslog_ != nil { Syslog_.Print(ByteArrayToString(incoming_ser_line)) }
- if Syslog_ != nil {
- Syslog_.Printf("%s", incoming_ser_line)
- }
- if next_incoming_serial_is_client_reply {
- next_incoming_serial_is_client_reply = false
- cmd_chans.Out() <- incoming_ser_line
- }
- pub_chans.Out() <- incoming_ser_line
- workaround_in_chan <- incoming_ser_line
- } else {
- Syslog_.Print("serial device disappeared, exiting")
- os.Exit(1)
- }
- case tv, timeout_notclosed := <-timeout_chan:
- if timeout_notclosed && tv && next_incoming_serial_is_client_reply {
- next_incoming_serial_is_client_reply = false
- cmd_chans.Out() <- [][]byte{[]byte("ERROR"), []byte("No reply from firmware")}
- }
- case incoming_request, ic_notclosed := <-cmd_chans.In():
- if !ic_notclosed {
- Syslog_.Print("zmq socket died, exiting")
- os.Exit(2)
- }
- if string(incoming_request[0]) == "log" {
- if len(incoming_request) < 2 {
- cmd_chans.Out() <- [][]byte{[]byte("ERROR"), []byte("argument missing")}
- continue
- }
- Syslog_.Printf("Log: %s", incoming_request[1:])
- cmd_chans.Out() <- [][]byte{[]byte("Ok")}
- continue
- }
- Syslog_.Printf("%s", incoming_request)
- if err := HandleCommand(incoming_request, serial_wr, serial_rd); err != nil {
- out_msg := [][]byte{[]byte("ERROR"), []byte(err.Error())}
- cmd_chans.Out() <- out_msg
- } else {
- pub_chans.Out() <- incoming_request
- next_incoming_serial_is_client_reply = true
- go func() { time.Sleep(3 * time.Second); timeout_chan <- true }()
- }
- }
- }
-}
+++ /dev/null
-#!/bin/zsh
-export GO386=387
-export CGO_ENABLED=1
-go-linux-386 clean
-#go-linux-386 build
-#strip ${PWD:t}
-go-linux-386 build -ldflags "-s" && rsync -v --progress ${PWD:t} torwaechter.realraum.at:/flash/tuer/
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- "bufio"
- "bytes"
- "os"
- "errors"
- "svn.spreadspace.org/realraum/go.svn/termios"
-)
-
-
-// ---------- Serial TTY Code -------------
-
-func openTTY(name string, speed uint) (file *os.File, err error) {
- file, err = os.OpenFile(name,os.O_RDWR, 0666)
- if err != nil { return }
- if err = termios.SetRawFile(file); err != nil { return }
- switch speed {
- case 0: // set no baudrate
- case 1200: err = termios.SetSpeedFile(file, termios.B1200)
- case 2400: err = termios.SetSpeedFile(file, termios.B2400)
- case 4800: err = termios.SetSpeedFile(file, termios.B4800)
- case 9600: err = termios.SetSpeedFile(file, termios.B9600)
- case 19200: err = termios.SetSpeedFile(file, termios.B19200)
- case 38400: err = termios.SetSpeedFile(file, termios.B38400)
- case 57600: err = termios.SetSpeedFile(file, termios.B57600)
- case 115200: err = termios.SetSpeedFile(file, termios.B115200)
- case 230400: err = termios.SetSpeedFile(file, termios.B230400)
- default:
- file.Close()
- err = errors.New("Unsupported Baudrate, use 0 to disable setting a baudrate")
- }
- return
-}
-
-func serialWriter(in <- chan string, serial * os.File) {
- for totty := range(in) {
- serial.WriteString(totty)
- serial.Sync()
- }
- serial.Close()
-}
-
-func serialReader(out chan <- [][]byte, serial * os.File) {
- linescanner := bufio.NewScanner(serial)
- linescanner.Split(bufio.ScanLines)
- for linescanner.Scan() {
- if err := linescanner.Err(); err != nil {
- panic(err.Error())
- }
- text := bytes.Fields([]byte(linescanner.Text()))
- if len(text) == 0 {
- continue
- }
- out <- text
- }
-}
-
-func OpenAndHandleSerial(filename string, serspeed uint) (chan string, chan [][]byte, error) {
- serial, err :=openTTY(filename, serspeed)
- if err != nil {
- return nil, nil, err
- }
- wr := make(chan string, 1)
- rd := make(chan [][]byte, 20)
- go serialWriter(wr, serial)
- go serialReader(rd, serial)
- return wr, rd, nil
-}
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- zmq "github.com/vaughan0/go-zmq"
- "time"
- )
-
-// ---------- ZeroMQ Code -------------
-
-func ZmqsInit(cmd_port, pub_port string) (ctx *zmq.Context, cmd_chans, pub_chans *zmq.Channels) {
-
- var err error
- ctx, err = zmq.NewContext()
- if err != nil {
- panic(err)
- }
- //close only on later panic, otherwise leave open:
- defer func(){ if r:= recover(); r != nil { ctx.Close(); panic(r) } }()
-
- if len(cmd_port) > 0 {
- cmd_sock, err := ctx.Socket(zmq.Rep)
- if err != nil {
- panic(err)
- }
- defer func() { if r:= recover(); r != nil { cmd_sock.Close(); panic(r) } }()
-
- cmd_sock.SetRecvTimeout(2 * time.Second)
- cmd_sock.SetSendTimeout(2 * time.Second)
-
- if err = cmd_sock.Bind(cmd_port); err != nil {
- panic(err)
- }
-
- cmd_chans = cmd_sock.ChannelsBuffer(10)
- go zmqsHandleError(cmd_chans)
- } else {
- cmd_chans = nil
- }
-
- if len(pub_port) > 0 {
- pub_sock, err := ctx.Socket(zmq.Pub)
- if err != nil {
- panic(err)
- }
- defer func() { if r:= recover(); r != nil { pub_sock.Close(); panic(r) } }()
-
- if err = pub_sock.Bind(pub_port); err != nil {
- panic(err)
- }
-
- pub_chans = pub_sock.ChannelsBuffer(10)
- go zmqsHandleError(pub_chans)
- } else {
- pub_chans = nil
- }
-
- return
-}
-
-func zmqsHandleError(chans *zmq.Channels) {
- for error := range(chans.Errors()) {
- chans.Close()
- panic(error)
- }
-}
\ No newline at end of file
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- "log"
- "regexp"
- "strconv"
- "errors"
- "os"
- "bufio"
-)
-
-var re_keynickline *regexp.Regexp = regexp.MustCompile("^\\s*([0-9a-fA-F]+)\\s+((?:\\p{Latin}|\\d)+).*")
-
-type KeyNickStore map[uint64]string
-
-func (key_nick_map *KeyNickStore) LoadKeysFile(filename string) error {
- keysfile, err := os.OpenFile(filename, os.O_RDONLY, 0400) // For read access.
- defer keysfile.Close()
- if err != nil {
- return err
- }
-
- //clear map
- *key_nick_map = make(KeyNickStore)
-
- linescanner := bufio.NewScanner(keysfile)
- linescanner.Split(bufio.ScanLines)
- for linescanner.Scan() {
- m := re_keynickline.FindStringSubmatch(linescanner.Text())
- if len(m) > 2 {
- if kuint, err := strconv.ParseUint(m[1], 16, 64); err == nil {
- (*key_nick_map)[kuint] = m[2]
- } else {
- log.Print("Error converting hex-cardid:",m[0])
- }
- }
- }
- return nil
-}
-
-func (key_nick_map *KeyNickStore) LookupHexKeyNick( key string ) (string, error) {
- kuint, err := strconv.ParseUint(key, 16, 64)
- if err != nil {
- return "", errors.New("Invalid Hex-Card-Id")
- }
- nick, present := (*key_nick_map)[kuint]
- if present {
- return nick, nil
- } else {
- return "", errors.New("Key Unknown")
- }
-}
\ No newline at end of file
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- "os"
- "flag"
- "fmt"
- //~ "log/syslog"
- //~ "log"
-)
-
-// ---------- Main Code -------------
-
-var (
- zmqport_ string
- door_keys_file_ string
- use_syslog_ bool
- start_server_ bool
- //~ syslog_ *log.Logger
-)
-
-func usage() {
- fmt.Fprintf(os.Stderr, "Usage: door_nick_lookup_zmq [options] [keyid1 [keyid2 [...]]]\n")
- flag.PrintDefaults()
-}
-
-func init() {
- flag.StringVar(&zmqport_, "zmqport", "ipc:///run/tuer/door_keyname.ipc", "zmq socket path")
- flag.StringVar(&door_keys_file_, "keysfile", "/flash/keys", "door keys file")
- //~ flag.BoolVar(&use_syslog_, "syslog", false, "log to syslog local2 facility")
- flag.BoolVar(&start_server_, "server", false, "open 0mq socket and listen to requests")
- flag.Usage = usage
- flag.Parse()
-}
-
-func getFileMTime(filename string ) (int64, error) {
- keysfile, err := os.Open(filename)
- if err != nil { return 0, err }
- defer keysfile.Close()
- stat, err := keysfile.Stat()
- if err != nil { return 0, err }
- return stat.ModTime().Unix(), nil
-}
-
-func main() {
- knstore := new(KeyNickStore)
- err := knstore.LoadKeysFile(door_keys_file_)
- if err != nil { panic(err) }
- door_keys_mtime, err := getFileMTime(door_keys_file_)
- if err != nil { panic(err) }
-
- for _, key := range(flag.Args()) {
- nick, err := knstore.LookupHexKeyNick(key)
- if err != nil {
- fmt.Printf("ERROR: %s for key %s\n", err.Error(), key)
- } else {
- fmt.Println(key,nick)
- }
- }
-
- if ! start_server_ {
- os.Exit(0)
- }
-
- zmqctx, zmqchans := ZmqsInit(zmqport_)
- if zmqchans == nil {
- os.Exit(0)
- }
- defer zmqchans.Close()
- defer zmqctx.Close()
-
- //~ if use_syslog_ {
- //~ var logerr error
- //~ syslog_, logerr = syslog.NewLogger(syslog.LOG_INFO | syslog.LOG_LOCAL2, 0)
- //~ if logerr != nil { panic(logerr) }
- //~ syslog_.Print("started")
- //~ defer syslog_.Print("exiting")
- //~ }
-
- for keybytes := range(zmqchans.In()) {
- current_door_keys_mtime, err := getFileMTime(door_keys_file_)
- if err == nil && current_door_keys_mtime > door_keys_mtime {
- door_keys_mtime = current_door_keys_mtime
- knstore.LoadKeysFile(door_keys_file_)
- }
- nick, err := knstore.LookupHexKeyNick(string(keybytes[0]))
- if err != nil {
- zmqchans.Out() <- [][]byte{[]byte("ERROR"), []byte(err.Error())}
- } else {
- zmqchans.Out() <- [][]byte{[]byte("RESULT"), keybytes[0], []byte(nick)}
- }
- }
-}
+++ /dev/null
-#!/bin/zsh
-export GO386=387
-export CGO_ENABLED=1
-go-linux-386 clean
-#go-linux-386 build
-#strip ${PWD:t}
-go-linux-386 build -ldflags "-s" && rsync -v --progress ${PWD:t} torwaechter.realraum.at:/flash/tuer/
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- zmq "github.com/vaughan0/go-zmq"
- )
-
-// ---------- ZeroMQ Code -------------
-
-func ZmqsInit(addrport string) (ctx *zmq.Context, chans *zmq.Channels) {
- var err error
- ctx, err = zmq.NewContext()
- if err != nil {
- panic(err)
- }
- //close only on later panic, otherwise leave open:
- defer func(){ if r:= recover(); r != nil { ctx.Close(); panic(r) } }()
-
- if len(addrport) > 0 {
- sock, err := ctx.Socket(zmq.Rep)
- if err != nil {
- panic(err)
- }
- defer func() { if r:= recover(); r != nil { sock.Close(); panic(r) } }()
-
- if err = sock.Bind(addrport); err != nil {
- panic(err)
- }
-
- chans = sock.ChannelsBuffer(10)
- go zmqsHandleError(chans)
- } else {
- chans = nil
- }
-
- return
-}
-
-func zmqsHandleError(chans *zmq.Channels) {
- for error := range(chans.Errors()) {
- chans.Close()
- panic(error)
- }
-}
\ No newline at end of file
+++ /dev/null
-This daemon should furthermore be the only one ! to regexp parse door firmware string messages, door command string messages and sensor string notices from different sources.
-Thus this should be the only place we have to change code when regular expressions change or new sources are added or ip addresses change.
-The data is then exported as go-struct like events. Internally (to add i.e. presence) and externally via 0mq pub
-Thus the same events are usable in different services written in different languages
-(instead of just one language where we could import a common library for regexp parsing again and again)
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import "os"
-import "log"
-import "log/syslog"
-
-type NullWriter struct {}
-func (n *NullWriter) Write(p []byte) (int, error) {return len(p),nil}
-
-var (
- Syslog_ *log.Logger
- Debug_ *log.Logger
-)
-
-func init() {
- Syslog_ = log.New(os.Stdout, "", log.LstdFlags)
- Debug_ = log.New(&NullWriter{}, "", 0)
-}
-
-func LogEnableSyslog() {
- var logerr error
- Syslog_, logerr = syslog.NewLogger(syslog.LOG_INFO | (18<<3), 0)
- if logerr != nil { panic(logerr) }
-}
-
-func LogEnableDebuglog() {
- Debug_ = log.New(os.Stderr, "DEBUG ", log.LstdFlags)
-}
\ No newline at end of file
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- "flag"
- //~ "time"
- pubsub "github.com/tuxychandru/pubsub"
- r3events "svn.spreadspace.org/realraum/go.svn/r3events"
-)
-
-//~ func StringArrayToByteArray(ss []string) [][]byte {
-//~ bb := make([][]byte, len(ss))
-//~ for index, s := range(ss) {
-//~ bb[index] = []byte(s)
-//~ }
-//~ return bb
-//~ }
-
-// ---------- Main Code -------------
-
-var (
- doorsub_addr_ string
- sensorssub_port_ string
- pub_port_ string
- keylookup_addr_ string
- brain_listen_addr_ string
- door_cmd_addr_ string
- use_syslog_ bool
- enable_debuglog_ bool
-)
-
-func init() {
- flag.StringVar(&door_cmd_addr_, "doorcmdaddr", "ipc:///run/tuer/door_cmd.ipc", "zmq door event publish addr")
- flag.StringVar(&doorsub_addr_, "doorsubaddr", "tcp://torwaechter.realraum.at:4242", "zmq door event publish addr")
- flag.StringVar(&sensorssub_port_, "sensorsubport", "tcp://*:4243", "zmq public/listen socket addr for incoming sensor data")
- flag.StringVar(&pub_port_, "pubport", "tcp://*:4244", "zmq port publishing consodilated events")
- flag.StringVar(&keylookup_addr_, "keylookupaddr", "ipc:///run/tuer/door_keyname.ipc", "address to use for key/name lookups")
- flag.StringVar(&brain_listen_addr_, "brainlisten", "tcp://*:4245", "address to listen for requests about latest stored event")
- flag.BoolVar(&use_syslog_, "syslog", false, "log to syslog local2 facility")
- flag.BoolVar(&enable_debuglog_, "debug", false, "enable debug logging")
- flag.Parse()
-}
-
-func main() {
- if enable_debuglog_ {
- LogEnableDebuglog()
- }
- if use_syslog_ {
- LogEnableSyslog()
- Syslog_.Print("started")
- defer Syslog_.Print("exiting")
- }
-
- zmqctx, sub_in_chans, pub_out_socket, keylookup_socket := ZmqsInit(doorsub_addr_, sensorssub_port_, pub_port_, keylookup_addr_)
- if sub_in_chans != nil {
- defer sub_in_chans.Close()
- }
- defer zmqctx.Close()
- if pub_out_socket != nil {
- defer pub_out_socket.Close()
- }
- if keylookup_socket != nil {
- defer keylookup_socket.Close()
- }
- if sub_in_chans == nil || pub_out_socket == nil || keylookup_socket == nil {
- panic("zmq sockets must not be nil !!")
- }
-
- ps := pubsub.New(10)
- defer ps.Shutdown() // ps.Shutdown should be called before zmq_ctx.Close(), since it will cause goroutines to shutdown and close zqm_sockets which is needed for zmq_ctx.Close() to return
- //~ ticker := time.NewTicker(time.Duration(5) * time.Minute)
-
- store_these_events_chan := ps.Sub("door", "doorcmd", "presence", "sensors", "buttons", "movement")
- go BrainCenter(zmqctx, brain_listen_addr_, store_these_events_chan)
-
- go MetaEventRoutine_Movement(ps, 10, 20, 10)
- go MetaEventRoutine_Presence(ps, 21, 200)
-
- // --- get update on most recent status ---
- answ := ZmqsAskQuestionsAndClose(zmqctx, door_cmd_addr_, [][][]byte{[][]byte{[]byte("status")}})
- for _, a := range answ {
- ParseSocketInputLine(a, ps, keylookup_socket)
- }
-
- publish_these_events_chan := ps.Sub("door", "doorcmd", "presence", "sensors", "buttons", "movement")
- for {
- select {
- case subin := <-sub_in_chans.In():
- ParseSocketInputLine(subin, ps, keylookup_socket)
- //~ case <- ticker.C:
- //~ MakeTimeTick(ps)
- case event_interface := <-publish_these_events_chan:
- data, err := r3events.MarshalEvent2ByteByte(event_interface)
- Debug_.Printf("publishing %s", data)
- if err != nil {
- Syslog_.Print(err)
- continue
- }
- if err := pub_out_socket.Send(data); err != nil {
- panic(err)
- }
- }
- }
-
-}
+++ /dev/null
-#!/bin/zsh
-export GO386=387
-export CGO_ENABLED=1
-go-linux-386 clean
-#go-linux-386 build
-#strip ${PWD:t}
-go-linux-386 build -ldflags "-s" && rsync -v --progress ${PWD:t} torwaechter.realraum.at:/flash/tuer/
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- "time"
- pubsub "github.com/tuxychandru/pubsub"
- "container/ring"
- r3events "svn.spreadspace.org/realraum/go.svn/r3events"
- )
-
-
-/// Movement Meta Event Injector:
-/// threshold number of movements within gran_duration*granularity seconds -> SomethingReallyIsMoving{True}
-/// No movement within 3 hours but movement within the last 6 hours -> SomethingReallyIsMoving{False}
-///
-/// Thus SomethingReallyIsMoving{True} fires regularly, but at most every gran_duration seconds
-/// While SomethingReallyIsMoving{False} fires only once to assure us that everybody might really be gone
-
-
-func MetaEventRoutine_Movement(ps *pubsub.PubSub, granularity, gran_duration int , threshold uint32) {
- var last_movement,last_movement1,last_movement2,last_movement3 int64
- var confidence uint8
- movement_window := ring.New(granularity+1)
- events_chan := ps.Sub("movement")
- defer ps.Unsub(events_chan, "movement")
- myticker := time.NewTicker(time.Duration(gran_duration) * time.Second)
-
- for { select {
- case event := <- events_chan:
- switch event.(type) {
- case r3events.MovementSensorUpdate:
- if movement_window.Value == nil {
- movement_window.Value = uint32(1)
- } else {
- movement_window.Value = uint32(movement_window.Value.(uint32) + 1)
- }
- }
- case gots := <- myticker.C:
- ts := gots.Unix()
- movement_window.Prev().Value = (uint32) (0)
- movement_window = movement_window.Next()
- var movsum uint32 = 0
- movement_window.Do(func(v interface{}){if v != nil {movsum += v.(uint32)}})
- if movsum > threshold {
- confidence = uint8(movsum)
- ps.Pub( r3events.SomethingReallyIsMoving{true, confidence ,ts}, "movement")
- last_movement = ts
- last_movement1 = ts
- last_movement2 = ts
- last_movement3 = ts
- }
- // this sucks.....
- if last_movement > 0 && ts - last_movement < 3600*6 {
- if ts - last_movement > 3600*3 {
- last_movement = 0
- ps.Pub( r3events.SomethingReallyIsMoving{false,99,ts}, "movement")
- } else if ts - last_movement > 3600 && last_movement3 > 0 {
- last_movement3 = 0
- ps.Pub( r3events.SomethingReallyIsMoving{false,50,ts}, "movement")
- } else if ts - last_movement > 1800 && last_movement2 > 0 {
- last_movement2 = 0
- ps.Pub( r3events.SomethingReallyIsMoving{false,20,ts}, "movement")
- } else if ts - last_movement > 120 && last_movement1 > 0 {
- last_movement1 = 0
- ps.Pub( r3events.SomethingReallyIsMoving{false,5,ts}, "movement")
- }
- }
- } }
-}
\ No newline at end of file
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- "time"
- //~ "./brain"
- pubsub "github.com/tuxychandru/pubsub"
- r3events "svn.spreadspace.org/realraum/go.svn/r3events"
-)
-
-func MetaEventRoutine_Presence(ps *pubsub.PubSub, movement_timeout, button_timeout int64) {
- var last_door_cmd *r3events.DoorCommandEvent
- var last_presence bool
- var last_event_indicating_presence, last_frontlock_use, last_manual_lockhandling int64
- var front_locked, front_shut, back_shut bool = true, true, true
-
- events_chan := ps.Sub("door", "doorcmd", "buttons", "movement")
- defer ps.Unsub(events_chan, "door", "doorcmd", "buttons", "movement")
-
- for event := range events_chan {
- Debug_.Printf("Presence prior: %t : %T %+v", last_presence, event, event)
- new_presence := last_presence
- ts := time.Now().Unix()
- evnt_type := r3events.NameOfStruct(event)
- switch evnt := event.(type) {
- case r3events.SomethingReallyIsMoving:
- if evnt.Movement {
- //ignore movements that happened just after locking door
- if (evnt.Ts - last_event_indicating_presence) > movement_timeout {
- new_presence = true
- }
- last_event_indicating_presence = evnt.Ts
- } else {
- if last_presence {
- Syslog_.Printf("Presence: Mhh, SomethingReallyIsMoving{%+v} received but presence still true. Quite still a bunch we have here.", evnt)
- }
- if front_locked && front_shut && back_shut && evnt.Confidence >= 90 && last_event_indicating_presence > 1800 && (last_door_cmd == nil || (last_door_cmd.Using != "Button" && last_door_cmd.Ts >= last_manual_lockhandling)) {
- new_presence = false
- }
- }
- case r3events.BoreDoomButtonPressEvent:
- new_presence = true
- last_event_indicating_presence = evnt.Ts
- case r3events.DoorCommandEvent:
- last_door_cmd = &evnt
- case r3events.DoorManualMovementEvent:
- last_manual_lockhandling = evnt.Ts
- last_event_indicating_presence = evnt.Ts
- case r3events.DoorLockUpdate:
- front_locked = evnt.Locked
- last_frontlock_use = evnt.Ts
- last_event_indicating_presence = evnt.Ts
- case r3events.DoorAjarUpdate:
- if front_shut == false && evnt.Shut && front_locked && evnt.Ts-last_frontlock_use > 2 {
- Syslog_.Print("Presence: ignoring frontdoor ajar event, since obviously someone is fooling around with the microswitch while the door is still open")
- } else {
- front_shut = evnt.Shut
- }
- last_event_indicating_presence = evnt.Ts
- case r3events.BackdoorAjarUpdate:
- back_shut = evnt.Shut
- last_event_indicating_presence = evnt.Ts
- }
-
- any_door_unlocked := (front_locked == false)
- any_door_ajar := !(front_shut && back_shut)
-
- if new_presence != last_presence {
- //... skip state check .. we had a definite presence event
- } else if any_door_unlocked || any_door_ajar {
- new_presence = true
- } else if last_door_cmd != nil && (last_door_cmd.Using == "Button" || last_door_cmd.Ts < last_manual_lockhandling) {
- // if last_door_cmd is set then: if either door was closed using Button or if time of manual lock movement is greater (newer) than timestamp of last_door_cmd
- new_presence = true
- } else if evnt_type == "DoorCommandEvent" {
- //don't set presence to false for just a door command, wait until we receive a LockUpdate
- //(fixes "door manually locked -> door opened with card from outside -> nobody present status sent since door is locked and we havent received door unloked event yet"-problem)
- continue
- } else {
- new_presence = false
- }
- //~ Debug_.Printf("Presence: new: %s , last:%s", new_presence, last_presence)
- if new_presence != last_presence {
- last_presence = new_presence
- ps.Pub(r3events.PresenceUpdate{new_presence, ts}, "presence")
- Syslog_.Printf("Presence: %t", new_presence)
- }
- }
-}
+++ /dev/null
-
-Presence Meta Event Injector:
- events indicating presence:
- - front door ajar
- - door lock using manual movement closing (unless door ajar, assume we would not use key to close from inside )
- - door unlock (any method, manual, key, card, phone, ssh, etc)
- - panic button press
- - door toggle button press
- - back door ajar
- - movement sensor (maybe threshold number movements within 5 minutes)
-
- events indicating somebody left:
- - door closed with card, phone, ssh (while backdor and frontdoor shut)
- - no movement within 3 hours and movement within the last 6 hours (disable trigger if sensor is broken)
-
-
- events indicating "alarm state" / special message:
- - Panic Button pressend
- - Sudden rise in Temp-Sensor-Value
- - Sudden rise in Dust/Smoke-Sensor-Value
-
-
-Movement Meta Event Injector:
- movement sensor (maybe threshold number movements within 5 minutes) -> Movement Passed Threshold
- no movement within 3 hours and movement within the last 6 hours -> Movement Absence Passed Threshold
- asign confidence to metaevent
- -> if few movement was detected before door closed -> lower timeout until no presence !
- -> if a lot of movement was detected -> longer timeout until no presence
- (e.g. confidence of SomethingReallyIsMoving{false} must reach level of SomethingReallyIsMoving{true} before presence switch is triggered
-
-
-Sensor Spike Event Injector:
- monitors sensor values and calculates running average mean, stddev over last hours,
- raises Event is value spikes, aka rised beyond mean +- stddev within 2 min (enables after 1 hour of collecting data)
-
-
-
-Use Cases to detect:
-* someone walks by the movement sensor towards the door. Closes it from outside with the Card and leaves -> nobody in room anymore
-* somone still works in the OLGA room while the last person in the main room leaves and closes the door behind him with the card
-
--> best idea so far:
- -> all doors closed and shut -> no movement for ~30 seconds after closing doors -> assume everybody left
- -> movement within next ~30 seconds -> assume somebody is still here until SomthingReallyIsMoving{false} fires
-
-
-possible better Solution:
- close door "differently" from outside if people are still inside (e.g. with buttonpress prior to closing with card from outside... or install a "CLOSE ONLY" event sending device which can be triggered through the glass)
\ No newline at end of file
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- zmq "github.com/vaughan0/go-zmq"
- r3events "svn.spreadspace.org/realraum/go.svn/r3events"
-)
-
-type hippocampus map[string]interface{}
-
-func BrainCenter( zmq_ctx *zmq.Context, listen_addr string, event_chan <- chan interface{} ) {
- zbrain_chans, err := ZmqsBindNewReplySocket(zmq_ctx, listen_addr)
- if err != nil { panic(err) }
- defer zbrain_chans.Close()
- h := make(hippocampus,5)
-
- for { select {
- case event, ec_still_open := <- event_chan:
- if ! ec_still_open { return }
- h[r3events.NameOfStruct(event)] = event
- Debug_.Printf("Brain: stored %s, %s", r3events.NameOfStruct(event), event)
-
- case brain_request := <- zbrain_chans.In():
- if len(brain_request) == 0 { continue }
- requested_eventname := string(brain_request[0])
- Debug_.Printf("Brain: received request: %s", requested_eventname)
- retr_event, is_in_map := h[requested_eventname]
- if is_in_map {
- data, err := r3events.MarshalEvent2ByteByte(retr_event)
- if err == nil {
- zbrain_chans.Out() <- data
- continue
- } else {
- Syslog_.Print("BrainCenter", err)
- Debug_.Print("BrainCenter", err)
- }
- }
- zbrain_chans.Out() <- [][]byte{[]byte("UNKNOWN")}
- } }
-}
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- "bytes"
- "regexp"
- "strconv"
- "time"
- //~ "./brain"
- pubsub "github.com/tuxychandru/pubsub"
- zmq "github.com/vaughan0/go-zmq"
- r3events "svn.spreadspace.org/realraum/go.svn/r3events"
-)
-
-var (
- //~ re_presence_ *regexp.Regexp = regexp.MustCompile("Presence: (yes|no)(?:, (opened|closed), (.+))?")
- //~ re_state_ *regexp.Regexp = regexp.MustCompile("State: (closed|opened|manual movement|error|reset|timeout after open|timeout after close|opening|closing).*")
- //~ re_status_ *regexp.Regexp = regexp.MustCompile("Status: (closed|opened), (closed|opened|manual movement|error|reset|timeout after open|timeout after close|opening|closing), (ajar|shut).*")
- //~ re_infocard_ *regexp.Regexp = regexp.MustCompile("Info\\(card\\): card\\(([a-fA-F0-9]+)\\) (found|not found).*")
- re_cardid_ *regexp.Regexp = regexp.MustCompile("card\\(([a-fA-F0-9]+)\\)")
- //~ re_infoajar_ *regexp.Regexp = regexp.MustCompile("Info\\(ajar\\): door is now (ajar|shut)")
- //~ re_command_ *regexp.Regexp = regexp.MustCompile("(open|close|toggle|reset)(?: +(Card|Phone|SSH|ssh))?(?: +(.+))?")
- //~ re_button_ *regexp.Regexp = regexp.MustCompile("PanicButton|button\\d?")
- //~ re_temp_ *regexp.Regexp = regexp.MustCompile("temp0: (\\d+\\.\\d+)")
- //~ re_photo_ *regexp.Regexp = regexp.MustCompile("photo0: (\\d+)")
-)
-
-func parseSocketInputLine_State(lines [][]byte, ps *pubsub.PubSub, ts int64) {
- switch string(lines[0]) {
- case "closed":
- ps.Pub(r3events.DoorLockUpdate{true, ts}, "door")
- case "opened":
- ps.Pub(r3events.DoorLockUpdate{false, ts}, "door")
- case "manual", "manual_movement": //movement
- ps.Pub(r3events.DoorManualMovementEvent{ts}, "door")
- case "error":
- ps.Pub(r3events.DoorProblemEvent{100, string(bytes.Join(lines, []byte(" "))), ts}, "door")
- case "reset":
- ps.Pub(r3events.DoorLockUpdate{true, ts}, "door")
- case "timeout_after_open":
- ps.Pub(r3events.DoorProblemEvent{10, string(lines[0]), ts}, "door")
- ps.Pub(r3events.DoorLockUpdate{false, ts}, "door")
- case "timeout_after_close":
- ps.Pub(r3events.DoorProblemEvent{20, string(lines[0]), ts}, "door")
- // can't say for sure that door is locked if we ran into timeout while closing
- //~ ps.Pub(r3events.DoorLockUpdate{true, ts}, "door")
- case "opening":
- case "closing":
- default:
- Syslog_.Print("parseSocketInputLine_State: Unexpected State:", lines)
- }
-}
-
-func ParseSocketInputLine(lines [][]byte, ps *pubsub.PubSub, keylookup_socket *zmq.Socket) { //, brn *brain.Brain) {
- ts := time.Now().Unix()
- if len(lines) < 1 {
- return
- }
- Debug_.Printf("ParseSocketInputLine: %s %s", string(lines[0]), lines[1:])
- switch string(lines[0]) {
- case "State:":
- if len(lines) < 2 {
- return
- }
- parseSocketInputLine_State(lines[1:], ps, ts)
- case "Status:":
- if len(lines) < 3 {
- return
- }
- if len(lines[1]) < 4 {
- return
- }
- ps.Pub(r3events.DoorLockUpdate{string(lines[1])[0:4] != "open", ts}, "door")
- ps.Pub(r3events.DoorAjarUpdate{string(lines[len(lines)-1]) == "shut", ts}, "door")
- case "Info(card):":
- if len(lines) < 3 {
- return
- }
- if string(lines[2]) != "found" {
- return
- }
- match_cardid := re_cardid_.FindSubmatch(lines[1])
- if len(match_cardid) > 1 {
- // PreCondition: same thread/goroutinge as created keylookup_socket !!!!
- nick, err := LookupCardIdNick(keylookup_socket, match_cardid[1])
- if err != nil {
- Syslog_.Print("CardID Lookup Error", err)
- nick = "Unresolvable KeyID"
- }
- // new event: toggle by user nick using card
- ps.Pub(r3events.DoorCommandEvent{"toggle", "Card", nick, ts}, "doorcmd")
- }
- case "Info(ajar):":
- if len(lines) < 5 {
- return
- }
- ps.Pub(r3events.DoorAjarUpdate{string(lines[4]) == "shut", ts}, "door")
- case "open", "close", "toggle", "reset":
- switch len(lines) {
- case 2:
- ps.Pub(r3events.DoorCommandEvent{Command: string(lines[0]), Using: string(lines[1]), Ts: ts}, "doorcmd")
- case 3:
- ps.Pub(r3events.DoorCommandEvent{Command: string(lines[0]), Using: string(lines[1]), Who: string(lines[2]), Ts: ts}, "doorcmd")
- default:
- return
- }
- case "BackdoorInfo(ajar):":
- ps.Pub(r3events.BackdoorAjarUpdate{string(lines[len(lines)-1]) == "shut", ts}, "door")
- case "GasLeakAlert":
- ps.Pub(r3events.GasLeakAlert{ts}, "sensors")
- case "temp0:", "temp1:", "temp2:", "temp3:":
- sensorid, err := strconv.ParseInt(string(lines[0][4]), 10, 32)
- if err != nil {
- return
- }
- newtemp, err := strconv.ParseFloat(string(lines[1]), 10)
- if err != nil {
- return
- }
- ps.Pub(r3events.TempSensorUpdate{int(sensorid), newtemp, ts}, "sensors")
- case "photo0:", "photo1:", "photo2:", "photo3:":
- sensorid, err := strconv.ParseInt(string(lines[0][5]), 10, 32)
- if err != nil {
- return
- }
- newphoto, err := strconv.ParseInt(string(lines[1]), 10, 32)
- if err != nil {
- return
- }
- ps.Pub(r3events.IlluminationSensorUpdate{int(sensorid), newphoto, ts}, "sensors")
- case "rh0:":
- //~ sensorid, err := strconv.ParseInt(string(lines[0][4]), 10, 32)
- //~ if err != nil {return }
- relhumid, err := strconv.ParseInt(string(lines[1]), 10, 32)
- if err != nil {
- return
- }
- ps.Pub(r3events.RelativeHumiditySensorUpdate{0, int(relhumid), ts}, "sensors")
- case "dust0:", "dust1:", "dust2:":
- sensorid, err := strconv.ParseInt(string(lines[0][4]), 10, 32)
- if err != nil {
- return
- }
- dustlvl, err := strconv.ParseInt(string(lines[1]), 10, 32)
- if err != nil {
- return
- }
- ps.Pub(r3events.DustSensorUpdate{int(sensorid), dustlvl, ts}, "sensors")
- default:
- evnt, pubsubcat, err := r3events.UnmarshalByteByte2Event(lines)
- if err == nil {
- ps.Pub(evnt, pubsubcat)
- }
- }
-}
-
-func MakeTimeTick(ps *pubsub.PubSub) {
- ps.Pub(r3events.TimeTick{time.Now().Unix()}, "time")
-}
-
-//~ match_presence := re_presence_.FindStringSubmatch(line)
-//~ match_status := re_status_.FindStringSubmatch(line)
-//~ match_command := re_command_.FindStringSubmatch(line)
-//~ match_button := re_button_.FindStringSubmatch(line)
-//~ match_temp := re_temp_.FindStringSubmatch(line)
-//~ match_photo := re_photo_.FindStringSubmatch(line)
-//~ if match_button != nil {
-//~ // brn.Oboite("button0", ts)
-//~ ps.Pub(BoreDoomButtonPressEvent{0, ts}, "buttons")
-//~ } else if match_temp != nil {
-//~ newtemp, err := strconv.ParseFloat((match_temp[1]), 32)
-//~ if err == nil {
-//~ // brn.Oboite( "temp0", newtemp)
-//~ ps.Pub(TempSensorUpdate{0, newtemp, ts}, "sensors")
-//~ }
-//~ } else if match_photo != nil {
-//~ newphoto, err := strconv.ParseInt(match_photo[1], 10, 32)
-//~ if err == nil {
-//~ // brn.Oboite("photo0", newphoto)
-//~ ps.Pub(IlluminationSensorUpdate{0, newphoto, ts}, "sensors")
-//~ }
-//~ } else if line == "movement" {
-//~ // brn.Oboite("movement", ts)
-//~ ps.Pub(MovementSensorUpdate{0, ts}, "movements")
-//~ }
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- zmq "github.com/vaughan0/go-zmq"
- "bytes"
- "errors"
- )
-
-// ---------- ZeroMQ Code -------------
-
-func ZmqsInit(sub_connect_port, sub_listen_port, pub_port, keylookup_port string) (ctx *zmq.Context, sub_chans *zmq.Channels, pub_sock *zmq.Socket, keylookup_sock *zmq.Socket) {
- var err error
- ctx, err = zmq.NewContext()
- if err != nil {
- panic(err)
- }
- //close only on later panic, otherwise leave open:
- defer func(){ if r:= recover(); r != nil { ctx.Close(); panic(r) } }()
-
- if len(sub_connect_port) > 0 && len(sub_listen_port) > 0 {
- sub_sock, err := ctx.Socket(zmq.Sub)
- if err != nil {
- panic(err)
- }
- defer func() { if r:= recover(); r != nil { sub_sock.Close(); panic(r) } }()
-
- sub_sock.Subscribe([]byte{}) //subscribe empty filter -> aka to all messages
-
- if err = sub_sock.Bind(sub_listen_port); err != nil {
- panic(err)
- }
-
- if err = sub_sock.Connect(sub_connect_port); err != nil {
- panic(err)
- }
-
- sub_chans = sub_sock.ChannelsBuffer(10)
- go zmqsHandleError(sub_chans)
- } else {
- sub_chans = nil
- }
-
- if len(pub_port) > 0 {
- pub_sock, err = ctx.Socket(zmq.Pub)
- if err != nil {
- panic(err)
- }
- defer func() { if r:= recover(); r != nil { pub_sock.Close(); panic(r) } }()
-
- if err = pub_sock.Bind(pub_port); err != nil {
- panic(err)
- }
- } else {
- pub_sock = nil
- }
-
- if len(keylookup_port) > 0 {
- keylookup_sock, err = ctx.Socket(zmq.Req)
- if err != nil {
- panic(err)
- }
- defer func() { if r:= recover(); r != nil { keylookup_sock.Close(); panic(r) } }()
-
- if err = keylookup_sock.Connect(keylookup_port); err != nil {
- panic(err)
- }
- } else {
- keylookup_sock = nil
- }
-
- return
-}
-
-func zmqsHandleError(chans *zmq.Channels) {
- for error := range(chans.Errors()) {
- chans.Close()
- panic(error)
- }
-}
-
-func ZmqsBindNewReplySocket(ctx *zmq.Context, addr string) (chans *zmq.Channels, err error) {
- if len(addr) == 0 {
- return nil, errors.New("No listen address given")
- }
- sock, err := ctx.Socket(zmq.Rep)
- if err != nil { return nil, err}
-
- if err = sock.Bind(addr); err != nil {
- sock.Close()
- return nil, err
- }
-
- chans = sock.ChannelsBuffer(10)
- go zmqsHandleError(chans)
-
- return chans, nil
-}
-
-func ZmqsRequestAnswer(sock *zmq.Socket, request [][]byte) (answer [][]byte) {
- if err := sock.Send(request); err != nil {
- panic(err)
- }
- parts, err := sock.Recv()
- if err != nil {
- panic(err)
- }
- return parts
-}
-
-func ZmqsAskQuestionsAndClose(ctx *zmq.Context, addr string, questions [][][]byte) [][][]byte {
- if len(addr) == 0 || ctx == nil { return nil }
-
- req_sock, err := ctx.Socket(zmq.Req)
- if err != nil {
- return nil
- }
- defer req_sock.Close()
-
- if err = req_sock.Connect(addr); err != nil {
- return nil
- }
-
- rv := make([][][]byte, len(questions))
- for index, q := range(questions) {
- rv[index] = ZmqsRequestAnswer(req_sock, q)
- }
- return rv
-}
-
-func LookupCardIdNick(s *zmq.Socket, hexbytes []byte) (string, error) {
- answ := ZmqsRequestAnswer(s, [][]byte{hexbytes})
- if len(answ) == 0 {
- return "", errors.New("Empty reply received")
- }
- if bytes.Compare(answ[0], []byte("ERROR")) == 0 {
- return "", errors.New(string(bytes.Join(answ[1:],[]byte(" "))))
- }
- if bytes.Compare(answ[0], []byte("RESULT")) != 0 || len(answ) != 3{
- return "", errors.New("Unknown reply received")
- }
- if bytes.Compare(answ[1], hexbytes) != 0 {
- return "", errors.New("Wrong reply received")
- }
- return string(answ[2]), nil
-}
\ No newline at end of file
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import "os"
-import "log"
-import "log/syslog"
-
-type NullWriter struct {}
-func (n *NullWriter) Write(p []byte) (int, error) {return len(p),nil}
-
-var (
- Syslog_ *log.Logger
- Debug_ *log.Logger
-)
-
-func init() {
- Syslog_ = log.New(&NullWriter{}, "", 0)
- Debug_ = log.New(&NullWriter{}, "", 0)
-}
-
-func LogEnableSyslog() {
- var logerr error
- Syslog_, logerr = syslog.NewLogger(syslog.LOG_INFO | (18<<3), 0)
- if logerr != nil { panic(logerr) }
-}
-
-func LogEnableDebuglog() {
- Syslog_ = log.New(os.Stdout, "", log.LstdFlags)
- Debug_ = log.New(os.Stderr, "DEBUG ", log.LstdFlags)
-}
\ No newline at end of file
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- "flag"
- "fmt"
- "time"
-
- "./r3xmppbot"
- pubsub "github.com/tuxychandru/pubsub"
- //~ "./brain"
- zmq "github.com/vaughan0/go-zmq"
- r3events "svn.spreadspace.org/realraum/go.svn/r3events"
-)
-
-type SpaceState struct {
- present bool
- buttonpress_until int64
- door_locked bool
- door_shut bool
-}
-
-var (
- xmpp_login_ struct {
- jid string
- pass string
- }
- xmpp_bot_authstring_ string
- xmpp_state_save_dir_ string
- r3eventssub_port_ string
- button_press_timeout_ int64 = 3600
- brain_connect_addr_ string
- enable_syslog_, enable_debug_ bool
-)
-
-type EventToXMPPStartupFinished struct{}
-
-//-------
-
-func init() {
- flag.StringVar(&xmpp_login_.jid, "xjid", "realrauminfo@realraum.at/Tuer", "XMPP Bot Login JID")
- flag.StringVar(&xmpp_login_.pass, "xpass", "", "XMPP Bot Login Password")
- flag.StringVar(&xmpp_bot_authstring_, "xbotauth", "", "String that users use to authenticate themselves to the bot")
- flag.StringVar(&xmpp_state_save_dir_, "xstatedir", "/flash/var/lib/r3netstatus/", "Directory to save XMPP bot state in")
- flag.StringVar(&r3eventssub_port_, "eventsubport", "tcp://torwaechter.realraum.at:4244", "zmq address to subscribe r3events")
- flag.StringVar(&brain_connect_addr_, "brainconnect", "tcp://torwaechter.realraum.at:4245", "address to ask about most recent stored events")
- flag.BoolVar(&enable_syslog_, "syslog", false, "enable logging to syslog")
- flag.BoolVar(&enable_debug_, "debug", false, "enable debug output")
- flag.Parse()
-}
-
-//-------
-
-func IfThenElseStr(c bool, strue, sfalse string) string {
- if c {
- return strue
- } else {
- return sfalse
- }
-}
-
-func composeDoorLockMessage(locked bool, frontshut r3events.DoorAjarUpdate, doorcmd r3events.DoorCommandEvent, ts int64) string {
- var ajarstring string = ""
- if frontshut.Shut == false && frontshut.Ts < doorcmd.Ts {
- ajarstring = " (still ajar)"
- }
- if ts-doorcmd.Ts < 30 {
- if len(doorcmd.Who) == 0 || doorcmd.Who == "-" {
- return fmt.Sprintf("The%s frontdoor was %s by %s at %s.", ajarstring, IfThenElseStr(locked, "locked", "unlocked"), doorcmd.Using, time.Unix(ts, 0).String())
- } else {
- return fmt.Sprintf("%s %s the%s frontdoor by %s at %s.", doorcmd.Who, IfThenElseStr(locked, "locked", "unlocked"), ajarstring, doorcmd.Using, time.Unix(ts, 0).String())
- }
- } else {
- return fmt.Sprintf("The%s frontdoor was %s manually at %s.", ajarstring, IfThenElseStr(locked, "locked", "unlocked"), time.Unix(ts, 0).String())
- }
-}
-
-func composePresence(present bool, temp_cx float64, light_lothr, last_buttonpress int64) r3xmppbot.XMPPStatusEvent {
- present_msg := "Somebody is present"
- notpresent_msg := "Nobody is here"
- button_msg := "The button has been pressed :-)"
- msg := "%s (CX: %.2f°C, LoTHR light: %d)"
-
- if present {
- if last_buttonpress > 0 && time.Now().Unix()-last_buttonpress < button_press_timeout_ {
- return r3xmppbot.XMPPStatusEvent{r3xmppbot.ShowFreeForChat, fmt.Sprintf(msg, button_msg, temp_cx, light_lothr)}
- } else {
- return r3xmppbot.XMPPStatusEvent{r3xmppbot.ShowOnline, fmt.Sprintf(msg, present_msg, temp_cx, light_lothr)}
- }
- } else {
- return r3xmppbot.XMPPStatusEvent{r3xmppbot.ShowNotAvailabe, fmt.Sprintf(msg, notpresent_msg, temp_cx, light_lothr)}
- }
-}
-
-func EventToXMPP(bot *r3xmppbot.XmppBot, events <-chan interface{}, xmpp_presence_events_chan chan<- interface{}) {
- button_msg := "Dooom ! The button has been pressed ! Propably someone is bored and in need of company ! ;-)"
- defer func() {
- if x := recover(); x != nil {
- //defer ist called _after_ EventToXMPP function has returned. Thus we recover after returning from this function.
- Syslog_.Printf("handleIncomingXMPPStanzas: run time panic: %v", x)
- }
- }()
-
- var present, frontlock bool = false, true
- var last_buttonpress, light_lothr int64 = 0, 0
- var temp_cx float64 = 0.0
- var last_door_cmd r3events.DoorCommandEvent
- var last_frontdoor_ajar r3events.DoorAjarUpdate = r3events.DoorAjarUpdate{true, 0}
- var standard_distribute_level r3xmppbot.R3JIDDesire = r3xmppbot.R3DebugInfo // initial state, changed after startup finished event recieved
-
- xmpp_presence_events_chan <- r3xmppbot.XMPPStatusEvent{r3xmppbot.ShowNotAvailabe, "Nobody is here"}
-
- for eventinterface := range events {
- Debug_.Printf("event2xmpp: %T %+v", eventinterface, eventinterface)
- switch event := eventinterface.(type) {
- case EventToXMPPStartupFinished:
- //after we received all events from QueryLatestEventsAndInjectThem, we get this event and start sending new events normally
- standard_distribute_level = r3xmppbot.R3OnlineOnlyInfo
- case r3events.PresenceUpdate:
- present = event.Present
- if !present {
- last_buttonpress = 0
- }
- xmpp_presence_events_chan <- composePresence(present, temp_cx, light_lothr, last_buttonpress)
- case r3events.DoorCommandEvent:
- last_door_cmd = event
- xmpp_presence_events_chan <- fmt.Sprintln("DoorCommand:", event.Command, "using", event.Using, "by", event.Who, time.Unix(event.Ts, 0))
- case r3events.DoorLockUpdate:
- if frontlock != event.Locked {
- xmpp_presence_events_chan <- r3xmppbot.XMPPMsgEvent{Msg: composeDoorLockMessage(event.Locked, last_frontdoor_ajar, last_door_cmd, event.Ts), DistributeLevel: standard_distribute_level, RememberAsStatus: true}
- }
- frontlock = event.Locked
- case r3events.DoorAjarUpdate:
- if last_frontdoor_ajar.Shut != event.Shut {
- xmpp_presence_events_chan <- r3xmppbot.XMPPMsgEvent{Msg: fmt.Sprintf("Frontdoor is %s (%s)", IfThenElseStr(event.Shut, "now shut.", "ajar."), time.Unix(event.Ts, 0).String()), DistributeLevel: r3xmppbot.R3DebugInfo, RememberAsStatus: false}
- }
- last_frontdoor_ajar = event
- case r3events.BackdoorAjarUpdate:
- xmpp_presence_events_chan <- r3xmppbot.XMPPMsgEvent{Msg: fmt.Sprintf("Backdoor is %s (%s)", IfThenElseStr(event.Shut, "now shut.", "ajar!"), time.Unix(event.Ts, 0).String()), DistributeLevel: standard_distribute_level, RememberAsStatus: false}
- case r3events.GasLeakAlert:
- xmpp_presence_events_chan <- r3xmppbot.XMPPMsgEvent{Msg: fmt.Sprintf("ALERT !! GasLeak Detected !!! (%s)", time.Unix(event.Ts, 0).String()), DistributeLevel: r3xmppbot.R3NeverInfo, RememberAsStatus: false}
- case r3events.IlluminationSensorUpdate:
- light_lothr = event.Value
- case r3events.TempSensorUpdate:
- if event.Sensorindex == 1 {
- temp_cx = event.Value
- }
- case r3events.BoreDoomButtonPressEvent:
- last_buttonpress = event.Ts
- xmpp_presence_events_chan <- composePresence(present, temp_cx, light_lothr, last_buttonpress)
- xmpp_presence_events_chan <- r3xmppbot.XMPPMsgEvent{Msg: button_msg, DistributeLevel: standard_distribute_level}
- case r3events.TimeTick:
- // update presence text with sensor and button info
- xmpp_presence_events_chan <- composePresence(present, temp_cx, light_lothr, last_buttonpress)
- // Try to XMPP Ping the server and if that fails, quit XMPPBot
- if bot.PingServer(900) == false && bot.PingServer(900) == false && bot.PingServer(900) == false && bot.PingServer(900) == false && bot.PingServer(900) == false {
- return
- }
- case r3events.DoorProblemEvent:
- xmpp_presence_events_chan <- r3xmppbot.XMPPMsgEvent{Msg: fmt.Sprintf("Door Problem: %s. SeverityLevel: %d (%s)", event.Problem, event.Severity, time.Unix(event.Ts, 0).String()), DistributeLevel: r3xmppbot.R3OnlineOnlyInfo, RememberAsStatus: false}
- }
- }
-}
-
-func RunXMPPBot(ps *pubsub.PubSub, zmqctx *zmq.Context) {
- var xmpperr error
- var bot *r3xmppbot.XmppBot
- var xmpp_presence_events_chan chan interface{}
- for {
- bot, xmpp_presence_events_chan, xmpperr = r3xmppbot.NewStartedBot(xmpp_login_.jid, xmpp_login_.pass, xmpp_bot_authstring_, xmpp_state_save_dir_, true)
- if xmpperr == nil {
- Syslog_.Printf("Successfully (re)started XMPP Bot")
- // subscribe before QueryLatestEventsAndInjectThem and EventToXMPP
- psevents := ps.Sub("presence", "door", "buttons", "updateinterval", "sensors", "xmppmeta")
- QueryLatestEventsAndInjectThem(ps, zmqctx)
- ps.Pub(EventToXMPPStartupFinished{}, "xmppmeta")
- EventToXMPP(bot, psevents, xmpp_presence_events_chan)
- // unsubscribe right away, since we don't known when reconnect will succeed and we don't want to block PubSub
- ps.Unsub(psevents, "presence", "door", "buttons", "updateinterval", "sensors", "xmppmeta")
- bot.StopBot()
- } else {
- Syslog_.Printf("Error starting XMPP Bot: %s", xmpperr.Error())
- }
- time.Sleep(20 * time.Second)
- }
-}
-
-func ParseZMQr3Event(lines [][]byte, ps *pubsub.PubSub) {
- evnt, pubsubcat, err := r3events.UnmarshalByteByte2Event(lines)
- Debug_.Printf("ParseZMQr3Event: %s %s %s", evnt, pubsubcat, err)
- if err != nil {
- return
- }
- ps.Pub(evnt, pubsubcat)
-}
-
-func QueryLatestEventsAndInjectThem(ps *pubsub.PubSub, zmqctx *zmq.Context) {
- answ := ZmqsAskQuestionsAndClose(zmqctx, brain_connect_addr_, [][][]byte{
- [][]byte{[]byte("BackdoorAjarUpdate")},
- [][]byte{[]byte("DoorCommandEvent")},
- [][]byte{[]byte("DoorLockUpdate")},
- [][]byte{[]byte("DoorAjarUpdate")},
- [][]byte{[]byte("PresenceUpdate")},
- [][]byte{[]byte("IlluminationSensorUpdate")},
- [][]byte{[]byte("TempSensorUpdate")}})
- for _, a := range answ {
- ParseZMQr3Event(a, ps)
- }
-}
-
-func main() {
- if enable_syslog_ {
- LogEnableSyslog()
- r3xmppbot.LogEnableSyslog()
- }
- if enable_debug_ {
- LogEnableDebuglog()
- r3xmppbot.LogEnableDebuglog()
- }
- Syslog_.Print("started")
- defer Syslog_.Print("exiting")
- zmqctx, zmqsub := ZmqsInit(r3eventssub_port_)
- defer zmqctx.Close()
- if zmqsub != nil {
- defer zmqsub.Close()
- }
- if zmqsub == nil {
- panic("zmq sockets must not be nil !!")
- }
-
- ps := pubsub.New(10)
- defer ps.Shutdown()
- //~ brn := brain.New()
- //~ defer brn.Shutdown()
-
- go EventToWeb(ps)
- // --- get update on most recent events ---
- QueryLatestEventsAndInjectThem(ps, zmqctx)
- go RunXMPPBot(ps, zmqctx)
-
- // --- receive and distribute events ---
- ticker := time.NewTicker(time.Duration(6) * time.Minute)
- for {
- select {
- case e := <-zmqsub.In():
- ParseZMQr3Event(e, ps) //, brn)
- case <-ticker.C:
- ps.Pub(r3events.TimeTick{time.Now().Unix()}, "updateinterval")
- }
- }
-}
+++ /dev/null
-#!/bin/zsh
-export GO386=387
-export CGO_ENABLED=1
-go-linux-386 clean
-#go-linux-386 build
-#strip ${PWD:t}
-go-linux-386 build -ldflags "-s" && rsync -v --progress ${PWD:t} torwaechter.realraum.at:/flash/tuer/
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package r3xmppbot
-
-import "os"
-import "log"
-import "log/syslog"
-
-type NullWriter struct {}
-func (n *NullWriter) Write(p []byte) (int, error) {return len(p),nil}
-
-var (
- Syslog_ *log.Logger
- Debug_ *log.Logger
-)
-
-func init() {
- Syslog_ = log.New(&NullWriter{}, "", 0)
- Debug_ = log.New(&NullWriter{}, "", 0)
-}
-
-func LogEnableSyslog() {
- var logerr error
- Syslog_, logerr = syslog.NewLogger(syslog.LOG_INFO | (18<<3), 0)
- if logerr != nil { panic(logerr) }
-}
-
-func LogEnableDebuglog() {
- Syslog_ = log.New(os.Stdout, "", log.LstdFlags)
- Debug_ = log.New(os.Stderr, "DEBUG ", log.LstdFlags)
-}
-
-type XMPPLogger struct {
-}
-
-func (s *XMPPLogger) Log(v ...interface{}) {
- Syslog_.Println(v...)
-}
-
-func (s *XMPPLogger) Logf(fmt string, v ...interface{}) {
- Syslog_.Printf(fmt, v...)
-}
-
-type XMPPDebugLogger struct {
-}
-
-func (s *XMPPDebugLogger) Log(v ...interface{}) {
- Debug_.Println(v...)
-}
-
-func (s *XMPPDebugLogger) Logf(fmt string, v ...interface{}) {
- Debug_.Printf(fmt, v...)
-}
\ No newline at end of file
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package r3xmppbot
-
-import (
- "encoding/xml"
- "time"
-
- xmpp "code.google.com/p/goexmpp"
-)
-
-// XMPP Ping
-type XMPPPing struct {
- XMLName xml.Name `xml:"urn:xmpp:ping ping"`
-}
-
-func HandleServerToClientPing(iq *xmpp.Iq, xmppout chan<- xmpp.Stanza) bool {
- ///<iq from='juliet@capulet.lit/balcony' to='capulet.lit' id='s2c1' type='result'/>
- if iq.Type != "get" {
- return false
- }
- for _, ele := range iq.Nested {
- if _, ok := ele.(*XMPPPing); ok {
- xmppout <- &xmpp.Iq{Header: xmpp.Header{To: iq.From, From: iq.To, Id: iq.Id, Type: "result"}}
- return true
- }
- }
- return false
-}
-
-func (botdata *XmppBot) PingServer(timeout_ms time.Duration) (is_up bool) {
- ///<iq from='juliet@capulet.lit/balcony' to='capulet.lit' id='c2s1' type='get'>
- /// <ping xmlns='urn:xmpp:ping'/>
- ///</iq>
- server_jid := new(xmpp.JID)
- server_jid.Set(botdata.my_jid_)
- iqping := &xmpp.Iq{Header: xmpp.Header{To: server_jid.Domain,
- From: botdata.my_jid_,
- Id: <-xmpp.Id,
- Type: "get",
- Nested: []interface{}{XMPPPing{}}}}
- pong := make(chan bool, 1)
- defer close(pong)
- f := func(v xmpp.Stanza) bool {
- defer recover() //recover from writing to possibly already closed chan
- let_others_handle_stanza := false
- iq, ok := v.(*xmpp.Iq)
- if !ok {
- Syslog_.Printf("response to iq ping wasn't iq: %s", v)
- pong <- false
- return true //let other handlers process reply
- }
- if iq.Type == "error" && iq.Error != nil && iq.Error.Type == "cancel" {
- Debug_.Printf("response to iq ping was cancel, server does not support ping")
- //server does not support ping, but at least we know server is still there
- } else if iq.Type != "result" {
- Syslog_.Printf("response to iq ping was not pong: %s", v)
- let_others_handle_stanza = true //let other handlers process reply
- }
- pong <- true
- return let_others_handle_stanza // return false so that Stanza v will not be appear in xmppclient_.Out()
- }
- botdata.xmppclient_.HandleStanza(iqping.Id, f)
- botdata.xmppclient_.Out <- iqping
- go func() {
- defer func() {
- if x := recover(); x == nil {
- Syslog_.Printf("response to iq ping timed out !!")
- }
- }() //recover from writing to possibly already closed chan. If we did not need to recover, then Handler did not receive reply
- time.Sleep(timeout_ms * time.Millisecond)
- pong <- false //xmpp ping timed out
- }()
- return <-pong
-}
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package r3xmppbot
-
-import (
- "crypto/tls"
- "encoding/json"
- "errors"
- "os"
- "path"
- "strings"
- "time"
-
- xmpp "code.google.com/p/goexmpp"
-)
-
-func (botdata *XmppBot) makeXMPPMessage(to string, message interface{}, subject interface{}) *xmpp.Message {
- xmppmsgheader := xmpp.Header{To: to,
- From: botdata.my_jid_,
- Id: <-xmpp.Id,
- Type: "chat",
- Lang: "",
- Innerxml: "",
- Error: nil,
- Nested: make([]interface{}, 0)}
-
- var msgsubject, msgbody *xmpp.Generic
- switch cast_msg := message.(type) {
- case string:
- msgbody = &xmpp.Generic{Chardata: cast_msg}
- case *string:
- msgbody = &xmpp.Generic{Chardata: *cast_msg}
- case *xmpp.Generic:
- msgbody = cast_msg
- default:
- msgbody = &xmpp.Generic{}
- }
- switch cast_msg := subject.(type) {
- case string:
- msgsubject = &xmpp.Generic{Chardata: cast_msg}
- case *string:
- msgsubject = &xmpp.Generic{Chardata: *cast_msg}
- case *xmpp.Generic:
- msgsubject = cast_msg
- default:
- msgsubject = &xmpp.Generic{}
- }
- return &xmpp.Message{Header: xmppmsgheader, Subject: msgsubject, Body: msgbody, Thread: &xmpp.Generic{}}
-}
-
-func (botdata *XmppBot) makeXMPPPresence(to, ptype, show, status string) *xmpp.Presence {
- xmppmsgheader := xmpp.Header{To: to,
- From: botdata.my_jid_,
- Id: <-xmpp.Id,
- Type: ptype,
- Lang: "",
- Innerxml: "",
- Error: nil,
- Nested: make([]interface{}, 0)}
- var gen_show, gen_status *xmpp.Generic
- if len(show) == 0 {
- gen_show = nil
- } else {
- gen_show = &xmpp.Generic{Chardata: show}
- }
- if len(status) == 0 {
- gen_status = nil
- } else {
- gen_status = &xmpp.Generic{Chardata: status}
- }
- return &xmpp.Presence{Header: xmppmsgheader, Show: gen_show, Status: gen_status}
-}
-
-type R3JIDDesire int
-
-const (
- R3NoChange R3JIDDesire = -1
- R3NeverInfo R3JIDDesire = iota // ignore first value by assigning to blank identifier
- R3OnlineOnlyInfo
- R3OnlineOnlyWithRecapInfo
- R3AlwaysInfo
- R3DebugInfo
-)
-
-const (
- ShowOnline string = ""
- ShowAway string = "away"
- ShowNotAvailabe string = "xa"
- ShowDoNotDisturb string = "dnd"
- ShowFreeForChat string = "chat"
-)
-
-type JidData struct {
- Online bool
- Wants R3JIDDesire
-}
-
-type JabberEvent struct {
- JID string
- Online bool
- Wants R3JIDDesire
- StatusNow bool
-}
-
-type XMPPMsgEvent struct {
- Msg string
- DistributeLevel R3JIDDesire
- RememberAsStatus bool
-}
-
-type XMPPStatusEvent struct {
- Show string
- Status string
-}
-
-type RealraumXmppNotifierConfig map[string]JidData
-
-type XmppBot struct {
- jid_lastauthtime_ map[string]int64
- realraum_jids_ RealraumXmppNotifierConfig
- password_ string
- my_jid_ string
- auth_timeout_ int64
- config_file_ string
- my_login_password_ string
- xmppclient_ *xmpp.Client
- presence_events_ *chan interface{}
-}
-
-func (data RealraumXmppNotifierConfig) saveTo(filepath string) {
- fh, err := os.Create(filepath)
- if err != nil {
- Syslog_.Println(err)
- return
- }
- defer fh.Close()
- enc := json.NewEncoder(fh)
- if err = enc.Encode(&data); err != nil {
- Syslog_.Println(err)
- return
- }
-}
-
-func (data RealraumXmppNotifierConfig) loadFrom(filepath string) {
- fh, err := os.Open(filepath)
- if err != nil {
- Syslog_.Println(err)
- return
- }
- defer fh.Close()
- dec := json.NewDecoder(fh)
- if err = dec.Decode(&data); err != nil {
- Syslog_.Println(err)
- return
- }
- for to, jiddata := range data {
- jiddata.Online = false
- data[to] = jiddata
- }
-}
-
-func (botdata *XmppBot) handleEventsforXMPP(xmppout chan<- xmpp.Stanza, presence_events <-chan interface{}, jabber_events <-chan JabberEvent) {
- var last_status_msg *string
-
- defer func() {
- if x := recover(); x != nil {
- Syslog_.Printf("handleEventsforXMPP: run time panic: %v", x)
- }
- for _ = range jabber_events {
- } //cleanout jabber_events queue
- }()
-
- for {
- select {
- case pe, pe_still_open := <-presence_events:
- if !pe_still_open {
- return
- }
- Debug_.Printf("handleEventsforXMPP<-presence_events: %T %+v", pe, pe)
- switch pec := pe.(type) {
- case xmpp.Stanza:
- xmppout <- pec
- continue
- case string:
- for to, jiddata := range botdata.realraum_jids_ {
- if jiddata.Wants >= R3DebugInfo {
- xmppout <- botdata.makeXMPPMessage(to, pec, nil)
- }
- }
-
- case XMPPStatusEvent:
- xmppout <- botdata.makeXMPPPresence("", "", pec.Show, pec.Status)
-
- case XMPPMsgEvent:
- if pec.RememberAsStatus {
- last_status_msg = &pec.Msg
- }
- for to, jiddata := range botdata.realraum_jids_ {
- if jiddata.Wants >= pec.DistributeLevel && ((jiddata.Wants >= R3OnlineOnlyInfo && jiddata.Online) || jiddata.Wants >= R3AlwaysInfo) {
- xmppout <- botdata.makeXMPPMessage(to, pec.Msg, nil)
- }
- }
- default:
- Debug_.Println("handleEventsforXMPP<-presence_events: unknown type received: quitting")
- return
- }
-
- case je, je_still_open := <-jabber_events:
- if !je_still_open {
- return
- }
- Debug_.Printf("handleEventsforXMPP<-jabber_events: %T %+v", je, je)
- simple_jid := removeJIDResource(je.JID)
- jid_data, jid_in_map := botdata.realraum_jids_[simple_jid]
-
- //send status if requested, even if user never changed any settings and thus is not in map
- if last_status_msg != nil && je.StatusNow {
- xmppout <- botdata.makeXMPPMessage(je.JID, last_status_msg, nil)
- }
-
- if jid_in_map {
- //if R3OnlineOnlyWithRecapInfo, we want a status update when coming online
- if last_status_msg != nil && !jid_data.Online && je.Online && jid_data.Wants == R3OnlineOnlyWithRecapInfo {
- xmppout <- botdata.makeXMPPMessage(je.JID, last_status_msg, nil)
- }
- jid_data.Online = je.Online
- if je.Wants > R3NoChange {
- jid_data.Wants = je.Wants
- }
- botdata.realraum_jids_[simple_jid] = jid_data
- botdata.realraum_jids_.saveTo(botdata.config_file_)
- } else if je.Wants > R3NoChange {
- botdata.realraum_jids_[simple_jid] = JidData{je.Online, je.Wants}
- botdata.realraum_jids_.saveTo(botdata.config_file_)
- }
- }
- }
-}
-
-func removeJIDResource(jid string) string {
- var jidjid xmpp.JID
- jidjid.Set(jid)
- jidjid.Resource = ""
- return jidjid.String()
-}
-
-func (botdata *XmppBot) isAuthenticated(jid string) bool {
- authtime, in_map := botdata.jid_lastauthtime_[jid]
- return in_map && time.Now().Unix()-authtime < botdata.auth_timeout_
-}
-
-const help_text_ string = "\n*auth*<password>* ...Enables you to use more commands.\n*time* ...Returns bot time."
-const help_text_auth string = "You are authorized to use the following commands:\n*off* ...You will no longer receive notifications.\n*on* ...You will be notified of r3 status changes while you are online.\n*on_with_recap* ...Like *on* but additionally you will receive the current status when you come online.\n*on_while_offline* ...You will receive all r3 status changes, wether you are online or offline.\n*status* ...Use it to query the current status.\n*time* ...Returns bot time.\n*bye* ...Logout."
-
-//~ var re_msg_auth_ *regexp.Regexp = regexp.MustCompile("auth\s+(\S+)")
-
-func (botdata *XmppBot) handleIncomingMessageDialog(inmsg xmpp.Message, xmppout chan<- xmpp.Stanza, jabber_events chan JabberEvent) {
- if inmsg.Body == nil || inmsg.GetHeader() == nil {
- return
- }
- bodytext_args := strings.Split(strings.Replace(inmsg.Body.Chardata, "*", " ", -1), " ")
- for len(bodytext_args) > 1 && len(bodytext_args[0]) == 0 {
- bodytext_args = bodytext_args[1:len(bodytext_args)] //get rid of empty first strings resulting from " text"
- }
- bodytext_lc_cmd := strings.ToLower(bodytext_args[0])
- if botdata.isAuthenticated(inmsg.GetHeader().From) {
- switch bodytext_lc_cmd {
- case "on":
- jabber_events <- JabberEvent{inmsg.GetHeader().From, true, R3OnlineOnlyInfo, false}
- xmppout <- botdata.makeXMPPMessage(inmsg.GetHeader().From, "Receive r3 status updates while online.", "Your New Status")
- case "off":
- jabber_events <- JabberEvent{inmsg.GetHeader().From, true, R3NeverInfo, false}
- xmppout <- botdata.makeXMPPMessage(inmsg.GetHeader().From, "Do not receive anything.", "Your New Status")
- case "on_with_recap":
- jabber_events <- JabberEvent{inmsg.GetHeader().From, true, R3OnlineOnlyWithRecapInfo, false}
- xmppout <- botdata.makeXMPPMessage(inmsg.GetHeader().From, "Receive r3 status updates while and current status on coming, online.", "Your New Status")
- case "on_while_offline":
- jabber_events <- JabberEvent{inmsg.GetHeader().From, true, R3AlwaysInfo, false}
- xmppout <- botdata.makeXMPPMessage(inmsg.GetHeader().From, "Receive all r3 status updates, even if you are offline.", "Your New Status")
- case "debug":
- jabber_events <- JabberEvent{inmsg.GetHeader().From, true, R3DebugInfo, false}
- xmppout <- botdata.makeXMPPMessage(inmsg.GetHeader().From, "Debug mode enabled", "Your New Status")
- case "bye", "quit", "logout":
- botdata.jid_lastauthtime_[inmsg.GetHeader().From] = 0
- xmppout <- botdata.makeXMPPMessage(inmsg.GetHeader().From, "Bye Bye !", nil)
- case "open", "close":
- xmppout <- botdata.makeXMPPMessage(inmsg.GetHeader().From, "Sorry, I'm just weak software, not strong enough to operate the door for you.", nil)
- case "status":
- jabber_events <- JabberEvent{inmsg.GetHeader().From, true, R3NoChange, true}
- case "time":
- xmppout <- botdata.makeXMPPMessage(inmsg.GetHeader().From, time.Now().String(), nil)
- case "ping":
- xmppout <- botdata.makeXMPPMessage(inmsg.GetHeader().From, "Pong with auth", nil)
- default:
- //~ auth_match = re_msg_auth_.FindStringSubmatch(inmsg.Body.Chardata)
- xmppout <- botdata.makeXMPPMessage(inmsg.GetHeader().From, help_text_auth, nil)
- }
- } else {
- switch bodytext_lc_cmd {
- case "hilfe", "help", "?", "hallo", "yes", "ja", "ja bitte", "bitte", "sowieso":
- xmppout <- botdata.makeXMPPMessage(inmsg.GetHeader().From, help_text_, "Available Commands")
- case "auth":
- authindex := 1
- for len(bodytext_args) > authindex && len(bodytext_args[authindex]) == 0 {
- authindex++
- }
- if len(bodytext_args) > authindex && bodytext_args[authindex] == botdata.password_ {
- botdata.jid_lastauthtime_[inmsg.GetHeader().From] = time.Now().Unix()
- xmppout <- botdata.makeXMPPMessage(inmsg.GetHeader().From, help_text_auth, nil)
- }
- case "status", "off", "on", "on_while_offline", "on_with_recap":
- xmppout <- botdata.makeXMPPMessage(inmsg.GetHeader().From, "Sorry, you need to be authorized to do that.", nil)
- case "time":
- xmppout <- botdata.makeXMPPMessage(inmsg.GetHeader().From, time.Now().String(), nil)
- case "ping":
- xmppout <- botdata.makeXMPPMessage(inmsg.GetHeader().From, "Pong", nil)
- case "":
- xmppout <- botdata.makeXMPPMessage(inmsg.GetHeader().From, "You're a quiet one, aren't you?", nil)
- default:
- //~ auth_match = re_msg_auth_.FindStringSubmatch(inmsg.Body.Chardata)
- xmppout <- botdata.makeXMPPMessage(inmsg.GetHeader().From, "A nice day to you too !\nDo you need \"help\" ?", nil)
- }
- }
-}
-
-func (botdata *XmppBot) handleIncomingXMPPStanzas(xmppin <-chan xmpp.Stanza, xmppout chan<- xmpp.Stanza, jabber_events chan JabberEvent) {
-
- defer func() {
- if x := recover(); x != nil {
- Syslog_.Printf("handleIncomingXMPPStanzas: run time panic: %v", x)
- }
- }()
-
- var error_count int = 0
- var incoming_stanza interface{}
-
- handleStanzaError := func() bool {
- error_count++
- if error_count > 15 {
- Syslog_.Println("handleIncomingXMPPStanzas: too many errors in series.. bailing out")
- botdata.StopBot()
- return true
- }
- return false
- }
-
- for incoming_stanza = range xmppin {
- switch stanza := incoming_stanza.(type) {
- case *xmpp.Message:
- if stanza.GetHeader() == nil {
- continue
- }
- if stanza.Type == "error" || stanza.Error != nil {
- Syslog_.Printf("XMPP %T Error: %s", stanza, stanza)
- if stanza.Error.Type == "cancel" {
- // asume receipient not reachable -> disable
- Syslog_.Printf("Error reaching %s. Disabling user, please reenable manually", stanza.From)
- jabber_events <- JabberEvent{stanza.From, false, R3NeverInfo, false}
- continue
- }
- if handleStanzaError() {
- return
- }
- continue
- } else {
- error_count = 0
- }
- botdata.handleIncomingMessageDialog(*stanza, xmppout, jabber_events)
- case *xmpp.Presence:
- if stanza.GetHeader() == nil {
- continue
- }
- if stanza.Type == "error" || stanza.Error != nil {
- Syslog_.Printf("XMPP %T Error: %s", stanza, stanza)
- if handleStanzaError() {
- return
- }
- continue
- } else {
- error_count = 0
- }
- switch stanza.GetHeader().Type {
- case "subscribe":
- xmppout <- botdata.makeXMPPPresence(stanza.GetHeader().From, "subscribed", "", "")
- jabber_events <- JabberEvent{stanza.GetHeader().From, true, R3NoChange, false}
- xmppout <- botdata.makeXMPPPresence(stanza.GetHeader().From, "subscribe", "", "")
- case "unsubscribe", "unsubscribed":
- jabber_events <- JabberEvent{stanza.GetHeader().From, false, R3NeverInfo, false}
- botdata.jid_lastauthtime_[stanza.GetHeader().From] = 0 //logout
- xmppout <- botdata.makeXMPPPresence(stanza.GetHeader().From, "unsubscribe", "", "")
- case "unavailable":
- jabber_events <- JabberEvent{stanza.GetHeader().From, false, R3NoChange, false}
- botdata.jid_lastauthtime_[stanza.GetHeader().From] = 0 //logout
- default:
- jabber_events <- JabberEvent{stanza.GetHeader().From, true, R3NoChange, false}
- }
-
- case *xmpp.Iq:
- if stanza.GetHeader() == nil {
- continue
- }
- if stanza.Type == "error" || stanza.Error != nil {
- Syslog_.Printf("XMPP %T Error: %s", stanza, stanza)
- if handleStanzaError() {
- return
- }
- continue
- } else {
- error_count = 0
- }
-
- if HandleServerToClientPing(stanza, xmppout) {
- continue
- } //if true then routine handled it and we can continue
- Debug_.Printf("Unhandled Iq: %s", stanza)
- }
- }
-}
-
-func init() {
- //~ xmpp.Debug = &XMPPDebugLogger{}
- xmpp.Info = &XMPPDebugLogger{}
- xmpp.Warn = &XMPPLogger{}
-}
-
-func NewStartedBot(loginjid, loginpwd, password, state_save_dir string, insecuretls bool) (*XmppBot, chan interface{}, error) {
- var err error
- botdata := new(XmppBot)
-
- botdata.realraum_jids_ = make(map[string]JidData, 1)
- botdata.jid_lastauthtime_ = make(map[string]int64, 1)
- botdata.my_jid_ = loginjid
- botdata.my_login_password_ = loginpwd
- botdata.password_ = password
- botdata.auth_timeout_ = 3600 * 2
-
- botdata.config_file_ = path.Join(state_save_dir, "r3xmpp."+removeJIDResource(loginjid)+".json")
-
- xmpp.TlsConfig = tls.Config{InsecureSkipVerify: insecuretls}
- botdata.realraum_jids_.loadFrom(botdata.config_file_)
-
- client_jid := new(xmpp.JID)
- client_jid.Set(botdata.my_jid_)
- botdata.xmppclient_, err = xmpp.NewClient(client_jid, botdata.my_login_password_, nil)
- if err != nil {
- Syslog_.Println("Error connecting to xmpp server", err)
- return nil, nil, err
- }
- if botdata.xmppclient_ == nil {
- Syslog_.Println("xmpp.NewClient returned nil without error")
- return nil, nil, errors.New("No answer from xmpp server")
- }
-
- err = botdata.xmppclient_.StartSession(true, &xmpp.Presence{})
- if err != nil {
- Syslog_.Println("'Error StartSession:", err)
- return nil, nil, err
- }
-
- roster := xmpp.Roster(botdata.xmppclient_)
- for _, entry := range roster {
- Debug_.Print(entry)
- if entry.Subscription == "from" {
- botdata.xmppclient_.Out <- botdata.makeXMPPPresence(entry.Jid, "subscribe", "", "")
- }
- if entry.Subscription == "none" {
- delete(botdata.realraum_jids_, entry.Jid)
- }
- }
-
- presence_events := make(chan interface{}, 1)
- jabber_events := make(chan JabberEvent, 1)
-
- go func() {
- for { //auto recover from panic
- botdata.handleEventsforXMPP(botdata.xmppclient_.Out, presence_events, jabber_events)
- }
- }()
- go func() {
- for { //auto recover from panic
- botdata.handleIncomingXMPPStanzas(botdata.xmppclient_.In, botdata.xmppclient_.Out, jabber_events)
- }
- }()
-
- botdata.presence_events_ = &presence_events
-
- return botdata, presence_events, nil
-}
-
-func (botdata *XmppBot) StopBot() {
- Syslog_.Println("Stopping XMPP Bot")
- if botdata.xmppclient_ != nil {
- close(botdata.xmppclient_.Out)
- }
- if botdata.presence_events_ != nil {
- *botdata.presence_events_ <- false
- close(*botdata.presence_events_)
- }
- botdata.config_file_ = ""
- botdata.realraum_jids_ = nil
- botdata.xmppclient_ = nil
-}
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-// spaceapi.go
-package spaceapi
-
-import (
- "encoding/json"
- "time"
-)
-
-const max_num_events int = 4
-
-type SpaceInfo map[string]interface{}
-
-type SpaceDoorLockSensor struct {
- value bool
- location string
- name string
- description string
-}
-
-type SpaceDoorAjarSensor struct {
- value bool
- location string
- name string
- description string
-}
-
-func MakeTempSensor(name, where, unit string, value float64) SpaceInfo {
- listofwhats := make([]SpaceInfo, 1)
- listofwhats[0] = SpaceInfo{
- "value": value,
- "unit": unit,
- "location": where,
- "name": name,
- "description": ""}
- return SpaceInfo{"temperature": listofwhats}
-}
-
-func MakeTempCSensor(name, where string, value float64) SpaceInfo {
- return MakeTempSensor(name,where,"\u00b0C",value)
-}
-
-func MakeIlluminationSensor(name, where, unit string, value int64) SpaceInfo {
- listofwhats := make([]SpaceInfo, 1)
- listofwhats[0] = SpaceInfo{
- "value": value,
- "unit": unit,
- "location": where,
- "name": name,
- "description": ""}
- return SpaceInfo{"ext_illumination": listofwhats}
-}
-
-func MakePowerConsumptionSensor(name, where, unit string, value int64) SpaceInfo {
- listofwhats := make([]SpaceInfo, 1)
- listofwhats[0] = SpaceInfo{
- "value": value,
- "unit": unit,
- "location": where,
- "name": name,
- "description": ""}
- return SpaceInfo{"power_consumption": listofwhats}
-}
-
-func MakeNetworkConnectionsSensor(name, where, nettype string, value, machines int64) SpaceInfo {
- listofwhats := make([]SpaceInfo, 1)
- listofwhats[0] = SpaceInfo{
- "value": value,
- "type": nettype,
- "machines": machines,
- "location": where,
- "name": name,
- "description": ""}
- return SpaceInfo{"network_connections": listofwhats}
-}
-
-func MakeMemberCountSensor(name, where string, value int64) SpaceInfo {
- listofwhats := make([]SpaceInfo, 1)
- listofwhats[0] = SpaceInfo{
- "value": value,
- "location": where,
- "name": name,
- "description": ""}
- return SpaceInfo{"total_member_count": listofwhats}
-}
-
-func MakeDoorLockSensor(name, where string, value bool) SpaceInfo {
- listofwhats := make([]SpaceInfo, 1)
- listofwhats[0] = SpaceInfo{
- "value": value,
- "location": where,
- "name": name,
- "description": ""}
- return SpaceInfo{"door_locked": listofwhats}
-}
-
-func MakeDoorAjarSensor(name, where string, value bool) SpaceInfo {
- listofwhats := make([]SpaceInfo, 1)
- listofwhats[0] = SpaceInfo{
- "value": value,
- "location": where,
- "name": name,
- "description": ""}
- return SpaceInfo{"ext_door_ajar": listofwhats}
-}
-
-func (nsi SpaceInfo) MergeInSensor(sensorinfo SpaceInfo) {
- if nsi["sensors"] == nil {
- nsi["sensors"] = SpaceInfo{}
- //~ listofwhats := make([]SpaceInfo, 1)
- //~ listofwhats[0] = sensortype.(SpaceInfo)
- //~ sensorobj := SpaceInfo{what: listofwhats}
- //~ nsi["sensors"] = sensorobj
- }
- sensorobj := nsi["sensors"].(SpaceInfo)
- for what, subsensorobjlist := range sensorinfo {
- if sensorobj[what] == nil {
- sensorobj[what] = subsensorobjlist
- } else {
- existingsensorobjslist := sensorobj[what].([]SpaceInfo)
- for _, newsensorobj := range subsensorobjlist.([]SpaceInfo) {
- foundandsubstituted := false
- for i:=0; i< len(existingsensorobjslist); i++ {
- if existingsensorobjslist[i]["name"] == newsensorobj["name"] {
- existingsensorobjslist[i] = newsensorobj
- foundandsubstituted = true
- }
- }
- if foundandsubstituted == false {
- sensorobj[what] = append(sensorobj[what].([]SpaceInfo), newsensorobj)
- //note that we do not change existingsensorobjslist here but directly sensorobj[what] !!
- //the implications being that, if we have several newsensorobj in the list:
- // a) optimisation: we only check them against the existing ones and spare ourselves the work of checking a newsensorobj's name against a just added other newsensorobjs's name
- // b) if the array sensorinfo[what] has several objects with the same name, nsi["sensors"] will also end up with these name conflicts
- }
- }
- }
- }
-}
-
-func (nsi SpaceInfo) AddSpaceContactInfo(phone, irc, email, ml, jabber, issuemail string) SpaceInfo {
- nsi["contact"] = SpaceInfo{
- "phone": phone,
- "email": email,
- "ml": ml,
- "jabber": jabber,
- "issue_mail": issuemail}
- nsi["issue_report_channels"] = [3]string{"issue_mail","email","ml"}
- return nsi
-}
-
-func (nsi SpaceInfo) AddSpaceFeed(feedtype, url string) SpaceInfo {
- newfeed := SpaceInfo{"url": url}
- if nsi["feeds"] == nil {
- nsi["feeds"] = SpaceInfo{feedtype: newfeed}
- } else {
- feedobj, ok := nsi["feeds"].(SpaceInfo) //type assertion (panics if false)
- if ok {
- feedobj[feedtype] = newfeed
- } else {
- panic("Wrong Type of feedobj: Should never happen")
- }
- }
- return nsi
-}
-
-func (nsi SpaceInfo) AddSpaceEvent(name, eventtype, extra string) SpaceInfo {
- newevent := SpaceInfo{"name": name, "type": eventtype, "timestamp": time.Now().Unix(), "extra": extra}
- if nsi["events"] == nil {
- eventlist := make([]SpaceInfo, 1)
- eventlist[0] = newevent
- nsi["events"] = eventlist
- } else {
- eventlist, ok := nsi["events"].([]SpaceInfo) //type assertion
- if ok {
- if len(eventlist) >= max_num_events {
- eventlist = eventlist[1:]
- }
- nsi["events"] = append(eventlist, newevent)
- } else {
- panic("Wrong Type of eventlist: Should never happen")
- }
- }
- return nsi
-}
-
-func (nsi SpaceInfo) AddSpaceAddress(address string) SpaceInfo {
- nsi["address"] = address
- if nsi["location"] != nil {
- location, ok := nsi["location"].(SpaceInfo)
- if ok {
- location["address"] = address
- }
- }
- return nsi
-}
-
-func (nsi SpaceInfo) SetStatus(open bool, status string) {
- nsi["status"] = status
- nsi["open"] = open
- nsi["lastchange"] = time.Now().Unix()
- state, ok := nsi["state"].(SpaceInfo)
- if ok {
- state["message"] = status
- state["open"] = open
- state["lastchange"] = nsi["lastchange"]
- }
-}
-
-func NewSpaceInfo(space string, url string, logo string, open_icon string, closed_icon string, lat float64, lon float64) SpaceInfo {
- nsi := map[string]interface{}{
- "api": "0.13",
- "space": space,
- "url": url,
- "logo": logo,
- "open": false,
- "lastchange": time.Now().Unix(),
- "icon": SpaceInfo{
- "open": open_icon,
- "closed": closed_icon,
- },
- "state": SpaceInfo{
- "open": false,
- "lastchange":time.Now().Unix(),
- "icon": SpaceInfo{
- "open": open_icon,
- "closed": closed_icon},
- },
- "location": SpaceInfo{
- "lat": lat,
- "lon": lon},
- "contact" : SpaceInfo {},
- }
- return nsi
-}
-
-func (data SpaceInfo) MakeJSON() ([]byte, error) {
- msg, err := json.Marshal(data)
- if err == nil {
- return msg, nil
- }
- return nil, err
-}
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- pubsub "github.com/tuxychandru/pubsub"
- "./spaceapi"
- "regexp"
- "net/http"
- "net/url"
- "time"
- "fmt"
- r3events "svn.spreadspace.org/realraum/go.svn/r3events"
- )
-
-
-type spaceState struct {
- present bool
- buttonpress_until int64
-}
-
-var (
- spaceapidata spaceapi.SpaceInfo = spaceapi.NewSpaceInfo("realraum", "http://realraum.at", "http://realraum.at/logo-red_250x250.png", "http://realraum.at/logo-re_open_100x100.png", "http://realraum.at/logo-re_empty_100x100.png",47.065554, 15.450435).AddSpaceAddress("Brockmanngasse 15, 8010 Graz, Austria")
- statusstate *spaceState = new(spaceState)
- re_querystresc_ *regexp.Regexp = regexp.MustCompile("[^\x30-\x39\x41-\x7E]")
-)
-
-
-func init() {
- spaceapidata.AddSpaceFeed("calendar", "http://grical.realraum.at/s/?query=!realraum&view=rss")
- spaceapidata.AddSpaceFeed("blog", "https://plus.google.com/113737596421797426873")
- spaceapidata.AddSpaceFeed("wiki", "http://realraum.at/wiki")
- spaceapidata.AddSpaceContactInfo("+43780700888524", "irc://irc.oftc.net/#realraum", "realraum@realraum.at", "realraum@realraum.at", "realraum@realraum.at", "vorstand@realraum.at")
-}
-
-
-func updateStatusString() {
- var spacestatus string
- if statusstate.present {
- if statusstate.buttonpress_until > time.Now().Unix() {
- spacestatus = "Panic! Present&Bored"
- } else {
- spacestatus = "Leute Anwesend"
- }
- } else {
- spacestatus = "Keiner Da"
- }
- spaceapidata.SetStatus(statusstate.present, spacestatus)
-}
-
-func publishStateToWeb() {
- updateStatusString()
- jsondata_b, err := spaceapidata.MakeJSON()
- if err != nil {
- Syslog_.Println("Error:", err)
- return
- }
- //jsondata_b := re_querystresc_.ReplaceAllFunc(jsondata_b, func(in []byte) []byte {
- // out := make([]byte, 4)
- // out[0] = '%'
- // copy(out[1:], []byte(strconv.FormatInt(int64(in[0]), 16)))
- // return out
- //})
- jsondata := url.QueryEscape(string(jsondata_b))
- resp, err := http.Get("http://www.realraum.at/cgi/status.cgi?pass=jako16&set=" + jsondata)
- if err != nil {
- Syslog_.Println("Error publishing realraum info", err)
- return
- }
- resp.Body.Close()
-}
-
-func EventToWeb(ps *pubsub.PubSub) {
- events := ps.Sub("presence","door","sensors","buttons","updateinterval")
-
- for eventinterface := range(events) {
- //Debug_.Printf("EventToWeb: %s" , eventinterface)
- switch event := eventinterface.(type) {
- case r3events.TimeTick:
- publishStateToWeb()
- case r3events.PresenceUpdate:
- statusstate.present = event.Present
- publishStateToWeb()
- case r3events.BackdoorAjarUpdate:
- spaceapidata.MergeInSensor(spaceapi.MakeDoorLockSensor("HintertorwaechterAjarSensor", "Hintertürkontakt", event.Shut))
- publishStateToWeb()
- case r3events.DoorAjarUpdate:
- spaceapidata.MergeInSensor(spaceapi.MakeDoorLockSensor("TorwaechterAjarSensor", "Türkontakt", event.Shut))
- publishStateToWeb()
- case r3events.DoorLockUpdate:
- spaceapidata.MergeInSensor(spaceapi.MakeDoorLockSensor("TorwaechterLock", "Türschloß", event.Locked))
- publishStateToWeb()
- case r3events.BoreDoomButtonPressEvent:
- statusstate.buttonpress_until = event.Ts + 3600
- spaceapidata.AddSpaceEvent("BoreDOOMButton", "check-in", "The button has been pressed")
- publishStateToWeb()
- case r3events.TempSensorUpdate:
- var tempsensorlocation string
- switch event.Sensorindex {
- case 0:
- tempsensorlocation = "LoTHR"
- case 1:
- tempsensorlocation = "CX"
- default:
- tempsensorlocation = "Sonstwo"
- }
- spaceapidata.MergeInSensor(spaceapi.MakeTempCSensor(fmt.Sprintf("Temp%d",event.Sensorindex),tempsensorlocation, event.Value))
- case r3events.IlluminationSensorUpdate:
- spaceapidata.MergeInSensor(spaceapi.MakeIlluminationSensor("Photodiode","LoTHR","1024V/5V", event.Value))
- case r3events.GasLeakAlert:
- spaceapidata.AddSpaceEvent("GasLeak", "alert", "GasLeak Alert has been triggered")
- publishStateToWeb()
- }
- }
-}
-
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- zmq "github.com/vaughan0/go-zmq"
- )
-
-// ---------- ZeroMQ Code -------------
-
-func ZmqsInit(sub_port string) (ctx *zmq.Context, sub_chans *zmq.Channels) {
- var err error
- ctx, err = zmq.NewContext()
- if err != nil {
- panic(err)
- }
- //close only on later panic, otherwise leave open:
- defer func(){ if r:= recover(); r != nil { ctx.Close(); panic(r) } }()
-
- if len(sub_port) > 0 {
- sub_sock, err := ctx.Socket(zmq.Sub)
- if err != nil {
- panic(err)
- }
- defer func() { if r:= recover(); r != nil { sub_sock.Close(); panic(r) } }()
-
- sub_sock.Subscribe([]byte{}) //subscribe empty filter -> aka to all messages
-
- if err = sub_sock.Connect(sub_port); err != nil {
- panic(err)
- }
-
- sub_chans = sub_sock.ChannelsBuffer(10)
- go zmqsHandleError(sub_chans)
- } else {
- sub_chans = nil
- }
-
- return
-}
-
-func zmqsHandleError(chans *zmq.Channels) {
- for error := range(chans.Errors()) {
- chans.Close()
- panic(error)
- }
-}
-
-func ZmqsRequestAnswer(sock *zmq.Socket, request [][]byte) (answer [][]byte) {
- if err := sock.Send(request); err != nil {
- panic(err)
- }
- parts, err := sock.Recv()
- if err != nil {
- panic(err)
- }
- return parts
-}
-
-func ZmqsAskQuestionsAndClose(ctx *zmq.Context, addr string, questions [][][]byte) [][][]byte {
- if len(addr) == 0 || ctx == nil { return nil }
-
- req_sock, err := ctx.Socket(zmq.Req)
- if err != nil {
- return nil
- }
- defer req_sock.Close()
-
- if err = req_sock.Connect(addr); err != nil {
- return nil
- }
-
- rv := make([][][]byte, len(questions))
- for index, q := range(questions) {
- rv[index] = ZmqsRequestAnswer(req_sock, q)
- }
- return rv
-}
\ No newline at end of file
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package r3events
-
-
-type DoorLockUpdate struct {
- Locked bool
- Ts int64
-}
-
-type DoorAjarUpdate struct {
- Shut bool
- Ts int64
-}
-
-type BackdoorAjarUpdate struct {
- Shut bool
- Ts int64
-}
-
-type DoorCommandEvent struct {
- Command string
- Using string
- Who string
- Ts int64
-}
-
-type DoorManualMovementEvent struct {
- Ts int64
-}
-
-type DoorProblemEvent struct {
- Severity int
- Problem string
- Ts int64
-}
-
-type BoreDoomButtonPressEvent struct {
- Ts int64
-}
-
-type TempSensorUpdate struct {
- Sensorindex int
- Value float64
- Ts int64
-}
-
-type IlluminationSensorUpdate struct {
- Sensorindex int
- Value int64
- Ts int64
-}
-
-type DustSensorUpdate struct {
- Sensorindex int
- Value int64
- Ts int64
-}
-
-type RelativeHumiditySensorUpdate struct {
- Sensorindex int
- Percent int
- Ts int64
-}
-
-type NetDHCPACK struct {
- Mac string
- IP string
- Name string
- Ts int64
-}
-
-type NetGWStatUpdate struct {
- WifiRX int32
- WifiTX int32
- EthernetRX int32
- EthernetTX int32
- InternetRX int32
- InternetTX int32
- NumNeigh int32
- Ts int64
-}
-
-type GasLeakAlert struct {
- Ts int64
-}
-
-type TimeTick struct {
- Ts int64
-}
-
-type MovementSensorUpdate struct {
- Sensorindex int
- Ts int64
-}
\ No newline at end of file
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package r3events
-
-import (
- "encoding/json"
- "fmt"
- "errors"
- "strings"
- )
-
-func NameOfStruct(evi interface{}) (name string) {
- etype := fmt.Sprintf("%T", evi)
- etype_lastsep := strings.LastIndex(etype,".")
- return etype[etype_lastsep+1:] //works in all cases for etype_lastsep in range -1 to len(etype)-1
-}
-
-func MarshalEvent2ByteByte(event_interface interface{}) (data [][]byte, err error) {
- var msg []byte
- //~ fmt.Printf("%T%+v\n", event_interface, event_interface)
- msg, err = json.Marshal(event_interface)
- if err != nil {
- return
- }
- data = [][]byte{[]byte(NameOfStruct(event_interface)), msg} //works in all cases for etype_lastsep in range -1 to len(etype)-1
- return
-}
-
-func UnmarshalByteByte2Event(data [][]byte) (event interface{}, category string, err error) {
- if len(data) != 2 {
- return nil, "", errors.New("not a r3event message")
- }
- switch string(data[0]) {
- case "DoorLockUpdate":
- newevent := new(DoorLockUpdate)
- err = json.Unmarshal(data[1],newevent)
- category = "door"
- event = *newevent
- case "DoorAjarUpdate":
- newevent := new(DoorAjarUpdate)
- err = json.Unmarshal(data[1], newevent)
- category = "door"
- event = *newevent
- case "BackdoorAjarUpdate":
- newevent := new(BackdoorAjarUpdate)
- err = json.Unmarshal(data[1], newevent)
- category = "door"
- event = *newevent
- case "DoorCommandEvent":
- newevent := new(DoorCommandEvent)
- err = json.Unmarshal(data[1], newevent)
- category = "door"
- event = *newevent
- case "DoorProblemEvent":
- newevent := new(DoorProblemEvent)
- err = json.Unmarshal(data[1], newevent)
- category = "door"
- event = *newevent
- case "DoorManualMovementEvent":
- newevent := new(DoorManualMovementEvent)
- err = json.Unmarshal(data[1], newevent)
- category = "door"
- event = *newevent
- case "BoreDoomButtonPressEvent":
- newevent := new(BoreDoomButtonPressEvent)
- err = json.Unmarshal(data[1], newevent)
- category = "buttons"
- event = *newevent
- case "TempSensorUpdate":
- newevent := new(TempSensorUpdate)
- err = json.Unmarshal(data[1], newevent)
- category = "sensors"
- event = *newevent
- case "IlluminationSensorUpdate":
- newevent := new(IlluminationSensorUpdate)
- err = json.Unmarshal(data[1], newevent)
- category = "sensors"
- event = *newevent
- case "DustSensorUpdate":
- newevent := new(DustSensorUpdate)
- err = json.Unmarshal(data[1], newevent)
- category = "sensors"
- event = *newevent
- case "RelativeHumiditySensorUpdate":
- newevent := new(RelativeHumiditySensorUpdate)
- err = json.Unmarshal(data[1], newevent)
- category = "sensors"
- event = *newevent
- case "TimeTick":
- newevent := new(TimeTick)
- err = json.Unmarshal(data[1], newevent)
- category = "time"
- event = *newevent
- case "GasLeakAlert":
- newevent := new(GasLeakAlert)
- err = json.Unmarshal(data[1], newevent)
- category = "sensors"
- event = *newevent
- case "MovementSensorUpdate":
- newevent := new(MovementSensorUpdate)
- err = json.Unmarshal(data[1], newevent)
- category = "movement"
- event = *newevent
- case "PresenceUpdate":
- newevent := new(PresenceUpdate)
- err = json.Unmarshal(data[1], newevent)
- category = "presence"
- event = *newevent
- case "SomethingReallyIsMoving":
- newevent := new(SomethingReallyIsMoving)
- err = json.Unmarshal(data[1], newevent)
- category = "movement"
- event = *newevent
- case "TempSensorSpike":
- newevent := new(TempSensorSpike)
- err = json.Unmarshal(data[1], newevent)
- category = "sensors"
- event = *newevent
- case "DustSensorSpike":
- newevent := new(DustSensorSpike)
- err = json.Unmarshal(data[1], newevent)
- category = "sensors"
- event = *newevent
- case "NetDHCPACK":
- newevent := new(NetDHCPACK)
- err = json.Unmarshal(data[1], newevent)
- category = "network"
- event = *newevent
- case "NetGWStatUpdate":
- newevent := new(NetGWStatUpdate)
- err = json.Unmarshal(data[1], newevent)
- category = "network"
- event = *newevent
- default:
- event = nil
- err = errors.New("cannot unmarshal unknown type")
- category = ""
- }
- return
-}
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package r3events
-
-type PresenceUpdate struct {
- Present bool
- Ts int64
-}
-
-type SomethingReallyIsMoving struct {
- Movement bool
- Confidence uint8
- Ts int64
-}
-
-type TempSensorSpike struct {
- Sensorindex int
- Value float64
- Ts int64
-}
-
-type DustSensorSpike struct {
- Sensorindex int
- Value int64
- Ts int64
-}
\ No newline at end of file
+++ /dev/null
-// +build linux,arm
-
-
-package termios
-
-import (
- "os";
- "syscall";
- "unsafe"
- "errors"
-)
-
-// termios types
-type cc_t byte
-type speed_t uint32
-type tcflag_t uint32
-
-// termios constants
-const (
- IGNBRK = tcflag_t (0000001)
- BRKINT = tcflag_t (0000002)
- syscall.IGNPAR = tcflag_t (0000004)
- syscall.PARMRK = tcflag_t (0000010)
- syscall.INLCR = tcflag_t (0000100)
- syscall.ECHONL = tcflag_t (0000100)
- syscall.IGNCR = tcflag_t (0000200)
- syscall.ICRNL = tcflag_t (0000400)
- syscall.INPCK = tcflag_t (0000020)
- syscall.ISTRIP = tcflag_t (0000040)
- syscall.IXON = tcflag_t (0002000)
- syscall.OPOST = tcflag_t (0000001)
- syscall.CS8 = tcflag_t (0000060)
- syscall.ECHO = tcflag_t (0000010)
- syscall.ICANON = tcflag_t (0000002)
- syscall.IEXTEN = tcflag_t (0100000)
- syscall.ISIG = tcflag_t (0000001)
- syscall.VTIME = tcflag_t (5)
- syscall.VMIN = tcflag_t (6)
- syscall.CBAUD = tcflag_t (0010017)
- syscall..CBAUDEX = tcflag_t (0010000)
-)
-
-const (
- B0 = speed_t(0000000) /* hang up */
- B50 = speed_t(0000001)
- B75 = speed_t(0000002)
- B110 = speed_t(0000003)
- B134 = speed_t(0000004)
- B150 = speed_t(0000005)
- B200 = speed_t(0000006)
- B300 = speed_t(0000007)
- B600 = speed_t(0000010)
- B1200 = speed_t(0000011)
- B1800 = speed_t(0000012)
- B2400 = speed_t(0000013)
- B4800 = speed_t(0000014)
- B9600 = speed_t(0000015)
- B19200 = speed_t(0000016)
- B38400 = speed_t(0000017)
- B57600 = speed_t(0010001)
- B115200 = speed_t(0010002)
- B230400 = speed_t(0010003)
- B460800 = speed_t(0010004)
- B500000 = speed_t(0010005)
- B576000 = speed_t(0010006)
- B921600 = speed_t(0010007)
- B1000000 = speed_t(0010010)
- B1152000 = speed_t(0010011)
- B1500000 = speed_t(0010012)
- B2000000 = speed_t(0010013)
- B2500000 = speed_t(0010014)
- B3000000 = speed_t(0010015)
- B3500000 = speed_t(0010016)
- B4000000 = speed_t(0010017)
-)
-
-//note that struct termios and struct __kernel_termios have DIFFERENT size and layout !!!
-const NCCS = 23 //23 on mips, 19 on alpha (also line and cc reversed), 19 on powerpc (also line and cc reversed), 17 on sparc,
-type termios struct {
- c_iflag, c_oflag, c_cflag, c_lflag tcflag_t
- c_line cc_t
- c_cc [NCCS]cc_t
- c_ispeed, c_ospeed speed_t
-}
-
-// ioctl constants
-const (
- TCGETS = 0x5401
- TCSETS = 0x5402
-)
-
-func getTermios(ttyfd uintptr, dst *termios) error {
- r1, _, errno := syscall. (syscall.SYS_IOCTL,
- uintptr (ttyfd), uintptr (TCGETS),
- uintptr (unsafe.Pointer (dst)));
-
- if err := os.NewSyscallError ("SYS_IOCTL", errno); errno!=0 && err != nil {
- return err
- }
-
- if r1 != 0 {
- // return errors.New("Error")
- }
- return nil
-}
-
-func setTermios(ttyfd uintptr, src *termios) error {
- r1, _, errno := syscall. (syscall.SYS_IOCTL,
- uintptr (ttyfd), uintptr (TCSETS),
- uintptr (unsafe.Pointer (src)));
-
- if err := os.NewSyscallError ("SYS_IOCTL", errno); errno!=0 &&err != nil {
- return err
- }
-
- if r1 != 0 {
- return errors.New ("Error during ioctl tcsets syscall")
- }
- return nil
-}
-
-func SetRawFd(fd uintptr) (error) {
- var orig_termios termios;
- if err := getTermios (fd, &orig_termios); err != nil { return err}
-
- orig_termios.c_iflag &= ^(syscall.IGNBRK|syscall.BRKINT|syscall.PARMRK|syscall.ISTRIP|syscall.INLCR|syscall.IGNCR|syscall.ICRNL|syscall.IXON);
- orig_termios.c_oflag &= ^(syscall.OPOST);
- orig_termios.c_lflag &= ^(syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.IEXTEN | syscall.ISIG);
- orig_termios.c_cflag |= (syscall.CS8);
-
- orig_termios.c_cc[syscall.VMIN] = 1;
- orig_termios.c_cc[syscall.VTIME] = 0;
-
- return setTermios(fd, &orig_termios)
-}
-
-func SetRawFile(f *os.File) (error) {
- return SetRawFd(f.Fd())
-}
-
-func SetSpeedFd(fd uintptr, speed speed_t) (err error) {
- var orig_termios termios;
- if err = getTermios (fd, &orig_termios); err != nil { return }
-
- orig_termios.c_ispeed = speed
- orig_termios.c_ospeed = speed
- //~ //input baudrate == output baudrate and we ignore special case B0
- //~ orig_termios.c_cflag &= ^(syscall.CBAUD | syscall..CBAUDEX)
- //~ orig_termios.c_cflag |= speed
- if err = setTermios(fd, &orig_termios); err != nil { return }
- if err = getTermios (fd, &orig_termios); err != nil { return }
- if orig_termios.c_ispeed != speed || orig_termios.c_ospeed != speed {
- err = errors.New("Failed to set speed")
- }
- //~ if err = getTermios (fd, &orig_termios); err != nil { return }
- //~ if orig_termios.c_cflag & (syscall.CBAUD | syscall.CBAUDEX) != speed {
- //~ err = errors.New("Failed to set speed")
- //~ }
- return
-}
-
-func SetSpeedFile(f *os.File, speed speed_t) (error) {
- return SetSpeedFd(f.Fd(), speed)
-}
\ No newline at end of file
+++ /dev/null
-// +build linux,386 linux,amd64
-
-
-package termios
-
-import (
- "os";
- "syscall";
- "unsafe"
- "errors"
-)
-
-// termios types
-type cc_t byte
-type speed_t uint32
-type tcflag_t uint32
-
-// termios constants
-const (
- IGNBRK = tcflag_t (0000001)
- BRKINT = tcflag_t (0000002)
- IGNPAR = tcflag_t (0000004)
- PARMRK = tcflag_t (0000010)
- INLCR = tcflag_t (0000100)
- ECHONL = tcflag_t (0000100)
- IGNCR = tcflag_t (0000200)
- ICRNL = tcflag_t (0000400)
- INPCK = tcflag_t (0000020)
- ISTRIP = tcflag_t (0000040)
- IXON = tcflag_t (0002000)
- OPOST = tcflag_t (0000001)
- CS8 = tcflag_t (0000060)
- ECHO = tcflag_t (0000010)
- ICANON = tcflag_t (0000002)
- IEXTEN = tcflag_t (0100000)
- ISIG = tcflag_t (0000001)
- VTIME = tcflag_t (5)
- VMIN = tcflag_t (6)
- CBAUD = tcflag_t (0010017)
- CBAUDEX = tcflag_t (0010000)
-)
-
-const (
- B0 = speed_t(0000000) /* hang up */
- B50 = speed_t(0000001)
- B75 = speed_t(0000002)
- B110 = speed_t(0000003)
- B134 = speed_t(0000004)
- B150 = speed_t(0000005)
- B200 = speed_t(0000006)
- B300 = speed_t(0000007)
- B600 = speed_t(0000010)
- B1200 = speed_t(0000011)
- B1800 = speed_t(0000012)
- B2400 = speed_t(0000013)
- B4800 = speed_t(0000014)
- B9600 = speed_t(0000015)
- B19200 = speed_t(0000016)
- B38400 = speed_t(0000017)
- B57600 = speed_t(0010001)
- B115200 = speed_t(0010002)
- B230400 = speed_t(0010003)
- B460800 = speed_t(0010004)
- B500000 = speed_t(0010005)
- B576000 = speed_t(0010006)
- B921600 = speed_t(0010007)
- B1000000 = speed_t(0010010)
- B1152000 = speed_t(0010011)
- B1500000 = speed_t(0010012)
- B2000000 = speed_t(0010013)
- B2500000 = speed_t(0010014)
- B3000000 = speed_t(0010015)
- B3500000 = speed_t(0010016)
- B4000000 = speed_t(0010017)
-)
-
-//note that struct termios and struct __kernel_termios have DIFFERENT size and layout !!!
-const NCCS = 19 //23 on mips, 19 on alpha (also line and cc reversed), 19 on powerpc (also line and cc reversed), 17 on sparc,
-type termios struct {
- c_iflag, c_oflag, c_cflag, c_lflag tcflag_t
- c_line cc_t
- c_cc [NCCS]cc_t
- //~ c_ispeed, c_ospeed speed_t //unused in kernel on x86 apparently
-}
-
-// ioctl constants
-const (
- TCGETS = 0x5401
- TCSETS = 0x5402
-)
-
-func getTermios(ttyfd uintptr, dst *termios) error {
- r1, _, errno := syscall.Syscall (syscall.SYS_IOCTL,
- uintptr (ttyfd), uintptr (TCGETS),
- uintptr (unsafe.Pointer (dst)));
-
- if err := os.NewSyscallError ("SYS_IOCTL", errno); errno!=0 && err != nil {
- return err
- }
-
- if r1 != 0 {
- // return errors.New("Error")
- }
- return nil
-}
-
-func setTermios(ttyfd uintptr, src *termios) error {
- r1, _, errno := syscall.Syscall (syscall.SYS_IOCTL,
- uintptr (ttyfd), uintptr (TCSETS),
- uintptr (unsafe.Pointer (src)));
-
- if err := os.NewSyscallError ("SYS_IOCTL", errno); errno!=0 &&err != nil {
- return err
- }
-
- if r1 != 0 {
- return errors.New ("Error during ioctl tcsets syscall")
- }
- return nil
-}
-
-func SetRawFd(fd uintptr) (error) {
- var orig_termios termios;
- if err := getTermios (fd, &orig_termios); err != nil { return err}
-
- orig_termios.c_iflag &= ^(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
- orig_termios.c_oflag &= ^(OPOST);
- orig_termios.c_lflag &= ^(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
- orig_termios.c_cflag |= (CS8);
-
- orig_termios.c_cc[VMIN] = 1;
- orig_termios.c_cc[VTIME] = 0;
-
- return setTermios(fd, &orig_termios)
-}
-
-func SetRawFile(f *os.File) (error) {
- return SetRawFd(f.Fd())
-}
-
-func SetSpeedFd(fd uintptr, speed speed_t) (err error) {
- var orig_termios termios;
- if err = getTermios (fd, &orig_termios); err != nil { return }
-
- //~ orig_termios.c_ispeed = speed
- //~ orig_termios.c_ospeed = speed
- //input baudrate == output baudrate and we ignore special case B0
- orig_termios.c_cflag &= ^(CBAUD | CBAUDEX)
- orig_termios.c_cflag |= tcflag_t(speed)
- if err = setTermios(fd, &orig_termios); err != nil { return }
- //~ if err = getTermios (fd, &orig_termios); err != nil { return }
- //~ if orig_termios.c_ispeed != speed || orig_termios.c_ospeed != speed {
- //~ err = errors.New("Failed to set speed")
- //~ }
- if err = getTermios (fd, &orig_termios); err != nil { return }
- if orig_termios.c_cflag & (CBAUD | CBAUDEX) != tcflag_t(speed) {
- err = errors.New("Failed to set speed")
- }
- return
-}
-
-func SetSpeedFile(f *os.File, speed speed_t) (error) {
- return SetSpeedFd(f.Fd(), speed)
-}
\ No newline at end of file
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import "os"
-import "log"
-import "log/syslog"
-
-type NullWriter struct {}
-func (n *NullWriter) Write(p []byte) (int, error) {return len(p),nil}
-
-var (
- Syslog_ *log.Logger
- Debug_ *log.Logger
-)
-
-func init() {
- Syslog_ = log.New(&NullWriter{}, "", 0)
- Debug_ = log.New(&NullWriter{}, "", 0)
-}
-
-func LogEnableSyslog() {
- var logerr error
- Syslog_, logerr = syslog.NewLogger(syslog.LOG_INFO | (18<<3), 0)
- if logerr != nil { panic(logerr) }
-}
-
-func LogEnableDebuglog() {
- Syslog_ = log.New(os.Stdout, "", log.LstdFlags)
- Debug_ = log.New(os.Stderr, "DEBUG ", log.LstdFlags)
-}
\ No newline at end of file
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- "flag"
- "time"
-
- zmq "github.com/vaughan0/go-zmq"
-)
-
-// ---------- Main Code -------------
-
-var (
- tty_dev_ string
- pub_addr string
- use_syslog_ bool
- enable_debug_ bool
- serial_speed_ uint
-)
-
-const exponential_backof_activation_threshold int64 = 4
-
-func init() {
- flag.StringVar(&pub_addr, "brokeraddr", "tcp://torwaechter.realraum.at:4243", "zmq address to send stuff to")
- flag.StringVar(&tty_dev_, "ttydev", "/dev/ttyACM0", "path do tty uc device")
- flag.UintVar(&serial_speed_, "serspeed", 0, "tty baudrate (0 to disable setting a baudrate e.g. in case of ttyACM)")
- flag.BoolVar(&use_syslog_, "syslog", false, "log to syslog local1 facility")
- flag.BoolVar(&enable_debug_, "debug", false, "debugging messages on")
- flag.Parse()
-}
-
-func ConnectSerialToZMQ(pub_sock *zmq.Socket, timeout time.Duration) {
- defer func() {
- if x := recover(); x != nil {
- Syslog_.Println(x)
- }
- }()
-
- serial_wr, serial_rd, err := OpenAndHandleSerial(tty_dev_, serial_speed_)
- if err != nil {
- panic(err)
- }
- defer close(serial_wr)
-
- t := time.NewTimer(timeout)
- for {
- select {
- case incoming_ser_line, seropen := <-serial_rd:
- if !seropen {
- return
- }
- t.Reset(timeout)
- Syslog_.Printf("%s", incoming_ser_line)
- if err := pub_sock.Send(incoming_ser_line); err != nil {
- Syslog_.Println(err.Error())
- }
-
- case <-t.C:
- Syslog_.Print("Timeout, no message for 120 seconds")
- }
- }
-}
-
-func main() {
- zmqctx, pub_sock := ZmqsInit(pub_addr)
- if pub_sock == nil {
- panic("zmq socket creation failed")
- }
- defer zmqctx.Close()
- defer pub_sock.Close()
-
- if enable_debug_ {
- LogEnableDebuglog()
- } else if use_syslog_ {
- LogEnableSyslog()
- Syslog_.Print("started")
- }
-
- var backoff_exp uint32 = 0
- for {
- start_time := time.Now().Unix()
- ConnectSerialToZMQ(pub_sock, time.Second*120)
- run_time := time.Now().Unix() - start_time
- if run_time > exponential_backof_activation_threshold {
- backoff_exp = 0
- }
- time.Sleep(150 * (1 << backoff_exp) * time.Millisecond)
- if backoff_exp < 12 {
- backoff_exp++
- }
- }
-}
+++ /dev/null
-#!/bin/zsh
-export GO386=387
-export CGO_ENABLED=1
-go-linux-386 clean
-go-linux-386 build -ldflags "-s" && rsync -v --progress ${PWD:t} gw.realraum.at:/flash/home/realraum/
-#go-linux-386 build -ldflags " --linkmode external -extldflags \"-L . -Bstatic ./libc.so.6 ./libglib-2.0.so.0 ./libstdc++.so.6 ./libm.so.6 ./libpthread.a ./librt.a\" "
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- "bufio"
- "bytes"
- "os"
- "errors"
- "svn.spreadspace.org/realraum/go.svn/termios"
-)
-
-
-// ---------- Serial TTY Code -------------
-
-func openTTY(name string, speed uint) (file *os.File, err error) {
- file, err = os.OpenFile(name,os.O_RDWR, 0600)
- if err != nil { return }
- if err = termios.SetRawFile(file); err != nil { return }
- switch speed {
- case 0: // set no baudrate
- case 1200: err = termios.SetSpeedFile(file, termios.B1200)
- case 2400: err = termios.SetSpeedFile(file, termios.B2400)
- case 4800: err = termios.SetSpeedFile(file, termios.B4800)
- case 9600: err = termios.SetSpeedFile(file, termios.B9600)
- case 19200: err = termios.SetSpeedFile(file, termios.B19200)
- case 38400: err = termios.SetSpeedFile(file, termios.B38400)
- case 57600: err = termios.SetSpeedFile(file, termios.B57600)
- case 115200: err = termios.SetSpeedFile(file, termios.B115200)
- case 230400: err = termios.SetSpeedFile(file, termios.B230400)
- default:
- file.Close()
- err = errors.New("Unsupported Baudrate, use 0 to disable setting a baudrate")
- }
- return
-}
-
-func serialWriter(in <- chan string, serial * os.File) {
- for totty := range(in) {
- serial.WriteString(totty)
- serial.Sync()
- }
- serial.Close()
-}
-
-func serialReader(out chan <- [][]byte, serial * os.File) {
- linescanner := bufio.NewScanner(serial)
- linescanner.Split(bufio.ScanLines)
- for linescanner.Scan() {
- if err := linescanner.Err(); err != nil {
- panic(err.Error())
- }
- text := bytes.Fields([]byte(linescanner.Text()))
- if len(text) == 0 {
- continue
- }
- out <- text
- }
-}
-
-func OpenAndHandleSerial(filename string, serspeed uint) (chan string, chan [][]byte, error) {
- serial, err :=openTTY(filename, serspeed)
- if err != nil {
- return nil, nil, err
- }
- wr := make(chan string, 1)
- rd := make(chan [][]byte, 20)
- go serialWriter(wr, serial)
- go serialReader(rd, serial)
- return wr, rd, nil
-}
+++ /dev/null
-// (c) Bernhard Tittelbach, 2013
-
-package main
-
-import (
- zmq "github.com/vaughan0/go-zmq"
- )
-
-// ---------- ZeroMQ Code -------------
-
-func ZmqsInit(pub_addr string) (ctx *zmq.Context, pub_sock *zmq.Socket) {
- var err error
- ctx, err = zmq.NewContext()
- if err != nil {
- panic(err)
- }
- //close only on later panic, otherwise leave open:
- defer func(){ if r:= recover(); r != nil { ctx.Close(); panic(r) } }()
-
- if len(pub_addr) > 0 {
- pub_sock, err = ctx.Socket(zmq.Pub)
- if err != nil {
- panic(err)
- }
- defer func() { if r:= recover(); r != nil { pub_sock.Close(); panic(r) } }()
-
- if err = pub_sock.Connect(pub_addr); err != nil {
- panic(err)
- }
- } else {
- pub_sock = nil
- }
-
- return
-}
-
-func zmqsHandleError(chans *zmq.Channels) {
- for error := range(chans.Errors()) {
- chans.Close()
- panic(error)
- }
-}
+++ /dev/null
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import with_statement
-import zmq.utils.jsonapi as json
-import zmq
-import time
-
-######## r3 ZMQ ############
-
-def sendR3Message(socket, structname, datadict):
- socket.send_multipart([structname, json.dumps(datadict)])
-
-#Start zmq connection to publish / forward sensor data
-zmqctx = zmq.Context()
-zmqctx.linger = 0
-zmqpub = zmqctx.socket(zmq.PUB)
-zmqpub.connect("tcp://torwaechter.realraum.at:4243")
-
-time.sleep(5)
-#listen for sensor data and forward them
-sendR3Message(zmqpub,"PresenceUpdate",{"Present":True,"Ts":int(time.time())})
-
-zmqpub.close()
-zmqctx.destroy()
-
-
+++ /dev/null
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-import os
-import os.path
-import sys
-import signal
-import zmq.utils.jsonapi as json
-import zmq
-########################
-
-def decodeR3Message(multipart_msg):
- try:
- return (multipart_msg[0], json.loads(multipart_msg[1]))
- except Exception, e:
- logging.debug("decodeR3Message:"+str(e))
- return ("",{})
-
-def exitHandler(signum, frame):
- try:
- zmqsub.close()
- zmqctx.destroy()
- except:
- pass
- sys.exit(0)
-
-signal.signal(signal.SIGINT, exitHandler)
-signal.signal(signal.SIGQUIT, exitHandler)
-
-while True:
- try:
- #Start zmq connection to publish / forward sensor data
- zmqctx = zmq.Context()
- zmqctx.linger = 0
- zmqsub = zmqctx.socket(zmq.SUB)
- zmqsub.setsockopt(zmq.SUBSCRIBE, "")
- zmqsub.connect("tcp://torwaechter.realraum.at:4244")
-
- while True:
-
- data = zmqsub.recv_multipart()
- (structname, dictdata) = decodeR3Message(data)
- print "Got data: " + structname + ":"+ str(dictdata)
-
- except Exception, ex:
- logging.error("main: "+str(ex))
- traceback.print_exc(file=sys.stdout)
- try:
- zmqsub.close()
- zmqctx.destroy()
- except:
- pass
- time.sleep(5)
+++ /dev/null
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-from __future__ import with_statement
-import os
-import os.path
-import sys
-import logging
-import logging.handlers
-import time
-import threading
-import signal
-import ConfigParser
-import traceback
-import shutil
-import zmq
-import zmq.utils.jsonapi as json
-import zmq.ssh.tunnel
-
-logger = logging.getLogger()
-logger.setLevel(logging.INFO)
-lh_syslog = logging.handlers.SysLogHandler(address="/dev/log",facility=logging.handlers.SysLogHandler.LOG_LOCAL2)
-lh_syslog.setFormatter(logging.Formatter('sensorvalues-to-json-zmq.py: %(levelname)s %(message)s'))
-logger.addHandler(lh_syslog)
-lh_stderr = logging.StreamHandler()
-logger.addHandler(lh_stderr)
-
-######## Config File Data Class ############
-
-class UWSConfig:
- def __init__(self,configfile=None):
- #Synchronisation
- self.lock=threading.Lock()
- self.finished_reading=threading.Condition(self.lock)
- self.finished_writing=threading.Condition(self.lock)
- self.currently_reading=0
- self.currently_writing=False
- #Config Data
- self.configfile=configfile
- self.config_parser=ConfigParser.ConfigParser()
- self.config_parser.add_section('json')
- self.config_parser.set('json','write_path',"/dev/shm/wget/r3sensors.json")
- self.config_parser.set('json','moveto_path',"/dev/shm/www/r3sensors.json")
- self.config_parser.set('json','backup_path',"/home/guests/realraum.wirdorange.org/r3sensors.json.bak")
- self.config_parser.set('json','backup_every',"50")
- self.config_parser.set('json','limit_list_len',"10000")
- self.config_parser.set('json','updateinterval',"30")
- self.config_parser.add_section('zmq')
- self.config_parser.set('zmq','remote_uri',"tcp://torwaechter.realraum.at:4244")
- self.config_parser.set('zmq','sshtunnel',"realraum@torwaechter.realraum.at:22000")
- self.config_parser.set('zmq','sshkeyfile',"/home/guests/realraum.wirdorange.org/id_rsa")
- self.config_parser.set('zmq','subscribe',"TempSensorUpdate IlluminationSensorUpdate DustSensorUpdate RelativeHumiditySensorUpdate MovementSensorUpdate")
- self.config_parser.add_section('debug')
- self.config_parser.set('debug','enabled',"False")
- self.config_mtime=0
- if not self.configfile is None:
- try:
- cf_handle = open(self.configfile,"r")
- cf_handle.close()
- except IOError:
- self.writeConfigFile()
- else:
- self.checkConfigUpdates()
-
- def guardReading(self):
- with self.lock:
- while self.currently_writing:
- self.finished_writing.wait()
- self.currently_reading+=1
-
- def unguardReading(self):
- with self.lock:
- self.currently_reading-=1
- self.finished_reading.notifyAll()
-
- def guardWriting(self):
- with self.lock:
- self.currently_writing=True
- while self.currently_reading > 0:
- self.finished_reading.wait()
-
- def unguardWriting(self):
- with self.lock:
- self.currently_writing=False
- self.finished_writing.notifyAll()
-
- def checkConfigUpdates(self):
- global logger
- if self.configfile is None:
- return
- logging.debug("Checking Configfile mtime: "+self.configfile)
- try:
- mtime = os.path.getmtime(self.configfile)
- except (IOError,OSError):
- return
- if self.config_mtime < mtime:
- logging.debug("Reading Configfile")
- self.guardWriting()
- try:
- self.config_parser.read(self.configfile)
- self.config_mtime=os.path.getmtime(self.configfile)
- except (ConfigParser.ParsingError, IOError), pe_ex:
- logging.error("Error parsing Configfile: "+str(pe_ex))
- self.unguardWriting()
- self.guardReading()
- if self.config_parser.get('debug','enabled') == "True":
- logger.setLevel(logging.DEBUG)
- else:
- logger.setLevel(logging.INFO)
- self.unguardReading()
-
- def writeConfigFile(self):
- if self.configfile is None:
- return
- logging.debug("Writing Configfile "+self.configfile)
- self.guardReading()
- try:
- cf_handle = open(self.configfile,"w")
- self.config_parser.write(cf_handle)
- cf_handle.close()
- self.config_mtime=os.path.getmtime(self.configfile)
- except IOError, io_ex:
- logging.error("Error writing Configfile: "+str(io_ex))
- self.configfile=None
- self.unguardReading()
-
- def __getattr__(self, name):
- underscore_pos=name.find('_')
- if underscore_pos < 0:
- raise AttributeError
- rv=None
- self.guardReading()
- try:
- rv = self.config_parser.get(name[0:underscore_pos], name[underscore_pos+1:])
- except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
- self.unguardReading()
- finally:
- self.unguardReading()
- return rv
-
-
-######## r3 ZMQ ############
-
-def sendR3Message(socket, structname, datadict):
- socket.send_multipart([structname, json.dumps(datadict)])
-
-def decodeR3Message(multipart_msg):
- try:
- return (multipart_msg[0], json.loads(multipart_msg[1]))
- except Exception, e:
- logging.debug("decodeR3Message:"+str(e))
- return ("",{})
-
-######## Main ############
-
-def exitHandler(signum, frame):
- logging.info("stopping")
- try:
- zmqsub.close()
- zmqctx.destroy()
- except:
- pass
- sys.exit(0)
-
-time_column_name_="Time"
-latest_values_ = {}
-sensor_store_ = {}
-sensor_cols_num_ = {} #stores number of columns for a sensor not counting Time (x-axis) column. AKA the number of data-rows. Equals highest SensorIndex +1
-reset_these_structnames_ = {}
-
-def addEventToTempLastValueStore(structname, msgdata):
- global latest_values_
- sensorindex = int(msgdata["Sensorindex"]) if "Sensorindex" in msgdata else 0
- if not structname in latest_values_:
- latest_values_[structname]=[]
- if not structname in sensor_cols_num_ or sensor_cols_num_[structname] < sensorindex +1:
- sensor_cols_num_[structname] = sensorindex +1
- if len(latest_values_[structname]) < sensor_cols_num_[structname]:
- latest_values_[structname] += [0] * (sensor_cols_num_[structname] - len(latest_values_[structname]))
- expandSensorStoreLists(structname, sensor_cols_num_[structname])
- # store Value in temp last value store:
- try:
- del msgdata["Sensorindex"]
- except:
- pass
- try:
- del msgdata["Ts"]
- except:
- pass
- if len(msgdata) > 0:
- #store first value that is not Sensorindex or Ts into store
- latest_values_[structname][sensorindex] = msgdata.values()[0]
- else:
- #if that value does not exist, (i.e. movementevent), count event occurances
- latest_values_[structname][sensorindex] += 1
- reset_these_structnames_[structname] = True
-
-
-def cleanTempLastValueOfMovementValues():
- global latest_values_
- for k in reset_these_structnames_.keys():
- latest_values_[k] = [0] * sensor_cols_num_[k]
-
-
-def expandSensorStoreLists(structname, newlength):
- global sensor_store_
- if not structname in sensor_store_:
- sensor_store_[structname]=[]
- #remove old headings so we can add them again below
- try:
- if sensor_store_[structname][0][0] == time_column_name_:
- sensor_store_[structname].pop(0)
- except:
- pass
- #expand all previous value lists
- newlength_including_time = newlength +1
- sensor_store_[structname] = map(lambda l: l[:newlength_including_time] + ([0] * (newlength_including_time - len(l))) , sensor_store_[structname])
-
-
-def addEventsToStore():
- global sensor_store_
- ts = int(time.time())
- for structname in latest_values_.keys():
- if not structname in sensor_store_:
- sensor_store_[structname]=[]
-
- #if missing, add Header List [Time, 0, 1, 2]
- if len(sensor_store_[structname]) == 0 or len(sensor_store_[structname][0]) < 2 or sensor_store_[structname][0][0] != time_column_name_:
- sensor_store_[structname].insert(0,[time_column_name_] + list(map(lambda n: "Sensor %d"%n,range(0,sensor_cols_num_[structname]))))
-
- # add values
- try:
- # if latest values are identical, just update timestamp
- if sensor_store_[structname][-1][1:] == latest_values_[structname] and sensor_store_[structname][-1][1:] == sensor_store_[structname][-2][1:]:
- sensor_store_[structname].pop()
- except:
- pass
- sensor_store_[structname].append([ts] + latest_values_[structname])
-
- #cap list lenght
- if uwscfg.json_limit_list_len:
- if len(sensor_store_[structname]) > uwscfg.json_limit_list_len:
- sensor_store_[structname] = sensor_store_[structname][- uwscfg.json_limit_list_len:]
-
-
-if __name__ == "__main__":
- #signal.signal(signal.SIGTERM, exitHandler)
- signal.signal(signal.SIGINT, exitHandler)
- signal.signal(signal.SIGQUIT, exitHandler)
-
- logging.info("%s started" % os.path.basename(sys.argv[0]))
-
- if len(sys.argv) > 1:
- uwscfg = UWSConfig(sys.argv[1])
- else:
- uwscfg = UWSConfig()
-
- try:
- with open(uwscfg.json_moveto_path,"rb") as fh:
- sensor_store_ = json.loads(fh.read())
- except Exception, e:
- logging.debug(e)
- try:
- with open(uwscfg.json_backup_path,"rb") as fh:
- sensor_store_ = json.loads(fh.read())
- except Exception, e:
- logging.debug(e)
-
-
- for k in set(sensor_store_.keys()).difference(set(uwscfg.zmq_subscribe.split(" "))):
- del sensor_store_[k] # del old sensordata of sensor we do not subscribe to
-
- for k in sensor_store_.keys():
- try:
- if len(sensor_store_[k][0]) > 1:
- sensor_cols_num_[k] = len(sensor_store_[k][0]) -1
- except:
- pass
-
- while True:
- try:
- #Start zmq connection to publish / forward sensor data
- zmqctx = zmq.Context()
- zmqctx.linger = 0
- zmqsub = zmqctx.socket(zmq.SUB)
- for topic in uwscfg.zmq_subscribe.split(" "):
- zmqsub.setsockopt(zmq.SUBSCRIBE, topic)
- if uwscfg.zmq_sshtunnel:
- zmq.ssh.tunnel.tunnel_connection(zmqsub, uwscfg.zmq_remote_uri, uwscfg.zmq_sshtunnel, keyfile=uwscfg.zmq_sshkeyfile)
- else:
- zmqsub.connect(uwscfg.zmq_remote_uri)
- backup_counter = 0
- last_update = int(time.time())
-
- while True:
- #receive sensor updates
- data = zmqsub.recv_multipart()
- (structname, dictdata) = decodeR3Message(data)
- logging.debug("Got data: " + structname + ":"+ str(dictdata))
-
- uwscfg.checkConfigUpdates()
-
- addEventToTempLastValueStore(structname, dictdata)
-
- logging.debug("lastdata:"+str(latest_values_))
- if int(time.time()) - last_update < int(uwscfg.json_updateinterval):
- continue
-
- logging.debug("update interval elapsed")
- last_update = int(time.time())
-
- addEventsToStore()
- cleanTempLastValueOfMovementValues()
- logging.debug("post-cleanMovement lastdata:"+str(latest_values_))
-
- backup_counter += 1
- # save sensor_store_ to json for apache
- with open(uwscfg.json_write_path,"wb") as fh:
- fh.truncate()
- fh.write(json.dumps(sensor_store_))
- if backup_counter > uwscfg.json_backup_every:
- backup_counter = 0
- shutil.copy(uwscfg.json_write_path, uwscfg.json_backup_path)
- shutil.move(uwscfg.json_write_path, uwscfg.json_moveto_path)
-
- except Exception, ex:
- logging.error("main: "+str(ex))
- traceback.print_exc(file=sys.stdout)
- try:
- zmqsub.close()
- zmqctx.destroy()
- except:
- pass
- time.sleep(5)
-
-
+++ /dev/null
-# common defaults for tuer_core and tuer_status
-
-DIR_RUN=/var/run/tuer
-DOOR_USR=tuer
-DOOR_GRP=nogroup
-
-DOOR_SOCKET=${DIR_RUN}/door_cmd.socket
+++ /dev/null
-#!/bin/sh
-# Start/stop the tuer status updater.
-#
-### BEGIN INIT INFO
-# Provides: tuer_actions
-# Required-Start: $remote_fs $syslog $time tuer_core tuer_presence
-# Required-Stop: $remote_fs $syslog $time tuer_core tuer_presence
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-### END INIT INFO
-
-EXE_SWITCH=/flash/tuer/switch-power.py
-EXE_SOUND=/flash/tuer/play-sound-status.py
-
-CFG_SWITCH=/flash/tuer/switch-power.cfg
-CFG_SOUND=/flash/tuer/play-sound-status.cfg
-
-. /etc/default/tuer
-
-PIDFILE_SWITCH=${DIR_RUN}/switch-power.pid
-PIDFILE_SOUND=${DIR_RUN}/play-sound-status.pid
-
-test -f $EXE_SWITCH || exit 1
-test -f $EXE_SOUND || exit 1
-if [ ! -d $DIR_RUN ]; then
- mkdir -p $DIR_RUN || exit 2
- chown -R $DOOR_USR:$DOOR_GRP $DIR_RUN
-fi
-
-. /lib/lsb/init-functions
-
-# Read the system's locale and set cron's locale. This locale
-# will be inherited by cron (used to set charset of emails)
-# and tasks running under it.
-
-case "$1" in
-start)
- log_daemon_msg "Starting door daemon" "switch-power"
- start-stop-daemon --start --quiet --pidfile $PIDFILE_SWITCH -b -m -c $DOOR_USR --startas $EXE_SWITCH -- $CFG_SWITCH
- log_end_msg $?
- log_daemon_msg "Starting door daemon" "play-sound"
- start-stop-daemon --start --quiet --pidfile $PIDFILE_SOUND -b -m -c $DOOR_USR --startas $EXE_SOUND -- $CFG_SOUND
- log_end_msg $?
- ;;
-stop)
- log_daemon_msg "Stopping door daemon" "switch-power"
- start-stop-daemon --stop --quiet --pidfile $PIDFILE_SWITCH -m --retry TERM/1/TERM/1/KILL
- log_end_msg $?
- sleep 1
- log_daemon_msg "Stopping door daemon" "play-sound"
- start-stop-daemon --stop --quiet --pidfile $PIDFILE_SOUND -m --retry TERM/1/TERM/1/KILL
- log_end_msg $?
- ;;
-restart)
- $0 stop
- $0 start
- ;;
-*) log_action_msg "Usage: $0 {start|stop|restart|reload|force-reload}"
- exit 2
- ;;
-esac
-exit 0
+++ /dev/null
-#!/bin/sh
-# Start/stop the tuer daemon core.
-#
-### BEGIN INIT INFO
-# Provides: tuer_cardidlookup
-# Required-Start: $remote_fs $syslog $time
-# Required-Stop: $remote_fs $syslog $time
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-### END INIT INFO
-
-EXE_KEYLOOKUP=/flash/tuer/door_nick_lookup_zmq
-DOOR_DEV=/dev/door
-
-. /etc/default/tuer
-
-PIDFILE_KEYLOOKUP=${DIR_RUN}/door_nick_lookup_server.pid
-
-test -e $EXE_KEYLOOKUP || exit 1
-if [ ! -d $DIR_RUN ]; then
- mkdir -p $DIR_RUN || exit 2
- chown -R $DOOR_USR:$DOOR_GRP $DIR_RUN
-fi
-chown $DOOR_USR:$DOOR_GRP $DOOR_DEV
-
-. /lib/lsb/init-functions
-
-# Read the system's locale and set cron's locale. This locale
-# will be inherited by cron (used to set charset of emails)
-# and tasks running under it.
-
-case "$1" in
-start)
- log_daemon_msg "Starting CardID Lookup Server" "door_nick_lookup_zmq"
- start-stop-daemon --start --quiet --pidfile $PIDFILE_KEYLOOKUP -c $DOOR_USR -m -g $DOOR_GRP -b --name door_nick_lookup_zmq --startas $EXE_KEYLOOKUP -- --server
- log_end_msg $?
- ;;
-stop)
- log_daemon_msg "Stopping CardID Lookup Server" "door_nick_lookup_zmq"
- start-stop-daemon --stop --quiet --pidfile $PIDFILE_KEYLOOKUP -m --name door_nick_lookup_zmq
- log_end_msg $?
- ;;
-restart)
- $0 stop
- $0 start
- ;;
-*)
- log_action_msg "Usage: $0 {start|stop|restart|reload|force-reload}"
- exit 2
- ;;
-esac
-exit 0
+++ /dev/null
-#!/bin/sh
-# Start/stop the tuer daemon core.
-#
-### BEGIN INIT INFO
-# Provides: tuer_core
-# Required-Start: $remote_fs $syslog $time
-# Required-Stop: $remote_fs $syslog $time
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-### END INIT INFO
-
-EXE_DOOR=/flash/tuer/door_daemon_zmq
-DOOR_DEV=/dev/door
-
-. /etc/default/tuer
-
-PIDFILE_DOOR=${DIR_RUN}/door_daemon.pid
-
-test -e $EXE_DOOR || exit 1
-if [ ! -d $DIR_RUN ]; then
- mkdir -p $DIR_RUN || exit 2
- chown -R $DOOR_USR:$DOOR_GRP $DIR_RUN
-fi
-chown $DOOR_USR:$DOOR_GRP $DOOR_DEV
-
-. /lib/lsb/init-functions
-
-# Read the system's locale and set cron's locale. This locale
-# will be inherited by cron (used to set charset of emails)
-# and tasks running under it.
-
-case "$1" in
-start)
- log_daemon_msg "Starting door daemon" "door_daemon_zmq"
- start-stop-daemon --start --quiet --pidfile $PIDFILE_DOOR -c $DOOR_USR -m -g $DOOR_GRP -b --name door_daemon_zmq --startas $EXE_DOOR -- --device $DOOR_DEV --cmdport "$DOOR_SOCKET" --syslog
- log_end_msg $?
- ;;
-stop)
- log_daemon_msg "Stopping door daemon" "door_daemon_zmq"
- start-stop-daemon --stop --quiet --pidfile $PIDFILE_DOOR -m --name door_daemon_zmq
- log_end_msg $?
- ;;
-restart)
- $0 stop
- $0 start
- ;;
-*) log_action_msg "Usage: $0 {start|stop|restart|reload|force-reload}"
- exit 2
- ;;
-esac
-exit 0
+++ /dev/null
-#!/bin/sh
-# Start/stop the tuer status updater.
-#
-### BEGIN INIT INFO
-# Provides: tuer_presence
-# Required-Start: $remote_fs $syslog $time tuer_core
-# Required-Stop: $remote_fs $syslog $time tuer_core
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-### END INIT INFO
-
-EXE_TRACK=/flash/tuer/r3-eventbroker_zmq
-CFG_TRACK="--syslog"
-
-. /etc/default/tuer
-
-PIDFILE_TRACK=${DIR_RUN}/r3-eventbroker_zmq.pid
-test -f $EXE_TRACK || exit 1
-if [ ! -d $DIR_RUN ]; then
- mkdir -p $DIR_RUN || exit 2
- chown -R $DOOR_USR:$DOOR_GRP $DIR_RUN
-fi
-
-. /lib/lsb/init-functions
-
-# Read the system's locale and set cron's locale. This locale
-# will be inherited by cron (used to set charset of emails)
-# and tasks running under it.
-
-case "$1" in
-start)
- log_daemon_msg "Starting r3 event broker" "r3-eventbroker_zmq"
- start-stop-daemon --start --quiet --pidfile $PIDFILE_TRACK -b -m -c $DOOR_USR -g $DOOR_GRP --startas $EXE_TRACK -- $CFG_TRACK
- log_end_msg $?
- ;;
-stop)
- log_daemon_msg "Stopping r3 event broker" "r3-eventbroker_zmq"
- start-stop-daemon --stop --quiet --pidfile $PIDFILE_TRACK -m --retry TERM/1/TERM/1/KILL
- log_end_msg $?
- ;;
-restart)
- $0 stop
- $0 start
- ;;
-*) log_action_msg "Usage: $0 {start|stop|restart|reload|force-reload}"
- exit 2
- ;;
-esac
-exit 0
+++ /dev/null
-#!/bin/bash
-socat UNIX-CONNECT:/var/run/tuer/door_cmd.socket -
+++ /dev/null
-#!/bin/sh
-# Start/stop the tuer status updater.
-#
-### BEGIN INIT INFO
-# Provides: tuer_status
-# Required-Start: $remote_fs $syslog $time tuer_core tuer_presence
-# Required-Stop: $remote_fs $syslog $time tuer_core tuer_presence
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-### END INIT INFO
-
-EXE_UWEB=/flash/tuer/r3-netstatus
-STATE_DIR=/flash/var/lib/r3netstatus/
-CFG_UWEB="-syslog"
-
-. /etc/default/tuer
-
-[ -n "$XMPPJID" ] && CFG_UWEB="$CFG_UWEB --xjid $XMPPJID"
-[ -n "$XMPPPASS" ] && CFG_UWEB="$CFG_UWEB --xpass $XMPPPASS"
-[ -n "$XMPPBOTAUTH" ] && CFG_UWEB="$CFG_UWEB --xbotauth $XMPPBOTAUTH"
-
-
-PIDFILE_UWEB=${DIR_RUN}/r3-netstatus.pid
-
-test -f $EXE_UWEB || exit 1
-if [ ! -d $DIR_RUN ]; then
- mkdir -p $DIR_RUN || exit 2
- chown -R $DOOR_USR:$DOOR_GRP $DIR_RUN
-fi
-
-if [ ! -d $STATE_DIR ]; then
- mkdir -p $STATE_DIR || exit 2
- chown -R $DOOR_USR:$DOOR_GRP $STATE_DIR
-fi
-
-. /lib/lsb/init-functions
-
-# Read the system's locale and set cron's locale. This locale
-# will be inherited by cron (used to set charset of emails)
-# and tasks running under it.
-
-case "$1" in
-start)
- log_daemon_msg "Starting xmpp and web status daemon" r3-netstatus
- start-stop-daemon --start --quiet --pidfile $PIDFILE_UWEB -b -m -c $DOOR_USR --startas $EXE_UWEB -- $CFG_UWEB
- log_end_msg $?
- ;;
-stop)
- log_daemon_msg "Stopping xmpp and web status daemon" r3-netstatus
- start-stop-daemon --stop --quiet --pidfile $PIDFILE_UWEB -m --retry TERM/1/TERM/1/KILL
- log_end_msg $?
- ;;
-restart)
- $0 stop
- $0 start
- ;;
-*) log_action_msg "Usage: $0 {start|stop|restart|reload|force-reload}"
- exit 2
- ;;
-esac
-exit 0
+++ /dev/null
-#!/bin/zsh
-#
-# make this the default shell for user tuerctl and add
-# the following line to sudoers file:
-#
-# tuerctl ALL=(tuer) NOPASSWD: /flash/tuer/tuer_socat.sh
-
-setopt histsubstpattern
-#local TUERCHAN="sudo -u tuer /flash/tuer/tuer_socat.sh"
-local TUERCHAN="sudo -u tuer /flash/tuer/door_client_zmq"
-
-[[ $1 == "-c" ]] && shift
-if [[ -z $1 ]]; then
- ${(z)TUERCHAN}
-else
- if [[ -z $SSH_ORIGINAL_COMMAND ]]; then
- echo "Usable commands are: open, close, toggle status"
- read -A CMD
- else
- CMD=("${=SSH_ORIGINAL_COMMAND}")
- fi
- if [[ $CMD == "status" ]]; then
- local EXT=""
- else
- local EXT=" ssh $1"
- fi
-
- ${(z)TUERCHAN} <<< "${${CMD[1]}:gs/[^a-zA-Z]//}${EXT}"
- [[ $CMD == status ]] && sleep 1
-fi
-
+++ /dev/null
-#!/bin/sh
-# Start/stop the tuer status updater.
-#
-### BEGIN INIT INFO
-# Provides: uc_sensor_node_zmq
-# Required-Start: $remote_fs $syslog $time
-# Required-Stop: $remote_fs $syslog $time
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-### END INIT INFO
-
-EXE_NODE=/home/realraum/uc_sensor_node_zmq
-CFG_NODE=""
-DIR_RUN=/var/run
-DOOR_USR=realraum
-DOOR_GRP=nogroup
-
-#. /etc/default/tuer
-
-PIDFILE_NODE=/var/run/uc_sensor_node_zmq.pid
-
-test -f $EXE_NODE || exit 1
-if [ ! -d $DIR_RUN ]; then
- mkdir -p $DIR_RUN || exit 2
- chown -R $DOOR_USR:$DOOR_GRP $DIR_RUN
-fi
-
-. /lib/lsb/init-functions
-
-# Read the system's locale and set cron's locale. This locale
-# will be inherited by cron (used to set charset of emails)
-# and tasks running under it.
-
-case "$1" in
-start)
- log_daemon_msg "Starting daemon" uc_sensor_node_zmq
- start-stop-daemon --start --quiet --pidfile $PIDFILE_NODE -b -m -c $DOOR_USR --startas $EXE_NODE -- $CFG_NODE
- log_end_msg $?
- ;;
-stop)
- log_daemon_msg "Stopping daemon" uc_sensor_node_zmq
- start-stop-daemon --stop --quiet --pidfile $PIDFILE_NODE -m --retry TERM/1/TERM/1/KILL
- log_end_msg $?
- ;;
-restart)
- $0 stop
- $0 start
- ;;
-*) log_action_msg "Usage: $0 {start|stop|restart|reload|force-reload}"
- exit 2
- ;;
-esac
-exit 0
+++ /dev/null
-# ardiuno tuer rules
-#
-# copy this to /etc/udev/rules.d/ and change serial number to your needs
-
-SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ATTRS{serial}=="A6008ifG", SYMLINK+="door", OWNER="tuer", GROUP="nogroup"
-
-# disable autosuspend for OpenPCD
-ACTION=="add", ATTR{idVendor}=="16c0", ATTR{idProduct}=="076b", MODE="664", OWNER="tuer", ATTR{power/autosuspend}="0"