remotedroid 0.4.4 → 0.5.4
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/remotedroid.rb +245 -712
- data/lib/remotedroid/client.rb +211 -0
- data/lib/remotedroid/control.rb +211 -0
- data/lib/remotedroid/controller.rb +170 -0
- data/lib/remotedroid/model.rb +227 -0
- data/lib/remotedroid/query.rb +60 -0
- metadata +9 -4
- 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: 667844020454a5bcfa4e47c7db865a9e1cfc70364da42840c8f6d4d1a6d4b021
|
|
4
|
+
data.tar.gz: 9058f9b6b4206cbf42e8c10ebdba4825bab4c1dcc9da477120bd6e09758af97c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 116782fbe0c6da9a938e3eeb59961189893fe6221bbdf7fd77d626ab374ab786480c977e0c6b847652e1f1e47b9300c160275cdec8241686209c7a10e190a7ea
|
|
7
|
+
data.tar.gz: 3521f559ef0febc0f37ce17aa174900ed8697dea131cbfec68db40fa6841d075930c972dfb33f2f4b8cd951d24054a3c7660c5daea5e54d0f38978444872630b
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data.tar.gz.sig
CHANGED
|
Binary file
|
data/lib/remotedroid.rb
CHANGED
|
@@ -8,20 +8,36 @@ require 'app-routes'
|
|
|
8
8
|
require 'sps-sub'
|
|
9
9
|
require 'ruby-macrodroid'
|
|
10
10
|
|
|
11
|
+
# PASTE_START
|
|
11
12
|
|
|
12
13
|
# Here's what's available so far:
|
|
13
14
|
#
|
|
14
15
|
# # Triggers
|
|
15
16
|
#
|
|
17
|
+
# ## Battery/Power
|
|
18
|
+
#
|
|
19
|
+
# * Power button toggle
|
|
20
|
+
#
|
|
21
|
+
# ## Connectivity
|
|
22
|
+
#
|
|
23
|
+
# ### Wifi State Change
|
|
24
|
+
#
|
|
25
|
+
# * Connected to Network
|
|
26
|
+
#
|
|
16
27
|
# ## Device Events
|
|
17
28
|
#
|
|
18
29
|
# * screen on
|
|
19
30
|
#
|
|
20
31
|
# ## Sensors
|
|
21
|
-
#
|
|
32
|
+
#
|
|
33
|
+
# * Activity Recognition
|
|
22
34
|
# * proximity (near)
|
|
23
35
|
# * shake device
|
|
24
36
|
#
|
|
37
|
+
# ## User Input
|
|
38
|
+
#
|
|
39
|
+
# * Swipe Screen
|
|
40
|
+
#
|
|
25
41
|
# ------------------------------------
|
|
26
42
|
#
|
|
27
43
|
# # Actions
|
|
@@ -48,6 +64,10 @@ require 'ruby-macrodroid'
|
|
|
48
64
|
#
|
|
49
65
|
# * Share Location
|
|
50
66
|
#
|
|
67
|
+
# ## MacroDroid specific
|
|
68
|
+
#
|
|
69
|
+
# * Disable Macro
|
|
70
|
+
#
|
|
51
71
|
# ## Media
|
|
52
72
|
#
|
|
53
73
|
# * Play sound (Doda)
|
|
@@ -177,6 +197,66 @@ m: stay awake off
|
|
|
177
197
|
t: webhook
|
|
178
198
|
a: stay awake off
|
|
179
199
|
|
|
200
|
+
m: Launch Google Play Music
|
|
201
|
+
t: webhook
|
|
202
|
+
a: Launch Google Play Music
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
m: Media Next
|
|
206
|
+
t: webhook
|
|
207
|
+
a:
|
|
208
|
+
Media Next
|
|
209
|
+
Simulate Media Button (Google Play Music)
|
|
210
|
+
|
|
211
|
+
m: Media Pause
|
|
212
|
+
t: webhook
|
|
213
|
+
a:
|
|
214
|
+
Media Pause
|
|
215
|
+
Simulate Media Button (Google Play Music)
|
|
216
|
+
|
|
217
|
+
m: Media Play
|
|
218
|
+
t: webhook
|
|
219
|
+
a:
|
|
220
|
+
Media Play
|
|
221
|
+
Simulate Media Button (Google Play Music)
|
|
222
|
+
|
|
223
|
+
m: Media Play Pause
|
|
224
|
+
t: webhook
|
|
225
|
+
a:
|
|
226
|
+
Media Play/Pause
|
|
227
|
+
Simulate Media Button (Google Play Music)
|
|
228
|
+
|
|
229
|
+
m: Media Previous
|
|
230
|
+
t: webhook
|
|
231
|
+
a:
|
|
232
|
+
Media Previous
|
|
233
|
+
Simulate Media Button (Google Play Music)
|
|
234
|
+
|
|
235
|
+
m: Media Stop
|
|
236
|
+
t: webhook
|
|
237
|
+
a:
|
|
238
|
+
Media Stop
|
|
239
|
+
Simulate Media Button (Google Play Music)
|
|
240
|
+
|
|
241
|
+
m: Open website
|
|
242
|
+
v: url
|
|
243
|
+
t: webhook
|
|
244
|
+
a: goto [lv=url]
|
|
245
|
+
|
|
246
|
+
m: Fill clipboard
|
|
247
|
+
v: clipboard
|
|
248
|
+
t: webhook
|
|
249
|
+
a:
|
|
250
|
+
Fill Clipboard
|
|
251
|
+
[lv=clipboard]
|
|
252
|
+
|
|
253
|
+
m: click text content
|
|
254
|
+
v: content
|
|
255
|
+
t: webhook
|
|
256
|
+
a:
|
|
257
|
+
UI Interaction
|
|
258
|
+
Click [[lv=content]]
|
|
259
|
+
|
|
180
260
|
m: Share location
|
|
181
261
|
t:
|
|
182
262
|
WebHook
|
|
@@ -189,7 +269,16 @@ a:
|
|
|
189
269
|
HTTP GET
|
|
190
270
|
identifier: location
|
|
191
271
|
coords: [lv=coords]
|
|
272
|
+
cell: [cell_id]
|
|
273
|
+
ssid: [ssid]
|
|
274
|
+
alt: [last_loc_alt]
|
|
275
|
+
time: [last_loc_age_timestamp]
|
|
276
|
+
mph: [last_loc_speed_mph]
|
|
277
|
+
kph: [last_loc_speed_kmh]
|
|
278
|
+
device: [device_model]
|
|
279
|
+
battery: [battery]
|
|
192
280
|
type: query
|
|
281
|
+
|
|
193
282
|
|
|
194
283
|
m: query
|
|
195
284
|
t: WebHook
|
|
@@ -247,613 +336,157 @@ m: Power connected
|
|
|
247
336
|
t: Power Connected: Any
|
|
248
337
|
a: webhook
|
|
249
338
|
|
|
250
|
-
m:
|
|
339
|
+
m: Screen on
|
|
251
340
|
t: screen on
|
|
252
|
-
a: webhook
|
|
253
|
-
|
|
254
|
-
EOF
|
|
255
|
-
|
|
256
|
-
=begin
|
|
257
|
-
m: Screen
|
|
258
|
-
v: on: true
|
|
259
|
-
t: WebHook
|
|
260
341
|
a:
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
Screen Off
|
|
265
|
-
End If
|
|
266
|
-
|
|
267
|
-
=end
|
|
268
|
-
|
|
269
|
-
module RemoteDroid
|
|
270
|
-
|
|
271
|
-
class Model
|
|
272
|
-
include AppRoutes
|
|
273
|
-
|
|
274
|
-
def initialize(obj=nil, root: 'device1', debug: false)
|
|
275
|
-
|
|
276
|
-
super()
|
|
277
|
-
@root, @debug = root, debug
|
|
278
|
-
@location = nil
|
|
279
|
-
|
|
280
|
-
if obj then
|
|
281
|
-
|
|
282
|
-
s = obj.strip
|
|
283
|
-
|
|
284
|
-
puts 's: ' + s.inspect if @debug
|
|
285
|
-
|
|
286
|
-
if s[0] == '<' or s.lines[1][0..1] == ' ' then
|
|
287
|
-
|
|
288
|
-
puts 'before easydom' if @debug
|
|
289
|
-
|
|
290
|
-
s2 = if s.lines[1][0..1] == ' ' then
|
|
291
|
-
|
|
292
|
-
lines = s.lines.map do |line|
|
|
293
|
-
line.sub(/(\w+) +is +(\w+)$/) {|x| "#{$1} {switch: #{$2}}" }
|
|
294
|
-
end
|
|
295
|
-
|
|
296
|
-
lines.join
|
|
297
|
-
|
|
298
|
-
else
|
|
299
|
-
s
|
|
300
|
-
end
|
|
301
|
-
|
|
302
|
-
@ed = EasyDom.new(s2)
|
|
303
|
-
else
|
|
304
|
-
build(s, root: root)
|
|
305
|
-
end
|
|
306
|
-
|
|
307
|
-
end
|
|
308
|
-
|
|
309
|
-
end
|
|
310
|
-
|
|
311
|
-
def build(raw_requests, root: @root)
|
|
312
|
-
|
|
313
|
-
@ed = EasyDom.new(debug: false, root: root)
|
|
314
|
-
raw_requests.lines.each {|line| request(line) }
|
|
315
|
-
|
|
316
|
-
end
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
def get_thing(h)
|
|
320
|
-
|
|
321
|
-
h[:thing].gsub!(/ /,'_')
|
|
322
|
-
|
|
323
|
-
if not h.has_key? :location then
|
|
324
|
-
location = false
|
|
325
|
-
h[:location] = find_path(h[:thing])
|
|
326
|
-
else
|
|
327
|
-
location = true
|
|
328
|
-
end
|
|
329
|
-
|
|
330
|
-
puts 'h: ' + h.inspect if @debug
|
|
331
|
-
|
|
332
|
-
a = []
|
|
333
|
-
a += h[:location].split(/ /)
|
|
334
|
-
a << h[:thing]
|
|
335
|
-
status = a.inject(@ed) {|r,x| r.send(x)}.send(h[:action])
|
|
336
|
-
|
|
337
|
-
if location then
|
|
338
|
-
"The %s %s is %s." % [h[:location], h[:thing], status]
|
|
339
|
-
else
|
|
340
|
-
"%s is %s." % [h[:thing].capitalize, status]
|
|
341
|
-
end
|
|
342
|
-
|
|
343
|
-
end
|
|
344
|
-
|
|
345
|
-
# Object Property (op)
|
|
346
|
-
# Helpful for accessing properites in dot notation
|
|
347
|
-
# e.g. op.livingroom.light.switch = 'off'
|
|
348
|
-
#
|
|
349
|
-
def op()
|
|
350
|
-
@ed
|
|
351
|
-
end
|
|
352
|
-
|
|
353
|
-
def query(s)
|
|
354
|
-
@ed.e.element(s)
|
|
355
|
-
end
|
|
356
|
-
|
|
357
|
-
# request accepts a string in plain english
|
|
358
|
-
# e.g. request 'switch the livingroom light on'
|
|
359
|
-
#
|
|
360
|
-
def request(s)
|
|
361
|
-
|
|
362
|
-
params = {request: s}
|
|
363
|
-
requests(params)
|
|
364
|
-
h = find_request(s)
|
|
365
|
-
|
|
366
|
-
method(h.first[-1]).call(h).gsub(/_/,' ')
|
|
367
|
-
|
|
368
|
-
end
|
|
369
|
-
|
|
370
|
-
def set_thing(h)
|
|
371
|
-
|
|
372
|
-
h[:thing].gsub!(/ /,'_')
|
|
373
|
-
h[:location] = find_path(h[:thing]) unless h.has_key? :location
|
|
374
|
-
|
|
375
|
-
a = []
|
|
376
|
-
a += h[:location].split(/ /)
|
|
377
|
-
a << h[:thing]
|
|
378
|
-
|
|
379
|
-
a.inject(@ed) {|r,x| r.send(x)}.send(h[:action], h[:value])
|
|
380
|
-
|
|
381
|
-
end
|
|
382
|
-
|
|
383
|
-
def to_sliml(level: 0)
|
|
384
|
-
|
|
385
|
-
s = @ed.to_sliml
|
|
386
|
-
|
|
387
|
-
return s if level.to_i > 0
|
|
388
|
-
|
|
389
|
-
lines = s.lines.map do |line|
|
|
390
|
-
|
|
391
|
-
line.sub(/\{[^\}]+\}/) do |x|
|
|
392
|
-
|
|
393
|
-
a = x.scan(/\w+: +[^ ]+/)
|
|
394
|
-
if a.length == 1 and x[/switch:/] then
|
|
395
|
-
|
|
396
|
-
val = x[/(?<=switch: ) *["']([^"']+)/,1]
|
|
397
|
-
'is ' + val
|
|
398
|
-
else
|
|
399
|
-
x
|
|
400
|
-
end
|
|
401
|
-
|
|
402
|
-
end
|
|
403
|
-
end
|
|
404
|
-
|
|
405
|
-
lines.join
|
|
406
|
-
|
|
407
|
-
end
|
|
408
|
-
|
|
409
|
-
def to_xml(options=nil)
|
|
410
|
-
@ed.xml(pretty: true).gsub(' style=\'\'','')
|
|
411
|
-
end
|
|
412
|
-
|
|
413
|
-
alias xml to_xml
|
|
414
|
-
|
|
415
|
-
# to_xml() is the preferred method
|
|
416
|
-
|
|
417
|
-
protected
|
|
418
|
-
|
|
419
|
-
def requests(params)
|
|
420
|
-
|
|
421
|
-
# e.g. switch the livingroom gas_fire off
|
|
422
|
-
#
|
|
423
|
-
get /(?:switch|turn) the ([^ ]+) +([^ ]+) +(on|off)$/ do |location, device, onoff|
|
|
424
|
-
{type: :set_thing, action: 'switch=', location: location, thing: device, value: onoff}
|
|
425
|
-
end
|
|
426
|
-
|
|
427
|
-
# e.g. switch the gas _fire off
|
|
428
|
-
#
|
|
429
|
-
get /(?:switch|turn) the ([^ ]+) +(on|off)$/ do |device, onoff|
|
|
430
|
-
{type: :set_thing, action: 'switch=', thing: device, value: onoff}
|
|
431
|
-
end
|
|
432
|
-
|
|
433
|
-
# e.g. is the livingroom gas_fire on?
|
|
434
|
-
#
|
|
435
|
-
get /is the ([^ ]+) +([^ ]+) +(?:on|off)\??$/ do |location, device|
|
|
436
|
-
{type: :get_thing, action: 'switch', location: location, thing: device}
|
|
437
|
-
end
|
|
438
|
-
|
|
439
|
-
# e.g. enable airplane mode
|
|
440
|
-
#
|
|
441
|
-
get /((?:dis|en)able) ([^$]+)$/ do |state, service|
|
|
442
|
-
{type: :set_thing, action: 'switch=', thing: service, value: state + 'd'}
|
|
443
|
-
end
|
|
444
|
-
|
|
445
|
-
# e.g. switch airplane mode off
|
|
446
|
-
#
|
|
447
|
-
get /switch (.*) (on|off)/ do |service, rawstate|
|
|
448
|
-
|
|
449
|
-
state = rawstate == 'on' ? 'enabled' : 'disabled'
|
|
450
|
-
{type: :set_thing, action: 'switch=', thing: service, value: state}
|
|
451
|
-
|
|
452
|
-
end
|
|
453
|
-
|
|
454
|
-
# e.g. is airplane mode enabed?
|
|
455
|
-
#
|
|
456
|
-
get /is (.*) +(?:(?:dis|en)abled)\??$/ do |service|
|
|
457
|
-
{type: :get_thing, action: 'switch', thing: service.gsub(/ /,'_')}
|
|
458
|
-
end
|
|
459
|
-
|
|
460
|
-
# e.g. is the gas_fire on?
|
|
461
|
-
#
|
|
462
|
-
get /is the ([^ ]+) +(?:on|off)\??$/ do |device|
|
|
463
|
-
location = find_path(device)
|
|
464
|
-
{type: :get_thing, action: 'switch', location: location, thing: device}
|
|
465
|
-
end
|
|
466
|
-
|
|
467
|
-
# e.g. fetch the livingroom temperature reading
|
|
468
|
-
#
|
|
469
|
-
get /fetch the ([^ ]+) +([^ ]+) +(?:reading)$/ do |location, device|
|
|
470
|
-
{type: :get_thing, action: 'reading', location: location, thing: device}
|
|
471
|
-
end
|
|
472
|
-
|
|
473
|
-
# e.g. fetch the temperature reading
|
|
474
|
-
#
|
|
475
|
-
get /fetch the ([^ ]+) +(?:reading)$/ do |device|
|
|
476
|
-
location = find_path(device)
|
|
477
|
-
{type: :get_thing, action: 'reading', location: location, thing: device}
|
|
478
|
-
end
|
|
479
|
-
|
|
480
|
-
end
|
|
481
|
-
|
|
482
|
-
private
|
|
483
|
-
|
|
484
|
-
def find_path(s)
|
|
485
|
-
puts 'find_path s: ' + s.inspect if @debug
|
|
486
|
-
found = query('//'+ s)
|
|
487
|
-
return unless found
|
|
488
|
-
a = found.backtrack.to_xpath.split('/')
|
|
489
|
-
a[1..-2].join(' ')
|
|
490
|
-
end
|
|
491
|
-
|
|
492
|
-
alias find_request run_route
|
|
493
|
-
|
|
494
|
-
end
|
|
495
|
-
|
|
496
|
-
class Controller
|
|
497
|
-
|
|
498
|
-
attr_reader :model, :control
|
|
499
|
-
attr_accessor :title, :macros, :store
|
|
500
|
-
|
|
501
|
-
def initialize(mcs, model=MODEL, deviceid: nil, debug: false)
|
|
502
|
-
|
|
503
|
-
@debug = debug
|
|
504
|
-
@syslog = []
|
|
505
|
-
|
|
506
|
-
@control = Control.new(deviceid)
|
|
507
|
-
@macros = mcs.macros
|
|
508
|
-
|
|
509
|
-
if model then
|
|
510
|
-
@model = Model.new(model)
|
|
511
|
-
end
|
|
512
|
-
|
|
513
|
-
@store = {}
|
|
514
|
-
@query = Query.new(self)
|
|
515
|
-
|
|
516
|
-
end
|
|
517
|
-
|
|
518
|
-
def export(s)
|
|
519
|
-
@macros = MacroDroid.new(s).macros
|
|
520
|
-
end
|
|
521
|
-
|
|
522
|
-
def invoke(name, options={})
|
|
523
|
-
|
|
524
|
-
if @control.respond_to? name.to_sym then
|
|
525
|
-
@control.method(name.to_sym).call(options)
|
|
526
|
-
else
|
|
527
|
-
@control.http_exec name.to_sym, options
|
|
528
|
-
end
|
|
529
|
-
end
|
|
530
|
-
|
|
531
|
-
# Object Property (op)
|
|
532
|
-
# Helpful for accessing properites in dot notation
|
|
533
|
-
# e.g. op.livingroom.light.switch = 'off'
|
|
534
|
-
#
|
|
535
|
-
def op()
|
|
536
|
-
@model.op
|
|
537
|
-
end
|
|
538
|
-
|
|
539
|
-
def query(id=nil)
|
|
540
|
-
|
|
541
|
-
return @query unless id
|
|
542
|
-
|
|
543
|
-
@store[id] = nil
|
|
342
|
+
webhook
|
|
343
|
+
identifier: screen_on_off
|
|
344
|
+
screen_on: true
|
|
544
345
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
:usb_mass_storage_enabled, :wifi_on]
|
|
549
|
-
|
|
550
|
-
secure = %i(bluetooth_name flashlight_enabled)
|
|
346
|
+
m: Power Button Toggle3
|
|
347
|
+
t: Power Button Toggle (3)
|
|
348
|
+
a: webhook
|
|
551
349
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
if id.downcase.to_sym == :location then
|
|
556
|
-
@control.http_exec id
|
|
557
|
-
elsif sys.include? id
|
|
558
|
-
@control.http_exec :'query-setting-system', {qvar: id}
|
|
559
|
-
elsif global.include? id
|
|
560
|
-
@control.http_exec :'query-setting-global', {qvar: id}
|
|
561
|
-
elsif secure.include? id
|
|
562
|
-
@control.http_exec :'query-setting-secure', {qvar: id}
|
|
563
|
-
elsif id.downcase.to_sym == :'take-picture'
|
|
564
|
-
@control.http_exec id
|
|
565
|
-
else
|
|
566
|
-
@control.http_exec :query, {qvar: id}
|
|
567
|
-
end
|
|
568
|
-
|
|
569
|
-
# wait for the local variable to be updated
|
|
570
|
-
# timeout after 5 seoncds
|
|
571
|
-
t = Time.now
|
|
572
|
-
|
|
573
|
-
begin
|
|
574
|
-
sleep 1
|
|
575
|
-
end until @store[id] or Time.now > t + 10
|
|
576
|
-
|
|
577
|
-
return {warning: 'HTTP response timeout'} if Time.now > t+5
|
|
578
|
-
|
|
579
|
-
return @store[id]
|
|
350
|
+
m: Power Button Toggle4
|
|
351
|
+
t: Power Button Toggle (4)
|
|
352
|
+
a: webhook
|
|
580
353
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
def request(s)
|
|
585
|
-
@model.request s
|
|
586
|
-
end
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
def trigger(name, detail={time: Time.now})
|
|
590
|
-
|
|
591
|
-
macros = @macros.select do |macro|
|
|
592
|
-
|
|
593
|
-
puts 'macro: ' + macro.inspect if @debug
|
|
354
|
+
m: Power Button Toggle5
|
|
355
|
+
t: Power Button Toggle (5)
|
|
356
|
+
a: webhook
|
|
594
357
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
@syslog << [Time.now, :trigger, name]
|
|
604
|
-
@syslog << [Time.now, :macro, macro.title]
|
|
605
|
-
end
|
|
606
|
-
|
|
607
|
-
valid_trigger
|
|
608
|
-
|
|
609
|
-
end
|
|
610
|
-
|
|
611
|
-
puts 'macros: ' + macros.inspect if @debug
|
|
612
|
-
|
|
613
|
-
macros.flat_map(&:run)
|
|
614
|
-
end
|
|
615
|
-
|
|
616
|
-
alias trigger_fired trigger
|
|
617
|
-
|
|
618
|
-
def update(id, val)
|
|
619
|
-
|
|
620
|
-
key = if %i(location take-picture).include? id
|
|
621
|
-
id
|
|
622
|
-
else
|
|
623
|
-
val.keys.first.to_sym
|
|
624
|
-
end
|
|
625
|
-
|
|
626
|
-
@store[key] = val
|
|
627
|
-
end
|
|
628
|
-
|
|
629
|
-
end
|
|
358
|
+
m: Connected to network
|
|
359
|
+
t:
|
|
360
|
+
Connected to network
|
|
361
|
+
Any Network
|
|
362
|
+
a: wait 2 seconds
|
|
363
|
+
a:
|
|
364
|
+
webhook
|
|
365
|
+
ssid: [ssid]
|
|
630
366
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
end
|
|
640
|
-
end
|
|
641
|
-
|
|
642
|
-
class Toast < Service
|
|
643
|
-
|
|
644
|
-
def invoke()
|
|
645
|
-
@callback.call :toast
|
|
646
|
-
end
|
|
647
|
-
|
|
648
|
-
end
|
|
649
|
-
|
|
650
|
-
class Torch < Service
|
|
651
|
-
|
|
652
|
-
def toggle()
|
|
653
|
-
@callback.http_exec :torch
|
|
654
|
-
end
|
|
655
|
-
|
|
656
|
-
end
|
|
657
|
-
|
|
658
|
-
class ControlHelper
|
|
659
|
-
|
|
660
|
-
def initialize(callback)
|
|
661
|
-
@callback
|
|
662
|
-
end
|
|
663
|
-
end
|
|
367
|
+
m: In Vehicle
|
|
368
|
+
t:
|
|
369
|
+
Activity - In Vehicle
|
|
370
|
+
Confidence >= 50%
|
|
371
|
+
a:
|
|
372
|
+
webhook
|
|
373
|
+
identifier: activity
|
|
374
|
+
index: 0
|
|
664
375
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
def bluetooth()
|
|
674
|
-
@bluetooth
|
|
675
|
-
end
|
|
676
|
-
|
|
677
|
-
def camera_flash_light(options={})
|
|
678
|
-
http_exec 'camera-flash-light', options
|
|
679
|
-
end
|
|
376
|
+
m: On Bicycle
|
|
377
|
+
t:
|
|
378
|
+
Activity - On Bicycle
|
|
379
|
+
Confidence >= 50%
|
|
380
|
+
a:
|
|
381
|
+
webhook
|
|
382
|
+
identifier: activity
|
|
383
|
+
index: 1
|
|
680
384
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
385
|
+
m: Running
|
|
386
|
+
t:
|
|
387
|
+
Activity - Running
|
|
388
|
+
Confidence >= 50%
|
|
389
|
+
a:
|
|
390
|
+
webhook
|
|
391
|
+
identifier: activity
|
|
392
|
+
index: 2
|
|
686
393
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
def self.disable()
|
|
696
|
-
http_exec 'hotspot', {enable: false}
|
|
697
|
-
end
|
|
698
|
-
|
|
699
|
-
def self.off()
|
|
700
|
-
self.disable
|
|
701
|
-
end
|
|
702
|
-
|
|
703
|
-
self
|
|
704
|
-
|
|
705
|
-
end
|
|
706
|
-
end
|
|
707
|
-
|
|
708
|
-
def http_exec(command, options={})
|
|
709
|
-
|
|
710
|
-
url = "https://trigger.macrodroid.com/%s/%s" % [@deviceid, command]
|
|
711
|
-
|
|
712
|
-
if options and options.any? then
|
|
713
|
-
h = options
|
|
714
|
-
url += '?' + \
|
|
715
|
-
URI.escape(h.map {|key,value| "%s=%s" % [key, value]}.join('&'))
|
|
716
|
-
end
|
|
717
|
-
|
|
718
|
-
s = open(url).read
|
|
719
|
-
|
|
720
|
-
end
|
|
721
|
-
|
|
722
|
-
def location(options={})
|
|
723
|
-
http_exec 'location'
|
|
724
|
-
end
|
|
725
|
-
|
|
726
|
-
def say_current_time(options={})
|
|
727
|
-
http_exec 'say-current-time'
|
|
728
|
-
end
|
|
729
|
-
|
|
730
|
-
alias say_time say_current_time
|
|
731
|
-
|
|
732
|
-
def screen(state=nil)
|
|
733
|
-
|
|
734
|
-
if state then
|
|
735
|
-
http_exec 'screen', {on: state == :on}
|
|
736
|
-
else
|
|
737
|
-
|
|
738
|
-
def self.on()
|
|
739
|
-
http_exec 'screen', {on: true}
|
|
740
|
-
end
|
|
741
|
-
|
|
742
|
-
def self.off()
|
|
743
|
-
http_exec 'screen', {on: false}
|
|
744
|
-
end
|
|
745
|
-
|
|
746
|
-
self
|
|
747
|
-
|
|
748
|
-
end
|
|
749
|
-
end
|
|
750
|
-
|
|
751
|
-
def share_location(options={})
|
|
752
|
-
http_exec 'share-location'
|
|
753
|
-
end
|
|
754
|
-
|
|
755
|
-
def speak_text(obj)
|
|
756
|
-
|
|
757
|
-
options = case obj
|
|
758
|
-
when String
|
|
759
|
-
{text: obj}
|
|
760
|
-
when Hash
|
|
761
|
-
obj
|
|
762
|
-
end
|
|
763
|
-
|
|
764
|
-
http_exec 'speak-text', options
|
|
765
|
-
end
|
|
766
|
-
|
|
767
|
-
alias say speak_text
|
|
768
|
-
|
|
769
|
-
def stay_awake(options={})
|
|
770
|
-
http_exec 'stay-awake', options
|
|
771
|
-
end
|
|
394
|
+
m: Walking
|
|
395
|
+
t:
|
|
396
|
+
Activity - Walking
|
|
397
|
+
Confidence >= 50%
|
|
398
|
+
a:
|
|
399
|
+
webhook
|
|
400
|
+
identifier: activity
|
|
401
|
+
index: 3
|
|
772
402
|
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
403
|
+
m: Still
|
|
404
|
+
t:
|
|
405
|
+
Activity - Still
|
|
406
|
+
Confidence >= 83%
|
|
407
|
+
a:
|
|
408
|
+
webhook
|
|
409
|
+
identifier: activity
|
|
410
|
+
index: 4
|
|
776
411
|
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
412
|
+
m: Swipe top left across
|
|
413
|
+
t:
|
|
414
|
+
Swipe Screen
|
|
415
|
+
Top Left - Across
|
|
416
|
+
a:
|
|
417
|
+
webhook
|
|
418
|
+
identifier: swipe
|
|
419
|
+
start: 0
|
|
420
|
+
motion: 0
|
|
421
|
+
|
|
422
|
+
m: Swipe top left diagonal
|
|
423
|
+
t:
|
|
424
|
+
Swipe Screen
|
|
425
|
+
Top Left - Diagonal
|
|
426
|
+
a:
|
|
427
|
+
webhook
|
|
428
|
+
identifier: swipe
|
|
429
|
+
start: 0
|
|
430
|
+
motion: 1
|
|
431
|
+
|
|
432
|
+
m: Swipe top left down
|
|
433
|
+
t:
|
|
434
|
+
Swipe Screen
|
|
435
|
+
Top Left - Down
|
|
436
|
+
a:
|
|
437
|
+
webhook
|
|
438
|
+
identifier: swipe
|
|
439
|
+
start: 0
|
|
440
|
+
motion: 2
|
|
441
|
+
|
|
442
|
+
m: Swipe top right across
|
|
443
|
+
t:
|
|
444
|
+
Swipe Screen
|
|
445
|
+
Top Right - Across
|
|
446
|
+
a:
|
|
447
|
+
webhook
|
|
448
|
+
identifier: swipe
|
|
449
|
+
start: 1
|
|
450
|
+
motion: 0
|
|
780
451
|
|
|
781
|
-
alias take_photo take_picture
|
|
782
452
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
453
|
+
m: Swipe top right diagonal
|
|
454
|
+
t:
|
|
455
|
+
Swipe Screen
|
|
456
|
+
Top Right - Diagonal
|
|
457
|
+
a:
|
|
458
|
+
webhook
|
|
459
|
+
identifier: swipe
|
|
460
|
+
start: 1
|
|
461
|
+
motion: 1
|
|
462
|
+
|
|
463
|
+
m: Swipe top right down
|
|
464
|
+
t:
|
|
465
|
+
Swipe Screen
|
|
466
|
+
Top Right - Down
|
|
467
|
+
a:
|
|
468
|
+
webhook
|
|
469
|
+
identifier: swipe
|
|
470
|
+
start: 1
|
|
471
|
+
motion: 2
|
|
795
472
|
|
|
473
|
+
m: flip from up to down
|
|
474
|
+
t: Flip Device Face Up -> Face Down
|
|
475
|
+
a:
|
|
476
|
+
webhook
|
|
477
|
+
identifier: flip_device
|
|
478
|
+
facedown: true
|
|
796
479
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
alias export write
|
|
805
|
-
|
|
806
|
-
def method_missing2(method_name, *args)
|
|
807
|
-
http_exec(method_name, args.first)
|
|
808
|
-
end
|
|
809
|
-
|
|
810
|
-
end
|
|
811
|
-
|
|
812
|
-
class Query
|
|
813
|
-
|
|
814
|
-
def initialize(callback)
|
|
815
|
-
@callback = callback
|
|
816
|
-
end
|
|
817
|
-
|
|
818
|
-
def airplane_mode_enabled?()
|
|
819
|
-
q(:airplane_mode_on).to_i > 0
|
|
820
|
-
end
|
|
821
|
-
|
|
822
|
-
def battery()
|
|
823
|
-
q(:battery).to_i
|
|
824
|
-
end
|
|
825
|
-
|
|
826
|
-
def current_brightness()
|
|
827
|
-
q(:current_brightness).to_i
|
|
828
|
-
end
|
|
480
|
+
m: flip from down to up
|
|
481
|
+
t: Flip Device Face Down -> Face Up
|
|
482
|
+
a:
|
|
483
|
+
webhook
|
|
484
|
+
identifier: flip_device
|
|
485
|
+
facedown: false
|
|
486
|
+
EOF
|
|
829
487
|
|
|
830
|
-
alias brightness current_brightness
|
|
831
|
-
|
|
832
|
-
def cell_id()
|
|
833
|
-
q(:cell_id)
|
|
834
|
-
end
|
|
835
|
-
|
|
836
|
-
alias cell_tower cell_id
|
|
837
|
-
|
|
838
|
-
def ip()
|
|
839
|
-
q(:ip)
|
|
840
|
-
end
|
|
841
|
-
|
|
842
|
-
def location()
|
|
843
|
-
@callback.query(:location)[:coords]
|
|
844
|
-
end
|
|
845
488
|
|
|
846
|
-
|
|
847
|
-
@callback.query(:'take-picture')
|
|
848
|
-
end
|
|
849
|
-
|
|
850
|
-
private
|
|
851
|
-
|
|
852
|
-
def q(id)
|
|
853
|
-
@callback.query(id)[id]
|
|
854
|
-
end
|
|
855
|
-
|
|
856
|
-
end
|
|
489
|
+
module RemoteDroid
|
|
857
490
|
|
|
858
491
|
class Server
|
|
859
492
|
|
|
@@ -870,127 +503,7 @@ module RemoteDroid
|
|
|
870
503
|
end
|
|
871
504
|
|
|
872
505
|
end
|
|
873
|
-
|
|
874
|
-
class Client
|
|
875
|
-
|
|
876
|
-
def initialize(host='127.0.0.1')
|
|
877
|
-
@drb = OneDrb::Client.new host: host, port: '5777'
|
|
878
|
-
end
|
|
879
|
-
|
|
880
|
-
def control
|
|
881
|
-
@drb.control
|
|
882
|
-
end
|
|
883
|
-
|
|
884
|
-
def export(s)
|
|
885
|
-
@drb.export(s)
|
|
886
|
-
end
|
|
887
|
-
|
|
888
|
-
def invoke(s, *args)
|
|
889
|
-
@drb.invoke(s, *args)
|
|
890
|
-
end
|
|
891
|
-
|
|
892
|
-
def query(id=nil)
|
|
893
|
-
|
|
894
|
-
return @drb.query unless id
|
|
895
|
-
t = Time.now
|
|
896
|
-
h = @drb.query(id)
|
|
897
|
-
h.merge({latency: (Time.now - t).round(3)})
|
|
898
|
-
|
|
899
|
-
end
|
|
900
|
-
|
|
901
|
-
def update(key, val)
|
|
902
|
-
@drb.update key.to_sym, val
|
|
903
|
-
end
|
|
904
|
-
|
|
905
|
-
def store()
|
|
906
|
-
@drb.store
|
|
907
|
-
end
|
|
908
|
-
|
|
909
|
-
# -- helpful methods -----------------
|
|
910
|
-
|
|
911
|
-
def battery()
|
|
912
|
-
query.battery
|
|
913
|
-
end
|
|
914
|
-
|
|
915
|
-
def cell_tower()
|
|
916
|
-
query.cell_tower
|
|
917
|
-
end
|
|
918
|
-
|
|
919
|
-
def hotspot(state=nil)
|
|
920
|
-
control.hotspot state
|
|
921
|
-
end
|
|
922
|
-
|
|
923
|
-
def location()
|
|
924
|
-
query.location
|
|
925
|
-
end
|
|
926
|
-
|
|
927
|
-
def photo()
|
|
928
|
-
take_picture
|
|
929
|
-
end
|
|
930
|
-
|
|
931
|
-
def say(text)
|
|
932
|
-
control.speak_text text
|
|
933
|
-
end
|
|
934
|
-
|
|
935
|
-
def say_time()
|
|
936
|
-
control.say_time
|
|
937
|
-
end
|
|
938
|
-
|
|
939
|
-
alias saytime say_time
|
|
940
|
-
|
|
941
|
-
def screen(state=nil)
|
|
942
|
-
control.screen state
|
|
943
|
-
end
|
|
944
|
-
|
|
945
|
-
def screen_on()
|
|
946
|
-
screen :on
|
|
947
|
-
end
|
|
948
|
-
|
|
949
|
-
def screen_off()
|
|
950
|
-
screen :off
|
|
951
|
-
end
|
|
952
|
-
|
|
953
|
-
def stay_awake()
|
|
954
|
-
control.stay_awake
|
|
955
|
-
end
|
|
956
|
-
|
|
957
|
-
def stay_awake_off()
|
|
958
|
-
control.stay_awake_off
|
|
959
|
-
end
|
|
960
|
-
|
|
961
|
-
def take_picture(ftp_src: nil, fileout: '.')
|
|
962
|
-
|
|
963
|
-
#screen.on
|
|
964
|
-
r = query.take_picture
|
|
965
|
-
|
|
966
|
-
if ftp_src then
|
|
967
|
-
|
|
968
|
-
# the sleep statement will be replaced in the near future,
|
|
969
|
-
# but it's fine to demonstrate it works
|
|
970
|
-
#sleep 8
|
|
971
|
-
|
|
972
|
-
credentials, dir = ftp_src.match(/(ftp:\/\/[^\/]+)\/([^$]+)/).captures
|
|
973
|
-
ftp = MyMediaFTP.new(credentials)
|
|
974
|
-
ftp.cd dir
|
|
975
|
-
filename = ftp.ls.sort_by {|x| x[:ctime]}.last[:name]
|
|
976
|
-
ftp.cp filename, fileout
|
|
977
|
-
|
|
978
|
-
end
|
|
979
|
-
|
|
980
|
-
end
|
|
981
|
-
|
|
982
|
-
alias take_photo take_picture
|
|
983
506
|
|
|
984
|
-
def torch()
|
|
985
|
-
control.torch
|
|
986
|
-
end
|
|
987
|
-
|
|
988
|
-
def vibrate
|
|
989
|
-
control.vibrate
|
|
990
|
-
end
|
|
991
|
-
|
|
992
|
-
end
|
|
993
|
-
|
|
994
507
|
class TriggerSubscriber < SPSSub
|
|
995
508
|
|
|
996
509
|
def initialize(host: 'sps.home', drb_host: '127.0.0.1')
|
|
@@ -1025,8 +538,19 @@ module RemoteDroid
|
|
|
1025
538
|
|
|
1026
539
|
context, json = msg.split(/:\s+/,2)
|
|
1027
540
|
category, action = context.split('/',2)
|
|
1028
|
-
|
|
1029
|
-
|
|
541
|
+
|
|
542
|
+
h = JSON.parse(json, symbolize_names: true)
|
|
543
|
+
|
|
544
|
+
if action == 'force_macro_run' and h[:serverside] then
|
|
545
|
+
|
|
546
|
+
a = @remote.run_macro(h)
|
|
547
|
+
a.each {|msg| self.notice 'macrodroid/action: ' + msg }
|
|
548
|
+
|
|
549
|
+
else
|
|
550
|
+
|
|
551
|
+
@remote.control.method(action.to_sym).call(h)
|
|
552
|
+
|
|
553
|
+
end
|
|
1030
554
|
|
|
1031
555
|
end
|
|
1032
556
|
|
|
@@ -1057,3 +581,12 @@ module RemoteDroid
|
|
|
1057
581
|
|
|
1058
582
|
end
|
|
1059
583
|
end
|
|
584
|
+
|
|
585
|
+
# PASTE_END
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
require 'remotedroid/model'
|
|
589
|
+
require 'remotedroid/query'
|
|
590
|
+
require 'remotedroid/control'
|
|
591
|
+
require 'remotedroid/controller'
|
|
592
|
+
require 'remotedroid/client'
|