ledenet_api 0.1.11 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b8e62ef0ba30a878e092cfc6b9c00a9285e52fb2
4
- data.tar.gz: 012b023d53d167c133d93a2da22a3963b069cc27
3
+ metadata.gz: ac6a8e5411f0e6bdd37433ddc3d165ba94ca0320
4
+ data.tar.gz: a642b47d4663a5656a8b7db3f21eb55b8a317e77
5
5
  SHA512:
6
- metadata.gz: 3f8f635dd04466eed819bea8e0d1f752665332974eec01f9612e65052faee166695449c0154a39397ef7ee9bcd47c1ab414405d423ef59474a5212c6f14fb38e
7
- data.tar.gz: e203a19cc9ea01064fdccbb7564a434a958372166eaa06a754b8137bd5b1a5d8e93bda880915d4868603a7461d79b879eae0956d6e53ee6c965a9750c2343b8b
6
+ metadata.gz: c9d8fd279d1e2b3f6574d2ec800a7e25cce533718bfdc61d5b3083099d6581c62f0981444d1a7f57ca5d296c7175aad64f53ab955b2e1880c4dd6056e96d7d17
7
+ data.tar.gz: f060415564c23e7adff09a80143703b18e1a023e175724469e8891c51d9cc391dfd2a5427b97b9dee6ff9df42d2233832320ea96c9da3aca5ee827b0bc7f99d1
data/Gemfile.lock CHANGED
@@ -1,11 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ledenet_api (0.1.3)
4
+ ledenet_api (0.1.11)
5
+ bindata (>= 1.8)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
8
9
  specs:
10
+ bindata (2.3.0)
9
11
  diff-lcs (1.2.5)
10
12
  rake (10.4.2)
11
13
  rspec (3.3.0)
@@ -32,4 +34,4 @@ DEPENDENCIES
32
34
  rspec
33
35
 
34
36
  BUNDLED WITH
35
- 1.10.5
37
+ 1.11.2
data/ledenet_api.gemspec CHANGED
@@ -18,6 +18,8 @@ Gem::Specification.new do |spec|
18
18
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.add_dependency 'bindata', '>= 2.3'
22
+
21
23
  spec.add_development_dependency "bundler", "~> 1.10"
22
24
  spec.add_development_dependency "rake", "~> 10.0"
23
25
  spec.add_development_dependency "rspec"
data/lib/ledenet/api.rb CHANGED
@@ -1,10 +1,13 @@
1
+ require 'ledenet/packets/set_power_request'
2
+ require 'ledenet/packets/status_request'
3
+ require 'ledenet/packets/update_color_request'
4
+
1
5
  module LEDENET
2
6
  class Api
3
- API_PORT = 5577
4
-
5
7
  DEFAULT_OPTIONS = {
6
8
  reuse_connection: false,
7
- max_retries: 3
9
+ max_retries: 3,
10
+ port: 5577
8
11
  }
9
12
 
10
13
  def initialize(device_address, options = {})
@@ -13,68 +16,69 @@ module LEDENET
13
16
  end
14
17
 
15
18
  def on
16
- send_bytes_action(0x71, 0x23, 0x0F, 0xA3)
17
-
18
- true
19
+ send_packet(LEDENET::Packets::SetPowerRequest.on_request)
19
20
  end
20
21
 
21
22
  def off
22
- send_bytes_action(0x71, 0x24 ,0x0F, 0xA4)
23
-
24
- true
23
+ send_packet(LEDENET::Packets::SetPowerRequest.off_request)
25
24
  end
26
25
 
27
26
  def on?
28
- (status.bytes[13] & 0x01) == 1
27
+ status.on?
29
28
  end
30
29
 
31
- def update_color(r, g, b)
32
- checksum = color_checksum(r, g, b)
30
+ def update_rgb(r, g, b)
31
+ update_color_data(red: r, green: g, blue: b)
32
+ end
33
33
 
34
- send_bytes_action(0x31, r, g, b, 0xFF, 0, 0x0F, checksum)
34
+ def update_warm_white(warm_white)
35
+ update_color_data(warm_white: warm_white)
36
+ end
35
37
 
36
- true
38
+ def update_color_data(o)
39
+ updated_data = current_color.merge(o)
40
+ send_packet(LEDENET::Packets::UpdateColorRequest.new(updated_data))
37
41
  end
