Class: TpLinkSmartplug::Device

Inherits:
Base
  • Object
show all
Includes:
Helpers, Message
Defined in:
lib/tp_link_smartplug/device.rb

Overview

Provides an object to represent to a plug

Author:

  • Ben Hughes

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Message

#decrypt, #encrypt

Methods included from Helpers

#debug_message, #nil_or_empty?

Constructor Details

#initialize(address:, port: 9999, auto_connect: true, auto_disconnect: true) ⇒ Device

Returns a new instance of Device.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/tp_link_smartplug/device.rb', line 21

def initialize(address:, port: 9999, auto_connect: true, auto_disconnect: true)
  super()

  @address = IPAddr.new(address, Socket::AF_INET)
  @port = port
  @timeout = 3
  @debug = false
  @sockaddr = Addrinfo.getaddrinfo(@address.to_s, @port, Socket::PF_INET, :STREAM, 6).first.to_sockaddr
  @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM)
  @poll_auto_close = auto_disconnect
  @auto_connect = auto_connect

  connect if auto_connect
end

Instance Attribute Details

#addressIPAddr

IP address of the plug

Returns:

  • (IPAddr)

    the current value of address



15
16
17
# File 'lib/tp_link_smartplug/device.rb', line 15

def address
  @address
end

#auto_connectObject

Returns the value of attribute auto_connect.



19
20
21
# File 'lib/tp_link_smartplug/device.rb', line 19

def auto_connect
  @auto_connect
end

#debugtrue, false

Control debug logging

Returns:

  • (true, false)

    the current value of debug



15
16
17
# File 'lib/tp_link_smartplug/device.rb', line 15

def debug
  @debug
end

#poll_auto_closeObject

Returns the value of attribute poll_auto_close.



19
20
21
# File 'lib/tp_link_smartplug/device.rb', line 19

def poll_auto_close
  @poll_auto_close
end

#portInteger

Port to connect to on the plug

Returns:

  • (Integer)

    the current value of port



15
16
17
# File 'lib/tp_link_smartplug/device.rb', line 15

def port
  @port
end

#timeoutInteger

Timeout value for connecting and sending commands to the plug

Returns:

  • (Integer)

    the current value of timeout



15
16
17
# File 'lib/tp_link_smartplug/device.rb', line 15

def timeout
  @timeout
end

Instance Method Details

#antitheftHash

Unsure

Returns:

  • (Hash)


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/tp_link_smartplug/device.rb', line 182

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :timezone,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy,
  :energygains,
  :ledon,
  :ledoff,
].each do |method|
  define_method method do
    JSON.parse(poll(command: TpLinkSmartplug::Command.const_get(method.upcase)))
  end
end

#closed?True, False

Return connection state closed

Returns:

  • (True, False)


93
94
95
96
97
98
99
# File 'lib/tp_link_smartplug/device.rb', line 93

def closed?
  @socket.recvfrom_nonblock(0)
rescue IO::WaitReadable
  false
rescue Errno::ENOTCONN, IOError
  true
end

#cloudinfoHash

Return plug cloud account configuration

Returns:

  • (Hash)


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/tp_link_smartplug/device.rb', line 182

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :timezone,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy,
  :energygains,
  :ledon,
  :ledoff,
].each do |method|
  define_method method do
    JSON.parse(poll(command: TpLinkSmartplug::Command.const_get(method.upcase)))
  end
end

#connectObject

Open connection to plug



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/tp_link_smartplug/device.rb', line 38

def connect
  debug_message("Connecting to #{@address} port #{@port}") if @debug
  debug_message("Connecting, socket state: #{@socket.closed? ? 'closed' : 'open'}") if @debug

  @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM) if closed?

  begin
    @socket.connect_nonblock(@sockaddr)
    debug_message('Connected') if @debug
  rescue IO::WaitWritable
    if @socket.wait_writable(@timeout)
      begin
        @socket.connect_nonblock(@sockaddr)
      rescue Errno::EISCONN
        debug_message('Connected') if @debug
      rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
        @socket.close
        raise TpLinkSmartplug::DeviceError, "Connection refused or host unreachable connecting to address #{@address}, port #{@port}!"
      rescue StandardError => e
        disconnect
        debug_message("Unexpected exception encountered. Error: #{e}") if @debug
        raise
      end
    else
      disconnect
      raise TpLinkSmartplug::DeviceError, "Connection timeout connecting to address #{@address}, port #{@port}."
    end
  rescue Errno::EISCONN
    debug_message('Connected') if @debug
  rescue Errno::EINPROGRESS
    debug_message('Connection in progress') if @debug
    retry
  rescue Errno::ECONNREFUSED
    raise TpLinkSmartplug::DeviceError, "Connection refused connecting to address #{@address}, port #{@port}."
  end
end

#countdownHash

Return countdown configured on the plug

Returns:

  • (Hash)


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/tp_link_smartplug/device.rb', line 182

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :timezone,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy,
  :energygains,
  :ledon,
  :ledoff,
].each do |method|
  define_method method do
    JSON.parse(poll(command: TpLinkSmartplug::Command.const_get(method.upcase)))
  end
end

#disconnectObject Also known as: close

Close connection to plug



77
78
79
# File 'lib/tp_link_smartplug/device.rb', line 77

def disconnect
  @socket.close unless closed?
end

#energyHash

Return plug energy data

