ewelink 3.3.2 → 4.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0fba630fc8ea0be922637f79d4618baccf676775fc37e35ffbd9847e479930f4
4
- data.tar.gz: 8e03090c2c1f9e469b25a9b3ff4dc21da74fd150c6432196038c464cca1608bb
3
+ metadata.gz: b8e686b44abcc1c59621d612a64b930f89a0041ac4607070bd47c801f04148ac
4
+ data.tar.gz: 3990a53b5d57e0c0523ba83050e7af904dd54a96337692a5fc800e6e3d0edaa9
5
5
  SHA512:
6
- metadata.gz: 854c5679733f93e5a54c3085858315874db86319b0d81898a64f807d6780f146cfe1f0767ce5b6e4c9ed576adcab59b3154a35399a2cae77a2d4bcac338e8d58
7
- data.tar.gz: 328c7a4e3c10ca31d1b4d636c97c12e6a8af6358401aac77fea2739a0300cac162fa85ee1028dcf5097e42989a5d3035d39f8abf832030b3eabf0037dd43f244
6
+ metadata.gz: 41aaa80ba63866bf04728c60489ed91b3b8294a61dc7e7d78779628b7530006bd41d306adb4e6a72ccdb1e72ed8322dd94efe897053ed02ce1da977e7560319a
7
+ data.tar.gz: c6af766c67c28efffd27a4186c3b603e9c4d3ab48e5fb8bc8ca1b52b5ce7aec8969297b932134c3c640ca5ece581ab70c6932ffb8a5597ebb54cc831b9bbfb98
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.3.2
1
+ 4.0.0
data/bin/ewelink CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative '../lib/ewelink'
4
4
 