38
42
 
39
- def current_color
40
- status.bytes[6, 3]
43
+ def current_rgb
44
+ current_color_data.values_at(:red, :green, :blue)
41
45
  end
42
46
 
43
- def reconnect!
44
- create_socket
47
+ def current_warm_white
48
+ current_color_data[:warm_white]
45
49
  end
46
50
 
47
- private
48
- def color_checksum(r, g, b)
49
- (r + g + b + 0x3F) % 0x100
51
+ def current_color_data
52
+ status_response = status
53
+ color_data = %w{red green blue warm_white}.map do |x|
54
+ [x.to_sym, status_response.send(x)]
50
55
  end
56
+ Hash[color_data]
57
+ end
51
58
 
52
- def status
53
- socket_action do
54
- send_bytes(0x81, 0x8A, 0x8B, 0x96)
55
-
56
- # Example response:
57
- # [129, 4, 35, 97, 33, 9, 11, 22, 33, 255, 3, 0, 0, 119]
58
- # R G B WW ^--- LSB indicates on/off
59
- flush_response(14)
60
- end
61
- end
59
+ def reconnect!
60
+ create_socket
61
+ true
62
+ end
62
63
 
63
- def flush_response(msg_length)
64
- @socket.recv(msg_length, Socket::MSG_WAITALL)
65
- end
64
+ def send_packet(packet)
65
+ socket_action do
66
+ @socket.write(packet.to_binary_s)
66
67
 
67
- def send_bytes(*b)
68
- @socket.write(b.pack('c*'))
68
+ if packet.response_reader != LEDENET::Packets::EmptyResponse
69
+ packet.response_reader.read(@socket)
70
+ end
69
71
  end
72
+ end
70
73
 
71
- def send_bytes_action(*b)
72
- socket_action { send_bytes(*b) }
74
+ private
75
+ def status
76
+ send_packet(LEDENET::Packets::StatusRequest.new)
73
77
  end
74
78
 
75
79
  def create_socket
76
80
  @socket.close unless @socket.nil? or @socket.closed?
77
- @socket = TCPSocket.new(@device_address, API_PORT)
81
+ @socket = TCPSocket.new(@device_address, @options[:port])
78
82
  end
79
83
 
80
84
  def socket_action
@@ -92,7 +96,9 @@ module LEDENET
92
96
  raise e
93
97
  end
94
98
  ensure
95
- @socket.close unless @socket.nil? or @socket.closed? or @options[:reuse_connection]
99
+ if !@socket.nil? && !@socket.closed? && !@options[:reuse_connection]
100
+ @socket.close
101
+ end
96
102
  end
97
103
  end
98
104
  end
@@ -18,7 +18,8 @@ module LEDENET
18
18
  DEFAULT_OPTIONS = {
19
19
  expected_devices: 1,
20
20
  timeout: 5,
21
- expected_models: []
21
+ expected_models: [],
22
+ udp_port: 48899
22
23
  }
23
24
 
24
25
  # The WiFi controllers these things appear to use support a discovery protocol
@@ -31,7 +32,7 @@ module LEDENET
31
32
  def self.discover_devices(options = {})
32
33
  options = DEFAULT_OPTIONS.merge(options)
33
34
 
34
- send_addr = ['<broadcast>', 48899]
35
+ send_addr = ['<broadcast>', options[:udp_port]]
35
36
  send_socket = UDPSocket.new
36
37
  send_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
37
38
  send_socket.send('HF-A11ASSISTHREAD', 0, send_addr[0], send_addr[1])
