tp_link_smartplug 0.1.0.alpha1 → 0.2.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
  SHA256:
3
- metadata.gz: 23a1848523acc948dd653d39fa3b9cec937bdba9d2a0ad6970308bac4af64d8d
4
- data.tar.gz: dd4d4a0fda92aeabfdc7adfb5f751f1b957438b168e5c96efaf4950d69e1bb3d
3
+ metadata.gz: c2553721065bc41fadca17408f6baacfa4fab953ec5df3e33d778c967910892f
4
+ data.tar.gz: 8b16c4709a255057a9db1f98b1e825d6e79eda470423a14e16da655db4be44f5
5
5
  SHA512:
6
- metadata.gz: e2259524ac344b200b19d4824178dfe18b5b7d92c8fbead1b3a4c40f3c073a3078b529f73bf035c4e1505f9827c9323f2f5c8e98f8076270783ed701d1ce6058
7
- data.tar.gz: 24ae9be641e069804c884abd18594ee8a2c355370033c06c36091dff990c0846325cc9878c1e08550658e88fabebe42e98ce60b0edf82cc57f71006b0b5d1753
6
+ metadata.gz: e9bf31292404284bc0705955133b20fcdf75bd34cf7e10e71b84e9332834c92f03697df54bfc472ae0502165771b64402c1c31cbdc1759414975a5820d5aaa80
7
+ data.tar.gz: a137ee0a57e53f4d85aa6841ac58cfdf1d14d29bf5e800759398a8d6767bb9e4b8b3a4a4249f002ea446ebc6d1e863f1f7de6e4cf10d80c0562ed7800d555cf2
@@ -1,7 +1,11 @@
1
- # frozen_string_literal: true
1
+ require_relative 'tp_link_smartplug/_base'
2
+ require_relative 'tp_link_smartplug/command'
3
+ require_relative 'tp_link_smartplug/device'
4
+ require_relative 'tp_link_smartplug/helpers'
5
+ require_relative 'tp_link_smartplug/message'
6
+ require_relative 'tp_link_smartplug/version'
2
7
 
3
- require 'tp_link_smartplug/command'
4
- require 'tp_link_smartplug/device'
5
- require 'tp_link_smartplug/helpers'
6
- require 'tp_link_smartplug/message'
7
- require 'tp_link_smartplug/version'
8
+ # Top level module
9
+ #
10
+ # @author Ben Hughes
11
+ module TpLinkSmartplug; end
@@ -0,0 +1,17 @@
1
+ require_relative 'helpers'
2
+
3
+ module TpLinkSmartplug
4
+ # Base plug class.
5
+ #
6
+ # @author Ben Hughes
7
+ class Base
8
+ include TpLinkSmartplug::Helpers
9
+
10
+ def initialize; end
11
+ end
12
+
13
+ # Base plug error class.
14
+ #
15
+ # @author Ben Hughes
16
+ class BaseError < StandardError; end
17
+ end
@@ -1,31 +1,29 @@
1
- # frozen_string_literal: true
2
-
3
1
  module TpLinkSmartplug
4
2
  # Module containing the static commands for the plug
5
3
  module Command
6
4
  # Plug information command
7
- INFO = '{"system":{"get_sysinfo":{}}}'
5
+ INFO = '{"system":{"get_sysinfo":{}}}'.freeze
8
6
  # Plug output on command
9
- ON = '{"system":{"set_relay_state":{"state":1}}}'
7
+ ON = '{"system":{"set_relay_state":{"state":1}}}'.freeze
10
8
  # Plug output off command
11
- OFF = '{"system":{"set_relay_state":{"state":0}}}'
9
+ OFF = '{"system":{"set_relay_state":{"state":0}}}'.freeze
12
10
  # Plug cloud info command
13
- CLOUDINFO = '{"cnCloud":{"get_info":{}}}'
11
+ CLOUDINFO = '{"cnCloud":{"get_info":{}}}'.freeze
14
12
  # Plug WLAN SSID scan command
15
- WLANSCAN = '{"netif":{"get_scaninfo":{"refresh":0}}}'
13
+ WLANSCAN = '{"netif":{"get_scaninfo":{"refresh":0}}}'.freeze
16
14
  # Plug time command
17
- TIME = '{"time":{"get_time":{}}}'
15
+ TIME = '{"time":{"get_time":{}}}'.freeze
18
16
  # Plug schedule command
19
- SCHEDULE = '{"schedule":{"get_rules":{}}}'
17
+ SCHEDULE = '{"schedule":{"get_rules":{}}}'.freeze
20
18
  # Plug countdown command
21
- COUNTDOWN = '{"count_down":{"get_rules":{}}}'
19
+ COUNTDOWN = '{"count_down":{"get_rules":{}}}'.freeze
22
20
  # Plug antitheft command
