changeset 138:cc04b6af0477

start pilight server in go Ignore-this: f10b5ce373b929bcedbe18b315f0abb9
author drewp@bigasterisk.com
date Sat, 12 Jul 2014 11:31:40 -0700
parents 1952788e5299
children 5b607e8d35d0
files service/pilight/pilight.go service/pilight/readme service/pilight/static/index.html
diffstat 3 files changed, 217 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/pilight/pilight.go	Sat Jul 12 11:31:40 2014 -0700
@@ -0,0 +1,118 @@
+package main
+
+import "github.com/go-martini/martini"
+import "github.com/tarm/goserial"
+import "log"
+import "io"
+import "net/http"
+import "image/color"
+import "color/hex"
+import "strconv"
+import "time"
+
+const ledCount = 3
+
+type Board struct {
+	ser       io.ReadWriteCloser
+	LedColors [ledCount]color.Color
+}
+
+func OpenBoard(dev string) (*Board, error) {
+	c := &serial.Config{Name: dev, Baud: 115200}
+	ser, err := serial.OpenPort(c)
+	if err != nil {
+		return nil, err
+	}
+	log.Printf("wait for arduino to start up")
+	time.Sleep(2 * time.Second)
+	b := &Board{ser: ser}
+	for i := 0; i < ledCount; i++ {
+		b.LedColors[i] = color.RGBA{}
+	}
+	return b, err
+}
+
+func (b *Board) Write(cmd byte, msg []byte) error {
+	head := make([]byte, 2)
+	head[0] = 0x60
+	head[1] = cmd
+	_, err := b.ser.Write(head)
+	if err != nil {
+		return err
+	}
+	_, err = b.ser.Write(msg)
+	if err != nil {
+		return err
+	}
+	return err
+}
+
+func (b *Board) UpdateLeds() error {
+	bytes := make([]byte, 9)
+
+	for i := 0; i < ledCount; i++ {
+		r, g, b, _ := b.LedColors[i].RGBA()
+		bytes[i*3+0] = uint8(r)
+		bytes[i*3+1] = uint8(g)
+		bytes[i*3+2] = uint8(b)
+	}
+	return b.Write(0, bytes)
+}
+
+func getBodyStringColor(req *http.Request) (c color.Color, err error) {
+	bytes := make([]byte, 1024)
+	n, err := req.Body.Read(bytes)
+	body := hex.Hex(string(bytes[:n]))
+	if err != nil {
+		return
+	}
+	r, g, b := hex.HexToRGB(body)
+	return color.RGBA{r, g, b, 0}, nil
+}
+
+func main() {
+	board, err := OpenBoard("/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A9YLHR7R-if00-port0")
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	m := martini.Classic()
+	m.Martini.Use(martini.Static("static"))
+	m.Get("/", martini.Static("static", martini.StaticOptions{}))
+	m.Put("/led/:id", func(req *http.Request, params martini.Params) (int, string) {
+		color, err := getBodyStringColor(req)
+		if err != nil {
+			return 400, ""
+		}
+		which, err := strconv.Atoi(params["id"])
+		if err != nil {
+			return 400, ""
+		}
+		
+		board.LedColors[which] = color
+		err = board.UpdateLeds()
+		if err != nil {
+			return 500, ""
+		}
+		
+		return 200, "ok"
+	})
+	m.Get("/led", func() string {
+		return "['#ff0000', '#ff0000']"
+	})
+	m.Put("/led", func(req *http.Request) (int, string) {
+		color, err := getBodyStringColor(req)
+		if err != nil {
+			return 400, ""
+		}
+
+		for i := 0; i < ledCount; i++ {
+			board.LedColors[i] = color
+		}
+		err = board.UpdateLeds()
+
+		return 200, "ok"
+	})
+	log.Printf("serving")
+	m.Run()
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/pilight/readme	Sat Jul 12 11:31:40 2014 -0700
@@ -0,0 +1,18 @@
+
+GET /
+  info
+
+PUT /led/0 <- '#ff0000'
+
+PUT /led <- '#ff0000' sets all
+
+GET /led/0 -> '#ff0000'
+GET /led -> ['#ff0000', '#ff0000']  json
+
+POST /image <- png; -> Location: /image/1
+PUT /image/1 <- new png
+GET /image/1 -> png
+PUT /animationMode  <- {mode: 'continuous', image: '/image/1', pxPerSec: 30}
+PUT /animationMode  <- {mode: 'none'}
+GET /animationMode -> last input json
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/pilight/static/index.html	Sat Jul 12 11:31:40 2014 -0700
@@ -0,0 +1,81 @@
+<!doctype html>
+<html>
+  <head>
+    <title>pilight</title>
+    <meta charset="utf-8" />
+    <script src="//bigasterisk.com/lib/jquery-2.0.3.js"></script>
+    <script src="//bigasterisk.com/lib/platform/0.2.3/platform.js"></script>
+    <link rel="import" href="static/input-rgb/input-rgb.html">
+    <style>
+      input-rgb {
+       border: 1px solid gray;
+       width: 300px;
+     }
+    </style>
+  </head>
+  <body>
+
+    <polymer-element name="led-output" attributes="url color">
+    <!-- calls PUT <url> with color string as the body, but also
+         avoids sending many repeated calls to url while the first one
+         is still in progress -->
+      <template>
+        {{status}}
+      </template>
+      <script>Polymer('led-output', {
+          created: function() {
+              this.pending = {}; // url: data
+              this.inflight = false;
+          },
+          colorChanged: function() {
+              this.pending["led"] = this.color;
+              this.sendMore();
+          },
+          sendMore: function() {
+              if (this.inflight) {
+                  return;
+              }
+              var urls = Object.keys(this.pending);
+              if (!urls.length) {
+                  return;
+              }
+              var url = urls.pop();
+              var data = this.pending[url];
+              delete this.pending[url];
+
+              this.status = "Sending...";
+              this.inflight = true;
+              $.ajax({
+                  type: "PUT",
+                  url: url,
+                  data: data,
+                  success: function() {
+                      this.status = "";
+                  }.bind(this),
+                  error: function() {
+                      this.status = "Send failed";
+                  }.bind(this),
+                  complete: function() {
+                      this.inflight = false;
+                      this.sendMore();
+                  }.bind(this)
+              });
+        }
+      });
+      </script>
+
+    </polymer-element>
+      
+    <polymer-element name="pilight-page" noscript>
+      <template>
+        LED0 color:
+        <input-rgb editable="true" hex="{{c1}}"></input-rgb>
+        <led-output which="led" color="{{c1}}"></led-output>
+      </template>
+    </polymer-element>
+
+    <pilight-page></pilight-page>
+
+
+  </body>
+</html>