changeset 1301:edb673a7dff8

rm old golang service that ran on a pi connected to an arduino connected to RGB leds. includes some color picker using polymer Ignore-this: ca47318f8bea6603ff3d584df19d5ca darcs-hash:4c2add59e2c23a21b87e7d497bb6949cfb8e9fab
author drewp <drewp@bigasterisk.com>
date Sun, 21 Apr 2019 02:52:49 -0700
parents 8c8134ca6cff
children 4d4eb35531b9
files service/pilight/makefile service/pilight/pilight.go service/pilight/readme service/pilight/src/color/hex/colorhex.go service/pilight/static/big-picker.html service/pilight/static/color.js service/pilight/static/index.html
diffstat 7 files changed, 0 insertions(+), 1363 deletions(-) [+]
line wrap: on
line diff
--- a/service/pilight/makefile	Sun Apr 21 02:48:58 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-GOPATH=$(shell pwd)
-export GOPATH
-build: deps
-	go build pilight.go
-
-deps: src/github.com/tarm/goserial src/github.com/go-martini/martini
-
-src/github.com/tarm/goserial:
-	go get github.com/tarm/goserial
-src/github.com/go-martini/martini:
-	go get github.com/go-martini/martini
-
-setup:
-	ln -s . public
-
-build-to-pi: deps
-	GOBIN=bin-pi GOARCH=arm go install pilight.go
-	rsync -a bin-pi/pilight pi@192.168.1.157:projects/homeauto/service/pilight/bin/
--- a/service/pilight/pilight.go	Sun Apr 21 02:48:58 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,195 +0,0 @@
-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"
-import "net/textproto"
-import "bufio"
-import "errors"
-import "encoding/json"
-
-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 (b *Board) ReadDht() (string, error) {
-	for try := 0; try < 5; try++ {
-		err := b.Write(0x2, make([]byte, 0))
-		if err != nil {
-			continue
-		}
-
-		reader := textproto.NewReader(bufio.NewReader(b.ser))
-		json, err := reader.ReadLine()
-		if err != nil {
-			continue
-		}
-		return json, nil
-	}
-	return "", errors.New("failed after all retries")
-}
-
-
-func (b *Board) ReadLeds() (colors []color.Color, err error) {
-	err = b.Write(0x3, make([]byte, 0))
-	if err != nil {
-		return
-	}
-	reader := textproto.NewReader(bufio.NewReader(b.ser))
-	line, err := reader.ReadLineBytes()
-	if err != nil {
-		return
-	}
-
-	type LedsMessage struct {
-		Leds []string
-	}
-	var ret LedsMessage
-	err = json.Unmarshal(line, &ret)
-	if err != nil {
-		return
-	}
-
-	colors = make([]color.Color, len(ret.Leds))
-	for i, c := range ret.Leds {
-		r, g, b := hex.HexToRGB(hex.Hex(c))
-		colors[i] = color.RGBA{r, g, b, 0}
-	}
-	
-	return colors, nil
-}
-
-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() (int, string) {
-
-		colors, err := board.ReadLeds()
-		if err != nil {
-			return 500, ""
-		}
-		hexColors := make([]hex.Hex, len(colors))
-		for i, c := range colors {
-			// hex.HexModel.Convert(c) seems like the
-			// right call, but fails because it returns
-			// Color not string
-			r, g, b, _ := c.RGBA()
-			hexColors[i] = hex.RGBToHex(uint8(r), uint8(g), uint8(b))
-		}
-
-		// content-type json
-		j, err := json.Marshal(hexColors)
-		if err != nil {
-			return 500, ""
-		}
-		return 200, string(j)
-	})
-	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"
-	})
-	m.Get("/dht", func() (int, string) {
-		json, err := board.ReadDht()
-		if err != nil {
-			return 500, ""
-		}
-		return 200, json
-	})
-	log.Printf("serving")
-	m.Run()
-}
--- a/service/pilight/readme	Sun Apr 21 02:48:58 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-
-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
-
--- a/service/pilight/src/color/hex/colorhex.go	Sun Apr 21 02:48:58 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-// From https://github.com/zond/wildlife/blob/master/code.google.com/p/gorilla/color/hex.go
-
-// Copyright 2012 The Gorilla Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package hex
-
-import (
-	"fmt"
-	"image/color"
-	"strconv"
-)
-
-// HexModel converts any Color to an Hex color.
-var HexModel = color.ModelFunc(hexModel)
-
-// Hex represents an RGB color in hexadecimal format.
-//
-// The length must be 3 or 6 characters, preceded or not by a '#'.
-type Hex string
-
-// RGBA returns the alpha-premultiplied red, green, blue and alpha values
-// for the Hex.
-func (c Hex) RGBA() (uint32, uint32, uint32, uint32) {
-	r, g, b := HexToRGB(c)
-	return uint32(r) * 0x101, uint32(g) * 0x101, uint32(b) * 0x101, 0xffff
-}
-
-// hexModel converts a Color to Hex.
-func hexModel(c color.Color) color.Color {
-	if _, ok := c.(Hex); ok {
-		return c
-	}
-	r, g, b, _ := c.RGBA()
-	return RGBToHex(uint8(r>>8), uint8(g>>8), uint8(b>>8))
-}
-
-// RGBToHex converts an RGB triple to an Hex string.
-func RGBToHex(r, g, b uint8) Hex {
-	return Hex(fmt.Sprintf("#%02X%02X%02X", r, g, b))
-}
-
-// HexToRGB converts an Hex string to a RGB triple.
-func HexToRGB(h Hex) (uint8, uint8, uint8) {
-	if len(h) > 0 && h[0] == '#' {
-		h = h[1:]
-	}
-	if len(h) == 3 {
-		h = h[:1] + h[:1] + h[1:2] + h[1:2] + h[2:] + h[2:]
-	}
-	if len(h) == 6 {
-		if rgb, err := strconv.ParseUint(string(h), 16, 32); err == nil {
-			return uint8(rgb >> 16), uint8((rgb >> 8) & 0xFF), uint8(rgb & 0xFF)
-		}
-	}
-	return 0, 0, 0
-}
--- a/service/pilight/static/big-picker.html	Sun Apr 21 02:48:58 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-<polymer-element name="big-picker" attributes="hex">
-  <template>
-    <style>
-     .pot {
-       width: 50px;
-       height: 50px;
-       border-radius: 50%;
-       box-shadow: 3px 2px 10px black;
-       border: 2px solid white;
-       margin: 10px;
-       position: absolute;
-     }
-     input[type=range] {
-       -webkit-appearance: slider-vertical;
-     }
-     #wide {
-       display: flex;
-     }
-     #samples {
-       outline: 1px solid gray;
-       width: 300px;
-       height: 300px;
-       position: relative;
-     }
-     #swatch {
-       position: absolute;
-       left: 110px;
-       top: 110px;
-       width: 60px;
-       height: 60px;
-     }
-
-     #lightness {
-       display: flex;
-       outline: 1px gray solid;
-       background: linear-gradient(to bottom, #ffffff 0%,#0e0e0e 100%);
-       width: 50px;
-     }
-    </style>
-
-    <div id="wide">
-      <div id="samples">
-        <template repeat="{{c in potColors}}">
-          <div class="pot" style="background: {{c}}" on-click="{{setColor}}"></div>
-        </template>
-        <input id="swatch" type="color" id="picker" value="{{hex}}" orient="vertical">
-      </div>
-      
-      <div id="lightness">
-        <input type="range" min="0" max="1" step=".01" value="{{lightness}}">
-      </div>
-    </div>
-  </template>
-  
-  <script src="color.js"></script>
-  <script type="text/javascript">
-    var Color = net.brehaut.Color;
-    Polymer('big-picker', {
-        hex: '#ffffff',
-        ready: function() {
-            this.lightness = .5;
-            this.potColors = ['hsl(20, 100%, 50%)',
-                              'hsl(60, 100%, 50%)',
-                              'hsl(100, 100%, 50%)',
-                              'hsl(140, 100%, 50%)',
-                              'hsl(180, 100%, 50%)',
-                              'hsl(220, 100%, 50%)',
-                              'hsl(260, 100%, 50%)',
-                              'hsl(300, 100%, 50%)',
-                              'hsl(340, 100%, 50%)',
-                              '#888888'];
-        },
-        domReady: function() {
-            var pots = this.$.samples.getElementsByClassName("pot");
-            $.each(pots, function (i, elem) {
-                var frac = i / pots.length;
-                elem.style.left = (100 + 100 * Math.sin(frac * 2 * Math.PI)) + "px";
-                elem.style.top  = (100 + 100 * Math.cos(frac * 2 * Math.PI)) + "px";
-            });
-        },
-        setColor: function(e) {
-            var c = Color(e.target.templateInstance.model.c).setLightness(this.lightness);
-            this.hex = c.toString();
-        },
-        hexChanged: function() {
-            this.lightness = Color(this.hex).getLightness();
-        },
-        lightnessChanged: function() {
-            var c = Color(this.hex).setLightness(this.lightness);
-            this.hex = c.toString();
-        }
-    });
-  </script>
-</polymer-element>
--- a/service/pilight/static/color.js	Sun Apr 21 02:48:58 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,840 +0,0 @@
-// Copyright (c) 2008-2013, Andrew Brehaut, Tim Baumann, Matt Wilson, 
-//                          Simon Heimler, Michel Vielmetter 
-//
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice,
-//   this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-//   this list of conditions and the following disclaimer in the documentation
-//   and/or other materials provided with the distribution.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-
-// color.js - version 1.0.1
-//
-// HSV <-> RGB code based on code from http://www.cs.rit.edu/~ncs/color/t_convert.html
-// object function created by Douglas Crockford.
-// Color scheme degrees taken from the colorjack.com colorpicker
-//
-// HSL support kindly provided by Tim Baumann - http://github.com/timjb
-
-// create namespaces
-/*global net */
-if ("undefined" == typeof net) { var net = {}; }
-if (!net.brehaut) { net.brehaut = {}; }
-
-// this module function is called with net.brehaut as 'this'
-(function ( ) {
-  "use strict";
-  // Constants
-
-  // css_colors maps color names onto their hex values
-  // these names are defined by W3C
-  var css_colors = {aliceblue:'#F0F8FF',antiquewhite:'#FAEBD7',aqua:'#00FFFF',aquamarine:'#7FFFD4',azure:'#F0FFFF',beige:'#F5F5DC',bisque:'#FFE4C4',black:'#000000',blanchedalmond:'#FFEBCD',blue:'#0000FF',blueviolet:'#8A2BE2',brown:'#A52A2A',burlywood:'#DEB887',cadetblue:'#5F9EA0',chartreuse:'#7FFF00',chocolate:'#D2691E',coral:'#FF7F50',cornflowerblue:'#6495ED',cornsilk:'#FFF8DC',crimson:'#DC143C',cyan:'#00FFFF',darkblue:'#00008B',darkcyan:'#008B8B',darkgoldenrod:'#B8860B',darkgray:'#A9A9A9',darkgrey:'#A9A9A9',darkgreen:'#006400',darkkhaki:'#BDB76B',darkmagenta:'#8B008B',darkolivegreen:'#556B2F',darkorange:'#FF8C00',darkorchid:'#9932CC',darkred:'#8B0000',darksalmon:'#E9967A',darkseagreen:'#8FBC8F',darkslateblue:'#483D8B',darkslategray:'#2F4F4F',darkslategrey:'#2F4F4F',darkturquoise:'#00CED1',darkviolet:'#9400D3',deeppink:'#FF1493',deepskyblue:'#00BFFF',dimgray:'#696969',dimgrey:'#696969',dodgerblue:'#1E90FF',firebrick:'#B22222',floralwhite:'#FFFAF0',forestgreen:'#228B22',fuchsia:'#FF00FF',gainsboro:'#DCDCDC',ghostwhite:'#F8F8FF',gold:'#FFD700',goldenrod:'#DAA520',gray:'#808080',grey:'#808080',green:'#008000',greenyellow:'#ADFF2F',honeydew:'#F0FFF0',hotpink:'#FF69B4',indianred:'#CD5C5C',indigo:'#4B0082',ivory:'#FFFFF0',khaki:'#F0E68C',lavender:'#E6E6FA',lavenderblush:'#FFF0F5',lawngreen:'#7CFC00',lemonchiffon:'#FFFACD',lightblue:'#ADD8E6',lightcoral:'#F08080',lightcyan:'#E0FFFF',lightgoldenrodyellow:'#FAFAD2',lightgray:'#D3D3D3',lightgrey:'#D3D3D3',lightgreen:'#90EE90',lightpink:'#FFB6C1',lightsalmon:'#FFA07A',lightseagreen:'#20B2AA',lightskyblue:'#87CEFA',lightslategray:'#778899',lightslategrey:'#778899',lightsteelblue:'#B0C4DE',lightyellow:'#FFFFE0',lime:'#00FF00',limegreen:'#32CD32',linen:'#FAF0E6',magenta:'#FF00FF',maroon:'#800000',mediumaquamarine:'#66CDAA',mediumblue:'#0000CD',mediumorchid:'#BA55D3',mediumpurple:'#9370D8',mediumseagreen:'#3CB371',mediumslateblue:'#7B68EE',mediumspringgreen:'#00FA9A',mediumturquoise:'#48D1CC',mediumvioletred:'#C71585',midnightblue:'#191970',mintcream:'#F5FFFA',mistyrose:'#FFE4E1',moccasin:'#FFE4B5',navajowhite:'#FFDEAD',navy:'#000080',oldlace:'#FDF5E6',olive:'#808000',olivedrab:'#6B8E23',orange:'#FFA500',orangered:'#FF4500',orchid:'#DA70D6',palegoldenrod:'#EEE8AA',palegreen:'#98FB98',paleturquoise:'#AFEEEE',palevioletred:'#D87093',papayawhip:'#FFEFD5',peachpuff:'#FFDAB9',peru:'#CD853F',pink:'#FFC0CB',plum:'#DDA0DD',powderblue:'#B0E0E6',purple:'#800080',rebeccapurple:'#663399',red:'#FF0000',rosybrown:'#BC8F8F',royalblue:'#4169E1',saddlebrown:'#8B4513',salmon:'#FA8072',sandybrown:'#F4A460',seagreen:'#2E8B57',seashell:'#FFF5EE',sienna:'#A0522D',silver:'#C0C0C0',skyblue:'#87CEEB',slateblue:'#6A5ACD',slategray:'#708090',slategrey:'#708090',snow:'#FFFAFA',springgreen:'#00FF7F',steelblue:'#4682B4',tan:'#D2B48C',teal:'#008080',thistle:'#D8BFD8',tomato:'#FF6347',turquoise:'#40E0D0',violet:'#EE82EE',wheat:'#F5DEB3',white:'#FFFFFF',whitesmoke:'#F5F5F5',yellow:'#FFFF00',yellowgreen:'#9ACD32"'};
-
-  // CSS value regexes, according to http://www.w3.org/TR/css3-values/
-  var css_integer = '(?:\\+|-)?\\d+';
-  var css_float = '(?:\\+|-)?\\d*\\.\\d+';
-  var css_number = '(?:' + css_integer + ')|(?:' + css_float + ')';
-  css_integer = '(' + css_integer + ')';
-  css_float = '(' + css_float + ')';
-  css_number = '(' + css_number + ')';
-  var css_percentage = css_number + '%';
-  var css_whitespace = '\\s*?';
-
-  // http://www.w3.org/TR/2003/CR-css3-color-20030514/
-  var hsl_hsla_regex = new RegExp([
-    '^hsl(a?)\\(', css_number, ',', css_percentage, ',', css_percentage, '(,(', css_number, '))?\\)$'
-  ].join(css_whitespace) );
-  var rgb_rgba_integer_regex = new RegExp([
-    '^rgb(a?)\\(', css_integer, ',', css_integer, ',', css_integer, '(,(', css_number, '))?\\)$'
-  ].join(css_whitespace) );
-  var rgb_rgba_percentage_regex = new RegExp([
-    '^rgb(a?)\\(', css_percentage, ',', css_percentage, ',', css_percentage, '(,(', css_number, '))?\\)$'
-  ].join(css_whitespace) );
-
-  // Package wide variables
-
-  // becomes the top level prototype object
-  var color;
-
-  /* registered_models contains the template objects for all the
-   * models that have been registered for the color class.
-   */
-  var registered_models = [];
-
-
-  /* factories contains methods to create new instance of
-   * different color models that have been registered.
-   */
-  var factories = {};
-
-  // Utility functions
-
-  /* object is Douglas Crockfords object function for prototypal
-   * inheritance.
-   */
-  if (!this.object) {
-    this.object = function (o) {
-      function F () { }
-      F.prototype = o;
-      return new F();
-    };
-  }
-  var object = this.object;
-
-  /* takes a value, converts to string if need be, then pads it
-   * to a minimum length.
-   */
-  function pad ( val, len ) {
-    val = val.toString();
-    var padded = [];
-
-    for (var i = 0, j = Math.max( len - val.length, 0); i < j; i++) {
-      padded.push('0');
-    }
-
-    padded.push(val);
-    return padded.join('');
-  }
-
-
-  /* takes a string and returns a new string with the first letter
-   * capitalised
-   */
-  function capitalise ( s ) {
-    return s.slice(0,1).toUpperCase() + s.slice(1);
-  }
-
-  /* removes leading and trailing whitespace
-   */
-  function trim ( str ) {
-    return str.replace(/^\s+|\s+$/g, '');
-  }
-
-  /* used to apply a method to object non-destructively by
-   * cloning the object and then apply the method to that
-   * new object
-   */
-  function cloneOnApply( meth ) {
-    return function ( ) {
-      var cloned = this.clone();
-      meth.apply(cloned, arguments);
-      return cloned;
-    };
-  }
-
-
-  /* registerModel is used to add additional representations
-   * to the color code, and extend the color API with the new
-   * operatiosn that model provides. see before for examples
-   */
-  function registerModel( name, model ) {
-    var proto = object(color);
-    var fields = []; // used for cloning and generating accessors
-
-    var to_meth = 'to'+ capitalise(name);
-
-    function convertAndApply( meth ) {
-      return function ( ) {
-        return meth.apply(this[to_meth](), arguments);
-      };
-    }
-
-    for (var key in model) if (model.hasOwnProperty(key)) {
-      proto[key] = model[key];
-      var prop = proto[key];
-
-      if (key.slice(0,1) == '_') { continue; }
-      if (!(key in color) && "function" == typeof prop) {
-        // the method found on this object is a) public and b) not
-        // currently supported by the color object. Create an impl that
-        // calls the toModel function and passes that new object
-        // onto the correct method with the args.
-        color[key] = convertAndApply(prop);
-      }
-      else if ("function" != typeof prop) {
-        // we have found a public property. create accessor methods
-        // and bind them up correctly
-        fields.push(key);
-        var getter = 'get'+capitalise(key);
-        var setter = 'set'+capitalise(key);
-
-        color[getter] = convertAndApply(
-          proto[getter] = (function ( key ) {
-            return function ( ) {
-              return this[key];
-            };
-          })( key )
-        );
-
-        color[setter] = convertAndApply(
-          proto[setter] = (function ( key ) {
-            return function ( val ) {
-              var cloned = this.clone();
-              cloned[key] = val;
-              return cloned;
-            };
-          })( key )
-        );
-      }
-    } // end of for over model
-
-    // a method to create a new object - largely so prototype chains dont
-    // get insane. This uses an unrolled 'object' so that F is cached
-    // for later use. this is approx a 25% speed improvement
-    function F () { }
-    F.prototype = proto;
-    function factory ( ) {
-      return new F();
-    }
-    factories[name] = factory;
-
-    proto.clone = function () {
-      var cloned = factory();
-      for (var i = 0, j = fields.length; i < j; i++) {
-        var key = fields[i];
-        cloned[key] = this[key];
-      }
-      return cloned;
-    };
-
-    color[to_meth] = function ( ) {
-      return factory();
-    };
-
-    registered_models.push(proto);
-
-    return proto;
-  }// end of registerModel
-
-  // Template Objects
-
-  /* color is the root object in the color hierarchy. It starts
-   * life as a very simple object, but as color models are
-   * registered it has methods programmatically added to manage
-   * conversions as needed.
-   */
-  color = {
-    /* fromObject takes an argument and delegates to the internal
-     * color models to try to create a new instance.
-     */
-    fromObject: function ( o ) {
-      if (!o) {
-        return object(color);
-      }
-
-      for (var i = 0, j = registered_models.length; i < j; i++) {
-        var nu = registered_models[i].fromObject(o);
-        if (nu) {
-          return nu;
-        }
-      }
-
-      return object(color);
-    },
-
-    toString: function ( ) {
-      return this.toCSS();
-    }
-  };
-
-  var transparent = null; // defined with an RGB later.
-
-  /* RGB is the red green blue model. This definition is converted
-   * to a template object by registerModel.
-   */
-  registerModel('RGB', {
-    red:    0,
-    green:  0,
-    blue:   0,
-    alpha:  0,
-
-    /* getLuminance returns a value between 0 and 1, this is the
-     * luminance calcuated according to
-     * http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC9
-     */
-    getLuminance: function ( ) {
-      return (this.red * 0.2126) + (this.green * 0.7152) + (this.blue * 0.0722);
-    },
-
-    /* does an alpha based blend of color onto this. alpha is the
-     * amount of 'color' to use. (0 to 1)
-     */
-    blend: function ( color , alpha ) {
-      color = color.toRGB();
-      alpha = Math.min(Math.max(alpha, 0), 1);
-      var rgb = this.clone();     
-
-      rgb.red = (rgb.red * (1 - alpha)) + (color.red * alpha);
-      rgb.green = (rgb.green * (1 - alpha)) + (color.green * alpha);
-      rgb.blue = (rgb.blue * (1 - alpha)) + (color.blue * alpha);
-      rgb.alpha = (rgb.alpha * (1 - alpha)) + (color.alpha * alpha);
-
-      return rgb;
-    },
-
-    /* fromObject attempts to convert an object o to and RGB
-     * instance. This accepts an object with red, green and blue
-     * members or a string. If the string is a known CSS color name
-     * or a hexdecimal string it will accept it.
-     */
-    fromObject: function ( o ) {
-      if (o instanceof Array) {
-        return this._fromRGBArray ( o );
-      }
-      if ("string" == typeof o) {
-        return this._fromCSS( trim( o ) );
-      }
-      if (o.hasOwnProperty('red') &&
-          o.hasOwnProperty('green') &&
-          o.hasOwnProperty('blue')) {
-        return this._fromRGB ( o );
-      }
-      // nothing matchs, not an RGB object
-    },
-
-    _stringParsers: [
-        // CSS RGB(A) literal:
-        function ( css ) {
-          css = trim(css);
-
-          var withInteger = match(rgb_rgba_integer_regex, 255);
-          if(withInteger) {
-            return withInteger;
-          }
-          return match(rgb_rgba_percentage_regex, 100);
-
-          function match(regex, max_value) {
-            var colorGroups = css.match( regex );
-
-            // If there is an "a" after "rgb", there must be a fourth parameter and the other way round
-            if (!colorGroups || (!!colorGroups[1] + !!colorGroups[5] === 1)) {
-              return null;
-            }
-
-            var rgb = factories.RGB();
-            rgb.red   = Math.min(1, Math.max(0, colorGroups[2] / max_value));
-            rgb.green = Math.min(1, Math.max(0, colorGroups[3] / max_value));
-            rgb.blue  = Math.min(1, Math.max(0, colorGroups[4] / max_value));
-            rgb.alpha = !!colorGroups[5] ? Math.min(Math.max(parseFloat(colorGroups[6]), 0), 1) : 1;
-
-            return rgb;
-          }
-        },
-
-        function ( css ) {
-            var lower = css.toLowerCase();
-            if (lower in css_colors) {
-              css = css_colors[lower];
-            }
-
-            if (!css.match(/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/)) {
-              return;
-            }
-
-            css = css.replace(/^#/,'');
-
-            var bytes = css.length / 3;
-
-            var max = Math.pow(16, bytes) - 1;
-
-            var rgb = factories.RGB();
-            rgb.red =   parseInt(css.slice(0, bytes), 16) / max;
-            rgb.green = parseInt(css.slice(bytes * 1,bytes * 2), 16) / max;
-            rgb.blue =  parseInt(css.slice(bytes * 2), 16) / max;
-            rgb.alpha = 1;
-            return rgb;
-        },
-
-        function ( css ) {
-            if (css.toLowerCase() !== 'transparent') return;
-
-            return transparent;
-        }
-    ],
-
-    _fromCSS: function ( css ) {
-      var color = null;
-      for (var i = 0, j = this._stringParsers.length; i < j; i++) {
-          color = this._stringParsers[i](css);
-          if (color) return color;
-      }
-    },
-
-    _fromRGB: function ( RGB ) {
-      var newRGB = factories.RGB();
-
-      newRGB.red = RGB.red;
-      newRGB.green = RGB.green;
-      newRGB.blue = RGB.blue;
-      newRGB.alpha = RGB.hasOwnProperty('alpha') ? RGB.alpha : 1;
-
-      return newRGB;
-    },
-
-    _fromRGBArray: function ( RGB ) {
-      var newRGB = factories.RGB();
-
-      newRGB.red = Math.max(0, Math.min(1, RGB[0] / 255));
-      newRGB.green = Math.max(0, Math.min(1, RGB[1] / 255));
-      newRGB.blue = Math.max(0, Math.min(1, RGB[2] / 255));
-      newRGB.alpha = RGB[3] !== undefined ? Math.max(0, Math.min(1, RGB[3])) : 1;
-
-      return newRGB;
-    },
-
-    // convert to a CSS string. defaults to two bytes a value
-    toCSSHex: function ( bytes ) {
-        bytes = bytes || 2;
-
-        var max = Math.pow(16, bytes) - 1;
-        var css = [
-          "#",
-          pad ( Math.round(this.red * max).toString( 16 ).toUpperCase(), bytes ),
-          pad ( Math.round(this.green * max).toString( 16 ).toUpperCase(), bytes ),
-          pad ( Math.round(this.blue * max).toString( 16 ).toUpperCase(), bytes )
-        ];
-
-        return css.join('');
-    },    
-    
-    toCSS: function ( bytes ) {
-      if (this.alpha === 1) return this.toCSSHex(bytes); 
-
-      var max = 255;
-      
-      var components = [
-        'rgba(',
-        Math.max(0, Math.min(max, Math.round(this.red * max))), ',',
-        Math.max(0, Math.min(max, Math.round(this.green * max))), ',', 
-        Math.max(0, Math.min(max, Math.round(this.blue * max))), ',',
-        Math.max(0, Math.min(1, this.alpha)), 
-        ')'
-      ];
-
-      return components.join('');
-    },
-
-    toHSV: function ( ) {
-      var hsv = factories.HSV();
-      var min, max, delta;
-
-      min = Math.min(this.red, this.green, this.blue);
-      max = Math.max(this.red, this.green, this.blue);
-      hsv.value = max; // v
-
-      delta = max - min;
-
-      if( delta == 0 ) { // white, grey, black
-        hsv.hue = hsv.saturation = 0;
-      }
-      else { // chroma
-        hsv.saturation = delta / max;
-
-        if( this.red == max ) {
-          hsv.hue = ( this.green - this.blue ) / delta; // between yellow & magenta
-        }
-        else if( this.green  == max ) {
-          hsv.hue = 2 + ( this.blue - this.red ) / delta; // between cyan & yellow
-        }
-        else {
-          hsv.hue = 4 + ( this.red - this.green ) / delta; // between magenta & cyan
-        }
-
-        hsv.hue = ((hsv.hue * 60) + 360) % 360; // degrees
-      }
-
-      hsv.alpha = this.alpha;
-
-      return hsv;
-    },
-    toHSL: function ( ) {
-      return this.toHSV().toHSL();
-    },
-
-    toRGB: function ( ) {
-      return this.clone();
-    }
-  });
-
-  transparent = color.fromObject({red: 0, blue: 0, green: 0, alpha: 0});
-
-
-  /* Like RGB above, this object describes what will become the HSV
-   * template object. This model handles hue, saturation and value.
-   * hue is the number of degrees around the color wheel, saturation
-   * describes how much color their is and value is the brightness.
-   */
-  registerModel('HSV', {
-    hue: 0,
-    saturation: 0,
-    value: 1,
-    alpha: 1,
-
-    shiftHue: cloneOnApply(function ( degrees ) {
-      var hue = (this.hue + degrees) % 360;
-      if (hue < 0) {
-        hue = (360 + hue) % 360;
-      }
-
-      this.hue = hue;
-    }),
-
-    devalueByAmount: cloneOnApply(function ( val ) {
-      this.value = Math.min(1, Math.max(this.value - val, 0));
-    }),
-
-    devalueByRatio: cloneOnApply(function ( val ) {
-      this.value = Math.min(1, Math.max(this.value * (1 - val), 0));
-    }),
-
-    valueByAmount: cloneOnApply(function ( val ) {
-      this.value = Math.min(1, Math.max(this.value + val, 0));
-    }),
-
-    valueByRatio: cloneOnApply(function ( val ) {
-      this.value = Math.min(1, Math.max(this.value * (1 + val), 0));
-    }),
-
-    desaturateByAmount: cloneOnApply(function ( val ) {
-      this.saturation = Math.min(1, Math.max(this.saturation - val, 0));
-    }),
-
-    desaturateByRatio: cloneOnApply(function ( val ) {
-      this.saturation = Math.min(1, Math.max(this.saturation * (1 - val), 0));
-    }),
-
-    saturateByAmount: cloneOnApply(function ( val ) {
-      this.saturation = Math.min(1, Math.max(this.saturation + val, 0));
-    }),
-
-    saturateByRatio: cloneOnApply(function ( val ) {
-      this.saturation = Math.min(1, Math.max(this.saturation * (1 + val), 0));
-    }),
-
-    schemeFromDegrees: function ( degrees ) {
-      var newColors = [];
-      for (var i = 0, j = degrees.length; i < j; i++) {
-        var col = this.clone();
-        col.hue = (this.hue + degrees[i]) % 360;
-        newColors.push(col);
-      }
-      return newColors;
-    },
-
-    complementaryScheme: function ( ) {
-      return this.schemeFromDegrees([0,180]);
-    },
-
-    splitComplementaryScheme: function ( ) {
-      return this.schemeFromDegrees([0,150,320]);
-    },
-
-    splitComplementaryCWScheme: function ( ) {
-      return this.schemeFromDegrees([0,150,300]);
-    },
-
-    splitComplementaryCCWScheme: function ( ) {
-      return this.schemeFromDegrees([0,60,210]);
-    },
-
-    triadicScheme: function ( ) {
-      return this.schemeFromDegrees([0,120,240]);
-    },
-
-    clashScheme: function ( ) {
-      return this.schemeFromDegrees([0,90,270]);
-    },
-
-    tetradicScheme: function ( ) {
-      return this.schemeFromDegrees([0,90,180,270]);
-    },
-
-    fourToneCWScheme: function ( ) {
-      return this.schemeFromDegrees([0,60,180,240]);
-    },
-
-    fourToneCCWScheme: function ( ) {
-      return this.schemeFromDegrees([0,120,180,300]);
-    },
-
-    fiveToneAScheme: function ( ) {
-      return this.schemeFromDegrees([0,115,155,205,245]);
-    },
-
-    fiveToneBScheme: function ( ) {
-      return this.schemeFromDegrees([0,40,90,130,245]);
-    },
-
-    fiveToneCScheme: function ( ) {
-      return this.schemeFromDegrees([0,50,90,205,320]);
-    },
-
-    fiveToneDScheme: function ( ) {
-      return this.schemeFromDegrees([0,40,155,270,310]);
-    },
-
-    fiveToneEScheme: function ( ) {
-      return this.schemeFromDegrees([0,115,230,270,320]);
-    },
-
-    sixToneCWScheme: function ( ) {
-      return this.schemeFromDegrees([0,30,120,150,240,270]);
-    },
-
-    sixToneCCWScheme: function ( ) {
-      return this.schemeFromDegrees([0,90,120,210,240,330]);
-    },
-
-    neutralScheme: function ( ) {
-      return this.schemeFromDegrees([0,15,30,45,60,75]);
-    },
-
-    analogousScheme: function ( ) {
-      return this.schemeFromDegrees([0,30,60,90,120,150]);
-    },
-
-    fromObject: function ( o ) {
-      if (o.hasOwnProperty('hue') &&
-          o.hasOwnProperty('saturation') &&
-          o.hasOwnProperty('value')) {
-        var hsv = factories.HSV();
-
-        hsv.hue = o.hue;
-        hsv.saturation = o.saturation;
-        hsv.value = o.value;
-        hsv.alpha = o.hasOwnProperty('alpha') ? o.alpha : 1;
-
-        return hsv;
-      }
-      // nothing matches, not an HSV object
-      return null;
-    },
-
-    _normalise: function ( ) {
-       this.hue %= 360;
-       this.saturation = Math.min(Math.max(0, this.saturation), 1);
-       this.value = Math.min(Math.max(0, this.value));
-       this.alpha = Math.min(1, Math.max(0, this.alpha));
-    },
-
-    toRGB: function ( ) {
-      this._normalise();
-
-      var rgb = factories.RGB();
-      var i;
-      var f, p, q, t;
-
-      if( this.saturation === 0 ) {
-        // achromatic (grey)
-        rgb.red = this.value;
-        rgb.green = this.value;
-        rgb.blue = this.value;
-        rgb.alpha = this.alpha;
-        return rgb;
-      }
-
-      var h = this.hue / 60;			// sector 0 to 5
-      i = Math.floor( h );
-      f = h - i;			// factorial part of h
-      p = this.value * ( 1 - this.saturation );
-      q = this.value * ( 1 - this.saturation * f );
-      t = this.value * ( 1 - this.saturation * ( 1 - f ) );
-
-      switch( i ) {
-        case 0:
-          rgb.red = this.value;
-          rgb.green = t;
-          rgb.blue = p;
-          break;
-        case 1:
-          rgb.red = q;
-          rgb.green = this.value;
-          rgb.blue = p;
-          break;
-        case 2:
-          rgb.red = p;
-          rgb.green = this.value;
-          rgb.blue = t;
-          break;
-        case 3:
-          rgb.red = p;
-          rgb.green = q;
-          rgb.blue = this.value;
-          break;
-        case 4:
-          rgb.red = t;
-          rgb.green = p;
-          rgb.blue = this.value;
-          break;
-        default:		// case 5:
-          rgb.red = this.value;
-          rgb.green = p;
-          rgb.blue = q;
-          break;
-      }
-
-      rgb.alpha = this.alpha;
-
-      return rgb;
-    },
-    toHSL: function() {
-      this._normalise();
-
-      var hsl = factories.HSL();
-
-      hsl.hue = this.hue;
-      var l = (2 - this.saturation) * this.value,
-          s = this.saturation * this.value;
-      if(l && 2 - l) {
-        s /= (l <= 1) ? l : 2 - l;
-      }
-      l /= 2;
-      hsl.saturation = s;
-      hsl.lightness = l;
-      hsl.alpha = this.alpha;
-
-      return hsl;
-    },
-
-    toHSV: function ( ) {
-      return this.clone();
-    }
-  });
-
-  registerModel('HSL', {
-    hue: 0,
-    saturation: 0,
-    lightness: 0,
-    alpha: 1,
-
-    darkenByAmount: cloneOnApply(function ( val ) {
-      this.lightness = Math.min(1, Math.max(this.lightness - val, 0));
-    }),
-
-    darkenByRatio: cloneOnApply(function ( val ) {
-      this.lightness = Math.min(1, Math.max(this.lightness * (1 - val), 0));
-    }),
-
-    lightenByAmount: cloneOnApply(function ( val ) {
-      this.lightness = Math.min(1, Math.max(this.lightness + val, 0));
-    }),
-
-    lightenByRatio: cloneOnApply(function ( val ) {
-      this.lightness = Math.min(1, Math.max(this.lightness * (1 + val), 0));
-    }),
-
-    fromObject: function ( o ) {
-      if ("string" == typeof o) {
-        return this._fromCSS( o );
-      }
-      if (o.hasOwnProperty('hue') &&
-          o.hasOwnProperty('saturation') &&
-          o.hasOwnProperty('lightness')) {
-        return this._fromHSL ( o );
-      }
-      // nothing matchs, not an RGB object
-    },
-
-    _fromCSS: function ( css ) {
-      var colorGroups = trim( css ).match( hsl_hsla_regex );
-
-      // if there is an "a" after "hsl", there must be a fourth parameter and the other way round
-      if (!colorGroups || (!!colorGroups[1] + !!colorGroups[5] === 1)) {
-        return null;
-      }
-
-      var hsl = factories.HSL();
-      hsl.hue        = (colorGroups[2] % 360 + 360) % 360;
-      hsl.saturation = Math.max(0, Math.min(parseInt(colorGroups[3], 10) / 100, 1));
-      hsl.lightness  = Math.max(0, Math.min(parseInt(colorGroups[4], 10) / 100, 1));
-      hsl.alpha      = !!colorGroups[5] ? Math.max(0, Math.min(1, parseFloat(colorGroups[6]))) : 1;
-
-      return hsl;
-    },
-
-    _fromHSL: function ( HSL ) {
-      var newHSL = factories.HSL();
-
-      newHSL.hue = HSL.hue;
-      newHSL.saturation = HSL.saturation;
-      newHSL.lightness = HSL.lightness;
-
-      newHSL.alpha = HSL.hasOwnProperty('alpha') ? HSL.alpha : 1;
-
-      return newHSL;
-    },
-
-    _normalise: function ( ) {
-       this.hue = (this.hue % 360 + 360) % 360;
-       this.saturation = Math.min(Math.max(0, this.saturation), 1);
-       this.lightness = Math.min(Math.max(0, this.lightness));
-       this.alpha = Math.min(1, Math.max(0, this.alpha));
-    },
-
-    toHSL: function() {
-      return this.clone();
-    },
-    toHSV: function() {
-      this._normalise();
-
-      var hsv = factories.HSV();
-
-      // http://ariya.blogspot.com/2008/07/converting-between-hsl-and-hsv.html
-      hsv.hue = this.hue; // H
-      var l = 2 * this.lightness,
-          s = this.saturation * ((l <= 1) ? l : 2 - l);
-      hsv.value = (l + s) / 2; // V
-      hsv.saturation = ((2 * s) / (l + s)) || 0; // S
-      hsv.alpha = this.alpha;
-
-      return hsv;
-    },
-    toRGB: function() {
-      return this.toHSV().toRGB();
-    }
-  });
-
-  // Package specific exports
-
-  /* the Color function is a factory for new color objects.
-   */
-  function Color( o ) {
-    return color.fromObject( o );
-  }
-  Color.isValid = function( str ) {
-    var key, c = Color( str );
-
-    var length = 0;
-    for(key in c) {
-      if(c.hasOwnProperty(key)) {
-        length++;
-      }
-    }
-
-    return length > 0;
-  };
-  net.brehaut.Color = Color;
-}).call(net.brehaut);
-
-/* Export to CommonJS
-*/
-var module;
-if(module) {
-  module.exports.Color = net.brehaut.Color;
-}
--- a/service/pilight/static/index.html	Sun Apr 21 02:48:58 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-<!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>
-    <script src="//bigasterisk.com/lib/polymer/0.2.3/polymer.js"></script>
-    <link rel="import" href="static/big-picker.html">
-    <style>
-      body {
-       background: #5c5c5c;
-       color: #E2E2E2;
-     }
-    </style>
-  </head>
-  <body>
-
-    <polymer-element name="led-output" attributes="url color">
-      <!--
-      First fetches the first led color and writes it on the color
-      attribute, then whenever color changes, 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;
-              this.enableWrites = false;
-
-              var retryFetch = function (triesLeft) {
-                  if (triesLeft < 1) {
-                      return;
-                  }
-                  $.ajax({
-                      type: "GET",
-                      url: "led",
-                      dataType: "json",
-                      success: function(result) {
-                          if (!result.length) {
-                              setTimeout(function() {
-                                  retryFetch(triesLeft - 1);
-                              }.bind(this), 100);
-                              return;
-                          }
-                          this.color = result[0];
-                          this.enableWrites = true;
-                      }.bind(this)
-                  });
-              }.bind(this);
-              retryFetch(5);
-          },
-          colorChanged: function() {
-              if (!this.enableWrites) {
-                  return;
-              }
-              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>
-        LED color:
-        <big-picker hex="{{c1}}"></big-picker>
-        <led-output which="led" color="{{c1}}"></led-output>
-      </template>
-    </polymer-element>
-
-    <pilight-page></pilight-page>
-
-    <div>
-      DHT: <span id="dht"></span>
-      <div id="temperature" style="background: #034c4d"></div>
-      <div id="humidity" style="background: #663d66"></div>
-    </div>
-
-    <script>
-    $(function() {
-        function update() {
-            $.getJSON("dht", function(result) {
-                result['tempF'] = 1.8 * result['temperature'] + 32;
-                result['time'] = new Date().toLocaleString();
-                $("#dht").text(JSON.stringify(result));
-                $("#temperature")
-                    .text(result['tempF'] + " deg F")
-                    .css('width', result['temperature'] * 10);
-                $("#humidity")
-                    .text(result['humidity'] + " humidity")
-                    .css('width', result['humidity'] * 10);
-            });
-        }
-
-        function loop() {
-            update();
-            setTimeout(function() {
-                requestAnimationFrame(loop);
-            }, 2000);
-        }
-        $.getJSON("dht", loop);
-    });
-    </script>
-  </body>
-</html>