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 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