mqttopia 0.1.9 → 0.1.18
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/.rubocop.yml +2 -0
- data/MQTT_SUBSCRIPTIONS.md +80 -43
- data/lib/mqttopia/client.rb +27 -9
- data/lib/mqttopia/serializers/test_debug.rb +5 -1
- data/lib/mqttopia/serializers/trip_metric.rb +73 -37
- data/lib/mqttopia/subscriptions/services/trip_metrics.rb +1 -0
- data/lib/mqttopia/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 22fd456b89816f0c1a408aa91ce87314f871501013eab946a19a48d7c3ddbffd
|
4
|
+
data.tar.gz: 1880d0c512433ddb69fa7fced3f1c191355346a2e66a5dd4c2e23be4d91d7497
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f575cbc7790b82d2e675a9fd9358dc6fe80cdbb7152375e04f742b4f9a1703f710ecb40fb79040a38684fb161e5f4d437473a25b326e77342caf21cccfe8fa1
|
7
|
+
data.tar.gz: ee39f5c542c8c399295d4802ab4c17334d3ea513d010c844bc7014061de550c58dc542f6e2c0ce9bef9a95aa94d93313cec2a88f7b14834dcc7c491dae91dd79
|
data/.rubocop.yml
CHANGED
data/MQTT_SUBSCRIPTIONS.md
CHANGED
@@ -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
|
-
"
|
15
|
-
"
|
16
|
-
|
17
|
-
"
|
18
|
-
"
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
"
|
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
|
-
|
46
|
-
|
47
|
-
power_saving_mode:
|
46
|
+
charging_status: "UNKNOWN",
|
47
|
+
optimization_status: false,
|
48
|
+
power_saving_mode: false
|
48
49
|
},
|
49
|
-
notification_permission:
|
50
|
-
gps:
|
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
|
-
"
|
80
|
-
"
|
81
|
-
|
82
|
-
"
|
83
|
-
"
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
"
|
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)
|
data/lib/mqttopia/client.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
102
|
+
|
103
|
+
if debugging && topic.exclude?(debugging_topic)
|
104
|
+
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:
|
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:
|
12
|
-
logged_at: body
|
13
|
-
received_at:
|
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
|
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
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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(
|
41
|
-
|
42
|
-
|
43
|
-
"
|
44
|
-
|
45
|
-
"
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
"
|
54
|
-
|
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
|
data/lib/mqttopia/version.rb
CHANGED
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.
|
4
|
+
version: 0.1.18
|
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-
|
11
|
+
date: 2024-11-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|