bravtroller 0.1.0 → 0.1.1
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
- 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
|