23
- ANTITHEFT = '{"anti_theft":{"get_rules":{}}}'
21
+ ANTITHEFT = '{"anti_theft":{"get_rules":{}}}'.freeze
24
22
  # Plug reboot command
25
- REBOOT = '{"system":{"reboot":{"delay":1}}}'
23
+ REBOOT = '{"system":{"reboot":{"delay":1}}}'.freeze
26
24
  # Plug reset command
27
- RESET = '{"system":{"reset":{"delay":1}}}'
25
+ RESET = '{"system":{"reset":{"delay":1}}}'.freeze
28
26
  # Plug energy command
29
- ENERGY = '{"emeter":{"get_realtime":{}}}'
27
+ ENERGY = '{"emeter":{"get_realtime":{}}}'.freeze
30
28
  end
31
29
  end
@@ -1,10 +1,7 @@
1
- # frozen_string_literal: true
2
-
3
1
  require 'socket'
4
2
  require 'ipaddr'
5
3
  require 'json'
6
- require 'tp_link_smartplug/helpers'
7
- require 'tp_link_smartplug/message'
4
+ require_relative './message'
8
5
 
9
6
  module TpLinkSmartplug
10
7
  # Provides an object to represent to a plug
@@ -14,22 +11,22 @@ module TpLinkSmartplug
14
11
  # @attr [Integer] port Port to connect to on the plug
15
12
  # @attr [Integer] timeout Timeout value for connecting and sending commands to the plug
16
13
  # @attr [true, false] debug Control debug logging
17
- class Device
14
+ class Device < TpLinkSmartplug::Base
18
15
  include TpLinkSmartplug::Helpers
19
16
  include TpLinkSmartplug::Message
20
17
 
21
- attr_accessor :address
22
- attr_accessor :port
23
- attr_accessor :timeout
24
- attr_accessor :debug
18
+ attr_accessor :address, :port, :timeout, :poll_auto_close, :debug
25
19
 
26
20
  def initialize(address:, port: 9999)
21
+ super()
22
+
27
23
  @address = IPAddr.new(address, Socket::AF_INET)
28
24
  @port = port
29
25
  @timeout = 3
30
26
  @debug = false
31
- @sockaddr = Addrinfo.getaddrinfo(address.to_s, port, Socket::PF_INET, :STREAM, 6).first.to_sockaddr
27
+ @sockaddr = Addrinfo.getaddrinfo(@address.to_s, @port, Socket::PF_INET, :STREAM, 6).first.to_sockaddr
32
28
  @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM)
29
+ @poll_auto_close = true
33
30
  end
34
31
 
35
32
  # Open connection to plug
@@ -42,23 +39,32 @@ module TpLinkSmartplug
42
39
 
43
40
  begin
44
41
  @socket.connect_nonblock(@sockaddr)
42
+ debug_message('Connected') if @debug
45
43
  rescue IO::WaitWritable
46
44
  if IO.select(nil, [@socket], nil, timeout)
47
45
  begin
48
46
  @socket.connect_nonblock(@sockaddr)
49
47
  rescue Errno::EISCONN
50
- debug_message('Connected') if debug
48
+ debug_message('Connected') if @debug
49
+ rescue Errno::ECONNREFUSED
50
+ @socket.close
51
+ raise TpLinkSmartplug::DeviceError, "Connection refused connecting to address #{@address}, port #{@port}!"
51
52
  rescue StandardError => e
52
53
  disconnect
53
- debug_message('Unexpected exception encountered.') if debug
54
- raise e
54
+ debug_message("Unexpected exception encountered. Error: #{e}") if @debug
55
+ raise
55
56
  end
56
57
  else
57
58
  @socket.close
58
- raise "Connection timeout connecting to address #{@address}, port #{@port}."
59
+ raise TpLinkSmartplug::DeviceError, "Connection timeout connecting to address #{@address}, port #{@port}."
59
60
  end
60
61
  rescue Errno::EISCONN
61
- debug_message('Connected') if debug
62
+ debug_message('Connected') if @debug
63
+ rescue Errno::EINPROGRESS
64
+ debug_message('Connection in progress') if @debug
65
+ retry
66
+ rescue Errno::ECONNREFUSED
67
+ raise TpLinkSmartplug::DeviceError, "Connection refused connecting to address #{@address}, port #{@port}."
62
68
  end
63
69
  end
64
70
 
@@ -68,21 +74,23 @@ module TpLinkSmartplug
68
74
  @socket.close unless @socket.closed?
69
75
  end
70
76
 
71
- # Return connection state
77
+ alias_method :close, :disconnect
78
+
79
+ # Return connection state open
72
80
  #
73
81
  # @return [True, False]
74
82
  def open?
75
83
  !@socket.closed?
76
84
  end
77
85
 
78
- # Return connection state
86
+ # Return connection state closed
79
87
  #
80
88
  # @return [True, False]
81
89
  def closed?
