dji_mqtt_connect 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 286e565c906b968d00df2865b04ab56f7edad331f603f059900d5d2ba0884e5f
4
- data.tar.gz: 1f1e18bf29b660f9d68a7bc2b3a888a967782ee284872eab52af3c40cc780230
3
+ metadata.gz: 480a31f560b51a7180e845294de0e25fb2668005051b76d88207ec5a7e2c2199
4
+ data.tar.gz: f03b528efc73a514a910c31f16cc824e6ca2287176916ceaa168eb90c6489b00
5
5
  SHA512:
6
- metadata.gz: 31e6ff2f90df68713a207cb3e70b8cb9c7aed4a4294ee70b3867b8f4a37390eb3d91931b0f533bac6361e2adac5dc307e3cb8544da762b9a9934949258f03c98
7
- data.tar.gz: 55f3e73e77128f8f6c97f6fcf9425975eb11497ede3c55db6df57e06dd95e1713aa2c7bdf2adf76766e9d949c2c7133f8d9dc00106bf5a1922e5a4c77e1e0d90
6
+ metadata.gz: fca3a2a03f9c700c4ca94e31cc247c198205523e3c5595f969238c1600b51fd5ee9381ba8325bedb56e99b135122db338ce38d239fe8abb0d0b1af3da66c42f0
7
+ data.tar.gz: 2a4ee86eebc3704c059d93f652383870c8f6d4b09f6e952879db5fa515ca5282e451496713134054a69acb15a211ca7fbb6902ea54f2be36b6b51ce8735850e6
data/README.md CHANGED
@@ -6,15 +6,13 @@ See also: https://developer.dji.com/doc/cloud-api-tutorial/en/server-api-referen
6
6
 
7
7
  ## Installation
8
8
 
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
10
-
11
9
  Install the gem and add to the application's Gemfile by executing:
12
10
 
13
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
11
+ $ bundle add dji_mqtt_connect
14
12
 
15
13
  If bundler is not being used to manage dependencies, install the gem by executing:
16
14
 
17
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
15
+ $ gem install dji_mqtt_connect
18
16
 
19
17
  ## Usage
20
18
 
@@ -45,5 +45,74 @@ module DjiMqttConnect
45
45
  }
46
46
  )
47
47
  end
48
+
49
+ def build_thing_product_config_requests_message
50
+ message_data = {
51
+ config_type: "json",
52
+ config_scope: "product"
53
+ }
54
+
55
+ Thing::Product::ConfigRequestsMessage.new(
56
+ _method: "config",
57
+ tid: "3093aad5-bb98-5026-685a-cea540eb9267",
58
+ bid: "479533e0-cb01-933c-3758-22f2a82abeb8",
59
+ timestamp: 1679380233000,
60
+ gateway: "gatewaysn",
61
+ data: message_data,
62
+ _data: message_data.deep_stringify_keys
63
+ )
64
+ end
65
+
66
+ def build_thing_product_config_requests_reply_message
67
+ request_message = build_thing_product_config_requests_message
68
+ reply_data = {
69
+ ntp_server_host: "http://time.google.com/",
70
+ app_id: "123456",
71
+ app_key: "app_key",
72
+ app_license: "app_license"
73
+ }
74
+
75
+ Thing::Product::ConfigRequestsReplyMessage.build_for(request_message, data: reply_data)
76
+ end
77
+
78
+ def build_thing_product_airport_bind_status_requests_message
79
+ message_data = {
80
+ devices: [
81
+ {
82
+ sn: "drone-sn"
83
+ },
84
+ {
85
+ sn: "dock-sn"
86
+ }
87
+ ]
88
+ }
89
+
90
+ Thing::Product::AirportBindStatusRequestsMessage.new(
91
+ _method: "airport_bind_status",
92
+ _data: message_data,
93
+ tid: "3093aad5-bb98-5026-685a-cea540eb9267",
94
+ bid: "479533e0-cb01-933c-3758-22f2a82abeb8",
95
+ timestamp: 1679380233000,
96
+ data: message_data
97
+ )
98
+ end
99
+
100
+ def build_thing_product_airport_bind_status_requests_reply_message
101
+ airport_bind_status_request = build_thing_product_airport_bind_status_requests_message
102
+
103
+ Thing::Product::AirportBindStatusRequestsReplyMessage.build_for(
104
+ airport_bind_status_request,
105
+ result: 0,
106
+ bind_status: airport_bind_status_request.data.devices.map.with_index do |device, index|
107
+ {
108
+ sn: device.sn,
109
+ is_device_bind_organization: (index % 2).zero?,
110
+ organization_id: "12345678",
111
+ organization_name: "12345",
112
+ device_callsign: "Device organization callsign"
113
+ }
114
+ end
115
+ )
116
+ end
48
117
  end
