ledenet_api 0.1.11 → 1.0.0

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: 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