projectsimulator 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/projectsimulator.rb +23 -410
- metadata +2 -42
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d6d7ab7020d9059697cd4a5d7e681cf876f560cc1837e74bd3eb0e896004a9c
|
4
|
+
data.tar.gz: d1c40af5df514a3a41b82d03610c3fd89c8938f27b87ade37518c3295e4f65b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ff10c8255f576a0bdd80920108ad6ef2e07ded1be62b84dae5a1beac65d8836ad80c21fb73fcc51c7e328dfb1f38621c60f28d05210a19953a588ee1261e73f
|
7
|
+
data.tar.gz: 20f8991ea5a55153acf1c1ef584c3063de630d64704fc174c2e99587fc8c24d0e8b589491d86577dab0d9c00650c2561917fef44e9a59a2276f714fe69ac9442
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/lib/projectsimulator.rb
CHANGED
@@ -2,10 +2,9 @@
|
|
2
2
|
|
3
3
|
# file: projectsimulator.rb
|
4
4
|
|
5
|
-
|
5
|
+
|
6
6
|
require 'easydom'
|
7
7
|
require 'app-routes'
|
8
|
-
require 'chronic_between'
|
9
8
|
|
10
9
|
|
11
10
|
module ProjectSimulator
|
@@ -127,430 +126,44 @@ module ProjectSimulator
|
|
127
126
|
alias find_request run_route
|
128
127
|
|
129
128
|
end
|
130
|
-
|
131
|
-
|
132
|
-
class Event
|
133
129
|
|
130
|
+
class Controller
|
131
|
+
|
132
|
+
attr_reader :macros
|
134
133
|
attr_accessor :title
|
135
|
-
attr_reader :triggers, :actions, :constraints, :messages
|
136
|
-
|
137
|
-
def initialize(e, time: nil, title: '', debug: false)
|
138
|
-
|
139
|
-
@time, @debug = time, debug
|
140
|
-
@title = e.text('event')
|
141
|
-
@actions = []
|
142
|
-
@triggers = []
|
143
|
-
@constraints = []
|
144
|
-
|
145
|
-
e.xpath('trigger').each do |x|
|
146
|
-
@triggers << Trigger.new(x.text().strip, time: time, debug: debug)\
|
147
|
-
.to_type
|
148
|
-
end
|
149
134
|
|
150
|
-
|
151
|
-
@actions << Action.new(x.text().strip, debug: debug).to_type
|
152
|
-
end
|
153
|
-
|
154
|
-
e.xpath('constraint').each do |x|
|
155
|
-
puts 'before Constraints.new'
|
156
|
-
@constraints << Constraint.new(x.text().strip, \
|
157
|
-
time: time, debug: debug).to_type
|
158
|
-
end
|
159
|
-
|
160
|
-
end
|
161
|
-
|
162
|
-
def match(trigger: nil, location: '')
|
163
|
-
|
164
|
-
@messages = []
|
165
|
-
|
166
|
-
h = {motion: MotionTrigger}
|
167
|
-
|
168
|
-
if @triggers.any? {|x| x.is_a? h[trigger.to_sym] and x.match } then
|
169
|
-
|
170
|
-
if @constraints.all?(&:match) then
|
171
|
-
|
172
|
-
@messages = @actions.map(&:call)
|
173
|
-
|
174
|
-
else
|
175
|
-
|
176
|
-
puts 'else reset?' if @debug
|
177
|
-
a = @constraints.select {|x| x.is_a? FrequencyConstraint }
|
178
|
-
puts 'a:' + a.inspect if @debug
|
179
|
-
a.each {|x| x.reset if x.counter > 0 }
|
180
|
-
return false
|
181
|
-
end
|
182
|
-
|
183
|
-
end
|
184
|
-
|
185
|
-
end
|
186
|
-
|
187
|
-
def time=(val)
|
188
|
-
@time = val
|
189
|
-
@constraints.each {|x| x.time = val if x.is_a? TimeConstraint }
|
190
|
-
end
|
191
|
-
|
192
|
-
def to_node()
|
135
|
+
def initialize(mcs, debug: false)
|
193
136
|
|
194
|
-
e = Rexle::Element.new(:event, attributes: {title: @title})
|
195
|
-
|
196
|
-
e.add node_collection(:triggers, @triggers)
|
197
|
-
e.add node_collection(:actions, @actions)
|
198
|
-
e.add node_collection(:constraints, @constraints)
|
199
|
-
|
200
|
-
return e
|
201
|
-
end
|
202
|
-
|
203
|
-
def to_rowx()
|
204
|
-
|
205
|
-
s = "event: %s\n\n" % @title
|
206
|
-
s + [@triggers, @actions, @constraints]\
|
207
|
-
.map {|x| x.collect(&:to_rowx).join("\n")}.join("\n")
|
208
|
-
end
|
209
|
-
|
210
|
-
private
|
211
|
-
|
212
|
-
def node_collection(name, a)
|
213
|
-
|
214
|
-
e = Rexle::Element.new(name)
|
215
|
-
a.each {|x| e.add x.to_node}
|
216
|
-
return e
|
217
|
-
|
218
|
-
end
|
219
|
-
|
220
|
-
end
|
221
|
-
|
222
|
-
class Action
|
223
|
-
include AppRoutes
|
224
|
-
|
225
|
-
attr_reader :to_type
|
226
|
-
|
227
|
-
def initialize(s, event: '', debug: false)
|
228
|
-
|
229
|
-
super()
|
230
137
|
@debug = debug
|
231
|
-
|
232
|
-
|
233
|
-
@
|
234
|
-
|
235
|
-
end
|
236
|
-
|
237
|
-
protected
|
238
|
-
|
239
|
-
def actions(params)
|
240
|
-
|
241
|
-
puts 'inside actions'
|
242
|
-
# e.g. Say 'Good morning'
|
243
|
-
#
|
244
|
-
get /say ['"]([^'"]+)/i do |s|
|
245
|
-
puts 's: ' + s.inspect if @debug
|
246
|
-
SayAction.new(s)
|
247
|
-
end
|
248
|
-
|
249
|
-
# e.g. webhook entered_kitchen
|
250
|
-
#
|
251
|
-
get /webhook (.*)/i do |name|
|
252
|
-
WebhookAction.new(name)
|
253
|
-
end
|
254
|
-
|
255
|
-
get /.*/ do
|
256
|
-
puts 'action unknown' if @debug
|
257
|
-
{}
|
258
|
-
end
|
259
|
-
|
260
|
-
end
|
261
|
-
|
262
|
-
private
|
263
|
-
|
264
|
-
alias find_action run_route
|
265
|
-
|
266
|
-
end
|
267
|
-
|
268
|
-
class Trigger
|
269
|
-
include AppRoutes
|
270
|
-
|
271
|
-
attr_reader :to_type
|
272
|
-
|
273
|
-
def initialize(s, time: nil, debug: false)
|
274
|
-
|
275
|
-
super()
|
276
|
-
@time, @debug = time, debug
|
277
|
-
params = {s: s}
|
278
|
-
puts 'inside Trigger'
|
279
|
-
puts 'params: ' + params.inspect
|
280
|
-
triggers(params)
|
281
|
-
@to_type = find_trigger(s)
|
282
|
-
|
283
|
-
end
|
284
|
-
|
285
|
-
protected
|
286
|
-
|
287
|
-
def triggers(params)
|
288
|
-
|
289
|
-
puts 'inside triggers'
|
290
|
-
|
291
|
-
# e.g. Motion detected in the kitchen
|
292
|
-
#
|
293
|
-
get /motion detected in the (.*)/i do |location|
|
294
|
-
puts 'motion detection trigger'
|
295
|
-
MotionTrigger.new(location)
|
296
|
-
end
|
297
|
-
|
298
|
-
end
|
299
|
-
|
300
|
-
private
|
301
|
-
|
302
|
-
alias find_trigger run_route
|
303
|
-
|
304
|
-
end
|
305
|
-
|
306
|
-
class Constraint
|
307
|
-
include AppRoutes
|
308
|
-
|
309
|
-
attr_reader :to_type
|
310
|
-
|
311
|
-
def initialize(s, time: nil, debug: false)
|
312
|
-
|
313
|
-
super()
|
314
|
-
@time, @debug = time, debug
|
315
|
-
|
316
|
-
params = {s: s }
|
317
|
-
constraints(params)
|
318
|
-
@to_type = find_constraint(s)
|
319
|
-
|
320
|
-
end
|
321
|
-
|
322
|
-
protected
|
323
|
-
|
324
|
-
def constraints(params)
|
325
|
-
|
326
|
-
puts 'inside constraints' if @debug
|
327
|
-
# e.g. Between 8am and 10am
|
328
|
-
#
|
329
|
-
get /^between (.*)/i do |s|
|
330
|
-
TimeConstraint.new(s, time: @time)
|
331
|
-
end
|
332
|
-
|
333
|
-
get /^on a (.*)/i do |s|
|
334
|
-
TimeConstraint.new(s, time: @time)
|
335
|
-
end
|
336
|
-
|
337
|
-
get /^(after .*)/i do |s|
|
338
|
-
TimeConstraint.new(s, time: @time)
|
339
|
-
end
|
340
|
-
|
341
|
-
get /^once only|only once|once|one time|1 time$/i do |s|
|
342
|
-
FrequencyConstraint.new(1, debug: @debug)
|
343
|
-
end
|
344
|
-
|
345
|
-
get /^twice only|only twice|twice|two times|2 times$/i do |s|
|
346
|
-
FrequencyConstraint.new(2, debug: @debug)
|
347
|
-
end
|
348
|
-
|
349
|
-
get /^(Maximum|Max|Up to) ?three times|3 times$/i do |s|
|
350
|
-
FrequencyConstraint.new(3, debug: @debug)
|
351
|
-
end
|
352
|
-
|
353
|
-
get /^(Maximum|Max|Up to) ?four times|4 times$/i do |s|
|
354
|
-
FrequencyConstraint.new(4, debug: @debug)
|
355
|
-
end
|
356
|
-
|
357
|
-
end
|
358
|
-
|
359
|
-
private
|
360
|
-
|
361
|
-
alias find_constraint run_route
|
362
|
-
end
|
363
|
-
|
364
|
-
class MotionTrigger
|
138
|
+
@syslog = []
|
139
|
+
|
140
|
+
@macros = mcs.macros
|
365
141
|
|
366
|
-
attr_reader :location
|
367
|
-
|
368
|
-
def initialize(locationx, location: locationx)
|
369
|
-
@location = location
|
370
|
-
end
|
371
|
-
|
372
|
-
def match()
|
373
|
-
@location.downcase == location.downcase
|
374
|
-
end
|
375
|
-
|
376
|
-
def to_node()
|
377
|
-
Rexle::Element.new(:trigger, \
|
378
|
-
attributes: {type: :motion, location: @location})
|
379
|
-
end
|
380
|
-
|
381
|
-
def to_rowx()
|
382
|
-
"trigger: Motion detected in the %s" % @location
|
383
142
|
end
|
384
|
-
|
385
|
-
end
|
386
|
-
|
387
|
-
class SayAction
|
388
|
-
|
389
|
-
def initialize(s, text: s)
|
390
|
-
@s = s
|
391
|
-
end
|
392
|
-
|
393
|
-
def call()
|
394
|
-
"say: %s" % @s
|
395
|
-
end
|
396
143
|
|
397
|
-
def to_node()
|
398
|
-
Rexle::Element.new(:action, attributes: {type: :say, text: @s})
|
399
|
-
end
|
400
|
-
|
401
|
-
def to_rowx()
|
402
|
-
"action: say %s" % @s
|
403
|
-
end
|
404
|
-
|
405
|
-
end
|
406
|
-
|
407
|
-
class WebhookAction
|
408
|
-
|
409
|
-
attr_accessor :url
|
410
|
-
|
411
|
-
def initialize(namex, name: namex, url: '127.0.0.1')
|
412
|
-
@name = name
|
413
|
-
@url = url
|
414
|
-
end
|
415
|
-
|
416
|
-
def call()
|
417
|
-
"webhook: %s" % @url
|
418
|
-
end
|
419
|
-
|
420
|
-
def to_node()
|
421
|
-
Rexle::Element.new(:action, \
|
422
|
-
attributes: {type: :webhook, name: @name, url: @url})
|
423
|
-
end
|
424
|
-
|
425
|
-
def to_rowx()
|
426
|
-
s = "action: webhook %s" % @name
|
427
|
-
s += "\n url: %s" % @url
|
428
|
-
end
|
429
|
-
|
430
|
-
end
|
431
|
-
|
432
|
-
class TimeConstraint
|
433
|
-
|
434
|
-
attr_accessor :time
|
435
|
-
|
436
|
-
def initialize(timesx, times: timesx, time: nil)
|
437
|
-
@times, @time = times, time
|
438
|
-
end
|
439
|
-
|
440
|
-
def match()
|
441
|
-
ChronicBetween.new(@times).within?(@time)
|
442
|
-
end
|
443
144
|
|
444
|
-
def
|
445
|
-
Rexle::Element.new(:constraint, \
|
446
|
-
attributes: {type: :time, times: @times})
|
447
|
-
end
|
448
|
-
|
449
|
-
def to_rowx()
|
450
|
-
"constraint: %s" % @times
|
451
|
-
end
|
452
|
-
|
453
|
-
end
|
454
|
-
|
455
|
-
class FrequencyConstraint
|
456
|
-
|
457
|
-
def initialize(freqx, freq: freqx, debug: false)
|
458
|
-
@freq, @debug = freq, debug
|
459
|
-
@counter = 0
|
460
|
-
end
|
461
|
-
|
462
|
-
def counter()
|
463
|
-
@counter
|
464
|
-
end
|
465
|
-
|
466
|
-
def increment()
|
467
|
-
@counter += 1
|
468
|
-
end
|
469
|
-
|
470
|
-
def match()
|
471
|
-
@counter < @freq
|
472
|
-
end
|
473
|
-
|
474
|
-
def reset()
|
475
|
-
puts 'resetting' if @debug
|
476
|
-
@counter = 0
|
477
|
-
end
|
478
|
-
|
479
|
-
def to_node()
|
480
|
-
Rexle::Element.new(:constraint, \
|
481
|
-
attributes: {type: :frequency, freq: @freq})
|
482
|
-
end
|
483
|
-
|
484
|
-
def to_rowx()
|
485
|
-
|
486
|
-
freq = case @freq
|
487
|
-
when 1
|
488
|
-
'Once'
|
489
|
-
when 2
|
490
|
-
'Twice'
|
491
|
-
else
|
492
|
-
"Maximum %s times" % @freq
|
493
|
-
end
|
494
|
-
|
495
|
-
"constraint: %s" % freq
|
496
|
-
|
497
|
-
end
|
498
|
-
|
499
|
-
end
|
500
|
-
|
501
|
-
class Controller
|
502
|
-
|
503
|
-
attr_reader :events
|
504
|
-
attr_accessor :time
|
505
|
-
|
506
|
-
def initialize(s, time: Time.now, debug: false)
|
507
|
-
|
508
|
-
@time, @debug = time, debug
|
509
|
-
|
510
|
-
doc = Rexle.new(RowX.new(s).to_xml)
|
511
|
-
|
512
|
-
@events = doc.root.xpath('item')\
|
513
|
-
.map {|e| Event.new(e, time: @time, debug: debug) }
|
514
|
-
|
515
|
-
end
|
516
|
-
|
517
|
-
def time=(val)
|
518
|
-
@time = val
|
519
|
-
@events.each {|event| event.time = val }
|
520
|
-
end
|
521
|
-
|
522
|
-
def to_doc()
|
145
|
+
def trigger(name, detail={})
|
523
146
|
|
524
|
-
|
525
|
-
@events.each {|event| doc.root.add event.to_node }
|
526
|
-
return doc
|
527
|
-
|
528
|
-
end
|
529
|
-
|
530
|
-
def to_rowx()
|
531
|
-
@events.collect(&:to_rowx).join("\n\n#{'-'*50}\n\n")
|
532
|
-
end
|
533
|
-
|
534
|
-
def trigger(name, location: '')
|
535
|
-
|
536
|
-
events = @events.select do |event|
|
147
|
+
macros = @macros.select do |macro|
|
537
148
|
|
538
|
-
puts '
|
149
|
+
puts 'macro: ' + macro.inspect if @debug
|
539
150
|
|
540
|
-
|
151
|
+
valid_trigger = macro.match?(name, detail)
|
152
|
+
|
153
|
+
puts 'valid_trigger: ' + valid_trigger.inspect if @debug
|
154
|
+
|
155
|
+
if valid_trigger then
|
156
|
+
@syslog << [Time.now, :trigger, name]
|
157
|
+
@syslog << [Time.now, :macro, macro.title]
|
158
|
+
end
|
159
|
+
|
160
|
+
valid_trigger
|
541
161
|
|
542
162
|
end
|
543
163
|
|
544
|
-
puts '
|
545
|
-
|
546
|
-
events.each do |event|
|
547
|
-
c = event.constraints.select {|x| x.is_a? FrequencyConstraint }
|
548
|
-
puts 'c:' + c.inspect
|
549
|
-
c.each(&:increment)
|
550
|
-
end
|
551
|
-
|
552
|
-
events.flat_map(&:messages)
|
164
|
+
puts 'macros: ' + macros.inspect if @debug
|
553
165
|
|
166
|
+
macros.flat_map(&:run)
|
554
167
|
end
|
555
168
|
|
556
169
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: projectsimulator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Robertson
|
@@ -35,28 +35,8 @@ cert_chain:
|
|
35
35
|
2GrtfOXGVOS+2jvmCQC6vU+ew9WBxiDUbebI95TeTwMs2o0cs3IASXX5rIn4TPcz
|
36
36
|
SCccB3fVg2yfsy5DivaWaZwg
|
37
37
|
-----END CERTIFICATE-----
|
38
|
-
date: 2020-
|
38
|
+
date: 2020-08-18 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
|
-
- !ruby/object:Gem::Dependency
|
41
|
-
name: rowx
|
42
|
-
requirement: !ruby/object:Gem::Requirement
|
43
|
-
requirements:
|
44
|
-
- - ">="
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: 0.7.0
|
47
|
-
- - "~>"
|
48
|
-
- !ruby/object:Gem::Version
|
49
|
-
version: '0.7'
|
50
|
-
type: :runtime
|
51
|
-
prerelease: false
|
52
|
-
version_requirements: !ruby/object:Gem::Requirement
|
53
|
-
requirements:
|
54
|
-
- - ">="
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
version: 0.7.0
|
57
|
-
- - "~>"
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
version: '0.7'
|
60
40
|
- !ruby/object:Gem::Dependency
|
61
41
|
name: easydom
|
62
42
|
requirement: !ruby/object:Gem::Requirement
|
@@ -97,26 +77,6 @@ dependencies:
|
|
97
77
|
- - ">="
|
98
78
|
- !ruby/object:Gem::Version
|
99
79
|
version: 0.1.19
|
100
|
-
- !ruby/object:Gem::Dependency
|
101
|
-
name: chronic_between
|
102
|
-
requirement: !ruby/object:Gem::Requirement
|
103
|
-
requirements:
|
104
|
-
- - "~>"
|
105
|
-
- !ruby/object:Gem::Version
|
106
|
-
version: '0.3'
|
107
|
-
- - ">="
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: 0.3.1
|
110
|
-
type: :runtime
|
111
|
-
prerelease: false
|
112
|
-
version_requirements: !ruby/object:Gem::Requirement
|
113
|
-
requirements:
|
114
|
-
- - "~>"
|
115
|
-
- !ruby/object:Gem::Version
|
116
|
-
version: '0.3'
|
117
|
-
- - ">="
|
118
|
-
- !ruby/object:Gem::Version
|
119
|
-
version: 0.3.1
|
120
80
|
description:
|
121
81
|
email: james@jamesrobertson.eu
|
122
82
|
executables: []
|
metadata.gz.sig
CHANGED
Binary file
|