-
Notifications
You must be signed in to change notification settings - Fork 0
/
geofence_monitor.cml
213 lines (161 loc) · 5.36 KB
/
geofence_monitor.cml
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
(* This structure is populated with HAMR-generated code *)
structure API =
struct
val empty_byte_array = Word8Array.array 0 (Word8.fromInt 0);
fun logInfo s = (
#(api_logInfo) s empty_byte_array
);
fun print_buffer buffer = (
#(raw_print_buffer) (Word8Array.substring buffer 0 (Word8Array.length buffer)) empty_byte_array
)
val data_t_max_payload = 8192 - 8;
val keep_in_zoneSizeBytes = 48;
val keep_out_zoneSizeBytes = 48;
val observedSizeBytes = data_t_max_payload;
val outputSizeBytes = data_t_max_payload;
fun get_keep_in_zone buffer = (
if Word8Array.length buffer >= keep_in_zoneSizeBytes then
#(api_get_keep_in_zones) "" buffer
else
logInfo (String.concat ["ERROR: get_keep_in_zone buffer too small"])
)
fun get_keep_out_zone buffer = (
if Word8Array.length buffer >= keep_out_zoneSizeBytes then
#(api_get_keep_out_zones) "" buffer
else
logInfo (String.concat ["ERROR: get_keep_out_zone buffer too small"])
)
fun get_observed buffer = (
if Word8Array.length buffer >= observedSizeBytes then
#(api_get_observed) "" buffer
else
logInfo (String.concat ["ERROR: observed buffer too small"])
)
fun send_output buffer = (
if Word8Array.length buffer <= outputSizeBytes then
#(api_send_output) (Word8Array.substring buffer 0 (Word8Array.length buffer)) empty_byte_array
else
logInfo (String.concat ["ERROR: output buffer too large"])
);
fun send_alert () = (
#(api_send_alert) "" empty_byte_array
);
fun toHexDigit nibble =
let val nibbleValue = Word8.toInt nibble
in case (nibbleValue)
of (0) => "0"
| (1) => "1"
| (2) => "2"
| (3) => "3"
| (4) => "4"
| (5) => "5"
| (6) => "6"
| (7) => "7"
| (8) => "8"
| (9) => "9"
| (10) => "a"
| (11) => "b"
| (12) => "c"
| (13) => "d"
| (14) => "e"
| (15) => "f"
| otherwise => "xDohx"
end;
fun toHex byte =
let val highNibble = (Word8.>> byte 4)
val lowNibble = (Word8.>> (Word8.<< byte 4) 4)
in String.concat [toHexDigit highNibble, toHexDigit lowNibble]
end;
fun word8ArrayToHex bytes =
let val length = (Word8Array.length bytes)
fun get i =
if i >= length then "" else
String.concat [toHex (Word8Array.sub bytes i), get (i + 1)]
in get(0)
end;
fun float2double float_byte_array double_byte_array =
#(float2double) float_byte_array double_byte_array;
end;
structure Geofence_Monitor =
struct
exception ERR string string;
val w8zero = Word8.fromInt 0;
(*---------------------------------------------------------------------------*)
(* Declare input buffers as global variables. *)
(*---------------------------------------------------------------------------*)
val kizone_buffer = Word8Array.array API.keep_in_zoneSizeBytes w8zero
val kozone_buffer = Word8Array.array API.keep_out_zoneSizeBytes w8zero
val observed_buffer = Word8Array.array API.observedSizeBytes w8zero
val emptybuf = Word8Array.array 0 w8zero;
fun clear buffer =
let val len = Word8Array.length buffer
fun zero i = Word8Array.update buffer i w8zero
fun loop j = if j < len then (zero j; loop (j+1)) else ()
in
loop 0
end;
fun fill_buffers() =
let in
API.get_keep_in_zone kizone_buffer
; API.get_keep_out_zone kozone_buffer
; API.get_observed observed_buffer
end
val out_buffer = Word8Array.array API.outputSizeBytes w8zero;
fun geofence_monitor () =
let val () = fill_buffers()
in
if Word8Array.sub observed_buffer 0 <> Word8.fromInt 0 then (
(* just pass the message onto the WPM *)
API.logInfo("STRIPPED Ver: just passing on the AutomationResponse to WPM");
clear out_buffer;
Word8Array.copy observed_buffer 1 (Word8Array.length observed_buffer - 1) out_buffer 0;
API.send_output out_buffer
)
else()
end
end (* Geofence_Monitor *)
(* This structure is populated with developer-written code *)
structure Client =
struct
fun initialise() = ();
fun timeTriggered() = (
Geofence_Monitor.geofence_monitor()
);
(* ===========================================================*
* The methods below are not currently used in HAMR/Slang *
* ===========================================================*)
fun activate() = ();
fun deactivate() = ();
fun finalise() = ();
fun recover() = ();
end;
(* This structure is populated with HAMR-generated code *)
structure Control =
struct
val singleton_byte_array = Word8Array.array 1 (Word8.fromInt 0);
fun pacer_emit() =
(#(sb_pacer_notification_emit) "" singleton_byte_array;
Word8Array.sub singleton_byte_array 0 <> Word8.fromInt 0);
fun pacer_wait() =
(#(sb_pacer_notification_wait) "" singleton_byte_array;
Word8Array.sub singleton_byte_array 0 <> Word8.fromInt 0);
val empty_byte_array = Word8Array.array 0 (Word8.fromInt 0);
fun receiveInput() = (#(api_receiveInput) "" empty_byte_array);
fun sendOutput() = (#(api_sendOutput) "" empty_byte_array);
fun loop () =
if pacer_wait() then
((*API.logInfo("Welcome to CakeML geofence_monitor_control");*)
receiveInput();
Client.timeTriggered();
sendOutput();
pacer_emit();
loop())
else
loop();
fun emitLoop() =
(pacer_emit();
loop());
end;
(* Startup *)
val _ = Client.initialise();
val _ = Control.emitLoop();