bravtroller 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +83 -0
- data/lib/bravtroller/client.rb +20 -0
- data/lib/bravtroller/remote.rb +11 -1
- data/lib/bravtroller/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e5a2d9ff7a5bd2ea66e36a38c24a53a03d93cd9
|
4
|
+
data.tar.gz: c8ee0410e7171bb40b079c6b9bdc4ebe537bddf6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bfcd5c7408e4adfe6dfb24c6bc917f5646c7830749c36498c6c8aa1b5bc2886ff64691e57476f06873dc164b4bf554d6e94741b074690e6921997d84e4814235
|
7
|
+
data.tar.gz: dca6881a1a3060ba680e3b888c948955e771224f3187f44084951917ea8193e307bb40793c5df2759228d954f9a4b6608cf23114e89668b8d6e9cbdb76fb7819
|
data/README.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# bravtroller
|
2
|
+
Controller for Sony Bravia KDL-50W700.
|
3
|
+
|
4
|
+
## Installing
|
5
|
+
|
6
|
+
bravtroller is available on [Rubygems](https://rubygems.org). You can install it with:
|
7
|
+
|
8
|
+
```
|
9
|
+
$ gem install bravtroller
|
10
|
+
```
|
11
|
+
|
12
|
+
You can also add it to your Gemfile:
|
13
|
+
|
14
|
+
```
|
15
|
+
gem 'bravtroller'
|
16
|
+
```
|
17
|
+
|
18
|
+
## What is it?
|
19
|
+
|
20
|
+
My Sony TV (a KDL-50W700) has an API. It's a weird combination of custom Sony JSON-over-HTTP and UPnP/SOAP. I wanted a Ruby library to control it, so I created this. I wouldn't be very surprised if other network-enabled Sony devices supported roughly the same interface.
|
21
|
+
|
22
|
+
## Authentication
|
23
|
+
|
24
|
+
#### Summary
|
25
|
+
|
26
|
+
My TV requires that a device authenticate with it before controlling it remotely. You can use `Bravtroller::Authenticator` to do that. This is what happens:
|
27
|
+
|
28
|
+
1. `Bravtroller::Authenticator` initiates an authentication request
|
29
|
+
2. The TV displays a 4 digit security code
|
30
|
+
3. A user-provided block is called to supply the security code (I just used `gets`)
|
31
|
+
4. The security code is submitted to the TV, and `Bravtroller` will then be authenticated
|
32
|
+
|
33
|
+
#### Example
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
require 'bravtroller/client'
|
37
|
+
require 'bravtroller/authenticator'
|
38
|
+
|
39
|
+
auth = Bravtroller::Authenticator.new( Bravtroller::Client.new(BRAVIA_IP_ADDRESS) )
|
40
|
+
|
41
|
+
a.authorized?
|
42
|
+
# => false
|
43
|
+
|
44
|
+
# This will initiate the procedure described above. The string returned is a cookie used by the SOAP client
|
45
|
+
a.authorize { gets.strip }
|
46
|
+
# > 3
|
47
|
+
# => "auth=xxxxxxx"
|
48
|
+
|
49
|
+
a.authorized?
|
50
|
+
# => true
|
51
|
+
```
|
52
|
+
|
53
|
+
## Example usage
|
54
|
+
|
55
|
+
The below example assumes Bravtroller has already been authenticated:
|
56
|
+
|
57
|
+
#### Remote emulator
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
require 'bravtroller/client'
|
61
|
+
require 'bravtroller/remote'
|
62
|
+
|
63
|
+
remote = Bravtroller::Remote.create( Bravtroller::Client.new(BRAVIA_IP_ADDRESS) )
|
64
|
+
|
65
|
+
remote.buttons
|
66
|
+
# => ["PowerOff", "Input", "GGuide", "EPG", "Favorites", "Display", "Home", "Options", "Return", "Up", "Down", "Right", "Left", "Confirm", "Red", "Green", "Yellow", "Blue", "Num1", "Num2", "Num3", "Num4", "Num5", "Num6", "Num7", "Num8", "Num9", "Num0", "Num11", "Num12", "VolumeUp", "VolumeDown", "Mute", "ChannelUp", "ChannelDown", "SubTitle", "ClosedCaption", "Enter", "DOT", "Analog", "Teletext", "Exit", "Analog2", "*AD", "Digital", "Analog?", "BS", "CS", "BSCS", "Ddata", "PicOff", "Tv_Radio", "Theater", "SEN", "InternetWidgets", "InternetVideo", "Netflix", "SceneSelect", "Mode3D", "iManual", "Audio", "Wide", "Jump", "PAP", "MyEPG", "ProgramDescription", "WriteChapter", "TrackID", "TenKey", "AppliCast", "acTVila", "DeleteVideo", "PhotoFrame", "TvPause", "KeyPad", "Media", "SyncMenu", "Forward", "Play", "Rewind", "Prev", "Stop", "Next", "Rec", "Pause", "Eject", "FlashPlus", "FlashMinus", "TopMenu", "PopUpMenu", "RakurakuStart", "OneTouchTimeRec", "OneTouchView", "OneTouchRec", "OneTouchStop", "DUX", "FootballMode", "Social"]
|
67
|
+
|
68
|
+
remote.press_button('VolumeUp')
|
69
|
+
```
|
70
|
+
|
71
|
+
#### Wake on LAN
|
72
|
+
|
73
|
+
You can also use `Bravtroller` to turn on the TV. Mine responds to the standard WOL magic packet, which is what the below method is doing. Assuming the same setup as above:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
remote.power_on
|
77
|
+
# => true
|
78
|
+
```
|
79
|
+
|
80
|
+
The caveat is that `remote` must be constructed while the TV is powered on. This is because:
|
81
|
+
|
82
|
+
1. It needs to communicate with the TV to construct the SOAP client. This is an artificial limitation. It could cache the service definition.
|
83
|
+
2. It need to determine the hardware address of the TV (necessary to construct the WOL packet). It does this by shelling out and calling `arp`. If the TV isn't in the ARP cache, it won't be able to determine the hardware address. Again -- an artificial limitation.
|
data/lib/bravtroller/client.rb
CHANGED
@@ -7,6 +7,26 @@ module Bravtroller
|
|
7
7
|
@bravia_address = bravia_address
|
8
8
|
end
|
9
9
|
|
10
|
+
def hw_addr
|
11
|
+
arp = `which arp`.strip
|
12
|
+
|
13
|
+
raise RuntimeError.new "Couldn't find arp binary" if arp.empty?
|
14
|
+
|
15
|
+
result = `#{arp} #{@bravia_address}`
|
16
|
+
hw_addr_match = result.match(/((?:[a-f0-9]{1,2}:?){6})/i)
|
17
|
+
if hw_addr_match.nil?
|
18
|
+
nil
|
19
|
+
else
|
20
|
+
# On my mac, octets with the most significant nibble = 0 show as "0" instead of "00"
|
21
|
+
hw_addr_match
|
22
|
+
.captures
|
23
|
+
.first
|
24
|
+
.split(':')
|
25
|
+
.map { |x| "#{x.length == 1 ? '0' : ''}#{x}" }
|
26
|
+
.join(':')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
10
30
|
def post_request(path, params = {}, headers = {})
|
11
31
|
json = JSON.generate(params)
|
12
32
|
uri = URI("http://#{@bravia_address}#{path}")
|
data/lib/bravtroller/remote.rb
CHANGED
@@ -40,8 +40,18 @@ module Bravtroller
|
|
40
40
|
@bravia_client = bravia_client
|
41
41
|
end
|
42
42
|
|
43
|
+
def power_on
|
44
|
+
addr = ['<broadcast>', 9]
|
45
|
+
sock = UDPSocket.new
|
46
|
+
sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
|
47
|
+
packet_data = (([255] * 6) + (@bravia_client.hw_addr.split(':').map(&:hex) * 16)).pack('C*')
|
48
|
+
sock.send(packet_data, 0, addr[0], addr[1])
|
49
|
+
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
43
53
|
def press_button(button_key)
|
44
|
-
raise RuntimeError.new "Undefined
|
54
|
+
raise RuntimeError.new "Undefined button: #{button_key}" if ircc_codes[button_key].nil?
|
45
55
|
|
46
56
|
@ircc_client.X_SendIRCC IRCCCode: ircc_codes[button_key]
|
47
57
|
end
|
data/lib/bravtroller/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bravtroller
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christopher Mullins
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-07-
|
11
|
+
date: 2015-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: easy_upnp
|
@@ -62,6 +62,7 @@ files:
|
|
62
62
|
- Gemfile
|
63
63
|
- Gemfile.lock
|
64
64
|
- LICENSE
|
65
|
+
- README.md
|
65
66
|
- Rakefile
|
66
67
|
- bravtroller.gemspec
|
67
68
|
- lib/bravtroller.rb
|