mqtt_api_client 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b088d9d3aeb35ebe2ccd4859de7b6ec9a662862ff4a3967f3b4024c6a1c19d7
4
- data.tar.gz: f0715c7f69236b628be8ea7b80ffd82e91810dedca081cbb13f1cc49b0a92c47
3
+ metadata.gz: a240564b318c55966a38d19bf82e3889f42913e95d6d0b55ca4029ef3e29a38e
4
+ data.tar.gz: a1882e0fb51e34be57b2cf9ae4daa6c2d80a09eb8a6a198cf3e384442132f043
5
5
  SHA512:
6
- metadata.gz: db1bde54e70d4dd57593f0c66b0a51be1a31bebc86d2fb3771898dd97302428d7c3a7a356bafb0e0767c331990c90f61c475f9a61ded3993dc474ed79c4b8c55
7
- data.tar.gz: fade692f1b10693adf0efd4e45a2e64c4684fae77496b089eeadefa6a5b00a4f1a75ef7d900823bc4b644d1b7163359e74befbb6f89eca5a5e3f5e50995297c0
6
+ metadata.gz: 828d9958263be605c6c1ad5f4a10b7aeeac4508e5131ef6bb6399113786e8f8fcf6ed0bb1bda7ecf4f3cffe9757cdc5880d602f10a46b35efec610115c774e2a
7
+ data.tar.gz: 2ae4cd4206a80f4740b562bb80535584c97dbece54c064da133a5b0660a8f07605a576e62a13e5ada794b5d31a053193616c1b5c3fc7422b828f9eab1d245bd9
@@ -0,0 +1,8 @@
1
+ DEVICE_IDENTIFIER=
2
+ MQTT_HOST=
3
+ MQTT_PORT=8883
4
+
5
+ DOTENV_LINEBREAK_MODE=legacy
6
+
7
+ MQTT_CERT="-----BEGIN CERTIFICATE-----\nxxxx\n-----END CERTIFICATE-----\n"
8
+ MQTT_KEY="-----BEGIN RSA PRIVATE KEY-----\nxxxx\n-----END RSA PRIVATE KEY-----\n"
data/.rubocop.yml ADDED
@@ -0,0 +1,71 @@
1
+ # The behavior of RuboCop can be controlled via the .rubocop.yml
2
+ # configuration file. It makes it possible to enable/disable
3
+ # certain cops (checks) and to alter their behavior if they accept
4
+ # any parameters. The file can be placed either in your home
5
+ # directory or in some project directory.
6
+ #
7
+ # RuboCop will start looking for the configuration file in the directory
8
+ # where the inspected file is and continue its way up to the root directory.
9
+ #
10
+ # See https://docs.rubocop.org/rubocop/configuration
11
+
12
+ require:
13
+ - rubocop-rake
14
+ - rubocop-rspec
15
+
16
+ AllCops:
17
+ TargetRubyVersion: 3.1
18
+ NewCops: enable
19
+
20
+ Gemspec/RequireMFA:
21
+ Enabled: false
22
+
23
+ Layout/CommentIndentation:
24
+ Enabled: false
25
+
26
+ Layout/LineLength:
27
+ Enabled: false
28
+
29
+ Metrics/MethodLength:
30
+ Enabled: false
31
+
32
+ Naming/MemoizedInstanceVariableName:
33
+ Enabled: false
34
+
35
+ RSpec/ExampleLength:
36
+ Enabled: false
37
+
38
+ RSpec/MessageSpies:
39
+ Enabled: false
40
+
41
+ RSpec/MultipleExpectations:
42
+ Enabled: false
43
+
44
+ RSpec/MultipleMemoizedHelpers:
45
+ Enabled: false
46
+
47
+ RSpec/ExpectInHook:
48
+ Enabled: false
49
+
50
+ Style/Documentation:
51
+ Enabled: false
52
+
53
+ Style/EmptyElse:
54
+ Exclude:
55
+ - lib/mqtt_api_client/command.rb
56
+
57
+ Style/GlobalVars:
58
+ Enabled: false
59
+
60
+ Style/Lambda:
61
+ Enabled: false
62
+
63
+ Style/SingleLineMethods:
64
+ Enabled: false
65
+
66
+ Style/StringLiterals:
67
+ Enabled: true
68
+ EnforcedStyle: double_quotes
69
+
70
+ Style/YodaCondition:
71
+ Enabled: false
data/README.md CHANGED
@@ -17,10 +17,33 @@ If bundler is not being used to manage dependencies, install the gem by executin
17
17
  ## Usage
