dji_mqtt_connect 0.1.22.2 → 0.1.23.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.
@@ -4,231 +4,11 @@ module DjiMqttConnect
4
4
  # Factories for building example messages
5
5
  # Do not include this in your production code
6
6
  module Factories
7
- # Events
7
+ autoload :EventsMessages, "dji_mqtt_connect/factories/events_messages"
8
+ autoload :StateMessages, "dji_mqtt_connect/factories/state_messages"
8
9
 
9
- def build_device_exit_homing_notify_events_message
10
- message_data = {
11
- action: 1,
12
- sn: "DOCK01",
13
- reason: "0"
14
- }
15
- Thing::Product::DeviceExitHomingNotifyEventsMessage.new(
16
- _method: "device_exit_homing_notify",
17
- bid: Message.generate_bid,
18
- tid: Message.generate_tid,
19
- need_reply: 1,
20
- gateway: "GATEWAY01",
21
- timestamp: Message.current_timestamp,
22
- data: message_data,
23
- _data: message_data
24
- )
25
- end
26
-
27
- def build_thing_product_device_reboot_events_message
28
- message_data = {
29
- result: 0,
30
- output: {
31
- status: "ok",
32
- progress: {
33
- percent: 100
34
- }
35
- }
36
- }
37
-
38
- Thing::Product::DeviceRebootEventsMessage.new(
39
- bid: Message.generate_bid,
40
- tid: Message.generate_tid,
41
- timestamp: Message.current_timestamp,
42
- _method: "device_reboot",
43
- need_reply: 1,
44
- data: message_data,
45
- _data: message_data
46
- )
47
- end
48
-
49
- def build_file_upload_callback_events_message
50
- message_data = {
51
- file: {
52
- object_key: "object_key",
53
- path: "xxx",
54
- name: "dog.jpeg",
55
- ext: {
56
- flight_id: "xxx",
57
- drone_model_key: "0-67-0",
58
- payload_model_key: "0-67-0",
59
- is_original: true
60
- },
61
- metadata: {
62
- shoot_position: {
63
- lat: 22.1,
64
- lng: 122.5
65
- },
66
- gimbal_yaw_degree: -91.4,
67
- absolute_altitude: 56.311,
68
- relative_altitude: 41.124,
69
- created_time: "2021-05-10 16:04:20"
70
- }
71
- },
72
- result: 0
73
- }
74
-
75
- Thing::Product::FileUploadCallbackEventsMessage.new(
76
- _method: "file_upload_callback",
77
- bid: Message.generate_bid,
78
- tid: Message.generate_tid,
79
- need_reply: 1,
80
- gateway: "xxx",
81
- timestamp: Message.current_timestamp,
82
- data: message_data,
83
- _data: message_data
84
- )
85
- end
86
-
87
- def build_fileupload_progress_events_message
88
- message_data = {
89
- output: {
90
- ext: {
91
- files: [
92
- {
93
- module: "0",
94
- size: 155232,
95
- device_sn: "drone_sn",
96
- key: "4bf0039f-6434-44a8-b891-8d7b6b7ff138/drone_sn/video_20220621_110830.log",
97
- fingerprint: "4f65b891f3bc09bdb6d4c36a996b532d",
98
- progress: {
99
- current_step: 19,
100
- progress: 100,
101
- finish_time: 1655781395926,
102
- upload_rate: 0,
103
- result: 0,
104
- status: "ok"
105
- }
106
- },
107
- {
108
- module: "3",
109
- size: 155232,
110
- device_sn: "dock_sn",
111
- key: "4bf0039f-6434-44a8-b891-8d7b6b7ff138/dock_sn/video_20220621_110830.log",
112
- fingerprint: "4f65b891f3bc09bdb6d4c36a996b532d",
113
- progress: {
114
- current_step: 19,
115
- total_step: 30,
116
- progress: 100,
117
- finish_time: 1655781395926,
118
- upload_rate: 0,
119
- result: 0,
120
- status: "ok"
121
- }
122
- }
123
- ]
124
- },
125
- status: "ok"
126
- }
127
- }
128
-
129
- Thing::Product::FileuploadProgressEventsMessage.new(
130
- _method: "fileupload_progress",
131
- need_reply: 0,
132
- bid: Message.generate_bid,
133
- tid: Message.generate_tid,
134
- timestamp: Message.current_timestamp,
135
- gateway: "dock_sn",
136
- _data: message_data,
137
- data: message_data
138
- )
139
- end
140
-
141
- def build_flighttask_progress_events_message
142
- message_data = {
143
- output: {
144
- ext: {
145
- current_waypoint_index: 3,
146
- media_count: 6,
147
- track_id: "track_id",
148
- flight_id: "flight_id",
149
- break_point: {
150
- index: 1,
151
- state: 0,
152
- progress: 0.34,
153
- wayline_id: 0,
154
- break_reason: 1,
155
- latitude: 23.4,
156
- longitude: 113.99,
157
- height: 100.23,
158
- attitude_head: 30
159
- }
160
- },
161
- progress: {
162
- current_step: 19,
163
- percent: 100
164
- },
165
- status: "ok"
166
- },
167
- result: 0
168
- }
169
-
170
- Thing::Product::FlighttaskProgressEventsMessage.new(
171
- bid: Message.generate_bid,
172
- tid: Message.generate_tid,
173
- data: message_data,
174
- _data: message_data,
175
- _method: "flighttask_progress",
176
- timestamp: Message.current_timestamp
177
- )
178
- end
179
-
180
- def build_flighttask_ready_events_message
181
- message_data = {
182
- flight_ids: [
183
- SecureRandom.uuid,
184
- SecureRandom.uuid
185
- ]
186
- }
187
-
188
- Thing::Product::FlighttaskReadyEventsMessage.new(
189
- bid: Message.generate_bid,
190
- tid: Message.generate_tid,
191
- data: message_data,
192
- _data: message_data,
193
- _method: "flighttask_ready",
194
- timestamp: Message.current_timestamp
195
- )
196
- end
197
-
198
- def build_highest_priority_upload_flighttask_media_events_message
199
- message_data = {
200
- flight_id: SecureRandom.uuid
201
- }
202
-
203
- Thing::Product::HighestPriorityUploadFlighttaskMediaEventsMessage.new(
204
- bid: Message.generate_bid,
205
- _data: message_data,
206
- data: message_data,
207
- _method: "highest_priority_upload_flighttask_media",
208
- need_reply: 1,
209
- tid: Message.generate_tid,
210
- timestamp: Message.current_timestamp,
211
- gateway: "DOCK01"
212
- )
213
- end
214
-
215
- def build_offline_map_sync_progress_events_message
216
- message_data = {
217
- status: "failed",
218
- reason: 0,
219
- file: "geofence_xxx.json"
220
- }
221
-
222
- Thing::Product::OfflineMapSyncProgressEventsMessage.new(
223
- bid: Message.generate_bid,
224
- tid: Message.generate_tid,
225
- timestamp: Message.current_timestamp,
226
- _method: "offline_map_sync_progress",
227
- need_reply: 1,
228
- data: message_data,
229
- _data: message_data
230
- )
231
- end
10
+ include EventsMessages
11
+ include StateMessages
232
12
 
