aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Crute <mcrute@gmail.com>2016-09-24 16:46:59 -0700
committerMike Crute <mcrute@gmail.com>2016-09-24 16:46:59 -0700
commit88a0976174eb96867af4c968fc72716f87e54094 (patch)
tree161737f5a0c5e5c96a63797e5fb999f027875b16
parent3ccc02f8f1c08fc82f581e9b3eb4315b42614c8e (diff)
downloadgo-inform-88a0976174eb96867af4c968fc72716f87e54094.tar.bz2
go-inform-88a0976174eb96867af4c968fc72716f87e54094.tar.xz
go-inform-88a0976174eb96867af4c968fc72716f87e54094.zip
Split messages again
-rw-r--r--inform/rx_messages.go (renamed from inform/messages.go)105
-rw-r--r--inform/server.go92
-rw-r--r--inform/tx_messages.go69
3 files changed, 179 insertions, 87 deletions
diff --git a/inform/messages.go b/inform/rx_messages.go
index 3dd8f6d..68fd393 100644
--- a/inform/messages.go
+++ b/inform/rx_messages.go
@@ -1,80 +1,11 @@
1package inform 1package inform
2 2
3// Messages we receive from devices
4
3import ( 5import (
4 "encoding/json" 6 "encoding/json"
5 "strconv"
6 "time"
7) 7)
8 8
9type AdminMetadata struct {
10 Id string `json:"_id"`
11 Language string `json:"lang"`
12 Username string `json:"name"`
13 Password string `json:"x_password"`
14}
15
16type CommandMessage struct {
17 Metadata *AdminMetadata `json:"_admin,omitempty"`
18 Id string `json:"_id,omitempty"`
19 Type string `json:"_type"`
20 Command string `json:"cmd"`
21 DateTime string `json:"datetime"`
22 DeviceId string `json:"device_id,omitempty"`
23 MacAddress string `json:"mac,omitempty"`
24 Model string `json:"model,omitempty"`
25 OffVoltage int `json:"off_volt,omitempty"`
26 Port int `json:"port"`
27 SensorId string `json:"sId,omitempty"`
28 ServerTime string `json:"server_time_in_utc"`
29 Time int64 `json:"time"`
30 Timer int `json:"timer"`
31 Value int `json:"val"`
32 Voltage int `json:"volt,omitempty"`
33}
34
35func NewOutputCommand(port, val, timer int) *CommandMessage {
36 return &CommandMessage{
37 Type: "cmd",
38 Command: "mfi-output",
39 DateTime: time.Now().Format(time.RFC3339),
40 Port: port,
41 ServerTime: unixMicroPSTString(),
42 Time: unixMicroPST(),
43 Timer: timer,
44 Value: val,
45 }
46}
47
48type NoopMessage struct {
49 Type string `json:"_type"`
50 Interval int `json:"interval"`
51 ServerTimeUTC string `json:"server_time_in_utc"`
52}
53
54func unixMicroPST() int64 {
55 l, _ := time.LoadLocation("America/Los_Angeles")
56 tnano := time.Now().In(l).UnixNano()
57 return tnano / int64(time.Millisecond)
58}
59
60func unixMicroPSTString() string {
61 return strconv.FormatInt(unixMicroPST(), 10)
62}
63
64func unixMicroUTCString() string {
65 tnano := time.Now().UTC().UnixNano()
66 t := tnano / int64(time.Millisecond)
67 return strconv.FormatInt(t, 10)
68}
69
70func NewNoop(interval int) *NoopMessage {
71 return &NoopMessage{
72 Type: "noop",
73 Interval: interval,
74 ServerTimeUTC: unixMicroUTCString(),
75 }
76}
77
78type DeviceMessage struct { 9type DeviceMessage struct {
79 IsDefault bool `json:"default"` 10 IsDefault bool `json:"default"`
80 IP string `json:"ip"` 11 IP string `json:"ip"`
@@ -86,6 +17,22 @@ type DeviceMessage struct {
86 Outputs []*OutputInfo 17 Outputs []*OutputInfo
87} 18}
88 19
20type OutputInfo struct {
21 Id string
22 Port int
23 OutputState bool
24 EnergySum float64
25 VoltageRMS float64
26 PowerFactor float64
27 CurrentRMS float64
28 Watts float64
29 ThisMonth float64
30 LastMonth float64
31 Dimmer bool
32 DimmerLevel int
33 DimmerLockSetting int
34}
35
89func (m *DeviceMessage) UnmarshalJSON(data []byte) error { 36func (m *DeviceMessage) UnmarshalJSON(data []byte) error {
90 type Alias DeviceMessage 37 type Alias DeviceMessage
91 aux := &struct { 38 aux := &struct {
@@ -144,19 +91,3 @@ func (m *DeviceMessage) UnmarshalJSON(data []byte) error {
144 91
145 return nil 92 return nil
146} 93}
147
148type OutputInfo struct {
149 Id string
150 Port int
151 OutputState bool
152 EnergySum float64
153 VoltageRMS float64
154 PowerFactor float64
155 CurrentRMS float64
156 Watts float64
157 ThisMonth float64
158 LastMonth float64
159 Dimmer bool
160 DimmerLevel int
161 DimmerLockSetting int
162}
diff --git a/inform/server.go b/inform/server.go
new file mode 100644
index 0000000..7e33a86
--- /dev/null
+++ b/inform/server.go
@@ -0,0 +1,92 @@
1package inform
2
3import (
4 "fmt"
5 "log"
6 "net/http"
7 "time"
8)
9
10type StateTree struct {
11 states map[string]map[int]int
12}
13
14func NewStateTree() *StateTree {
15 return &StateTree{make(map[string]map[int]int)}
16}
17
18func (t *StateTree) ensureNode(device string, port int) {
19 _, ok := t.states[device]
20 if !ok {
21 t.states[device] = make(map[int]int)
22 }
23
24 _, ok = t.states[device][port]
25 if !ok {
26 t.states[device][port] = 0
27 }
28}
29
30func (t *StateTree) GetState(device string, port int) int {
31 t.ensureNode(device, port)
32 return t.states[device][port]
33}
34
35func (t *StateTree) SetState(device string, port, value int) {
36 t.ensureNode(device, port)
37 t.states[device][port] = value
38}
39
40func Log(handler http.Handler) http.Handler {
41 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
42 handler.ServeHTTP(w, r)
43 t := time.Now().Format("02/Jan/2006 15:04:05")
44 log.Printf("%s - - [%s] \"%s %s %s\"", r.RemoteAddr, t, r.Method, r.URL, r.Proto)
45 // Addr - - [D/M/Y H:M:S] "Method RequestURI Proto" Code Size
46 // 127.0.0.1 - - [24/Sep/2016 14:30:35] "GET / HTTP/1.1" 200 -
47 })
48}
49
50type InformHandler struct {
51 Codec *Codec
52 StateTree *StateTree
53}
54
55func (h *InformHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
56 if r.Method != http.MethodPost {
57 http.Error(w, "405 Method Not Allowed", http.StatusMethodNotAllowed)
58 return
59 }
60
61 if r.URL != nil && r.URL.Path != "/inform" {
62 http.Error(w, "404 Not Found", http.StatusNotFound)
63 return
64 }
65
66 msg, err := h.Codec.Unmarshal(r.Body)
67 if err != nil {
68 http.Error(w, "Bad Request", http.StatusBadRequest)
69 return
70 }
71
72 pl := NewInformWrapper()
73 copy(pl.MacAddr, msg.MacAddr)
74 pl.SetEncrypted(true)
75
76 // TODO: compare current state to tree and update
77
78 res, err := h.Codec.Marshal(pl)
79 if err != nil {
80 http.Error(w, "Server Error", 500)
81 return
82 }
83
84 fmt.Fprintf(w, "%s", res)
85}
86
87func NewServer(handler *InformHandler) *http.Server {
88 return &http.Server{
89 Addr: ":6080",
90 Handler: Log(handler),
91 }
92}
diff --git a/inform/tx_messages.go b/inform/tx_messages.go
new file mode 100644
index 0000000..0021ef3
--- /dev/null
+++ b/inform/tx_messages.go
@@ -0,0 +1,69 @@
1package inform
2
3// Messages we send to devices
4
5import (
6 "strconv"
7 "time"
8)
9
10type CommandMessage struct {
11 Id string `json:"_id,omitempty"`
12 Type string `json:"_type"`
13 Command string `json:"cmd"`
14 DateTime string `json:"datetime"`
15 DeviceId string `json:"device_id,omitempty"`
16 MacAddress string `json:"mac,omitempty"`
17 Model string `json:"model,omitempty"`
18 OffVoltage int `json:"off_volt,omitempty"`
19 Port int `json:"port"`
20 SensorId string `json:"sId,omitempty"`
21 ServerTime string `json:"server_time_in_utc"`
22 Time int64 `json:"time"`
23 Timer int `json:"timer"`
24 Value int `json:"val"`
25 Voltage int `json:"volt,omitempty"`
26}
27
28func NewOutputCommand(port, val, timer int) *CommandMessage {
29 return &CommandMessage{
30 Type: "cmd",
31 Command: "mfi-output",
32 DateTime: time.Now().Format(time.RFC3339),
33 Port: port,
34 ServerTime: unixMicroPSTString(),
35 Time: unixMicroPST(),
36 Timer: timer,
37 Value: val,
38 }
39}
40
41type NoopMessage struct {
42 Type string `json:"_type"`
43 Interval int `json:"interval"`
44 ServerTimeUTC string `json:"server_time_in_utc"`
45}
46
47func unixMicroPST() int64 {
48 l, _ := time.LoadLocation("America/Los_Angeles")
49 tnano := time.Now().In(l).UnixNano()
50 return tnano / int64(time.Millisecond)
51}
52
53func unixMicroPSTString() string {
54 return strconv.FormatInt(unixMicroPST(), 10)
55}
56
57func unixMicroUTCString() string {
58 tnano := time.Now().UTC().UnixNano()
59 t := tnano / int64(time.Millisecond)
60 return strconv.FormatInt(t, 10)
61}
62
63func NewNoop(interval int) *NoopMessage {
64 return &NoopMessage{
65 Type: "noop",
66 Interval: interval,
67 ServerTimeUTC: unixMicroUTCString(),
68 }
69}