49
118
  end
@@ -6,6 +6,8 @@ require "json"
6
6
  module DjiMqttConnect
7
7
  module Sys::Product
8
8
  class StatusMarshal < MessageMarshal
9
+ include Utils::MessageParsing
10
+
9
11
  # Rename pesky `method` argument to `_method` and makes a copy of the raw data
10
12
  class AttributeTransformer < Dry::Transformer::Pipe
11
13
  import Dry::Transformer::HashTransformations
@@ -27,7 +29,7 @@ module DjiMqttConnect
27
29
  transformed_message = attribute_transformer.call(parsed_message)
28
30
 
29
31
  # Build an instance of the class, or a generic message from the current class
30
- message_class = message_class_for_parsed_message(parsed_message)
32
+ message_class = message_class_for_parsed_message(parsed_message, StatusMessage)
31
33
  message_class.new transformed_message
32
34
  rescue JSON::ParserError => e
33
35
  raise ParseError.new(e, "Unable to parse message as JSON")
@@ -40,18 +42,6 @@ module DjiMqttConnect
40
42
  def attribute_transformer
41
43
  @attribute_transformer ||= AttributeTransformer.new
42
44
  end
43
-
44
- def message_class_for_parsed_message(parsed_message)
45
- # update_topo => UpdateTopo
46
- classified_method = ActiveSupport::Inflector.classify(parsed_message["method"])
47
-
48
- # UpdateTopo => DjiMqttConnect::Sys::Product::UpdateTopoStatusMessage
49
- module_prefix, joiner, class_suffix = StatusMessage.name.rpartition("::")
50
- message_class_name = [module_prefix, joiner, classified_method, class_suffix].join
51
-
52
- # Constantize an instance of the message-specific class, or fallback to a generic message
53
- ActiveSupport::Inflector.safe_constantize(message_class_name) || StatusMessage
54
- end
55
45
  end
56
46
  end
57
47
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry-struct"
4
+ require "dry-transformer"
5
+ require "json"
6
+
7
+ module DjiMqttConnect
8
+ module Thing::Product
9
+ class RequestsMarshal < MessageMarshal
10
+ include Utils::MessageParsing
11
+
12
+ # Rename pesky `method` argument to `_method` and makes a copy of the raw data
13
+ class AttributeTransformer < Dry::Transformer::Pipe
14
+ import Dry::Transformer::HashTransformations
15
+
16
+ define! do
17
+ symbolize_keys
18
+
19
+ copy_keys data: :_data
20
+ rename_keys method: :_method
21
+ end
22
+ end
23
+
24
+ # Attempts to look a the method attribute, and builds a specific Message class for the message
25
+ def load(raw_message)
26
+ # Parse the message from JSON
27
+ parsed_message = JSON.parse(raw_message)
28
+
29
+ # Transform the message
30
+ transformed_message = attribute_transformer.call(parsed_message)
31
+
32
+ # Build an instance of the class, or a generic message from the current class
33
+ message_class = message_class_for_parsed_message(parsed_message, RequestsMessage)
34
+ message_class.new transformed_message
35
+ rescue JSON::ParserError => e
36
+ raise ParseError.new(e, "Unable to parse message as JSON")
37
+ rescue Dry::Struct::Error => e
38
+ raise ParseError.new(e, "Unexpected #{message_class} payload")
39
+ end
40
+
41
+ private
42
+
43
+ def attribute_transformer
44
+ @attribute_transformer ||= AttributeTransformer.new
45
+ end
46
+ end
47
+ end
48
+ 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 RequestsReplyMarshal < 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
@@ -17,7 +17,7 @@ module DjiMqttConnect
17
17
  )