233
13
  # OSD
234
14
 
@@ -1166,85 +946,5 @@ module DjiMqttConnect
1166
946
  data: message_data
1167
947
  )
1168
948
  end
1169
-
1170
- ### State Messages ###
1171
-
1172
- def build_thing_product_live_capacity_state_message
1173
- message_data = {
1174
- live_capacity: {
1175
- available_video_number: 3,
1176
- coexist_video_number_max: 2,
1177
- device_list: [
1178
- {
1179
- sn: "DOCK01",
1180
- available_video_number: 1,
1181
- coexist_video_number_max: 1,
1182
- camera_list: [
1183
- {
1184
- camera_index: "165-0-7",
1185
- available_video_number: 1,
1186
- coexist_video_number_max: 1,
1187
- video_list: [
1188
- {
1189
- video_index: "normal-0",
1190
- video_type: "normal",
1191
- switchable_video_types: [
1192
- "normal"
1193
- ]
1194
- }
1195
- ]
1196
- }
1197
- ]
1198
- },
1199
- {
1200
- sn: "DRONE01",
1201
- available_video_number: 2,
1202
- coexist_video_number_max: 2,
1203
- camera_list: [
1204
- {
1205
- camera_index: "39-0-7",
1206
- available_video_number: 1,
1207
- coexist_video_number_max: 1,
1208
- video_list: [
1209
- {
1210
- video_index: "normal-0",
1211
- video_type: "normal",
1212
- switchable_video_types: [
1213
- "normal"
1214
- ]
1215
- }
1216
- ]
1217
- },
1218
- {
1219
- camera_index: "52-0-0",
1220
- available_video_number: 1,
1221
- coexist_video_number_max: 1,
1222
- video_list: [
1223
- {
1224
- video_index: "normal-0",
1225
- video_type: "wide",
1226
- switchable_video_types: [
1227
- "wide",
1228
- "zoom",
1229
- "ir"
1230
- ]
1231
- }
1232
- ]
1233
- }
1234
- ]
1235
- }
1236
- ]
1237
- }
1238
- }
1239
-
1240
- Thing::Product::StateMessage.new(
1241
- bid: Message.generate_bid,
1242
- tid: Message.generate_tid,
1243
- timestamp: Message.current_timestamp,
1244
- gateway: "GATEWAY01",
1245
- _data: message_data,
1246
- data: message_data
1247
- )
1248
- end
1249
949
  end
