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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 68dcd827b96c8dddcbf6723c1cfbc91f513b92c9
4
- data.tar.gz: 675598aee283db134b67f3244133043379680341
3
+ metadata.gz: 1e5a2d9ff7a5bd2ea66e36a38c24a53a03d93cd9
4
+ data.tar.gz: c8ee0410e7171bb40b079c6b9bdc4ebe537bddf6
5
5
  SHA512:
6
- metadata.gz: a39d66e9beaa1e7473078c9019472a7b869be43febbc88e08fae52c16e9c6498bad99bbf4a09a1101d6a8238f9a85cad19b651a9c27bacac16c413d05e7d8cf1
7
- data.tar.gz: 83de2af313aec84fb0dafe33d53b23e986a22957e1d2acad2f9835683382b1eaa0a452048c8d62f4fd67426071d412a772448afde1bcbfd26ebf91781be8634f
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.
@@ -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}")
@@ -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 buton: #{button_key}" if ircc_codes[button_key].nil?
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
@@ -1,3 +1,3 @@
1
1
  module Bravtroller
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
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.0
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-10 00:00:00.000000000 Z
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