18
18
  end
19
19
 
20
- attribute :_method, Types::String
20
+ attribute :_method, Types::String.enum("update_topo")
21
21
 
22
22
  attribute :tid, Types::String
23
23
  attribute :bid, Types::String
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Thing::Product
5
+ class AirportBindStatusRequestsMessage < RequestsMessage
6
+ attribute :_method, Types::String.enum("airport_bind_status")
7
+
8
+ attribute :data do
9
+ attribute :devices, Types::Array do
10
+ attribute :sn, Types::String
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Thing::Product
5
+ class AirportBindStatusRequestsReplyMessage < Message
6
+ def self.build_for(airport_bind_status_message, bind_status:, result: 0)
7
+ new(
8
+ _method: airport_bind_status_message._method,
9
+ tid: airport_bind_status_message.tid,
10
+ bid: airport_bind_status_message.bid,
11
+ timestamp: Time.now.strftime("%s%L").to_i,
12
+ data: {
13
+ result: result,
14
+ output: {
15
+ bind_status: bind_status
16
+ }
17
+ }
18
+ )
19
+ end
20
+
21
+ attribute :tid, Types::UUID
22
+ attribute :bid, Types::UUID
23
+ attribute :timestamp, Types::Timestamp
24
+
25
+ attribute :_method, Types::String.enum("airport_bind_status")
26
+
27
+ attribute :data do
28
+ attribute :result, Types::Integer
29
+ attribute :output do
30
+ attribute :bind_status, Types::Array do
31
+ attribute :sn, Types::String
32
+ attribute :is_device_bind_organization, Types::Bool
33
+ attribute :organization_id, Types::String
34
+ attribute :organization_name, Types::String
35
+ attribute :device_callsign, Types::String
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Thing::Product
5
+ class ConfigRequestsMessage < RequestsMessage
6
+ attribute :gateway, Types::String
7
+ attribute :_method, Types::String.enum("config")
8
+
9
+ attribute :data do
10
+ attribute :config_type, Types::String.enum("json")
11
+ attribute :config_scope, Types::String.enum("product")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Thing::Product
5
+ class ConfigRequestsReplyMessage < Message
6
+ def self.build_for(config_request_message, data:)
7
+ new(
8
+ _method: config_request_message._method,
9
+ data: data,
10
+ tid: config_request_message.tid,
11
+ bid: config_request_message.bid,
12
+ timestamp: Time.now.strftime("%s%L").to_i,
13
+ gateway: config_request_message.gateway
14
+ )
15
+ end
16
+
17
+ attribute :tid, Types::UUID
18
+ attribute :bid, Types::UUID
19
+ attribute :timestamp, Types::Timestamp
20
+ attribute :gateway, Types::String
21
+
22
+ attribute :_method, Types::String.enum("config")
23
+ attribute :data do
24
+ attribute :ntp_server_host, Types::String
25
+ attribute :app_id, Types::String
26
+ attribute :app_key, Types::String
27
+ attribute :app_license, Types::String
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Thing::Product
5
+ class RequestsMessage < DjiMqttConnect::Message
6
+ attribute :tid, Types::UUID
7
+ attribute :bid, Types::UUID
8
+ attribute :timestamp, Types::Timestamp
9
+
10
+ attribute :_data, Types::Hash
11
+ attribute :_method, Types::String
12
+
13
+ def to_s
14
+ # Include data method for Generic messages
15
+ instance_of?(RequestsMessage) ? "#{super}[#{_method}]" : super
16
+ end
17
+ end
18
+ end
19
+ end
@@ -17,6 +17,8 @@ module DjiMqttConnect
17
17
 