1250
950
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry-transformer"
4
+ require "json"
5
+
6
+ module DjiMqttConnect
7
+ module Thing::Product
8
+ class StateReplyMarshal < MessageMarshal
9
+ # Renames the method attribute
10
+ class HashTransformer < Dry::Transformer::Pipe
11
+ import Dry::Transformer::HashTransformations
12
+
13
+ define! do
14
+ rename_keys _method: :method
15
+ end
16
+ end
17
+
18
+ # Converts a message for transmission via MQTT
19
+ def dump(message)
20
+ # Fix up the hash representation
21
+ transformed_message = hash_transformer.call(message)
22
+
23
+ # Convert the transformed message into JSON
24
+ JSON.generate(transformed_message)
25
+ end
26
+
27
+ private
28
+
29
+ def hash_transformer
30
+ @hash_transformer ||= HashTransformer.new
31
+ end
32
+ end
33
+ end
34
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module DjiMqttConnect
4
4
  module Thing::Product
5
- class DeviceLogEventsMessage < ServicesReplyMessage
5
+ class DeviceLogEventsMessage < EventsMessage
6
6
  # BID is not always included in message
7
7
  attribute? :bid, Types::UUID
8
8
 
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Thing::Product
5
+ class TakeoffToPointProgressEventsMessage < EventsMessage
6
+ attribute :_method, Types::String.enum("takeoff_to_point_progress")
7
+
8
+ attribute :data do
9
+ attribute :flight_id, Types::String
10
+ attribute :remaining_distance, Types::Integer
11
+ attribute :remaining_time, Types::Integer
12
+ attribute :result, Types::Integer
13
+ attribute :status, Types::String
14
+ attribute :track_id, Types::String | Types::Nil
15
+ attribute :way_point_index, Types::Integer
16
+ end
17
+ end
18
+ end
19
+ end
@@ -21,19 +21,7 @@ module DjiMqttConnect
21
21
  attribute :tid, Types::UUID
22
22
  attribute :timestamp, Types::Timestamp
23
23
 
24
- attribute :_method, Types::String.enum(
25
- "airsense_warning",
26
- "device_exit_homing_notify",
27
- "device_reboot",
28
- "file_upload_callback",
29
- "fileupload_progress",
30
- "flight_areas_drone_location",
31
- "flight_areas_sync_progress",
32
- "flighttask_progress",
33
- "flighttask_ready",
34
- "highest_priority_upload_flighttask_media",
35
- "offline_map_sync_progress"
36
- )
24
+ attribute :_method, Types::String
37
25
 
