remotedroid 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/remotedroid.rb +462 -0
- metadata +151 -0
- metadata.gz.sig +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b788429e24f18de3a9237abe1fb9d8ba73ddb252edb59caa63b99fa9be986fad
|
4
|
+
data.tar.gz: 5257691864646241e82b92eeece3139c01ca743e1d4c13e49675f441fb5a734d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dc5aee582390fe67b13e0e69876207292ab4b0892761bb55fea80826bbf5bf62515118decd47815d5ff00b28b2dd25f8179a74e3ddf2d4a02a6ee5c90c662711
|
7
|
+
data.tar.gz: 0c1fabdaa87e9907f4d79b1fb68285c1f6b7190393daffedfb362436628badfbf0f0c14a8da8d46869197d861f377ad02b7b0bae2681aa3a796d88f7346fd45b
|
checksums.yaml.gz.sig
ADDED
Binary file
|
data.tar.gz.sig
ADDED
Binary file
|
data/lib/remotedroid.rb
ADDED
@@ -0,0 +1,462 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# file: remotedroid.rb
|
4
|
+
|
5
|
+
require 'onedrb'
|
6
|
+
require 'easydom'
|
7
|
+
require 'app-routes'
|
8
|
+
require 'sps-sub'
|
9
|
+
require 'ruby-macrodroid'
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
RD_MACROS =<<EOF
|
14
|
+
m: Torch
|
15
|
+
t: webhook
|
16
|
+
a: Torch toggle
|
17
|
+
|
18
|
+
m: Toast
|
19
|
+
v: msg:
|
20
|
+
t: WebHook
|
21
|
+
a:
|
22
|
+
Popup Message
|
23
|
+
[lv=msg]
|
24
|
+
|
25
|
+
m: shake device
|
26
|
+
t: shake device
|
27
|
+
a: webhook
|
28
|
+
EOF
|
29
|
+
|
30
|
+
module RemoteDroid
|
31
|
+
|
32
|
+
class Model
|
33
|
+
include AppRoutes
|
34
|
+
|
35
|
+
def initialize(obj=nil, root: 'device1', debug: false)
|
36
|
+
|
37
|
+
super()
|
38
|
+
@root, @debug = root, debug
|
39
|
+
@location = nil
|
40
|
+
|
41
|
+
if obj then
|
42
|
+
|
43
|
+
s = obj.strip
|
44
|
+
|
45
|
+
puts 's: ' + s.inspect if @debug
|
46
|
+
|
47
|
+
if s[0] == '<' or s.lines[1][0..1] == ' ' then
|
48
|
+
|
49
|
+
puts 'before easydom' if @debug
|
50
|
+
|
51
|
+
s2 = if s.lines[1][0..1] == ' ' then
|
52
|
+
|
53
|
+
lines = s.lines.map do |line|
|
54
|
+
line.sub(/(\w+) +is +(\w+)$/) {|x| "#{$1} {switch: #{$2}}" }
|
55
|
+
end
|
56
|
+
|
57
|
+
lines.join
|
58
|
+
|
59
|
+
else
|
60
|
+
s
|
61
|
+
end
|
62
|
+
|
63
|
+
@ed = EasyDom.new(s2)
|
64
|
+
else
|
65
|
+
build(s, root: root)
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
def build(raw_requests, root: @root)
|
73
|
+
|
74
|
+
@ed = EasyDom.new(debug: false, root: root)
|
75
|
+
raw_requests.lines.each {|line| request(line) }
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
def get_thing(h)
|
81
|
+
|
82
|
+
h[:thing].gsub!(/ /,'_')
|
83
|
+
|
84
|
+
if not h.has_key? :location then
|
85
|
+
location = false
|
86
|
+
h[:location] = find_path(h[:thing])
|
87
|
+
else
|
88
|
+
location = true
|
89
|
+
end
|
90
|
+
|
91
|
+
puts 'h: ' + h.inspect if @debug
|
92
|
+
|
93
|
+
a = []
|
94
|
+
a += h[:location].split(/ /)
|
95
|
+
a << h[:thing]
|
96
|
+
status = a.inject(@ed) {|r,x| r.send(x)}.send(h[:action])
|
97
|
+
|
98
|
+
if location then
|
99
|
+
"The %s %s is %s." % [h[:location], h[:thing], status]
|
100
|
+
else
|
101
|
+
"%s is %s." % [h[:thing].capitalize, status]
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
# Object Property (op)
|
107
|
+
# Helpful for accessing properites in dot notation
|
108
|
+
# e.g. op.livingroom.light.switch = 'off'
|
109
|
+
#
|
110
|
+
def op()
|
111
|
+
@ed
|
112
|
+
end
|
113
|
+
|
114
|
+
def query(s)
|
115
|
+
@ed.e.element(s)
|
116
|
+
end
|
117
|
+
|
118
|
+
# request accepts a string in plain english
|
119
|
+
# e.g. request 'switch the livingroom light on'
|
120
|
+
#
|
121
|
+
def request(s)
|
122
|
+
|
123
|
+
params = {request: s}
|
124
|
+
requests(params)
|
125
|
+
h = find_request(s)
|
126
|
+
|
127
|
+
method(h.first[-1]).call(h).gsub(/_/,' ')
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
def set_thing(h)
|
132
|
+
|
133
|
+
h[:thing].gsub!(/ /,'_')
|
134
|
+
h[:location] = find_path(h[:thing]) unless h.has_key? :location
|
135
|
+
|
136
|
+
a = []
|
137
|
+
a += h[:location].split(/ /)
|
138
|
+
a << h[:thing]
|
139
|
+
|
140
|
+
a.inject(@ed) {|r,x| r.send(x)}.send(h[:action], h[:value])
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
def to_sliml(level: 0)
|
145
|
+
|
146
|
+
s = @ed.to_sliml
|
147
|
+
|
148
|
+
return s if level.to_i > 0
|
149
|
+
|
150
|
+
lines = s.lines.map do |line|
|
151
|
+
|
152
|
+
line.sub(/\{[^\}]+\}/) do |x|
|
153
|
+
|
154
|
+
a = x.scan(/\w+: +[^ ]+/)
|
155
|
+
if a.length == 1 and x[/switch:/] then
|
156
|
+
|
157
|
+
val = x[/(?<=switch: ) *["']([^"']+)/,1]
|
158
|
+
'is ' + val
|
159
|
+
else
|
160
|
+
x
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
lines.join
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
def to_xml(options=nil)
|
171
|
+
@ed.xml(pretty: true).gsub(' style=\'\'','')
|
172
|
+
end
|
173
|
+
|
174
|
+
alias xml to_xml
|
175
|
+
|
176
|
+
# to_xml() is the preferred method
|
177
|
+
|
178
|
+
protected
|
179
|
+
|
180
|
+
def requests(params)
|
181
|
+
|
182
|
+
# e.g. switch the livingroom gas_fire off
|
183
|
+
#
|
184
|
+
get /(?:switch|turn) the ([^ ]+) +([^ ]+) +(on|off)$/ do |location, device, onoff|
|
185
|
+
{type: :set_thing, action: 'switch=', location: location, thing: device, value: onoff}
|
186
|
+
end
|
187
|
+
|
188
|
+
# e.g. switch the gas _fire off
|
189
|
+
#
|
190
|
+
get /(?:switch|turn) the ([^ ]+) +(on|off)$/ do |device, onoff|
|
191
|
+
{type: :set_thing, action: 'switch=', thing: device, value: onoff}
|
192
|
+
end
|
193
|
+
|
194
|
+
# e.g. is the livingroom gas_fire on?
|
195
|
+
#
|
196
|
+
get /is the ([^ ]+) +([^ ]+) +(?:on|off)\??$/ do |location, device|
|
197
|
+
{type: :get_thing, action: 'switch', location: location, thing: device}
|
198
|
+
end
|
199
|
+
|
200
|
+
# e.g. enable airplane mode
|
201
|
+
#
|
202
|
+
get /((?:dis|en)able) ([^$]+)$/ do |state, service|
|
203
|
+
{type: :set_thing, action: 'switch=', thing: service, value: state + 'd'}
|
204
|
+
end
|
205
|
+
|
206
|
+
# e.g. switch airplane mode off
|
207
|
+
#
|
208
|
+
get /switch (.*) (on|off)/ do |service, rawstate|
|
209
|
+
|
210
|
+
state = rawstate == 'on' ? 'enabled' : 'disabled'
|
211
|
+
{type: :set_thing, action: 'switch=', thing: service, value: state}
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
# e.g. is airplane mode enabed?
|
216
|
+
#
|
217
|
+
get /is (.*) +(?:(?:dis|en)abled)\??$/ do |service|
|
218
|
+
{type: :get_thing, action: 'switch', thing: service.gsub(/ /,'_')}
|
219
|
+
end
|
220
|
+
|
221
|
+
# e.g. is the gas_fire on?
|
222
|
+
#
|
223
|
+
get /is the ([^ ]+) +(?:on|off)\??$/ do |device|
|
224
|
+
location = find_path(device)
|
225
|
+
{type: :get_thing, action: 'switch', location: location, thing: device}
|
226
|
+
end
|
227
|
+
|
228
|
+
# e.g. fetch the livingroom temperature reading
|
229
|
+
#
|
230
|
+
get /fetch the ([^ ]+) +([^ ]+) +(?:reading)$/ do |location, device|
|
231
|
+
{type: :get_thing, action: 'reading', location: location, thing: device}
|
232
|
+
end
|
233
|
+
|
234
|
+
# e.g. fetch the temperature reading
|
235
|
+
#
|
236
|
+
get /fetch the ([^ ]+) +(?:reading)$/ do |device|
|
237
|
+
location = find_path(device)
|
238
|
+
{type: :get_thing, action: 'reading', location: location, thing: device}
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
|
243
|
+
private
|
244
|
+
|
245
|
+
def find_path(s)
|
246
|
+
puts 'find_path s: ' + s.inspect if @debug
|
247
|
+
found = query('//'+ s)
|
248
|
+
return unless found
|
249
|
+
a = found.backtrack.to_xpath.split('/')
|
250
|
+
a[1..-2].join(' ')
|
251
|
+
end
|
252
|
+
|
253
|
+
alias find_request run_route
|
254
|
+
|
255
|
+
end
|
256
|
+
|
257
|
+
class Controller
|
258
|
+
|
259
|
+
attr_reader :model, :control
|
260
|
+
attr_accessor :title, :macros
|
261
|
+
|
262
|
+
def initialize(mcs, model=MODEL, deviceid: nil, debug: false)
|
263
|
+
|
264
|
+
@debug = debug
|
265
|
+
@syslog = []
|
266
|
+
|
267
|
+
@control = Control.new(deviceid)
|
268
|
+
@macros = mcs.macros
|
269
|
+
|
270
|
+
if model then
|
271
|
+
@model = Model.new(model)
|
272
|
+
end
|
273
|
+
|
274
|
+
end
|
275
|
+
|
276
|
+
def export(s)
|
277
|
+
@macros = MacroDroid.new(s).macros
|
278
|
+
end
|
279
|
+
|
280
|
+
# Object Property (op)
|
281
|
+
# Helpful for accessing properites in dot notation
|
282
|
+
# e.g. op.livingroom.light.switch = 'off'
|
283
|
+
#
|
284
|
+
def op()
|
285
|
+
@model.op
|
286
|
+
end
|
287
|
+
|
288
|
+
def request(s)
|
289
|
+
@model.request s
|
290
|
+
end
|
291
|
+
|
292
|
+
|
293
|
+
def trigger(name, detail={time: Time.now})
|
294
|
+
|
295
|
+
macros = @macros.select do |macro|
|
296
|
+
|
297
|
+
puts 'macro: ' + macro.inspect if @debug
|
298
|
+
|
299
|
+
# fetch the associated properties from the model if possible and
|
300
|
+
# merge them into the detail.
|
301
|
+
#
|
302
|
+
valid_trigger = macro.match?(name, detail, @model.op)
|
303
|
+
|
304
|
+
puts 'valid_trigger: ' + valid_trigger.inspect if @debug
|
305
|
+
|
306
|
+
if valid_trigger then
|
307
|
+
@syslog << [Time.now, :trigger, name]
|
308
|
+
@syslog << [Time.now, :macro, macro.title]
|
309
|
+
end
|
310
|
+
|
311
|
+
valid_trigger
|
312
|
+
|
313
|
+
end
|
314
|
+
|
315
|
+
puts 'macros: ' + macros.inspect if @debug
|
316
|
+
|
317
|
+
macros.flat_map(&:run)
|
318
|
+
end
|
319
|
+
|
320
|
+
alias trigger_fired trigger
|
321
|
+
|
322
|
+
end
|
323
|
+
|
324
|
+
class Service
|
325
|
+
def initialize(callback)
|
326
|
+
@callback = callback
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
class Bluetooth
|
331
|
+
def enable()
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
class Toast < Service
|
336
|
+
|
337
|
+
def invoke()
|
338
|
+
@callback.call :toast
|
339
|
+
end
|
340
|
+
|
341
|
+
end
|
342
|
+
|
343
|
+
class Torch < Service
|
344
|
+
|
345
|
+
def toggle()
|
346
|
+
@callback.http_exec :torch
|
347
|
+
end
|
348
|
+
|
349
|
+
end
|
350
|
+
|
351
|
+
class Control
|
352
|
+
|
353
|
+
def initialize(dev=nil, deviceid: dev, remote_url: nil, debug: false)
|
354
|
+
|
355
|
+
@deviceid, @remote_url, @debug = deviceid, remote_url, debug
|
356
|
+
@torch = Torch.new(self)
|
357
|
+
end
|
358
|
+
|
359
|
+
def bluetooth()
|
360
|
+
@bluetooth
|
361
|
+
end
|
362
|
+
|
363
|
+
def http_exec(command, options={})
|
364
|
+
|
365
|
+
url = "https://trigger.macrodroid.com/%s/%s" % [@deviceid, command]
|
366
|
+
File.write '/tmp/foo.txt', 'url : ' + url.inspect #if @debug
|
367
|
+
|
368
|
+
if options and options.any? then
|
369
|
+
h = options
|
370
|
+
url += '?' + \
|
371
|
+
URI.escape(h.map {|key,value| "%s=%s" % [key, value]}.join('&'))
|
372
|
+
end
|
373
|
+
|
374
|
+
s = open(url).read
|
375
|
+
|
376
|
+
end
|
377
|
+
|
378
|
+
def toast(options={})
|
379
|
+
http_exec 'toast', options
|
380
|
+
end
|
381
|
+
|
382
|
+
def torch()
|
383
|
+
@torch
|
384
|
+
end
|
385
|
+
|
386
|
+
def write(s)
|
387
|
+
|
388
|
+
MacroDroid.new(RD_MACROS, deviceid: @deviceid,
|
389
|
+
remote_url: @remote_url, debug: @debug).export s
|
390
|
+
|
391
|
+
end
|
392
|
+
|
393
|
+
alias export write
|
394
|
+
|
395
|
+
def method_missing(method_name, *args)
|
396
|
+
http_exec(method_name, args.first)
|
397
|
+
end
|
398
|
+
|
399
|
+
end
|
400
|
+
|
401
|
+
class Server
|
402
|
+
|
403
|
+
def initialize(s, drb_host: '127.0.0.1', deviceid: nil)
|
404
|
+
|
405
|
+
md = MacroDroid.new(s)
|
406
|
+
rdc = RemoteDroid::Controller.new(md, deviceid: deviceid)
|
407
|
+
@drb = OneDrb::Server.new host: drb_host, port: '5777', obj: rdc
|
408
|
+
|
409
|
+
end
|
410
|
+
|
411
|
+
def start
|
412
|
+
@drb.start
|
413
|
+
end
|
414
|
+
|
415
|
+
end
|
416
|
+
|
417
|
+
class TriggerSubscriber < SPSSub
|
418
|
+
|
419
|
+
def initialize(host: 'sps.home', drb_host: '127.0.0.1')
|
420
|
+
@remote = OneDrb::Client.new host: drb_host, port: '5777'
|
421
|
+
super(host: host)
|
422
|
+
end
|
423
|
+
|
424
|
+
def subscribe(topic: 'macrodroid/trigger')
|
425
|
+
|
426
|
+
super(topic: topic) do |msg|
|
427
|
+
|
428
|
+
trigger, json = msg.split(/:\s+/,2)
|
429
|
+
a = @remote.trigger_fired trigger.to_sym,
|
430
|
+
JSON.parse(json, symbolize_names: true)
|
431
|
+
a.each {|msg| self.notice 'macrodroid/action: ' + msg }
|
432
|
+
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
end
|
437
|
+
|
438
|
+
class ActionSubscriber < SPSSub
|
439
|
+
|
440
|
+
def initialize(host: 'sps.home', drb_host: '127.0.0.1')
|
441
|
+
@remote = OneDrb::Client.new host: drb_host, port: '5777'
|
442
|
+
super(host: host)
|
443
|
+
end
|
444
|
+
|
445
|
+
def subscribe(topic: 'macrodroid/action')
|
446
|
+
|
447
|
+
super(topic: topic) do |msg|
|
448
|
+
|
449
|
+
context, json = msg.split(/:\s+/,2)
|
450
|
+
category, action = context.split('/',2)
|
451
|
+
@remote.control.method(action.to_sym)\
|
452
|
+
.call(JSON.parse(json, symbolize_names: true))
|
453
|
+
|
454
|
+
end
|
455
|
+
|
456
|
+
end
|
457
|
+
|
458
|
+
end
|
459
|
+
|
460
|
+
|
461
|
+
end
|
462
|
+
|
metadata
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: remotedroid
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Robertson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain:
|
11
|
+
- |
|
12
|
+
-----BEGIN CERTIFICATE-----
|
13
|
+
MIIEXjCCAsagAwIBAgIBATANBgkqhkiG9w0BAQsFADAsMSowKAYDVQQDDCFnZW1t
|
14
|
+
YXN0ZXIvREM9amFtZXNyb2JlcnRzb24vREM9ZXUwHhcNMjAxMDAyMjI0OTAyWhcN
|
15
|
+
MjExMDAyMjI0OTAyWjAsMSowKAYDVQQDDCFnZW1tYXN0ZXIvREM9amFtZXNyb2Jl
|
16
|
+
cnRzb24vREM9ZXUwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDq6tMR
|
17
|
+
goUkxOiD/E2J2UU4fyOz3KcaiZhm6aGXLypRQkjsVT9ZbZUFJP6rL0vudHuw7TGU
|
18
|
+
hnX5/SRRoHAcGn7j+mznEqJdIlVrtK5+pQ1h2/cnNMZrKbXhkfLLo/2Pl8JCw5gY
|
19
|
+
8IKQCmf6SDdrxt/MVxyuXCjoVq0QaHgJOYTLuoSobYV1JtXiHrXvDkjDBeugWodb
|
20
|
+
+J/AejxIEEzj4VCD4T8eGyyhqx/tDDokfHRCwD69K2CL1TG+v11NN+kwKAw1B5uQ
|
21
|
+
juvPpNMMmvdGIRClLLVYS2GZ1PY3eAkt4D682Ct/SIbBs/WZPBQ7V4u1q0xsFskO
|
22
|
+
+kZDM3FUpjkjFIAKJQojxMJBgxsBIOFyW7mwUASwYikd47Hptu4AoxO9cyla2ZJ8
|
23
|
+
XE49SU79LZzW6xNqYCkuRESjV+V65xyIpRymT/vWFRzfVafjDtxsvBu8zuQvB55E
|
24
|
+
EJhU2iK7IxEMD9vK7Vq7opgqgR3XokiNwWuNmt/ak3mcnUcgFBkiNAlO3RsCAwEA
|
25
|
+
AaOBijCBhzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUNXjM9pAU
|
26
|
+
/zrKDRZKV+SleokUpk8wJgYDVR0RBB8wHYEbZ2VtbWFzdGVyQGphbWVzcm9iZXJ0
|
27
|
+
c29uLmV1MCYGA1UdEgQfMB2BG2dlbW1hc3RlckBqYW1lc3JvYmVydHNvbi5ldTAN
|
28
|
+
BgkqhkiG9w0BAQsFAAOCAYEAlTd2THoLR/qMTRE/P0KMRYH96GbPyLOH29TOfQ+7
|
29
|
+
DSEtxS9dMbl0IQ7jSMkK8/pwYF/OLO11862CeJFh+kKIYEOnrhp8T2kn2HyXNZen
|
30
|
+
0zklZgb3A3NGdK3CKZG1RkMHH9Hu6vBiivR+zLYCATuw842dcLQG/UR/cMGGby6k
|
31
|
+
yflohsIKH2MmfQr2fs0h5m04AcvD1Zqc+z1SF6KElcLws40xw2Qfcl2GRK8rcClW
|
32
|
+
njOBpwPRQJLE6sio0Kq5VkwuAPbJ72WKK986mwv9bnGWqhfIvz+ZCpa8kKNjk2Z+
|
33
|
+
HMPueoY9XP6X0MgDiqpvy9cECNn93LU7+iX1hBu3ALnwSsW/1gWip/So8kXkK/D0
|
34
|
+
Jr6sGap//zpHcpzbBI/H5if8VFSIL5nivEX4dUqzIZo5M0ngeOsFf2Ka6PHYSPsZ
|
35
|
+
io3WPRDjULC924M5S8wbrus31v2AUjqFBPvmHr7caf/VHErWypV482xcDhWt1eif
|
36
|
+
0G2k2ptozXcBS9odsqGUTb5N
|
37
|
+
-----END CERTIFICATE-----
|
38
|
+
date: 2020-10-02 00:00:00.000000000 Z
|
39
|
+
dependencies:
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: onedrb
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.1.0
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0.1'
|
50
|
+
type: :runtime
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 0.1.0
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0.1'
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: easydom
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0.2'
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.2.1
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0.2'
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 0.2.1
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: sps-sub
|
82
|
+
requirement: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - "~>"
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0.3'
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.3.7
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.3'
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: 0.3.7
|
100
|
+
- !ruby/object:Gem::Dependency
|
101
|
+
name: ruby-macrodroid
|
102
|
+
requirement: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - "~>"
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0.8'
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.8.12
|
110
|
+
type: :runtime
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0.8'
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: 0.8.12
|
120
|
+
description:
|
121
|
+
email: james@jamesrobertson.eu
|
122
|
+
executables: []
|
123
|
+
extensions: []
|
124
|
+
extra_rdoc_files: []
|
125
|
+
files:
|
126
|
+
- lib/remotedroid.rb
|
127
|
+
homepage: https://github.com/jrobertson/remotedroid
|
128
|
+
licenses:
|
129
|
+
- MIT
|
130
|
+
metadata: {}
|
131
|
+
post_install_message:
|
132
|
+
rdoc_options: []
|
133
|
+
require_paths:
|
134
|
+
- lib
|
135
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
requirements: []
|
146
|
+
rubygems_version: 3.0.3
|
147
|
+
signing_key:
|
148
|
+
specification_version: 4
|
149
|
+
summary: A Ruby-MacroDroid related experiment into triggering macros and responding
|
150
|
+
to actions remotely.
|
151
|
+
test_files: []
|
metadata.gz.sig
ADDED
Binary file
|