dji_mqtt_connect 0.1.1.4 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop/rspec.yml +2 -2
  3. data/Gemfile.lock +20 -9
  4. data/dji_mqtt_connect.gemspec +48 -0
  5. data/lib/dji_mqtt_connect/factories.rb +65 -0
  6. data/lib/dji_mqtt_connect/marshals/thing/product/osd_marshal.rb +17 -3
  7. data/lib/dji_mqtt_connect/messages/thing/product/airport_organization_get_requests_message.rb +15 -0
  8. data/lib/dji_mqtt_connect/messages/thing/product/airport_organization_get_requests_reply_message.rb +34 -0
  9. data/lib/dji_mqtt_connect/messages/thing/product/dock_osd_message.rb +199 -0
  10. data/lib/dji_mqtt_connect/messages/thing/product/drone_osd_message.rb +114 -10
  11. data/lib/dji_mqtt_connect/messages/thing/product/remote_osd_message.rb +4 -9
  12. data/lib/dji_mqtt_connect/messages/thing/product/storage_config_get_requests_message.rb +14 -0
  13. data/lib/dji_mqtt_connect/messages/thing/product/storage_config_get_requests_reply_message.rb +44 -0
  14. data/lib/dji_mqtt_connect/mixins/latitude_conditional.rb +12 -0
  15. data/lib/dji_mqtt_connect/mixins/longitude_conditional.rb +12 -0
  16. data/lib/dji_mqtt_connect/mixins/temperature_conditional.rb +12 -0
  17. data/lib/dji_mqtt_connect/topics/sys/product/status.rb +8 -1
  18. data/lib/dji_mqtt_connect/topics/thing/product/osd.rb +8 -3
  19. data/lib/dji_mqtt_connect/topics/thing/product/requests.rb +8 -1
  20. data/lib/dji_mqtt_connect/types.rb +3 -0
  21. data/lib/dji_mqtt_connect/utils/message_sanitizer.rb +90 -0
  22. data/lib/dji_mqtt_connect/utils/message_schema_generator.rb +39 -0
  23. data/lib/dji_mqtt_connect/utils/mqttx_fixture_data_generator.rb +68 -0
  24. data/lib/dji_mqtt_connect/version.rb +1 -1
  25. data/lib/dji_mqtt_connect.rb +15 -0
  26. metadata +14 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d7418cbbd6b891b0d72ea6d8e47f9b7f813b9de2dffd97f7bae249292a73f510
4
- data.tar.gz: 6f2047ad8fcb7db0eff553c8c4dde862d2dbaa8b0820cd240a400d276470e51f
3
+ metadata.gz: 824a4b8942fc65705e25588a32df620e49602573b1eb14ed6f1b2c34c98023cd
4
+ data.tar.gz: 7f9dc5c06e40c04862baed3c41b8342da77a9fbedb083ab7432b9173180ebce1
5
5
  SHA512:
6
- metadata.gz: d1d174f8a9475a59f1e5ed31835903a49dbc1100464fbf9da910b47f7219ed348ab710aee3baef7c1da75d17ef4e5340203e033650a50257018fa7499fae67b1
7
- data.tar.gz: 9c9795cea856dd583733174aa9fd0871c50772b23d438bfb3d1608dd913187df62e4e7cb9468c6ad4beba336c60d163f9887a8c635714cf1dd0853ab25789f69
6
+ metadata.gz: 58ccec055d15866882fd93521c5d312719012c10e8778e18b99191c2bb48a7173ac0283f7f18daf21fb950d0472c02b3cb861cd1d07b0da0584e62278d62554c
7
+ data.tar.gz: ac4f30aa186b37fa04dbadbc49d813648c08ca031809a7c3b73d97fb0d6f7489cc680d74e0a3a83015ebcf77d26d25386c7f8dbecdb4e04e337308bc3a1f7a6c
data/.rubocop/rspec.yml CHANGED
@@ -48,8 +48,8 @@ RSpec/ReceiveCounts:
48
48
  Capybara/CurrentPathExpectation:
49
49
  Enabled: true
50
50
 
51
- RSpec/FactoryBot/AttributeDefinedStatically:
51
+ FactoryBot/AttributeDefinedStatically:
52
52
  Enabled: true
53
53
 
54
- RSpec/FactoryBot/CreateList:
54
+ FactoryBot/CreateList:
55
55
  Enabled: true
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dji_mqtt_connect (0.1.1.4)
4
+ dji_mqtt_connect (0.1.2)
5
5
  activesupport (>= 6.0, <= 8)
6
6
  dry-struct (~> 1.6)
7
7
  dry-transformer (~> 1.0)
@@ -46,15 +46,16 @@ GEM
46
46
  zeitwerk (~> 2.6)
47
47
  globalid (1.1.0)
48
48
  activesupport (>= 5.0)
49
- i18n (1.12.0)
49
+ i18n (1.13.0)
50
50
  concurrent-ruby (~> 1.0)
51
51
  ice_nine (0.11.2)
52
52
  json (2.6.3)
53
53
  language_server-protocol (3.17.0.3)
54
+ lint_roller (1.0.0)
54
55
  minitest (5.18.0)
55
56
  mqtt (0.6.0)
56
57
  parallel (1.23.0)
57
- parser (3.2.2.0)
58
+ parser (3.2.2.1)
58
59
  ast (~> 2.4.1)
59
60
  rainbow (3.1.1)
60
61
  rake (13.0.6)
@@ -66,7 +67,7 @@ GEM
66
67
  rspec-mocks (~> 3.12.0)
67
68
  rspec-core (3.12.2)
68
69
  rspec-support (~> 3.12.0)
69
- rspec-expectations (3.12.2)
70
+ rspec-expectations (3.12.3)
70
71
  diff-lcs (>= 1.2.0, < 2.0)
71
72
  rspec-support (~> 3.12.0)
72
73
  rspec-mocks (3.12.5)
@@ -83,18 +84,21 @@ GEM
83
84
  rubocop-ast (>= 1.28.0, < 2.0)
84
85
  ruby-progressbar (~> 1.7)
85
86
  unicode-display_width (>= 2.4.0, < 3.0)
86
- rubocop-ast (1.28.0)
87
+ rubocop-ast (1.28.1)
87
88
  parser (>= 3.2.1.0)
88
- rubocop-capybara (2.17.1)
89
+ rubocop-capybara (2.18.0)
89
90
  rubocop (~> 1.41)
91
+ rubocop-factory_bot (2.22.0)
92
+ rubocop (~> 1.33)
90
93
  rubocop-performance (1.16.0)
91
94
  rubocop (>= 1.7.0, < 2.0)
92
95
  rubocop-ast (>= 0.4.0)
93
96
  rubocop-rake (0.6.0)