@@ -0,0 +1,6 @@
1
+ require 'bindata'
2
+
3
+ module LEDENET::Packets
4
+ class EmptyResponse < BinData::Record
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ require 'bindata'
2
+
3
+ module LEDENET
4
+ class Checksum < BinData::Record
5
+ mandatory_parameter :packet_data
6
+
7
+ uint8 :checksum, :value => ->() { packet_data.values.reduce(&:+) % 0x100 }
8
+ end
9
+ end
@@ -0,0 +1,29 @@
1
+ require 'bindata'
2
+
3
+ require 'ledenet/packets/fields/checksum'
4
+ require 'ledenet/packets/empty_response'
5
+
6
+ module LEDENET::Packets
7
+ class SetPowerRequest < BinData::Record
8
+ mandatory_parameter :on?
9
+ hide :checksum
10
+
11
+ uint8 :packet_id, value: 0x71
12
+ uint8 :power_status, value: ->() { on? ? 0x23 : 0x24 }
13
+ uint8 :remote_or_local, value: 0x0F
14
+
15
+ checksum :checksum, packet_data: ->() { snapshot }
16
+
17
+ def response_reader
18
+ LEDENET::Packets::EmptyResponse
19
+ end
20
+
21
+ def self.on_request
22
+ SetPowerRequest.new(on?: true)
23
+ end
24
+
25
+ def self.off_request
26
+ SetPowerRequest.new(on?: false)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,20 @@
1
+ require 'bindata'
2
+
3
+ require 'ledenet/packets/fields/checksum'
4
+ require 'ledenet/packets/status_response'
5
+
6
+ module LEDENET::Packets
7
+ class StatusRequest < BinData::Record
8
+ hide :checksum
9
+
10
+ uint8 :packet_id, value: 0x81
11
+ uint8 :payload1, value: 0x8A
12
+ uint8 :payload2, value: 0x8B
13
+
14
+ checksum :checksum, packet_data: ->() { snapshot }
15
+
16
+ def response_reader
17
+ LEDENET::Packets::StatusResponse
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,31 @@
1
+ require 'bindata'
2
+
3
+ require 'ledenet/packets/fields/checksum'
4
+
5
+ module LEDENET::Packets
6
+ class StatusResponse < BinData::Record
7
+ hide :checksum, :unused_payload
8
+
9
+ uint8 :packet_id, value: 0x81
10
+ uint8 :device_name
11
+ uint8 :power_status
12
+
13
+ # I'm not sure these are the correct field labels. Basing it off of some
14
+ # documentation that looks like it's for a slightly different protocol.
15
+ uint8 :mode
16
+ uint8 :run_status
17
+ uint8 :speed
18
+
19
+ uint8 :red
20
+ uint8 :green
21
+ uint8 :blue
22
+ uint8 :warm_white
23
+
24
+ uint16be :unused_payload, value: 0x0000
25
+ uint8 :checksum
26
+
27
+ def on?
28
+ (power_status & 0x01) == 0x01
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,28 @@
1
+ require 'bindata'
2
+
3
+ require 'ledenet/packets/fields/checksum'
4
+ require 'ledenet/packets/empty_response'
5
+
6
+ module LEDENET::Packets
7
+ class UpdateColorRequest < BinData::Record
8
+ hide :checksum
9
+
10
+ uint8 :packet_id, value: 0x31
11
+
12
+ uint8 :red
13
+ uint8 :green
14
+ uint8 :blue
15
+ uint8 :warm_white
16
+
17
+ uint8 :unused_payload, value: 0
18
+
19
+ # Not clear to me what difference this makes. Remote = 0xF0, Local = 0x0F
20
+ uint8 :remote_or_local, value: 0x0F
21
+
22
+ checksum :checksum, packet_data: ->() { snapshot }
23
+
24
+ def response_reader
25
+ LEDENET::Packets::EmptyResponse
26
+ end
27
+ end
28
+ end
@@ -1,3 +1,3 @@
1
1
  module LEDENET
2
- VERSION = '0.1.11'
2
+ VERSION = '1.0.0'
3
3
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ledenet_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.11
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Mullins
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-03-16 00:00:00.000000000 Z
11
+ date: 2016-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bindata
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '2.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '2.3'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -68,6 +82,12 @@ files:
68
82
  - ledenet_api.gemspec
69
83
  - lib/ledenet/api.rb
70
84
  - lib/ledenet/device_discovery.rb
85
+ - lib/ledenet/packets/empty_response.rb
86
+ - lib/ledenet/packets/fields/checksum.rb
87
+ - lib/ledenet/packets/set_power_request.rb
88
+ - lib/ledenet/packets/status_request.rb
89
+ - lib/ledenet/packets/status_response.rb
90
+ - lib/ledenet/packets/update_color_request.rb
71
91
  - lib/ledenet/version.rb
72
92
  - lib/ledenet_api.rb
73
93
  homepage: http://www.github.com/sidoh/ledenet_api