mqttopia 0.1.9 → 0.1.20

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: 6dcdb52227984d43667ef297e1740a96329a28931140f2c2760a6446cf5ee31a
4
- data.tar.gz: 8d1ba1e116657ae18027c2686599476b859600de42fec69c1e938f23a6c89f05
3
+ metadata.gz: 79c7db296f5f4dfd2db80af02eddd1d43798b0e18175aab756b150adbe38bcca
4
+ data.tar.gz: 189124b048379437624b76a850d97bf4d3ae23c8eed6fcca427cf1fc0275c969
5
5
  SHA512:
6
- metadata.gz: b8ae4365a041299e9e4e4e2e43c75cdb4ca5cf8406fc451e0e95a47ccc834ccf21998c76f909c8bb924922588b0eaecedaaa7689ba9ad8881b3d8d3fa0ff6823
7
- data.tar.gz: 2bd8bef90f21419e6fdf594eb4c81ad920bb11eac3bbfd74c081280b9d0e866bb32802cda0b90f0b71804521127195af9e6b0e0ca36035093c917e6fd6b7fef6
6
+ metadata.gz: 6644b34775b0a900bcd5527f5a918e7ab09a331ad747d31505f74a28df843e4edac8b3ff06240b36645cbf4a528b47d1690e7f2167a4863bc425c991fb9606d9
7
+ data.tar.gz: c5778d6141e09c7aaf6e95b6a86dc66c62091db9f9566b07f9224e3f610b9da76f945724ef9ef54f01fa1cf7834ecb389741e8190be276eba9e20b25ec571995
data/.rubocop.yml CHANGED
@@ -37,3 +37,5 @@ Lint/MissingSuper:
37
37
  Enabled: false
38
38
  Lint/RescueException:
39
39
  Enabled: false
40
+ Style/RedundantFetchBlock:
41
+ Enabled: false
@@ -11,24 +11,25 @@ This subscription handles trip metrics and serializes the data related to trips,
11
11
  ### **Payload Structure:**
12
12
  ```json
13
13
  {
14
- "trip_id": 123,
15
- "metrics": {
16
- "locPerms": 0,
17
- "connt": "wf",
18
- "batt": { "l": 100, "cs": "charging" },
19
- "battPwOp": 0,
20
- "pws": 0,
21
- "notf": 1,
22
- "gps": 1,
23
- "nlog": 500,
24
- "loc": {
25
- "lat": 29.9585182,
26
- "lon": 31.0423193,
27
- "acc": 20,
28
- "alt": 150.5,
29
- "ts": 1729074275127 // unix timestamp
30
- },
31
- "ts": 1729074279737 // unix timestamp
14
+ "tid": "101",
15
+ "ts": 1729504252695,
16
+ "batt": {
17
+ "l": 100,
18
+ "cs": "2"
19
+ },
20
+ "connt": "wf",
21
+ "pws": -1,
22
+ "gps": -1,
23
+ "nlog": 585,
24
+ "battPwOp": -1,
25
+ "locPerms": 0,
26
+ "notf": -1,
27
+ "loc": {
28
+ "lat": 29.97577349165706,
29
+ "lon": 31.097835359438037,
30
+ "acc": 3.6214938163757324,
31
+ "alt": 0,
32
+ "ts": 1729504252310
32
33
  }
33
34
  }
34
35
  ```
@@ -42,12 +43,12 @@ This subscription handles trip metrics and serializes the data related to trips,
42
43
  connection_type: "wf",
43
44
  battery: {
44
45
  battery_level: 100,
45
- charging_statuc: "charging",
46
- opmization_status: 0,
47
- power_saving_mode: 0
46
+ charging_status: "UNKNOWN",
47
+ optimization_status: false,
48
+ power_saving_mode: false
48
49
  },
