tp_link_smartplug 0.1.0.alpha1 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|