diff options
author | Mike Crute <mcrute@gmail.com> | 2016-09-24 16:46:59 -0700 |
---|---|---|
committer | Mike Crute <mcrute@gmail.com> | 2016-09-24 16:46:59 -0700 |
commit | 88a0976174eb96867af4c968fc72716f87e54094 (patch) | |
tree | 161737f5a0c5e5c96a63797e5fb999f027875b16 | |
parent | 3ccc02f8f1c08fc82f581e9b3eb4315b42614c8e (diff) | |
download | go-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.go | 92 | ||||
-rw-r--r-- | inform/tx_messages.go | 69 |
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 @@ | |||
1 | package inform | 1 | package inform |
2 | 2 | ||
3 | // Messages we receive from devices | ||
4 | |||
3 | import ( | 5 | import ( |
4 | "encoding/json" | 6 | "encoding/json" |
5 | "strconv" | ||
6 | "time" | ||
7 | ) | 7 | ) |
8 | 8 | ||
9 | type 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 | |||
16 | type 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 | |||
35 | func 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 | |||
48 | type NoopMessage struct { | ||
49 | Type string `json:"_type"` | ||
50 | Interval int `json:"interval"` | ||
51 | ServerTimeUTC string `json:"server_time_in_utc"` | ||
52 | } | ||
53 | |||
54 | func unixMicroPST() int64 { | ||
55 | l, _ := time.LoadLocation("America/Los_Angeles") | ||
56 | tnano := time.Now().In(l).UnixNano() | ||
57 | return tnano / int64(time.Millisecond) | ||
58 | } | ||
59 | |||
60 | func unixMicroPSTString() string { | ||
61 | return strconv.FormatInt(unixMicroPST(), 10) | ||
62 | } | ||
63 | |||
64 | func unixMicroUTCString() string { | ||
65 | tnano := time.Now().UTC().UnixNano() | ||
66 | t := tnano / int64(time.Millisecond) | ||
67 | return strconv.FormatInt(t, 10) | ||
68 | } | ||
69 | |||
70 | func NewNoop(interval int) *NoopMessage { | ||
71 | return &NoopMessage{ | ||
72 | Type: "noop", | ||
73 | Interval: interval, | ||
74 | ServerTimeUTC: unixMicroUTCString(), | ||
75 | } | ||
76 | } | ||
77 | |||
78 | type DeviceMessage struct { | 9 | type 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 | ||
20 | type 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 | |||
89 | func (m *DeviceMessage) UnmarshalJSON(data []byte) error { | 36 | func (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 | |||
148 | type 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 @@ | |||
1 | package inform | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "log" | ||
6 | "net/http" | ||
7 | "time" | ||
8 | ) | ||
9 | |||
10 | type StateTree struct { | ||
11 | states map[string]map[int]int | ||
12 | } | ||
13 | |||
14 | func NewStateTree() *StateTree { | ||
15 | return &StateTree{make(map[string]map[int]int)} | ||
16 | } | ||
17 | |||
18 | func (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 | |||
30 | func (t *StateTree) GetState(device string, port int) int { | ||
31 | t.ensureNode(device, port) | ||
32 | return t.states[device][port] | ||
33 | } | ||
34 | |||
35 | func (t *StateTree) SetState(device string, port, value int) { | ||
36 | t.ensureNode(device, port) | ||
37 | t.states[device][port] = value | ||
38 | } | ||
39 | |||
40 | func 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 | |||
50 | type InformHandler struct { | ||
51 | Codec *Codec | ||
52 | StateTree *StateTree | ||
53 | } | ||
54 | |||
55 | func (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 | |||
87 | func 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 @@ | |||
1 | package inform | ||
2 | |||
3 | // Messages we send to devices | ||
4 | |||
5 | import ( | ||
6 | "strconv" | ||
7 | "time" | ||
8 | ) | ||
9 | |||
10 | type 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 | |||
28 | func 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 | |||
41 | type NoopMessage struct { | ||
42 | Type string `json:"_type"` | ||
43 | Interval int `json:"interval"` | ||
44 | ServerTimeUTC string `json:"server_time_in_utc"` | ||
45 | } | ||
46 | |||
47 | func unixMicroPST() int64 { | ||
48 | l, _ := time.LoadLocation("America/Los_Angeles") | ||
49 | tnano := time.Now().In(l).UnixNano() | ||
50 | return tnano / int64(time.Millisecond) | ||
51 | } | ||
52 | |||
53 | func unixMicroPSTString() string { | ||
54 | return strconv.FormatInt(unixMicroPST(), 10) | ||
55 | } | ||
56 | |||
57 | func unixMicroUTCString() string { | ||
58 | tnano := time.Now().UTC().UnixNano() | ||
59 | t := tnano / int64(time.Millisecond) | ||
60 | return strconv.FormatInt(t, 10) | ||
61 | } | ||
62 | |||
63 | func NewNoop(interval int) *NoopMessage { | ||
64 | return &NoopMessage{ | ||
65 | Type: "noop", | ||
66 | Interval: interval, | ||
67 | ServerTimeUTC: unixMicroUTCString(), | ||
68 | } | ||
69 | } | ||