Class: TpLinkSmartplug::Device

Inherits:
Object
  • 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

Constructor Details

#initialize(address:, port: 9999) ⇒ Device

Returns a new instance of Device.



27
28
29
30
31
32
33
34
35
# File 'lib/tp_link_smartplug/device.rb', line 27

def initialize(address:, port: 9999)
  @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 = true
end

Instance Attribute Details

#addressIPAddr

IP address of the plug

Returns:

  • (IPAddr)

    the current value of address



17
18
19
# File 'lib/tp_link_smartplug/device.rb', line 17

def address
  @address
end

#debugtrue, false

Control debug logging

Returns:

  • (true, false)

    the current value of debug



17
18
19
# File 'lib/tp_link_smartplug/device.rb', line 17

def debug
  @debug
end

#poll_auto_closeObject

Returns the value of attribute poll_auto_close.



24
25
26
# File 'lib/tp_link_smartplug/device.rb', line 24

def poll_auto_close
  @poll_auto_close
end

#portInteger

Port to connect to on the plug

Returns:

  • (Integer)

    the current value of port



17
18
19
# File 'lib/tp_link_smartplug/device.rb', line 17

def port
  @port
end

#timeoutInteger

Timeout value for connecting and sending commands to the plug

Returns:

  • (Integer)

    the current value of timeout



17
18
19
# File 'lib/tp_link_smartplug/device.rb', line 17

def timeout
  @timeout
end

Instance Method Details

#antitheftHash

Unsure

Returns:

  • (Hash)


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/tp_link_smartplug/device.rb', line 161

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy
].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)


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

def closed?
  @socket.closed?
end

#cloudinfoHash

Return plug cloud account configuration

Returns:

  • (Hash)


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/tp_link_smartplug/device.rb', line 161

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

#connectObject

Open connection to plug



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
# File 'lib/tp_link_smartplug/device.rb', line 39

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)
  rescue IO::WaitWritable
    if IO.select(nil, [@socket], nil, timeout)
      begin
        @socket.connect_nonblock(@sockaddr)
      rescue Errno::EISCONN
        debug_message('Connected') if debug
      rescue StandardError => e
        disconnect
        debug_message('Unexpected exception encountered.') if debug
        raise e
      end
    else
      @socket.close
      raise "Connection timeout connecting to address #{@address}, port #{@port}."
    end
  rescue Errno::EISCONN
    debug_message('Connected') if debug
  end
end

#countdownHash

Return countdown configured on the plug

Returns:

  • (Hash)


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/tp_link_smartplug/device.rb', line 161

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy
].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



69
70
71
# File 'lib/tp_link_smartplug/device.rb', line 69

def disconnect
  @socket.close unless @socket.closed?
end

#energyHash

Return plug energy data

Returns:

  • (Hash)


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/tp_link_smartplug/device.rb', line 161

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy
].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)


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/tp_link_smartplug/device.rb', line 161

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy
].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)


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/tp_link_smartplug/device.rb', line 161

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy
].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)


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/tp_link_smartplug/device.rb', line 161

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy
].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)


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

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



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/tp_link_smartplug/device.rb', line 93

def poll(command:)
  connect

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

  begin
    data = @socket.recv_nonblock(2048)
  rescue IO::WaitReadable
    IO.select([@socket])
    retry
  end

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

  raise 'No data received' if data.nil? || data.empty?

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

  data
end

#rebootHash

Reboot plug

Returns:

  • (Hash)


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/tp_link_smartplug/device.rb', line 161

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

#resryHash

Reset plug

Returns:

  • (Hash)


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/tp_link_smartplug/device.rb', line 161

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy
].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)


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/tp_link_smartplug/device.rb', line 161

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy
].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)


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/tp_link_smartplug/device.rb', line 161

[
  :info,
  :on,
  :off,
  :cloudinfo,
  :wlanscan,
  :time,
  :schedule,
  :countdown,
  :antitheft,
  :reboot,
  :reset,
  :energy
].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)


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/tp_link_smartplug/device.rb', line 161

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