82
90
  @socket.closed?
83
91
  end
84
92
 
85
- # Polls a plug with a command
93
+ # Polls plug with a command
86
94
  #
87
95
  # @param command [String] the command to send to the plug
88
96
  # @return [Hash] the output from the plug command
@@ -102,16 +110,18 @@ module TpLinkSmartplug
102
110
  rescue IO::WaitReadable
103
111
  IO.select([@socket])
104
112
  retry
105
- ensure
106
- disconnect unless closed?
107
113
  end
108
114
 
109
- raise 'Error occured during disconnect' unless closed?
110
- raise 'No data received' if data.nil? || data.empty?
115
+ if @poll_auto_close && !closed?
116
+ disconnect
117
+ raise 'Error occured during disconnect' unless closed?
118
+ end
119
+
120
+ raise 'No data received' if nil_or_empty?(data)
111
121
 
112
- debug_message("Received Raw: #{data}") if debug
122
+ debug_message("Received Raw: #{data}") if @debug
113
123
  data = decrypt(data[4..data.length])
114
- debug_message("Received Decrypted: #{data}") if debug
124
+ debug_message("Received Decrypted: #{data}") if @debug
115
125
 
116
126
  data
117
127
  end
@@ -164,11 +174,13 @@ module TpLinkSmartplug
164
174
  :antitheft,
165
175
  :reboot,
166
176
  :reset,
167
- :energy
177
+ :energy,
168
178
  ].each do |method|
169
179
  define_method method do
170
180
  JSON.parse(poll(command: TpLinkSmartplug::Command.const_get(method.upcase)))
171
181
  end
172
182
  end
173
183
  end
184
+
185
+ class DeviceError < TpLinkSmartplug::BaseError; end
174
186
  end
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  require 'time'
4
2
 
5
3
  module TpLinkSmartplug
@@ -10,7 +8,16 @@ module TpLinkSmartplug
10
8
  # @param string [String] the message to be formatted for debug output
11
9
  def debug_message(string)
12
10
  caller_method = caller_locations(1..1).first.label
13
- STDOUT.puts(Time.now.strftime('%Y-%m-%d %H:%M:%S: ').concat("#{caller_method}: ").concat(string))
11
+ $stdout.puts(Time.now.strftime('%Y-%m-%d %H:%M:%S: ').concat("#{caller_method}: ").concat(string))
12
+ end
13
+
14
+ # Tests a variable for nil or empty status
15
+ #
16
+ # @param v the variable to be tested
17
+ def nil_or_empty?(value)
18
+ return true if value.nil? || (value.respond_to?(:empty?) && value.empty?)
19
+
20
+ false
14
21
  end
15
22
  end
16
23
  end
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: false
2
-
3
1
  module TpLinkSmartplug
4
2
  # Helper methods for plug communication messages
5
3
  module Message
@@ -1,7 +1,5 @@
1
- # frozen_string_literal: true
2
-
3
1
  # @author Ben Hughes
4
2
  module TpLinkSmartplug
5
3
  # Gem version
6
- VERSION = '0.0.1'
4
+ VERSION = '0.2.0'.freeze
7
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tp_link_smartplug
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.alpha1
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Hughes
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-08 00:00:00.000000000 Z
11
+ date: 2021-01-24 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Control and retrieve data from a TP-Link HS100/110 (Metered) Smartplug
14
14
  email: bmhughes@bmhughes.co.uk
@@ -17,6 +17,7 @@ extensions: []
17
17
  extra_rdoc_files: []
18
18
  files:
19
19
  - "./lib/tp_link_smartplug.rb"
20
+ - "./lib/tp_link_smartplug/_base.rb"
20
21
  - "./lib/tp_link_smartplug/command.rb"
21
22
  - "./lib/tp_link_smartplug/device.rb"
22
23
  - "./lib/tp_link_smartplug/helpers.rb"
@@ -25,7 +26,8 @@ files:
25
26
  homepage: https://github.com/bmhughes/tp_link_smartplug
26
27
  licenses:
27
28
  - Apache-2.0
28
- metadata: {}
29
+ metadata:
30
+ github_repo: ssh://github.com/bmhughes/tp_link_smartplug
29
31
  post_install_message:
30
32
  rdoc_options: []
31
33
  require_paths:
@@ -37,12 +39,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
37
39
  version: '2.5'
38
40
  required_rubygems_version: !ruby/object:Gem::Requirement
39
41
  requirements:
40
- - - ">"
42
+ - - ">="
41
43
  - !ruby/object:Gem::Version
42
- version: 1.3.1
44
+ version: '0'
43
45
  requirements: []
44
- rubyforge_project:
45
- rubygems_version: 2.7.7
46
+ rubygems_version: 3.1.4
46
47
  signing_key:
47
48
  specification_version: 4
48
49
  summary: TP-Link HS100/110 Smart Plug interaction library