aws_iot_device 0.1.5 → 1.0.0

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.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/README.md +155 -148
  4. data/aws_iot_device.gemspec +11 -11
  5. data/codeclimate.yml +6 -0
  6. data/lib/aws_iot_device.rb +2 -1
  7. data/lib/aws_iot_device/mqtt_adapter.rb +1 -2
  8. data/lib/aws_iot_device/mqtt_adapter/client.rb +74 -6
  9. data/lib/aws_iot_device/mqtt_adapter/paho_mqtt_adapter.rb +207 -0
  10. data/lib/aws_iot_device/mqtt_adapter/ruby_mqtt_adapter.rb +10 -4
  11. data/lib/aws_iot_device/mqtt_shadow_client.rb +1 -0
  12. data/lib/aws_iot_device/mqtt_shadow_client/mqtt_manager.rb +133 -67
  13. data/lib/aws_iot_device/mqtt_shadow_client/shadow_action_manager.rb +229 -146
  14. data/lib/aws_iot_device/mqtt_shadow_client/shadow_client.rb +78 -20
  15. data/lib/aws_iot_device/mqtt_shadow_client/shadow_topic_manager.rb +51 -26
  16. data/lib/aws_iot_device/mqtt_shadow_client/topic_builder.rb +15 -30
  17. data/lib/aws_iot_device/version.rb +1 -1
  18. data/samples/config_shadow.rb +72 -0
  19. data/samples/mqtt_client_samples/mqtt_client_samples.rb +7 -59
  20. data/samples/shadow_action_samples/sample_shadow_action_update.rb +7 -61
  21. data/samples/shadow_client_samples/samples_shadow_client_block.rb +25 -0
  22. data/samples/shadow_client_samples/samples_shadow_client_delete.rb +9 -58
  23. data/samples/shadow_client_samples/samples_shadow_client_description.rb +64 -0
  24. data/samples/shadow_client_samples/samples_shadow_client_get.rb +11 -62
  25. data/samples/shadow_client_samples/samples_shadow_client_getting_started.rb +22 -0
  26. data/samples/shadow_client_samples/samples_shadow_client_update.rb +7 -58
  27. data/samples/shadow_topic_samples/sample_topic_manager.rb +10 -61
  28. metadata +71 -16
  29. data/lib/aws_iot_device/mqtt_adapter/mqtt_adapter.rb +0 -139
