From 7aa8d6094a6e2e98a5e2ee1e9e69a58e42678ad6 Mon Sep 17 00:00:00 2001 From: Bernhard Tittelbach Date: Tue, 29 Jan 2013 13:00:06 +0000 Subject: [PATCH] r3 spaceapi updater daemon written in go --- r3-webstatus-spaceapi/main.go | 137 ++++++++++++++++++++++++++++ r3-webstatus-spaceapi/spaceapi/spaceapi.go | 123 +++++++++++++++++++++++++ 2 files changed, 260 insertions(+) create mode 100644 r3-webstatus-spaceapi/main.go create mode 100644 r3-webstatus-spaceapi/spaceapi/spaceapi.go diff --git a/r3-webstatus-spaceapi/main.go b/r3-webstatus-spaceapi/main.go new file mode 100644 index 0000000..9844717 --- /dev/null +++ b/r3-webstatus-spaceapi/main.go @@ -0,0 +1,137 @@ +package main + +import ( + "./spaceapi" + "bufio" + "fmt" + "net" + "net/http" + "net/url" + "regexp" + "time" +) + +type SpaceState struct { + present bool + buttonpress_until int64 +} + +var ( + re_presence_ *regexp.Regexp = regexp.MustCompile("Presence: (yes|no)(?:, (opened|closed), (.+))?") + 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+)") + re_querystresc_ *regexp.Regexp = regexp.MustCompile("[^\x30-\x39\x41-\x7E]") + 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").AddSpaceAddress("Jakoministr. 16 ground level left, 8010 Graz, Austria").AddSpaceLatLon(47.065779129, 15.442322614) + statusstate *SpaceState = new(SpaceState) +) + +//------- + +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 { + fmt.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 { + fmt.Println("Error publishing realraum info", err) + return + } + defer resp.Body.Close() +} + +func parseSocketInputLine(line string) { + match_presence := re_presence_.FindStringSubmatch(line) + match_button := re_button_.FindStringSubmatch(line) + match_temp := re_temp_.FindStringSubmatch(line) + match_photo := re_photo_.FindStringSubmatch(line) + + if match_presence != nil { + statusstate.present = (match_presence[1] == "yes") + publishStateToWeb() + } else if match_button != nil { + statusstate.buttonpress_until = time.Now().Unix() + 3600 + spaceapidata.AddSpaceEvent("PanicButton", "check-in", "The button has been pressed") + publishStateToWeb() + } else if match_temp != nil { + spaceapidata.UpdateSensorData("temp", "Ceiling", match_temp[1]+"C") + //newtemp, err = strconv.ParseFloat((match_temp[1]), 32) + //if err == nil { + // spaceapidata.UpdateSensorData("temp", "Ceiling", strconv.FormatFloat(newtemp, 'f', 2, 32)+"C") + // spacestate.temperature = newtemp + //} + } else if match_photo != nil { + spaceapidata.UpdateSensorData("light", "Front", match_photo[1]) + //newphoto, err = strconv.ParseInt(match_photo[1], 10, 32) + //if err == nil { + // spacestate.lightlevel = newphoto + //} + } +} + +func readFromUSocket(path string, c chan string) { +ReOpenSocket: + for { + presence_socket, err := net.Dial("unix", path) + if err != nil { + //Waiting on Socket + time.Sleep(5 * time.Second) + continue ReOpenSocket + } + presence_reader := bufio.NewReader(presence_socket) + for { + line, err := presence_reader.ReadString('\n') + if err != nil { + //Socket closed + presence_socket.Close() + continue ReOpenSocket + } + c <- line + } + } +} + +func main() { + spaceapidata.AddSpaceFeed("calendar", "application/rss+xml", "http://grical.realraum.at/s/?query=!realraum&view=rss") + spaceapidata.AddSpaceFeed("google+", "text/html", "https://plus.google.com/113737596421797426873") + spaceapidata.AddSpaceContactInfo("+43780700888524", "irc://irc.oftc.net/#realraum", "realraum@realraum.at", "realraum@realraum.at", "realraum@realraum.at") + eventqueue := make(chan string) + ticker := time.NewTicker(time.Duration(15) * time.Minute) + go readFromUSocket("/var/run/tuer/presence.socket", eventqueue) + for { + select { + case e := <-eventqueue: + parseSocketInputLine(e) + case <-ticker.C: + publishStateToWeb() + } + } +} + +/* TODO: +* Read config from an .ini file + */ diff --git a/r3-webstatus-spaceapi/spaceapi/spaceapi.go b/r3-webstatus-spaceapi/spaceapi/spaceapi.go new file mode 100644 index 0000000..7e08819 --- /dev/null +++ b/r3-webstatus-spaceapi/spaceapi/spaceapi.go @@ -0,0 +1,123 @@ +// spaceapi.go +package spaceapi + +import ( + "encoding/json" + "time" +) + +const max_num_events int = 4 + +type SpaceInfo map[string]interface{} + +func (nsi SpaceInfo) UpdateSensorData(what, where, value string) { + if nsi["sensors"] == nil { + sensorlist := make([]SpaceInfo, 1) + sensorlist[0] = SpaceInfo{what: SpaceInfo{where: value}} + nsi["sensors"] = sensorlist + } else { + sensorlist, ok := nsi["sensors"].([]SpaceInfo) //type assertion (panics if false) + if ok { + for _, sensor := range sensorlist { + if sensor[what] != nil { + sensorinfo, ok2 := sensor[what].(SpaceInfo) + if ok2 { + sensorinfo[where] = value + return + } else { + panic("Wrong Type of sensorinfo: Should never happen") + } + } + } + //else + nsi["sensors"] = append(sensorlist, SpaceInfo{what: SpaceInfo{where: value}}) + } else { + panic("Wrong Type of sensorlist: Should never happen") + } + } +} + +func (nsi SpaceInfo) AddSpaceContactInfo(phone, irc, email, ml, jabber string) SpaceInfo { + nsi["contact"] = SpaceInfo{ + "phone": phone, + "email": email, + "ml": ml, + "jabber": jabber} + return nsi +} + +func (nsi SpaceInfo) AddSpaceFeed(name, mimetype, url string) SpaceInfo { + newfeed := SpaceInfo{"name": name, "type": mimetype, "url": url} + if nsi["feeds"] == nil { + feedlist := make([]SpaceInfo, 1) + feedlist[0] = newfeed + nsi["feeds"] = feedlist + } else { + feedlist, ok := nsi["feeds"].([]SpaceInfo) //type assertion (panics if false) + if ok { + nsi["feeds"] = append(feedlist, newfeed) + } else { + panic("Wrong Type of feedlist: Should never happen") + } + } + return nsi +} + +func (nsi SpaceInfo) AddSpaceEvent(name, eventtype, extra string) SpaceInfo { + newevent := SpaceInfo{"name": name, "type": eventtype, "t": 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 + return nsi +} + +func (nsi SpaceInfo) AddSpaceLatLon(lat float64, lon float64) SpaceInfo { + nsi["lat"] = lat + nsi["lon"] = lon + return nsi +} + +func (nsi SpaceInfo) SetStatus(open bool, status string) { + nsi["status"] = status + nsi["open"] = open + nsi["lastchange"] = time.Now().Unix() +} + +func NewSpaceInfo(space string, url string, logo string, open_icon string, closed_icon string) SpaceInfo { + nsi := map[string]interface{}{ + "api": "0.13", + "space": space, + "url": url, + "logo": logo, + "open": false, + "lastchange": time.Now().Unix(), + "icon": map[string]interface{}{ + "open": open_icon, + "closed": closed_icon}} + return nsi +} + +func (data SpaceInfo) MakeJSON() ([]byte, error) { + msg, err := json.Marshal(data) + if err == nil { + return msg, nil + } + return nil, err +} -- 1.7.10.4