# HG changeset patch
# User drewp@bigasterisk.com
# Date 1377970430 25200
# Node ID 27a685ce2e5d9b99e6f1f0ded739d3f544221de5
# Parent 5907eeb9a630657db6d4a131cafc1401e971b4b9
more laundry web support
Ignore-this: c7313465fbd93fa902b909f9128c2ad
diff -r 5907eeb9a630 -r 27a685ce2e5d service/laundry/index.html
--- a/service/laundry/index.html Mon Aug 26 22:11:29 2013 -0700
+++ b/service/laundry/index.html Sat Aug 31 10:33:50 2013 -0700
@@ -2,7 +2,7 @@
laundry pi
-
+
@@ -12,20 +12,23 @@
current /status
(as an rdf graph)
+
+ Inputs
motion: {{status.motion}}
switch1: {{status.switch1}}
switch2: {{status.switch2}}
switch3: {{status.switch3}}
doorClosed: {{status.doorClosed}}
-
+ Outputs
orange led: {{status.led}}
- strike:
- speaker:
+ strike: {{status.strike}}
+ speaker: {{speakerStatus}}
- Status: {{status | json}}
+ Raw status
+ {{status | json}}
diff -r 5907eeb9a630 -r 27a685ce2e5d service/laundry/laundry.go
--- a/service/laundry/laundry.go Mon Aug 26 22:11:29 2013 -0700
+++ b/service/laundry/laundry.go Sat Aug 31 10:33:50 2013 -0700
@@ -5,6 +5,7 @@
"log"
"net/http"
"strconv"
+ "time"
"encoding/json"
"github.com/bmizerany/pat"
"github.com/mrmorphic/hwio"
@@ -74,18 +75,35 @@
if err := hwio.PinMode(pins.InSwitch2, hwio.INPUT_PULLUP); err != nil { panic(err) }
if err := hwio.PinMode(pins.InSwitch3, hwio.INPUT_PULLUP); err != nil { panic(err) }
if err := hwio.PinMode(pins.InDoorClosed, hwio.INPUT_PULLUP); err != nil { panic(err) }
- if err := hwio.PinMode(pins.OutLed, hwio.OUTPUT); err != nil { panic(err) }
+ if err := hwio.PinMode(pins.OutLed, hwio.OUTPUT); err != nil { panic(err) }
if err := hwio.PinMode(pins.OutSpeaker, hwio.OUTPUT); err != nil { panic(err) }
if err := hwio.PinMode(pins.OutStrike, hwio.OUTPUT); err != nil { panic(err) }
return pins
}
+
+func booleanBody(w http.ResponseWriter, r *http.Request) (level int, err error) {
+ body, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ panic(err)
+ }
+ level, err2 := strconv.Atoi(string(body[:]))
+ if err2 != nil {
+ http.Error(w, "body must be '0' or '1'", http.StatusBadRequest)
+ return 0, err
+ }
+ return level, nil
+}
+
func main() {
pins := SetupIo()
m := pat.New()
m.Get("/", http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
+ // this one needs to fail if the hardware is broken in
+ // any way that we can determine, though I'm not sure
+ // what that will mean on rpi
http.ServeFile(w, r, "index.html")
}));
@@ -100,29 +118,74 @@
"switch3": DigitalRead(pins.InSwitch3),
"doorClosed": DigitalRead(pins.InDoorClosed),
"led": pins.LastOutLed,
+ "strike": pins.LastOutStrike,
})
}));
-
+
m.Put("/led", http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
- level, err := strconv.Atoi(string(body[:]))
- if err != nil {
- http.Error(w, "body must be '0' or '1'", http.StatusBadRequest)
- return
+ var level int
+ if string(body) == "on" {
+ level = 1
+ } else if string(body) == "off" {
+ level = 0
+ } else {
+ http.Error(w, "body must be 'on' or 'off'", http.StatusBadRequest)
+ return
}
hwio.DigitalWrite(pins.OutLed, level)
pins.LastOutLed = level
-
http.Error(w, "", http.StatusAccepted)
- }));
+ }))
+ setStrike := func (level int) {
+ hwio.DigitalWrite(pins.OutStrike, level)
+ pins.LastOutStrike = level
+ }
+
+ m.Put("/strike", http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
+ level, err := booleanBody(w, r)
+ if err != nil {
+ panic(err)
+ }
+ setStrike(level)
+ http.Error(w, "", http.StatusAccepted)
+ }))
+
+ m.Put("/strike/temporaryUnlock", http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
+ err := r.ParseForm()
+ if err != nil {
+ panic(err)
+ }
+ seconds, err2 := strconv.ParseFloat(string(r.Form["seconds"][0]), 32)
+ if err2 != nil {
+ http.Error(w, "seconds must be a float", http.StatusBadRequest)
+ return
+ }
+
+ // This is not correctly reentrant. There should be a
+ // stack of temporary effects that unpop correctly,
+ // and status should show you any running effects.
+ setStrike(1)
+ go func() {
+ time.Sleep(time.Duration(seconds * float64(time.Second)))
+ setStrike(0)
+ }()
+ http.Error(w, "", http.StatusAccepted)
+ }))
+
+ m.Put("/speaker/beep", http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
+ // queue a beep
+ http.Error(w, "", http.StatusAccepted)
+ }))
+
http.Handle("/", m)
- log.Printf("Listening on port 8080")
- err := http.ListenAndServe(":8080", nil)
+ log.Printf("Listening on port 8081")
+ err := http.ListenAndServe(":8081", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
diff -r 5907eeb9a630 -r 27a685ce2e5d service/laundry/static/gui.js
--- a/service/laundry/static/gui.js Mon Aug 26 22:11:29 2013 -0700
+++ b/service/laundry/static/gui.js Sat Aug 31 10:33:50 2013 -0700
@@ -11,6 +11,17 @@
$http.put("led", value).succeed(function () {
refresh();
});
+ };
+ $scope.temporaryUnlock = function () {
+ var seconds = 3;
+ $http.put("strike/temporaryUnlock", {seconds: seconds}).succeed(function () {
+ refresh();
+ setTimeout(function () { refresh(); }, (seconds + .1) * 1000);
+ });
+ };
+ $scope.beep = function () {
+ $http.put("speaker/beep").succeed(function () {
+ $scope.speakerStatus = "sent at " + new Date();
+ });
}
-
}