-
Notifications
You must be signed in to change notification settings - Fork 1
/
devices.go
160 lines (126 loc) · 3.85 KB
/
devices.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package wbgong
import (
"fmt"
"sort"
)
// Device is a user representation of MQTT device
//
// Devices are passed to observers, but observers must not
// access Devices async with Driver (use them only as references
// to pass them via Events)
//
// External device objects are only created by Driver; driver doesn't access
// to these objects after passing AddExternalDevice event
type Device interface {
// Gets external driver ID (from /meta/driver)
GetDriverId() string
// Gets local driver object
GetDriver() DeviceDriver
// Sets transaction
SetTx(tx DriverTx)
// Gets device id
GetId() string
// Gets device title
GetTitle() Title
// Gets control by id
GetControl(id string) Control
// Lists controls
ControlsList() []Control
// Checks whether control with given id exists
HasControl(id string) bool
// Gets all device metadata
GetMeta() MetaInfo
// Gets all device metadata for /meta
GetMetaJson() MetaInfo
// Marks device as deleted
// Used by Driver frontend and device itself
MarkDeleted()
// Checks if device is marked as deleted
IsDeleted() bool
}
// LocalDevice is a user representation of local MQTT device
type LocalDevice interface {
Device
// Checks whether device is virtual
// * Virtual devices have value cache (ability to restore previous control values on load);
// * Non-virtual devices (physical devices) doesn't
// This flag is used by Driver
IsVirtual() bool
// Checks whether user wants to load previous values for device at load.
// This flag is used by Driver
DoLoadPrevious() bool
// Creates new control by args
// Returns 'future' value
CreateControl(args ControlArgs) func() (Control, error)
// Removes control by id
RemoveControl(id string) func() error
}
// ExternalDevice is a user representation of external MQTT device
// Provides extra methods to modify device via driver events
type ExternalDevice interface {
Device
// Add external control
AddControl(control Control) error
// Adds meta information from event
AcceptMeta(event NewExternalDeviceMetaEvent) error
// Sets device title
SetTitle(title Title)
// Internal function to remove control on cleanup
RemoveControl(id string)
}
// LocalDeviceArgs is a handy way to pass local device attributes
type LocalDeviceArgs interface {
SetVirtual(v bool) LocalDeviceArgs
SetDoLoadPrevious(v bool) LocalDeviceArgs
SetId(v string) LocalDeviceArgs
SetTitle(v Title) LocalDeviceArgs
SetDriver(v DeviceDriver) LocalDeviceArgs
GetID() *string
GetTitle() *Title
GetDriver() DeviceDriver
GetVirtual() bool
GetDoLoadPrevious() bool
}
// MetaInfo is a type that represents /meta/+ topics for drivers and controls
type MetaInfo map[string]interface{}
// Implementation of Stringer interface to print metadata correctly
func (m MetaInfo) String() (ret string) {
ret = "[ "
keys := make([]string, 0, len(m))
for key := range m {
keys = append(keys, key)
}
sort.Strings(keys)
for _, key := range keys {
ret += fmt.Sprintf("%s: '%v' ", key, m[key])
}
ret += "]"
return
}
// Delta calculates the difference between two MetaInfos and returns
// a new MetaInfo with delta containing these rows:
// - rows with the same key but different values;
// - rows from newMeta without the complementary ones in oldMeta - with values from newMeta;
// - rows from oldMeta without the complementary ones in newMeta - with empty values ("").
//
// For example:
//
// newMeta: [ "a": "123", "b": "xyz", "d": "0" ]
// oldMeta: [ "a": "456", "c": "hello", "d": "0" ]
// delta: [ "a": "123", "b": "xyz", "c": "" ]
func (m MetaInfo) Delta(oldMeta MetaInfo) (delta MetaInfo) {
delta = make(MetaInfo)
// find changed values
for key, newValue := range m {
if oldValue, ok := oldMeta[key]; !ok || (ok && oldValue != newValue) {
delta[key] = newValue
}
}
// find deleted values
for key := range oldMeta {
if _, ok := m[key]; !ok {
delta[key] = ""
}
}
return
}