firmware/user workaround: send open if user opens door after timeout_after_open
[svn42.git] / go / door_daemon_zmq / main.go
1 // (c) Bernhard Tittelbach, 2013
2
3 package main
4
5 import (
6         "flag"
7         "os"
8         "time"
9 )
10
11 //~ func StringArrayToByteArray(ss []string) [][]byte {
12 //~ bb := make([][]byte, len(ss))
13 //~ for index, s := range(ss) {
14 //~ bb[index] = []byte(s)
15 //~ }
16 //~ return bb
17 //~ }
18
19 // ---------- Main Code -------------
20
21 var (
22         cmd_port_      string
23         pub_port_      string
24         door_tty_path_ string
25         enable_syslog_ bool
26         enable_debug_  bool
27 )
28
29 func init() {
30         flag.StringVar(&cmd_port_, "cmdport", "ipc:///run/tuer/door_cmd.ipc", "zmq command socket path")
31         flag.StringVar(&pub_port_, "pubport", "tcp://*:4242", "zmq public/listen socket path")
32         flag.StringVar(&door_tty_path_, "device", "/dev/door", "door tty device path")
33         flag.BoolVar(&enable_syslog_, "syslog", false, "enable logging to syslog")
34         flag.BoolVar(&enable_debug_, "debug", false, "enable debug output")
35         flag.Parse()
36 }
37
38 func main() {
39         if enable_syslog_ {
40                 LogEnableSyslog()
41         }
42         if enable_debug_ {
43                 LogEnableDebuglog()
44         }
45         Syslog_.Print("started")
46         defer Syslog_.Print("exiting")
47
48         zmqctx, cmd_chans, pub_chans := ZmqsInit(cmd_port_, pub_port_)
49         defer cmd_chans.Close()
50         defer pub_chans.Close()
51         defer zmqctx.Close()
52
53         serial_wr, serial_rd, err := OpenAndHandleSerial(door_tty_path_, 0)
54         defer close(serial_wr)
55         if err != nil {
56                 panic(err)
57         }
58
59         workaround_in_chan := WorkaroundFirmware(serial_wr)
60         defer close(workaround_in_chan)
61
62         var next_incoming_serial_is_client_reply bool
63         timeout_chan := make(chan bool)
64         defer close(timeout_chan)
65         for {
66                 select {
67                 case incoming_ser_line, is_notclosed := <-serial_rd:
68                         if is_notclosed {
69                                 //~ if Syslog_ != nil { Syslog_.Print(ByteArrayToString(incoming_ser_line)) }
70                                 if Syslog_ != nil {
71                                         Syslog_.Printf("%s", incoming_ser_line)
72                                 }
73                                 if next_incoming_serial_is_client_reply {
74                                         next_incoming_serial_is_client_reply = false
75                                         cmd_chans.Out() <- incoming_ser_line
76                                 }
77                                 pub_chans.Out() <- incoming_ser_line
78                                 workaround_in_chan <- incoming_ser_line
79                         } else {
80                                 Syslog_.Print("serial device disappeared, exiting")
81                                 os.Exit(1)
82                         }
83                 case tv, timeout_notclosed := <-timeout_chan:
84                         if timeout_notclosed && tv && next_incoming_serial_is_client_reply {
85                                 next_incoming_serial_is_client_reply = false
86                                 cmd_chans.Out() <- [][]byte{[]byte("ERROR"), []byte("No reply from firmware")}
87                         }
88                 case incoming_request, ic_notclosed := <-cmd_chans.In():
89                         if !ic_notclosed {
90                                 Syslog_.Print("zmq socket died, exiting")
91                                 os.Exit(2)
92                         }
93                         if string(incoming_request[0]) == "log" {
94                                 if len(incoming_request) < 2 {
95                                         cmd_chans.Out() <- [][]byte{[]byte("ERROR"), []byte("argument missing")}
96                                         continue
97                                 }
98                                 Syslog_.Printf("Log: %s", incoming_request[1:])
99                                 cmd_chans.Out() <- [][]byte{[]byte("Ok")}
100                                 continue
101                         }
102                         Syslog_.Printf("%s", incoming_request)
103                         if err := HandleCommand(incoming_request, serial_wr, serial_rd); err != nil {
104                                 out_msg := [][]byte{[]byte("ERROR"), []byte(err.Error())}
105                                 cmd_chans.Out() <- out_msg
106                         } else {
107                                 pub_chans.Out() <- incoming_request
108                                 next_incoming_serial_is_client_reply = true
109                                 go func() { time.Sleep(3 * time.Second); timeout_chan <- true }()
110                         }
111                 }
112         }
113 }