diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/install_deps.sh b/mattermost/install_deps.sh
new file mode 100644
index 0000000..6a3cec5
--- /dev/null
+++ b/mattermost/install_deps.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+
+sudo apt-get install filepp
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/install_deps.sh b/mattermost/install_deps.sh
new file mode 100644
index 0000000..6a3cec5
--- /dev/null
+++ b/mattermost/install_deps.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+
+sudo apt-get install filepp
diff --git a/mattermost/package.sh b/mattermost/package.sh
new file mode 100644
index 0000000..7253322
--- /dev/null
+++ b/mattermost/package.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+cd "$( dirname "${BASH_SOURCE[0]}" )"
+tar -czvf bathroom.tar.gz plugin.json -C server bathroom-linux-amd64 -C ../webapp/dist main.js
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/install_deps.sh b/mattermost/install_deps.sh
new file mode 100644
index 0000000..6a3cec5
--- /dev/null
+++ b/mattermost/install_deps.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+
+sudo apt-get install filepp
diff --git a/mattermost/package.sh b/mattermost/package.sh
new file mode 100644
index 0000000..7253322
--- /dev/null
+++ b/mattermost/package.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+cd "$( dirname "${BASH_SOURCE[0]}" )"
+tar -czvf bathroom.tar.gz plugin.json -C server bathroom-linux-amd64 -C ../webapp/dist main.js
diff --git a/mattermost/plugin.json b/mattermost/plugin.json
new file mode 100644
index 0000000..ba3a186
--- /dev/null
+++ b/mattermost/plugin.json
@@ -0,0 +1,17 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/install_deps.sh b/mattermost/install_deps.sh
new file mode 100644
index 0000000..6a3cec5
--- /dev/null
+++ b/mattermost/install_deps.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+
+sudo apt-get install filepp
diff --git a/mattermost/package.sh b/mattermost/package.sh
new file mode 100644
index 0000000..7253322
--- /dev/null
+++ b/mattermost/package.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+cd "$( dirname "${BASH_SOURCE[0]}" )"
+tar -czvf bathroom.tar.gz plugin.json -C server bathroom-linux-amd64 -C ../webapp/dist main.js
diff --git a/mattermost/plugin.json b/mattermost/plugin.json
new file mode 100644
index 0000000..ba3a186
--- /dev/null
+++ b/mattermost/plugin.json
@@ -0,0 +1,17 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/plugin_templ.json b/mattermost/plugin_templ.json
new file mode 100644
index 0000000..634b204
--- /dev/null
+++ b/mattermost/plugin_templ.json
@@ -0,0 +1,21 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+#ifdef fsnotify
+ {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#else
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#endif
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/install_deps.sh b/mattermost/install_deps.sh
new file mode 100644
index 0000000..6a3cec5
--- /dev/null
+++ b/mattermost/install_deps.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+
+sudo apt-get install filepp
diff --git a/mattermost/package.sh b/mattermost/package.sh
new file mode 100644
index 0000000..7253322
--- /dev/null
+++ b/mattermost/package.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+cd "$( dirname "${BASH_SOURCE[0]}" )"
+tar -czvf bathroom.tar.gz plugin.json -C server bathroom-linux-amd64 -C ../webapp/dist main.js
diff --git a/mattermost/plugin.json b/mattermost/plugin.json
new file mode 100644
index 0000000..ba3a186
--- /dev/null
+++ b/mattermost/plugin.json
@@ -0,0 +1,17 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/plugin_templ.json b/mattermost/plugin_templ.json
new file mode 100644
index 0000000..634b204
--- /dev/null
+++ b/mattermost/plugin_templ.json
@@ -0,0 +1,21 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+#ifdef fsnotify
+ {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#else
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#endif
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64
index 681e00f..c478ac9 100755
--- a/mattermost/server/bathroom-linux-amd64
+++ b/mattermost/server/bathroom-linux-amd64
Binary files differ
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/install_deps.sh b/mattermost/install_deps.sh
new file mode 100644
index 0000000..6a3cec5
--- /dev/null
+++ b/mattermost/install_deps.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+
+sudo apt-get install filepp
diff --git a/mattermost/package.sh b/mattermost/package.sh
new file mode 100644
index 0000000..7253322
--- /dev/null
+++ b/mattermost/package.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+cd "$( dirname "${BASH_SOURCE[0]}" )"
+tar -czvf bathroom.tar.gz plugin.json -C server bathroom-linux-amd64 -C ../webapp/dist main.js
diff --git a/mattermost/plugin.json b/mattermost/plugin.json
new file mode 100644
index 0000000..ba3a186
--- /dev/null
+++ b/mattermost/plugin.json
@@ -0,0 +1,17 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/plugin_templ.json b/mattermost/plugin_templ.json
new file mode 100644
index 0000000..634b204
--- /dev/null
+++ b/mattermost/plugin_templ.json
@@ -0,0 +1,21 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+#ifdef fsnotify
+ {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#else
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#endif
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64
index 681e00f..c478ac9 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 225a000..b3512ab 100644
--- a/mattermost/server/bathroom.go
+++ b/mattermost/server/bathroom.go
@@ -30,6 +30,8 @@
"encoding/base64"
)
+const DO_LOGGING = false
+
var userSplit *regexp.Regexp = regexp.MustCompile(`\s+(^|[^,])|\s*,\s*`)
const (
@@ -139,6 +141,12 @@
}
}
+func (p *BathroomMonitorPlugin) log(log string) {
+ if DO_LOGGING {
+ p.API.LogInfo(log)
+ }
+}
+
func (p *BathroomMonitorPlugin) setDoorStatus(id uint8, status uint, report bool) error {
if id < 1 || id > p.config.numDoors {
return errors.New(fmt.Sprintf("Invalid door id %d", id))
@@ -156,8 +164,12 @@
p.doors[id - 1].status = status
if report {
statusStr, _ := statusName(status)
- p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ _ = statusStr
+ //p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ p.API.PublishWebSocketEvent("updated", map[string]interface{}{}, &model.WebsocketBroadcast{})
}
+ } else {
+ p.log(fmt.Sprintf("Asked to change status from %d to %d ?", p.doors[id - 1].status, status))
}
return nil
@@ -186,12 +198,12 @@
p.configLock.Unlock()
- doorVal, ok := r.Form["door_id"]
- if !ok || len(doorVal) == 0 {
+ doorStr, ok := r.Form["door_id"]
+ if !ok || len(doorStr) == 0 {
return 0, errors.New("Please send door id")
}
- doorId, err := strconv.ParseUint(doorVal[0], 10, 8)
+ doorId, err := strconv.ParseUint(doorStr[0], 10, 8)
if err != nil {
return 0, errors.New(fmt.Sprintf("Couldn't parse door_id: %s", err.Error()))
}
@@ -205,7 +217,7 @@
}
func (p *BathroomMonitorPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
- p.API.LogInfo(fmt.Sprintf("Requested path: %s", r.URL.Path))
+ p.log(fmt.Sprintf("Requested path: %s %s", r.URL.Path, c.IpAddress))
if r.URL.Path == "/status" {
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -224,7 +236,7 @@
}
if r.URL.Path == "/status-update" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
@@ -232,13 +244,13 @@
return
}
- statusVal, ok := r.Form["status"]
- if !ok || len(statusVal) == 0 {
+ statusStr, ok := r.Form["status"]
+ if !ok || len(statusStr) == 0 {
fmt.Fprint(w, "Please send door status")
return
}
- status, err := strconv.ParseUint(statusVal[0], 10, 8)
+ status, err := strconv.ParseUint(statusStr[0], 10, 8)
if err != nil {
fmt.Fprintf(w, "Couldn't parse status: %s", err.Error())
return
@@ -249,6 +261,11 @@
return
}
+ statusVal := Open
+ if status == 1 {
+ statusVal = Closed
+ }
+
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -257,34 +274,34 @@
return
}
- p.API.LogInfo("Getting random bytes")
+ p.log("Getting random bytes")
var verifyBytes [50]byte
rand.Read(verifyBytes[:])
- p.API.LogInfo("Encoding random bytes")
+ p.log("Encoding random bytes")
verifyB64 := base64.StdEncoding.EncodeToString(verifyBytes[:])
- p.API.LogInfo("Encryping random bytes")
+ p.log("Encryping random bytes")
encrypted, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, p.doors[doorId8 - 1].pubKey, verifyBytes[:], []byte{})
if err != nil {
fmt.Fprintf(w, "Couldn't encrypt verification: %s", err.Error())
return
}
- p.API.LogInfo("Encoding encrypted bytes")
+ p.log("Encoding encrypted bytes")
encryptedB64 := base64.StdEncoding.EncodeToString(encrypted)
req := &DoorRequest {
- ip:r.RemoteAddr,
+ ip:c.IpAddress,
time:time.Now().Unix(),
verify:verifyB64,
- status: uint(status),
+ status: statusVal,
}
p.doors[doorId8 - 1].lastRequest = req
- p.API.LogInfo(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
+ p.log(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
fmt.Fprint(w, encryptedB64)
@@ -293,7 +310,7 @@
}
if r.URL.Path == "/verify-status" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
fmt.Fprint(w, err.Error())
@@ -306,8 +323,10 @@
return
}
+ p.log("Verify locking")
p.doorLock.Lock()
defer p.doorLock.Unlock()
+ p.log("Verify done locking")
if p.doors[doorId8 - 1].lastRequest == nil {
fmt.Fprint(w, "Invalid request")
@@ -315,7 +334,7 @@
}
req := p.doors[doorId8 - 1].lastRequest
- if req.ip != r.RemoteAddr {
+ if req.ip != c.IpAddress {
fmt.Fprintf(w, "Not your request %s %s", req.ip, r.RemoteAddr)
return
}
@@ -328,17 +347,20 @@
if req.verify != verifyB64[0] {
+ p.log(fmt.Sprintf("Failed verification %s %s", req.verify, verifyB64[0]))
fmt.Fprint(w, "Unauthorized request")
return
}
- p.doorLock.Lock()
- defer p.doorLock.Unlock()
-
p.doors[doorId8 - 1].lastRequest = nil
- p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changing")
+ err = p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changed")
+ if err != nil {
+ fmt.Fprintf(w, "Couldn't set status %d %d: %s", doorId8, req.status, err.Error())
+ }
return
@@ -463,7 +485,7 @@
p.initDoors()
- p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
+ p.log(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
if configErr != nil {
p.postAdminChannel(configErr.Error())
@@ -562,7 +584,7 @@
}
}
case <- p.configChanged:
- p.API.LogInfo(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
+ p.log(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
run = false
}
}
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/install_deps.sh b/mattermost/install_deps.sh
new file mode 100644
index 0000000..6a3cec5
--- /dev/null
+++ b/mattermost/install_deps.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+
+sudo apt-get install filepp
diff --git a/mattermost/package.sh b/mattermost/package.sh
new file mode 100644
index 0000000..7253322
--- /dev/null
+++ b/mattermost/package.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+cd "$( dirname "${BASH_SOURCE[0]}" )"
+tar -czvf bathroom.tar.gz plugin.json -C server bathroom-linux-amd64 -C ../webapp/dist main.js
diff --git a/mattermost/plugin.json b/mattermost/plugin.json
new file mode 100644
index 0000000..ba3a186
--- /dev/null
+++ b/mattermost/plugin.json
@@ -0,0 +1,17 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/plugin_templ.json b/mattermost/plugin_templ.json
new file mode 100644
index 0000000..634b204
--- /dev/null
+++ b/mattermost/plugin_templ.json
@@ -0,0 +1,21 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+#ifdef fsnotify
+ {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#else
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#endif
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64
index 681e00f..c478ac9 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 225a000..b3512ab 100644
--- a/mattermost/server/bathroom.go
+++ b/mattermost/server/bathroom.go
@@ -30,6 +30,8 @@
"encoding/base64"
)
+const DO_LOGGING = false
+
var userSplit *regexp.Regexp = regexp.MustCompile(`\s+(^|[^,])|\s*,\s*`)
const (
@@ -139,6 +141,12 @@
}
}
+func (p *BathroomMonitorPlugin) log(log string) {
+ if DO_LOGGING {
+ p.API.LogInfo(log)
+ }
+}
+
func (p *BathroomMonitorPlugin) setDoorStatus(id uint8, status uint, report bool) error {
if id < 1 || id > p.config.numDoors {
return errors.New(fmt.Sprintf("Invalid door id %d", id))
@@ -156,8 +164,12 @@
p.doors[id - 1].status = status
if report {
statusStr, _ := statusName(status)
- p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ _ = statusStr
+ //p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ p.API.PublishWebSocketEvent("updated", map[string]interface{}{}, &model.WebsocketBroadcast{})
}
+ } else {
+ p.log(fmt.Sprintf("Asked to change status from %d to %d ?", p.doors[id - 1].status, status))
}
return nil
@@ -186,12 +198,12 @@
p.configLock.Unlock()
- doorVal, ok := r.Form["door_id"]
- if !ok || len(doorVal) == 0 {
+ doorStr, ok := r.Form["door_id"]
+ if !ok || len(doorStr) == 0 {
return 0, errors.New("Please send door id")
}
- doorId, err := strconv.ParseUint(doorVal[0], 10, 8)
+ doorId, err := strconv.ParseUint(doorStr[0], 10, 8)
if err != nil {
return 0, errors.New(fmt.Sprintf("Couldn't parse door_id: %s", err.Error()))
}
@@ -205,7 +217,7 @@
}
func (p *BathroomMonitorPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
- p.API.LogInfo(fmt.Sprintf("Requested path: %s", r.URL.Path))
+ p.log(fmt.Sprintf("Requested path: %s %s", r.URL.Path, c.IpAddress))
if r.URL.Path == "/status" {
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -224,7 +236,7 @@
}
if r.URL.Path == "/status-update" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
@@ -232,13 +244,13 @@
return
}
- statusVal, ok := r.Form["status"]
- if !ok || len(statusVal) == 0 {
+ statusStr, ok := r.Form["status"]
+ if !ok || len(statusStr) == 0 {
fmt.Fprint(w, "Please send door status")
return
}
- status, err := strconv.ParseUint(statusVal[0], 10, 8)
+ status, err := strconv.ParseUint(statusStr[0], 10, 8)
if err != nil {
fmt.Fprintf(w, "Couldn't parse status: %s", err.Error())
return
@@ -249,6 +261,11 @@
return
}
+ statusVal := Open
+ if status == 1 {
+ statusVal = Closed
+ }
+
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -257,34 +274,34 @@
return
}
- p.API.LogInfo("Getting random bytes")
+ p.log("Getting random bytes")
var verifyBytes [50]byte
rand.Read(verifyBytes[:])
- p.API.LogInfo("Encoding random bytes")
+ p.log("Encoding random bytes")
verifyB64 := base64.StdEncoding.EncodeToString(verifyBytes[:])
- p.API.LogInfo("Encryping random bytes")
+ p.log("Encryping random bytes")
encrypted, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, p.doors[doorId8 - 1].pubKey, verifyBytes[:], []byte{})
if err != nil {
fmt.Fprintf(w, "Couldn't encrypt verification: %s", err.Error())
return
}
- p.API.LogInfo("Encoding encrypted bytes")
+ p.log("Encoding encrypted bytes")
encryptedB64 := base64.StdEncoding.EncodeToString(encrypted)
req := &DoorRequest {
- ip:r.RemoteAddr,
+ ip:c.IpAddress,
time:time.Now().Unix(),
verify:verifyB64,
- status: uint(status),
+ status: statusVal,
}
p.doors[doorId8 - 1].lastRequest = req
- p.API.LogInfo(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
+ p.log(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
fmt.Fprint(w, encryptedB64)
@@ -293,7 +310,7 @@
}
if r.URL.Path == "/verify-status" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
fmt.Fprint(w, err.Error())
@@ -306,8 +323,10 @@
return
}
+ p.log("Verify locking")
p.doorLock.Lock()
defer p.doorLock.Unlock()
+ p.log("Verify done locking")
if p.doors[doorId8 - 1].lastRequest == nil {
fmt.Fprint(w, "Invalid request")
@@ -315,7 +334,7 @@
}
req := p.doors[doorId8 - 1].lastRequest
- if req.ip != r.RemoteAddr {
+ if req.ip != c.IpAddress {
fmt.Fprintf(w, "Not your request %s %s", req.ip, r.RemoteAddr)
return
}
@@ -328,17 +347,20 @@
if req.verify != verifyB64[0] {
+ p.log(fmt.Sprintf("Failed verification %s %s", req.verify, verifyB64[0]))
fmt.Fprint(w, "Unauthorized request")
return
}
- p.doorLock.Lock()
- defer p.doorLock.Unlock()
-
p.doors[doorId8 - 1].lastRequest = nil
- p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changing")
+ err = p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changed")
+ if err != nil {
+ fmt.Fprintf(w, "Couldn't set status %d %d: %s", doorId8, req.status, err.Error())
+ }
return
@@ -463,7 +485,7 @@
p.initDoors()
- p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
+ p.log(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
if configErr != nil {
p.postAdminChannel(configErr.Error())
@@ -562,7 +584,7 @@
}
}
case <- p.configChanged:
- p.API.LogInfo(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
+ p.log(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
run = false
}
}
diff --git a/mattermost/server/bathroom.tar.gz b/mattermost/server/bathroom.tar.gz
deleted file mode 100644
index f2298e9..0000000
--- a/mattermost/server/bathroom.tar.gz
+++ /dev/null
Binary files differ
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/install_deps.sh b/mattermost/install_deps.sh
new file mode 100644
index 0000000..6a3cec5
--- /dev/null
+++ b/mattermost/install_deps.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+
+sudo apt-get install filepp
diff --git a/mattermost/package.sh b/mattermost/package.sh
new file mode 100644
index 0000000..7253322
--- /dev/null
+++ b/mattermost/package.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+cd "$( dirname "${BASH_SOURCE[0]}" )"
+tar -czvf bathroom.tar.gz plugin.json -C server bathroom-linux-amd64 -C ../webapp/dist main.js
diff --git a/mattermost/plugin.json b/mattermost/plugin.json
new file mode 100644
index 0000000..ba3a186
--- /dev/null
+++ b/mattermost/plugin.json
@@ -0,0 +1,17 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/plugin_templ.json b/mattermost/plugin_templ.json
new file mode 100644
index 0000000..634b204
--- /dev/null
+++ b/mattermost/plugin_templ.json
@@ -0,0 +1,21 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+#ifdef fsnotify
+ {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#else
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#endif
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64
index 681e00f..c478ac9 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 225a000..b3512ab 100644
--- a/mattermost/server/bathroom.go
+++ b/mattermost/server/bathroom.go
@@ -30,6 +30,8 @@
"encoding/base64"
)
+const DO_LOGGING = false
+
var userSplit *regexp.Regexp = regexp.MustCompile(`\s+(^|[^,])|\s*,\s*`)
const (
@@ -139,6 +141,12 @@
}
}
+func (p *BathroomMonitorPlugin) log(log string) {
+ if DO_LOGGING {
+ p.API.LogInfo(log)
+ }
+}
+
func (p *BathroomMonitorPlugin) setDoorStatus(id uint8, status uint, report bool) error {
if id < 1 || id > p.config.numDoors {
return errors.New(fmt.Sprintf("Invalid door id %d", id))
@@ -156,8 +164,12 @@
p.doors[id - 1].status = status
if report {
statusStr, _ := statusName(status)
- p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ _ = statusStr
+ //p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ p.API.PublishWebSocketEvent("updated", map[string]interface{}{}, &model.WebsocketBroadcast{})
}
+ } else {
+ p.log(fmt.Sprintf("Asked to change status from %d to %d ?", p.doors[id - 1].status, status))
}
return nil
@@ -186,12 +198,12 @@
p.configLock.Unlock()
- doorVal, ok := r.Form["door_id"]
- if !ok || len(doorVal) == 0 {
+ doorStr, ok := r.Form["door_id"]
+ if !ok || len(doorStr) == 0 {
return 0, errors.New("Please send door id")
}
- doorId, err := strconv.ParseUint(doorVal[0], 10, 8)
+ doorId, err := strconv.ParseUint(doorStr[0], 10, 8)
if err != nil {
return 0, errors.New(fmt.Sprintf("Couldn't parse door_id: %s", err.Error()))
}
@@ -205,7 +217,7 @@
}
func (p *BathroomMonitorPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
- p.API.LogInfo(fmt.Sprintf("Requested path: %s", r.URL.Path))
+ p.log(fmt.Sprintf("Requested path: %s %s", r.URL.Path, c.IpAddress))
if r.URL.Path == "/status" {
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -224,7 +236,7 @@
}
if r.URL.Path == "/status-update" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
@@ -232,13 +244,13 @@
return
}
- statusVal, ok := r.Form["status"]
- if !ok || len(statusVal) == 0 {
+ statusStr, ok := r.Form["status"]
+ if !ok || len(statusStr) == 0 {
fmt.Fprint(w, "Please send door status")
return
}
- status, err := strconv.ParseUint(statusVal[0], 10, 8)
+ status, err := strconv.ParseUint(statusStr[0], 10, 8)
if err != nil {
fmt.Fprintf(w, "Couldn't parse status: %s", err.Error())
return
@@ -249,6 +261,11 @@
return
}
+ statusVal := Open
+ if status == 1 {
+ statusVal = Closed
+ }
+
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -257,34 +274,34 @@
return
}
- p.API.LogInfo("Getting random bytes")
+ p.log("Getting random bytes")
var verifyBytes [50]byte
rand.Read(verifyBytes[:])
- p.API.LogInfo("Encoding random bytes")
+ p.log("Encoding random bytes")
verifyB64 := base64.StdEncoding.EncodeToString(verifyBytes[:])
- p.API.LogInfo("Encryping random bytes")
+ p.log("Encryping random bytes")
encrypted, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, p.doors[doorId8 - 1].pubKey, verifyBytes[:], []byte{})
if err != nil {
fmt.Fprintf(w, "Couldn't encrypt verification: %s", err.Error())
return
}
- p.API.LogInfo("Encoding encrypted bytes")
+ p.log("Encoding encrypted bytes")
encryptedB64 := base64.StdEncoding.EncodeToString(encrypted)
req := &DoorRequest {
- ip:r.RemoteAddr,
+ ip:c.IpAddress,
time:time.Now().Unix(),
verify:verifyB64,
- status: uint(status),
+ status: statusVal,
}
p.doors[doorId8 - 1].lastRequest = req
- p.API.LogInfo(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
+ p.log(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
fmt.Fprint(w, encryptedB64)
@@ -293,7 +310,7 @@
}
if r.URL.Path == "/verify-status" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
fmt.Fprint(w, err.Error())
@@ -306,8 +323,10 @@
return
}
+ p.log("Verify locking")
p.doorLock.Lock()
defer p.doorLock.Unlock()
+ p.log("Verify done locking")
if p.doors[doorId8 - 1].lastRequest == nil {
fmt.Fprint(w, "Invalid request")
@@ -315,7 +334,7 @@
}
req := p.doors[doorId8 - 1].lastRequest
- if req.ip != r.RemoteAddr {
+ if req.ip != c.IpAddress {
fmt.Fprintf(w, "Not your request %s %s", req.ip, r.RemoteAddr)
return
}
@@ -328,17 +347,20 @@
if req.verify != verifyB64[0] {
+ p.log(fmt.Sprintf("Failed verification %s %s", req.verify, verifyB64[0]))
fmt.Fprint(w, "Unauthorized request")
return
}
- p.doorLock.Lock()
- defer p.doorLock.Unlock()
-
p.doors[doorId8 - 1].lastRequest = nil
- p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changing")
+ err = p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changed")
+ if err != nil {
+ fmt.Fprintf(w, "Couldn't set status %d %d: %s", doorId8, req.status, err.Error())
+ }
return
@@ -463,7 +485,7 @@
p.initDoors()
- p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
+ p.log(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
if configErr != nil {
p.postAdminChannel(configErr.Error())
@@ -562,7 +584,7 @@
}
}
case <- p.configChanged:
- p.API.LogInfo(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
+ p.log(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
run = false
}
}
diff --git a/mattermost/server/bathroom.tar.gz b/mattermost/server/bathroom.tar.gz
deleted file mode 100644
index f2298e9..0000000
--- a/mattermost/server/bathroom.tar.gz
+++ /dev/null
Binary files differ
diff --git a/mattermost/server/build.sh b/mattermost/server/build.sh
index 916a360..c2c1a0e 100755
--- a/mattermost/server/build.sh
+++ b/mattermost/server/build.sh
@@ -1,4 +1,4 @@
#! /usr/bin/env bash
-filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) plugin_templ.json > plugin.json
+filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) ../plugin_templ.json > ../plugin.json
GOOS=linux GOARCH=amd64 go build $( [[ ! -z "$DEFS" ]] && echo -tags $DEFS ) -o bathroom-linux-amd64 bathroom.go $FILES
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/install_deps.sh b/mattermost/install_deps.sh
new file mode 100644
index 0000000..6a3cec5
--- /dev/null
+++ b/mattermost/install_deps.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+
+sudo apt-get install filepp
diff --git a/mattermost/package.sh b/mattermost/package.sh
new file mode 100644
index 0000000..7253322
--- /dev/null
+++ b/mattermost/package.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+cd "$( dirname "${BASH_SOURCE[0]}" )"
+tar -czvf bathroom.tar.gz plugin.json -C server bathroom-linux-amd64 -C ../webapp/dist main.js
diff --git a/mattermost/plugin.json b/mattermost/plugin.json
new file mode 100644
index 0000000..ba3a186
--- /dev/null
+++ b/mattermost/plugin.json
@@ -0,0 +1,17 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/plugin_templ.json b/mattermost/plugin_templ.json
new file mode 100644
index 0000000..634b204
--- /dev/null
+++ b/mattermost/plugin_templ.json
@@ -0,0 +1,21 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+#ifdef fsnotify
+ {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#else
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#endif
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64
index 681e00f..c478ac9 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 225a000..b3512ab 100644
--- a/mattermost/server/bathroom.go
+++ b/mattermost/server/bathroom.go
@@ -30,6 +30,8 @@
"encoding/base64"
)
+const DO_LOGGING = false
+
var userSplit *regexp.Regexp = regexp.MustCompile(`\s+(^|[^,])|\s*,\s*`)
const (
@@ -139,6 +141,12 @@
}
}
+func (p *BathroomMonitorPlugin) log(log string) {
+ if DO_LOGGING {
+ p.API.LogInfo(log)
+ }
+}
+
func (p *BathroomMonitorPlugin) setDoorStatus(id uint8, status uint, report bool) error {
if id < 1 || id > p.config.numDoors {
return errors.New(fmt.Sprintf("Invalid door id %d", id))
@@ -156,8 +164,12 @@
p.doors[id - 1].status = status
if report {
statusStr, _ := statusName(status)
- p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ _ = statusStr
+ //p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ p.API.PublishWebSocketEvent("updated", map[string]interface{}{}, &model.WebsocketBroadcast{})
}
+ } else {
+ p.log(fmt.Sprintf("Asked to change status from %d to %d ?", p.doors[id - 1].status, status))
}
return nil
@@ -186,12 +198,12 @@
p.configLock.Unlock()
- doorVal, ok := r.Form["door_id"]
- if !ok || len(doorVal) == 0 {
+ doorStr, ok := r.Form["door_id"]
+ if !ok || len(doorStr) == 0 {
return 0, errors.New("Please send door id")
}
- doorId, err := strconv.ParseUint(doorVal[0], 10, 8)
+ doorId, err := strconv.ParseUint(doorStr[0], 10, 8)
if err != nil {
return 0, errors.New(fmt.Sprintf("Couldn't parse door_id: %s", err.Error()))
}
@@ -205,7 +217,7 @@
}
func (p *BathroomMonitorPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
- p.API.LogInfo(fmt.Sprintf("Requested path: %s", r.URL.Path))
+ p.log(fmt.Sprintf("Requested path: %s %s", r.URL.Path, c.IpAddress))
if r.URL.Path == "/status" {
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -224,7 +236,7 @@
}
if r.URL.Path == "/status-update" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
@@ -232,13 +244,13 @@
return
}
- statusVal, ok := r.Form["status"]
- if !ok || len(statusVal) == 0 {
+ statusStr, ok := r.Form["status"]
+ if !ok || len(statusStr) == 0 {
fmt.Fprint(w, "Please send door status")
return
}
- status, err := strconv.ParseUint(statusVal[0], 10, 8)
+ status, err := strconv.ParseUint(statusStr[0], 10, 8)
if err != nil {
fmt.Fprintf(w, "Couldn't parse status: %s", err.Error())
return
@@ -249,6 +261,11 @@
return
}
+ statusVal := Open
+ if status == 1 {
+ statusVal = Closed
+ }
+
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -257,34 +274,34 @@
return
}
- p.API.LogInfo("Getting random bytes")
+ p.log("Getting random bytes")
var verifyBytes [50]byte
rand.Read(verifyBytes[:])
- p.API.LogInfo("Encoding random bytes")
+ p.log("Encoding random bytes")
verifyB64 := base64.StdEncoding.EncodeToString(verifyBytes[:])
- p.API.LogInfo("Encryping random bytes")
+ p.log("Encryping random bytes")
encrypted, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, p.doors[doorId8 - 1].pubKey, verifyBytes[:], []byte{})
if err != nil {
fmt.Fprintf(w, "Couldn't encrypt verification: %s", err.Error())
return
}
- p.API.LogInfo("Encoding encrypted bytes")
+ p.log("Encoding encrypted bytes")
encryptedB64 := base64.StdEncoding.EncodeToString(encrypted)
req := &DoorRequest {
- ip:r.RemoteAddr,
+ ip:c.IpAddress,
time:time.Now().Unix(),
verify:verifyB64,
- status: uint(status),
+ status: statusVal,
}
p.doors[doorId8 - 1].lastRequest = req
- p.API.LogInfo(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
+ p.log(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
fmt.Fprint(w, encryptedB64)
@@ -293,7 +310,7 @@
}
if r.URL.Path == "/verify-status" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
fmt.Fprint(w, err.Error())
@@ -306,8 +323,10 @@
return
}
+ p.log("Verify locking")
p.doorLock.Lock()
defer p.doorLock.Unlock()
+ p.log("Verify done locking")
if p.doors[doorId8 - 1].lastRequest == nil {
fmt.Fprint(w, "Invalid request")
@@ -315,7 +334,7 @@
}
req := p.doors[doorId8 - 1].lastRequest
- if req.ip != r.RemoteAddr {
+ if req.ip != c.IpAddress {
fmt.Fprintf(w, "Not your request %s %s", req.ip, r.RemoteAddr)
return
}
@@ -328,17 +347,20 @@
if req.verify != verifyB64[0] {
+ p.log(fmt.Sprintf("Failed verification %s %s", req.verify, verifyB64[0]))
fmt.Fprint(w, "Unauthorized request")
return
}
- p.doorLock.Lock()
- defer p.doorLock.Unlock()
-
p.doors[doorId8 - 1].lastRequest = nil
- p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changing")
+ err = p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changed")
+ if err != nil {
+ fmt.Fprintf(w, "Couldn't set status %d %d: %s", doorId8, req.status, err.Error())
+ }
return
@@ -463,7 +485,7 @@
p.initDoors()
- p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
+ p.log(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
if configErr != nil {
p.postAdminChannel(configErr.Error())
@@ -562,7 +584,7 @@
}
}
case <- p.configChanged:
- p.API.LogInfo(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
+ p.log(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
run = false
}
}
diff --git a/mattermost/server/bathroom.tar.gz b/mattermost/server/bathroom.tar.gz
deleted file mode 100644
index f2298e9..0000000
--- a/mattermost/server/bathroom.tar.gz
+++ /dev/null
Binary files differ
diff --git a/mattermost/server/build.sh b/mattermost/server/build.sh
index 916a360..c2c1a0e 100755
--- a/mattermost/server/build.sh
+++ b/mattermost/server/build.sh
@@ -1,4 +1,4 @@
#! /usr/bin/env bash
-filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) plugin_templ.json > plugin.json
+filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) ../plugin_templ.json > ../plugin.json
GOOS=linux GOARCH=amd64 go build $( [[ ! -z "$DEFS" ]] && echo -tags $DEFS ) -o bathroom-linux-amd64 bathroom.go $FILES
diff --git a/mattermost/server/package.sh b/mattermost/server/package.sh
deleted file mode 100755
index c8ce874..0000000
--- a/mattermost/server/package.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#! /usr/bin/env bash
-
-tar -czvf bathroom.tar.gz bathroom-linux-amd64 plugin.json
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/install_deps.sh b/mattermost/install_deps.sh
new file mode 100644
index 0000000..6a3cec5
--- /dev/null
+++ b/mattermost/install_deps.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+
+sudo apt-get install filepp
diff --git a/mattermost/package.sh b/mattermost/package.sh
new file mode 100644
index 0000000..7253322
--- /dev/null
+++ b/mattermost/package.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+cd "$( dirname "${BASH_SOURCE[0]}" )"
+tar -czvf bathroom.tar.gz plugin.json -C server bathroom-linux-amd64 -C ../webapp/dist main.js
diff --git a/mattermost/plugin.json b/mattermost/plugin.json
new file mode 100644
index 0000000..ba3a186
--- /dev/null
+++ b/mattermost/plugin.json
@@ -0,0 +1,17 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/plugin_templ.json b/mattermost/plugin_templ.json
new file mode 100644
index 0000000..634b204
--- /dev/null
+++ b/mattermost/plugin_templ.json
@@ -0,0 +1,21 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+#ifdef fsnotify
+ {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#else
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#endif
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64
index 681e00f..c478ac9 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 225a000..b3512ab 100644
--- a/mattermost/server/bathroom.go
+++ b/mattermost/server/bathroom.go
@@ -30,6 +30,8 @@
"encoding/base64"
)
+const DO_LOGGING = false
+
var userSplit *regexp.Regexp = regexp.MustCompile(`\s+(^|[^,])|\s*,\s*`)
const (
@@ -139,6 +141,12 @@
}
}
+func (p *BathroomMonitorPlugin) log(log string) {
+ if DO_LOGGING {
+ p.API.LogInfo(log)
+ }
+}
+
func (p *BathroomMonitorPlugin) setDoorStatus(id uint8, status uint, report bool) error {
if id < 1 || id > p.config.numDoors {
return errors.New(fmt.Sprintf("Invalid door id %d", id))
@@ -156,8 +164,12 @@
p.doors[id - 1].status = status
if report {
statusStr, _ := statusName(status)
- p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ _ = statusStr
+ //p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ p.API.PublishWebSocketEvent("updated", map[string]interface{}{}, &model.WebsocketBroadcast{})
}
+ } else {
+ p.log(fmt.Sprintf("Asked to change status from %d to %d ?", p.doors[id - 1].status, status))
}
return nil
@@ -186,12 +198,12 @@
p.configLock.Unlock()
- doorVal, ok := r.Form["door_id"]
- if !ok || len(doorVal) == 0 {
+ doorStr, ok := r.Form["door_id"]
+ if !ok || len(doorStr) == 0 {
return 0, errors.New("Please send door id")
}
- doorId, err := strconv.ParseUint(doorVal[0], 10, 8)
+ doorId, err := strconv.ParseUint(doorStr[0], 10, 8)
if err != nil {
return 0, errors.New(fmt.Sprintf("Couldn't parse door_id: %s", err.Error()))
}
@@ -205,7 +217,7 @@
}
func (p *BathroomMonitorPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
- p.API.LogInfo(fmt.Sprintf("Requested path: %s", r.URL.Path))
+ p.log(fmt.Sprintf("Requested path: %s %s", r.URL.Path, c.IpAddress))
if r.URL.Path == "/status" {
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -224,7 +236,7 @@
}
if r.URL.Path == "/status-update" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
@@ -232,13 +244,13 @@
return
}
- statusVal, ok := r.Form["status"]
- if !ok || len(statusVal) == 0 {
+ statusStr, ok := r.Form["status"]
+ if !ok || len(statusStr) == 0 {
fmt.Fprint(w, "Please send door status")
return
}
- status, err := strconv.ParseUint(statusVal[0], 10, 8)
+ status, err := strconv.ParseUint(statusStr[0], 10, 8)
if err != nil {
fmt.Fprintf(w, "Couldn't parse status: %s", err.Error())
return
@@ -249,6 +261,11 @@
return
}
+ statusVal := Open
+ if status == 1 {
+ statusVal = Closed
+ }
+
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -257,34 +274,34 @@
return
}
- p.API.LogInfo("Getting random bytes")
+ p.log("Getting random bytes")
var verifyBytes [50]byte
rand.Read(verifyBytes[:])
- p.API.LogInfo("Encoding random bytes")
+ p.log("Encoding random bytes")
verifyB64 := base64.StdEncoding.EncodeToString(verifyBytes[:])
- p.API.LogInfo("Encryping random bytes")
+ p.log("Encryping random bytes")
encrypted, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, p.doors[doorId8 - 1].pubKey, verifyBytes[:], []byte{})
if err != nil {
fmt.Fprintf(w, "Couldn't encrypt verification: %s", err.Error())
return
}
- p.API.LogInfo("Encoding encrypted bytes")
+ p.log("Encoding encrypted bytes")
encryptedB64 := base64.StdEncoding.EncodeToString(encrypted)
req := &DoorRequest {
- ip:r.RemoteAddr,
+ ip:c.IpAddress,
time:time.Now().Unix(),
verify:verifyB64,
- status: uint(status),
+ status: statusVal,
}
p.doors[doorId8 - 1].lastRequest = req
- p.API.LogInfo(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
+ p.log(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
fmt.Fprint(w, encryptedB64)
@@ -293,7 +310,7 @@
}
if r.URL.Path == "/verify-status" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
fmt.Fprint(w, err.Error())
@@ -306,8 +323,10 @@
return
}
+ p.log("Verify locking")
p.doorLock.Lock()
defer p.doorLock.Unlock()
+ p.log("Verify done locking")
if p.doors[doorId8 - 1].lastRequest == nil {
fmt.Fprint(w, "Invalid request")
@@ -315,7 +334,7 @@
}
req := p.doors[doorId8 - 1].lastRequest
- if req.ip != r.RemoteAddr {
+ if req.ip != c.IpAddress {
fmt.Fprintf(w, "Not your request %s %s", req.ip, r.RemoteAddr)
return
}
@@ -328,17 +347,20 @@
if req.verify != verifyB64[0] {
+ p.log(fmt.Sprintf("Failed verification %s %s", req.verify, verifyB64[0]))
fmt.Fprint(w, "Unauthorized request")
return
}
- p.doorLock.Lock()
- defer p.doorLock.Unlock()
-
p.doors[doorId8 - 1].lastRequest = nil
- p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changing")
+ err = p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changed")
+ if err != nil {
+ fmt.Fprintf(w, "Couldn't set status %d %d: %s", doorId8, req.status, err.Error())
+ }
return
@@ -463,7 +485,7 @@
p.initDoors()
- p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
+ p.log(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
if configErr != nil {
p.postAdminChannel(configErr.Error())
@@ -562,7 +584,7 @@
}
}
case <- p.configChanged:
- p.API.LogInfo(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
+ p.log(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
run = false
}
}
diff --git a/mattermost/server/bathroom.tar.gz b/mattermost/server/bathroom.tar.gz
deleted file mode 100644
index f2298e9..0000000
--- a/mattermost/server/bathroom.tar.gz
+++ /dev/null
Binary files differ
diff --git a/mattermost/server/build.sh b/mattermost/server/build.sh
index 916a360..c2c1a0e 100755
--- a/mattermost/server/build.sh
+++ b/mattermost/server/build.sh
@@ -1,4 +1,4 @@
#! /usr/bin/env bash
-filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) plugin_templ.json > plugin.json
+filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) ../plugin_templ.json > ../plugin.json
GOOS=linux GOARCH=amd64 go build $( [[ ! -z "$DEFS" ]] && echo -tags $DEFS ) -o bathroom-linux-amd64 bathroom.go $FILES
diff --git a/mattermost/server/package.sh b/mattermost/server/package.sh
deleted file mode 100755
index c8ce874..0000000
--- a/mattermost/server/package.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#! /usr/bin/env bash
-
-tar -czvf bathroom.tar.gz bathroom-linux-amd64 plugin.json
diff --git a/mattermost/server/plugin.json b/mattermost/server/plugin.json
deleted file mode 100644
index e4d22cb..0000000
--- a/mattermost/server/plugin.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "id": "com.mattermost.bathroom",
- "name": "Bathroom Monitor",
- "server": {
- "executable": "bathroom-linux-amd64"
- },
- "settings_schema": {
- "settings": [
- {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
- {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
- {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
- ]
- }
-}
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/install_deps.sh b/mattermost/install_deps.sh
new file mode 100644
index 0000000..6a3cec5
--- /dev/null
+++ b/mattermost/install_deps.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+
+sudo apt-get install filepp
diff --git a/mattermost/package.sh b/mattermost/package.sh
new file mode 100644
index 0000000..7253322
--- /dev/null
+++ b/mattermost/package.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+cd "$( dirname "${BASH_SOURCE[0]}" )"
+tar -czvf bathroom.tar.gz plugin.json -C server bathroom-linux-amd64 -C ../webapp/dist main.js
diff --git a/mattermost/plugin.json b/mattermost/plugin.json
new file mode 100644
index 0000000..ba3a186
--- /dev/null
+++ b/mattermost/plugin.json
@@ -0,0 +1,17 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/plugin_templ.json b/mattermost/plugin_templ.json
new file mode 100644
index 0000000..634b204
--- /dev/null
+++ b/mattermost/plugin_templ.json
@@ -0,0 +1,21 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+#ifdef fsnotify
+ {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#else
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#endif
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64
index 681e00f..c478ac9 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 225a000..b3512ab 100644
--- a/mattermost/server/bathroom.go
+++ b/mattermost/server/bathroom.go
@@ -30,6 +30,8 @@
"encoding/base64"
)
+const DO_LOGGING = false
+
var userSplit *regexp.Regexp = regexp.MustCompile(`\s+(^|[^,])|\s*,\s*`)
const (
@@ -139,6 +141,12 @@
}
}
+func (p *BathroomMonitorPlugin) log(log string) {
+ if DO_LOGGING {
+ p.API.LogInfo(log)
+ }
+}
+
func (p *BathroomMonitorPlugin) setDoorStatus(id uint8, status uint, report bool) error {
if id < 1 || id > p.config.numDoors {
return errors.New(fmt.Sprintf("Invalid door id %d", id))
@@ -156,8 +164,12 @@
p.doors[id - 1].status = status
if report {
statusStr, _ := statusName(status)
- p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ _ = statusStr
+ //p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ p.API.PublishWebSocketEvent("updated", map[string]interface{}{}, &model.WebsocketBroadcast{})
}
+ } else {
+ p.log(fmt.Sprintf("Asked to change status from %d to %d ?", p.doors[id - 1].status, status))
}
return nil
@@ -186,12 +198,12 @@
p.configLock.Unlock()
- doorVal, ok := r.Form["door_id"]
- if !ok || len(doorVal) == 0 {
+ doorStr, ok := r.Form["door_id"]
+ if !ok || len(doorStr) == 0 {
return 0, errors.New("Please send door id")
}
- doorId, err := strconv.ParseUint(doorVal[0], 10, 8)
+ doorId, err := strconv.ParseUint(doorStr[0], 10, 8)
if err != nil {
return 0, errors.New(fmt.Sprintf("Couldn't parse door_id: %s", err.Error()))
}
@@ -205,7 +217,7 @@
}
func (p *BathroomMonitorPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
- p.API.LogInfo(fmt.Sprintf("Requested path: %s", r.URL.Path))
+ p.log(fmt.Sprintf("Requested path: %s %s", r.URL.Path, c.IpAddress))
if r.URL.Path == "/status" {
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -224,7 +236,7 @@
}
if r.URL.Path == "/status-update" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
@@ -232,13 +244,13 @@
return
}
- statusVal, ok := r.Form["status"]
- if !ok || len(statusVal) == 0 {
+ statusStr, ok := r.Form["status"]
+ if !ok || len(statusStr) == 0 {
fmt.Fprint(w, "Please send door status")
return
}
- status, err := strconv.ParseUint(statusVal[0], 10, 8)
+ status, err := strconv.ParseUint(statusStr[0], 10, 8)
if err != nil {
fmt.Fprintf(w, "Couldn't parse status: %s", err.Error())
return
@@ -249,6 +261,11 @@
return
}
+ statusVal := Open
+ if status == 1 {
+ statusVal = Closed
+ }
+
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -257,34 +274,34 @@
return
}
- p.API.LogInfo("Getting random bytes")
+ p.log("Getting random bytes")
var verifyBytes [50]byte
rand.Read(verifyBytes[:])
- p.API.LogInfo("Encoding random bytes")
+ p.log("Encoding random bytes")
verifyB64 := base64.StdEncoding.EncodeToString(verifyBytes[:])
- p.API.LogInfo("Encryping random bytes")
+ p.log("Encryping random bytes")
encrypted, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, p.doors[doorId8 - 1].pubKey, verifyBytes[:], []byte{})
if err != nil {
fmt.Fprintf(w, "Couldn't encrypt verification: %s", err.Error())
return
}
- p.API.LogInfo("Encoding encrypted bytes")
+ p.log("Encoding encrypted bytes")
encryptedB64 := base64.StdEncoding.EncodeToString(encrypted)
req := &DoorRequest {
- ip:r.RemoteAddr,
+ ip:c.IpAddress,
time:time.Now().Unix(),
verify:verifyB64,
- status: uint(status),
+ status: statusVal,
}
p.doors[doorId8 - 1].lastRequest = req
- p.API.LogInfo(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
+ p.log(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
fmt.Fprint(w, encryptedB64)
@@ -293,7 +310,7 @@
}
if r.URL.Path == "/verify-status" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
fmt.Fprint(w, err.Error())
@@ -306,8 +323,10 @@
return
}
+ p.log("Verify locking")
p.doorLock.Lock()
defer p.doorLock.Unlock()
+ p.log("Verify done locking")
if p.doors[doorId8 - 1].lastRequest == nil {
fmt.Fprint(w, "Invalid request")
@@ -315,7 +334,7 @@
}
req := p.doors[doorId8 - 1].lastRequest
- if req.ip != r.RemoteAddr {
+ if req.ip != c.IpAddress {
fmt.Fprintf(w, "Not your request %s %s", req.ip, r.RemoteAddr)
return
}
@@ -328,17 +347,20 @@
if req.verify != verifyB64[0] {
+ p.log(fmt.Sprintf("Failed verification %s %s", req.verify, verifyB64[0]))
fmt.Fprint(w, "Unauthorized request")
return
}
- p.doorLock.Lock()
- defer p.doorLock.Unlock()
-
p.doors[doorId8 - 1].lastRequest = nil
- p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changing")
+ err = p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changed")
+ if err != nil {
+ fmt.Fprintf(w, "Couldn't set status %d %d: %s", doorId8, req.status, err.Error())
+ }
return
@@ -463,7 +485,7 @@
p.initDoors()
- p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
+ p.log(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
if configErr != nil {
p.postAdminChannel(configErr.Error())
@@ -562,7 +584,7 @@
}
}
case <- p.configChanged:
- p.API.LogInfo(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
+ p.log(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
run = false
}
}
diff --git a/mattermost/server/bathroom.tar.gz b/mattermost/server/bathroom.tar.gz
deleted file mode 100644
index f2298e9..0000000
--- a/mattermost/server/bathroom.tar.gz
+++ /dev/null
Binary files differ
diff --git a/mattermost/server/build.sh b/mattermost/server/build.sh
index 916a360..c2c1a0e 100755
--- a/mattermost/server/build.sh
+++ b/mattermost/server/build.sh
@@ -1,4 +1,4 @@
#! /usr/bin/env bash
-filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) plugin_templ.json > plugin.json
+filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) ../plugin_templ.json > ../plugin.json
GOOS=linux GOARCH=amd64 go build $( [[ ! -z "$DEFS" ]] && echo -tags $DEFS ) -o bathroom-linux-amd64 bathroom.go $FILES
diff --git a/mattermost/server/package.sh b/mattermost/server/package.sh
deleted file mode 100755
index c8ce874..0000000
--- a/mattermost/server/package.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#! /usr/bin/env bash
-
-tar -czvf bathroom.tar.gz bathroom-linux-amd64 plugin.json
diff --git a/mattermost/server/plugin.json b/mattermost/server/plugin.json
deleted file mode 100644
index e4d22cb..0000000
--- a/mattermost/server/plugin.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "id": "com.mattermost.bathroom",
- "name": "Bathroom Monitor",
- "server": {
- "executable": "bathroom-linux-amd64"
- },
- "settings_schema": {
- "settings": [
- {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
- {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
- {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
- ]
- }
-}
diff --git a/mattermost/server/plugin_templ.json b/mattermost/server/plugin_templ.json
deleted file mode 100644
index 1de221a..0000000
--- a/mattermost/server/plugin_templ.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "id": "com.mattermost.bathroom",
- "name": "Bathroom Monitor",
- "server": {
- "executable": "bathroom-linux-amd64"
- },
- "settings_schema": {
- "settings": [
- {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
-#ifdef fsnotify
- {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
-#else
- {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
-#endif
- {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
- ]
- }
-}
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/install_deps.sh b/mattermost/install_deps.sh
new file mode 100644
index 0000000..6a3cec5
--- /dev/null
+++ b/mattermost/install_deps.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+
+sudo apt-get install filepp
diff --git a/mattermost/package.sh b/mattermost/package.sh
new file mode 100644
index 0000000..7253322
--- /dev/null
+++ b/mattermost/package.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+cd "$( dirname "${BASH_SOURCE[0]}" )"
+tar -czvf bathroom.tar.gz plugin.json -C server bathroom-linux-amd64 -C ../webapp/dist main.js
diff --git a/mattermost/plugin.json b/mattermost/plugin.json
new file mode 100644
index 0000000..ba3a186
--- /dev/null
+++ b/mattermost/plugin.json
@@ -0,0 +1,17 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/plugin_templ.json b/mattermost/plugin_templ.json
new file mode 100644
index 0000000..634b204
--- /dev/null
+++ b/mattermost/plugin_templ.json
@@ -0,0 +1,21 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+#ifdef fsnotify
+ {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#else
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#endif
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64
index 681e00f..c478ac9 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 225a000..b3512ab 100644
--- a/mattermost/server/bathroom.go
+++ b/mattermost/server/bathroom.go
@@ -30,6 +30,8 @@
"encoding/base64"
)
+const DO_LOGGING = false
+
var userSplit *regexp.Regexp = regexp.MustCompile(`\s+(^|[^,])|\s*,\s*`)
const (
@@ -139,6 +141,12 @@
}
}
+func (p *BathroomMonitorPlugin) log(log string) {
+ if DO_LOGGING {
+ p.API.LogInfo(log)
+ }
+}
+
func (p *BathroomMonitorPlugin) setDoorStatus(id uint8, status uint, report bool) error {
if id < 1 || id > p.config.numDoors {
return errors.New(fmt.Sprintf("Invalid door id %d", id))
@@ -156,8 +164,12 @@
p.doors[id - 1].status = status
if report {
statusStr, _ := statusName(status)
- p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ _ = statusStr
+ //p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ p.API.PublishWebSocketEvent("updated", map[string]interface{}{}, &model.WebsocketBroadcast{})
}
+ } else {
+ p.log(fmt.Sprintf("Asked to change status from %d to %d ?", p.doors[id - 1].status, status))
}
return nil
@@ -186,12 +198,12 @@
p.configLock.Unlock()
- doorVal, ok := r.Form["door_id"]
- if !ok || len(doorVal) == 0 {
+ doorStr, ok := r.Form["door_id"]
+ if !ok || len(doorStr) == 0 {
return 0, errors.New("Please send door id")
}
- doorId, err := strconv.ParseUint(doorVal[0], 10, 8)
+ doorId, err := strconv.ParseUint(doorStr[0], 10, 8)
if err != nil {
return 0, errors.New(fmt.Sprintf("Couldn't parse door_id: %s", err.Error()))
}
@@ -205,7 +217,7 @@
}
func (p *BathroomMonitorPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
- p.API.LogInfo(fmt.Sprintf("Requested path: %s", r.URL.Path))
+ p.log(fmt.Sprintf("Requested path: %s %s", r.URL.Path, c.IpAddress))
if r.URL.Path == "/status" {
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -224,7 +236,7 @@
}
if r.URL.Path == "/status-update" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
@@ -232,13 +244,13 @@
return
}
- statusVal, ok := r.Form["status"]
- if !ok || len(statusVal) == 0 {
+ statusStr, ok := r.Form["status"]
+ if !ok || len(statusStr) == 0 {
fmt.Fprint(w, "Please send door status")
return
}
- status, err := strconv.ParseUint(statusVal[0], 10, 8)
+ status, err := strconv.ParseUint(statusStr[0], 10, 8)
if err != nil {
fmt.Fprintf(w, "Couldn't parse status: %s", err.Error())
return
@@ -249,6 +261,11 @@
return
}
+ statusVal := Open
+ if status == 1 {
+ statusVal = Closed
+ }
+
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -257,34 +274,34 @@
return
}
- p.API.LogInfo("Getting random bytes")
+ p.log("Getting random bytes")
var verifyBytes [50]byte
rand.Read(verifyBytes[:])
- p.API.LogInfo("Encoding random bytes")
+ p.log("Encoding random bytes")
verifyB64 := base64.StdEncoding.EncodeToString(verifyBytes[:])
- p.API.LogInfo("Encryping random bytes")
+ p.log("Encryping random bytes")
encrypted, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, p.doors[doorId8 - 1].pubKey, verifyBytes[:], []byte{})
if err != nil {
fmt.Fprintf(w, "Couldn't encrypt verification: %s", err.Error())
return
}
- p.API.LogInfo("Encoding encrypted bytes")
+ p.log("Encoding encrypted bytes")
encryptedB64 := base64.StdEncoding.EncodeToString(encrypted)
req := &DoorRequest {
- ip:r.RemoteAddr,
+ ip:c.IpAddress,
time:time.Now().Unix(),
verify:verifyB64,
- status: uint(status),
+ status: statusVal,
}
p.doors[doorId8 - 1].lastRequest = req
- p.API.LogInfo(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
+ p.log(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
fmt.Fprint(w, encryptedB64)
@@ -293,7 +310,7 @@
}
if r.URL.Path == "/verify-status" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
fmt.Fprint(w, err.Error())
@@ -306,8 +323,10 @@
return
}
+ p.log("Verify locking")
p.doorLock.Lock()
defer p.doorLock.Unlock()
+ p.log("Verify done locking")
if p.doors[doorId8 - 1].lastRequest == nil {
fmt.Fprint(w, "Invalid request")
@@ -315,7 +334,7 @@
}
req := p.doors[doorId8 - 1].lastRequest
- if req.ip != r.RemoteAddr {
+ if req.ip != c.IpAddress {
fmt.Fprintf(w, "Not your request %s %s", req.ip, r.RemoteAddr)
return
}
@@ -328,17 +347,20 @@
if req.verify != verifyB64[0] {
+ p.log(fmt.Sprintf("Failed verification %s %s", req.verify, verifyB64[0]))
fmt.Fprint(w, "Unauthorized request")
return
}
- p.doorLock.Lock()
- defer p.doorLock.Unlock()
-
p.doors[doorId8 - 1].lastRequest = nil
- p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changing")
+ err = p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changed")
+ if err != nil {
+ fmt.Fprintf(w, "Couldn't set status %d %d: %s", doorId8, req.status, err.Error())
+ }
return
@@ -463,7 +485,7 @@
p.initDoors()
- p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
+ p.log(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
if configErr != nil {
p.postAdminChannel(configErr.Error())
@@ -562,7 +584,7 @@
}
}
case <- p.configChanged:
- p.API.LogInfo(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
+ p.log(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
run = false
}
}
diff --git a/mattermost/server/bathroom.tar.gz b/mattermost/server/bathroom.tar.gz
deleted file mode 100644
index f2298e9..0000000
--- a/mattermost/server/bathroom.tar.gz
+++ /dev/null
Binary files differ
diff --git a/mattermost/server/build.sh b/mattermost/server/build.sh
index 916a360..c2c1a0e 100755
--- a/mattermost/server/build.sh
+++ b/mattermost/server/build.sh
@@ -1,4 +1,4 @@
#! /usr/bin/env bash
-filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) plugin_templ.json > plugin.json
+filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) ../plugin_templ.json > ../plugin.json
GOOS=linux GOARCH=amd64 go build $( [[ ! -z "$DEFS" ]] && echo -tags $DEFS ) -o bathroom-linux-amd64 bathroom.go $FILES
diff --git a/mattermost/server/package.sh b/mattermost/server/package.sh
deleted file mode 100755
index c8ce874..0000000
--- a/mattermost/server/package.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#! /usr/bin/env bash
-
-tar -czvf bathroom.tar.gz bathroom-linux-amd64 plugin.json
diff --git a/mattermost/server/plugin.json b/mattermost/server/plugin.json
deleted file mode 100644
index e4d22cb..0000000
--- a/mattermost/server/plugin.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "id": "com.mattermost.bathroom",
- "name": "Bathroom Monitor",
- "server": {
- "executable": "bathroom-linux-amd64"
- },
- "settings_schema": {
- "settings": [
- {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
- {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
- {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
- ]
- }
-}
diff --git a/mattermost/server/plugin_templ.json b/mattermost/server/plugin_templ.json
deleted file mode 100644
index 1de221a..0000000
--- a/mattermost/server/plugin_templ.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "id": "com.mattermost.bathroom",
- "name": "Bathroom Monitor",
- "server": {
- "executable": "bathroom-linux-amd64"
- },
- "settings_schema": {
- "settings": [
- {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
-#ifdef fsnotify
- {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
-#else
- {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
-#endif
- {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
- ]
- }
-}
diff --git a/mattermost/webapp/bathroom.tar.gz b/mattermost/webapp/bathroom.tar.gz
new file mode 100644
index 0000000..48d8426
--- /dev/null
+++ b/mattermost/webapp/bathroom.tar.gz
Binary files differ
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/install_deps.sh b/mattermost/install_deps.sh
new file mode 100644
index 0000000..6a3cec5
--- /dev/null
+++ b/mattermost/install_deps.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+
+sudo apt-get install filepp
diff --git a/mattermost/package.sh b/mattermost/package.sh
new file mode 100644
index 0000000..7253322
--- /dev/null
+++ b/mattermost/package.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+cd "$( dirname "${BASH_SOURCE[0]}" )"
+tar -czvf bathroom.tar.gz plugin.json -C server bathroom-linux-amd64 -C ../webapp/dist main.js
diff --git a/mattermost/plugin.json b/mattermost/plugin.json
new file mode 100644
index 0000000..ba3a186
--- /dev/null
+++ b/mattermost/plugin.json
@@ -0,0 +1,17 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/plugin_templ.json b/mattermost/plugin_templ.json
new file mode 100644
index 0000000..634b204
--- /dev/null
+++ b/mattermost/plugin_templ.json
@@ -0,0 +1,21 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+#ifdef fsnotify
+ {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#else
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#endif
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64
index 681e00f..c478ac9 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 225a000..b3512ab 100644
--- a/mattermost/server/bathroom.go
+++ b/mattermost/server/bathroom.go
@@ -30,6 +30,8 @@
"encoding/base64"
)
+const DO_LOGGING = false
+
var userSplit *regexp.Regexp = regexp.MustCompile(`\s+(^|[^,])|\s*,\s*`)
const (
@@ -139,6 +141,12 @@
}
}
+func (p *BathroomMonitorPlugin) log(log string) {
+ if DO_LOGGING {
+ p.API.LogInfo(log)
+ }
+}
+
func (p *BathroomMonitorPlugin) setDoorStatus(id uint8, status uint, report bool) error {
if id < 1 || id > p.config.numDoors {
return errors.New(fmt.Sprintf("Invalid door id %d", id))
@@ -156,8 +164,12 @@
p.doors[id - 1].status = status
if report {
statusStr, _ := statusName(status)
- p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ _ = statusStr
+ //p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ p.API.PublishWebSocketEvent("updated", map[string]interface{}{}, &model.WebsocketBroadcast{})
}
+ } else {
+ p.log(fmt.Sprintf("Asked to change status from %d to %d ?", p.doors[id - 1].status, status))
}
return nil
@@ -186,12 +198,12 @@
p.configLock.Unlock()
- doorVal, ok := r.Form["door_id"]
- if !ok || len(doorVal) == 0 {
+ doorStr, ok := r.Form["door_id"]
+ if !ok || len(doorStr) == 0 {
return 0, errors.New("Please send door id")
}
- doorId, err := strconv.ParseUint(doorVal[0], 10, 8)
+ doorId, err := strconv.ParseUint(doorStr[0], 10, 8)
if err != nil {
return 0, errors.New(fmt.Sprintf("Couldn't parse door_id: %s", err.Error()))
}
@@ -205,7 +217,7 @@
}
func (p *BathroomMonitorPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
- p.API.LogInfo(fmt.Sprintf("Requested path: %s", r.URL.Path))
+ p.log(fmt.Sprintf("Requested path: %s %s", r.URL.Path, c.IpAddress))
if r.URL.Path == "/status" {
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -224,7 +236,7 @@
}
if r.URL.Path == "/status-update" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
@@ -232,13 +244,13 @@
return
}
- statusVal, ok := r.Form["status"]
- if !ok || len(statusVal) == 0 {
+ statusStr, ok := r.Form["status"]
+ if !ok || len(statusStr) == 0 {
fmt.Fprint(w, "Please send door status")
return
}
- status, err := strconv.ParseUint(statusVal[0], 10, 8)
+ status, err := strconv.ParseUint(statusStr[0], 10, 8)
if err != nil {
fmt.Fprintf(w, "Couldn't parse status: %s", err.Error())
return
@@ -249,6 +261,11 @@
return
}
+ statusVal := Open
+ if status == 1 {
+ statusVal = Closed
+ }
+
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -257,34 +274,34 @@
return
}
- p.API.LogInfo("Getting random bytes")
+ p.log("Getting random bytes")
var verifyBytes [50]byte
rand.Read(verifyBytes[:])
- p.API.LogInfo("Encoding random bytes")
+ p.log("Encoding random bytes")
verifyB64 := base64.StdEncoding.EncodeToString(verifyBytes[:])
- p.API.LogInfo("Encryping random bytes")
+ p.log("Encryping random bytes")
encrypted, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, p.doors[doorId8 - 1].pubKey, verifyBytes[:], []byte{})
if err != nil {
fmt.Fprintf(w, "Couldn't encrypt verification: %s", err.Error())
return
}
- p.API.LogInfo("Encoding encrypted bytes")
+ p.log("Encoding encrypted bytes")
encryptedB64 := base64.StdEncoding.EncodeToString(encrypted)
req := &DoorRequest {
- ip:r.RemoteAddr,
+ ip:c.IpAddress,
time:time.Now().Unix(),
verify:verifyB64,
- status: uint(status),
+ status: statusVal,
}
p.doors[doorId8 - 1].lastRequest = req
- p.API.LogInfo(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
+ p.log(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
fmt.Fprint(w, encryptedB64)
@@ -293,7 +310,7 @@
}
if r.URL.Path == "/verify-status" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
fmt.Fprint(w, err.Error())
@@ -306,8 +323,10 @@
return
}
+ p.log("Verify locking")
p.doorLock.Lock()
defer p.doorLock.Unlock()
+ p.log("Verify done locking")
if p.doors[doorId8 - 1].lastRequest == nil {
fmt.Fprint(w, "Invalid request")
@@ -315,7 +334,7 @@
}
req := p.doors[doorId8 - 1].lastRequest
- if req.ip != r.RemoteAddr {
+ if req.ip != c.IpAddress {
fmt.Fprintf(w, "Not your request %s %s", req.ip, r.RemoteAddr)
return
}
@@ -328,17 +347,20 @@
if req.verify != verifyB64[0] {
+ p.log(fmt.Sprintf("Failed verification %s %s", req.verify, verifyB64[0]))
fmt.Fprint(w, "Unauthorized request")
return
}
- p.doorLock.Lock()
- defer p.doorLock.Unlock()
-
p.doors[doorId8 - 1].lastRequest = nil
- p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changing")
+ err = p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changed")
+ if err != nil {
+ fmt.Fprintf(w, "Couldn't set status %d %d: %s", doorId8, req.status, err.Error())
+ }
return
@@ -463,7 +485,7 @@
p.initDoors()
- p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
+ p.log(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
if configErr != nil {
p.postAdminChannel(configErr.Error())
@@ -562,7 +584,7 @@
}
}
case <- p.configChanged:
- p.API.LogInfo(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
+ p.log(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
run = false
}
}
diff --git a/mattermost/server/bathroom.tar.gz b/mattermost/server/bathroom.tar.gz
deleted file mode 100644
index f2298e9..0000000
--- a/mattermost/server/bathroom.tar.gz
+++ /dev/null
Binary files differ
diff --git a/mattermost/server/build.sh b/mattermost/server/build.sh
index 916a360..c2c1a0e 100755
--- a/mattermost/server/build.sh
+++ b/mattermost/server/build.sh
@@ -1,4 +1,4 @@
#! /usr/bin/env bash
-filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) plugin_templ.json > plugin.json
+filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) ../plugin_templ.json > ../plugin.json
GOOS=linux GOARCH=amd64 go build $( [[ ! -z "$DEFS" ]] && echo -tags $DEFS ) -o bathroom-linux-amd64 bathroom.go $FILES
diff --git a/mattermost/server/package.sh b/mattermost/server/package.sh
deleted file mode 100755
index c8ce874..0000000
--- a/mattermost/server/package.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#! /usr/bin/env bash
-
-tar -czvf bathroom.tar.gz bathroom-linux-amd64 plugin.json
diff --git a/mattermost/server/plugin.json b/mattermost/server/plugin.json
deleted file mode 100644
index e4d22cb..0000000
--- a/mattermost/server/plugin.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "id": "com.mattermost.bathroom",
- "name": "Bathroom Monitor",
- "server": {
- "executable": "bathroom-linux-amd64"
- },
- "settings_schema": {
- "settings": [
- {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
- {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
- {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
- ]
- }
-}
diff --git a/mattermost/server/plugin_templ.json b/mattermost/server/plugin_templ.json
deleted file mode 100644
index 1de221a..0000000
--- a/mattermost/server/plugin_templ.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "id": "com.mattermost.bathroom",
- "name": "Bathroom Monitor",
- "server": {
- "executable": "bathroom-linux-amd64"
- },
- "settings_schema": {
- "settings": [
- {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
-#ifdef fsnotify
- {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
-#else
- {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
-#endif
- {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
- ]
- }
-}
diff --git a/mattermost/webapp/bathroom.tar.gz b/mattermost/webapp/bathroom.tar.gz
new file mode 100644
index 0000000..48d8426
--- /dev/null
+++ b/mattermost/webapp/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/webapp/dist/main.js b/mattermost/webapp/dist/main.js
index 8a0c4f1..4cca171 100644
--- a/mattermost/webapp/dist/main.js
+++ b/mattermost/webapp/dist/main.js
@@ -94,7 +94,121 @@
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-eval("\n\n//# sourceURL=webpack:///./src/index.jsx?");
+
+
+var _react = _interopRequireDefault(__webpack_require__(/*! react */ "react"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+class BathroomComponent extends _react.default.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ doors: {}
+ };
+ }
+
+ componentDidMount() {
+ Registry.registerWebSocketEventHandler("custom_com.mattermost.bathroom_updated", this.updateDoors.bind(this));
+ this.updateDoors();
+ }
+
+ componentWillUnmount() {
+ Registry.unregisterWebSocketEventHandler("custom_com.mattermost.bathroom_updated");
+ }
+
+ async updateDoors(msg) {
+ var url = Store.getState().entities.general.config.SiteURL + "/plugins/com.mattermost.bathroom/status";
+ var res = await fetch(url);
+ var json = await res.json();
+ this.setState({
+ "doors": json
+ });
+ }
+
+ render() {
+ if (!this.state.doors) return;
+ var columns = 6;
+ var keys = Object.keys(this.state.doors).sort();
+ var width = Math.floor(100 / columns) + "%";
+ var widthPx = "23px";
+ var elems = [];
+ var row = [];
+
+ for (var i = 0; i < keys.length
+ /*(Math.floor(keys.length / 6) + 1) * 6*/
+ ; i++) {
+ var img = null;
+
+ if (i < keys.length) {
+ var door = this.state.doors[keys[i]];
+ var imgFile = null;
+
+ switch (door) {
+ default:
+ case "unknown":
+ imgFile = "/static/emoji/2753.png";
+ break;
+
+ case "open":
+ imgFile = "/static/emoji/1f6bd.png";
+ break;
+
+ case "closed":
+ imgFile = "/static/emoji/26d4-fe0f.png";
+ break;
+ }
+
+ img = _react.default.createElement("img", {
+ src: imgFile,
+ width: "100%",
+ style: {
+ "padding": "2px"
+ }
+ });
+ }
+
+ row.push(_react.default.createElement("td", {
+ width: widthPx
+ }, img));
+
+ if (i % columns == columns - 1 || i == keys.length - 1) {
+ elems.push(_react.default.createElement(_react.default.Fragment, null, [...row]));
+ row.length = 0;
+ }
+ }
+
+ return (//
+ _react.default.createElement("div", {
+ style: {
+ "text-align": "center",
+ width: "100%",
+ "padding-top": "10px"
+ }
+ }, _react.default.createElement("table", {
+ style: {
+ "margin-left": "auto",
+ "margin-right": "auto"
+ }
+ }, elems))
+ );
+ }
+
+}
+
+var Registry = null;
+var Store = null;
+
+class BathroomMonitorPlugin {
+ initialize(registry, store) {
+ Registry = registry;
+ Store = store;
+ registry.registerLeftSidebarHeaderComponent(BathroomComponent);
+ }
+
+}
+
+window.registerPlugin('com.mattermost.bathroom', new BathroomMonitorPlugin());
/***/ }),
@@ -105,8 +219,21 @@
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
-eval("module.exports = __webpack_require__(/*! ./src/index.jsx */\"./src/index.jsx\");\n\n\n//# sourceURL=webpack:///multi_./src/index.jsx?");
+module.exports = __webpack_require__(/*! ./src/index.jsx */"./src/index.jsx");
+
+
+/***/ }),
+
+/***/ "react":
+/*!************************!*\
+ !*** external "React" ***!
+ \************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = React;
/***/ })
-/******/ });
\ No newline at end of file
+/******/ });
+//# sourceMappingURL=main.js.map
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/install_deps.sh b/mattermost/install_deps.sh
new file mode 100644
index 0000000..6a3cec5
--- /dev/null
+++ b/mattermost/install_deps.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+
+sudo apt-get install filepp
diff --git a/mattermost/package.sh b/mattermost/package.sh
new file mode 100644
index 0000000..7253322
--- /dev/null
+++ b/mattermost/package.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+cd "$( dirname "${BASH_SOURCE[0]}" )"
+tar -czvf bathroom.tar.gz plugin.json -C server bathroom-linux-amd64 -C ../webapp/dist main.js
diff --git a/mattermost/plugin.json b/mattermost/plugin.json
new file mode 100644
index 0000000..ba3a186
--- /dev/null
+++ b/mattermost/plugin.json
@@ -0,0 +1,17 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/plugin_templ.json b/mattermost/plugin_templ.json
new file mode 100644
index 0000000..634b204
--- /dev/null
+++ b/mattermost/plugin_templ.json
@@ -0,0 +1,21 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+#ifdef fsnotify
+ {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#else
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#endif
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64
index 681e00f..c478ac9 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 225a000..b3512ab 100644
--- a/mattermost/server/bathroom.go
+++ b/mattermost/server/bathroom.go
@@ -30,6 +30,8 @@
"encoding/base64"
)
+const DO_LOGGING = false
+
var userSplit *regexp.Regexp = regexp.MustCompile(`\s+(^|[^,])|\s*,\s*`)
const (
@@ -139,6 +141,12 @@
}
}
+func (p *BathroomMonitorPlugin) log(log string) {
+ if DO_LOGGING {
+ p.API.LogInfo(log)
+ }
+}
+
func (p *BathroomMonitorPlugin) setDoorStatus(id uint8, status uint, report bool) error {
if id < 1 || id > p.config.numDoors {
return errors.New(fmt.Sprintf("Invalid door id %d", id))
@@ -156,8 +164,12 @@
p.doors[id - 1].status = status
if report {
statusStr, _ := statusName(status)
- p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ _ = statusStr
+ //p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ p.API.PublishWebSocketEvent("updated", map[string]interface{}{}, &model.WebsocketBroadcast{})
}
+ } else {
+ p.log(fmt.Sprintf("Asked to change status from %d to %d ?", p.doors[id - 1].status, status))
}
return nil
@@ -186,12 +198,12 @@
p.configLock.Unlock()
- doorVal, ok := r.Form["door_id"]
- if !ok || len(doorVal) == 0 {
+ doorStr, ok := r.Form["door_id"]
+ if !ok || len(doorStr) == 0 {
return 0, errors.New("Please send door id")
}
- doorId, err := strconv.ParseUint(doorVal[0], 10, 8)
+ doorId, err := strconv.ParseUint(doorStr[0], 10, 8)
if err != nil {
return 0, errors.New(fmt.Sprintf("Couldn't parse door_id: %s", err.Error()))
}
@@ -205,7 +217,7 @@
}
func (p *BathroomMonitorPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
- p.API.LogInfo(fmt.Sprintf("Requested path: %s", r.URL.Path))
+ p.log(fmt.Sprintf("Requested path: %s %s", r.URL.Path, c.IpAddress))
if r.URL.Path == "/status" {
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -224,7 +236,7 @@
}
if r.URL.Path == "/status-update" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
@@ -232,13 +244,13 @@
return
}
- statusVal, ok := r.Form["status"]
- if !ok || len(statusVal) == 0 {
+ statusStr, ok := r.Form["status"]
+ if !ok || len(statusStr) == 0 {
fmt.Fprint(w, "Please send door status")
return
}
- status, err := strconv.ParseUint(statusVal[0], 10, 8)
+ status, err := strconv.ParseUint(statusStr[0], 10, 8)
if err != nil {
fmt.Fprintf(w, "Couldn't parse status: %s", err.Error())
return
@@ -249,6 +261,11 @@
return
}
+ statusVal := Open
+ if status == 1 {
+ statusVal = Closed
+ }
+
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -257,34 +274,34 @@
return
}
- p.API.LogInfo("Getting random bytes")
+ p.log("Getting random bytes")
var verifyBytes [50]byte
rand.Read(verifyBytes[:])
- p.API.LogInfo("Encoding random bytes")
+ p.log("Encoding random bytes")
verifyB64 := base64.StdEncoding.EncodeToString(verifyBytes[:])
- p.API.LogInfo("Encryping random bytes")
+ p.log("Encryping random bytes")
encrypted, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, p.doors[doorId8 - 1].pubKey, verifyBytes[:], []byte{})
if err != nil {
fmt.Fprintf(w, "Couldn't encrypt verification: %s", err.Error())
return
}
- p.API.LogInfo("Encoding encrypted bytes")
+ p.log("Encoding encrypted bytes")
encryptedB64 := base64.StdEncoding.EncodeToString(encrypted)
req := &DoorRequest {
- ip:r.RemoteAddr,
+ ip:c.IpAddress,
time:time.Now().Unix(),
verify:verifyB64,
- status: uint(status),
+ status: statusVal,
}
p.doors[doorId8 - 1].lastRequest = req
- p.API.LogInfo(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
+ p.log(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
fmt.Fprint(w, encryptedB64)
@@ -293,7 +310,7 @@
}
if r.URL.Path == "/verify-status" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
fmt.Fprint(w, err.Error())
@@ -306,8 +323,10 @@
return
}
+ p.log("Verify locking")
p.doorLock.Lock()
defer p.doorLock.Unlock()
+ p.log("Verify done locking")
if p.doors[doorId8 - 1].lastRequest == nil {
fmt.Fprint(w, "Invalid request")
@@ -315,7 +334,7 @@
}
req := p.doors[doorId8 - 1].lastRequest
- if req.ip != r.RemoteAddr {
+ if req.ip != c.IpAddress {
fmt.Fprintf(w, "Not your request %s %s", req.ip, r.RemoteAddr)
return
}
@@ -328,17 +347,20 @@
if req.verify != verifyB64[0] {
+ p.log(fmt.Sprintf("Failed verification %s %s", req.verify, verifyB64[0]))
fmt.Fprint(w, "Unauthorized request")
return
}
- p.doorLock.Lock()
- defer p.doorLock.Unlock()
-
p.doors[doorId8 - 1].lastRequest = nil
- p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changing")
+ err = p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changed")
+ if err != nil {
+ fmt.Fprintf(w, "Couldn't set status %d %d: %s", doorId8, req.status, err.Error())
+ }
return
@@ -463,7 +485,7 @@
p.initDoors()
- p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
+ p.log(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
if configErr != nil {
p.postAdminChannel(configErr.Error())
@@ -562,7 +584,7 @@
}
}
case <- p.configChanged:
- p.API.LogInfo(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
+ p.log(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
run = false
}
}
diff --git a/mattermost/server/bathroom.tar.gz b/mattermost/server/bathroom.tar.gz
deleted file mode 100644
index f2298e9..0000000
--- a/mattermost/server/bathroom.tar.gz
+++ /dev/null
Binary files differ
diff --git a/mattermost/server/build.sh b/mattermost/server/build.sh
index 916a360..c2c1a0e 100755
--- a/mattermost/server/build.sh
+++ b/mattermost/server/build.sh
@@ -1,4 +1,4 @@
#! /usr/bin/env bash
-filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) plugin_templ.json > plugin.json
+filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) ../plugin_templ.json > ../plugin.json
GOOS=linux GOARCH=amd64 go build $( [[ ! -z "$DEFS" ]] && echo -tags $DEFS ) -o bathroom-linux-amd64 bathroom.go $FILES
diff --git a/mattermost/server/package.sh b/mattermost/server/package.sh
deleted file mode 100755
index c8ce874..0000000
--- a/mattermost/server/package.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#! /usr/bin/env bash
-
-tar -czvf bathroom.tar.gz bathroom-linux-amd64 plugin.json
diff --git a/mattermost/server/plugin.json b/mattermost/server/plugin.json
deleted file mode 100644
index e4d22cb..0000000
--- a/mattermost/server/plugin.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "id": "com.mattermost.bathroom",
- "name": "Bathroom Monitor",
- "server": {
- "executable": "bathroom-linux-amd64"
- },
- "settings_schema": {
- "settings": [
- {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
- {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
- {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
- ]
- }
-}
diff --git a/mattermost/server/plugin_templ.json b/mattermost/server/plugin_templ.json
deleted file mode 100644
index 1de221a..0000000
--- a/mattermost/server/plugin_templ.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "id": "com.mattermost.bathroom",
- "name": "Bathroom Monitor",
- "server": {
- "executable": "bathroom-linux-amd64"
- },
- "settings_schema": {
- "settings": [
- {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
-#ifdef fsnotify
- {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
-#else
- {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
-#endif
- {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
- ]
- }
-}
diff --git a/mattermost/webapp/bathroom.tar.gz b/mattermost/webapp/bathroom.tar.gz
new file mode 100644
index 0000000..48d8426
--- /dev/null
+++ b/mattermost/webapp/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/webapp/dist/main.js b/mattermost/webapp/dist/main.js
index 8a0c4f1..4cca171 100644
--- a/mattermost/webapp/dist/main.js
+++ b/mattermost/webapp/dist/main.js
@@ -94,7 +94,121 @@
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-eval("\n\n//# sourceURL=webpack:///./src/index.jsx?");
+
+
+var _react = _interopRequireDefault(__webpack_require__(/*! react */ "react"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+class BathroomComponent extends _react.default.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ doors: {}
+ };
+ }
+
+ componentDidMount() {
+ Registry.registerWebSocketEventHandler("custom_com.mattermost.bathroom_updated", this.updateDoors.bind(this));
+ this.updateDoors();
+ }
+
+ componentWillUnmount() {
+ Registry.unregisterWebSocketEventHandler("custom_com.mattermost.bathroom_updated");
+ }
+
+ async updateDoors(msg) {
+ var url = Store.getState().entities.general.config.SiteURL + "/plugins/com.mattermost.bathroom/status";
+ var res = await fetch(url);
+ var json = await res.json();
+ this.setState({
+ "doors": json
+ });
+ }
+
+ render() {
+ if (!this.state.doors) return;
+ var columns = 6;
+ var keys = Object.keys(this.state.doors).sort();
+ var width = Math.floor(100 / columns) + "%";
+ var widthPx = "23px";
+ var elems = [];
+ var row = [];
+
+ for (var i = 0; i < keys.length
+ /*(Math.floor(keys.length / 6) + 1) * 6*/
+ ; i++) {
+ var img = null;
+
+ if (i < keys.length) {
+ var door = this.state.doors[keys[i]];
+ var imgFile = null;
+
+ switch (door) {
+ default:
+ case "unknown":
+ imgFile = "/static/emoji/2753.png";
+ break;
+
+ case "open":
+ imgFile = "/static/emoji/1f6bd.png";
+ break;
+
+ case "closed":
+ imgFile = "/static/emoji/26d4-fe0f.png";
+ break;
+ }
+
+ img = _react.default.createElement("img", {
+ src: imgFile,
+ width: "100%",
+ style: {
+ "padding": "2px"
+ }
+ });
+ }
+
+ row.push(_react.default.createElement("td", {
+ width: widthPx
+ }, img));
+
+ if (i % columns == columns - 1 || i == keys.length - 1) {
+ elems.push(_react.default.createElement(_react.default.Fragment, null, [...row]));
+ row.length = 0;
+ }
+ }
+
+ return (//
+ _react.default.createElement("div", {
+ style: {
+ "text-align": "center",
+ width: "100%",
+ "padding-top": "10px"
+ }
+ }, _react.default.createElement("table", {
+ style: {
+ "margin-left": "auto",
+ "margin-right": "auto"
+ }
+ }, elems))
+ );
+ }
+
+}
+
+var Registry = null;
+var Store = null;
+
+class BathroomMonitorPlugin {
+ initialize(registry, store) {
+ Registry = registry;
+ Store = store;
+ registry.registerLeftSidebarHeaderComponent(BathroomComponent);
+ }
+
+}
+
+window.registerPlugin('com.mattermost.bathroom', new BathroomMonitorPlugin());
/***/ }),
@@ -105,8 +219,21 @@
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
-eval("module.exports = __webpack_require__(/*! ./src/index.jsx */\"./src/index.jsx\");\n\n\n//# sourceURL=webpack:///multi_./src/index.jsx?");
+module.exports = __webpack_require__(/*! ./src/index.jsx */"./src/index.jsx");
+
+
+/***/ }),
+
+/***/ "react":
+/*!************************!*\
+ !*** external "React" ***!
+ \************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = React;
/***/ })
-/******/ });
\ No newline at end of file
+/******/ });
+//# sourceMappingURL=main.js.map
\ No newline at end of file
diff --git a/mattermost/webapp/dist/main.js.map b/mattermost/webapp/dist/main.js.map
new file mode 100644
index 0000000..26114e4
--- /dev/null
+++ b/mattermost/webapp/dist/main.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/index.jsx","webpack:///external \"React\""],"names":["BathroomComponent","React","Component","constructor","props","state","doors","componentDidMount","Registry","registerWebSocketEventHandler","updateDoors","bind","componentWillUnmount","unregisterWebSocketEventHandler","msg","url","Store","getState","entities","general","config","SiteURL","res","fetch","json","setState","render","columns","keys","Object","sort","width","Math","floor","widthPx","elems","row","i","length","img","door","imgFile","push","BathroomMonitorPlugin","initialize","registry","store","registerLeftSidebarHeaderComponent","window","registerPlugin"],"mappings":"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","file":"main.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","import React from 'react';\n\nclass BathroomComponent extends React.Component\n{\n constructor(props)\n {\n super(props);\n this.state = {doors:{}};\n }\n componentDidMount()\n {\n Registry.registerWebSocketEventHandler(\"custom_com.mattermost.bathroom_updated\", this.updateDoors.bind(this));\n this.updateDoors();\n }\n componentWillUnmount()\n {\n Registry.unregisterWebSocketEventHandler(\"custom_com.mattermost.bathroom_updated\");\n }\n async updateDoors(msg)\n {\n var url = Store.getState().entities.general.config.SiteURL + \"/plugins/com.mattermost.bathroom/status\";\n var res = await fetch(url);\n var json = await res.json();\n this.setState({\"doors\":json});\n }\n render()\n {\n if (!this.state.doors) return;\n var columns = 6;\n var keys = Object.keys(this.state.doors).sort();\n var width = (Math.floor(100 / columns)) + \"%\";\n var widthPx = \"23px\";\n var elems = [];\n var row = [];\n for (var i = 0; i < keys.length /*(Math.floor(keys.length / 6) + 1) * 6*/; i++)\n {\n var img = null;\n if (i < keys.length)\n {\n var door = this.state.doors[keys[i]];\n var imgFile = null;\n switch (door)\n {\n default:\n case \"unknown\":\n imgFile = \"/static/emoji/2753.png\";\n break;\n case \"open\":\n imgFile = \"/static/emoji/1f6bd.png\";\n break;\n case \"closed\":\n imgFile = \"/static/emoji/26d4-fe0f.png\";\n break;\n }\n img =
\n }\n row.push({img} | );\n if (i % columns == columns - 1 || i == keys.length - 1)\n {\n elems.push({[...row]});\n row.length = 0;\n }\n }\n return (\n //\n \n );\n }\n}\n\nvar Registry = null;\nvar Store = null;\n\nclass BathroomMonitorPlugin\n{\n initialize(registry, store)\n {\n Registry = registry;\n Store = store;\n registry.registerLeftSidebarHeaderComponent(BathroomComponent);\n }\n}\n\nwindow.registerPlugin('com.mattermost.bathroom', new BathroomMonitorPlugin());\n","module.exports = React;"],"sourceRoot":""}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/install_deps.sh b/mattermost/install_deps.sh
new file mode 100644
index 0000000..6a3cec5
--- /dev/null
+++ b/mattermost/install_deps.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+
+sudo apt-get install filepp
diff --git a/mattermost/package.sh b/mattermost/package.sh
new file mode 100644
index 0000000..7253322
--- /dev/null
+++ b/mattermost/package.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+cd "$( dirname "${BASH_SOURCE[0]}" )"
+tar -czvf bathroom.tar.gz plugin.json -C server bathroom-linux-amd64 -C ../webapp/dist main.js
diff --git a/mattermost/plugin.json b/mattermost/plugin.json
new file mode 100644
index 0000000..ba3a186
--- /dev/null
+++ b/mattermost/plugin.json
@@ -0,0 +1,17 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/plugin_templ.json b/mattermost/plugin_templ.json
new file mode 100644
index 0000000..634b204
--- /dev/null
+++ b/mattermost/plugin_templ.json
@@ -0,0 +1,21 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+#ifdef fsnotify
+ {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#else
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#endif
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64
index 681e00f..c478ac9 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 225a000..b3512ab 100644
--- a/mattermost/server/bathroom.go
+++ b/mattermost/server/bathroom.go
@@ -30,6 +30,8 @@
"encoding/base64"
)
+const DO_LOGGING = false
+
var userSplit *regexp.Regexp = regexp.MustCompile(`\s+(^|[^,])|\s*,\s*`)
const (
@@ -139,6 +141,12 @@
}
}
+func (p *BathroomMonitorPlugin) log(log string) {
+ if DO_LOGGING {
+ p.API.LogInfo(log)
+ }
+}
+
func (p *BathroomMonitorPlugin) setDoorStatus(id uint8, status uint, report bool) error {
if id < 1 || id > p.config.numDoors {
return errors.New(fmt.Sprintf("Invalid door id %d", id))
@@ -156,8 +164,12 @@
p.doors[id - 1].status = status
if report {
statusStr, _ := statusName(status)
- p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ _ = statusStr
+ //p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ p.API.PublishWebSocketEvent("updated", map[string]interface{}{}, &model.WebsocketBroadcast{})
}
+ } else {
+ p.log(fmt.Sprintf("Asked to change status from %d to %d ?", p.doors[id - 1].status, status))
}
return nil
@@ -186,12 +198,12 @@
p.configLock.Unlock()
- doorVal, ok := r.Form["door_id"]
- if !ok || len(doorVal) == 0 {
+ doorStr, ok := r.Form["door_id"]
+ if !ok || len(doorStr) == 0 {
return 0, errors.New("Please send door id")
}
- doorId, err := strconv.ParseUint(doorVal[0], 10, 8)
+ doorId, err := strconv.ParseUint(doorStr[0], 10, 8)
if err != nil {
return 0, errors.New(fmt.Sprintf("Couldn't parse door_id: %s", err.Error()))
}
@@ -205,7 +217,7 @@
}
func (p *BathroomMonitorPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
- p.API.LogInfo(fmt.Sprintf("Requested path: %s", r.URL.Path))
+ p.log(fmt.Sprintf("Requested path: %s %s", r.URL.Path, c.IpAddress))
if r.URL.Path == "/status" {
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -224,7 +236,7 @@
}
if r.URL.Path == "/status-update" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
@@ -232,13 +244,13 @@
return
}
- statusVal, ok := r.Form["status"]
- if !ok || len(statusVal) == 0 {
+ statusStr, ok := r.Form["status"]
+ if !ok || len(statusStr) == 0 {
fmt.Fprint(w, "Please send door status")
return
}
- status, err := strconv.ParseUint(statusVal[0], 10, 8)
+ status, err := strconv.ParseUint(statusStr[0], 10, 8)
if err != nil {
fmt.Fprintf(w, "Couldn't parse status: %s", err.Error())
return
@@ -249,6 +261,11 @@
return
}
+ statusVal := Open
+ if status == 1 {
+ statusVal = Closed
+ }
+
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -257,34 +274,34 @@
return
}
- p.API.LogInfo("Getting random bytes")
+ p.log("Getting random bytes")
var verifyBytes [50]byte
rand.Read(verifyBytes[:])
- p.API.LogInfo("Encoding random bytes")
+ p.log("Encoding random bytes")
verifyB64 := base64.StdEncoding.EncodeToString(verifyBytes[:])
- p.API.LogInfo("Encryping random bytes")
+ p.log("Encryping random bytes")
encrypted, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, p.doors[doorId8 - 1].pubKey, verifyBytes[:], []byte{})
if err != nil {
fmt.Fprintf(w, "Couldn't encrypt verification: %s", err.Error())
return
}
- p.API.LogInfo("Encoding encrypted bytes")
+ p.log("Encoding encrypted bytes")
encryptedB64 := base64.StdEncoding.EncodeToString(encrypted)
req := &DoorRequest {
- ip:r.RemoteAddr,
+ ip:c.IpAddress,
time:time.Now().Unix(),
verify:verifyB64,
- status: uint(status),
+ status: statusVal,
}
p.doors[doorId8 - 1].lastRequest = req
- p.API.LogInfo(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
+ p.log(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
fmt.Fprint(w, encryptedB64)
@@ -293,7 +310,7 @@
}
if r.URL.Path == "/verify-status" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
fmt.Fprint(w, err.Error())
@@ -306,8 +323,10 @@
return
}
+ p.log("Verify locking")
p.doorLock.Lock()
defer p.doorLock.Unlock()
+ p.log("Verify done locking")
if p.doors[doorId8 - 1].lastRequest == nil {
fmt.Fprint(w, "Invalid request")
@@ -315,7 +334,7 @@
}
req := p.doors[doorId8 - 1].lastRequest
- if req.ip != r.RemoteAddr {
+ if req.ip != c.IpAddress {
fmt.Fprintf(w, "Not your request %s %s", req.ip, r.RemoteAddr)
return
}
@@ -328,17 +347,20 @@
if req.verify != verifyB64[0] {
+ p.log(fmt.Sprintf("Failed verification %s %s", req.verify, verifyB64[0]))
fmt.Fprint(w, "Unauthorized request")
return
}
- p.doorLock.Lock()
- defer p.doorLock.Unlock()
-
p.doors[doorId8 - 1].lastRequest = nil
- p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changing")
+ err = p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changed")
+ if err != nil {
+ fmt.Fprintf(w, "Couldn't set status %d %d: %s", doorId8, req.status, err.Error())
+ }
return
@@ -463,7 +485,7 @@
p.initDoors()
- p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
+ p.log(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
if configErr != nil {
p.postAdminChannel(configErr.Error())
@@ -562,7 +584,7 @@
}
}
case <- p.configChanged:
- p.API.LogInfo(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
+ p.log(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
run = false
}
}
diff --git a/mattermost/server/bathroom.tar.gz b/mattermost/server/bathroom.tar.gz
deleted file mode 100644
index f2298e9..0000000
--- a/mattermost/server/bathroom.tar.gz
+++ /dev/null
Binary files differ
diff --git a/mattermost/server/build.sh b/mattermost/server/build.sh
index 916a360..c2c1a0e 100755
--- a/mattermost/server/build.sh
+++ b/mattermost/server/build.sh
@@ -1,4 +1,4 @@
#! /usr/bin/env bash
-filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) plugin_templ.json > plugin.json
+filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) ../plugin_templ.json > ../plugin.json
GOOS=linux GOARCH=amd64 go build $( [[ ! -z "$DEFS" ]] && echo -tags $DEFS ) -o bathroom-linux-amd64 bathroom.go $FILES
diff --git a/mattermost/server/package.sh b/mattermost/server/package.sh
deleted file mode 100755
index c8ce874..0000000
--- a/mattermost/server/package.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#! /usr/bin/env bash
-
-tar -czvf bathroom.tar.gz bathroom-linux-amd64 plugin.json
diff --git a/mattermost/server/plugin.json b/mattermost/server/plugin.json
deleted file mode 100644
index e4d22cb..0000000
--- a/mattermost/server/plugin.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "id": "com.mattermost.bathroom",
- "name": "Bathroom Monitor",
- "server": {
- "executable": "bathroom-linux-amd64"
- },
- "settings_schema": {
- "settings": [
- {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
- {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
- {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
- ]
- }
-}
diff --git a/mattermost/server/plugin_templ.json b/mattermost/server/plugin_templ.json
deleted file mode 100644
index 1de221a..0000000
--- a/mattermost/server/plugin_templ.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "id": "com.mattermost.bathroom",
- "name": "Bathroom Monitor",
- "server": {
- "executable": "bathroom-linux-amd64"
- },
- "settings_schema": {
- "settings": [
- {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
-#ifdef fsnotify
- {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
-#else
- {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
-#endif
- {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
- ]
- }
-}
diff --git a/mattermost/webapp/bathroom.tar.gz b/mattermost/webapp/bathroom.tar.gz
new file mode 100644
index 0000000..48d8426
--- /dev/null
+++ b/mattermost/webapp/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/webapp/dist/main.js b/mattermost/webapp/dist/main.js
index 8a0c4f1..4cca171 100644
--- a/mattermost/webapp/dist/main.js
+++ b/mattermost/webapp/dist/main.js
@@ -94,7 +94,121 @@
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-eval("\n\n//# sourceURL=webpack:///./src/index.jsx?");
+
+
+var _react = _interopRequireDefault(__webpack_require__(/*! react */ "react"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+class BathroomComponent extends _react.default.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ doors: {}
+ };
+ }
+
+ componentDidMount() {
+ Registry.registerWebSocketEventHandler("custom_com.mattermost.bathroom_updated", this.updateDoors.bind(this));
+ this.updateDoors();
+ }
+
+ componentWillUnmount() {
+ Registry.unregisterWebSocketEventHandler("custom_com.mattermost.bathroom_updated");
+ }
+
+ async updateDoors(msg) {
+ var url = Store.getState().entities.general.config.SiteURL + "/plugins/com.mattermost.bathroom/status";
+ var res = await fetch(url);
+ var json = await res.json();
+ this.setState({
+ "doors": json
+ });
+ }
+
+ render() {
+ if (!this.state.doors) return;
+ var columns = 6;
+ var keys = Object.keys(this.state.doors).sort();
+ var width = Math.floor(100 / columns) + "%";
+ var widthPx = "23px";
+ var elems = [];
+ var row = [];
+
+ for (var i = 0; i < keys.length
+ /*(Math.floor(keys.length / 6) + 1) * 6*/
+ ; i++) {
+ var img = null;
+
+ if (i < keys.length) {
+ var door = this.state.doors[keys[i]];
+ var imgFile = null;
+
+ switch (door) {
+ default:
+ case "unknown":
+ imgFile = "/static/emoji/2753.png";
+ break;
+
+ case "open":
+ imgFile = "/static/emoji/1f6bd.png";
+ break;
+
+ case "closed":
+ imgFile = "/static/emoji/26d4-fe0f.png";
+ break;
+ }
+
+ img = _react.default.createElement("img", {
+ src: imgFile,
+ width: "100%",
+ style: {
+ "padding": "2px"
+ }
+ });
+ }
+
+ row.push(_react.default.createElement("td", {
+ width: widthPx
+ }, img));
+
+ if (i % columns == columns - 1 || i == keys.length - 1) {
+ elems.push(_react.default.createElement(_react.default.Fragment, null, [...row]));
+ row.length = 0;
+ }
+ }
+
+ return (//
+ _react.default.createElement("div", {
+ style: {
+ "text-align": "center",
+ width: "100%",
+ "padding-top": "10px"
+ }
+ }, _react.default.createElement("table", {
+ style: {
+ "margin-left": "auto",
+ "margin-right": "auto"
+ }
+ }, elems))
+ );
+ }
+
+}
+
+var Registry = null;
+var Store = null;
+
+class BathroomMonitorPlugin {
+ initialize(registry, store) {
+ Registry = registry;
+ Store = store;
+ registry.registerLeftSidebarHeaderComponent(BathroomComponent);
+ }
+
+}
+
+window.registerPlugin('com.mattermost.bathroom', new BathroomMonitorPlugin());
/***/ }),
@@ -105,8 +219,21 @@
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
-eval("module.exports = __webpack_require__(/*! ./src/index.jsx */\"./src/index.jsx\");\n\n\n//# sourceURL=webpack:///multi_./src/index.jsx?");
+module.exports = __webpack_require__(/*! ./src/index.jsx */"./src/index.jsx");
+
+
+/***/ }),
+
+/***/ "react":
+/*!************************!*\
+ !*** external "React" ***!
+ \************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = React;
/***/ })
-/******/ });
\ No newline at end of file
+/******/ });
+//# sourceMappingURL=main.js.map
\ No newline at end of file
diff --git a/mattermost/webapp/dist/main.js.map b/mattermost/webapp/dist/main.js.map
new file mode 100644
index 0000000..26114e4
--- /dev/null
+++ b/mattermost/webapp/dist/main.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/index.jsx","webpack:///external \"React\""],"names":["BathroomComponent","React","Component","constructor","props","state","doors","componentDidMount","Registry","registerWebSocketEventHandler","updateDoors","bind","componentWillUnmount","unregisterWebSocketEventHandler","msg","url","Store","getState","entities","general","config","SiteURL","res","fetch","json","setState","render","columns","keys","Object","sort","width","Math","floor","widthPx","elems","row","i","length","img","door","imgFile","push","BathroomMonitorPlugin","initialize","registry","store","registerLeftSidebarHeaderComponent","window","registerPlugin"],"mappings":";QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;;;;AClFA;;;;AAEA,MAAMA,iBAAN,SAAgCC,eAAMC,SAAtC,CACA;AACIC,aAAW,CAACC,KAAD,EACX;AACI,UAAMA,KAAN;AACA,SAAKC,KAAL,GAAa;AAACC,WAAK,EAAC;AAAP,KAAb;AACH;;AACDC,mBAAiB,GACjB;AACIC,YAAQ,CAACC,6BAAT,CAAuC,wCAAvC,EAAiF,KAAKC,WAAL,CAAiBC,IAAjB,CAAsB,IAAtB,CAAjF;AACA,SAAKD,WAAL;AACH;;AACDE,sBAAoB,GACpB;AACIJ,YAAQ,CAACK,+BAAT,CAAyC,wCAAzC;AACH;;AACD,QAAMH,WAAN,CAAkBI,GAAlB,EACA;AACI,QAAIC,GAAG,GAAGC,KAAK,CAACC,QAAN,GAAiBC,QAAjB,CAA0BC,OAA1B,CAAkCC,MAAlC,CAAyCC,OAAzC,GAAmD,yCAA7D;AACA,QAAIC,GAAG,GAAG,MAAMC,KAAK,CAACR,GAAD,CAArB;AACA,QAAIS,IAAI,GAAG,MAAMF,GAAG,CAACE,IAAJ,EAAjB;AACA,SAAKC,QAAL,CAAc;AAAC,eAAQD;AAAT,KAAd;AACH;;AACDE,QAAM,GACN;AACI,QAAI,CAAC,KAAKrB,KAAL,CAAWC,KAAhB,EAAuB;AACvB,QAAIqB,OAAO,GAAG,CAAd;AACA,QAAIC,IAAI,GAAGC,MAAM,CAACD,IAAP,CAAY,KAAKvB,KAAL,CAAWC,KAAvB,EAA8BwB,IAA9B,EAAX;AACA,QAAIC,KAAK,GAAIC,IAAI,CAACC,KAAL,CAAW,MAAMN,OAAjB,CAAD,GAA8B,GAA1C;AACA,QAAIO,OAAO,GAAG,MAAd;AACA,QAAIC,KAAK,GAAG,EAAZ;AACA,QAAIC,GAAG,GAAG,EAAV;;AACA,SAAK,IAAIC,CAAC,GAAG,CAAb,EAAgBA,CAAC,GAAGT,IAAI,CAACU;AAAO;AAAhC,MAA2ED,CAAC,EAA5E,EACA;AACI,UAAIE,GAAG,GAAG,IAAV;;AACA,UAAIF,CAAC,GAAGT,IAAI,CAACU,MAAb,EACA;AACI,YAAIE,IAAI,GAAG,KAAKnC,KAAL,CAAWC,KAAX,CAAiBsB,IAAI,CAACS,CAAD,CAArB,CAAX;AACA,YAAII,OAAO,GAAG,IAAd;;AACA,gBAAQD,IAAR;AAEI;AACA,eAAK,SAAL;AACIC,mBAAO,GAAG,wBAAV;AACA;;AACJ,eAAK,MAAL;AACIA,mBAAO,GAAG,yBAAV;AACA;;AACJ,eAAK,QAAL;AACIA,mBAAO,GAAG,6BAAV;AACA;AAXR;;AAaAF,WAAG,GAAG;AAAK,aAAG,EAAEE,OAAV;AAAmB,eAAK,EAAC,MAAzB;AAAgC,eAAK,EAAE;AAAC,uBAAU;AAAX;AAAvC,UAAN;AACH;;AACDL,SAAG,CAACM,IAAJ,CAAS;AAAI,aAAK,EAAER;AAAX,SAAqBK,GAArB,CAAT;;AACA,UAAIF,CAAC,GAAGV,OAAJ,IAAeA,OAAO,GAAG,CAAzB,IAA8BU,CAAC,IAAIT,IAAI,CAACU,MAAL,GAAc,CAArD,EACA;AACIH,aAAK,CAACO,IAAN,CAAW,6BAAC,cAAD,CAAO,QAAP,QAAiB,CAAC,GAAGN,GAAJ,CAAjB,CAAX;AACAA,WAAG,CAACE,MAAJ,GAAa,CAAb;AACH;AACJ;;AACD,WACI;AACA;AAAK,aAAK,EAAE;AAAC,wBAAc,QAAf;AAAyBP,eAAK,EAAC,MAA/B;AAAuC,yBAAc;AAArD;AAAZ,SACA;AAAO,aAAK,EAAE;AAAC,yBAAc,MAAf;AAAuB,0BAAe;AAAtC;AAAd,SACCI,KADD,CADA;AAFJ;AAQH;;AApEL;;AAuEA,IAAI3B,QAAQ,GAAG,IAAf;AACA,IAAIQ,KAAK,GAAG,IAAZ;;AAEA,MAAM2B,qBAAN,CACA;AACIC,YAAU,CAACC,QAAD,EAAWC,KAAX,EACV;AACItC,YAAQ,GAAGqC,QAAX;AACA7B,SAAK,GAAG8B,KAAR;AACAD,YAAQ,CAACE,kCAAT,CAA4C/C,iBAA5C;AACH;;AANL;;AASAgD,MAAM,CAACC,cAAP,CAAsB,yBAAtB,EAAiD,IAAIN,qBAAJ,EAAjD,E;;;;;;;;;;;;;;;;;;;;;;;ACvFA,uB","file":"main.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","import React from 'react';\n\nclass BathroomComponent extends React.Component\n{\n constructor(props)\n {\n super(props);\n this.state = {doors:{}};\n }\n componentDidMount()\n {\n Registry.registerWebSocketEventHandler(\"custom_com.mattermost.bathroom_updated\", this.updateDoors.bind(this));\n this.updateDoors();\n }\n componentWillUnmount()\n {\n Registry.unregisterWebSocketEventHandler(\"custom_com.mattermost.bathroom_updated\");\n }\n async updateDoors(msg)\n {\n var url = Store.getState().entities.general.config.SiteURL + \"/plugins/com.mattermost.bathroom/status\";\n var res = await fetch(url);\n var json = await res.json();\n this.setState({\"doors\":json});\n }\n render()\n {\n if (!this.state.doors) return;\n var columns = 6;\n var keys = Object.keys(this.state.doors).sort();\n var width = (Math.floor(100 / columns)) + \"%\";\n var widthPx = \"23px\";\n var elems = [];\n var row = [];\n for (var i = 0; i < keys.length /*(Math.floor(keys.length / 6) + 1) * 6*/; i++)\n {\n var img = null;\n if (i < keys.length)\n {\n var door = this.state.doors[keys[i]];\n var imgFile = null;\n switch (door)\n {\n default:\n case \"unknown\":\n imgFile = \"/static/emoji/2753.png\";\n break;\n case \"open\":\n imgFile = \"/static/emoji/1f6bd.png\";\n break;\n case \"closed\":\n imgFile = \"/static/emoji/26d4-fe0f.png\";\n break;\n }\n img =
\n }\n row.push({img} | );\n if (i % columns == columns - 1 || i == keys.length - 1)\n {\n elems.push({[...row]});\n row.length = 0;\n }\n }\n return (\n //\n \n );\n }\n}\n\nvar Registry = null;\nvar Store = null;\n\nclass BathroomMonitorPlugin\n{\n initialize(registry, store)\n {\n Registry = registry;\n Store = store;\n registry.registerLeftSidebarHeaderComponent(BathroomComponent);\n }\n}\n\nwindow.registerPlugin('com.mattermost.bathroom', new BathroomMonitorPlugin());\n","module.exports = React;"],"sourceRoot":""}
\ No newline at end of file
diff --git a/mattermost/webapp/src/index.jsx b/mattermost/webapp/src/index.jsx
index e69de29..0868e33 100644
--- a/mattermost/webapp/src/index.jsx
+++ b/mattermost/webapp/src/index.jsx
@@ -0,0 +1,88 @@
+import React from 'react';
+
+class BathroomComponent extends React.Component
+{
+ constructor(props)
+ {
+ super(props);
+ this.state = {doors:{}};
+ }
+ componentDidMount()
+ {
+ Registry.registerWebSocketEventHandler("custom_com.mattermost.bathroom_updated", this.updateDoors.bind(this));
+ this.updateDoors();
+ }
+ componentWillUnmount()
+ {
+ Registry.unregisterWebSocketEventHandler("custom_com.mattermost.bathroom_updated");
+ }
+ async updateDoors(msg)
+ {
+ var url = Store.getState().entities.general.config.SiteURL + "/plugins/com.mattermost.bathroom/status";
+ var res = await fetch(url);
+ var json = await res.json();
+ this.setState({"doors":json});
+ }
+ render()
+ {
+ if (!this.state.doors) return;
+ var columns = 6;
+ var keys = Object.keys(this.state.doors).sort();
+ var width = (Math.floor(100 / columns)) + "%";
+ var widthPx = "23px";
+ var elems = [];
+ var row = [];
+ for (var i = 0; i < keys.length /*(Math.floor(keys.length / 6) + 1) * 6*/; i++)
+ {
+ var img = null;
+ if (i < keys.length)
+ {
+ var door = this.state.doors[keys[i]];
+ var imgFile = null;
+ switch (door)
+ {
+ default:
+ case "unknown":
+ imgFile = "/static/emoji/2753.png";
+ break;
+ case "open":
+ imgFile = "/static/emoji/1f6bd.png";
+ break;
+ case "closed":
+ imgFile = "/static/emoji/26d4-fe0f.png";
+ break;
+ }
+ img =
+ }
+ row.push({img} | );
+ if (i % columns == columns - 1 || i == keys.length - 1)
+ {
+ elems.push({[...row]});
+ row.length = 0;
+ }
+ }
+ return (
+ //
+
+ );
+ }
+}
+
+var Registry = null;
+var Store = null;
+
+class BathroomMonitorPlugin
+{
+ initialize(registry, store)
+ {
+ Registry = registry;
+ Store = store;
+ registry.registerLeftSidebarHeaderComponent(BathroomComponent);
+ }
+}
+
+window.registerPlugin('com.mattermost.bathroom', new BathroomMonitorPlugin());
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/install_deps.sh b/mattermost/install_deps.sh
new file mode 100644
index 0000000..6a3cec5
--- /dev/null
+++ b/mattermost/install_deps.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+
+sudo apt-get install filepp
diff --git a/mattermost/package.sh b/mattermost/package.sh
new file mode 100644
index 0000000..7253322
--- /dev/null
+++ b/mattermost/package.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+cd "$( dirname "${BASH_SOURCE[0]}" )"
+tar -czvf bathroom.tar.gz plugin.json -C server bathroom-linux-amd64 -C ../webapp/dist main.js
diff --git a/mattermost/plugin.json b/mattermost/plugin.json
new file mode 100644
index 0000000..ba3a186
--- /dev/null
+++ b/mattermost/plugin.json
@@ -0,0 +1,17 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/plugin_templ.json b/mattermost/plugin_templ.json
new file mode 100644
index 0000000..634b204
--- /dev/null
+++ b/mattermost/plugin_templ.json
@@ -0,0 +1,21 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+#ifdef fsnotify
+ {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#else
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#endif
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64
index 681e00f..c478ac9 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 225a000..b3512ab 100644
--- a/mattermost/server/bathroom.go
+++ b/mattermost/server/bathroom.go
@@ -30,6 +30,8 @@
"encoding/base64"
)
+const DO_LOGGING = false
+
var userSplit *regexp.Regexp = regexp.MustCompile(`\s+(^|[^,])|\s*,\s*`)
const (
@@ -139,6 +141,12 @@
}
}
+func (p *BathroomMonitorPlugin) log(log string) {
+ if DO_LOGGING {
+ p.API.LogInfo(log)
+ }
+}
+
func (p *BathroomMonitorPlugin) setDoorStatus(id uint8, status uint, report bool) error {
if id < 1 || id > p.config.numDoors {
return errors.New(fmt.Sprintf("Invalid door id %d", id))
@@ -156,8 +164,12 @@
p.doors[id - 1].status = status
if report {
statusStr, _ := statusName(status)
- p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ _ = statusStr
+ //p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ p.API.PublishWebSocketEvent("updated", map[string]interface{}{}, &model.WebsocketBroadcast{})
}
+ } else {
+ p.log(fmt.Sprintf("Asked to change status from %d to %d ?", p.doors[id - 1].status, status))
}
return nil
@@ -186,12 +198,12 @@
p.configLock.Unlock()
- doorVal, ok := r.Form["door_id"]
- if !ok || len(doorVal) == 0 {
+ doorStr, ok := r.Form["door_id"]
+ if !ok || len(doorStr) == 0 {
return 0, errors.New("Please send door id")
}
- doorId, err := strconv.ParseUint(doorVal[0], 10, 8)
+ doorId, err := strconv.ParseUint(doorStr[0], 10, 8)
if err != nil {
return 0, errors.New(fmt.Sprintf("Couldn't parse door_id: %s", err.Error()))
}
@@ -205,7 +217,7 @@
}
func (p *BathroomMonitorPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
- p.API.LogInfo(fmt.Sprintf("Requested path: %s", r.URL.Path))
+ p.log(fmt.Sprintf("Requested path: %s %s", r.URL.Path, c.IpAddress))
if r.URL.Path == "/status" {
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -224,7 +236,7 @@
}
if r.URL.Path == "/status-update" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
@@ -232,13 +244,13 @@
return
}
- statusVal, ok := r.Form["status"]
- if !ok || len(statusVal) == 0 {
+ statusStr, ok := r.Form["status"]
+ if !ok || len(statusStr) == 0 {
fmt.Fprint(w, "Please send door status")
return
}
- status, err := strconv.ParseUint(statusVal[0], 10, 8)
+ status, err := strconv.ParseUint(statusStr[0], 10, 8)
if err != nil {
fmt.Fprintf(w, "Couldn't parse status: %s", err.Error())
return
@@ -249,6 +261,11 @@
return
}
+ statusVal := Open
+ if status == 1 {
+ statusVal = Closed
+ }
+
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -257,34 +274,34 @@
return
}
- p.API.LogInfo("Getting random bytes")
+ p.log("Getting random bytes")
var verifyBytes [50]byte
rand.Read(verifyBytes[:])
- p.API.LogInfo("Encoding random bytes")
+ p.log("Encoding random bytes")
verifyB64 := base64.StdEncoding.EncodeToString(verifyBytes[:])
- p.API.LogInfo("Encryping random bytes")
+ p.log("Encryping random bytes")
encrypted, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, p.doors[doorId8 - 1].pubKey, verifyBytes[:], []byte{})
if err != nil {
fmt.Fprintf(w, "Couldn't encrypt verification: %s", err.Error())
return
}
- p.API.LogInfo("Encoding encrypted bytes")
+ p.log("Encoding encrypted bytes")
encryptedB64 := base64.StdEncoding.EncodeToString(encrypted)
req := &DoorRequest {
- ip:r.RemoteAddr,
+ ip:c.IpAddress,
time:time.Now().Unix(),
verify:verifyB64,
- status: uint(status),
+ status: statusVal,
}
p.doors[doorId8 - 1].lastRequest = req
- p.API.LogInfo(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
+ p.log(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
fmt.Fprint(w, encryptedB64)
@@ -293,7 +310,7 @@
}
if r.URL.Path == "/verify-status" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
fmt.Fprint(w, err.Error())
@@ -306,8 +323,10 @@
return
}
+ p.log("Verify locking")
p.doorLock.Lock()
defer p.doorLock.Unlock()
+ p.log("Verify done locking")
if p.doors[doorId8 - 1].lastRequest == nil {
fmt.Fprint(w, "Invalid request")
@@ -315,7 +334,7 @@
}
req := p.doors[doorId8 - 1].lastRequest
- if req.ip != r.RemoteAddr {
+ if req.ip != c.IpAddress {
fmt.Fprintf(w, "Not your request %s %s", req.ip, r.RemoteAddr)
return
}
@@ -328,17 +347,20 @@
if req.verify != verifyB64[0] {
+ p.log(fmt.Sprintf("Failed verification %s %s", req.verify, verifyB64[0]))
fmt.Fprint(w, "Unauthorized request")
return
}
- p.doorLock.Lock()
- defer p.doorLock.Unlock()
-
p.doors[doorId8 - 1].lastRequest = nil
- p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changing")
+ err = p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changed")
+ if err != nil {
+ fmt.Fprintf(w, "Couldn't set status %d %d: %s", doorId8, req.status, err.Error())
+ }
return
@@ -463,7 +485,7 @@
p.initDoors()
- p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
+ p.log(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
if configErr != nil {
p.postAdminChannel(configErr.Error())
@@ -562,7 +584,7 @@
}
}
case <- p.configChanged:
- p.API.LogInfo(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
+ p.log(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
run = false
}
}
diff --git a/mattermost/server/bathroom.tar.gz b/mattermost/server/bathroom.tar.gz
deleted file mode 100644
index f2298e9..0000000
--- a/mattermost/server/bathroom.tar.gz
+++ /dev/null
Binary files differ
diff --git a/mattermost/server/build.sh b/mattermost/server/build.sh
index 916a360..c2c1a0e 100755
--- a/mattermost/server/build.sh
+++ b/mattermost/server/build.sh
@@ -1,4 +1,4 @@
#! /usr/bin/env bash
-filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) plugin_templ.json > plugin.json
+filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) ../plugin_templ.json > ../plugin.json
GOOS=linux GOARCH=amd64 go build $( [[ ! -z "$DEFS" ]] && echo -tags $DEFS ) -o bathroom-linux-amd64 bathroom.go $FILES
diff --git a/mattermost/server/package.sh b/mattermost/server/package.sh
deleted file mode 100755
index c8ce874..0000000
--- a/mattermost/server/package.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#! /usr/bin/env bash
-
-tar -czvf bathroom.tar.gz bathroom-linux-amd64 plugin.json
diff --git a/mattermost/server/plugin.json b/mattermost/server/plugin.json
deleted file mode 100644
index e4d22cb..0000000
--- a/mattermost/server/plugin.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "id": "com.mattermost.bathroom",
- "name": "Bathroom Monitor",
- "server": {
- "executable": "bathroom-linux-amd64"
- },
- "settings_schema": {
- "settings": [
- {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
- {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
- {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
- ]
- }
-}
diff --git a/mattermost/server/plugin_templ.json b/mattermost/server/plugin_templ.json
deleted file mode 100644
index 1de221a..0000000
--- a/mattermost/server/plugin_templ.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "id": "com.mattermost.bathroom",
- "name": "Bathroom Monitor",
- "server": {
- "executable": "bathroom-linux-amd64"
- },
- "settings_schema": {
- "settings": [
- {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
-#ifdef fsnotify
- {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
-#else
- {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
-#endif
- {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
- ]
- }
-}
diff --git a/mattermost/webapp/bathroom.tar.gz b/mattermost/webapp/bathroom.tar.gz
new file mode 100644
index 0000000..48d8426
--- /dev/null
+++ b/mattermost/webapp/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/webapp/dist/main.js b/mattermost/webapp/dist/main.js
index 8a0c4f1..4cca171 100644
--- a/mattermost/webapp/dist/main.js
+++ b/mattermost/webapp/dist/main.js
@@ -94,7 +94,121 @@
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-eval("\n\n//# sourceURL=webpack:///./src/index.jsx?");
+
+
+var _react = _interopRequireDefault(__webpack_require__(/*! react */ "react"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+class BathroomComponent extends _react.default.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ doors: {}
+ };
+ }
+
+ componentDidMount() {
+ Registry.registerWebSocketEventHandler("custom_com.mattermost.bathroom_updated", this.updateDoors.bind(this));
+ this.updateDoors();
+ }
+
+ componentWillUnmount() {
+ Registry.unregisterWebSocketEventHandler("custom_com.mattermost.bathroom_updated");
+ }
+
+ async updateDoors(msg) {
+ var url = Store.getState().entities.general.config.SiteURL + "/plugins/com.mattermost.bathroom/status";
+ var res = await fetch(url);
+ var json = await res.json();
+ this.setState({
+ "doors": json
+ });
+ }
+
+ render() {
+ if (!this.state.doors) return;
+ var columns = 6;
+ var keys = Object.keys(this.state.doors).sort();
+ var width = Math.floor(100 / columns) + "%";
+ var widthPx = "23px";
+ var elems = [];
+ var row = [];
+
+ for (var i = 0; i < keys.length
+ /*(Math.floor(keys.length / 6) + 1) * 6*/
+ ; i++) {
+ var img = null;
+
+ if (i < keys.length) {
+ var door = this.state.doors[keys[i]];
+ var imgFile = null;
+
+ switch (door) {
+ default:
+ case "unknown":
+ imgFile = "/static/emoji/2753.png";
+ break;
+
+ case "open":
+ imgFile = "/static/emoji/1f6bd.png";
+ break;
+
+ case "closed":
+ imgFile = "/static/emoji/26d4-fe0f.png";
+ break;
+ }
+
+ img = _react.default.createElement("img", {
+ src: imgFile,
+ width: "100%",
+ style: {
+ "padding": "2px"
+ }
+ });
+ }
+
+ row.push(_react.default.createElement("td", {
+ width: widthPx
+ }, img));
+
+ if (i % columns == columns - 1 || i == keys.length - 1) {
+ elems.push(_react.default.createElement(_react.default.Fragment, null, [...row]));
+ row.length = 0;
+ }
+ }
+
+ return (//
+ _react.default.createElement("div", {
+ style: {
+ "text-align": "center",
+ width: "100%",
+ "padding-top": "10px"
+ }
+ }, _react.default.createElement("table", {
+ style: {
+ "margin-left": "auto",
+ "margin-right": "auto"
+ }
+ }, elems))
+ );
+ }
+
+}
+
+var Registry = null;
+var Store = null;
+
+class BathroomMonitorPlugin {
+ initialize(registry, store) {
+ Registry = registry;
+ Store = store;
+ registry.registerLeftSidebarHeaderComponent(BathroomComponent);
+ }
+
+}
+
+window.registerPlugin('com.mattermost.bathroom', new BathroomMonitorPlugin());
/***/ }),
@@ -105,8 +219,21 @@
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
-eval("module.exports = __webpack_require__(/*! ./src/index.jsx */\"./src/index.jsx\");\n\n\n//# sourceURL=webpack:///multi_./src/index.jsx?");
+module.exports = __webpack_require__(/*! ./src/index.jsx */"./src/index.jsx");
+
+
+/***/ }),
+
+/***/ "react":
+/*!************************!*\
+ !*** external "React" ***!
+ \************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = React;
/***/ })
-/******/ });
\ No newline at end of file
+/******/ });
+//# sourceMappingURL=main.js.map
\ No newline at end of file
diff --git a/mattermost/webapp/dist/main.js.map b/mattermost/webapp/dist/main.js.map
new file mode 100644
index 0000000..26114e4
--- /dev/null
+++ b/mattermost/webapp/dist/main.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/index.jsx","webpack:///external \"React\""],"names":["BathroomComponent","React","Component","constructor","props","state","doors","componentDidMount","Registry","registerWebSocketEventHandler","updateDoors","bind","componentWillUnmount","unregisterWebSocketEventHandler","msg","url","Store","getState","entities","general","config","SiteURL","res","fetch","json","setState","render","columns","keys","Object","sort","width","Math","floor","widthPx","elems","row","i","length","img","door","imgFile","push","BathroomMonitorPlugin","initialize","registry","store","registerLeftSidebarHeaderComponent","window","registerPlugin"],"mappings":"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","file":"main.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","import React from 'react';\n\nclass BathroomComponent extends React.Component\n{\n constructor(props)\n {\n super(props);\n this.state = {doors:{}};\n }\n componentDidMount()\n {\n Registry.registerWebSocketEventHandler(\"custom_com.mattermost.bathroom_updated\", this.updateDoors.bind(this));\n this.updateDoors();\n }\n componentWillUnmount()\n {\n Registry.unregisterWebSocketEventHandler(\"custom_com.mattermost.bathroom_updated\");\n }\n async updateDoors(msg)\n {\n var url = Store.getState().entities.general.config.SiteURL + \"/plugins/com.mattermost.bathroom/status\";\n var res = await fetch(url);\n var json = await res.json();\n this.setState({\"doors\":json});\n }\n render()\n {\n if (!this.state.doors) return;\n var columns = 6;\n var keys = Object.keys(this.state.doors).sort();\n var width = (Math.floor(100 / columns)) + \"%\";\n var widthPx = \"23px\";\n var elems = [];\n var row = [];\n for (var i = 0; i < keys.length /*(Math.floor(keys.length / 6) + 1) * 6*/; i++)\n {\n var img = null;\n if (i < keys.length)\n {\n var door = this.state.doors[keys[i]];\n var imgFile = null;\n switch (door)\n {\n default:\n case \"unknown\":\n imgFile = \"/static/emoji/2753.png\";\n break;\n case \"open\":\n imgFile = \"/static/emoji/1f6bd.png\";\n break;\n case \"closed\":\n imgFile = \"/static/emoji/26d4-fe0f.png\";\n break;\n }\n img =
\n }\n row.push({img} | );\n if (i % columns == columns - 1 || i == keys.length - 1)\n {\n elems.push({[...row]});\n row.length = 0;\n }\n }\n return (\n //\n \n );\n }\n}\n\nvar Registry = null;\nvar Store = null;\n\nclass BathroomMonitorPlugin\n{\n initialize(registry, store)\n {\n Registry = registry;\n Store = store;\n registry.registerLeftSidebarHeaderComponent(BathroomComponent);\n }\n}\n\nwindow.registerPlugin('com.mattermost.bathroom', new BathroomMonitorPlugin());\n","module.exports = React;"],"sourceRoot":""}
\ No newline at end of file
diff --git a/mattermost/webapp/src/index.jsx b/mattermost/webapp/src/index.jsx
index e69de29..0868e33 100644
--- a/mattermost/webapp/src/index.jsx
+++ b/mattermost/webapp/src/index.jsx
@@ -0,0 +1,88 @@
+import React from 'react';
+
+class BathroomComponent extends React.Component
+{
+ constructor(props)
+ {
+ super(props);
+ this.state = {doors:{}};
+ }
+ componentDidMount()
+ {
+ Registry.registerWebSocketEventHandler("custom_com.mattermost.bathroom_updated", this.updateDoors.bind(this));
+ this.updateDoors();
+ }
+ componentWillUnmount()
+ {
+ Registry.unregisterWebSocketEventHandler("custom_com.mattermost.bathroom_updated");
+ }
+ async updateDoors(msg)
+ {
+ var url = Store.getState().entities.general.config.SiteURL + "/plugins/com.mattermost.bathroom/status";
+ var res = await fetch(url);
+ var json = await res.json();
+ this.setState({"doors":json});
+ }
+ render()
+ {
+ if (!this.state.doors) return;
+ var columns = 6;
+ var keys = Object.keys(this.state.doors).sort();
+ var width = (Math.floor(100 / columns)) + "%";
+ var widthPx = "23px";
+ var elems = [];
+ var row = [];
+ for (var i = 0; i < keys.length /*(Math.floor(keys.length / 6) + 1) * 6*/; i++)
+ {
+ var img = null;
+ if (i < keys.length)
+ {
+ var door = this.state.doors[keys[i]];
+ var imgFile = null;
+ switch (door)
+ {
+ default:
+ case "unknown":
+ imgFile = "/static/emoji/2753.png";
+ break;
+ case "open":
+ imgFile = "/static/emoji/1f6bd.png";
+ break;
+ case "closed":
+ imgFile = "/static/emoji/26d4-fe0f.png";
+ break;
+ }
+ img =
+ }
+ row.push({img} | );
+ if (i % columns == columns - 1 || i == keys.length - 1)
+ {
+ elems.push({[...row]});
+ row.length = 0;
+ }
+ }
+ return (
+ //
+
+ );
+ }
+}
+
+var Registry = null;
+var Store = null;
+
+class BathroomMonitorPlugin
+{
+ initialize(registry, store)
+ {
+ Registry = registry;
+ Store = store;
+ registry.registerLeftSidebarHeaderComponent(BathroomComponent);
+ }
+}
+
+window.registerPlugin('com.mattermost.bathroom', new BathroomMonitorPlugin());
diff --git a/mattermost/webapp/webpack.config.js b/mattermost/webapp/webpack.config.js
index 57121e1..b7e2419 100644
--- a/mattermost/webapp/webpack.config.js
+++ b/mattermost/webapp/webpack.config.js
@@ -4,6 +4,7 @@
entry: [
'./src/index.jsx',
],
+ devtool: 'source-map',
resolve: {
modules: [
'src',
diff --git a/.gitignore b/.gitignore
index 1377554..3819313 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.swp
+*.swo
diff --git a/mattermost/bathroom.tar.gz b/mattermost/bathroom.tar.gz
new file mode 100644
index 0000000..246e3c9
--- /dev/null
+++ b/mattermost/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/install_deps.sh b/mattermost/install_deps.sh
new file mode 100644
index 0000000..6a3cec5
--- /dev/null
+++ b/mattermost/install_deps.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+
+sudo apt-get install filepp
diff --git a/mattermost/package.sh b/mattermost/package.sh
new file mode 100644
index 0000000..7253322
--- /dev/null
+++ b/mattermost/package.sh
@@ -0,0 +1,3 @@
+#! /usr/bin/env bash
+cd "$( dirname "${BASH_SOURCE[0]}" )"
+tar -czvf bathroom.tar.gz plugin.json -C server bathroom-linux-amd64 -C ../webapp/dist main.js
diff --git a/mattermost/plugin.json b/mattermost/plugin.json
new file mode 100644
index 0000000..ba3a186
--- /dev/null
+++ b/mattermost/plugin.json
@@ -0,0 +1,17 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/plugin_templ.json b/mattermost/plugin_templ.json
new file mode 100644
index 0000000..634b204
--- /dev/null
+++ b/mattermost/plugin_templ.json
@@ -0,0 +1,21 @@
+{
+ "id": "com.mattermost.bathroom",
+ "name": "Bathroom Monitor",
+ "server": {
+ "executable": "bathroom-linux-amd64"
+ },
+ "webapp": {
+ "bundle_path": "main.js"
+ },
+ "settings_schema": {
+ "settings": [
+ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
+#ifdef fsnotify
+ {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#else
+ {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
+#endif
+ {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
+ ]
+ }
+}
diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64
index 681e00f..c478ac9 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 225a000..b3512ab 100644
--- a/mattermost/server/bathroom.go
+++ b/mattermost/server/bathroom.go
@@ -30,6 +30,8 @@
"encoding/base64"
)
+const DO_LOGGING = false
+
var userSplit *regexp.Regexp = regexp.MustCompile(`\s+(^|[^,])|\s*,\s*`)
const (
@@ -139,6 +141,12 @@
}
}
+func (p *BathroomMonitorPlugin) log(log string) {
+ if DO_LOGGING {
+ p.API.LogInfo(log)
+ }
+}
+
func (p *BathroomMonitorPlugin) setDoorStatus(id uint8, status uint, report bool) error {
if id < 1 || id > p.config.numDoors {
return errors.New(fmt.Sprintf("Invalid door id %d", id))
@@ -156,8 +164,12 @@
p.doors[id - 1].status = status
if report {
statusStr, _ := statusName(status)
- p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ _ = statusStr
+ //p.postAdminChannel(fmt.Sprintf("STATUS: door %d = %s", id, statusStr))
+ p.API.PublishWebSocketEvent("updated", map[string]interface{}{}, &model.WebsocketBroadcast{})
}
+ } else {
+ p.log(fmt.Sprintf("Asked to change status from %d to %d ?", p.doors[id - 1].status, status))
}
return nil
@@ -186,12 +198,12 @@
p.configLock.Unlock()
- doorVal, ok := r.Form["door_id"]
- if !ok || len(doorVal) == 0 {
+ doorStr, ok := r.Form["door_id"]
+ if !ok || len(doorStr) == 0 {
return 0, errors.New("Please send door id")
}
- doorId, err := strconv.ParseUint(doorVal[0], 10, 8)
+ doorId, err := strconv.ParseUint(doorStr[0], 10, 8)
if err != nil {
return 0, errors.New(fmt.Sprintf("Couldn't parse door_id: %s", err.Error()))
}
@@ -205,7 +217,7 @@
}
func (p *BathroomMonitorPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
- p.API.LogInfo(fmt.Sprintf("Requested path: %s", r.URL.Path))
+ p.log(fmt.Sprintf("Requested path: %s %s", r.URL.Path, c.IpAddress))
if r.URL.Path == "/status" {
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -224,7 +236,7 @@
}
if r.URL.Path == "/status-update" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
@@ -232,13 +244,13 @@
return
}
- statusVal, ok := r.Form["status"]
- if !ok || len(statusVal) == 0 {
+ statusStr, ok := r.Form["status"]
+ if !ok || len(statusStr) == 0 {
fmt.Fprint(w, "Please send door status")
return
}
- status, err := strconv.ParseUint(statusVal[0], 10, 8)
+ status, err := strconv.ParseUint(statusStr[0], 10, 8)
if err != nil {
fmt.Fprintf(w, "Couldn't parse status: %s", err.Error())
return
@@ -249,6 +261,11 @@
return
}
+ statusVal := Open
+ if status == 1 {
+ statusVal = Closed
+ }
+
p.doorLock.Lock()
defer p.doorLock.Unlock()
@@ -257,34 +274,34 @@
return
}
- p.API.LogInfo("Getting random bytes")
+ p.log("Getting random bytes")
var verifyBytes [50]byte
rand.Read(verifyBytes[:])
- p.API.LogInfo("Encoding random bytes")
+ p.log("Encoding random bytes")
verifyB64 := base64.StdEncoding.EncodeToString(verifyBytes[:])
- p.API.LogInfo("Encryping random bytes")
+ p.log("Encryping random bytes")
encrypted, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, p.doors[doorId8 - 1].pubKey, verifyBytes[:], []byte{})
if err != nil {
fmt.Fprintf(w, "Couldn't encrypt verification: %s", err.Error())
return
}
- p.API.LogInfo("Encoding encrypted bytes")
+ p.log("Encoding encrypted bytes")
encryptedB64 := base64.StdEncoding.EncodeToString(encrypted)
req := &DoorRequest {
- ip:r.RemoteAddr,
+ ip:c.IpAddress,
time:time.Now().Unix(),
verify:verifyB64,
- status: uint(status),
+ status: statusVal,
}
p.doors[doorId8 - 1].lastRequest = req
- p.API.LogInfo(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
+ p.log(fmt.Sprintf("NEW REQUEST SAVED: %s %d %s", req.ip, req.time, req.verify))
fmt.Fprint(w, encryptedB64)
@@ -293,7 +310,7 @@
}
if r.URL.Path == "/verify-status" {
r.ParseForm()
- p.API.LogInfo("Contacted by " + r.RemoteAddr)
+ p.log("Contacted by " + r.RemoteAddr)
doorId8, err := p.validateRequestDoorId(r)
if err != nil {
fmt.Fprint(w, err.Error())
@@ -306,8 +323,10 @@
return
}
+ p.log("Verify locking")
p.doorLock.Lock()
defer p.doorLock.Unlock()
+ p.log("Verify done locking")
if p.doors[doorId8 - 1].lastRequest == nil {
fmt.Fprint(w, "Invalid request")
@@ -315,7 +334,7 @@
}
req := p.doors[doorId8 - 1].lastRequest
- if req.ip != r.RemoteAddr {
+ if req.ip != c.IpAddress {
fmt.Fprintf(w, "Not your request %s %s", req.ip, r.RemoteAddr)
return
}
@@ -328,17 +347,20 @@
if req.verify != verifyB64[0] {
+ p.log(fmt.Sprintf("Failed verification %s %s", req.verify, verifyB64[0]))
fmt.Fprint(w, "Unauthorized request")
return
}
- p.doorLock.Lock()
- defer p.doorLock.Unlock()
-
p.doors[doorId8 - 1].lastRequest = nil
- p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changing")
+ err = p.setDoorStatus(doorId8, req.status, true)
+ p.log("Changed")
+ if err != nil {
+ fmt.Fprintf(w, "Couldn't set status %d %d: %s", doorId8, req.status, err.Error())
+ }
return
@@ -463,7 +485,7 @@
p.initDoors()
- p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
+ p.log(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath))
if configErr != nil {
p.postAdminChannel(configErr.Error())
@@ -562,7 +584,7 @@
}
}
case <- p.configChanged:
- p.API.LogInfo(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
+ p.log(fmt.Sprintf("CONFIG CHANGED, RESTARTING %d", p.configUpdates))
run = false
}
}
diff --git a/mattermost/server/bathroom.tar.gz b/mattermost/server/bathroom.tar.gz
deleted file mode 100644
index f2298e9..0000000
--- a/mattermost/server/bathroom.tar.gz
+++ /dev/null
Binary files differ
diff --git a/mattermost/server/build.sh b/mattermost/server/build.sh
index 916a360..c2c1a0e 100755
--- a/mattermost/server/build.sh
+++ b/mattermost/server/build.sh
@@ -1,4 +1,4 @@
#! /usr/bin/env bash
-filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) plugin_templ.json > plugin.json
+filepp $( [[ ! -z "$DEFS" ]] && echo -D$DEFS ) ../plugin_templ.json > ../plugin.json
GOOS=linux GOARCH=amd64 go build $( [[ ! -z "$DEFS" ]] && echo -tags $DEFS ) -o bathroom-linux-amd64 bathroom.go $FILES
diff --git a/mattermost/server/package.sh b/mattermost/server/package.sh
deleted file mode 100755
index c8ce874..0000000
--- a/mattermost/server/package.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#! /usr/bin/env bash
-
-tar -czvf bathroom.tar.gz bathroom-linux-amd64 plugin.json
diff --git a/mattermost/server/plugin.json b/mattermost/server/plugin.json
deleted file mode 100644
index e4d22cb..0000000
--- a/mattermost/server/plugin.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "id": "com.mattermost.bathroom",
- "name": "Bathroom Monitor",
- "server": {
- "executable": "bathroom-linux-amd64"
- },
- "settings_schema": {
- "settings": [
- {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
- {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
- {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
- ]
- }
-}
diff --git a/mattermost/server/plugin_templ.json b/mattermost/server/plugin_templ.json
deleted file mode 100644
index 1de221a..0000000
--- a/mattermost/server/plugin_templ.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "id": "com.mattermost.bathroom",
- "name": "Bathroom Monitor",
- "server": {
- "executable": "bathroom-linux-amd64"
- },
- "settings_schema": {
- "settings": [
- {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"},
-#ifdef fsnotify
- {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
-#else
- {"key":"KeyPath", "display_name":"", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"},
-#endif
- {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"}
- ]
- }
-}
diff --git a/mattermost/webapp/bathroom.tar.gz b/mattermost/webapp/bathroom.tar.gz
new file mode 100644
index 0000000..48d8426
--- /dev/null
+++ b/mattermost/webapp/bathroom.tar.gz
Binary files differ
diff --git a/mattermost/webapp/dist/main.js b/mattermost/webapp/dist/main.js
index 8a0c4f1..4cca171 100644
--- a/mattermost/webapp/dist/main.js
+++ b/mattermost/webapp/dist/main.js
@@ -94,7 +94,121 @@
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-eval("\n\n//# sourceURL=webpack:///./src/index.jsx?");
+
+
+var _react = _interopRequireDefault(__webpack_require__(/*! react */ "react"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+class BathroomComponent extends _react.default.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ doors: {}
+ };
+ }
+
+ componentDidMount() {
+ Registry.registerWebSocketEventHandler("custom_com.mattermost.bathroom_updated", this.updateDoors.bind(this));
+ this.updateDoors();
+ }
+
+ componentWillUnmount() {
+ Registry.unregisterWebSocketEventHandler("custom_com.mattermost.bathroom_updated");
+ }
+
+ async updateDoors(msg) {
+ var url = Store.getState().entities.general.config.SiteURL + "/plugins/com.mattermost.bathroom/status";
+ var res = await fetch(url);
+ var json = await res.json();
+ this.setState({
+ "doors": json
+ });
+ }
+
+ render() {
+ if (!this.state.doors) return;
+ var columns = 6;
+ var keys = Object.keys(this.state.doors).sort();
+ var width = Math.floor(100 / columns) + "%";
+ var widthPx = "23px";
+ var elems = [];
+ var row = [];
+
+ for (var i = 0; i < keys.length
+ /*(Math.floor(keys.length / 6) + 1) * 6*/
+ ; i++) {
+ var img = null;
+
+ if (i < keys.length) {
+ var door = this.state.doors[keys[i]];
+ var imgFile = null;
+
+ switch (door) {
+ default:
+ case "unknown":
+ imgFile = "/static/emoji/2753.png";
+ break;
+
+ case "open":
+ imgFile = "/static/emoji/1f6bd.png";
+ break;
+
+ case "closed":
+ imgFile = "/static/emoji/26d4-fe0f.png";
+ break;
+ }
+
+ img = _react.default.createElement("img", {
+ src: imgFile,
+ width: "100%",
+ style: {
+ "padding": "2px"
+ }
+ });
+ }
+
+ row.push(_react.default.createElement("td", {
+ width: widthPx
+ }, img));
+
+ if (i % columns == columns - 1 || i == keys.length - 1) {
+ elems.push(_react.default.createElement(_react.default.Fragment, null, [...row]));
+ row.length = 0;
+ }
+ }
+
+ return (//
+ _react.default.createElement("div", {
+ style: {
+ "text-align": "center",
+ width: "100%",
+ "padding-top": "10px"
+ }
+ }, _react.default.createElement("table", {
+ style: {
+ "margin-left": "auto",
+ "margin-right": "auto"
+ }
+ }, elems))
+ );
+ }
+
+}
+
+var Registry = null;
+var Store = null;
+
+class BathroomMonitorPlugin {
+ initialize(registry, store) {
+ Registry = registry;
+ Store = store;
+ registry.registerLeftSidebarHeaderComponent(BathroomComponent);
+ }
+
+}
+
+window.registerPlugin('com.mattermost.bathroom', new BathroomMonitorPlugin());
/***/ }),
@@ -105,8 +219,21 @@
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
-eval("module.exports = __webpack_require__(/*! ./src/index.jsx */\"./src/index.jsx\");\n\n\n//# sourceURL=webpack:///multi_./src/index.jsx?");
+module.exports = __webpack_require__(/*! ./src/index.jsx */"./src/index.jsx");
+
+
+/***/ }),
+
+/***/ "react":
+/*!************************!*\
+ !*** external "React" ***!
+ \************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = React;
/***/ })
-/******/ });
\ No newline at end of file
+/******/ });
+//# sourceMappingURL=main.js.map
\ No newline at end of file
diff --git a/mattermost/webapp/dist/main.js.map b/mattermost/webapp/dist/main.js.map
new file mode 100644
index 0000000..26114e4
--- /dev/null
+++ b/mattermost/webapp/dist/main.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/index.jsx","webpack:///external \"React\""],"names":["BathroomComponent","React","Component","constructor","props","state","doors","componentDidMount","Registry","registerWebSocketEventHandler","updateDoors","bind","componentWillUnmount","unregisterWebSocketEventHandler","msg","url","Store","getState","entities","general","config","SiteURL","res","fetch","json","setState","render","columns","keys","Object","sort","width","Math","floor","widthPx","elems","row","i","length","img","door","imgFile","push","BathroomMonitorPlugin","initialize","registry","store","registerLeftSidebarHeaderComponent","window","registerPlugin"],"mappings":"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","file":"main.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","import React from 'react';\n\nclass BathroomComponent extends React.Component\n{\n constructor(props)\n {\n super(props);\n this.state = {doors:{}};\n }\n componentDidMount()\n {\n Registry.registerWebSocketEventHandler(\"custom_com.mattermost.bathroom_updated\", this.updateDoors.bind(this));\n this.updateDoors();\n }\n componentWillUnmount()\n {\n Registry.unregisterWebSocketEventHandler(\"custom_com.mattermost.bathroom_updated\");\n }\n async updateDoors(msg)\n {\n var url = Store.getState().entities.general.config.SiteURL + \"/plugins/com.mattermost.bathroom/status\";\n var res = await fetch(url);\n var json = await res.json();\n this.setState({\"doors\":json});\n }\n render()\n {\n if (!this.state.doors) return;\n var columns = 6;\n var keys = Object.keys(this.state.doors).sort();\n var width = (Math.floor(100 / columns)) + \"%\";\n var widthPx = \"23px\";\n var elems = [];\n var row = [];\n for (var i = 0; i < keys.length /*(Math.floor(keys.length / 6) + 1) * 6*/; i++)\n {\n var img = null;\n if (i < keys.length)\n {\n var door = this.state.doors[keys[i]];\n var imgFile = null;\n switch (door)\n {\n default:\n case \"unknown\":\n imgFile = \"/static/emoji/2753.png\";\n break;\n case \"open\":\n imgFile = \"/static/emoji/1f6bd.png\";\n break;\n case \"closed\":\n imgFile = \"/static/emoji/26d4-fe0f.png\";\n break;\n }\n img =
\n }\n row.push({img} | );\n if (i % columns == columns - 1 || i == keys.length - 1)\n {\n elems.push({[...row]});\n row.length = 0;\n }\n }\n return (\n //\n \n );\n }\n}\n\nvar Registry = null;\nvar Store = null;\n\nclass BathroomMonitorPlugin\n{\n initialize(registry, store)\n {\n Registry = registry;\n Store = store;\n registry.registerLeftSidebarHeaderComponent(BathroomComponent);\n }\n}\n\nwindow.registerPlugin('com.mattermost.bathroom', new BathroomMonitorPlugin());\n","module.exports = React;"],"sourceRoot":""}
\ No newline at end of file
diff --git a/mattermost/webapp/src/index.jsx b/mattermost/webapp/src/index.jsx
index e69de29..0868e33 100644
--- a/mattermost/webapp/src/index.jsx
+++ b/mattermost/webapp/src/index.jsx
@@ -0,0 +1,88 @@
+import React from 'react';
+
+class BathroomComponent extends React.Component
+{
+ constructor(props)
+ {
+ super(props);
+ this.state = {doors:{}};
+ }
+ componentDidMount()
+ {
+ Registry.registerWebSocketEventHandler("custom_com.mattermost.bathroom_updated", this.updateDoors.bind(this));
+ this.updateDoors();
+ }
+ componentWillUnmount()
+ {
+ Registry.unregisterWebSocketEventHandler("custom_com.mattermost.bathroom_updated");
+ }
+ async updateDoors(msg)
+ {
+ var url = Store.getState().entities.general.config.SiteURL + "/plugins/com.mattermost.bathroom/status";
+ var res = await fetch(url);
+ var json = await res.json();
+ this.setState({"doors":json});
+ }
+ render()
+ {
+ if (!this.state.doors) return;
+ var columns = 6;
+ var keys = Object.keys(this.state.doors).sort();
+ var width = (Math.floor(100 / columns)) + "%";
+ var widthPx = "23px";
+ var elems = [];
+ var row = [];
+ for (var i = 0; i < keys.length /*(Math.floor(keys.length / 6) + 1) * 6*/; i++)
+ {
+ var img = null;
+ if (i < keys.length)
+ {
+ var door = this.state.doors[keys[i]];
+ var imgFile = null;
+ switch (door)
+ {
+ default:
+ case "unknown":
+ imgFile = "/static/emoji/2753.png";
+ break;
+ case "open":
+ imgFile = "/static/emoji/1f6bd.png";
+ break;
+ case "closed":
+ imgFile = "/static/emoji/26d4-fe0f.png";
+ break;
+ }
+ img =
+ }
+ row.push({img} | );
+ if (i % columns == columns - 1 || i == keys.length - 1)
+ {
+ elems.push({[...row]});
+ row.length = 0;
+ }
+ }
+ return (
+ //
+
+ );
+ }
+}
+
+var Registry = null;
+var Store = null;
+
+class BathroomMonitorPlugin
+{
+ initialize(registry, store)
+ {
+ Registry = registry;
+ Store = store;
+ registry.registerLeftSidebarHeaderComponent(BathroomComponent);
+ }
+}
+
+window.registerPlugin('com.mattermost.bathroom', new BathroomMonitorPlugin());
diff --git a/mattermost/webapp/webpack.config.js b/mattermost/webapp/webpack.config.js
index 57121e1..b7e2419 100644
--- a/mattermost/webapp/webpack.config.js
+++ b/mattermost/webapp/webpack.config.js
@@ -4,6 +4,7 @@
entry: [
'./src/index.jsx',
],
+ devtool: 'source-map',
resolve: {
modules: [
'src',
diff --git a/pi/monitor.py b/pi/monitor.py
index 5d37f82..18d9312 100644
--- a/pi/monitor.py
+++ b/pi/monitor.py
@@ -38,6 +38,32 @@
private_key = RSA.import_key(open("private.pem").read())
rsa = PKCS1_OAEP.new(private_key);
+def report(val):
+ try:
+ url = url_base + "status-update" + ext + "?door_id=" + str(id) + "&status=" + ("1" if val else "0")
+ print " open " + url
+ response = urllib2.urlopen(url)
+
+ responseStr = response.read()
+ print "Response: " + responseStr
+ enc_verify = base64.b64decode(responseStr)
+
+ verify = rsa.decrypt(enc_verify)
+
+ if ext == "":
+ verify = base64.b64encode(verify)
+
+ print " verifying with: " + verify
+
+ url = url_base + "verify-status" + ext + "?door_id=" + str(id) + "&verify=" + verify
+ print " open " + url
+ response = urllib2.urlopen(url)
+ print " returned: " + response.read()
+ except Exception as e:
+ print str(e)
+ traceback.print_tb(sys.exc_info()[2])
+
+report(False)
while True:
now_pressed = b.is_pressed
if now_pressed == status:
@@ -48,31 +74,8 @@
now_pressed = b.is_pressed
if now_pressed != status:
status = now_pressed
-
print "status now: " + str(status)
- try:
- url = url_base + "status-update" + ext + "?door_id=" + str(id) + "&status=" + ("1" if status else "0")
- print " open " + url
- response = urllib2.urlopen(url)
-
- responseStr = response.read()
- print "Response: " + responseStr
- enc_verify = base64.b64decode(responseStr)
-
- verify = rsa.decrypt(enc_verify)
-
- if ext == "":
- verify = base64.b64encode(verify)
-
- print " verifying with: " + verify
-
- url = url_base + "verify-status" + ext + "?door_id=" + str(id) + "&verify=" + urllib.quote(verify)
- print " open " + url
- response = urllib2.urlopen(url)
- print " returned: " + response.read()
- except Exception as e:
- print str(e)
- traceback.print_tb(sys.exc_info()[2])
+ report(status)
sleep(1)