77dd32a1e6b17d3fe1c4626140cc6532f6c4913e
[svn42.git] / r3-webstatus-spaceapi / main.go
1 package main
2
3 import (
4         "./spaceapi"
5     "./r3xmppbot"
6         "bufio"
7         "fmt"
8         "net"
9         "net/http"
10         "net/url"
11         "regexp"
12         "time"
13     "strconv"
14 )
15
16 type SpaceState struct {
17         present           bool
18         buttonpress_until int64
19     door_locked bool
20     door_shut bool
21 }
22
23 var (
24         re_presence_    *regexp.Regexp     = regexp.MustCompile("Presence: (yes|no)(?:, (opened|closed), (.+))?")
25         re_status_      *regexp.Regexp     = regexp.MustCompile("Status: (closed|opened), (opening|waiting|closing|idle), (ajar|shut).*")
26         re_button_      *regexp.Regexp     = regexp.MustCompile("PanicButton|button\\d?")
27         re_temp_        *regexp.Regexp     = regexp.MustCompile("temp0: (\\d+\\.\\d+)")
28         re_photo_       *regexp.Regexp     = regexp.MustCompile("photo0: (\\d+)")
29         re_querystresc_ *regexp.Regexp     = regexp.MustCompile("[^\x30-\x39\x41-\x7E]")
30         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.065779129, 15.442322614).AddSpaceAddress("Jakoministr. 16 ground level left, 8010 Graz, Austria")
31         statusstate     *SpaceState        = new(SpaceState)
32         xmpp_presence_events_chan_     chan interface{}
33 )
34
35 //-------
36
37 func updateStatusString() {
38         var spacestatus string
39         if statusstate.present {
40                 if statusstate.buttonpress_until > time.Now().Unix() {
41                         spacestatus = "Panic! Present&Bored"
42                 } else {
43                         spacestatus = "Leute Anwesend"
44                 }
45         } else {
46                 spacestatus = "Keiner Da"
47         }
48         spaceapidata.SetStatus(statusstate.present, spacestatus)
49 }
50
51 func publishStateToWeb() {
52         updateStatusString()
53         jsondata_b, err := spaceapidata.MakeJSON()
54         if err != nil {
55                 fmt.Println("Error:", err)
56                 return
57         }
58         //jsondata_b := re_querystresc_.ReplaceAllFunc(jsondata_b, func(in []byte) []byte {
59         //      out := make([]byte, 4)
60         //      out[0] = '%'
61         //      copy(out[1:], []byte(strconv.FormatInt(int64(in[0]), 16)))
62         //      return out
63         //})
64         jsondata := url.QueryEscape(string(jsondata_b))
65         resp, err := http.Get("http://www.realraum.at/cgi/status.cgi?pass=jako16&set=" + jsondata)
66         if err != nil {
67                 fmt.Println("Error publishing realraum info", err)
68                 return
69         }
70         defer resp.Body.Close()
71 }
72
73 func parseSocketInputLine(line string) {
74         match_presence := re_presence_.FindStringSubmatch(line)
75         match_status := re_status_.FindStringSubmatch(line)
76         match_button := re_button_.FindStringSubmatch(line)
77         match_temp := re_temp_.FindStringSubmatch(line)
78         match_photo := re_photo_.FindStringSubmatch(line)
79
80         if match_presence != nil {
81                 statusstate.present = (match_presence[1] == "yes")
82         statusstate.door_locked = (match_presence[2] == "closed")
83         //spaceapidata.MergeInSensor(spaceapi.MakeDoorLockSensor("Torwaechter", "Front Door", match_presence[2] == "closed"))
84         spaceapidata.MergeInSensor(spaceapi.MakeDoorLockSensor("TorwaechterLock", "Türschloß", statusstate.door_locked))
85                 publishStateToWeb()
86         xmpp_presence_events_chan_ <- r3xmppbot.PresenceEvent{statusstate.present, statusstate.door_locked, statusstate.door_shut}
87         } else if match_status != nil {
88         statusstate.door_locked = (match_status[1] == "closed")
89         statusstate.door_shut = (match_status[3] == "shut")
90         spaceapidata.MergeInSensor(spaceapi.MakeDoorLockSensor("TorwaechterLock", "Türschloß", statusstate.door_locked))
91         spaceapidata.MergeInSensor(spaceapi.MakeDoorLockSensor("TorwaechterAjarSensor", "Türkontakt", statusstate.door_shut))
92         //spaceapidata.MergeInSensor(spaceapi.MakeDoorAjarSensor("Torwaechter", "Front Door", match_presence[3] == "shut"))
93         publishStateToWeb()
94         xmpp_presence_events_chan_ <- r3xmppbot.PresenceEvent{statusstate.present, statusstate.door_locked, statusstate.door_shut}
95         } else if match_button != nil {
96                 statusstate.buttonpress_until = time.Now().Unix() + 3600
97                 spaceapidata.AddSpaceEvent("PanicButton", "check-in", "The button has been pressed")
98                 publishStateToWeb()
99         xmpp_presence_events_chan_ <- "The button has been pressed ! Propably someone is bored and need company ! ;-)"
100         } else if match_temp != nil {
101                 newtemp, err := strconv.ParseFloat((match_temp[1]), 32)
102                 if err == nil {
103             spaceapidata.MergeInSensor(spaceapi.MakeTempCSensor("Temp0","Decke",newtemp))
104                 }
105         } else if match_photo != nil {
106                 newphoto, err := strconv.ParseInt(match_photo[1], 10, 32)
107                 if err == nil {
108                         spaceapidata.MergeInSensor(spaceapi.MakeIlluminationSensor("Photodiode","Decke","1024V/5V",newphoto))
109                 }
110         }
111 }
112
113 func readFromUSocket(path string, c chan string) {
114 ReOpenSocket:
115         for {
116                 presence_socket, err := net.Dial("unix", path)
117                 if err != nil {
118                         //Waiting on Socket
119                         time.Sleep(5 * time.Second)
120                         continue ReOpenSocket
121                 }
122                 presence_reader := bufio.NewReader(presence_socket)
123                 for {
124                         line, err := presence_reader.ReadString('\n')
125                         if err != nil {
126                                 //Socket closed
127                                 presence_socket.Close()
128                                 continue ReOpenSocket
129                         }
130                         c <- line
131                 }
132         }
133 }
134
135 func main() {
136         spaceapidata.AddSpaceFeed("calendar", "http://grical.realraum.at/s/?query=!realraum&view=rss")
137         spaceapidata.AddSpaceFeed("blog", "https://plus.google.com/113737596421797426873")
138         spaceapidata.AddSpaceFeed("wiki", "http://realraum.at/wiki")
139         spaceapidata.AddSpaceContactInfo("+43780700888524", "irc://irc.oftc.net/#realraum", "realraum@realraum.at", "realraum@realraum.at", "realraum@realraum.at", "vorstand@realraum.at")
140
141     var err error
142     var bot *r3xmppbot.XmppBot
143     bot, xmpp_presence_events_chan_, err = r3xmppbot.NewStartedBot("realrauminfo@realraum.at/Tuer", "d7ynC6Dg", "r3alraumOLGAXMPPInfos", true)
144     if err != nil {
145         fmt.Println(err)
146         return
147     }
148     defer bot.StopBot()
149     
150     //~ presence_events <- PresenceEvent{true, true, true}
151     //~ presence_events <- PresenceEvent{true, true, false}
152     //~ presence_events <- PresenceEvent{true, false, false}    
153     
154
155     eventqueue := make(chan string)
156     defer close(eventqueue)
157     
158         ticker := time.NewTicker(time.Duration(7) * time.Minute)
159         go readFromUSocket("/var/run/tuer/presence.socket", eventqueue)
160         for {
161                 select {
162                 case e := <-eventqueue:
163                         parseSocketInputLine(e)
164                 case <-ticker.C:
165                         publishStateToWeb()
166                 }
167         }
168 }
169
170 /* TODO:
171 * Read config from an .ini file
172  */