38
26
  attribute :data do
39
27
  include Mixins::ResultMessage
@@ -82,7 +82,18 @@ module DjiMqttConnect
82
82
 
83
83
  attribute :_data, Types::Hash
84
84
 
85
+ # NOTE: Included in some state messages, requires a reply on the state_reply topic if true
86
+ attribute? :need_reply, Types::Integer.enum(0, 1)
87
+
88
+ def need_reply?
89
+ need_reply == 1
90
+ end
91
+
85
92
  attribute :data do
93
+ attribute? :geo_caging_status do
94
+ attribute :state, Types::Integer
95
+ end
96
+
86
97
  # Not all messages will have a live_capacity attribute
87
98
  attribute? :live_capacity do
88
99
  attribute :available_video_number, Types::Integer
@@ -103,6 +114,65 @@ module DjiMqttConnect
103
114
  end
104
115
  end
105
116
  end
117
+
118
+ attribute? :live_status, Types::Array do
119
+ attribute :video_id, Types::String
120
+ attribute :video_type, Types::String
121
+ attribute :video_quality, Types::Integer
122
+ attribute :status, Types::Integer
123
+ attribute :error_status, Types::Integer
124
+ end
125
+
126
+ attribute? :payloads, Types::Array do
127
+ attribute :control_source, Types::String
128
+ attribute? :firmware_version, Types::String
129
+ attribute :payload_index, Types::String
130
+ attribute? :sn, Types::String
131
+ end
132
+
133
+ attribute? :rtcm_info do
134
+ attribute :host, Types::String
135
+ attribute :mount_point, Types::String
136
+ attribute :port, Types::String
137
+ attribute :rtcm_device_type, Types::Integer
138
+ attribute :source_type, Types::Integer
139
+ end
140
+
141
+ attribute? :wireless_link_topo do
142
+ attribute :center_node do
143
+ attribute :sdr_id, Types::Integer
144
+ attribute :sn, Types::String
145
+ end
146
+
147
+ attribute :leaf_nodes, Types::Array do
148
+ attribute :control_source_index, Types::Integer
149
+ attribute :sdr_id, Types::Integer
150
+ attribute :sn, Types::String
151
+ attribute :valid, Types::Bool
152
+ end
153
+
154
+ attribute :secret_code, Types::Array.of(Types::Integer)
155
+ end
156
+
157
+ attribute? :ar_info_switch, Types::Integer
158
+ attribute? :commander_flight_height, Types::Integer
159
+ attribute? :commander_flight_mode, Types::Integer
160
+ attribute? :commander_mode_lost_action, Types::Integer
161
+ attribute? :control_source, Types::String
162
+ attribute? :current_commander_flight_mode, Types::Integer
163
+ attribute? :current_rth_mode, Types::Integer
164
+ attribute? :flysafe_database_version, Types::String
165
+ attribute? :home_latitude, Types::Latitude
166
+ attribute? :home_longitude, Types::Longitude
167
+ attribute? :locked, Types::Bool
168
+ attribute? :mode_code_reason, Types::Integer
169
+ attribute? :offline_map_enable, Types::Bool
170
+ attribute? :rth_mode, Types::Integer
171
+ attribute? :uom_real_name_state, Types::Integer
172
+ attribute? :wpmz_version, Types::String
173
+
174
+ attribute? :low_battery_warning_threshold, Types::Integer
175
+ attribute? :serious_low_battery_warning_threshold, Types::Integer
106
176
  end
107
177
  end
108
178
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Thing::Product
5
+ class StateReplyMessage < Message
6
+ # a result of 0 means we approve of this action
7
+ def self.build_for(events_message, result: 0)
8
+ new(
9
+ tid: events_message.tid,
10
+ bid: events_message.bid,
11
+ timestamp: current_timestamp,
12
+ data: {
13
+ result: result
14
+ }
15
+ )
16
+ end
17
+
18
+ attribute :bid, Types::UUID
19
+ attribute :tid, Types::UUID
20
+ attribute :timestamp, Types::Timestamp
21
+
22
+ attribute :data do
23
+ include Mixins::ResultMessage
24
+
25
+ attribute :result, Types::ResultCode
26
+ end
27
+ end
28
+ end
29
+ end
@@ -25,6 +25,9 @@ module DjiMqttConnect
25
25
  event_name = message.class.name.demodulize.sub(/sMessage\z/, "").underscore.to_sym
