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 +4 -4
- data/lib/tp_link_smartplug.rb +10 -6
- data/lib/tp_link_smartplug/_base.rb +17 -0
- data/lib/tp_link_smartplug/command.rb +12 -14
- data/lib/tp_link_smartplug/device.rb +37 -25
- data/lib/tp_link_smartplug/helpers.rb +10 -3
- data/lib/tp_link_smartplug/message.rb +0 -2
- data/lib/tp_link_smartplug/version.rb +1 -3
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2553721065bc41fadca17408f6baacfa4fab953ec5df3e33d778c967910892f
|
4
|
+
data.tar.gz: 8b16c4709a255057a9db1f98b1e825d6e79eda470423a14e16da655db4be44f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9bf31292404284bc0705955133b20fcdf75bd34cf7e10e71b84e9332834c92f03697df54bfc472ae0502165771b64402c1c31cbdc1759414975a5820d5aaa80
|
7
|
+
data.tar.gz: a137ee0a57e53f4d85aa6841ac58cfdf1d14d29bf5e800759398a8d6767bb9e4b8b3a4a4249f002ea446ebc6d1e863f1f7de6e4cf10d80c0562ed7800d555cf2
|
data/lib/tp_link_smartplug.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
-
|
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
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
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(
|
54
|
-
raise
|
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
|
-
|
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
|
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
|
-
|
110
|
-
|
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
|
-
|
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
|
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
|
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:
|
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:
|
44
|
+
version: '0'
|
43
45
|
requirements: []
|
44
|
-
|
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
|