94
97
  rubocop (~> 1.0)
95
- rubocop-rspec (2.20.0)
98
+ rubocop-rspec (2.22.0)
96
99
  rubocop (~> 1.33)
97
100
  rubocop-capybara (~> 2.17)
101
+ rubocop-factory_bot (~> 2.22)
98
102
  ruby-progressbar (1.13.0)
99
103
  simplecov (0.22.0)
100
104
  docile (~> 1.1)
@@ -102,16 +106,23 @@ GEM
102
106
  simplecov_json_formatter (~> 0.1)
103
107
  simplecov-html (0.12.3)
104
108
  simplecov_json_formatter (0.1.4)
105
- standard (1.27.0)
109
+ standard (1.28.2)
106
110
  language_server-protocol (~> 3.17.0.2)
111
+ lint_roller (~> 1.0)
107
112
  rubocop (~> 1.50.2)
113
+ standard-custom (~> 1.0.0)
114
+ standard-performance (~> 1.0.1)
115
+ standard-custom (1.0.0)
116
+ lint_roller (~> 1.0)
117
+ standard-performance (1.0.1)
118
+ lint_roller (~> 1.0)
108
119
  rubocop-performance (~> 1.16.0)
109
120
  tzinfo (2.0.6)
110
121
  concurrent-ruby (~> 1.0)
111
122
  unicode-display_width (2.4.2)
112
123
  wisper (2.0.1)
113
124
  wisper-rspec (1.1.0)
114
- zeitwerk (2.6.7)
125
+ zeitwerk (2.6.8)
115
126
 
116
127
  PLATFORMS
117
128
  x86_64-darwin-21
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/dji_mqtt_connect/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "dji_mqtt_connect"
7
+ spec.version = DjiMqttConnect::VERSION
8
+ spec.authors = ["Sphere Drones"]
9
+ spec.email = ["projects@spheregroup.com.au"]
10
+
11
+ spec.summary = "Manages MQTT Connections with DJI Drones"
12
+ # spec.description = "TODO: Write a longer description or delete this line."
13
+ spec.homepage = "https://github.com/sphere-drones/dji_mqtt_connect"
14
+ spec.required_ruby_version = ">= 3.1.0"
15
+
16
+ # spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
17
+
18
+ spec.metadata["homepage_uri"] = spec.homepage
19
+ spec.metadata["source_code_uri"] = "https://github.com/sphere-drones/dji_mqtt_connect"
20
+ spec.metadata["changelog_uri"] = "https://github.com/sphere-drones/dji_mqtt_connect/main/CHANGELOG.md"
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(__dir__) do
25
+ `git ls-files -z`.split("\x0").reject do |f|
26
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|circleci)|appveyor)})
27
+ end
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+
33
+ # Use Active Support for inflection and logging
34
+ spec.add_dependency "activesupport", ">= 6.0", "<= 8"
35
+
36
+ # Use Dry-rb for valid POROs
37
+ spec.add_dependency "dry-struct", "~> 1.6"
38
+ spec.add_dependency "dry-transformer", "~> 1.0"
39
+
40
+ # Use MQTT as a client for receiving/sending messages
41
+ spec.add_dependency "mqtt", "~> 0.6.0"
42
+
43
+ # Use Whisper for events
44
+ spec.add_dependency "wisper", "~> 2.0"
45
+
46
+ # For more information and examples about making a new gem, check out our
47
+ # guide at: https://bundler.io/guides/creating_gem.html
48
+ end
@@ -114,5 +114,70 @@ module DjiMqttConnect
114
114
  end
115
115
  )
116
116
  end
117
+
118
+ def build_thing_product_airport_organization_get_requests_message
119
+ message_data = {
120
+ device_binding_code: "device_binding_code",
121
+ organization_id: "organization_id"
122
+ }
123
+
124
+ Thing::Product::AirportOrganizationGetRequestsMessage.new(
125
+ _method: "airport_organization_get",
126
+ _data: message_data,
127
+ tid: "3093aad5-bb98-5026-685a-cea540eb9267",
128
+ bid: "479533e0-cb01-933c-3758-22f2a82abeb8",
129
+ timestamp: 1679380233000,
130
+ data: message_data
131
+ )
132
+ end
133
+
134
+ def build_thing_product_airport_organization_get_requests_reply_message
135
+ airport_organization_get_request = build_thing_product_airport_organization_get_requests_message
136
+
137
+ Thing::Product::AirportOrganizationGetRequestsReplyMessage.build_for(
138
+ airport_organization_get_request,
139
+ result: 0,
140
+ output: {
141
+ organization_name: "12345"
142
+ }
143
+ )
144
+ end
145
+
146
+ def build_thing_product_storage_config_get_requests_message
147
+ message_data = {
148
+ module: 0
149
+ }
150
+
151
+ Thing::Product::StorageConfigGetRequestsMessage.new(
152
+ _method: "storage_config_get",
153
+ _data: message_data,
154
+ tid: "3093aad5-bb98-5026-685a-cea540eb9267",
155
+ bid: "479533e0-cb01-933c-3758-22f2a82abeb8",
156
+ timestamp: 1679380233000,
157
+ data: message_data
158
+ )
159
+ end
160
+
161
+ def build_thing_product_storage_config_get_requests_reply_message
162
+ storage_config_get_request = build_thing_product_storage_config_get_requests_message
163
+
164
+ Thing::Product::StorageConfigGetRequestsReplyMessage.build_for(
165
+ storage_config_get_request,
166
+ result: 0,
167
+ output: {
168
+ bucket: "bucket_name",
169
+ credentials: {
170
+ access_key_id: "access_key_id",
171
+ access_key_secret: "access_key_secret",
172
+ expire: 3600,
173
+ security_token: "security_token"
174
+ },
175
+ endpoint: "https://oss-cn-hangzhou.aliyuncs.com",
176
+ object_key_prefix: "b4cfaae6-bd9d-4cd0-8472-63b608c3c581",
177
+ provider: "ali",
178
+ region: "hz"
179
+ }
180
+ )
181
+ end
117
182
  end
118
183
  end
@@ -12,10 +12,15 @@ module DjiMqttConnect
12
12
  import Dry::Transformer::HashTransformations
13
13
 
14
14
  define! do
15
+ # Ensure there is a data element
16
+ map_value "data", ->(data) { data || {} }
17
+
18
+ # Create a backup for unsupported attributes
15
19
  copy_keys "data" => "_data"
16
20
 
17
21
  map_value "data" do
18
- guard ->(data) { data&.key?("wireless_link") } do
22
+ # Rename the invalid (for Ruby) wireless link attributes
23
+ guard ->(data) { data.key?("wireless_link") } do
19
24
  # Translate wireless_link 4g keys (from remote payload)
