diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64 index 8473f7e..2f3a056 100755 --- a/mattermost/server/bathroom-linux-amd64 +++ b/mattermost/server/bathroom-linux-amd64 Binary files differ diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64 index 8473f7e..2f3a056 100755 --- a/mattermost/server/bathroom-linux-amd64 +++ b/mattermost/server/bathroom-linux-amd64 Binary files differ diff --git a/mattermost/server/bathroom.go b/mattermost/server/bathroom.go index 043d702..87150be 100644 --- a/mattermost/server/bathroom.go +++ b/mattermost/server/bathroom.go @@ -16,6 +16,11 @@ "strings" "regexp" "strconv" + "time" + "github.com/fsnotify/fsnotify" + "io/ioutil" + "html" + "encoding/json" ) var userSplit *regexp.Regexp = regexp.MustCompile(`\s+(^|[^,])|\s*,\s*`) @@ -65,7 +70,23 @@ } func (p *BathroomMonitorPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) { - fmt.Fprint(w, "Hello, world!") + if r.URL.Path == "/status" { + var write map[string]string = make(map[string]string) + for d, s := range p.doors { + val := "open" + if s { + val = "closed" + } + write[fmt.Sprintf("%d", d + 1)] = val + } + if output, err := json.Marshal(write); err == nil { + fmt.Fprint(w, string(output)) + } else { + fmt.Fprint(w, html.EscapeString(err.Error())) + } + return + } + http.NotFound(w, r) } func (p *BathroomMonitorPlugin) confChangedEvent() { @@ -148,7 +169,6 @@ } func (p *BathroomMonitorPlugin) OnConfigurationChange() error { - p.configLock.Lock() defer p.configLock.Unlock() @@ -217,17 +237,80 @@ p.postAdminChannel(configErr.Error()) } + p.confChangedEvent() + return configErr } func watchLoop(p *BathroomMonitorPlugin) { + doorFile, err := regexp.Compile(`(^|/)door(\d+)$`) + if err != nil { + p.API.LogError(errors.Wrap(err, "Couldn't compile regex").Error()) + return + } + for { p.configLock.Lock() + numDoors := p.config.numDoors + watchPath := p.config.WatchPath p.configLock.Unlock() - select { - case <- p.configChanged: - p.API.LogInfo(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates)) + + _ = numDoors + + watcher, err := fsnotify.NewWatcher() + if err != nil { + p.API.LogError(errors.Wrap(err, "Couldn't make watcher").Error()) + time.Sleep(60) + continue } + + err = watcher.Add(watchPath) + + if err != nil { + p.API.LogError(errors.Wrap(err, "Couldn't watch WatchPath").Error()) + } + + run := true + for ;run; { + select { + case event, ok := <- watcher.Events: + if (!ok) { + p.API.LogError(errors.Wrap(err, "Couldn't get fsnotify event").Error()) + time.Sleep(60) + run = false + } else { + match := doorFile.FindStringSubmatch(event.Name) + if match != nil { + id64, err := strconv.ParseUint(match[2], 10, 8) + _ = id64 + if err == nil { + id := uint8(id64) + if id >= 1 && id <= numDoors { + if event.Op & fsnotify.Write == fsnotify.Write || event.Op & fsnotify.Create == fsnotify.Create { + if statusBytes, err := ioutil.ReadFile(event.Name); err == nil { + status := string(statusBytes) + if len(status) > 0 { + p.postAdminChannel("STATUS: " + event.Name + " = " + status) + doorSensor := strings.Trim(status, " \t\n") == "1" + p.doors[id - 1] = doorSensor + } + } else { + p.API.LogError(errors.Wrap(err, "Couldn't read door file").Error()) + } + } + } + } else { + p.API.LogError(errors.Wrap(err, "ParseUint error").Error()) + } + } + } + case <- p.configChanged: + p.API.LogInfo(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates)) + run = false + } + } + + watcher.Close() } } diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64 index 8473f7e..2f3a056 100755 --- a/mattermost/server/bathroom-linux-amd64 +++ b/mattermost/server/bathroom-linux-amd64 Binary files differ diff --git a/mattermost/server/bathroom.go b/mattermost/server/bathroom.go index 043d702..87150be 100644 --- a/mattermost/server/bathroom.go +++ b/mattermost/server/bathroom.go @@ -16,6 +16,11 @@ "strings" "regexp" "strconv" + "time" + "github.com/fsnotify/fsnotify" + "io/ioutil" + "html" + "encoding/json" ) var userSplit *regexp.Regexp = regexp.MustCompile(`\s+(^|[^,])|\s*,\s*`) @@ -65,7 +70,23 @@ } func (p *BathroomMonitorPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) { - fmt.Fprint(w, "Hello, world!") + if r.URL.Path == "/status" { + var write map[string]string = make(map[string]string) + for d, s := range p.doors { + val := "open" + if s { + val = "closed" + } + write[fmt.Sprintf("%d", d + 1)] = val + } + if output, err := json.Marshal(write); err == nil { + fmt.Fprint(w, string(output)) + } else { + fmt.Fprint(w, html.EscapeString(err.Error())) + } + return + } + http.NotFound(w, r) } func (p *BathroomMonitorPlugin) confChangedEvent() { @@ -148,7 +169,6 @@ } func (p *BathroomMonitorPlugin) OnConfigurationChange() error { - p.configLock.Lock() defer p.configLock.Unlock() @@ -217,17 +237,80 @@ p.postAdminChannel(configErr.Error()) } + p.confChangedEvent() + return configErr } func watchLoop(p *BathroomMonitorPlugin) { + doorFile, err := regexp.Compile(`(^|/)door(\d+)$`) + if err != nil { + p.API.LogError(errors.Wrap(err, "Couldn't compile regex").Error()) + return + } + for { p.configLock.Lock() + numDoors := p.config.numDoors + watchPath := p.config.WatchPath p.configLock.Unlock() - select { - case <- p.configChanged: - p.API.LogInfo(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates)) + + _ = numDoors + + watcher, err := fsnotify.NewWatcher() + if err != nil { + p.API.LogError(errors.Wrap(err, "Couldn't make watcher").Error()) + time.Sleep(60) + continue } + + err = watcher.Add(watchPath) + + if err != nil { + p.API.LogError(errors.Wrap(err, "Couldn't watch WatchPath").Error()) + } + + run := true + for ;run; { + select { + case event, ok := <- watcher.Events: + if (!ok) { + p.API.LogError(errors.Wrap(err, "Couldn't get fsnotify event").Error()) + time.Sleep(60) + run = false + } else { + match := doorFile.FindStringSubmatch(event.Name) + if match != nil { + id64, err := strconv.ParseUint(match[2], 10, 8) + _ = id64 + if err == nil { + id := uint8(id64) + if id >= 1 && id <= numDoors { + if event.Op & fsnotify.Write == fsnotify.Write || event.Op & fsnotify.Create == fsnotify.Create { + if statusBytes, err := ioutil.ReadFile(event.Name); err == nil { + status := string(statusBytes) + if len(status) > 0 { + p.postAdminChannel("STATUS: " + event.Name + " = " + status) + doorSensor := strings.Trim(status, " \t\n") == "1" + p.doors[id - 1] = doorSensor + } + } else { + p.API.LogError(errors.Wrap(err, "Couldn't read door file").Error()) + } + } + } + } else { + p.API.LogError(errors.Wrap(err, "ParseUint error").Error()) + } + } + } + case <- p.configChanged: + p.API.LogInfo(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates)) + run = false + } + } + + watcher.Close() } } diff --git a/mattermost/server/bathroom.tar.gz b/mattermost/server/bathroom.tar.gz index d11c006..407d374 100644 --- a/mattermost/server/bathroom.tar.gz +++ b/mattermost/server/bathroom.tar.gz Binary files differ