kasa 0.1.1 → 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/Gemfile +0 -8
- data/README.md +11 -1
- data/lib/kasa/devices.rb +10 -7
- data/lib/kasa/factory.rb +4 -2
- data/lib/kasa/protocol.rb +10 -2
- data/lib/kasa/version.rb +1 -1
- data/lib/kasa.rb +15 -0
- metadata +114 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8e186cc4152335207cb22e4a1ca609b90b4d975af35e4c7928b47b2ef28015af
|
4
|
+
data.tar.gz: 0a7a3cb147c216fc56dbb6f33ade5b5a017399a2e6b75410055d32951a2b1a28
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5652eb61fefad48dc3781fd35d4109d7c697cf31415958333889cf50d467e537458dbfd0c0473c7dbfe9d55c73d6224635385d2c8b5be8e87321e158d298360c
|
7
|
+
data.tar.gz: 01ba283907de37a317b7802d70a416bdcd2cae3d7fb1866e7f2f4269f6fed05beee4bb68c82bc6a4dd66786fec75aedc9d630ca1ebfe24bf56a84f980d9106d2
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -28,7 +28,9 @@ kasa.devices.first.on
|
|
28
28
|
|
29
29
|
Local network device is detected but can be optionally overridden:
|
30
30
|
```
|
31
|
-
|
31
|
+
require 'kasa'
|
32
|
+
|
33
|
+
kasa = Kasa.new(discover_interface_override: 'eth1')
|
32
34
|
```
|
33
35
|
|
34
36
|
To connect to known host and adjust brightness:
|
@@ -39,6 +41,14 @@ device = Kasa::Factory.new('192.168.1.55')
|
|
39
41
|
device.brightness=50
|
40
42
|
```
|
41
43
|
|
44
|
+
To get device summary:
|
45
|
+
```
|
46
|
+
require 'kasa'
|
47
|
+
|
48
|
+
kasa = Kasa.new
|
49
|
+
kasa.summary
|
50
|
+
```
|
51
|
+
|
42
52
|
## Development
|
43
53
|
|
44
54
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/kasa/devices.rb
CHANGED
@@ -6,12 +6,15 @@ class Kasa
|
|
6
6
|
ON = 1
|
7
7
|
OFF = 0
|
8
8
|
|
9
|
-
attr_reader :ip
|
9
|
+
attr_reader :ip, :alias, :model, :dev_name, :mac
|
10
10
|
|
11
11
|
# initialize
|
12
|
-
def initialize(ip)
|
12
|
+
def initialize(ip, args)
|
13
13
|
@ip = ip
|
14
|
-
@
|
14
|
+
@alias = args['alias']
|
15
|
+
@model = args['model']
|
16
|
+
@dev_name = args['dev_name']
|
17
|
+
@mac = args['mac']
|
15
18
|
end
|
16
19
|
|
17
20
|
# Get system information
|
@@ -70,8 +73,8 @@ class Kasa
|
|
70
73
|
def brightness=(level)
|
71
74
|
Kasa::Protocol.get(
|
72
75
|
@ip,
|
73
|
-
location: '/smartlife.iot.dimmer/set_brightness
|
74
|
-
value: level
|
76
|
+
location: '/smartlife.iot.dimmer/set_brightness',
|
77
|
+
value: { brightness: level }
|
75
78
|
)
|
76
79
|
end
|
77
80
|
end
|
@@ -80,9 +83,9 @@ class Kasa
|
|
80
83
|
class SmartStrip < NonDimmable
|
81
84
|
attr_accessor :children
|
82
85
|
|
83
|
-
def initialize(ip)
|
86
|
+
def initialize(ip, args)
|
84
87
|
super
|
85
|
-
@children =
|
88
|
+
@children = args['children'].map { |c| c['id'] }
|
86
89
|
end
|
87
90
|
|
88
91
|
# Turn on light
|
data/lib/kasa/factory.rb
CHANGED
@@ -11,6 +11,7 @@ class Kasa
|
|
11
11
|
NonDimmable => [
|
12
12
|
'HS200(US)',
|
13
13
|
'HS105(US)',
|
14
|
+
'HS103(US)',
|
14
15
|
'HS210(US)'
|
15
16
|
],
|
16
17
|
SmartStrip => [
|
@@ -24,13 +25,14 @@ class Kasa
|
|
24
25
|
class Factory
|
25
26
|
# Factory
|
26
27
|
def self.new(ip)
|
27
|
-
|
28
|
+
sysinfo = Kasa::Protocol.get(ip, location: '/system/get_sysinfo')
|
29
|
+
model = sysinfo['model']
|
28
30
|
begin
|
29
31
|
object = DEVICE_TYPES.detect { |_k, v| v.include? model }.first.allocate
|
30
32
|
rescue StandardError => _e
|
31
33
|
raise "#{model} not supported"
|
32
34
|
end
|
33
|
-
object.send :initialize, ip
|
35
|
+
object.send :initialize, ip, sysinfo
|
34
36
|
object
|
35
37
|
end
|
36
38
|
end
|
data/lib/kasa/protocol.rb
CHANGED
@@ -19,13 +19,21 @@ class Kasa
|
|
19
19
|
transport(ip, encode(request.to_json))
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
response = JSON.parse decode(encoded_response)
|
23
|
+
response = strip_location(location, response)
|
24
|
+
validate response
|
25
|
+
|
26
|
+
response
|
27
|
+
end
|
28
|
+
|
29
|
+
# examine error code
|
30
|
+
def self.validate(response)
|
31
|
+
raise response.to_json if response.is_a?(Hash) && response['err_code']&.negative?
|
23
32
|
end
|
24
33
|
|
25
34
|
# strip away the request location from the response
|
26
35
|
def self.strip_location(location, response)
|
27
36
|
location = location.split('/').reject(&:empty?)
|
28
|
-
response = JSON.parse response
|
29
37
|
location.each do |j|
|
30
38
|
response = (response[j] or response)
|
31
39
|
end
|
data/lib/kasa/version.rb
CHANGED
data/lib/kasa.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'timeout'
|
4
4
|
require 'base64'
|
5
5
|
require 'logger'
|
6
|
+
require 'terminal-table'
|
6
7
|
require_relative 'kasa/version'
|
7
8
|
require_relative 'kasa/factory'
|
8
9
|
|
@@ -33,6 +34,20 @@ class Kasa
|
|
33
34
|
@devices
|
34
35
|
end
|
35
36
|
|
37
|
+
# human readable devices summary
|
38
|
+
def summary
|
39
|
+
all_headings = @devices.first.instance_variables
|
40
|
+
common_headings = @devices.each_with_object(all_headings) do |d, memo|
|
41
|
+
memo & d.instance_variables
|
42
|
+
end
|
43
|
+
rows = devices.map do |d|
|
44
|
+
common_headings.map do |a|
|
45
|
+
d.instance_variable_get a
|
46
|
+
end
|
47
|
+
end
|
48
|
+
puts Terminal::Table.new headings: common_headings, rows: rows
|
49
|
+
end
|
50
|
+
|
36
51
|
private
|
37
52
|
|
38
53
|
# Return CIDR of first IPv4 interface or user-specified interface
|
metadata
CHANGED
@@ -1,15 +1,127 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kasa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christopher Jenkins
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-02-
|
11
|
+
date: 2022-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: timeout
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.1'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: base64
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.1'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: logger
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.4'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.4'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: terminal-table
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '13.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '13.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.21'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.21'
|
13
125
|
- !ruby/object:Gem::Dependency
|
14
126
|
name: rubocop-rspec
|
15
127
|
requirement: !ruby/object:Gem::Requirement
|