20
25
  map_value "wireless_link" do
21
26
  rename_keys "4g_freq_band" => "_4g_freq_band",
@@ -38,6 +43,8 @@ module DjiMqttConnect
38
43
  DroneOsdMessage
39
44
  elsif remote_osd_data_attributes.all? { |attribute| message_data.key?(attribute.to_s) }
40
45
  RemoteOsdMessage
46
+ elsif dock_osd_data_attributes.any? { |attribute| message_data.key?(attribute.to_s) }
47
+ DockOsdMessage
41
48
  else
42
49
  OsdMessage
43
50
  end
@@ -57,12 +64,19 @@ module DjiMqttConnect
57
64
  @attribute_transformer ||= AttributeTransformer.new
58
65
  end
59
66
 
67
+ def dock_osd_data_attributes
68
+ @dock_osd_data_attributes ||= DockOsdMessage::STABLE_DATA_ATTRIBUTES.map(&:to_s)
69
+ end
70
+
60
71
  def drone_osd_data_attributes
61
- @drone_osd_data_attributes ||= DjiMqttConnect::Thing::Product::DroneOsdMessage::Data.schema.keys.map(&:name)
72
+ @drone_osd_data_attributes ||= DroneOsdMessage::STABLE_DATA_ATTRIBUTES.map(&:to_s)
62
73
  end
63
74
 
64
75
  def remote_osd_data_attributes
65
- @remote_osd_data_attributes ||= DjiMqttConnect::Thing::Product::RemoteOsdMessage::Data.schema.keys.map(&:name)
76
+ @remote_osd_data_attributes ||= begin
77
+ data_keys = DjiMqttConnect::Thing::Product::RemoteOsdMessage::Data.schema.keys
78
+ data_keys.select(&:required?).map(&:name)
79
+ end
66
80
  end
67
81
  end
