type export advancement
[svn42.git] / go / r3-eventbroker_zmq / sockettoevent.go
1 // (c) Bernhard Tittelbach, 2013
2
3 package main
4
5 import (
6     "regexp"
7     "strconv"
8     "time"
9     //~ "./brain"
10     "encoding/json"
11     pubsub "github.com/tuxychandru/pubsub"
12     zmq "github.com/vaughan0/go-zmq"
13     "log"
14     "fmt"
15     )
16
17 var (
18         re_presence_    *regexp.Regexp     = regexp.MustCompile("Presence: (yes|no)(?:, (opened|closed), (.+))?")
19         re_state_      *regexp.Regexp     = regexp.MustCompile("State: (closed|opened|manual movement|error|reset|timeout after open|timeout after close|opening|closing).*")
20         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).*")
21         re_infocard_      *regexp.Regexp     = regexp.MustCompile("Info\\(card\\): card\\(([a-fA-F0-9]+)\\) (found|not found).*")
22         re_cardid_      *regexp.Regexp     = regexp.MustCompile("card\\(([a-fA-F0-9]+)\\)")
23         re_infoajar_      *regexp.Regexp     = regexp.MustCompile("Info\\(ajar\\): door is now (ajar|shut)")
24         re_command_     *regexp.Regexp     = regexp.MustCompile("(open|close|toggle|reset)(?: +(Card|Phone|SSH|ssh))?(?: +(.+))?")
25         re_button_      *regexp.Regexp     = regexp.MustCompile("PanicButton|button\\d?")
26         re_temp_        *regexp.Regexp     = regexp.MustCompile("temp0: (\\d+\\.\\d+)")
27         re_photo_       *regexp.Regexp     = regexp.MustCompile("photo0: (\\d+)")
28 )
29
30
31 type DoorLockUpdate struct {
32     DoorID int
33     Locked bool
34     Ts int64
35 }
36
37 type DoorAjarUpdate struct {
38     DoorID int
39     Shut bool
40     Ts int64
41 }
42
43 type DoorCommandEvent struct {
44     Command string
45     Using string
46     Who string
47     Ts int64
48 }
49
50 type ButtonPressUpdate struct {
51     Buttonindex int
52     Ts int64
53 }
54
55 type TempSensorUpdate struct {
56     Sensorindex int
57     Value float64
58     Ts int64
59 }
60
61 type IlluminationSensorUpdate struct {
62     Sensorindex int
63     Value int64
64     Ts int64
65 }
66
67 type TimeTick struct {
68     Ts int64
69 }
70
71 type MovementSensorUpdate struct {
72     Sensorindex int
73     Ts int64
74 }
75
76 func parseSocketInputLine_State(lines [][]byte, ps *pubsub.PubSub, ts int64) {
77     switch string(lines[0]) {
78         case "closed":
79             ps.Pub(DoorLockUpdate{0, true, ts}, "door")
80         case "opened":
81             ps.Pub(DoorLockUpdate{0, false, ts}, "door")
82         case "manual":   //movement
83         case "error":
84         case "reset":
85             ps.Pub(DoorLockUpdate{0, true, ts}, "door")
86         case "timeout":   //after open | after close
87         case "opening":
88         case "closing":
89         default:
90     }
91 }
92
93
94 func ParseSocketInputLine(lines [][]byte, ps *pubsub.PubSub, keylookup_socket *zmq.Socket) { //, brn *brain.Brain) {
95     var tidbit interface{}
96     ts := time.Now().Unix()
97     if len(lines) < 1 { return }
98     log.Printf("ParseSocketInputLine: %s %s",string(lines[0]), lines[1:])
99     switch string(lines[0]) {
100         case "State:":
101             if len(lines) < 2 { return }
102             parseSocketInputLine_State(lines[1:], ps, ts)
103         case "Status:":
104             if len(lines) < 3 { return }
105             tidbit = DoorLockUpdate{0, string(lines[1]) == "closed", ts}
106             //~ brn.Oboite("door", tidbit)
107             ps.Pub(tidbit, "door")
108             tidbit = DoorAjarUpdate{0, string(lines[len(lines)-2]) == "shut", ts}
109             //~ brn.Oboite("door", tidbit)
110             ps.Pub(tidbit, "door")
111         case "Info(card):":
112             if len(lines) < 3 { return }
113             if string(lines[2]) != "found" { return }
114             match_cardid := re_cardid_.FindSubmatch(lines[1])
115             if len(match_cardid) > 1 {
116                 // PreCondition: same thread/goroutinge as created keylookup_socket !!!!
117                 nick, err := LookupCardIdNick(keylookup_socket, match_cardid[1])
118                 if err != nil {
119                     Syslog_.Print("CardID Lookup Error",err)
120                     nick = "Unresolvable KeyID"
121                 }
122                 // new event: toggle by user nick using card
123                 ps.Pub(DoorCommandEvent{"toggle", "Card", nick, ts},"doorcmd")
124             }
125         case "Info(ajar):":
126             if len(lines) < 5 { return }
127             tidbit = DoorAjarUpdate{0, string(lines[4]) == "shut", ts}
128             //~ brn.Oboite("door", tidbit)
129             ps.Pub(tidbit, "door")
130         case "open", "close", "toggle", "reset":
131             ps.Pub(DoorCommandEvent{string(lines[0]), string(lines[1]), string(lines[2]), ts},"doorcmd")
132         case "photo0":
133             newphoto, err := strconv.ParseInt(string(lines[1]), 10, 32)
134             if err == nil {
135                 // brn.Oboite("photo0", newphoto)
136                 ps.Pub(IlluminationSensorUpdate{0, newphoto, ts}, "sensors")
137             }
138     }
139 }
140
141 func MakeTimeTick(ps *pubsub.PubSub) {
142     ps.Pub(TimeTick{time.Now().Unix()},"time")
143 }
144
145 func FormatEventForSocket(event_interface interface{}) (data [][]byte, err error) {
146     var msg []byte
147     fmt.Printf("%T%+v\n", event_interface, event_interface)
148     etype := fmt.Sprintf("%T", event_interface)[5:]
149         msg, err = json.Marshal(map[string]interface{}{etype: event_interface})
150         if err != nil {
151                 return
152         }
153     data = [][]byte{msg}
154     return
155 }
156
157     //~ match_presence := re_presence_.FindStringSubmatch(line)
158     //~ match_status := re_status_.FindStringSubmatch(line)
159     //~ match_command := re_command_.FindStringSubmatch(line)
160     //~ match_button := re_button_.FindStringSubmatch(line)
161     //~ match_temp := re_temp_.FindStringSubmatch(line)
162     //~ match_photo := re_photo_.FindStringSubmatch(line)
163         //~ if match_button != nil {
164         //~ // brn.Oboite("button0", ts)
165         //~ ps.Pub(ButtonPressUpdate{0, ts}, "buttons")
166         //~ } else if match_temp != nil {
167                 //~ newtemp, err := strconv.ParseFloat((match_temp[1]), 32)
168                 //~ if err == nil {
169             //~ // brn.Oboite( "temp0", newtemp)
170             //~ ps.Pub(TempSensorUpdate{0, newtemp, ts}, "sensors")
171                 //~ }
172         //~ } else if match_photo != nil {
173                 //~ newphoto, err := strconv.ParseInt(match_photo[1], 10, 32)
174                 //~ if err == nil {
175             //~ // brn.Oboite("photo0", newphoto)
176             //~ ps.Pub(IlluminationSensorUpdate{0, newphoto, ts}, "sensors")
177                 //~ }
178         //~ } else if line == "movement" {
179         //~ // brn.Oboite("movement", ts)
180         //~ ps.Pub(MovementSensorUpdate{0, ts}, "movements")
181         //~ }