@@ -0,0 +1,207 @@
1
+ require 'paho-mqtt'
2
+
3
+ module AwsIotDevice
4
+ module MqttAdapter
5
+ class PahoMqttAdapter
6
+
7
+ def initialize(*args)
8
+ @client = PahoMqtt::Client.new(*args)
9
+ end
10
+
11
+ def client_id
12
+ @client.client_id
13
+ end
14
+
15
+ def connect(*args, &block)
16
+ if args.last.is_a?(Hash)
17
+ attr = args.last
18
+ attr.each_pair do |k, v|
19
+ if [:host, :port, :keep_alive, :persistent].include?(k)
20
+ @client.send("#{k}=", v)
21
+ else
22
+ raise ArgumentError, "Parameter error, invalid paramater \"#{k}\" for connect with paho-mqtt"
23
+ end
24
+ end
25
+ end
26
+ @client.connect
27
+ if block_given?
28
+ begin
29
+ yield(self)
30
+ ensure
31
+ @mqtt_client.disconnect
32
+ end
33
+ end
34
+ end
35
+
36
+ def publish(topic, payload="", retain=false, qos=0)
37
+ @client.publish(topic, payload, retain, qos)
38
+ end
39
+
40
+ def loop_start
41
+ Thread.new { loop_forever }
42
+ end
43
+
44
+ def loop_stop(thread)
45
+ thread.join
46
+ end
47
+
48
+ def loop_forever
49
+ loop do
50
+ @client.mqtt_loop
51
+ end
52
+ end
53
+
54
+ def mqtt_loop
55
+ @client.mqtt_loop
56
+ end
57
+
58
+ def loop_read
59
+ @client.loop_read
60
+ end
61
+
62
+ def loop_write
63
+ @client.loop_write
64
+ end
65
+
66
+ def loop_misc
67
+ @client.loop_misc
68
+ end
69
+
70
+ def get(topic=nil, &block)
71
+ @client.loop_read(1)
72
+ end
73
+
74
+ def get_packet(topic=nil, &block)
75
+ @client.loop_read(1)
76
+ end
77
+
78
+ def generate_client_id
79
+ @client.generate_client_id
80
+ end
81
+
82
+ def disconnect(send_msg)
83
+ @client.disconnect(send_msg)
84
+ end
85
+
86
+ def connected?
87
+ @client.connected?
88
+ end
89
+
90
+ def subscribe(topic, qos)
91
+ @client.subscribe([topic, qos])
92
+ end
93
+
94
+ def subscribe_bunch(topics)
95
+ @client.subscribe(topics)
96
+ end
97
+
98
+ def unsubscribe(topic)
99
+ @client.unsubscribe(topic)
100
+ end
101
+
102
+ def unsubscribe_bunch(topics)
103
+ @client.unsubscribe(topics)
104
+ end
105
+
106
+ def set_tls_ssl_context(ca_cert=nil, cert=nil, key=nil)
107
+ @client.config_ssl_context(cert, key, ca_cert)
108
+ end
109
+
110
+ def add_callback_filter_topic(topic, callback=nil, &block)
111
+ @client.add_topic_callback(topic, callback, &block)
112
+ end
113
+
114
+ def remove_callback_filter_topic(topic)
115
+ @client.remove_topic_callback(topic)
116
+ end
117
+
118
+ def on_connack=(callback)
119
+ @client.on_connack = callback
120
+ end
121
+
122
+ def on_suback=(callback)
123
+ @client.on_suback = callback
124
+ end
125
+
126
+ def on_unsuback=(callback)
127
+ @client.on_unsuback = callback
128
+ end
129
+
130
+ def on_puback=(callback)
131
+ @client.on_puback = callback
132
+ end
133
+
134
+ def on_pubrec=(callback)
135
+ @client.on_pubrec = callback
136
+ end
137
+
138
+ def on_pubrel=(callback)
139
+ @client.on_pubrel = callback
140
+ end
141
+
142
+ def on_pubcomp=(callback)
143
+ @client.on_pubcomp = callback
144
+ end
145
+
146
+ def on_message=(callback)
147
+ @client.on_message = callback
148
+ end
149
+
150
+ def on_connack(&block)
151
+ @client.on_connack(&block)
152
+ end
153
+
154
+ def on_suback(&block)
155
+ @client.on_suback(&block)
156
+ end
157
+
158
+ def on_unsuback(&block)
159
+ @client.on_unsuback(&block)
160
+ end
161
+
162
+ def on_puback(&block)
163
+ @client.on_puback(&block)
164
+ end
165
+
166
+ def on_pubrec(&block)
167
+ @client.on_pubrec(&block)
168
+ end
169
+
170
+ def on_pubrel(&block)
171
+ @client.on_pubrel(&block)
172
+ end
173
+
174
+ def on_pubcomp(&block)
175
+ @client.on_pubcomp(&block)
176
+ end
177
+
178
+ def on_message(&block)
179
+ @client.on_message(&block)
180
+ end
181
+
182
+ def host
183
+ @client.host
184
+ end
185
+
186
+ def host=(host)
187
+ @client.host = host
188
+ end
189
+
190
+ def port
191
+ @client.port
192
+ end
193
+
194
+ def port=(port)
195
+ @client.port = port
196
+ end
197
+
198
+ def ssl
199
+ @client.ssl
200
+ end
201
+
202
+ def ssl=(ssl)
203
+ @client.ssl = ssl
204
+ end
205
+ end
206
+ end
207
+ end
@@ -29,7 +29,7 @@ module AwsIotDevice
29
29
  end
30
30
 
31
31
  def connect(*args, &block)
32
- client = create_client(*args) if @client.nil?
32
+ @client = create_client(*args) if @client.nil?
33
33
  @client.connect(&block)
34
34
  loop_start
35
35
  end
@@ -87,7 +87,6 @@ module AwsIotDevice
87
87
  @client.port
88
88
  end
89
89
 
90
-
91
90
  def port=(port)
92
91
  @client.port = port
93
92
  end
@@ -134,7 +133,7 @@ module AwsIotDevice
134
133
  ### Fitlering message if matching to filtered topic
135
134
  topic = message.topic
136
135
  if @filtered_topics.key?(topic)
137
- callback = @filtered_topics[topic]
136
+ callback = @filtered_topics[topic]
138
137
  callback.call(message)
139
138
  else
140
139
  on_message_callback(message)
@@ -144,17 +143,24 @@ module AwsIotDevice
144
143
  end
145
144
 
146
145
  def loop_write
146
+ puts "loop_write is unavailable for ruby-mqtt client's"
147
147
  end
148
148
 
149
149
  def loop_misc
150
+ puts "loop_misc is unavailable for ruby-mqtt client's"
150
151
  end
151
152
 
152
153
  def on_message=(callback)
153
154
  @on_message = callback
154
155
  end