18
18
 
19
19
  ```ruby
20
- command = MqttApiClient::Command.new(certificate, private_key, "localhost")
20
+ #
21
+ # connect to your MQTT broker (AWS IoT, Mosquitto, and so on..)
22
+ # @param [String], crt
23
+ # @param [String], key
24
+ # @param [String], host
25
+ mqtt_client = MQTT::Client.new.tap do |client|
26
+ # connection info
27
+ client.host = "my.host"
28
+ client.port = 8883
29
+ client.ssl = true
30
+
31
+ # certificates
32
+ client.cert = my_cert
33
+ client.key = my_private_key
34
+
35
+ client.connect
36
+ end
37
+
38
+ #
39
+ # @param [MQTT::Client], mqtt_client
40
+ # @param [String], device_identifier
41
+ command = MqttApiClient::Command.new(mqtt_client, "D0045F")
21
42
 
22
43
  command.health_status
23
44
  command.file_list
45
+
46
+ command.disconnect
24
47
  ```
25
48
 
26
49
  ## Development
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+ require "fileutils"
5
+ module MqttApiClient
6
+ class Device
7
+ TIMEOUT_SECONDS = 2
8
+
9
+ attr_reader :mqtt_client, :device_identifier, :logger
10
+
11
+ #
12
+ # @param mqtt_client [MQTT::Client]
13
+ # @param device_identifier [String]
14
+ def initialize(mqtt_client:, device_identifier:, logger: default_logger(device_identifier))
15
+ @mqtt_client = mqtt_client
16
+ @device_identifier = device_identifier
17
+ @logger = logger
18
+
19
+ logger&.info "Command logger initialized at #{Time.now}"
20
+
21
+ subscribe_to_all(
22
+ "device/#{device_identifier}/file_list",
23
+ "device/#{device_identifier}/health_status"
24
+ )
25
+ end
26
+
27
+ def file_list
28
+ mqtt_client.publish("device/#{device_identifier}/command", "file_list")
29
+
30
+ begin
31
+ process_get(
32
+ "device/#{device_identifier}/file_list",
33
+ "file_list"
34
+ )
35
+ rescue Timeout::Error => e
36
+ logger&.error "file_list timeout: #{e}"
37
+
38
+ Timeout::Error.new(e)
39
+ end
40
+ end
41
+
42
+ def health_status
43
+ mqtt_client.publish("device/#{device_identifier}/command", "health_status")
44
+
45
+ begin
46
+ process_get(
47
+ "device/#{device_identifier}/health_status",
48
+ "health_status"
49
+ )
50
+ rescue Timeout::Error => e
51
+ logger&.error "health_status timeout: #{e}"
52
+
53
+ Timeout::Error.new(e)
54
+ end
55
+ end
56
+
57
+ def disconnect
58
+ mqtt_client.disconnect
59
+ end
60
+
61
+ private
62
+
63
+ def process_get(subscribed_topic, logger_key)
64
+ @_process_get ||= Timeout.timeout(TIMEOUT_SECONDS) do
65
+ mqtt_client.get do |topic, message|
66
+ if topic == subscribed_topic
67
+ logger&.info "#{logger_key}: #{message}"
68
+
69
+ # do any logic with a message there, if you need to
70
+
71
+ return message
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ def default_logger(device_identifier)
78
+ FileUtils.mkdir_p("log")
79
+
80
+ Logger.new("log/device_#{device_identifier}.log", "daily")
81
+ end
82
+
83
+ #
84
+ # @param topics [Array<String]
85
+ def subscribe_to_all(*topics)
86
+ topics.each { |topic| mqtt_client.subscribe(topic) }
87
+ end
88
+ end
89
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MqttApiClient
4
- VERSION = "0.1.1"
4
+ VERSION = "0.2.1"
5
5
  end
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "amazing_print"
4
- require "dotenv/load"
5
3
  require "mqtt"
6
- require_relative "mqtt_api_client/command"
4
+ require_relative "mqtt_api_client/device"
7
5
  require_relative "mqtt_api_client/version"
8
6
 