18
18
  logger.info("Received #{message} from #{device_identifier}")
19
19
  broadcast(message._method.to_sym, device_identifier, message)
20
+ rescue ParseError => error
21
+ broadcast(:parse_error, error, raw_message)
20
22
  end
21
23
  end
22
24
 
@@ -20,6 +20,8 @@ module DjiMqttConnect
20
20
  # Build event name and broadcast (i.e. ::RemoteOsdMessage => remote_osd_update)
21
21
  event_name = message.class.name.demodulize.sub(/Message\z/, "Update").underscore.to_sym
22
22
  broadcast(event_name, device_identifier, message)
23
+ rescue ParseError => error
24
+ broadcast(:parse_error, error, raw_message)
23
25
  end
24
26
  end
25
27
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Thing::Product
5
+ class RequestsTopicRepository < TopicRepository
6
+ REQUESTS_TOPIC_REGEX = /\Athing\/product\/(?<gateway_sn>.+)\/requests\z/
7
+
8
+ def listen!
9
+ listen_to_topic("thing/product/+/requests") do |topic, raw_message|
10
+ logger.debug(raw_message)
11
+
12
+ matched_topic = REQUESTS_TOPIC_REGEX.match(topic)
13
+ raise Error, "Unknown topic: #{topic}" unless matched_topic
14
+
15
+ gateway_sn = matched_topic[:gateway_sn]
16
+ message = requests_marshal.load(raw_message)
17
+
18
+ logger.info("Received #{message} from #{gateway_sn}")
19
+ broadcast(message._method.to_sym, gateway_sn, message)
20
+ rescue ParseError => error
21
+ broadcast(:parse_error, error, raw_message)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def requests_marshal
28
+ @requests_marshal ||= RequestsMarshal.new
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Thing::Product
5
+ class RequestsReplyTopicRepository < TopicRepository
6
+ # Publishes a message to gateway_sn on the "thing/product/+/requests_reply" topic.
7
+ def publish_to_device(gateway_sn, requests_reply_message)
8
+ publish_to_topic(
9
+ "thing/product/#{gateway_sn}/requests_reply",
10
+ requests_reply_message,
11
+ marshal: RequestsReplyMarshal
12
+ )
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Utils
5
+ module MessageParsing
6
+ private
7
+
8
+ def message_class_for_parsed_message(parsed_message, generic_class)
9
+ # update_topo => UpdateTopo
10
+ classified_method = ActiveSupport::Inflector.classify(parsed_message["method"])
11
+
12
+ # UpdateTopo => DjiMqttConnect::Sys::Product::UpdateTopoStatusMessage
13
+ module_prefix, joiner, class_suffix = generic_class.name.rpartition("::")
14
+ message_class_name = [module_prefix, joiner, classified_method, class_suffix].join
15
+
16
+ # Constantize an instance of the message-specific class, or fallback to a generic message
17
+ ActiveSupport::Inflector.safe_constantize(message_class_name) || generic_class
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DjiMqttConnect
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
@@ -37,14 +37,31 @@ module DjiMqttConnect
37
37
  autoload :DroneOsdMessage, "dji_mqtt_connect/messages/thing/product/drone_osd_message"
38
38
  autoload :RemoteOsdMessage, "dji_mqtt_connect/messages/thing/product/remote_osd_message"
39
39
 
40
+ autoload :AirportBindStatusRequestsMessage, "dji_mqtt_connect/messages/thing/product/airport_bind_status_requests_message"
41
+ autoload :ConfigRequestsMessage, "dji_mqtt_connect/messages/thing/product/config_requests_message"
42
+ autoload :RequestsMessage, "dji_mqtt_connect/messages/thing/product/requests_message"
43
+
44
+ autoload :AirportBindStatusRequestsReplyMessage, "dji_mqtt_connect/messages/thing/product/airport_bind_status_requests_reply_message"
45
+ autoload :ConfigRequestsReplyMessage, "dji_mqtt_connect/messages/thing/product/config_requests_reply_message"
46
+
40
47
  # Topics