155
156
 
157
+ def on_message(&block)
158
+ @on_message = block if block_given?
159
+ @on_message
160
+ end
161
+
156
162
  def on_message_callback(message)
157
- if @on_message.is_a? Proc
163
+ if @on_message.is_a?(Proc) || @on_message.lambda?
158
164
  @on_message.call(message)
159
165
  end
160
166
  end
@@ -2,5 +2,6 @@ require 'aws_iot_device/mqtt_shadow_client/shadow_client'
2
2
 
3
3
  module AwsIotDevice
4
4
  module MqttShadowClient
5
+ ACTION_NAME = %w(get update delete delta).freeze
5
6
  end
6
7
  end
@@ -10,49 +10,32 @@ module AwsIotDevice
10
10
 
11
11
  attr_accessor :mqtt_operation_timeout_s
12
12
 
13
- attr_accessor :host
14
-
15
- attr_accessor :port
16
-
17
13
  attr_accessor :ssl
18
14
 
19
15
  def initialize(*args)
20
16
  @client = create_mqtt_adapter(*args)
17
+ @mqtt_operation_timeout_s = 2
21
18
  @mutex_publish = Mutex.new()
22
19
  @mutex_subscribe = Mutex.new()
23
20
  @mutex_unsubscribe = Mutex.new()
24
- @ssl_configured = false
25
-
26
- if args.last.is_a?(Hash)
27
- attr = args.pop
28
- attr.each_pair do |k, v|
29
- self.send("#{k}=", v)
30
- end
31
- end
32
-
33
- if need_ssl_configure?
34
- @client.set_tls_ssl_context(@ca_file, @cert, @key)
35
- @ssl_configured = true
36
- end
37
-
38
- ### Set the on_message's callback
39
- @client.on_message = Proc.new do |message|
40
- on_message_callback(message)
41
- end
42
21
  end
43
22
 
44
- def cert_file=(path)
45
- @cert = path
23
+ def host=(host)
24
+ @client.host = host
46
25
  end
47
26
 
48
- def key_file=(path)
49
- @key = path
27
+ def host
28
+ @client.host
50
29
  end
51
30
 
52
- def ca_file=(path)
53
- @ca_file = path
31
+ def port=(port)
32
+ @client.port = port
54
33
  end
55
34
 
35
+ def port
36
+ @client.port
37
+ end
38
+
56
39
  def client_id
57
40
  @client.client_id
58
41
  end
@@ -61,74 +44,157 @@ module AwsIotDevice
61
44
  @client = MqttAdapter::Client.new(*args)
62
45
  end
63
46
 
64
- def on_message_callback(message)
65
- puts "Received (with no custom callback registred) : "
66
- puts "------------------- Topic: #{message.topic}"
67
- puts "------------------- Payload: #{message.payload}"
68
- end
69
-
70
47
  def config_endpoint(host, port)
71
- if host.nil? || port.nil?
72
- raise "config_endpoint error: either host || port is undefined error"
73
- end
74
- @host = host
75
- @port = port
48
+ raise ArgumentError, "configure endpoint either host or port is nil" if host.nil? || port.nil?
49
+ @client.host = host
50
+ @client.port = port
76
51
  end
77
52
 
78
53
  def config_ssl_context(ca_file, key, cert)
79
- @ca_file = ca_file
80
- @key = key
81
- @cert = cert
82
- @client.set_tls_ssl_context(ca_file, cert, key)
54
+ self.ca_file = ca_file
55
+ self.key = key
56
+ self.cert = cert
57
+ @client.set_tls_ssl_context(@ca_file, @cert, @key)
83
58
  end
84
59
 
85
- def connect(keep_alive_interval=30, &block)
86
- if keep_alive_interval.nil? && keep_alive_interval.is_a(Integer)
87
- raise "connect error: keep_alive_interval cannot be a not nil Interger"
88
- end
89
-
90
- @client.host=(@host)
91
- @client.port=(@port)
60
+ def connect(*args, &block)
92
61
  ### Execute a mqtt opration loop in background for time period defined by mqtt_connection_timeout
93
- @client.connect(block)
62
+ @client.connect(*args, &block)
94
63
  end
95
64
 
96
65
  def disconnect
97
66
  @client.disconnect
98
67
  end
99
68
 
