projectsimulator 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 850c1d323a1816a344d896177412330258c4b9bcbe8c946182701533efdddf05
4
- data.tar.gz: 9e7a2e6ab061f4820207085240a52d8bd36847e57b6ef5d8cf0a625739802dad
3
+ metadata.gz: 7e70e7f4a42e34c20b395b0fab1113c1ed59bbb00c2e0b0b117b201708d8578c
4
+ data.tar.gz: 3c9431a5a680b62c1070023a2b32f4b540530145d0eb896af6bc629105643d2f
5
5
  SHA512:
6
- metadata.gz: e52e950765845719638554324e058fdda5484feb34128aad13b76f8ff0623b5db4af437aaf60778e6b2356edb43533347831e7a78c3269500f61be6183946ca0
7
- data.tar.gz: 55d386d448cd8edb318f938771505d2d61155d7106ebf48932469ffab840db66de019a0556bfe481206af055668326e111cfc04f50346aef7f48a16ac5b80740
6
+ metadata.gz: '0683c9527e84ffa413551d16b9d9fff3805fe9042a7068b3bdbf8b7c6ede26894aa6d2ce26a7cef07144abfa7501c577f0db9aa13418fe40f5283c283563be46'
7
+ data.tar.gz: a64eb0b3ba73be9163927edcdb8f202f955fc29474a9c65539a456a3f4e70f3612cbe97c9892a996b62d529436485319183cce26c80f37883f6b162fd204b443
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -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 Model
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 get_device(h)
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
- a = []
71
- a << h[:location].split(/ /) if h.has_key? :location
72
- a << h[:service]
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
- # request accepts a string in plain english
96
- # e.g. request 'switch the livingroom light on'
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
- end
282
- end
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.3.3
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-08-20 00:00:00.000000000 Z
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