26
26
  broadcast(event_name, device_sn, message)
27
27
  end
28
+
29
+ # Broadcast a generic received events message event
30
+ broadcast(:received_events_message, device_sn, message)
28
31
  rescue ParseError => error
29
32
  broadcast(:parse_error, error, topic, raw_message)
30
33
  end
@@ -3,7 +3,7 @@
3
3
  module DjiMqttConnect
4
4
  module Thing::Product
5
5
  class OsdTopicRepository < TopicRepository
6
- OSD_TOPIC_REGEX = /\Athing\/product\/(?<device_identifier>.+)\/osd\z/
6
+ OSD_TOPIC_REGEX = /\Athing\/product\/(?<device_sn>.+)\/osd\z/
7
7
 
8
8
  def listen!
9
9
  listen_to_topic("thing/product/+/osd") do |topic, raw_message|
@@ -12,10 +12,10 @@ module DjiMqttConnect
12
12
  matched_topic = OSD_TOPIC_REGEX.match(topic)
13
13
  raise Error, "Unknown topic: #{topic}" unless matched_topic
14
14
 
15
- device_identifier = matched_topic[:device_identifier]
15
+ device_sn = matched_topic[:device_sn]
16
16
  message = OsdMarshal.load(raw_message)
17
17
 
18
- logger.info("Received #{message} from #{device_identifier}")
18
+ logger.info("Received #{message} from #{device_sn}")
19
19
 
20
20
  if message.instance_of?(OsdMessage)
21
21
  # Broadcast an unsupported message event
@@ -23,8 +23,11 @@ module DjiMqttConnect
23
23
  else
24
24
  # Build event name and broadcast (i.e. ::RemoteOsdMessage => remote_osd_update)
25
25
  event_name = message.class.name.demodulize.sub(/Message\z/, "Update").underscore.to_sym
26
- broadcast(event_name, device_identifier, message)
26
+ broadcast(event_name, device_sn, message)
27
27
  end
28
+
29
+ # Broadcast a generic received osd message event
30
+ broadcast(:received_osd_message, device_sn, message)
28
31
  rescue ParseError => error
29
32
  broadcast(:parse_error, error, topic, raw_message)
30
33
  end
@@ -24,6 +24,9 @@ module DjiMqttConnect
24
24
  # Build event name and broadcast (i.e. ::ConfigRequestsMessage => config)
25
25
  broadcast(message._method.to_sym, gateway_sn, message)
26
26
  end
27
+
28
+ # Broadcast a generic received requests message event
29
+ broadcast(:received_requests_message, gateway_sn, message)
27
30
  rescue ParseError => error
28
31
  broadcast(:parse_error, error, topic, raw_message)
29
32
  end
@@ -25,6 +25,9 @@ module DjiMqttConnect
25
25
  event_name = "#{message._method.to_sym}_reply"
26
26
  broadcast(event_name, gateway_sn, message)
27
27
  end
28
+
29
+ # Broadcast a generic received services reply message event
30
+ broadcast(:received_services_reply_message, gateway_sn, message)
28
31
  rescue ParseError => error
29
32
  broadcast(:parse_error, error, topic, raw_message)
30
33
  end
@@ -3,7 +3,7 @@
3
3
  module DjiMqttConnect
4
4
  module Thing::Product
5
5
  class StateTopicRepository < TopicRepository
6
- STATE_TOPIC_REGEX = /\Athing\/product\/(?<gateway_sn>.+)\/state\z/
6
+ STATE_TOPIC_REGEX = /\Athing\/product\/(?<device_sn>.+)\/state\z/
7
7
 
8
8
  def listen!
9
9
  listen_to_topic("thing/product/+/state") do |topic, raw_message|