41
48
  autoload :OsdTopicRepository, "dji_mqtt_connect/topics/thing/product/osd"
49
+ autoload :RequestsTopicRepository, "dji_mqtt_connect/topics/thing/product/requests"
50
+ autoload :RequestsReplyTopicRepository, "dji_mqtt_connect/topics/thing/product/requests_reply"
42
51
 
43
52
  # Marshals
44
53
  autoload :OsdMarshal, "dji_mqtt_connect/marshals/thing/product/osd_marshal"
54
+
55
+ autoload :RequestsMarshal, "dji_mqtt_connect/marshals/thing/product/requests_marshal"
56
+ autoload :RequestsReplyMarshal, "dji_mqtt_connect/marshals/thing/product/requests_reply_marshal"
45
57
  end
46
58
  end
47
59
 
60
+ # Utils
61
+ module Utils
62
+ autoload :MessageParsing, "dji_mqtt_connect/utils/message_parsing"
63
+ end
64
+
48
65
  # Railties
49
66
  module Railties
50
67
  autoload :MessageSerializer, "dji_mqtt_connect/railties/message_serializer"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dji_mqtt_connect
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sphere Drones
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-03 00:00:00.000000000 Z
11
+ date: 2023-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -110,21 +110,31 @@ files:
110
110
  - lib/dji_mqtt_connect/marshals/sys/product/status_marshal.rb
111
111
  - lib/dji_mqtt_connect/marshals/sys/product/status_reply_marshal.rb
112
112
  - lib/dji_mqtt_connect/marshals/thing/product/osd_marshal.rb
113
+ - lib/dji_mqtt_connect/marshals/thing/product/requests_marshal.rb
114
+ - lib/dji_mqtt_connect/marshals/thing/product/requests_reply_marshal.rb
113
115
  - lib/dji_mqtt_connect/message.rb
114
116
  - lib/dji_mqtt_connect/message_marshal.rb
115
117
  - lib/dji_mqtt_connect/messages/sys/product/status_message.rb
116
118
  - lib/dji_mqtt_connect/messages/sys/product/update_topo_status_message.rb
117
119
  - lib/dji_mqtt_connect/messages/sys/product/update_topo_status_reply_message.rb
120
+ - lib/dji_mqtt_connect/messages/thing/product/airport_bind_status_requests_message.rb
121
+ - lib/dji_mqtt_connect/messages/thing/product/airport_bind_status_requests_reply_message.rb
122
+ - lib/dji_mqtt_connect/messages/thing/product/config_requests_message.rb
123
+ - lib/dji_mqtt_connect/messages/thing/product/config_requests_reply_message.rb
118
124
  - lib/dji_mqtt_connect/messages/thing/product/drone_osd_message.rb
119
125
  - lib/dji_mqtt_connect/messages/thing/product/osd_message.rb
120
126
  - lib/dji_mqtt_connect/messages/thing/product/remote_osd_message.rb
127
+ - lib/dji_mqtt_connect/messages/thing/product/requests_message.rb
121
128
  - lib/dji_mqtt_connect/railtie.rb
122
129
  - lib/dji_mqtt_connect/railties/message_serializer.rb
123
130
  - lib/dji_mqtt_connect/topic_repository.rb
124
131
  - lib/dji_mqtt_connect/topics/sys/product/status.rb
125
132
  - lib/dji_mqtt_connect/topics/sys/product/status_reply.rb
126
133
  - lib/dji_mqtt_connect/topics/thing/product/osd.rb
134
+ - lib/dji_mqtt_connect/topics/thing/product/requests.rb
135
+ - lib/dji_mqtt_connect/topics/thing/product/requests_reply.rb
127
136
  - lib/dji_mqtt_connect/types.rb
137
+ - lib/dji_mqtt_connect/utils/message_parsing.rb
128
138
  - lib/dji_mqtt_connect/version.rb
129
139
  - sig/dji_mqtt_connect.rbs
130
140
  homepage: https://github.com/sphere-drones/dji_mqtt_connect