Returns:

  • (Hash)


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/tp_link_smartplug/device.rb', line 182

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :timezone,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy,
  :energygains,
  :ledon,
  :ledoff,
].each do |method|
  define_method method do
    JSON.parse(poll(command: TpLinkSmartplug::Command.const_get(method.upcase)))
  end
end

#infoHash

Return plug information

Returns:

  • (Hash)


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/tp_link_smartplug/device.rb', line 182

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :timezone,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy,
  :energygains,
  :ledon,
  :ledoff,
].each do |method|
  define_method method do
    JSON.parse(poll(command: TpLinkSmartplug::Command.const_get(method.upcase)))
  end
end

#ledoffHash

Enable plug night mode (LED off)

Returns:

  • (Hash)


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/tp_link_smartplug/device.rb', line 182

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :timezone,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy,
  :energygains,
  :ledon,
  :ledoff,
].each do |method|
  define_method method do
    JSON.parse(poll(command: TpLinkSmartplug::Command.const_get(method.upcase)))
  end
end

#ledonHash

Disable plug night mode (LED on)

Returns:

  • (Hash)


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/tp_link_smartplug/device.rb', line 182

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :timezone,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy,
  :energygains,
  :ledon,
  :ledoff,
].each do |method|
  define_method method do
    JSON.parse(poll(command: TpLinkSmartplug::Command.const_get(method.upcase)))
  end
end

#offHash

Turn plug output off

Returns:

  • (Hash)


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/tp_link_smartplug/device.rb', line 182

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :timezone,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy,
  :energygains,
  :ledon,
  :ledoff,
].each do |method|
  define_method method do
    JSON.parse(poll(command: TpLinkSmartplug::Command.const_get(method.upcase)))
  end
end

#onHash

Turn plug output on

Returns:

  • (Hash)


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/tp_link_smartplug/device.rb', line 182

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :timezone,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy,
  :energygains,
  :ledon,
  :ledoff,
].each do |method|
  define_method method do
    JSON.parse(poll(command: TpLinkSmartplug::Command.const_get(method.upcase)))
  end
end

#open?True, False

Return connection state open

Returns:

  • (True, False)


86
87
88
# File 'lib/tp_link_smartplug/device.rb', line 86

def open?
  !@socket.closed?
end

#poll(command:) ⇒ Hash

Polls plug with a command

Parameters:

  • command (String)

    the command to send to the plug

Returns:

  • (Hash)

    the output from the plug command

Raises:



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/tp_link_smartplug/device.rb', line 105

def poll(command:)
  connect if closed?

  begin
    debug_message("Sending: #{decrypt(encrypt(command)[4..(command.length + 4)])}") if @debug
    @socket.write_nonblock(encrypt(command))
  rescue IO::WaitWritable
    @socket.wait_writable(@timeout)
    retry
  end

  begin
    data = @socket.recv_nonblock(2048)
  rescue IO::WaitReadable
    @socket.wait_readable(@timeout)
    retry
  end

  if @poll_auto_close && !closed?
    disconnect
    raise DeviceError, 'Error occured during disconnect' unless closed?
  end

  raise DeviceError, 'No data received' if nil_or_empty?(data)

  debug_message("Received Raw: #{data.split('\\')}") if @debug
  data = decrypt(data[4..data.length])
  debug_message("Received Decrypted: #{data}") if @debug

  data
end

#rebootHash

Reboot plug

Returns:

  • (Hash)


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/tp_link_smartplug/device.rb', line 182

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :timezone,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy,
  :energygains,
  :ledon,
  :ledoff,
].each do |method|
  define_method method do
    JSON.parse(poll(command: TpLinkSmartplug::Command.const_get(method.upcase)))
  end
end

#resetHash

Reset plug

Returns:

  • (Hash)


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/tp_link_smartplug/device.rb', line 182

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :timezone,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy,
  :energygains,
  :ledon,
  :ledoff,
].each do |method|
  define_method method do
    JSON.parse(poll(command: TpLinkSmartplug::Command.const_get(method.upcase)))
  end
end

#scheduleHash

Return schedule configured on the plug

Returns:

  • (Hash)


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/tp_link_smartplug/device.rb', line 182

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :timezone,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy,
  :energygains,
  :ledon,
  :ledoff,
].each do |method|
  define_method method do
    JSON.parse(poll(command: TpLinkSmartplug::Command.const_get(method.upcase)))
  end
end

#timeHash

Return system time from the plug

Returns:

  • (Hash)


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/tp_link_smartplug/device.rb', line 182

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :timezone,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy,
  :energygains,
  :ledon,
  :ledoff,
].each do |method|
  define_method method do
    JSON.parse(poll(command: TpLinkSmartplug::Command.const_get(method.upcase)))
  end
end

#timezoneHash

Return system timezone from the plug

Returns:

  • (Hash)


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/tp_link_smartplug/device.rb', line 182

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :timezone,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy,
  :energygains,
  :ledon,
  :ledoff,
].each do |method|
  define_method method do
    JSON.parse(poll(command: TpLinkSmartplug::Command.const_get(method.upcase)))
  end
end

#wlanscanHash

Perform a scan for wireless SSIDs

Returns:

  • (Hash)


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/tp_link_smartplug/device.rb', line 182

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :timezone,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy,
  :energygains,
  :ledon,
  :ledoff,
].each do |method|
  define_method method do
    JSON.parse(poll(command: TpLinkSmartplug::Command.const_get(method.upcase)))
  end
end