100
- def publish(topic, payload="", qos=0, retain=nil)
101
- if topic.nil?
102
- raise "publish error: topic cannot be nil"
103
- end
104
- @mutex_publish.synchronize{
105
- @client.publish(topic,payload,qos,retain)
69
+ def publish(topic, payload="", retain=nil, qos=0)
70
+ raise ArgumentError, "publish topic cannot be nil" if topic.nil?
71
+ @mutex_publish.synchronize {
72
+ @client.publish(topic, payload, retain, qos)
106
73
  }
107
74
  end
108
75
 
109
76
  def subscribe(topic, qos=0, callback=nil)
110
- if topic.nil?
111
- raise "subscribe error: topic cannot be nil"
112
- end
113
- ret = false
77
+ raise ArgumentError, "subscribe topic cannot be nil" if topic.nil?
114
78
  @mutex_subscribe.synchronize {
115
79
  @client.add_callback_filter_topic(topic, callback)
116
- @client.subscribe(topic)
80
+ @client.subscribe(topic, qos)
117
81
  }
118
82
  end
119
83
 
84
+ def subscribe_bunch(*topics)
85
+ @mutex_subscribe.synchronize {
86
+ topics.each do |topic|
87
+ @client.add_callback_filter_topic(topic.first, topic.pop) if !topic[2].nil? && topic[2].is_a?(Proc)
88
+ end
89
+ @client.subscribe_bunch(topics)
90
+ }
91
+ end
92
+
120
93
  def unsubscribe(topic)
121
- if topic.nil?
122
- raise "unsubscribe error: topic cannot be nil"
123
- end
94
+ raise ArgumentError, "unsubscribe topic cannot be nil" if topic.nil?
124
95
  @mutex_unsubscribe.synchronize{
125
96
  @client.remove_callback_filter_topic(topic)
126
97
  @client.unsubscribe(topic)
127
98
  }
128
99
  end
129
100
 
130
- def need_ssl_configure?
131
- !( @ca_file.nil? || @cert.nil? || @key.nil? ) && @ssl
101
+ def unsubscribe_bunch(*topics)
102
+ @mutex_unsubscribe.synchronize {
103
+ topics.each do |topic|
104
+ @client.remove_callback_filter_topic(topic)
105
+ end
106
+ @client.unsubscribe_bunch(topics)
107
+ }
108
+ end
109
+
110
+ def on_connack=(callback)
111
+ @client.on_connack = callback if paho_client?
112
+ end
113
+
114
+ def on_suback=(callback)
115
+ @client.on_suback = callback if paho_client?
116
+ end
117
+
118
+ def on_unsuback=(callback)
119
+ @client.on_unsuback = callback if paho_client?
120
+ end
121
+
122
+ def on_puback=(callback)
123
+ @client.on_puback = callback if paho_client?
124
+ end
125
+
126
+ def on_pubrec=(callback)
127
+ @client.on_pubrec = callback if paho_client?
128
+ end
129
+
130
+ def on_pubrel=(callback)
131
+ @client.on_pubrel = callback if paho_client?
132
+ end
133
+
134
+ def on_pubcomp=(callback)
135
+ @client.on_pubcomp = callback if paho_client?
136
+ end
137
+
138
+ def on_message=(callback)
139
+ @client.on_message = callback
140
+ end
141
+
142
+ def on_connack(&block)
143
+ @client.on_connack(&block) if paho_client?
144
+ end
145
+
146
+ def on_suback(&block)
147
+ @client.on_suback(&block) if paho_client?
148
+ end
149
+
150
+ def on_unsuback(&block)
151
+ @client.on_unsuback(&block) if paho_client?
152
+ end
153
+
154
+ def on_puback(&block)
155
+ @client.on_puback(&block) if paho_client?
156
+ end
157
+
158
+ def on_pubrec(&block)
159
+ @client.on_pubrec(&block) if paho_client?
160
+ end
161
+
162
+ def on_pubrel(&block)
163
+ @client.on_pubrel(&block) if paho_client?
164
+ end
165
+
166
+ def on_pubcomp(&block)
167
+ @client.on_pubcomp(&block) if paho_client?
168
+ end
169
+
170
+ def on_message(&block)
171
+ @client.on_message(&block)
172
+ end
173
+
174
+ def add_topic_callback(topic, callback, &block)
175
+ @client.add_callback_filter_topic(topic, callback, &block)
176
+ end
177
+
178
+ def remove_topic_callback(topic)
179
+ @client.remove_callback_filter_topic(topic)
180
+ end
181
+
182
+ def paho_client?
183
+ @client.adapter.class == MqttAdapter::PahoMqttAdapter
184
+ end
185
+
186
+ private
187
+
188
+ def cert=(path)
189
+ @cert = path
190
+ end
191
+
192
+ def key=(path)
193
+ @key = path
194
+ end
195
+
196
+ def ca_file=(path)
197
+ @ca_file = path
132
198
  end
133
199
  end
134
200
  end