5
- Ewelink.logger = Logger.new(STDOUT, formatter: -> (severity, time, progname, message) {
5
+ Ewelink.logger = Logger.new($stdout, formatter: lambda { |_severity, _time, progname, message|
6
6
  text = ''
7
7
  text << "[#{progname}] " if progname.present?
8
8
  text << message.to_s << "\n"
data/ewelink.gemspec CHANGED
@@ -9,17 +9,19 @@ Gem::Specification.new do |s|
9
9
  s.description = 'Manage eWeLink smart home devices'
10
10
  s.license = 'MIT'
11
11
 
12
- s.files = `git ls-files | grep -vE '^(spec/|test/|\\.|Gemfile|Rakefile)'`.split("\n")
13
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ s.files = %x(git ls-files | grep -vE '^(spec/|test/|\\.|Gemfile|Rakefile)').split("\n")
13
+ s.executables = %x(git ls-files -- bin/*).split("\n").map { |f| File.basename(f) }
14
14
  s.require_paths = ['lib']
15
15
 
16
- s.required_ruby_version = '>= 2.0.0'
16
+ s.required_ruby_version = '>= 3.1.0'
17
17
 
18
- s.add_dependency 'activesupport', '>= 6.0.0', '< 7.0.0'
18
+ s.add_dependency 'activesupport', '>= 7.0.0', '< 8.0.0'
19
19
  s.add_dependency 'faye-websocket', '>= 0.11.0', '< 0.12.0'
20
- s.add_dependency 'httparty', '>= 0.18.0', '< 0.19.0'
20
+ s.add_dependency 'httparty', '>= 0.20.0', '< 0.21.0'
21
21
  s.add_dependency 'thread', '>= 0.2.0', '< 0.3.0'
22
22
 
23
23
  s.add_development_dependency 'byebug', '>= 11.0.0', '< 12.0.0'
24
24
  s.add_development_dependency 'rake', '>= 13.0.0', '< 14.0.0'
25
+ s.add_development_dependency 'rubocop', '>= 1.25.0', '< 2.0.0'
26
+ s.add_development_dependency 'rubocop-rake', '>= 0.6.0', '< 1.0.0'
25
27
  end
data/lib/ewelink/api.rb CHANGED
@@ -2,14 +2,13 @@ module Ewelink
2
2
 
3
3
  class Api
4
4
 
5
- APP_ID = 'oeVkj2lYFGnJu5XUtWisfW4utiN4u9Mq'
6
- APP_SECRET = '6Nz4n0xA8s8qdxQf2GqurZj2Fs55FUvM'
7
- DEFAULT_REGION = 'us'
5
+ APP_ID = 'oeVkj2lYFGnJu5XUtWisfW4utiN4u9Mq'.freeze
6
+ APP_SECRET = '6Nz4n0xA8s8qdxQf2GqurZj2Fs55FUvM'.freeze
7
+ DEFAULT_REGION = 'us'.freeze
8
8
  REQUEST_TIMEOUT = 10.seconds
9
9
  RF_BRIDGE_DEVICE_UIID = 28
10
- SWITCH_DEVICES_UIIDS = [1, 5, 6, 24]
11
- URL = 'https://#{region}-api.coolkit.cc:8080'
12
- UUID_NAMESPACE = 'e25750fb-3710-41af-b831-23224f4dd609';
10
+ SWITCH_DEVICES_UIIDS = [1, 5, 6, 24].freeze
11
+ URL = 'https://#{region}-api.coolkit.cc:8080'.freeze
13
12
  VERSION = 8
14
13
  WEB_SOCKET_CHECK_AUTHENTICATION_TIMEOUT = 30.seconds
15
14
  WEB_SOCKET_PING_TOLERANCE_FACTOR = 1.5
@@ -18,11 +17,11 @@ module Ewelink
18
17
 
19
18
  attr_reader :email, :password, :phone_number
20
19
 
21
- def initialize(async_actions: false, email: nil, password:, phone_number: nil, update_devices_status_on_connect: false)
20
+ def initialize(password:, async_actions: false, email: nil, phone_number: nil, update_devices_status_on_connect: false)
22
21
  @async_actions = async_actions.present?
23
22
  @email = email.presence.try(:strip)
24
23
  @mutexs = {}
25
- @password = password.presence || raise(Error.new(":password must be specified"))
24
+ @password = password.presence || raise(Error.new(':password must be specified'))
26
25
  @phone_number = phone_number.presence.try(:strip)
27
26
  @update_devices_status_on_connect = update_devices_status_on_connect.present?
28
27
  @web_socket_authenticated = false
@@ -85,19 +84,19 @@ module Ewelink
85
84
  end
86
85
  end
87
86
 
88
- [
89
- :@authentication_infos,
90
- :@devices,
91
- :@last_web_socket_pong_at,
92
- :@region,
93
- :@rf_bridge_buttons,
94
- :@switches,
95
- :@web_socket_ping_interval,
96
- :@web_socket_ping_thread,
97
- :@web_socket_thread,
98
- :@web_socket_url,
99
- :@web_socket,
100
- ].each do |variable|
87
+ %i(
88
+ @authentication_infos
89
+ @devices
90
+ @last_web_socket_pong_at
91
+ @region
92
+ @rf_bridge_buttons
93
+ @switches
94
+ @web_socket_ping_interval
95
+ @web_socket_ping_thread
96
+ @web_socket_thread
97
+ @web_socket_url
98
+ @web_socket
99
+ ).each do |variable|
101
100
  remove_instance_variable(variable) if instance_variable_defined?(variable)
102
101
  end
103
102
  self
@@ -115,10 +114,10 @@ module Ewelink
115
114
  device_name = device['name'].presence || next
116
115
  buttons = device['params']['rfList'].each do |rf|
117
116
  button = {
118
- api_key: api_key,
117
+ api_key:,
119
118
  channel: rf['rfChl'],
120
- device_id: device_id,
121
- device_name: device_name,
119
+ device_id:,
120
+ device_name:,
122
121
  }
123
122
  remote_info = device['tags']['zyx_info'].find { |info| info['buttonName'].find { |data| data.key?(button[:channel].to_s) } }.presence || next
124
123
  remote_name = remote_info['name'].try(:squish).presence || next
@@ -126,10 +125,10 @@ module Ewelink
126
125
  button_name = button_info.values.first.try(:squish).presence || next
127
126
  button.merge!({
128
127
  name: button_name,
129
- remote_name: remote_name,
128
+ remote_name:,
130
129
  remote_type: remote_info['remote_type'],
131
130
  })
132
- button[:uuid] = Digest::UUID.uuid_v5(UUID_NAMESPACE, "#{button[:device_id]}/#{button[:channel]}")
131
+ button[:uuid] = Digest::UUID.uuid_v5(Digest::UUID::DNS_NAMESPACE, "#{button[:device_id]}/#{button[:channel]}")
133
132
  buttons << button
134
133
  end
135
134
  end
@@ -167,11 +166,11 @@ module Ewelink
167
166
  device_id = device['deviceid'].presence || next
168
167
  name = device['name'].presence || next
169
168
  switch = {
170
- api_key: api_key,
171
- device_id: device_id,
172
- name: name,
169
+ api_key:,
170
+ device_id:,
171
+ name:,
173
172
  }
174
- switch[:uuid] = Digest::UUID.uuid_v5(UUID_NAMESPACE, switch[:device_id])
173
+ switch[:uuid] = Digest::UUID.uuid_v5(Digest::UUID::DNS_NAMESPACE, switch[:device_id])
175
174
  switches << switch
176
175
  end
177
176
  end.tap { |switches| Ewelink.logger.debug(self.class.name) { "Found #{switches.size} switch(es)" } }
@@ -255,7 +254,7 @@ module Ewelink
255
254
  params['phoneNumber'] = phone_number
256
255
  end
257
256
  body = JSON.generate(params)
258
- response = rest_request(:post, '/api/user/login', { body: body, headers: { 'Authorization' => "Sign #{Base64.encode64(OpenSSL::HMAC.digest('SHA256', APP_SECRET, body))}" } })
257
+ response = rest_request(:post, '/api/user/login', { body:, headers: { 'Authorization' => "Sign #{Base64.encode64(OpenSSL::HMAC.digest('SHA256', APP_SECRET, body))}" } })
259
258
  raise(Error.new('Authentication token not found')) if response['at'].blank?
260
259
  raise(Error.new('API key not found')) if response['user'].blank? || response['user']['apikey'].blank?
261
260
  {
@@ -314,7 +313,7 @@ module Ewelink
314
313
  method = method.to_s.upcase
315
314
  headers = (options[:headers] || {}).reverse_merge('Content-Type' => 'application/json')
316
315
  Ewelink.logger.debug(self.class.name) { "#{method} #{url}" }
317
- response = HTTParty.send(method.downcase, url, options.merge(headers: headers).reverse_merge(timeout: REQUEST_TIMEOUT))
316
+ response = HTTParty.send(method.downcase, url, options.merge(headers:).reverse_merge(timeout: REQUEST_TIMEOUT))
318
317
  raise(Error.new("#{method} #{url}: #{response.code}")) unless response.success?
319
318
  if response['error'] == 301 && response['region'].present?
320
319
  @region = response['region']
@@ -391,12 +390,12 @@ module Ewelink
391
390
  EventMachine.run do
392
391
  @web_socket = Faye::WebSocket::Client.new(web_socket_url)
393
392
 
394
- @web_socket.on(:close) do |event|
393
+ @web_socket.on(:close) do
395
394
  Ewelink.logger.debug(self.class.name) { 'WebSocket closed' }
396
395
  reload
397
396
  end
398
397
 
399
- @web_socket.on(:open) do |event|
398
+ @web_socket.on(:open) do
400
399
  Ewelink.logger.debug(self.class.name) { 'WebSocket opened' }
401
400
  @last_web_socket_pong_at = Time.now
402
401
  authenticate_web_socket_api_key
@@ -413,7 +412,7 @@ module Ewelink
413
412
 
414
413
  begin
415
414
  json = JSON.parse(message)
416
- rescue => e
415
+ rescue
417
416
  Ewelink.logger.error(self.class.name) { 'WebSocket JSON parse error' }
418
417
  reload
419
418
  next
@@ -436,7 +435,7 @@ module Ewelink
436
435
  end
437
436
 
438
437
  if json['deviceid'].present? && json['params'].is_a?(Hash) && json['params']['switch'].present?
439
- switch = switches.find { |switch| switch[:device_id] == json['deviceid'] }
438
+ switch = switches.find { |item| item[:device_id] == json['deviceid'] }
440
439
  if switch.present?
441
440
  @web_socket_switches_statuses[switch[:uuid]] = json['params']['switch']
442
441
  Ewelink.logger.debug(self.class.name) { "Switch #{switch[:uuid].inspect} is #{@web_socket_switches_statuses[switch[:uuid]]}" }
@@ -483,13 +482,11 @@ module Ewelink
483
482
  end
484
483
  end
485
484
 
486
- def web_socket_wait_for(condition, initialize_web_socket: false, &block)
485
+ def web_socket_wait_for(condition, initialize_web_socket: false)
487
486
  web_socket if initialize_web_socket
488
487
  begin
489
488
  Timeout.timeout(REQUEST_TIMEOUT) do
490
- while !condition.call
491
- sleep(WEB_SOCKET_WAIT_INTERVAL)
492
- end
489
+ sleep(WEB_SOCKET_WAIT_INTERVAL) until condition.call
493
490
  block_given? ? yield : true
494
491
  end
495
492
  rescue => e
@@ -9,7 +9,7 @@ module Ewelink
9
9
  options[:turn_switches_on_uuids].each { |uuid| api.turn_switch!(uuid, :on) }
10
10
  options[:turn_switches_off_uuids].each { |uuid| api.turn_switch!(uuid, :off) }
11
11
  options[:press_rf_bridge_buttons_uuids].each { |uuid| api.press_rf_bridge_button!(uuid) }
12
- puts(JSON.pretty_generate(options[:switch_status_uuids].map { |uuid| [uuid, api.switch_on?(uuid) ? 'on' : 'off'] }.to_h)) if options[:switch_status_uuids].present?
12
+ puts(JSON.pretty_generate(options[:switch_status_uuids].to_h { |uuid| [uuid, api.switch_on?(uuid) ? 'on' : 'off'] })) if options[:switch_status_uuids].present?
13
13
  end
14
14
 
15
15
  private
@@ -56,23 +56,21 @@ module Ewelink
56
56
  end
57
57
  arguments = parser.parse!
58
58
  if arguments.any?
59
- STDERR.puts("Invalid option specified: #{arguments.first}")
60
- STDERR.puts(parser.summarize)
59
+ warn("Invalid option specified: #{arguments.first}")
60
+ warn(parser.summarize)
61
61
  exit(1)
62
62
  end
63
63
  if options[:email].blank? && options[:phone_number].blank?
64
- STDERR.puts('Email or phone number must be specified')
65
- STDERR.puts(parser.summarize)
64
+ warn('Email or phone number must be specified')
65
+ warn(parser.summarize)
66
66
  exit(1)
67
67
  end
68
- if [:list_switches, :list_rf_bridge_buttons, :turn_switches_on_uuids, :turn_switches_off_uuids, :press_rf_bridge_buttons_uuids, :switch_status_uuids].map { |action| options[action] }.all?(&:blank?)
69
- STDERR.puts('An action must be specified (listing switches, press RF bridge button, etc.)')
70
- STDERR.puts(parser.summarize)
68
+ if %i(list_switches list_rf_bridge_buttons turn_switches_on_uuids turn_switches_off_uuids press_rf_bridge_buttons_uuids switch_status_uuids).map { |action| options[action] }.all?(&:blank?)
69
+ warn('An action must be specified (listing switches, press RF bridge button, etc.)')
70
+ warn(parser.summarize)
71
71
  exit(1)
72
72
  end
73
- while options[:password].blank?
74
- options[:password] = IO::console.getpass("Enter eWeLink account's password: ")
75
- end
73
+ options[:password] = IO.console.getpass("Enter eWeLink account's password: ") while options[:password].blank?
76
74
  options
77
75
  end
78
76
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ewelink
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.2
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexis Toulotte
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-26 00:00:00.000000000 Z
11
+ date: 2022-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,20 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 6.0.0
19
+ version: 7.0.0
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: 7.0.0
22
+ version: 8.0.0
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: 6.0.0
29
+ version: 7.0.0
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: 7.0.0
32
+ version: 8.0.0
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: faye-websocket
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -56,20 +56,20 @@ dependencies:
56
56
  requirements:
57
57
  - - ">="
58
58
  - !ruby/object:Gem::Version
59
- version: 0.18.0
59
+ version: 0.20.0
60
60
  - - "<"
61
61
  - !ruby/object:Gem::Version
62
- version: 0.19.0
62
+ version: 0.21.0
63
63
  type: :runtime
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - ">="
68
68
  - !ruby/object:Gem::Version
69
- version: 0.18.0
69
+ version: 0.20.0
70
70
  - - "<"
71
71
  - !ruby/object:Gem::Version
72
- version: 0.19.0
72
+ version: 0.21.0
73
73
  - !ruby/object:Gem::Dependency
74
74
  name: thread
75
75
  requirement: !ruby/object:Gem::Requirement
@@ -130,6 +130,46 @@ dependencies:
130
130
  - - "<"
131
131
  - !ruby/object:Gem::Version
132
132
  version: 14.0.0
133
+ - !ruby/object:Gem::Dependency
134
+ name: rubocop
135
+ requirement: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: 1.25.0
140
+ - - "<"
141
+ - !ruby/object:Gem::Version
142
+ version: 2.0.0
143
+ type: :development
144
+ prerelease: false
145
+ version_requirements: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: 1.25.0
150
+ - - "<"
151
+ - !ruby/object:Gem::Version
152
+ version: 2.0.0
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubocop-rake
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: 0.6.0
160
+ - - "<"
161
+ - !ruby/object:Gem::Version
162
+ version: 1.0.0
163
+ type: :development
164
+ prerelease: false
165
+ version_requirements: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - ">="
168
+ - !ruby/object:Gem::Version
169
+ version: 0.6.0
170
+ - - "<"
171
+ - !ruby/object:Gem::Version
172
+ version: 1.0.0
133
173
  description: Manage eWeLink smart home devices
134
174
  email: al@alweb.org
135
175
  executables:
@@ -157,14 +197,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
157
197
  requirements:
158
198
  - - ">="
159
199
  - !ruby/object:Gem::Version
160
- version: 2.0.0
200
+ version: 3.1.0
161
201
  required_rubygems_version: !ruby/object:Gem::Requirement
162
202
  requirements:
163
203
  - - ">="
164
204
  - !ruby/object:Gem::Version
165
205
  version: '0'
166
206
  requirements: []
167
- rubygems_version: 3.2.15
207
+ rubygems_version: 3.3.3
168
208
  signing_key:
169
209
  specification_version: 4
170
210
  summary: Manage eWeLink devices