49
- notification_permission: 1,
50
- gps: 1,
50
+ notification_permission: false,
51
+ gps: false,
51
52
  location: {
52
53
  latitude: 29.9585182,
53
54
  longitude: 31.0423193,
@@ -63,10 +64,45 @@ This subscription handles trip metrics and serializes the data related to trips,
63
64
 
64
65
  ---
65
66
 
66
- ### **Date Types:**
67
+ ### **Date Types and mapping:**
67
68
 
68
69
  - To decode a unix timestamp use the following link [epoch_converter](https://www.epochconverter.com/)
69
-
70
+ - **optimization_status**, **power_saving_mode**, **notification_permission**
71
+ ```json
72
+ {
73
+ "0": true,
74
+ "-1": false
75
+ }
76
+ ```
77
+ - **location_permission**
78
+ ```json
79
+ {
80
+ "0": "BACKGROUND_FINE",
81
+ "-1": "BACKGROUND_COARSE",
82
+ "-2": "FOREGROUND_FINE",
83
+ "-3": "FOREGROUND_COARSE",
84
+ "-4": "DISABLED"
85
+ }
86
+ ```
87
+ - **connection_type**
88
+ ```json
89
+ {
90
+ "wf": "WIFI",
91
+ "cel": "CELLULAR",
92
+ "et": "ETHERNET",
93
+ "nc": "NO_CONNECTION",
94
+ "uk": "UNKNOWN"
95
+ }
96
+ ```
97
+ - **charging_status**
98
+ ```json
99
+ {
100
+ "0": "UNKNOWN",
101
+ "1": "DISCHARGING",
102
+ "2": "CHARGING",
103
+ "3": "FULL"
104
+ }
105
+ ```
70
106
  ---
71
107
 
72
108
  ### **Usage Example:**
@@ -76,24 +112,25 @@ $client.subscribe('illa/trips/20/trip_metric/send/user/20') do |response|
76
112
  end
77
113
 
78
114
  payload = {
79
- "trip_id": 123,
80
- "metrics": {
81
- "locPerms": 0,
82
- "connt": "wf",
83
- "batt": { "l": 100, "cs": "charging" },
84
- "battPwOp": 0,
85
- "pws": 0,
86
- "notf": 1,
87
- "gps": 1,
88
- "nlog": 500,
89
- "loc": {
90
- "lat": 29.9585182,
91
- "lon": 31.0423193,
92
- "acc": 20,
93
- "alt": 150.5,
94
- "ts": 1729074275127
95
- },
96
- "ts": 1729074279737
115
+ "tid": "101",
116
+ "ts": 1729504252695,
117
+ "batt": {
118
+ "l": 100,
119
+ "cs": "2"
120
+ },
121
+ "connt": "wf",
122
+ "pws": -1,
123
+ "gps": -1,
124
+ "nlog": 585,
125
+ "battPwOp": -1,
126
+ "locPerms": 0,
127
+ "notf": -1,
128
+ "loc": {
129
+ "lat": 29.97577349165706,
130
+ "lon": 31.097835359438037,
131
+ "acc": 3.6214938163757324,
132
+ "alt": 0,
133
+ "ts": 1729504252310
97
134
  }
98
135
  }
99
136
  $client.publish('illa/trips/20/trip_metric/send/user/20', payload)
@@ -8,7 +8,7 @@ require_relative "subscriptions/redirect"
8
8
  module Mqttopia
9
9
  class Client
10
10
  @instance = nil
11
- attr_reader :mqtt_client, :debugging
11
+ attr_reader :mqtt_client, :debugging, :debugging_topic
12
12
 
13
13
  def self.instance
14
14
  @instance ||= new
@@ -31,6 +31,7 @@ module Mqttopia
31
31
  ack_timeout: 5
32
32
  )
33
33
  @debugging = Mqttopia.debugging
34
+ @debugging_topic = "mqttopia/test/debugging"
34
35
  rescue Exception => e
35
36
  log_error("initialize", e)
36
37
  end
@@ -45,18 +46,24 @@ module Mqttopia
45
46
  disconnect_and_log("connect", e)
46
47
  end
47
48
 
48
- def publish(topic, message = nil, qos = 0)
49
- return unless ensure_connection
49
+ def self.publish(topic, message = nil, qos = 0)
50
+ client = new
51
+ client.connect
50
52
 
51
53
  # publish(topic, payload = '', retain = false, qos = 0)
52
- mqtt_client.publish(topic, message, false, qos)
53
- log_debug("Sent message on topic #{topic}: #{message} with QOS #{qos}")
54
+ client.mqtt_client.publish(topic, message, false, qos)
55
+ client.disconnect
56
+
57
+ Mqttopia::Logger.debug("\n#{message}\n") if client.debugging
58
+ true
54
59
  rescue Exception => e
55
- disconnect_and_log("publish", e)
60
+ Mqttopia::Logger.error("\nMqttopia::Client -> publish: #{e}\n")
61
+ false
56
62
  end
57
63
 
58
64
  def subscribe(topic, qos = 0, &block)
59
65
  return unless ensure_connection
66
+ raise StandardError, "Blocked Topic" if [debugging_topic].include?(topic)
60
67
 
61
68
  mqtt_client.subscribe(topic => qos)
62
69
  create_subscription_thread(qos, &block)
@@ -68,6 +75,10 @@ module Mqttopia
68
75
  mqtt_client.disconnect if connected?
69
76
  end
70
77
 
78
+ def ready_to_connect?
79
+ !active_host.nil?
80
+ end
81
+
71
82
  private
72
83
 
73
84
  def active_host(hosts = Mqttopia.hosts, port = Mqttopia.port, timeout = 10)
@@ -82,13 +93,20 @@ module Mqttopia
82
93
  nil # Return nil if no reachable host is found
83
94
  end
84
95
 
85
- def create_subscription_thread(qos, &block)
96
+ def create_subscription_thread(qos)
86
97
  Thread.new do
87
98
  mqtt_client.get do |topic, message|
88
99
  log_debug("Received RAW message on topic #{topic}: #{message} with QOS #{qos}")
89
100
 
90
101
  response = safe_mqtt_response(topic, message)
91
- block.call(response) if response
102
+
103
+ if debugging && topic.exclude?(debugging_topic)
104
+ Mqttopia::Client.publish(debugging_topic,
105
+ { 'topic_name': topic,
106
+ 'mqttopia_response': response }, 2)
107
+ end
108
+
109
+ yield response if response
92
110
  end
93
111
  end
94
112
  end
@@ -99,7 +117,7 @@ module Mqttopia
99
117
  payload: parse_json(raw_payload)
100
118
  ).call
101
119
  rescue Exception => e
102
- log_error("safe_mqtt_response", e)
120
+ log_error("safe_mqtt_response", e) if debugging
103
121
  nil
104
122
  end
105
123
 
@@ -9,9 +9,13 @@ module Mqttopia
9
9
  {
10
10
  topic_name: body[:topic_name],
11
11
  payload: body[:payload],
12
- received_at: DateTime.now.strftime("%Q")&.to_s
12
+ received_at: current_timestamp
13
13
  }
14
14
  end
15
+
16
+ def current_timestamp
17
+ DateTime.now.strftime("%Q")
18
+ end
15
19
  end
16
20
  end
17
21
  end
@@ -5,53 +5,89 @@ module Mqttopia
5
5
  module TripMetric
6
6
  module_function
7
7
 
8
+ KEYS = %i[ts locPerms connt batt battPwOp pws notf gps nlog loc].freeze
9
+
8
10
  def serialize(body)
11
+ return unless valid_metric?(body[:metrics])
12
+
9
13
  {
10
14
  trip_id: body[:trip_id],
11
- metrics: body[:metrics] && metric_serialize(body[:metrics]),
12
- logged_at: body[:metrics] && body[:metrics][:ts]&.to_s,
13
- received_at: DateTime.now.strftime("%Q")&.to_s
15
+ metrics: serialize_metrics(body[:metrics]),
16
+ logged_at: body.dig(:metrics, :ts)&.to_s,
17
+ received_at: current_timestamp
18
+ }
19
+ end
20
+
21
+ def serialize_metrics(metrics)
22
+ {
23
+ location_permission: location_permission_mapper(metrics[:locPerms]),
24
+ connection_type: connection_type_mapper(metrics[:connt]),
25
+ battery: serialize_battery(metrics[:batt], metrics[:battPwOp], metrics[:pws]),
26
+ notification_permission: metrics[:notf]&.zero?,
27
+ gps: metrics[:gps]&.zero?,
28
+ number_of_trip_logs: metrics[:nlog],
29
+ location: serialize_location(metrics[:loc])
14
30
  }
15
31
  end
16
32
 
17
- def metric_serialize(metric)
33
+ def serialize_battery(battery, optimization_status, power_saving_mode)
34
+ return unless battery
35
+
36
+ {
37
+ battery_level: battery[:l],
38
+ charging_status: charging_status_mapper(battery[:cs]),
39
+ optimization_status: optimization_status&.zero?,
40
+ power_saving_mode: power_saving_mode&.zero?
41
+ }
42
+ end
43
+
44
+ def serialize_location(location)
45
+ return unless location
46
+
18
47
  {
19
- location_permission: location_permission_mapper(metric[:locPerms]),
20
- connection_type: metric[:connt],
21
- battery: {
22
- battery_level: metric[:batt] && metric[:batt][:l],
23
- charging_statuc: metric[:batt] && metric[:batt][:cs],
24
- opmization_status: metric[:battPwOp],
25
- power_saving_mode: metric[:pws]
26
- },
27
- notification_permission: metric[:notf],
28
- gps: metric[:gps],
29
- number_of_trip_logs: metric[:nlog],
30
- location: metric[:loc] && {
31
- latitude: metric[:loc][:lat],
32
- longitude: metric[:loc][:lon],
33
- accuracy: metric[:loc][:acc],
34
- altitude: metric[:loc][:alt],
35
- logged_at: metric[:loc][:ts]&.to_s
36
- }
48
+ latitude: location[:lat],
49
+ longitude: location[:lon],
50
+ accuracy: location[:acc],
51
+ altitude: location[:alt],
52
+ logged_at: location[:ts]&.to_s
37
53
  }
38
54
  end
39
55
 
40
- def location_permission_mapper(location_permission)
41
- case location_permission
42
- when 0
43
- "BACKGROUND_FINE"
44
- when -1
45
- "BACKGROUND_COARSE"
46
- when -2
47
- "FOREGROUND_FINE"
48
- when -3
49
- "FOREGROUND_COARSE"
50
- when -4
51
- "DISABLED"
52
- else
53
- "UNKNOWN"
54
- end
56
+ def location_permission_mapper(permission)
57
+ {
58
+ "0" => "BACKGROUND_FINE",
59
+ "-1" => "BACKGROUND_COARSE",
60
+ "-2" => "FOREGROUND_FINE",
61
+ "-3" => "FOREGROUND_COARSE",
62
+ "-4" => "DISABLED"
63
+ }.fetch(permission&.to_s) { "UNKNOWN" }
64
+ end
65
+
66
+ def connection_type_mapper(connection_type)
67
+ {
68
+ "wf" => "WIFI",
69
+ "cel" => "CELLULAR",
70
+ "et" => "ETHERNET",
71
+ "nc" => "NO_CONNECTION",
72
+ "uk" => "UNKNOWN"
73
+ }.fetch(connection_type) { "UNKNOWN" }
74
+ end
75
+
76
+ def charging_status_mapper(charging_status)
77
+ {
78
+ "0" => "UNKNOWN",
79
+ "1" => "DISCHARGING",
80
+ "2" => "CHARGING",
81
+ "3" => "FULL"
82
+ }.fetch(charging_status&.to_s) { "UNKNOWN" }
83
+ end
84
+
85
+ def valid_metric?(metrics)
86
+ metrics.is_a?(Hash) && KEYS.all? { |key| metrics.key?(key) }
87
+ end
88
+
89
+ def current_timestamp
90
+ DateTime.now.strftime("%Q")
55
91
  end
56
92
  end
57
93
  end
@@ -16,6 +16,7 @@ module Mqttopia
16
16
 
17
17
  validates :trip_id, presence: true, numericality: { only_integer: true, greater_than: 0 }
18
18
  validates :metrics, presence: true
19
+ # validate :metric_json_format
19
20
 
20
21
  def initialize(trip_id:, metrics:, options: {})
21
22
  @trip_id = trip_id
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mqttopia
4
- VERSION = "0.1.9"
4
+ VERSION = "0.1.20"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mqttopia
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.1.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Illa Tech
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-10-24 00:00:00.000000000 Z
11
+ date: 2025-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel