projectsimulator 0.3.3 → 0.4.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 +15 -261
- data/lib/projectsimulator/controller.rb +116 -0
- data/lib/projectsimulator/model.rb +232 -0
- metadata +24 -2
- 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: 7e70e7f4a42e34c20b395b0fab1113c1ed59bbb00c2e0b0b117b201708d8578c
|
4
|
+
data.tar.gz: 3c9431a5a680b62c1070023a2b32f4b540530145d0eb896af6bc629105643d2f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0683c9527e84ffa413551d16b9d9fff3805fe9042a7068b3bdbf8b7c6ede26894aa6d2ce26a7cef07144abfa7501c577f0db9aa13418fe40f5283c283563be46'
|
7
|
+
data.tar.gz: a64eb0b3ba73be9163927edcdb8f202f955fc29474a9c65539a456a3f4e70f3612cbe97c9892a996b62d529436485319183cce26c80f37883f6b162fd204b443
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/lib/projectsimulator.rb
CHANGED
@@ -4,279 +4,33 @@
|
|
4
4
|
|
5
5
|
|
6
6
|
require 'easydom'
|
7
|
+
require 'unichron'
|
7
8
|
require 'app-routes'
|
8
9
|
|
9
10
|
|
10
11
|
module ProjectSimulator
|
11
12
|
|
12
|
-
class
|
13
|
-
include AppRoutes
|
14
|
-
|
15
|
-
def initialize(obj=nil, root: 'building1', debug: false)
|
16
|
-
|
17
|
-
super()
|
18
|
-
@root, @debug = root, debug
|
19
|
-
@location = nil
|
20
|
-
|
21
|
-
if obj then
|
22
|
-
|
23
|
-
s = obj.strip
|
24
|
-
|
25
|
-
puts 's: ' + s.inspect if @debug
|
26
|
-
|
27
|
-
if s[0] == '<' or s.lines[1][0..1] == ' ' then
|
28
|
-
|
29
|
-
puts 'before easydom' if @debug
|
30
|
-
|
31
|
-
s2 = if s.lines[1][0..1] == ' ' then
|
32
|
-
|
33
|
-
lines = s.lines.map do |line|
|
34
|
-
line.sub(/(\w+) +is +(\w+)$/) {|x| "#{$1} {switch: #{$2}}" }
|
35
|
-
end
|
36
|
-
|
37
|
-
lines.join
|
38
|
-
|
39
|
-
else
|
40
|
-
s
|
41
|
-
end
|
42
|
-
|
43
|
-
@ed = EasyDom.new(s2)
|
44
|
-
else
|
45
|
-
build(s, root: root)
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
51
|
-
|
52
|
-
def build(raw_requests, root: @root)
|
53
|
-
|
54
|
-
@ed = EasyDom.new(debug: false, root: root)
|
55
|
-
raw_requests.lines.each {|line| request(line) }
|
56
|
-
|
57
|
-
end
|
13
|
+
class Server
|
58
14
|
|
59
|
-
def
|
60
|
-
|
61
|
-
a = h[:location].split(/ /)
|
62
|
-
a << h[:device]
|
63
|
-
status = a.inject(@ed) {|r,x| r.send(x)}.send(h[:action])
|
64
|
-
"The %s %s is %s." % [h[:location], h[:device], status]
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
def get_service(h)
|
15
|
+
def initialize(macros_package, drb_host: '127.0.0.1', devices: nil,
|
16
|
+
debug: false)
|
69
17
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
status = a.inject(@ed) {|r,x| r.send(x)}.send(h[:action])
|
18
|
+
rdc = ProjectSimulator::Controller.new(macros_package, devices: devices,
|
19
|
+
debug: debug)
|
20
|
+
@drb = OneDrb::Server.new host: drb_host, port: '5777', obj: rdc
|
74
21
|
|
75
|
-
if h.has_key? :location then
|
76
|
-
"The %s %s is %s." % [h[:location], h[:service], status]
|
77
|
-
else
|
78
|
-
"%s is %s." % [h[:service].capitalize, status]
|
79
|
-
end
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
# Object Property (op)
|
84
|
-
# Helpful for accessing properites in dot notation
|
85
|
-
# e.g. op.livingroom.light.switch = 'off'
|
86
|
-
#
|
87
|
-
def op()
|
88
|
-
@ed
|
89
|
-
end
|
90
|
-
|
91
|
-
def query(s)
|
92
|
-
@ed.e.element(s)
|
93
22
|
end
|
94
23
|
|
95
|
-
|
96
|
-
|
97
|
-
#
|
98
|
-
def request(s)
|
99
|
-
|
100
|
-
params = {request: s}
|
101
|
-
requests(params)
|
102
|
-
h = find_request(s)
|
103
|
-
|
104
|
-
method(h.first[-1]).call(h).gsub(/_/,' ')
|
105
|
-
|
106
|
-
end
|
107
|
-
|
108
|
-
def set_device(h)
|
109
|
-
|
110
|
-
a = h[:location].split(/ /)
|
111
|
-
a << h[:device]
|
112
|
-
a.inject(@ed) {|r,x| r.send(x)}.send(h[:action], h[:value])
|
113
|
-
|
24
|
+
def start
|
25
|
+
@drb.start
|
114
26
|
end
|
115
|
-
|
116
|
-
def set_service(h)
|
117
|
-
|
118
|
-
a = []
|
119
|
-
a += h[:location].split(/ /) if h[:location]
|
120
|
-
a << h[:service]
|
121
|
-
a.inject(@ed) {|r,x| r.send(x)}.send(h[:action], h[:value])
|
122
|
-
|
123
|
-
end
|
124
|
-
|
125
|
-
def to_sliml(level: 0)
|
126
|
-
|
127
|
-
s = @ed.to_sliml
|
128
|
-
|
129
|
-
return s if level.to_i > 0
|
130
|
-
|
131
|
-
lines = s.lines.map do |line|
|
132
|
-
|
133
|
-
line.sub(/\{[^\}]+\}/) do |x|
|
134
|
-
|
135
|
-
a = x.scan(/\w+: +[^ ]+/)
|
136
|
-
if a.length == 1 and x[/switch:/] then
|
137
|
-
|
138
|
-
val = x[/(?<=switch: ) *["']([^"']+)/,1]
|
139
|
-
'is ' + val
|
140
|
-
else
|
141
|
-
x
|
142
|
-
end
|
143
|
-
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
lines.join
|
148
|
-
|
149
|
-
end
|
150
|
-
|
151
|
-
def to_xml(options=nil)
|
152
|
-
@ed.xml(pretty: true).gsub(' style=\'\'','')
|
153
|
-
end
|
154
|
-
|
155
|
-
alias xml to_xml
|
156
|
-
|
157
|
-
# to_xml() is the preferred method
|
158
|
-
|
159
|
-
protected
|
160
|
-
|
161
|
-
def requests(params)
|
162
|
-
|
163
|
-
# e.g. switch the livingroom gas_fire off
|
164
|
-
#
|
165
|
-
get /(?:switch|turn) the ([^ ]+) +([^ ]+) +(on|off)$/ do |location, device, onoff|
|
166
|
-
{type: :set_device, action: 'switch=', location: location, device: device, value: onoff}
|
167
|
-
end
|
168
|
-
|
169
|
-
# e.g. switch the gas _fire off
|
170
|
-
#
|
171
|
-
get /(?:switch|turn) the ([^ ]+) +(on|off)$/ do |device, onoff|
|
172
|
-
location = find_path(device)
|
173
|
-
{type: :set_device, action: 'switch=', location: location, device: device, value: onoff}
|
174
|
-
end
|
175
|
-
|
176
|
-
# e.g. is the livingroom gas_fire on?
|
177
|
-
#
|
178
|
-
get /is the ([^ ]+) +([^ ]+) +(?:on|off)\??$/ do |location, device|
|
179
|
-
{type: :get_device, action: 'switch', location: location, device: device}
|
180
|
-
end
|
181
|
-
|
182
|
-
# e.g. enable airplane mode
|
183
|
-
#
|
184
|
-
get /((?:dis|en)able) ([^$]+)$/ do |state, rawservice|
|
185
|
-
service = rawservice.gsub(/ /,'_')
|
186
|
-
location = find_path(service)
|
187
|
-
{type: :set_service, action: 'switch=', location: location, service: service, value: state + 'd'}
|
188
|
-
end
|
189
|
-
|
190
|
-
# e.g. switch airplane mode off
|
191
|
-
#
|
192
|
-
get /switch (.*) (on|off)/ do |rawservice, rawstate|
|
193
|
-
|
194
|
-
state = rawstate == 'on' ? 'enabled' : 'disabled'
|
195
|
-
service = rawservice.gsub(/ /,'_')
|
196
|
-
location = find_path(service)
|
197
|
-
{type: :set_service, action: 'switch=', location: location, service: service, value: state}
|
198
|
-
end
|
199
|
-
|
200
|
-
# e.g. is airplane mode enabed?
|
201
|
-
#
|
202
|
-
get /is (.*) +(?:(?:dis|en)abled)\??$/ do |service|
|
203
|
-
{type: :get_service, action: 'switch', service: service.gsub(/ /,'_')}
|
204
|
-
end
|
205
|
-
|
206
|
-
# e.g. is the gas_fire on?
|
207
|
-
#
|
208
|
-
get /is the ([^ ]+) +(?:on|off)\??$/ do |device|
|
209
|
-
location = find_path(device)
|
210
|
-
{type: :get_device, action: 'switch', location: location, device: device}
|
211
|
-
end
|
212
|
-
|
213
|
-
# e.g. fetch the livingroom temperature reading
|
214
|
-
#
|
215
|
-
get /fetch the ([^ ]+) +([^ ]+) +(?:reading)$/ do |location, device|
|
216
|
-
{type: :get_device, action: 'reading', location: location, device: device}
|
217
|
-
end
|
218
|
-
|
219
|
-
# e.g. fetch the temperature reading
|
220
|
-
#
|
221
|
-
get /fetch the ([^ ]+) +(?:reading)$/ do |device|
|
222
|
-
location = find_path(device)
|
223
|
-
{type: :get_device, action: 'reading', location: location, device: device}
|
224
|
-
end
|
225
|
-
|
226
|
-
end
|
227
|
-
|
228
|
-
private
|
229
|
-
|
230
|
-
def find_path(s)
|
231
|
-
puts 'find_path s: ' + s.inspect if @debug
|
232
|
-
found = query('//'+ s)
|
233
|
-
return unless found
|
234
|
-
a = found.backtrack.to_xpath.split('/')
|
235
|
-
a[1..-2].join(' ')
|
236
|
-
end
|
237
|
-
|
238
|
-
alias find_request run_route
|
239
27
|
|
240
28
|
end
|
29
|
+
|
30
|
+
|
31
|
+
end
|
241
32
|
|
242
|
-
class Controller
|
243
|
-
|
244
|
-
attr_reader :macros
|
245
|
-
attr_accessor :title
|
246
|
-
|
247
|
-
def initialize(mcs, debug: false)
|
248
|
-
|
249
|
-
@debug = debug
|
250
|
-
@syslog = []
|
251
|
-
|
252
|
-
@macros = mcs.macros
|
253
|
-
|
254
|
-
end
|
255
|
-
|
256
|
-
|
257
|
-
def trigger(name, detail={time: $env[:time]})
|
258
|
-
|
259
|
-
macros = @macros.select do |macro|
|
260
|
-
|
261
|
-
puts 'macro: ' + macro.inspect if @debug
|
262
|
-
|
263
|
-
valid_trigger = macro.match?(name, detail)
|
264
|
-
|
265
|
-
puts 'valid_trigger: ' + valid_trigger.inspect if @debug
|
266
|
-
|
267
|
-
if valid_trigger then
|
268
|
-
@syslog << [Time.now, :trigger, name]
|
269
|
-
@syslog << [Time.now, :macro, macro.title]
|
270
|
-
end
|
271
|
-
|
272
|
-
valid_trigger
|
273
|
-
|
274
|
-
end
|
275
|
-
|
276
|
-
puts 'macros: ' + macros.inspect if @debug
|
277
|
-
|
278
|
-
macros.flat_map(&:run)
|
279
|
-
end
|
280
33
|
|
281
|
-
|
282
|
-
|
34
|
+
require 'projectsimulator/model'
|
35
|
+
require 'projectsimulator/controller'
|
36
|
+
require 'projectsimulator/client'
|
@@ -0,0 +1,116 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# file: projectsimulator/controller.rb
|
4
|
+
|
5
|
+
|
6
|
+
module ProjectSimulator
|
7
|
+
|
8
|
+
class Controller
|
9
|
+
|
10
|
+
attr_reader :macros, :model
|
11
|
+
attr_accessor :title, :speed
|
12
|
+
|
13
|
+
def initialize(mcs, model=nil, time: Time.now, speed: 1, debug: false)
|
14
|
+
|
15
|
+
@debug = debug
|
16
|
+
@syslog = []
|
17
|
+
|
18
|
+
@macros = mcs.macros
|
19
|
+
|
20
|
+
if model then
|
21
|
+
@model = Model.new(model)
|
22
|
+
end
|
23
|
+
|
24
|
+
@state = :stop
|
25
|
+
@speed = speed
|
26
|
+
|
27
|
+
@qt = UnichronUtils::Quicktime.new time: time, speed: @speed
|
28
|
+
@qt.start
|
29
|
+
@qt.pause
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
# Object Property (op)
|
34
|
+
# Helpful for accessing properites in dot notation
|
35
|
+
# e.g. op.livingroom.light.switch = 'off'
|
36
|
+
#
|
37
|
+
def op()
|
38
|
+
@model.op if @model
|
39
|
+
end
|
40
|
+
|
41
|
+
def pause()
|
42
|
+
@state = :pause
|
43
|
+
@qt.pause
|
44
|
+
end
|
45
|
+
|
46
|
+
def play()
|
47
|
+
@state = :play
|
48
|
+
@qt.play
|
49
|
+
end
|
50
|
+
|
51
|
+
def request(s)
|
52
|
+
@model.request s
|
53
|
+
end
|
54
|
+
|
55
|
+
def start()
|
56
|
+
|
57
|
+
|
58
|
+
Thread.new do
|
59
|
+
|
60
|
+
old_time = @qt.time - 1
|
61
|
+
|
62
|
+
loop do
|
63
|
+
|
64
|
+
interval = (1 / (2.0 * @speed))
|
65
|
+
(sleep interval; next) if @state != :play or old_time == @qt.time
|
66
|
+
#puts Time.now.inspect if @debug
|
67
|
+
r = self.trigger :timer, {time: @qt.time}
|
68
|
+
|
69
|
+
yield(r) if r.any?
|
70
|
+
|
71
|
+
puts 'r: ' + r.inspect if @debug and r.any?
|
72
|
+
sleep interval
|
73
|
+
old_time = @qt.time
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def stop()
|
80
|
+
@state = :stop
|
81
|
+
@qt.pause
|
82
|
+
end
|
83
|
+
|
84
|
+
def time()
|
85
|
+
@qt.time
|
86
|
+
end
|
87
|
+
|
88
|
+
def trigger(name, detail={})
|
89
|
+
|
90
|
+
macros = @macros.select do |macro|
|
91
|
+
|
92
|
+
#puts 'macro: ' + macro.inspect if @debug
|
93
|
+
|
94
|
+
# fetch the associated properties from the model if possible and
|
95
|
+
# merge them into the detail.
|
96
|
+
#
|
97
|
+
valid_trigger = macro.match?(name, detail, op())
|
98
|
+
|
99
|
+
#puts 'valid_trigger: ' + valid_trigger.inspect if @debug
|
100
|
+
|
101
|
+
if valid_trigger then
|
102
|
+
@syslog << [Time.now, :trigger, name]
|
103
|
+
@syslog << [Time.now, :macro, macro.title]
|
104
|
+
end
|
105
|
+
|
106
|
+
valid_trigger
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
#puts 'macros: ' + macros.inspect if @debug
|
111
|
+
|
112
|
+
macros.flat_map(&:run)
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# file: projectsimulator/controller.rb
|
4
|
+
|
5
|
+
|
6
|
+
module ProjectSimulator
|
7
|
+
|
8
|
+
class Model
|
9
|
+
include AppRoutes
|
10
|
+
|
11
|
+
def initialize(obj=nil, root: 'building1', debug: false)
|
12
|
+
|
13
|
+
super()
|
14
|
+
@root, @debug = root, debug
|
15
|
+
@location = nil
|
16
|
+
|
17
|
+
if obj then
|
18
|
+
|
19
|
+
s = obj.strip
|
20
|
+
|
21
|
+
puts 's: ' + s.inspect if @debug
|
22
|
+
|
23
|
+
if s[0] == '<' or s.lines[1][0..1] == ' ' then
|
24
|
+
|
25
|
+
puts 'before easydom' if @debug
|
26
|
+
|
27
|
+
s2 = if s.lines[1][0..1] == ' ' then
|
28
|
+
|
29
|
+
lines = s.lines.map do |line|
|
30
|
+
line.sub(/(\w+) +is +(\w+)$/) {|x| "#{$1} {switch: #{$2}}" }
|
31
|
+
end
|
32
|
+
|
33
|
+
lines.join
|
34
|
+
|
35
|
+
else
|
36
|
+
s
|
37
|
+
end
|
38
|
+
|
39
|
+
@ed = EasyDom.new(s2)
|
40
|
+
else
|
41
|
+
build(s, root: root)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
def build(raw_requests, root: @root)
|
49
|
+
|
50
|
+
@ed = EasyDom.new(debug: false, root: root)
|
51
|
+
raw_requests.lines.each {|line| request(line) }
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
def get_thing(h)
|
57
|
+
|
58
|
+
h[:thing].gsub!(/ /,'_')
|
59
|
+
|
60
|
+
if not h.has_key? :location then
|
61
|
+
location = false
|
62
|
+
h[:location] = find_path(h[:thing])
|
63
|
+
else
|
64
|
+
location = true
|
65
|
+
end
|
66
|
+
|
67
|
+
puts 'h: ' + h.inspect if @debug
|
68
|
+
|
69
|
+
a = []
|
70
|
+
a += h[:location].split(/ /)
|
71
|
+
a << h[:thing]
|
72
|
+
status = a.inject(@ed) {|r,x| r.send(x)}.send(h[:action])
|
73
|
+
|
74
|
+
if location then
|
75
|
+
"The %s %s is %s." % [h[:location], h[:thing], status]
|
76
|
+
else
|
77
|
+
"%s is %s." % [h[:thing].capitalize, status]
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
# Object Property (op)
|
83
|
+
# Helpful for accessing properites in dot notation
|
84
|
+
# e.g. op.livingroom.light.switch = 'off'
|
85
|
+
#
|
86
|
+
def op()
|
87
|
+
@ed
|
88
|
+
end
|
89
|
+
|
90
|
+
def query(s)
|
91
|
+
@ed.e.element(s)
|
92
|
+
end
|
93
|
+
|
94
|
+
# request accepts a string in plain english
|
95
|
+
# e.g. request 'switch the livingroom light on'
|
96
|
+
#
|
97
|
+
def request(s)
|
98
|
+
|
99
|
+
params = {request: s}
|
100
|
+
requests(params)
|
101
|
+
h = find_request(s)
|
102
|
+
|
103
|
+
method(h.first[-1]).call(h).gsub(/_/,' ')
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
def set_thing(h)
|
108
|
+
|
109
|
+
h[:thing].gsub!(/ /,'_')
|
110
|
+
h[:location] = find_path(h[:thing]) unless h.has_key? :location
|
111
|
+
|
112
|
+
a = []
|
113
|
+
a += h[:location].split(/ /)
|
114
|
+
a << h[:thing]
|
115
|
+
|
116
|
+
a.inject(@ed) {|r,x| r.send(x)}.send(h[:action], h[:value])
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
def to_sliml(level: 0)
|
121
|
+
|
122
|
+
s = @ed.to_sliml
|
123
|
+
|
124
|
+
return s if level.to_i > 0
|
125
|
+
|
126
|
+
lines = s.lines.map do |line|
|
127
|
+
|
128
|
+
line.sub(/\{[^\}]+\}/) do |x|
|
129
|
+
|
130
|
+
a = x.scan(/\w+: +[^ ]+/)
|
131
|
+
if a.length == 1 and x[/switch:/] then
|
132
|
+
|
133
|
+
val = x[/(?<=switch: ) *["']([^"']+)/,1]
|
134
|
+
'is ' + val
|
135
|
+
else
|
136
|
+
x
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
lines.join
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
def to_xml(options=nil)
|
147
|
+
@ed.xml(pretty: true).gsub(' style=\'\'','')
|
148
|
+
end
|
149
|
+
|
150
|
+
alias xml to_xml
|
151
|
+
|
152
|
+
# to_xml() is the preferred method
|
153
|
+
|
154
|
+
protected
|
155
|
+
|
156
|
+
def requests(params)
|
157
|
+
|
158
|
+
# e.g. switch the livingroom gas_fire off
|
159
|
+
#
|
160
|
+
get /(?:switch|turn) the ([^ ]+) +([^ ]+) +(on|off)$/ do |location, device, onoff|
|
161
|
+
{type: :set_thing, action: 'switch=', location: location, thing: device, value: onoff}
|
162
|
+
end
|
163
|
+
|
164
|
+
# e.g. switch the gas _fire off
|
165
|
+
#
|
166
|
+
get /(?:switch|turn) the ([^ ]+) +(on|off)$/ do |device, onoff|
|
167
|
+
{type: :set_thing, action: 'switch=', thing: device, value: onoff}
|
168
|
+
end
|
169
|
+
|
170
|
+
# e.g. is the livingroom gas_fire on?
|
171
|
+
#
|
172
|
+
get /is the ([^ ]+) +([^ ]+) +(?:on|off)\??$/ do |location, device|
|
173
|
+
{type: :get_thing, action: 'switch', location: location, thing: device}
|
174
|
+
end
|
175
|
+
|
176
|
+
# e.g. enable airplane mode
|
177
|
+
#
|
178
|
+
get /((?:dis|en)able) ([^$]+)$/ do |state, service|
|
179
|
+
{type: :set_thing, action: 'switch=', thing: service, value: state + 'd'}
|
180
|
+
end
|
181
|
+
|
182
|
+
# e.g. switch airplane mode off
|
183
|
+
#
|
184
|
+
get /switch (.*) (on|off)/ do |service, rawstate|
|
185
|
+
|
186
|
+
state = rawstate == 'on' ? 'enabled' : 'disabled'
|
187
|
+
{type: :set_thing, action: 'switch=', thing: service, value: state}
|
188
|
+
|
189
|
+
end
|
190
|
+
|
191
|
+
# e.g. is airplane mode enabed?
|
192
|
+
#
|
193
|
+
get /is (.*) +(?:(?:dis|en)abled)\??$/ do |service|
|
194
|
+
{type: :get_thing, action: 'switch', thing: service.gsub(/ /,'_')}
|
195
|
+
end
|
196
|
+
|
197
|
+
# e.g. is the gas_fire on?
|
198
|
+
#
|
199
|
+
get /is the ([^ ]+) +(?:on|off)\??$/ do |device|
|
200
|
+
location = find_path(device)
|
201
|
+
{type: :get_thing, action: 'switch', location: location, thing: device}
|
202
|
+
end
|
203
|
+
|
204
|
+
# e.g. fetch the livingroom temperature reading
|
205
|
+
#
|
206
|
+
get /fetch the ([^ ]+) +([^ ]+) +(?:reading)$/ do |location, device|
|
207
|
+
{type: :get_thing, action: 'reading', location: location, thing: device}
|
208
|
+
end
|
209
|
+
|
210
|
+
# e.g. fetch the temperature reading
|
211
|
+
#
|
212
|
+
get /fetch the ([^ ]+) +(?:reading)$/ do |device|
|
213
|
+
location = find_path(device)
|
214
|
+
{type: :get_thing, action: 'reading', location: location, thing: device}
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|
218
|
+
|
219
|
+
private
|
220
|
+
|
221
|
+
def find_path(s)
|
222
|
+
puts 'find_path s: ' + s.inspect if @debug
|
223
|
+
found = query('//'+ s)
|
224
|
+
return unless found
|
225
|
+
a = found.backtrack.to_xpath.split('/')
|
226
|
+
a[1..-2].join(' ')
|
227
|
+
end
|
228
|
+
|
229
|
+
alias find_request run_route
|
230
|
+
|
231
|
+
end
|
232
|
+
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.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Robertson
|
@@ -35,8 +35,28 @@ cert_chain:
|
|
35
35
|
2GrtfOXGVOS+2jvmCQC6vU+ew9WBxiDUbebI95TeTwMs2o0cs3IASXX5rIn4TPcz
|
36
36
|
SCccB3fVg2yfsy5DivaWaZwg
|
37
37
|
-----END CERTIFICATE-----
|
38
|
-
date: 2020-
|
38
|
+
date: 2020-11-18 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: unichron
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.2.0
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0.2'
|
50
|
+
type: :runtime
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 0.2.0
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0.2'
|
40
60
|
- !ruby/object:Gem::Dependency
|
41
61
|
name: easydom
|
42
62
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,6 +104,8 @@ extensions: []
|
|
84
104
|
extra_rdoc_files: []
|
85
105
|
files:
|
86
106
|
- lib/projectsimulator.rb
|
107
|
+
- lib/projectsimulator/controller.rb
|
108
|
+
- lib/projectsimulator/model.rb
|
87
109
|
homepage: https://github.com/jrobertson/projectsimulator
|
88
110
|
licenses:
|
89
111
|
- MIT
|
metadata.gz.sig
CHANGED
Binary file
|