9
7
  module MqttApiClient
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mqtt_api_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladyslav Sumskyi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-05-22 00:00:00.000000000 Z
11
+ date: 2024-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mqtt
@@ -31,8 +31,9 @@ executables: []
31
31
  extensions: []
32
32
  extra_rdoc_files: []
33
33
  files:
34
- - ".env.example"
34
+ - ".env.local.example"
35
35
  - ".rspec"
36
+ - ".rubocop.yml"
36
37
  - CHANGELOG.md
37
38
  - CODE_OF_CONDUCT.md
38
39
  - LICENSE.txt
@@ -40,7 +41,7 @@ files:
40
41
  - Rakefile
41
42
  - bitbucket-pipelines.yml
42
43
  - lib/mqtt_api_client.rb
43
- - lib/mqtt_api_client/command.rb
44
+ - lib/mqtt_api_client/device.rb
44
45
  - lib/mqtt_api_client/version.rb
45
46
  homepage: https://bitbucket.org/macklabsinc/mqtt_api_client/src/master/
46
47
  licenses:
@@ -66,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
67
  - !ruby/object:Gem::Version
67
68
  version: '0'
68
69
  requirements: []
69
- rubygems_version: 3.4.10
70
+ rubygems_version: 3.4.19
70
71
  signing_key:
71
72
  specification_version: 4
72
73
  summary: MQTT API Client
data/.env.example DELETED
@@ -1,4 +0,0 @@
1
- AWS_CERTIFICATE=
2
- AWS_PRIVATE_KEY=
3
- LOCAL_CERTIFICATE=
4
- LOCAL_PRIVATE_KEY=
@@ -1,95 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "logger"
4
-
5
- module MqttApiClient
6
- # commands implemented
7
- class Command
8
- attr_reader :mqtt_client, :crt, :key, :host, :logger
9
-
10
- #
11
- # @param [File|String], crt
12
- # @param [File|String], key
13
- def initialize(crt, key, host)
14
- @crt = if File.file? crt
15
- File.read crt
16
- else
17
- crt
18
- end
19
- @key = if File.file? key
20
- File.read key
21
- else
22
- key
23
- end
24
-
25
- @host = host
26
-
27
- @logger = Logger.new("log/command.log", "daily")
28
- @logger.info "Command logger initialized at #{Time.now}"
29
-
30
- connect
31
- end
32
-
33
- # rubocop:disable Style/EmptyElse
34
- def file_list(device_identifier)
35
- subscribed_topic = "device/#{device_identifier}/file_list"
36
-
37
- mqtt_client.subscribe(subscribed_topic)
38
- mqtt_client.publish("device/#{device_identifier}/command", "file_list")
39
-
40
- mqtt_client.get do |topic, message|
41
- mqtt_client.unsubscribe(subscribed_topic) if topic == subscribed_topic
42
-
43
- if topic == subscribed_topic
44
- logger.info "New file_list: #{message}"
45
-
46
- # do some logic with a message, probably update device file_list in the DB ?
47
-
48
- return message
49
- else
50
- # I don't want to raise exception here because we are
51
- # getting messages from the whole mqtt queue, one by one,
52
- # and the next message could be that what we need
53
- end
54
- end
55
- end
56
-
57
- def health_status(device_identifier)
58
- subscribed_topic = "device/#{device_identifier}/health_status"
59
- mqtt_client.subscribe(subscribed_topic)
60
-
61
- mqtt_client.publish("device/#{device_identifier}/command", "health_status")
62
-
63
- mqtt_client.get do |topic, message|
64
- mqtt_client.unsubscribe(subscribed_topic) if topic == subscribed_topic
65
-
66
- if topic == subscribed_topic
67
- logger.info "New health_status: #{message}"
68
-
69
- # do some logic with a message, probably update device health_status in the DB ?
70
-
71
- return message
72
- else
73
- # I don't want to raise exception here because we are
74
- # getting messages from the whole mqtt queue, one by one,
75
- # and the next message could be that what we need
76
- end
77
- # rubocop:enable Style/EmptyElse
78
- end
79
- end
80
-
81
- private
82
-
83
- def connect
84
- @mqtt_client = MQTT::Client.new
85
- @mqtt_client.host = host
86
- @mqtt_client.port = 8883
87
- @mqtt_client.ssl = true
88
-
89
- @mqtt_client.cert = crt
90
- @mqtt_client.key = key
91
-
92
- @mqtt_client.connect
93
- end
94
- end
95
- end