-
Notifications
You must be signed in to change notification settings - Fork 0
/
driver.hms
134 lines (95 loc) · 2.91 KB
/
driver.hms
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
// Questions:
// When is a driver invoked?
// - During bootup and is then suspended (quice nice)
// - Everytime a device-request is made (quite easy)
// => For the outside, it should seem like the driver is a singleton (only one instance of the driver per server)
// How is persistent data saved?
// - Homescript key-value store? (currently very ugly)
// - The configuration is saved seperately.
// During boot?
fn init() {
// Initializes driver stuff here
}
// Interacts with the device?
fn process_request() {
}
// How can external scripts interact with the driver?
// Like a normal script (only use special public wrapper functions) (very nice actually)
// => You normally know which device to `talk to`.
// Problem: similar devices (smart outlets) with different drivers
// Maybe create classes / hierachies for the different device types
// - Device
// - Input
// - Output
// - Outlet
// - Power
// - Power
// No: implement it like go: a driver can `provide` functionality.
// Depending on how much of that functionality is implemented, general device-agnostic functions can be used to control the device.
// General functions can be:
// - set_power (on / off) : switches, lamps
// - Set_power_percent (0..100) : dimmers
// - set_brightness (0..100) : lamps
// - set_color (hex) : lamps
// - set_color_temperature (0..100) : lamps
// - set_color_temperature (0..100) : lamps
// - report_power(): int
@Device {
type: lamp // ident,
icon: "md-icon",
implements {
power, power_percent, color_temperature, // idents
}
}
// OR: implement classes or methods on objects
// in this case: the type system must be redone: compatibility can also fail if there is a name mismatch
type ShellyDuo = {
}
methods on ShellyDuo {
fn set_power() {
}
}
// The driver is automatically invoked using the device and all required params?
// If this throws an error, the driver does not crash but an eror is reported.
fn set_power(device: ShellyDuo, power: bool) {
http(device.url, ...)
}
//
// EXAMPLE 0
//
// The `@foo` denots a singleton instance that is valid globally and managed / saved between runs of the script.
// The homescript host must provice a single0
import state from driver;
import @Device, @Driver from driver;
type Node = {
url: str,
name: str,
token: str,
}
@Driver // Singleton
type NodeManagerDriver = {
nodes: [Node]
};
@Device // Singleton
type NodeSwitch = {
id: str,
targetNode: ?str,
};
provide Driver {
fn init(driver) {
...
}
fn report_health(driver) {
}
}
// The dependency chain here is required so that the extractors below work.
impl Device : Driver {
fn set_power(@Device, @Driver, power: bool) {
for node in driver.nodes {
send_node(node, device, power);
}
}
}
fn main() {
Driver.set_power(true)
}