68
82
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Thing::Product
5
+ # https://developer.dji.com/doc/cloud-api-tutorial/en/server-api-reference/mqtt/thing-model/gateway/dock/organization.html#search-for-the-organization-information-that-device-bound-to
6
+ class AirportOrganizationGetRequestsMessage < RequestsMessage
7
+ attribute :_method, Types::String.enum("airport_organization_get")
8
+
9
+ attribute :data do
10
+ attribute :device_binding_code, Types::String
11
+ attribute :organization_id, Types::String
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Thing::Product
5
+ # https://developer.dji.com/doc/cloud-api-tutorial/en/server-api-reference/mqtt/thing-model/gateway/dock/organization.html#search-for-the-organization-information-that-device-bound-to
6
+ class AirportOrganizationGetRequestsReplyMessage < Message
7
+ def self.build_for(airport_organization_get_message, output:, result: 0)
8
+ new(
9
+ _method: airport_organization_get_message._method,
10
+ tid: airport_organization_get_message.tid,
11
+ bid: airport_organization_get_message.bid,
12
+ timestamp: Time.now.strftime("%s%L").to_i,
13
+ data: {
14
+ result: result,
15
+ output: output
16
+ }
17
+ )
18
+ end
19
+
20
+ attribute :tid, Types::UUID
21
+ attribute :bid, Types::UUID
22
+ attribute :timestamp, Types::Timestamp
23
+
24
+ attribute :_method, Types::String.enum("airport_organization_get")
25
+
26
+ attribute :data do
27
+ attribute :result, Types::Integer
28
+ attribute :output do
29
+ attribute :organization_name, Types::String
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,199 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Thing::Product
5
+ class DockOsdMessage < OsdMessage
6
+ schema schema.strict
7
+
8
+ STABLE_DATA_ATTRIBUTES = %i[
9
+ drc_state
10
+ drone_in_dock
11
+ job_number
12
+ ]
13
+
14
+ attribute :data do
15
+ include Mixins::LatitudeConditional
16
+ include Mixins::LongitudeConditional
17
+ include Mixins::TemperatureConditional
18
+
19
+ attribute? :acc_time, Types::Integer
20
+ attribute? :activation_time, Types::Integer
21
+
22
+ attribute? :backup_battery do
23
+ include Mixins::TemperatureConditional
24
+
25
+ attribute :switch, Types::Integer.enum(0, 1)
26
+ attribute :voltage, Types::Integer
27
+ attribute :temperature, Types::Temperature
28
+ end
29
+
30
+ # {"0":"Disconnected","1":"Connecting","2":"Connected"}
31
+ attribute? :drc_state, Types::Integer.enum(0, 1, 2)
32
+
33
+ attribute? :drone_battery_maintenance_info do
34
+ attribute :batteries, Types::Array do
35
+ include Mixins::TemperatureConditional
36
+
37
+ attribute :index, Types::Integer
38
+ attribute :capacity_percent, Types::Integer
39
+ attribute :voltage, Types::Integer
40
+ attribute :temperature, Types::Temperature
41
+ end
42
+
43
+ # {"0":"Battery is not in heating or insulation","1":"Battery is in heating","2":"Battery is in insulation"}
44
+ attribute? :heat_state, Types::Integer.enum(0, 1, 2)
45
+
46
+ # {"0":"No need to maintenance","1":"Need maintenance","2":"Under maintenance"}
47
+ attribute? :maintenance_state, Types::Integer
48
+ attribute? :maintenance_time_left, Types::Integer
49
+ end
50
+
51
+ attribute? :drone_charge_state do
52
+ # {"0":"not charging","1":"charging"}
53
+ attribute :state, Types::Integer.enum(0, 1)
54
+
55
+ # {"min":"0","max":"100"}
56
+ attribute :capacity_percent, Types::Integer.constrained(gteq: 0, lteq: 100)
57
+ end
58
+ attribute? :drone_in_dock, Types::Integer.enum(0, 1)
59
+
60
+ attribute? :electric_supply_voltage, Types::Integer
61
+
62
+ attribute? :flighttask_prepare_capacity, Types::Integer
63
+ attribute? :flighttask_step_code, Types::Integer
64
+
65
+ attribute? :job_number, Types::Integer
66
+
67
+ attribute? :latitude, Types::Latitude
68
+ attribute? :longitude, Types::Longitude
69
+
70
+ attribute? :maintain_status do
71
+ attribute :maintain_status_array, Types::Array do
72
+ # {"0":"No maintenance","1":"Under maintenance"}
73
+ attribute :state, Types::Integer
74
+
75
+ # {"0":"No maintenance","1":"Drone basic maintenance","2":"Drone routine maintenance","3":"Drone deep maintenance","17":"Dock maintenance"}
76
+ attribute :last_maintain_type, Types::Integer
77
+
78
+ attribute :last_maintain_time, Types::Integer
79
+ attribute :last_maintain_work_sorties, Types::Integer
80
+ end
81
+ end
82
+
83
+ attribute? :media_file_detail do
84
+ attribute :remain_upload, Types::Integer
85
+ end
86
+
87
+ attribute? :network_state do
88
+ attribute :type, Types::Integer
89
+ attribute :quality, Types::Integer
90
+ attribute :rate, Types::JSON::Decimal
91
+ end
92
+
93
+ attribute? :sdr do
94
+ attribute :down_quality, Types::Integer
95
+ attribute :frequency_band, Types::JSON::Decimal
96
+ attribute :up_quality, Types::Integer
97
+ end
98
+
99
+ attribute? :wireless_link do
100
+ attribute :_4g_freq_band, Types::JSON::Decimal
101
+ attribute :_4g_gnd_quality, Types::Integer
102
+ attribute :_4g_link_state, Types::Integer
103
+ attribute :_4g_quality, Types::Integer
104
+ attribute :_4g_uav_quality, Types::Integer
105
+ attribute :dongle_number, Types::Integer
106
+ attribute :link_workmode, Types::Integer
107
+ attribute :sdr_freq_band, Types::JSON::Decimal
108
+ attribute :sdr_link_state, Types::Integer
109
+ attribute :sdr_quality, Types::Integer
110
+ end
111
+
112
+ attribute? :working_current, Types::Integer
113
+ attribute? :working_voltage, Types::Integer
114
+
115
+ # Weather
116
+
117
+ attribute? :height, Types::JSON::Decimal
118
+ attribute? :humidity, Types::Integer
119
+ attribute? :rainfall, Types::JSON::Decimal
120
+ attribute? :temperature, Types::Temperature
121
+ attribute? :wind_speed, Types::JSON::Decimal
122
+ attribute? :environment_temperature, Types::Temperature
123
+
124
+ attribute? :alternate_land_point do
125
+ attribute :latitude, Types::Latitude
126
+ attribute :longitude, Types::Longitude
127
+ attribute :height, Types::JSON::Decimal
128
+ attribute :safe_land_height, Types::JSON::Decimal
129
+ attribute :is_configured, Types::Integer.enum(0, 1)
130
+ end
131
+
132
+ attribute? :first_power_on, Types::Integer
133
+
134
+ attribute? :position_state do
135
+ # {"0":"Not calibrated","1":"Calibrated"}
136
+ attribute :is_calibration, Types::Integer.enum(0, 1)
137
+
138
+ # {"0":"Not start","1":"fixing","2":"fix successfully","3":"fix failed"}
139
+ attribute :is_fixed, Types::Integer.enum(0, 1, 2, 3)
140
+
141
+ attribute :quality, Types::Integer.constrained(gteq: 0, lteq: 5)
142
+ attribute :gps_number, Types::Integer
143
+ attribute :rtk_number, Types::Integer
144
+ end
145
+
146
+ attribute? :storage do
147
+ attribute :total, Types::Integer
148
+ attribute :used, Types::Integer
149
+ end
150
+
151
+ # {"0":"Idle","1":"On-site debugging","2":"Remote debugging","3":"Firmware upgrading","4":"Working"}
152
+ attribute? :mode_code, Types::Integer.enum(0, 1, 2, 3, 4)
153
+
154
+ attribute? :air_conditioner do
155
+ # {"0":"Idle mode (No cooling, heating, and dehumidification)","1":"Cooling mode","2":"Heating mode","3":"Dehumidification mode","4":"Cooling exit mode","5":"Heating exit mode","6":"Dehumidification exit mode","7":"Cooling preparation mode","8":"Heating preparation mode","9":"Dehumidification preparation mode"}
156
+ attribute :air_conditioner_state, Types::Integer.enum(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
157
+ attribute :switch_time, Types::Integer
158
+ end
159
+
160
+ # {"0":"Closed","1":"Opened"}
161
+ attribute? :alarm_state, Types::Integer.enum(0, 1)
162
+
163
+ # {"1":"Planned storage strategy of battery","2":"Emergency storage strategy of battery"}
164
+ attribute? :battery_store_mode, Types::Integer.enum(1, 2)
165
+
166
+ # {"0":"Closed","1":"Opened","2":"Half-open","3":"Cover state is abnormal"}
167
+ attribute? :cover_state, Types::Integer.enum(0, 1, 2, 3)
168
+
169
+ # {"0":"Closed","1":"Opened"}
170
+ attribute? :emergency_stop_state, Types::Integer.enum(0, 1)
171
+
172
+ # {"0":"Closed","1":"Opened","2":"Half-open","3":"Putter state is abnormal"}
173
+ attribute? :putter_state, Types::Integer.enum(0, 1, 2, 3)
174
+
175
+ # {"0":"Closed","1":"Opened"}
176
+ attribute? :supplement_light_state, Types::Integer.enum(0, 1)
177
+
178
+ attribute? :sub_device do
179
+ attribute? :device_sn, Types::String
180
+ attribute? :device_model_key, Types::String
181
+
182
+ # {"0":"Offline","1":"Online"}
183
+ attribute :device_online_status, Types::Integer.enum(0, 1)
184
+
185
+ # {"0":"Not paired","1":"Paired"}
186
+ attribute :device_paired, Types::Integer.enum(0, 1)
187
+ end
188
+
189
+ def drone_in_dock?
190
+ drone_in_dock == 1
191
+ end
192
+
193
+ def environment_temperature?
194
+ environment_temperature && !Types::InvalidTemperature.valid?(environment_temperature)
195
+ end
196
+ end
197
+ end
198
+ end
199
+ end
@@ -3,19 +3,42 @@
3
3
  module DjiMqttConnect
4
4
  module Thing::Product
5
5
  class DroneOsdMessage < OsdMessage
6
+ STABLE_DATA_ATTRIBUTES = %i[
7
+ mode_code
8
+ gear
9
+ horizontal_speed
10
+ vertical_speed
11
+ latitude
12
+ longitude
13
+ height
14
+ elevation
15
+ attitude_head
16
+ attitude_pitch
17
+ attitude_roll
18
+ home_distance
19
+ wind_direction
20
+ wind_speed
21
+ ]
22
+
6
23
  attribute :data do
24
+ include Mixins::LatitudeConditional
25
+ include Mixins::LongitudeConditional
26
+
7
27
  attribute :attitude_head, Types::JSON::Decimal
8
28
  attribute :attitude_pitch, Types::JSON::Decimal
9
29
  attribute :attitude_roll, Types::JSON::Decimal
10
30
  attribute :battery do
11
31
  attribute :batteries, Types::Array do
32
+ include Mixins::TemperatureConditional
33
+
12
34
  attribute :capacity_percent, Types::Integer
13
35
  attribute :firmware_version, Types::String
36
+ attribute? :high_voltage_storage_days, Types::Integer
14
37
  attribute :index, Types::Integer
15
38
  attribute :loop_times, Types::Integer
16
39
  attribute :sn, Types::String
17
40
  attribute :sub_type, Types::DeviceSubType
18
- attribute :temperature, Types::JSON::Decimal
41
+ attribute :temperature, Types::Temperature
19
42
  attribute :type, Types::DeviceType
20
43
  attribute :voltage, Types::Integer
21
44
  end
@@ -24,15 +47,21 @@ module DjiMqttConnect
24
47
  attribute :remain_flight_time, Types::Integer
25
48
  attribute :return_home_power, Types::Integer
26
49
  end
27
- attribute :distance_limit_status do
50
+ attribute? :distance_limit_status do
28
51
  attribute :distance_limit, Types::Integer
29
- attribute :state, Types::Integer
52
+
53
+ # {"0":"Not reached","1":"Reached"}
54
+ attribute? :is_near_distance_limit, Types::Integer.enum(0, 1)
55
+
56
+ # {"0":"Not set","1":"Have been set"}
57
+ attribute :state, Types::Integer.enum(0, 1)
30
58
  end
31
59
  attribute :elevation, Types::JSON::Decimal
60
+
32
61
  attribute :firmware_version, Types::String
33
62
  attribute :gear, Types::Integer
34
63
  attribute :height, Types::JSON::Decimal
35
- attribute :height_limit, Types::JSON::Decimal
64
+ attribute? :height_limit, Types::JSON::Decimal
36
65
  attribute :home_distance, Types::JSON::Decimal
37
66
  attribute :horizontal_speed, Types::JSON::Decimal
38
67
  attribute :latitude, Types::Latitude
@@ -44,24 +73,99 @@ module DjiMqttConnect
44
73
  attribute :quality, Types::Integer
45
74
  attribute :rtk_number, Types::Integer
46
75
  end
47
- attribute :storage do
76
+ attribute? :storage do
48
77
  attribute :total, Types::Integer
49
78
  attribute :used, Types::Integer
50
79
  end
51
80
  attribute :total_flight_distance, Types::JSON::Decimal
52
81
  attribute :total_flight_time, Types::JSON::Decimal
53
- attribute :track_id, Types::String
82
+ attribute? :track_id, Types::String
54
83
  attribute :vertical_speed, Types::JSON::Decimal
55
84
  attribute :wind_direction, Types::JSON::Decimal
56
85
  attribute :wind_speed, Types::JSON::Decimal
57
86
 
58
- def latitude?
59
- !Types::NullInteger.valid?(latitude)
87
+ # M30 Fields
88
+
89
+ attribute? :cameras, Types::Array do
90
+ # {"0":"Photo taking","1":"Recording"}
91
+ attribute :camera_mode, Types::Integer.enum(0, 1)
92
+
93
+ # {"min":2,"max":20}
94
+ attribute :ir_zoom_factor, Types::JSON::Decimal
95
+
96
+ attribute :liveview_world_region do
97
+ attribute :bottom, Types::JSON::Decimal.constrained(gteq: 0, lteq: 1)
98
+ attribute :left, Types::JSON::Decimal.constrained(gteq: 0, lteq: 1)
99
+ attribute :right, Types::JSON::Decimal.constrained(gteq: 0, lteq: 1)
100
+ attribute :top, Types::JSON::Decimal.constrained(gteq: 0, lteq: 1)
101
+ end
102
+
103
+ attribute :payload_index, Types::String
104
+
105
+ # {"0":"Idle","1":"Taking photo"}
106
+ attribute :photo_state, Types::Integer.enum(0, 1)
107
+
108
+ # {"0":"Idle","1":"Recording"}
109
+ attribute :recording_state, Types::Integer.enum(0, 1)
110
+
111
+ # {"unit":"s"}
112
+ attribute :record_time, Types::Integer
113
+
114
+ attribute :remain_photo_num, Types::Integer
115
+
116
+ # {"unit":"s"}
117
+ attribute :remain_record_duration, Types::Integer
118
+
119
+ # {"min":2,"max":200}
120
+ attribute :zoom_factor, Types::JSON::Decimal
60
121
  end
61
122
 
62
- def longitude?
63
- !Types::NullInteger.valid?(longitude)
123
+ # {"0":"Continue to execute the wayline task","1":"Exit the wayline task, and execute the remote controller out of control action."}
124
+ attribute? :exit_wayline_when_rc_lost, Types::Integer.enum(0, 1)
125
+
126
+ attribute? :is_near_area_limit, Types::Integer.enum(0, 1)
127
+
128
+ # {"0":"Not reached","1":"Reached"}
129
+ attribute? :is_near_height_limit, Types::Integer.enum(0, 1)
130
+
131
+ attribute? :maintain_status do
132
+ attribute :maintain_status_array, Types::Array do
133
+ attribute :last_maintain_flight_sorties, Types::Integer
134
+
135
+ # {"unit":"hour"}
136
+ attribute :last_maintain_flight_time, Types::Integer
137
+
138
+ attribute :last_maintain_time, Types::Integer
139
+
140
+ # {"0":"No maintenance","1":"Drone basic maintenance","2":"Drone routine maintenance","3":"Drone deep maintenance","17":"Dock maintenance"}
141
+ attribute :last_maintain_type, Types::Integer.enum(0, 1, 2, 3, 17)
142
+
143
+ # {"0":"No maintenance","1":"Under maintenance"}
144
+ attribute :state, Types::Integer.enum(0, 1)
145
+ end
64
146
  end
147
+
148
+ # {"0":"Off","1":"On"}
149
+ attribute? :night_lights_state, Types::Integer.enum(0, 1)
150
+
151
+ attribute? :obstacle_avoidance do
152
+ # {"0":"Close","1":"Open"}
153
+ attribute :horizon, Types::Integer.enum(0, 1)
154
+
155
+ # {"0":"Close","1":"Open"}
156
+ attribute :upside, Types::Integer.enum(0, 1)
157
+
158
+ # {"0":"Close","1":"Open"}
159
+ attribute :downside, Types::Integer.enum(0, 1)
160
+ end
161
+
162
+ # {"0":"Hovering","1":"Landing","2":"Returning to home"}
163
+ attribute? :rc_lost_action, Types::Integer.enum(0, 1, 2)
164
+
165
+ # {"unit":"m","min":20,"max":500}
166
+ attribute? :rth_altitude, Types::Integer
167
+
168
+ attribute? :total_flight_sorties, Types::Integer
65
169
  end
66
170
  end
67
171
  end
@@ -4,6 +4,9 @@ module DjiMqttConnect
4
4
  module Thing::Product
5
5
  class RemoteOsdMessage < OsdMessage
6
6
  attribute :data do
7
+ include Mixins::LatitudeConditional
8
+ include Mixins::LongitudeConditional
9
+
7
10
  attribute :capacity_percent, Types::Integer
8
11
  attribute :latitude, Types::Latitude
9
12
  attribute :live_status do
@@ -14,7 +17,7 @@ module DjiMqttConnect
14
17
  end
15
18
  attribute :longitude, Types::Longitude
16
19
  attribute :transmission_signal_quality, Types::Integer
17
- attribute :wireless_link do
20
+ attribute? :wireless_link do
18
21
  attribute :_4g_freq_band, Types::JSON::Decimal
19
22
  attribute :_4g_gnd_quality, Types::Integer
20
23
  attribute :_4g_link_state, Types::Integer
@@ -31,14 +34,6 @@ module DjiMqttConnect
31
34
  attribute :frequency_band, Types::Integer
32
35
  attribute :upward_quality, Types::Integer
33
36
  end
34
-
35
- def latitude?
36
- !Types::NullInteger.valid?(latitude)
37
- end
38
-
39
- def longitude?
40
- !Types::NullInteger.valid?(longitude)
41
- end
42
37
  end
43
38
  end
44
39
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Thing::Product
5
+ # https://developer.dji.com/doc/cloud-api-tutorial/en/server-api-reference/mqtt/thing-model/gateway/dock/file.html#obtain-upload-temporary-credentials
6
+ class StorageConfigGetRequestsMessage < RequestsMessage
7
+ attribute :_method, Types::String.enum("storage_config_get")
8
+
9
+ attribute :data do
10
+ attribute :module, Types::Integer.enum(0)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Thing::Product
5
+ # https://developer.dji.com/doc/cloud-api-tutorial/en/server-api-reference/mqtt/thing-model/gateway/dock/file.html#obtain-upload-temporary-credentials
6
+ class StorageConfigGetRequestsReplyMessage < Message
7
+ def self.build_for(storage_config_get_message, output:, result: 0)
8
+ new(
9
+ _method: storage_config_get_message._method,
10
+ tid: storage_config_get_message.tid,
11
+ bid: storage_config_get_message.bid,
12
+ timestamp: Time.now.strftime("%s%L").to_i,
13
+ data: {
14
+ result: result,
15
+ output: output
16
+ }
17
+ )
18
+ end
19
+
20
+ attribute :tid, Types::UUID
21
+ attribute :bid, Types::UUID
22
+ attribute :timestamp, Types::Timestamp
23
+
24
+ attribute :_method, Types::String.enum("storage_config_get")
25
+
26
+ attribute :data do
27
+ attribute :result, Types::Integer
28
+ attribute :output do
29
+ attribute :bucket, Types::String
30
+ attribute :credentials do
31
+ attribute :access_key_id, Types::String
32
+ attribute :access_key_secret, Types::String
33
+ attribute :expire, Types::Integer
34
+ attribute :security_token, Types::String
35
+ end
36
+ attribute :endpoint, Types::String
37
+ attribute :provider, Types::String
38
+ attribute :region, Types::String
39
+ attribute :object_key_prefix, Types::String
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Mixins
5
+ # Provides a conditional that returns false for nil for invalid latitude values
6
+ module LatitudeConditional
7
+ def latitude?
8
+ latitude && !Types::NullInteger.valid?(latitude)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Mixins
5
+ # Provides a conditional that returns false for nil for invalid longitude values
6
+ module LongitudeConditional
7
+ def longitude?
8
+ longitude && !Types::NullInteger.valid?(longitude)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DjiMqttConnect
4
+ module Mixins
5
+ # Provides a conditional that returns false for nil or excessive values (invalid data)
6
+ module TemperatureConditional
7
+ def temperature?
8
+ temperature && !Types::InvalidTemperature.valid?(temperature)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -16,7 +16,14 @@ module DjiMqttConnect
16
16
  message = status_marshal.load(raw_message)
17
17
 
18
18
  logger.info("Received #{message} from #{device_identifier}")
19
- broadcast(message._method.to_sym, device_identifier, message)
19
+
20
+ if message.instance_of?(StatusMessage)
21
+ # Broadcast an unsupported message event
22
+ broadcast(:unsupported_message, topic, raw_message)
23
+ else
24
+ # Build event name and broadcast (i.e. ::UpdateTopoStatusMessage => update_topo)
25
+ broadcast(message._method.to_sym, device_identifier, message)
26
+ end
20
27
  rescue ParseError => error
21
28
  broadcast(:parse_error, error, topic, raw_message)
22
29
  end
@@ -17,9 +17,14 @@ module DjiMqttConnect
17
17
 
18
18
  logger.info("Received #{message} from #{device_identifier}")
19
19
 
20
- # Build event name and broadcast (i.e. ::RemoteOsdMessage => remote_osd_update)
21
- event_name = message.class.name.demodulize.sub(/Message\z/, "Update").underscore.to_sym
22
- broadcast(event_name, device_identifier, message)
20
+ if message.instance_of?(OsdMessage)
21
+ # Broadcast an unsupported message event
22
+ broadcast(:unsupported_message, topic, raw_message)
23
+ else
24
+ # Build event name and broadcast (i.e. ::RemoteOsdMessage => remote_osd_update)
25
+ event_name = message.class.name.demodulize.sub(/Message\z/, "Update").underscore.to_sym
26
+ broadcast(event_name, device_identifier, message)
27
+ end
23
28
  rescue ParseError => error
24
29
  broadcast(:parse_error, error, topic, raw_message)
25
30
  end
@@ -16,7 +16,14 @@ module DjiMqttConnect
16
16
  message = requests_marshal.load(raw_message)
17
17
 
18
18
  logger.info("Received #{message} from #{gateway_sn}")
19
- broadcast(message._method.to_sym, gateway_sn, message)
19
+
20
+ if message.instance_of?(RequestsMessage)
21
+ # Broadcast an unsupported message event
22
+ broadcast(:unsupported_message, topic, raw_message)
23
+ else
24
+ # Build event name and broadcast (i.e. ::ConfigRequestsMessage => config)
25
+ broadcast(message._method.to_sym, gateway_sn, message)
26
+ end
20
27
  rescue ParseError => error
21
28
  broadcast(:parse_error, error, topic, raw_message)
22
29
  end
@@ -24,5 +24,8 @@ module DjiMqttConnect
24
24
  DeviceDomain = Types::Coercible::Integer # dock returns this value as string
25
25
  DeviceType = Types::Integer
26
26
  DeviceSubType = Types::Integer
27
+
28
+ InvalidTemperature = Types::Integer.constrained(gteq: 1300) # maximum temp of k-type thermocouple, errors are usually 30K+
29
+ Temperature = InvalidTemperature | Types::JSON::Decimal
27
30
  end
28
31
  end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/keys"
4
+
5
+ module DjiMqttConnect
6
+ module Utils
7
+ # Sanitizes MQTT messages to remove any personally-identifiable information
8
+ class MessageSanitizer
9
+ DEFAULT_LATITUDE = "-33.865143"
10
+ DEFAULT_LONGITUDE = "151.209900"
11
+
12
+ SECRET_KEYS = %w[app_id app_key app_license callsign device_secret nonce]
13
+
14
+ SERIAL_NUMBER_KEYS = %w[device_sn gateway sn]
15
+
16
+ TOPIC_REGEX = /\A.+\/.+\/(.+)\/.+/
17
+
18
+ def initialize(latitude: DEFAULT_LATITUDE, longitude: DEFAULT_LONGITUDE, secret_keys: SECRET_KEYS, serial_number_keys: SERIAL_NUMBER_KEYS, serial_number_aliases: {})
19
+ @latitude = latitude
20
+ @longitude = longitude
21
+
22
+ @secret_keys = secret_keys
23
+ @serial_number_keys = serial_number_keys
24
+
25
+ serial_aliases = serial_number_aliases.stringify_keys
26
+ @serial_number_generator = Hash.new do |h, k|
27
+ return "" if k.length == 0
28
+ h[k] = serial_aliases.fetch(k) { sprintf("%s%02d", "SERIAL", h.length + 1) }
29
+ end
30
+ serial_aliases.keys.each { |k| serial_number_generator[k] }
31
+ end
32
+
33
+ def sanitize_topic(topic)
34
+ topic.sub(TOPIC_REGEX) { |topic_match| topic_match.sub($1, serial_number_generator[$1]) }
35
+ end
36
+
37
+ def sanitize_message(message)
38
+ sanitized_message = sanitize_object(message)
39
+ strip_serial_numbers(sanitized_message)
40
+ end
41
+
42
+ private
43
+
44
+ attr_reader :latitude, :longitude
45
+ attr_reader :secret_keys, :serial_number_keys, :serial_number_generator
46
+
47
+ def sanitize_object(object)
48
+ case object
49
+ when Hash
50
+ serial_number_keys.each do |key|
51
+ if object.key?(key) && object[key].length > 0
52
+ object[key] = serial_number_generator[object[key]]
53
+ end
54
+ end
55
+ secret_keys.each do |key|
56
+ object[key] = key.upcase if object.key?(key)
57
+ end
58
+ if object.key?("latitude")
59
+ obj_latitude = object["latitude"]
60
+ object["latitude"] = (obj_latitude.is_a?(Integer) && obj_latitude.zero?) ? 0 : latitude
61
+ end
62
+ if object.key?("longitude")
63
+ obj_longitude = object["longitude"]
64
+ object["longitude"] = (obj_longitude.is_a?(Integer) && obj_longitude.zero?) ? 0 : longitude
65
+ end
66
+
67
+ object.transform_values { |v| sanitize_object(v) }
68
+ when Array
69
+ object.map { |v| sanitize_object(v) }
70
+ else
71
+ object
72
+ end
73
+ end
74
+
75
+ # Strips known serial numbers from an object
76
+ def strip_serial_numbers(object)
77
+ case object
78
+ when Hash
79
+ object.transform_values { |v| strip_serial_numbers(v) }
80
+ when Array
81
+ object.map { |v| strip_serial_numbers(v) }
82
+ when String
83
+ object.split("-").map { |s| serial_number_generator.fetch(s, s) }.join("-")
84
+ else
85
+ object
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/array/wrap"
4
+
5
+ module DjiMqttConnect
6
+ module Utils
7
+ # Generates a simple message schema from a mqtt message
8
+ #
9
+ # Schema is simply the class name of any element that is not a Hash or Array
10
+ class MessageSchemaGenerator
11
+ def initialize(retain_attributes: [])
12
+ @retain_attributes = Array.wrap(retain_attributes)
13
+ end
14
+
15
+ def generate(message)
16
+ case message
17
+ when Hash
18
+ retain_values = retain_attributes.each_with_object({}) do |attribute, hash|
19
+ next unless message.key?(attribute)
20
+
21
+ attribute_value = message[attribute]
22
+ next if attribute_value.is_a?(Hash) || attribute_value.is_a?(Array)
23
+
24
+ hash[attribute] = "#{attribute_value.class.name}:#{attribute_value}"
25
+ end
26
+ message.transform_values { |v| generate(v) }.merge(retain_values)
27
+ when Array
28
+ message.map { |v| generate(v) }
29
+ else
30
+ message.class.name
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :retain_attributes
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
4
+
5
+ module DjiMqttConnect
6
+ module Utils
7
+ # Generates anonymised fixture data from MQTTX JSON Export Dumps
8
+ class MqttxFixtureDataGenerator
9
+ def self.from_file(file_path, **sanitizer_args)
10
+ raw_data = File.read(file_path)
11
+ new JSON.parse(raw_data), message_sanitizer: MessageSanitizer.new(**sanitizer_args)
12
+ end
13
+
14
+ def initialize(mqttx_data, message_sanitizer:)
15
+ @mqttx_data = mqttx_data
16
+ @message_sanitizer = message_sanitizer
17
+ end
18
+
19
+ # Generates fixture data using ALL found messages in the MQTTX export
20
+ #
21
+ # # Output is:
22
+ # <topic 1>: <message 1 as json>
23
+ # <topic 1>: <message 2 as json>
24
+ def generate
25
+ extracted_messages.each_with_object(StringIO.new) do |(topic, message), builder|
26
+ builder.puts [topic, message.to_json].join(": ")
27
+ end.string
28
+ end
29
+
30
+ # Generates fixture data using unique found messages in the MQTTX export
31
+ #
32
+ # A message is considered unique if the topic and schema does not match any other messages
33
+ #
34
+ # # Output is:
35
+ # <topic 1>: <message 1 as json>
36
+ def generate_unique(**schema_generator_args)
37
+ message_schema_generator = MessageSchemaGenerator.new(**schema_generator_args)
38
+
39
+ unique_messages = extracted_messages.each_with_object({}) do |(topic, message), found|
40
+ message_schema = message_schema_generator.generate(message)
41
+ found[[topic, message_schema]] ||= [topic, message]
42
+ end.values
43
+
44
+ unique_messages.each_with_object(StringIO.new) do |(topic, message), builder|
45
+ builder.puts [topic, message.to_json].join(": ")
46
+ end.string
47
+ end
48
+
49
+ private
50
+
51
+ attr_reader :mqttx_data, :message_sanitizer
52
+
53
+ def extracted_messages
54
+ return enum_for(:extracted_messages) unless block_given?
55
+
56
+ mqttx_data.each do |client_output|
57
+ client_messages = client_output["messages"]
58
+
59
+ client_messages.each do |message|
60
+ message_topic = message_sanitizer.sanitize_topic(message.fetch("topic"))
61
+ message_payload = JSON.parse message.fetch("payload")
62
+ yield(message_topic, message_sanitizer.sanitize_message(message_payload))
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DjiMqttConnect
4
- VERSION = "0.1.1.4"
4
+ VERSION = "0.1.2"
5
5
  end
@@ -34,15 +34,20 @@ module DjiMqttConnect
34
34
  module Product
35
35
  # Messages
36
36
  autoload :OsdMessage, "dji_mqtt_connect/messages/thing/product/osd_message"
37
+ autoload :DockOsdMessage, "dji_mqtt_connect/messages/thing/product/dock_osd_message"
37
38
  autoload :DroneOsdMessage, "dji_mqtt_connect/messages/thing/product/drone_osd_message"
38
39
  autoload :RemoteOsdMessage, "dji_mqtt_connect/messages/thing/product/remote_osd_message"
39
40
 
40
41
  autoload :AirportBindStatusRequestsMessage, "dji_mqtt_connect/messages/thing/product/airport_bind_status_requests_message"
42
+ autoload :AirportOrganizationGetRequestsMessage, "dji_mqtt_connect/messages/thing/product/airport_organization_get_requests_message"
41
43
  autoload :ConfigRequestsMessage, "dji_mqtt_connect/messages/thing/product/config_requests_message"
44
+ autoload :StorageConfigGetRequestsMessage, "dji_mqtt_connect/messages/thing/product/storage_config_get_requests_message"
42
45
  autoload :RequestsMessage, "dji_mqtt_connect/messages/thing/product/requests_message"
43
46
 
44
47
  autoload :AirportBindStatusRequestsReplyMessage, "dji_mqtt_connect/messages/thing/product/airport_bind_status_requests_reply_message"
48
+ autoload :AirportOrganizationGetRequestsReplyMessage, "dji_mqtt_connect/messages/thing/product/airport_organization_get_requests_reply_message"
45
49
  autoload :ConfigRequestsReplyMessage, "dji_mqtt_connect/messages/thing/product/config_requests_reply_message"
50
+ autoload :StorageConfigGetRequestsReplyMessage, "dji_mqtt_connect/messages/thing/product/storage_config_get_requests_reply_message"
46
51
 
47
52
  # Topics
48
53
  autoload :OsdTopicRepository, "dji_mqtt_connect/topics/thing/product/osd"
@@ -57,9 +62,19 @@ module DjiMqttConnect
57
62
  end
58
63
  end
59
64
 
65
+ # Mixinx
66
+ module Mixins
67
+ autoload :LatitudeConditional, "dji_mqtt_connect/mixins/latitude_conditional"
68
+ autoload :LongitudeConditional, "dji_mqtt_connect/mixins/longitude_conditional"
69
+ autoload :TemperatureConditional, "dji_mqtt_connect/mixins/temperature_conditional"
70
+ end
71
+
60
72
  # Utils
61
73
  module Utils
62
74
  autoload :MessageParsing, "dji_mqtt_connect/utils/message_parsing"
75
+ autoload :MessageSanitizer, "dji_mqtt_connect/utils/message_sanitizer"
76
+ autoload :MessageSchemaGenerator, "dji_mqtt_connect/utils/message_schema_generator"
77
+ autoload :MqttxFixtureDataGenerator, "dji_mqtt_connect/utils/mqttx_fixture_data_generator"
63
78
  end
64
79
 
65
80
  # Railties
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.1.4
4
+ version: 0.1.2
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-05 00:00:00.000000000 Z
11
+ date: 2023-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -103,6 +103,7 @@ files:
103
103
  - Gemfile.lock
104
104
  - README.md
105
105
  - Rakefile
106
+ - dji_mqtt_connect.gemspec
106
107
  - lib/dji_mqtt_connect.rb
107
108
  - lib/dji_mqtt_connect/client.rb
108
109
  - lib/dji_mqtt_connect/error.rb
@@ -119,12 +120,20 @@ files:
119
120
  - lib/dji_mqtt_connect/messages/sys/product/update_topo_status_reply_message.rb
120
121
  - lib/dji_mqtt_connect/messages/thing/product/airport_bind_status_requests_message.rb
121
122
  - lib/dji_mqtt_connect/messages/thing/product/airport_bind_status_requests_reply_message.rb
123
+ - lib/dji_mqtt_connect/messages/thing/product/airport_organization_get_requests_message.rb
124
+ - lib/dji_mqtt_connect/messages/thing/product/airport_organization_get_requests_reply_message.rb
122
125
  - lib/dji_mqtt_connect/messages/thing/product/config_requests_message.rb
123
126
  - lib/dji_mqtt_connect/messages/thing/product/config_requests_reply_message.rb
127
+ - lib/dji_mqtt_connect/messages/thing/product/dock_osd_message.rb
124
128
  - lib/dji_mqtt_connect/messages/thing/product/drone_osd_message.rb
125
129
  - lib/dji_mqtt_connect/messages/thing/product/osd_message.rb
126
130
  - lib/dji_mqtt_connect/messages/thing/product/remote_osd_message.rb
127
131
  - lib/dji_mqtt_connect/messages/thing/product/requests_message.rb
132
+ - lib/dji_mqtt_connect/messages/thing/product/storage_config_get_requests_message.rb
133
+ - lib/dji_mqtt_connect/messages/thing/product/storage_config_get_requests_reply_message.rb
134
+ - lib/dji_mqtt_connect/mixins/latitude_conditional.rb
135
+ - lib/dji_mqtt_connect/mixins/longitude_conditional.rb
136
+ - lib/dji_mqtt_connect/mixins/temperature_conditional.rb
128
137
  - lib/dji_mqtt_connect/railtie.rb
129
138
  - lib/dji_mqtt_connect/railties/message_serializer.rb
130
139
  - lib/dji_mqtt_connect/topic_repository.rb
@@ -135,6 +144,9 @@ files:
135
144
  - lib/dji_mqtt_connect/topics/thing/product/requests_reply.rb
136
145
  - lib/dji_mqtt_connect/types.rb
137
146
  - lib/dji_mqtt_connect/utils/message_parsing.rb
147
+ - lib/dji_mqtt_connect/utils/message_sanitizer.rb
148
+ - lib/dji_mqtt_connect/utils/message_schema_generator.rb
149
+ - lib/dji_mqtt_connect/utils/mqttx_fixture_data_generator.rb
138
150
  - lib/dji_mqtt_connect/version.rb
139
151
  - sig/dji_mqtt_connect.rbs
140
152
  homepage: https://github.com/sphere-drones/dji_mqtt_connect