@@ -12,13 +12,13 @@ module DjiMqttConnect
12
12
  matched_topic = STATE_TOPIC_REGEX.match(topic)
13
13
  raise Error, "Unknown topic: #{topic}" unless matched_topic
14
14
 
15
- gateway_sn = matched_topic[:gateway_sn]
15
+ device_sn = matched_topic[:device_sn]
16
16
  message = state_marshal.load(raw_message)
17
17
 
18
- logger.info("Received #{message} from #{gateway_sn}")
18
+ logger.info("Received #{message} from #{device_sn}")
19
19
 
20
- # Broadcast the state update
21
- broadcast(:state_update, gateway_sn, message)
20
+ # Broadcast a generic received state message event
21
+ broadcast(:received_state_message, device_sn, message)
22
22
  rescue ParseError => error
23
23
  broadcast(:parse_error, error, topic, raw_message)
24
24
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Thing::Product
5
+ class StateReplyTopicRepository < TopicRepository
6
+ # Publishes a message to gateway_sn on the "thing/product/+/state_reply" topic.
7
+ def publish_to_device(gateway_sn, state_reply_message)
8
+ publish_to_topic(
9
+ "thing/product/#{gateway_sn}/state_reply",
10
+ state_reply_message,
11
+ marshal: StateReplyMarshal
12
+ )
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DjiMqttConnect
4
- VERSION = "0.1.22.2"
4
+ VERSION = "0.1.23.1"
5
5
  end
@@ -51,6 +51,7 @@ module DjiMqttConnect
51
51
  autoload :OfflineMapSyncProgressEventsMessage, "dji_mqtt_connect/messages/thing/product/events/offline_map_sync_progress"
52
52
  autoload :ReturnHomeInfoEventsMessage, "dji_mqtt_connect/messages/thing/product/events/return_home_info"
53
53
  autoload :StatusCodeEventsMessage, "dji_mqtt_connect/messages/thing/product/events/status_code"
54
+ autoload :TakeoffToPointProgressEventsMessage, "dji_mqtt_connect/messages/thing/product/events/takeoff_to_point_progress"
54
55
  autoload :TrackEventsMessage, "dji_mqtt_connect/messages/thing/product/events/track"
55
56
  autoload :EventsMessage, "dji_mqtt_connect/messages/thing/product/events_message"
56
57
 
@@ -119,6 +120,7 @@ module DjiMqttConnect
119
120
  autoload :ReturnHomeCancelServicesReplyMessage, "dji_mqtt_connect/messages/thing/product/services_reply/return_home_cancel"
120
121
 
121
122
  autoload :StateMessage, "dji_mqtt_connect/messages/thing/product/state_message"
123
+ autoload :StateReplyMessage, "dji_mqtt_connect/messages/thing/product/state_reply_message"
122
124
 
123
125
  # Topics
124
126
  autoload :EventsTopicRepository, "dji_mqtt_connect/topics/thing/product/events"
@@ -129,6 +131,7 @@ module DjiMqttConnect
129
131
  autoload :ServicesTopicRepository, "dji_mqtt_connect/topics/thing/product/services"
130
132
  autoload :ServicesReplyTopicRepository, "dji_mqtt_connect/topics/thing/product/services_reply"
131
133
  autoload :StateTopicRepository, "dji_mqtt_connect/topics/thing/product/state"
134
+ autoload :StateReplyTopicRepository, "dji_mqtt_connect/topics/thing/product/state_reply"
132
135
 
133
136
  # Marshals
134
137
  autoload :EventsMarshal, "dji_mqtt_connect/marshals/thing/product/events_marshal"
@@ -143,6 +146,7 @@ module DjiMqttConnect
143
146
  autoload :ServicesReplyMarshal, "dji_mqtt_connect/marshals/thing/product/services_reply_marshal"
144
147
 
145
148
  autoload :StateMarshal, "dji_mqtt_connect/marshals/thing/product/state_marshal"
149
+ autoload :StateReplyMarshal, "dji_mqtt_connect/marshals/thing/product/state_reply_marshal"
146
150
  end
147
151
  end
148
152