cosmosc2-kasa-plug 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 146ebc6050d7cfa29d272af27814cae1eb3de6ce1e4da13cb70703eca05ad0c4
4
+ data.tar.gz: a2e9f4ab507e3eb05e0b4b16621efd62b1b264fc597854c61643568d1648cf8c
5
+ SHA512:
6
+ metadata.gz: 9bad9abc5595c0aabf88c00d8af47c4c3636d36f2257377ec5f379979cf9827e10453b2b538418777a844d35f199c87b73f46fb3966623dd69465a3c0ddd14a3
7
+ data.tar.gz: 49336d1f6079d2ea368aa7a9088533bb9adc41d11476bb14d84256421aa644aa7511ae78a0453e09bf3bf24732cda71f7826a6a70927b53cf38f0b92ed865bf7
data/LICENSE.txt ADDED
@@ -0,0 +1,9 @@
1
+ The MIT License
2
+
3
+ Copyright 2021 Ryan Melton
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,24 @@
1
+ ## COSMOS v5 Kasa Plug Plugin
2
+
3
+ This plugin provides an Interface and Target for connecting to Kasa / TP-Link Smart Home Wifi Plugs
4
+
5
+ ## Getting Started
6
+
7
+ 1. Plug in your Kasa Plug and connect it to your Wifi network using the Kasa App
8
+
9
+ 2. Determine the IP Address of Your Kasa Plug using Your Home Router (or other methods)
10
+
11
+ 3. Install the plugin .gem file to the COSMOS Admin Page and Enter the IP Address
12
+
13
+ ## Contributing
14
+
15
+ Contributing is easy.
16
+
17
+ 1. Fork the project
18
+ 2. Create a feature branch
19
+ 3. Make your changes
20
+ 4. Submit a pull request
21
+
22
+ ## License
23
+
24
+ The MIT License - See LICENSE.txt
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ # encoding: ascii-8bit
2
+
3
+ # Copyright 2021 Ball Aerospace & Technologies Corp.
4
+ # All Rights Reserved.
5
+ #
6
+ # This program is free software; you can modify and/or redistribute it
7
+ # under the terms of the GNU Affero General Public License
8
+ # as published by the Free Software Foundation; version 3 with
9
+ # attribution addendums as found in the LICENSE.txt
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # This program may also be used under the terms of a commercial or
17
+ # enterprise edition license of COSMOS if purchased from the
18
+ # copyright holder
19
+
20
+ PLUGIN_NAME = Dir['*.gemspec'][0].split('.')[0..-2].join('.')
21
+
22
+ task :warn_version do
23
+ unless ENV['VERSION']
24
+ puts "Warning: VERSION is required for releases: rake <task> VERSION=X.X.X"
25
+ end
26
+ end
27
+
28
+ task :build => [:warn_version] do
29
+ _, platform, *_ = RUBY_PLATFORM.split("-")
30
+ if platform == 'mswin32' or platform == 'mingw32'
31
+ puts "Warning: Building gem on Windows will lose file permissions"
32
+ end
33
+ system("gem build #{PLUGIN_NAME}")
34
+ end
data/plugin.txt ADDED
@@ -0,0 +1,9 @@
1
+ VARIABLE target_name PLUG
2
+ VARIABLE int_name PLUG_INT
3
+ VARIABLE ip 192.168.1.0
4
+ VARIABLE port 9999
5
+
6
+ TARGET PLUG <%= target_name %>
7
+
8
+ INTERFACE <%= int_name %> kasa_interface.rb <%= ip %> <%= port %>
9
+ MAP_TARGET <%= target_name %>
@@ -0,0 +1,16 @@
1
+ COMMAND <%= target_name %> INFO BIG_ENDIAN "Gets the telemetry from the plug"
2
+ DISABLE_MESSAGES
3
+ APPEND_ID_PARAMETER DATA 0 STRING '{"system":{"get_sysinfo":{}}}' "Info Command to Plug"
4
+
5
+ COMMAND <%= target_name %> ON BIG_ENDIAN "Turns the plug on"
6
+ APPEND_ID_PARAMETER DATA 0 STRING '{"system":{"set_relay_state":{"state":1}}}' "On Command to Plug"
7
+
8
+ COMMAND <%= target_name %> OFF BIG_ENDIAN "Turns the plug off"
9
+ APPEND_ID_PARAMETER DATA 0 STRING '{"system":{"set_relay_state":{"state":0}}}' "Off Command to Plug"
10
+
11
+ COMMAND <%= target_name %> LED_ON BIG_ENDIAN "Turns the plugs led on"
12
+ APPEND_ID_PARAMETER DATA 0 STRING '{"system":{"set_led_off":{"off":0}}}' "Info Command to Plug"
13
+
14
+ COMMAND <%= target_name %> LED_OFF BIG_ENDIAN "Turns the plugs led off"
15
+ APPEND_ID_PARAMETER DATA 0 STRING '{"system":{"set_led_off":{"off":1}}}' "Info Command to Plug"
16
+
@@ -0,0 +1,11 @@
1
+ TELEMETRY <%= target_name %> STATUS BIG_ENDIAN "Status of the Plug"
2
+ APPEND_ID_ITEM PACKET_ID 8 UINT 1 "Packet Id"
3
+ APPEND_ITEM RELAY 8 UINT "Relay State"
4
+ STATE ON 1
5
+ STATE OFF 0
6
+ APPEND_ITEM LED 8 UINT "LED State"
7
+ STATE ON 1
8
+ STATE OFF 0
9
+
10
+ TELEMETRY <%= target_name %> RESPONSE BIG_ENDIAN "Response from the Plug"
11
+ APPEND_ITEM DATA 0 STRING "Response data"
@@ -0,0 +1,127 @@
1
+ # encoding: ascii-8bit
2
+
3
+ require 'cosmos'
4
+ require 'cosmos/interfaces/tcpip_client_interface'
5
+ require 'json'
6
+ require_relative 'kasa_protocol'
7
+
8
+ module Cosmos
9
+ class KasaInterface < TcpipClientInterface
10
+ def initialize (hostname, port, polling_period_seconds = 30, write_timeout = 10.0, read_timeout = nil)
11
+ super(hostname, port, port, write_timeout, read_timeout, 'LENGTH', 0, 32, 4)
12
+ add_protocol(KasaProtocol, [], :READ_WRITE)
13
+ @status_packet = nil
14
+ @polling_period_seconds = polling_period_seconds.to_i
15
+ @polling_thread = nil
16
+ @polling_thread_run = true
17
+ @polling_thread_sleeper = nil
18
+ end
19
+
20
+ def connect
21
+ super()
22
+
23
+ if @polling_period_seconds > 0
24
+ @polling_thread_run = true
25
+ @polling_thread_sleeper = Sleeper.new
26
+ @polling_thread = Thread.new do
27
+ while @polling_thread_run
28
+ send_info_command()
29
+ break if @polling_thread_sleeper.sleep(@polling_period_seconds)
30
+ end
31
+ rescue => err
32
+ Logger.instance.error("Polling thread unexpectedly died : #{@name}")
33
+ raise err
34
+ end
35
+ end
36
+ end
37
+
38
+ def disconnect
39
+ if @polling_thread
40
+ @polling_thread_run = false
41
+ @polling_thread_sleeper.cancel
42
+ @polling_thread.join
43
+ @polling_thread = nil
44
+ @polling_thread_sleeper = nil
45
+ end
46
+ super()
47
+ end
48
+
49
+ def write(packet)
50
+ result = super(packet)
51
+ # Follow every non-INFO command with an INFO command
52
+ send_info_command() if packet.packet_name != 'INFO'
53
+ return result
54
+ end
55
+
56
+ def read
57
+ if @status_packet
58
+ packet = @status_packet
59
+ @status_packet = nil
60
+ return packet
61
+ end
62
+ packet = super()
63
+
64
+ # Info Command Results Format
65
+ # {
66
+ # "system":
67
+ # {
68
+ # "get_sysinfo":
69
+ # {
70
+ # "sw_ver":"1.0.3 Build 201015 Rel.142523",
71
+ # "hw_ver":"5.0","model":"HS103(US)",
72
+ # "deviceId":"8006E861C909AAF4BABED171339873F91E67E71C",
73
+ # "oemId":"211C91F3C6FA93568D818524FE170CEC",
74
+ # "hwId":"B25CBC5351DD892EA69AB42199F59E41",
75
+ # "rssi":-51,
76
+ # "latitude_i":400299,
77
+ # "longitude_i":-1050636,
78
+ # "alias":"Plug1",
79
+ # "status":"new",
80
+ # "mic_type":"IOT.SMARTPLUGSWITCH",
81
+ # "feature":"TIM",
82
+ # "mac":"00:31:92:43:F4:35",
83
+ # "updating":0,
84
+ # "led_off":1,
85
+ # "relay_state":0,
86
+ # "on_time":0,
87
+ # "icon_hash":"",
88
+ # "dev_name":"Smart Wi-Fi Plug Mini",
89
+ # "active_mode":"none",
90
+ # "next_action":{"type":-1},
91
+ # "err_code":0
92
+ # }
93
+ # }
94
+ # }
95
+
96
+ if packet
97
+ json_hash = JSON.parse(packet.buffer(false))
98
+ system = json_hash['system']
99
+ if system
100
+ get_sysinfo = system['get_sysinfo']
101
+ if get_sysinfo
102
+ @status_packet = System.telemetry.packet(@target_names[0], 'STATUS')
103
+ @status_packet.write('PACKET_ID', 1)
104
+ relay = get_sysinfo['relay_state']
105
+ @status_packet.write('RELAY', relay)
106
+ led_off = get_sysinfo['led_off']
107
+ if led_off == 0
108
+ led = 1
109
+ else
110
+ led = 0
111
+ end
112
+ @status_packet.write('LED', led)
113
+ @status_packet.received_time = nil
114
+ end
115
+ end
116
+ end
117
+
118
+ return packet
119
+ end
120
+
121
+ def send_info_command
122
+ info_command = System.commands.packet(@target_names[0], 'INFO').dup
123
+ info_command.restore_defaults
124
+ write(info_command)
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,43 @@
1
+ # encoding: ascii-8bit
2
+
3
+ require 'cosmos/interfaces/protocols/protocol'
4
+
5
+ module Cosmos
6
+
7
+ # Performs the TPLink SmartHome Protocol
8
+ class KasaProtocol < Protocol
9
+
10
+ def read_data(data)
11
+ return super(data) if data.length <= 0
12
+ return kasa_decode(data)
13
+ end
14
+
15
+ def write_data(data)
16
+ return kasa_encode(data)
17
+ end
18
+
19
+ def kasa_encode(string)
20
+ key = 171
21
+ result = [string.length].pack("N")
22
+ string.each_byte do |byte|
23
+ a = key ^ byte
24
+ key = a
25
+ result << a
26
+ end
27
+ return result
28
+ end
29
+
30
+ def kasa_decode(string)
31
+ key = 171
32
+ result = ""
33
+ string[4..-1].each_byte do |byte|
34
+ a = key ^ byte
35
+ key = byte
36
+ result << [a].pack("C")
37
+ end
38
+ return result
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,5 @@
1
+ SCREEN AUTO AUTO 1
2
+
3
+ TITLE "<%= target_name %> STATUS"
4
+ LABELVALUE <%= target_name %> STATUS RELAY
5
+ LABELVALUE <%= target_name %> STATUS LED
@@ -0,0 +1,5 @@
1
+ REQUIRE kasa_interface.rb
2
+
3
+ # Ignored Parameters
4
+ # IGNORE_PARAMETER parameter_name
5
+ IGNORE_PARAMETER DATA
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cosmosc2-kasa-plug
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Melton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-11-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cosmos
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: " This plugin an Interface and Target to Connect COSMOS to a Kasa
28
+ Smart Plug\n"
29
+ email:
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - LICENSE.txt
35
+ - README.md
36
+ - Rakefile
37
+ - plugin.txt
38
+ - targets/PLUG/cmd_tlm/plug_cmds.txt
39
+ - targets/PLUG/cmd_tlm/plug_tlm.txt
40
+ - targets/PLUG/lib/kasa_interface.rb
41
+ - targets/PLUG/lib/kasa_protocol.rb
42
+ - targets/PLUG/screens/status.txt
43
+ - targets/PLUG/target.txt
44
+ homepage: https://github.com/ryanmelt/cosmosc2-kasa-plug
45
+ licenses:
46
+ - MIT
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubygems_version: 3.1.6
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: COSMOS Plugin to Connect to Kasa Smart Plugs
67
+ test_files: []