-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathChapter060-Mobile-Messaging-MQTT.html
794 lines (594 loc) · 55.7 KB
/
Chapter060-Mobile-Messaging-MQTT.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
<section data-type="chapter" id="ch_mobile_mqtt" xmlns="http://www.w3.org/1999/xhtml">
<h1>Mobile Messaging with MQTT</h1>
<p class="lead">In this chapter, we will write an iOS application using the MQTTKit library to send and receive messages using<a contenteditable="false" data-primary="mobile messaging with MQTT" data-type="indexterm" id="mobmessMQTT"> </a> the MQTT protocol.<a contenteditable="false" data-primary="MQTT" data-secondary="mobile messaging with" data-type="indexterm" id="MQTTmobmess"> </a></p>
<p>In <a data-type="xref" href="#ch_introduction_mqtt_example">#ch_introduction_mqtt_example</a>, we described the Motions application (<a data-type="xref" href="img_mobile_mqtt_1">img_mobile_mqtt_1</a>). In this chapter, <a contenteditable="false" data-primary="mobile messaging with MQTT" data-secondary="Motions application (example)" data-type="indexterm"> </a>we will write the iOS application that broadcasts the device motion data and receives alert messages.</p>
<figure id="img_mobile_mqtt_1"><img alt="Diagram of the Motions+ iOS application" src="images/mawm_0601.png" />
<figcaption>Diagram of the Motions iOS application</figcaption>
</figure>
<div data-type="note">
<p>Throughout the chapter, we will show all the code required to run the application.</p>
<p>The whole application code can be retrieved from the <a href="http://bit.ly/mwm-code">GitHub repository</a> in the <em>mqtt/ios/</em> directory.</p>
</div>
<section data-type="sect1" id="__code_mqttkit_code">
<h1>MQTTKit</h1>
<p>This book uses the MQTTKit library for iOS (and Mac OS X) applications.<a contenteditable="false" data-primary="MQTTKit" data-type="indexterm"> </a> It is a modern Objective-C library that uses ARC and blocks to write messaging clients in a simple fashion.<a contenteditable="false" data-primary="Objective-C" data-secondary="MQTTKit library" data-type="indexterm"> </a> It is based on the <a href="http://mosquitto.org">Mosquitto</a> project that provides a lower-level C implementation of MQTT.</p>
<p>The source code of this library project is hosted on <a href="http://bit.ly/mwm-mqttkit">GitHub</a>.</p>
</section>
<section data-type="sect1" id="_create_the_code_motions_code_project_with_xcode">
<h1>Create the Motions Project with Xcode</h1>
<p>We will use <a href="http://bit.ly/apple-xcode">Xcode</a> to create the Locations iOS application.</p>
<p>After Xcode is installed and started, we select "Create a new Xcode project" from its launch<a contenteditable="false" data-primary="Xcode" data-secondary="creating Motions project" data-type="indexterm"> </a> screen.<a contenteditable="false" data-primary="mobile messaging with MQTT" data-secondary="Motions application (example)" data-tertiary="creating Motions project with Xcode" data-type="indexterm"> </a> The application will be composed of a single view, so we select the Single View Application template in iOS → Application from the template screen, as illustrated in <a data-type="xref" href="img_mobile_mqtt_125">img_mobile_mqtt_125</a>.</p>
<figure id="img_mobile_mqtt_125"><img alt="XCode template screen" src="images/mawm_0602.png" />
<figcaption>Select Single View Application from the template screen</figcaption>
</figure>
<p>We will call the project Motions and select to build it only for iPhone devices, as illustrated in <a data-type="xref" href="img_mobile_mqtt_2">img_mobile_mqtt_2</a>.</p>
<figure id="img_mobile_mqtt_2"><img alt="XCode project options screen" src="images/mawm_0603.png" />
<figcaption>XCode project options screen</figcaption>
</figure>
<p>Finally, we will save it in a folder on our machine.</p>
</section>
<section data-type="sect1" id="_create_the_podfile">
<h1>Create the Podfile</h1>
<p>We will again use CocoaPods to manage the project dependencies (as explained in <a data-type="xref" href="#ch_mobile_stomp_cocoapods">#ch_mobile_stomp_cocoapods</a> for the<a contenteditable="false" data-primary="mobile messaging with STOMP" data-secondary="creating the Podfile" data-type="indexterm"> </a> STOMP example).<a contenteditable="false" data-primary="CocoaPods library manager" data-type="indexterm"> </a></p>
<p>We close Xcode because CocoaPods will modify the project settings to import the dependencies.</p>
<p>We create a file named <em>Podfile</em> at the<a contenteditable="false" data-primary="Podfile, creating" data-secondary="for MQTT Motions application (example)" data-type="indexterm"> </a> root of the project (in the same directory as <em>Motions.xcodeproj</em>):</p>
<pre data-type="programlisting">
xcodeproj 'Motions.xcodeproj'
pod 'MQTTKit', :git => 'https://github.com/mobile-web-messaging/MQTTKit.git'
platform :ios, '5.0'</pre>
<p>After saving this file, run the <strong><code>pod install</code></strong> command:<a contenteditable="false" data-primary="pod install command" data-type="indexterm"></a></p>
<div data-type="example" id="ex_mobile_mqtt_2">
<h5>Install Motions dependencies</h5>
<pre data-type="programlisting">
$ pod install
Analyzing dependencies
Pre-downloading: `MQTTKit` from `https://github.com/mobile-web-messaging/MQTTKit.git`
Downloading dependencies
Installing MQTTKit (0.1.1)
Generating Pods project
Integrating client project
[!] From now on use `Motions.xcworkspace`.</pre>
</div>
<p>We can now open Xcode again, but we must do it using the <em>workspace</em> file named <em>Motions.xcworkspace</em>, and not <a contenteditable="false" data-primary="Xcode" data-secondary="opening Motions workspace file" data-type="indexterm"> </a>the <em>project</em> file named <em>Motions.xcodeproj</em> (<a data-type="xref" href="img_mobile_mqtt_3">img_mobile_mqtt_3</a>).</p>
<figure id="img_mobile_mqtt_3"><img alt="Open the workspace file" src="images/mawm_0604.png" />
<figcaption>Open the workspace file</figcaption>
</figure>
<p>First, we will verify that the project is set up correctly and that the application can run in the iOS simulator.</p>
<p>We will simulate the latest iPhone devices by selecting Product → Destination → iPhone Retina (4-inch 64-bit) from the Xcode menu bar.<a contenteditable="false" data-primary="iOS simulator" data-type="indexterm"> </a></p>
<!--
Command symbol is not displayed in PDF.
-->
<p>If we run the application by selecting Product → Run (or pressing <code>⌘+R</code>), the iOS simulator starts and opens the application, which is composed of a blank view. This confirms that the project and its dependencies are successfully compiled and launched.</p>
</section>
<section data-type="sect1" id="_identify_the_device">
<h1>Identify the Device</h1>
<p>This step is similar to the Locations iOS application <a contenteditable="false" data-primary="device IDs" data-type="indexterm"> </a>described in <a data-type="xref" href="#ch_mobile_stomp_deviceID">#ch_mobile_stomp_deviceID</a>.<a contenteditable="false" data-primary="mobile messaging with STOMP" data-secondary="identifying the device" data-type="indexterm"> </a></p>
<p>We will generate a unique identifier for the iOS device and display it in the view.</p>
<p>Click on <em>Main.storyboard</em> to open it. From the Object library, drag a Label on the View's window. Place it at the top of the view and change the text to "Device ID," as shown in <a data-type="xref" href="img_mobile_mqtt_4">img_mobile_mqtt_4</a>.</p>
<figure id="img_mobile_mqtt_4"><img alt="Add the Device ID label" src="images/mawm_0605.png" />
<figcaption>Add the Device ID label</figcaption>
</figure>
<p>We will again change its Font to System 13.0 and its Alignment to centered to fit the screen.</p>
<p>This label will be connected to a <code>deviceIDLabel</code> outlet property defined in the <code>MWMViewController</code> private interface in the <em>MWMViewController.m</em> file. We also add a <code>deviceID</code> string to store the device identifier:</p>
<pre data-code-language="objc" data-type="programlisting">
@interface MWMViewController ()
@property (weak, nonatomic) IBOutlet UILabel *deviceIDLabel;
@property (strong, nonatomic) NSString *deviceID;
@end</pre>
<p>Open the <em>Main.storyboard</em> and Ctrl-click on View Controller to see its connection panel. Drag from deviceIDLabel to the UILabel to connect it. See <a data-type="xref" href="img_mobile_mqtt_5">img_mobile_mqtt_5</a>.</p>
<figure id="img_mobile_mqtt_5"><img alt="Connect the deviceIDLabel outlet property to the device ID UILabel" src="images/mawm_0606.png" />
<figcaption>Connect the deviceIDLabel outlet property to the Device ID UILabel</figcaption>
</figure>
<p>The device identifier is generated in the <code>MWMViewController</code> implementation when the view is loaded and stored in the <code>deviceID</code> property. We also set the <code>deviceIDLabel</code>'s <code>text</code> to this identifier:</p>
<pre data-code-language="objc" data-type="programlisting">
- (void)viewDidLoad
{
[super viewDidLoad];
self.deviceID = [UIDevice currentDevice].identifierForVendor.UUIDString;
NSLog(@"Device identifier is %@", self.deviceID);
self.deviceIDLabel.text = self.deviceID;
}</pre>
</section>
<section data-type="sect1" id="_display_the_device_motions_values">
<h1>Display the Device Motions Values</h1>
<p>The device motion will be identified using the <a contenteditable="false" data-primary="pitch, roll, and yaw values" data-secondary="displaying in Motions application (example)" data-type="indexterm"> </a>pitch, roll, and yaw values. <a contenteditable="false" data-primary="mobile messaging with STOMP" data-secondary="displaying device motion values" data-type="indexterm"> </a>To have some graphical feedback as we move the device, we will add three <code>UILabel</code>s that show these three values.</p>
<p>Click on <em>Main.storyboard</em> to open it. From the Object library, drag three Labels on the View's window below the Device ID label. Change their respective text to "pitch," "roll," and "yaw," as illustrated in <a data-type="xref" href="img_mobile_mqtt_6">img_mobile_mqtt_6</a>.</p>
<figure id="img_mobile_mqtt_6"><img alt="Add three labels to display the device's pitch, roll and yaw values." src="images/mawm_0607.png" />
<figcaption>Add three labels to display the device’s pitch, roll, and yaw values</figcaption>
</figure>
<p>We create three outlet properties in the <code>MWMViewController</code> private interface for these labels:</p>
<pre data-code-language="objc" data-type="programlisting">
@interface MWMViewController ()
@property (weak, nonatomic) IBOutlet UILabel *deviceIDLabel;
@property (weak, nonatomic) IBOutlet UILabel *pitchLabel;
@property (weak, nonatomic) IBOutlet UILabel *rollLabel;
@property (weak, nonatomic) IBOutlet UILabel *yawLabel;
@property (strong, nonatomic) NSString *deviceID;
@end</pre>
<p>The next step is to connect the three labels in the <em>Main.storyboard</em> to these three outlet properties.</p>
<p>Open the <em>Main.storyboard</em> and Ctrl-click on View Controller to see its connection panel. Drag from its pitchLabel property to the corresponding pitch UILabel to connect it (see <a data-type="xref" href="img_mobile_mqtt_7">img_mobile_mqtt_7</a>).</p>
<figure id="img_mobile_mqtt_7"><img alt="Connect the pitchLabel outlet property to the pitch UILabel" src="images/mawm_0608.png" />
<figcaption>Connect the pitchLabel outlet property to the pitch UILabel</figcaption>
</figure>
<p>Repeat this operation for the <code>rollLabel</code> and <code>yawLabel</code> to connect them.</p>
<p>At this stage, the graphical objects are connected and we can capture the device motion to update these labels and then broadcast the motion data using MQTT.</p>
</section>
<section data-type="sect1" id="_capture_the_device_motions_with_code_coremotion_code_framework">
<h1>Capture the Device Motions with CoreMotion Framework</h1>
<p>iOS provides the <code>CoreMotion</code> framework to capture the <a contenteditable="false" data-primary="mobile messaging with STOMP" data-secondary="capturing device motions with CoreMotion framework" data-type="indexterm"> </a>motion of the devices.<a contenteditable="false" data-primary="CoreMotion framework" data-type="indexterm"> </a></p>
<p>We need to add it to the libraries linked by the application (see <a data-type="xref" href="add_cm_frame">add_cm_frame</a>). Click on the Motions project and then the Motions target. In the General tab, under the Linked Frameworks and Libraries section, click on the <code>+</code> button. In the selection window, type "CoreMotion," select CoreMotion.framework, and click on the Add button.</p>
<p>We can now use the CoreMotion framework by importing <em>CoreMotion/CoreMotion.h</em> at the top of the <em>CoreMotion/CoreMotion.h</em> file.</p>
<p>We will also define a <code>motionManager</code> property in the <code>MWMViewController</code> private interface to use <code>CoreMotion</code>:</p>
<pre data-code-language="objc" data-type="programlisting">
#import <CoreMotion/CoreMotion.h>
@interface MWMViewController ()
@property (strong, nonatomic) CMMotionManager *motionManager;
@end</pre>
<p>This <code>motionManager</code> is used to capture the device motions. We must create a new <code>CMMotionManager</code>, specify the interval of updates, and call its <code>startDeviceMotionUpdatesToQueue:withHandler:</code> method to get the device motion periodically in a block. We create a new <code>NSOperationQueue</code> to receive these updates on this queue.</p>
<figure id="add_cm_frame"><img alt="Add the CoreMotion framework" src="images/mawm_0609.png" />
<figcaption>Add the CoreMotion framework</figcaption>
</figure>
<p>The device motion is represented by a <code>CMDeviceMotion</code> object. In our example, we are interested only in its <code>attitude</code> property that contains the pitch, roll, and yaw value we want to broadcast. Their values are expressed in radians, so we will convert them in degrees to display them.</p>
<p>The block to receive motion updates is executed on the <code>NSOperationQueue</code> we created, so we cannot update the <code>UILabel</code> from it. We must instead create another block and call <code>dispatch_async</code> to execute the graphical changes on the UI main queue (which is retrieved by calling <code>dispatch_get_main_queue()</code>).</p>
<p>All this logic can be written in <code>viewDidLoad</code> so that the motion manager starts receiving updates when the view is loaded:</p>
<pre data-code-language="objc" data-type="programlisting">
- (void)viewDidLoad
{
[super viewDidLoad];
self.deviceID = [UIDevice currentDevice].identifierForVendor.UUIDString;
NSLog(@"Device identifier is %@", self.deviceID);
self.deviceIDLabel.text = self.deviceID;
self.motionManager = [[CMMotionManager alloc] init];
// get the device motion updates every second.
self.motionManager.deviceMotionUpdateInterval = 1;
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[self.motionManager startDeviceMotionUpdatesToQueue:queue
withHandler:^(CMDeviceMotion *motion,
NSError *error) {
if(!error) {
CMAttitude *attitude = motion.attitude;
dispatch_async(dispatch_get_main_queue(), ^{
// convert values from radians to degrees
double pitch = attitude.pitch * 180 / M_PI;
double roll = attitude.roll * 180 / M_PI;
double yaw = attitude.yaw * 180 / M_PI;
self.pitchLabel.text =
[NSString stringWithFormat:@"pitch: %.0f°", pitch];
self.rollLabel.text =
[NSString stringWithFormat:@"roll: %.0f°", roll];
self.yawLabel.text =
[NSString stringWithFormat:@"yaw: %.0f°", yaw];
});
}
}];
}
</pre>
<p>We also need to notify the <code>motionManager</code> that we no longer want to receive updates when the view is no longer used. We need to call its <code>stopDeviceMotionUpdates</code> method inside the view controller’s <code>dealloc</code> method:</p>
<pre data-code-language="objc" data-type="programlisting">
- (void)dealloc
{
[self.motionManager stopDeviceMotionUpdates];
}</pre>
<p>At this stage, if you run the Motions application on your iPhone and move it, the pitch, roll, and yaw labels will be updated to reflect the changes in the device motions (<a data-type="xref" href="img_mobile_mqtt_8">img_mobile_mqtt_8</a>).</p>
<div data-type="note">
<p>The iOS Simulator cannot simulate device motions. If you run the Motions application in the simulator, the <code>motionManager</code> will not send any device motions updates. At the time of writing this book, the only way to test this code is to run the application on a real iOS device.</p>
</div>
<p>We now capture the device motions and display them. The next step is to broadcast them by sending MQTT messages.</p>
</section>
<figure id="img_mobile_mqtt_8"><img alt="The motion values change when the device moves." src="images/mawm_0610.png" />
<figcaption>The motion values change when the device moves</figcaption>
</figure>
<section data-type="sect1" id="ch_mobile_mqtt_client">
<h1>Create an MQTT Client with MQTTKit</h1>
<p>To send and receive messages with MQTT, we must first import the MQTTKit library that was added to the project<a contenteditable="false" data-primary="mobile messaging with MQTT" data-secondary="creating MQTT client with MQTTKit" data-type="indexterm"> </a> using <a contenteditable="false" data-primary="MQTTKit" data-secondary="creating MQTT client with" data-type="indexterm"> </a>CocoaPods at the beginning of this chapter.</p>
<p>We must import its header file <em>MQTTKit.h</em> at the top of the <em>MWMViewController.m</em> file and add an <code>MQTTClient</code> property named <code>client</code> to the <code>MWMViewController</code> private interface.</p>
<p>We also define a constant to represent the hostname of the MQTT broker we are using in <em>iot.eclipse.org</em>:</p>
<pre data-code-language="objc" data-type="programlisting">
#import <MQTTKit/MQTTKit.h>
#define kMqttHost @"iot.eclipse.org"
@interface MWMViewController ()
@property (strong, nonatomic) MQTTClient *client;
@end</pre>
<p>We will create a new <code>MQTTClient</code> object in the <code>MWMViewController</code>'s <code>viewDidLoad</code> method. An <code>MQTTClient</code> must be uniquely identified for the MQTT brokers it connects to. We can use the <code>deviceID</code> as its client identifier:</p>
<pre data-code-language="objc" data-type="programlisting">
- (void)viewDidLoad
{
[super viewDidLoad];
...
self.client = [[MQTTClient alloc] initWithClientId:self.deviceID];
}</pre>
</section>
<section data-type="sect1" id="_connect_to_a_mqtt_broker">
<h1>Connect to an MQTT Broker</h1>
<p>An MQTTKit client will connect to the MQTT Broker when its <code>connectToHost:completionHandler:</code> method<a contenteditable="false" data-primary="mobile messaging with MQTT" data-secondary="connecting to an MQTT broker" data-type="indexterm"> </a> is called.<a contenteditable="false" data-primary="brokers" data-secondary="connecting to an MQTT broker" data-type="indexterm"> </a> MQTTKit is event-driven, so the client will be <em>effectively</em> connected when its <code>completionHandler</code> block is called and the return code <code>MQTTConnectionReturnCode</code> is equal to <code>ConnectionAccepted</code>.</p>
<p>You cannot assume that the client is connected when the <code>connectToHost:completionHandler:</code> method returns. Any actions that require the client to be connected must happen inside the <code>completionHandler</code> block.</p>
<p>We will encapsulate this code in a <code>connect</code> method:</p>
<pre data-code-language="objc" data-type="programlisting">
#pragma mark - MQTTKit Actions
- (void)connect
{
NSLog(@"Connecting to %@...", kMqttHost);
[self.client connectToHost:kMqttHost
completionHandler:^(MQTTConnectionReturnCode code) {
if (code == ConnectionAccepted) {
NSLog(@"connected to the MQTT broker");
} else {
NSLog(@"Failed to connect to the MQTT broker: code=%lu", code);
}
}];
}</pre>
<p>We will call this method from <code>viewDidLoad</code> to connect to the MQTT broker as soon as the view is loaded:</p>
<pre data-code-language="objc" data-type="programlisting">
- (void)viewDidLoad
{
[super viewDidLoad];
self.deviceID = [UIDevice currentDevice].identifierForVendor.UUIDString;
NSLog(@"Device identifier is %@", self.deviceID);
self.deviceIDLabel.text = self.deviceID;
...
self.client = [[MQTTClient alloc] initWithClientId:self.deviceID];
[self connect];
}</pre>
</section>
<section data-type="sect1" id="_disconnect_from_a_mqtt_broker">
<h1>Disconnect from an MQTT Broker</h1>
<p>The <code>client</code> can disconnect from the MQTT broker <a contenteditable="false" data-primary="mobile messaging with MQTT" data-secondary="disconnecting from an MQTT broker" data-type="indexterm"> </a>by calling its <code>disconnectWithCompletionHandler:</code> method.<a contenteditable="false" data-primary="brokers" data-secondary="disconnecting from an MQTT broker" data-type="indexterm"> </a></p>
<p>The <code>completionHandler</code> block as a <code>code</code> parameter will be <code>0</code> if the disconnection succeeds:</p>
<pre data-code-language="objc" data-type="programlisting">
- (void)disconnect
{
[self.client disconnectWithCompletionHandler:^(NSUInteger code) {
if (code == 0) {
NSLog(@"disconnected from the MQTT broker");
} else {
NSLog(@"disconnected unexpectedly...");
}
}];
}</pre>
<p>We want to disconnect from the MQTT broker when the <code>MWMViewController</code> is no longer used. We will call the <code>disconnect</code> method from <code>dealloc</code>:</p>
<pre data-code-language="objc" data-type="programlisting">
- (void)dealloc
{
[self.motionManager stopDeviceMotionUpdates];
[self disconnect];
}</pre>
</section>
<section data-type="sect1" id="_send_mqtt_messages">
<h1>Send MQTT Messages</h1>
<p>The <code>MWMViewController</code> automatically connects to the MQTT broker when its view is loaded and disconnects when it is <a contenteditable="false" data-primary="mobile messaging with MQTT" data-secondary="sending MQTT messages" data-type="indexterm" id="mobmessMQTTsend"> </a>deallocated.<a contenteditable="false" data-primary="messages" data-secondary="sending MQTT messages" data-type="indexterm" id="messMQTTsend"> </a> The next step is to send messages every time the device motion values are updated.</p>
<p>The MQTT protocol is a binary protocol. The message payload must be encoded as binary data<a contenteditable="false" data-primary="payload" data-secondary="binary payload for MQTT messages" data-type="indexterm"> </a> to be sent. <a contenteditable="false" data-primary="MQTTKit" data-secondary="methods to send messages" data-type="indexterm"> </a>The MQTTKit library provides two methods to send <span class="keep-together">messages:</span></p>
<ul>
<li>
<p>The <code>publishData:toTopic:withQos:retain:</code> method expects an <code>NSData</code> object as the message payload and its <code>bytes</code> will be used.</p>
</li>
<li>
<p>The <code>publishString:toTopic:withQos:retain:</code> method can also be used for the common case of sending a text message. Internally, the <code>NSString</code> that is passed in as a parameter is encoded as an <code>NSData</code> using the UTF-8 encoding.</p>
</li>
</ul>
<p>In the Motions iOS application, we send a message with a binary payload composed of three 64-bit floats for the pitch, roll, and yaw values contained in a <code>CMAttitude</code> object. We will build the payload’s <code>NSData</code> by converting the double values to a platform-independent format using the <code>CFConvertDoubleHostToSwapped</code> function.</p>
<p>The other three parameters to the <code>publish…</code> methods are the same for both the binary and text payload version.</p>
<p>The <code>topic</code> parameter is the name of the topic to send the message. According to <a data-type="xref" href="#ch_introduction_mqtt_example_topology">#ch_introduction_mqtt_example_topology</a>, the name of the topic is <code>/mwm/XXX/motion</code> where "XXX" is the device identifier.</p>
<p>The <code>qos</code> parameter corresponds to the <em>Quality of Service</em> (or QoS) to use to deliver the messages to the consumers.</p>
<section data-type="sect2" id="mqtt_qos">
<h2>Quality of Service</h2>
<p>The MQTT protocol defines<a contenteditable="false" data-primary="mobile messaging with MQTT" data-secondary="sending MQTT messages" data-tertiary="Quality of Service (QoS)" data-type="indexterm"> </a> three levels of<a contenteditable="false" data-primary="Quality of Service (QoS)" data-secondary="At Most Once, At Least Once, and Exactly Once levels" data-type="indexterm"> </a> Quality of Service:</p>
<ul>
<li>
<p><code>At Most Once</code> (with the value <code>0</code> represented by <code>AtMostOnce</code> in MQTTKit)</p>
</li>
<li>
<p><code>At Least Once</code> (with the value <code>1</code> represented by <code>AtLeastOnce</code> in MQTTKit)</p>
</li>
<li>
<p><code>Exactly Once</code> (with the value <code>2</code> represented by <code>ExactlyOnce</code> in MQTTKit)</p>
</li>
</ul>
<p>These levels of QoS determine the guarantee that the MQTT broker will accept to deliver a message. With <code>At Most Once</code>, the MQTT broker guarantees that the published message will be delivered at most once to its consumers. This means that the consumers may not receive the message at all. If an error (such as a network failure or a crash) occurs while the message is sent to the broker, it is possible that it will be lost and the consumers will never receive it.</p>
<p>With <code>At Least Once</code>, the MQTT <a contenteditable="false" data-primary="At Least Once QoS" data-type="indexterm"> </a>broker guarantees that the published message will be delivered at least once to the consumers. This also means that a consumer may receive the same message twice. If there is an error when the producer sends the message to the broker and a message acknowledgment has not been received, it will resend it a second time as a <em>duplicate</em> (the MQTT message will have a <code>DUP</code> bit set). When the broker receives this duplicate message, it will redeliver it to the consumer, but it is possible that they in fact received the original message. The consumer might need to check if the <code>DUP</code> bit is set on the delivered message to know whether it is an original message (and it must process it) or a duplicate (and it can discard it).</p>
<p>The <code>At Least Once</code> QoS offers the guarantee that no published message will be lost, but at the cost of performance and additional code on the consumer side. The performance cost is caused by the additional message (a <code>PUBACK</code> message) sent from the broker to the client to acknowledge that it has received the published message. That means that using this QoS level to publish <code>N</code> messages will involve exchanging <code>2*N</code> messages between the producer and the broker.</p>
<p>The highest level of delivery is provided using the <code>Exactly Once</code> QoS. <a contenteditable="false" data-primary="Exactly Once QoS" data-type="indexterm"> </a>With that level, the MQTT broker guarantees that the published message will be delivered <em>exactly</em> once by the consumers. There will be no lost messages or duplicate messages. This is guaranteed by additional exchanges of messages between the producer and broker (<code>PUBREC</code>, <code>PUBREL</code>, <code>PUBCOMP</code> messages). That means that using this QoS level to publish <code>N</code> messages will involve exchanging <code>4*N</code> messages, requires four times more network trips than the lowest level of QoS of <code>At Most Once</code> and twice<a contenteditable="false" data-primary="At Most Once QoS" data-type="indexterm"> </a> more than the <code>At Least Once</code> level.</p>
<p>Choosing the correct QoS depends on the type of message exchanged and the <em>importance</em> of its payload. In the Motions iOS application, the published message contains device motion that is updated every second. It is acceptable if a published message is <em>lost</em> because a new message with updated content will be sent just one second later. Using the <code>At Most Once</code> QoS is the best choice for this type of message.</p>
<p>All the complexities of using a higher level of QoS are transparent from the application using MQTT, as it is the responsibility of the client library to handle it. However, you need to be aware of the cost associated with using these QoSes, as they can significantly impact your application performance and the device in general (the additional network trips will drain the battery life).</p>
</section>
<section data-type="sect2" id="_retained_message">
<h2>Retained Message</h2>
<p>The final parameter of the <code>publish…</code> methods is a boolean to specify whether the published message must<a contenteditable="false" data-primary="mobile messaging with MQTT" data-secondary="sending MQTT messages" data-tertiary="retained messages" data-type="indexterm"> </a> be <em>retained</em> by the topic.<a contenteditable="false" data-primary="retained messages (MQTT)" data-type="indexterm"> </a></p>
<p>If this flag is set on the message, the broker will deliver the message to its subscribers and keep holding the message. If a new consumer subscribes to this topic, the broker will deliver the retained message to it. This is useful, as the new subscriber will not have to wait for a publisher to send a message to receive new data. The retained message contains the <em>Last Known Good</em> value.<a contenteditable="false" data-primary="Last Known Good value" data-type="indexterm"> </a></p>
<p>In our case, we will publish messages with <code>retain</code> set to <code>YES</code>. If consumers subscribe to the device motion topic <em>after</em> the device stops updating its motion values, they will still be able to use the last known device motion value. This example is a bit of a stretch. A more interesting example would be an application broadcasting its location (similar to the <code>Locations</code> application). Using retained message would allow the consumers to know the last known position of the device before it stops broadcasting its position.</p>
<p>To sum up, the <code>Motions</code> application will<a contenteditable="false" data-primary="mobile messaging with MQTT" data-secondary="sending MQTT messages" data-tertiary="Motions application (example)" data-type="indexterm"> </a> send a message:</p>
<ul>
<li>
<p>With a binary payload composed of three 64-bit floats for the device’s pitch, roll, and yaw values</p>
</li>
<li>
<p>To the device motion topic <code>/mwm/XXX/motion</code> where <code>XXX</code> is the device identifier</p>
</li>
<li>
<p>With a QoS of <code>At Most Once</code>, because we accept that a published message may not be delivered</p>
</li>
<li>
<p>With <code>retain</code> set to <code>YES</code> so that the broker will retain the Last Known Good message to deliver it to new subscribers</p>
</li>
</ul>
<p>We will encapsulate this code in a <code>send:</code> method taking a <code>CMAttitude</code> parameter:</p>
<pre data-code-language="objc" data-type="programlisting">
- (void)send:(CMAttitude *)attitude
{
uint64_t values[3] = {
CFConvertDoubleHostToSwapped(attitude.pitch).v,
CFConvertDoubleHostToSwapped(attitude.roll).v,
CFConvertDoubleHostToSwapped(attitude.yaw).v
};
NSData *data = [NSData dataWithBytes:&values length:sizeof(values)];
NSString *topic =[NSString stringWithFormat:@"/mwm/%@/motion",
self.deviceID];
[self.client publishData:data
toTopic:topic
withQos:AtMostOnce
retain:YES
completionHandler:nil];
}</pre>
<p>The message will contain the motion values in radians. It will be up to the consumers to convert them in degrees if necessary.</p>
<p>Finally, the last step is to call this method every time a device motion value is updated by the <code>motionManger</code>. This occurs in the <code>viewDidLoad</code> method inside the <code>handler</code> block passed to the <code>motionManger</code>'s <code>startDeviceMotionUpdatesToQueue:withHandler:</code> method:</p>
<pre data-code-language="objc" data-type="programlisting">
- (void)viewDidLoad
{
[super viewDidLoad];
self.deviceID = [UIDevice currentDevice].identifierForVendor.UUIDString;
NSLog(@"Device identifier is %@", self.deviceID);
self.deviceIDLabel.text = self.deviceID;
self.motionManager = [[CMMotionManager alloc] init];
// get the device motion updates every second.
self.motionManager.deviceMotionUpdateInterval = 1;
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[self.motionManager startDeviceMotionUpdatesToQueue:queue
withHandler:^(CMDeviceMotion *motion,
NSError *error) {
if(!error) {
CMAttitude *attitude = motion.attitude;
dispatch_async(dispatch_get_main_queue(), ^{
// convert values from radians to degrees
double pitch = attitude.pitch * 180 / M_PI;
double roll = attitude.roll * 180 / M_PI;
double yaw = attitude.yaw * 180 / M_PI;
self.pitchLabel.text =
[NSString stringWithFormat:@"pitch: %.0f°", pitch];
self.rollLabel.text =
[NSString stringWithFormat:@"roll: %.0f°", roll];
self.yawLabel.text =
[NSString stringWithFormat:@"yaw: %.0f°", yaw];
});
[self send:attitude];
}
}];
self.client = [[MQTTClient alloc] initWithClientId:self.deviceID];
[self connect];
}
</pre>
<p>We now have the <code>Motions</code> iOS application that is sending MQTT messages. How can we check that this is working as expected? </p>
<p>Conversely to <code>STOMP</code>, <code>MQTT</code> is a binary protocol and we cannot use a simple telnet client to create a consumer and receive messages sent by the application.</p>
<p>However, the <a href="http://mosquitto.org">Mosquitto broker</a> provides a simple command-line tool to send and <span class="keep-together">receive</span> message from<a contenteditable="false" data-primary="brokers" data-secondary="Mosquitto broker" data-type="indexterm"> </a> an MQTT broker. <a data-type="xref" href="#appendix_mosquitto">#appendix_mosquitto</a> explains how to download and install the Mosquitto broker.<a contenteditable="false" data-primary="Mosquitto broker" data-secondary="command-line tool to send/receive messages from MQTT broker" data-type="indexterm"> </a> After it is done, we can use its <code>mosquitto_sub</code> command-line tool to connect to an MQTT broker (hosted at <em>iot.eclipse.org</em>) and subscribe to the device motion topic (in my case, <code>/mwm/C0962483-7DD9-43CC-B1A0-2E7FBFC05060/motion</code>; you will have to replace it using your own device identifier).</p>
<p>This tool will display the message payload. We are sending binary payload, so we will pipe the command into the <code>hexdump</code> tool to<a contenteditable="false" data-primary="hexdump tool" data-type="indexterm"> </a> display the hexadecimal representation of the binary payload:</p>
<pre data-code-language="bash" data-type="programlisting">
$ mosquitto_sub -h iot.eclipse.org -t /mwm/C0962483-7DD9-43CC-B1A0-2E7FBFC05060/motion | hexdump
...
0000050 aa b0 4c 3f 9b 41 0c 6b 08 35 d3 3f d2 4b 23 f2
0000060 71 1e 47 0a 3f d5 05 6a c4 37 52 16 3f d8 f7 b5
0000070 34 f6 19 ea bf d2 97 6f 1a 65 86 af 0a 3f af 23
0000080 78 91 85 1c 8d bf df b9 12 c4 78 64 1c 3f cb 3c
0000090 50 fd 05 26 5b 0a 3f d1 60 87 16 0b 12 9e bf c2
...</pre>
<p>This confirms that the Motions application is effectively <a contenteditable="false" data-primary="messages" data-secondary="sending MQTT messages" data-startref="messMQTTsend" data-type="indexterm"> </a>publishing MQTT messages.<a contenteditable="false" data-primary="mobile messaging with MQTT" data-secondary="sending MQTT messages" data-startref="mobmessMQTTsend" data-type="indexterm"> </a></p>
</section>
</section>
<section data-type="sect1" id="ch_mobile_mqtt_receive">
<h1>Receive MQTT Messages</h1>
<p>As described in <a data-type="xref" href="#ch_introduction_mqtt_example">#ch_introduction_mqtt_example</a>, the Motions iOS application is also a consumer from <a contenteditable="false" data-primary="mobile messaging with MQTT" data-secondary="receiving MQTT messages" data-type="indexterm"> </a>the topic <code>/mwm/XXX/alert</code>.<a contenteditable="false" data-primary="messages" data-secondary="receiving MQTT messages" data-type="indexterm"> </a> When it receives a message from this topic, it must change its background color to "alert" the user.</p>
<p>Let’s write the method that alerts the user by changing the background color first. This <code>warnUser:</code> method takes an <code>NSString</code> parameter that should correspond to a color. Using <code>UIKit</code> animations, we will:</p>
<ol>
<li>
<p>Animate the controller’s view to change its background color from its original color to the one created from the <code>NSString</code> parameter.</p>
</li>
<li>
<p>Wait two seconds after the first animation is completed to revert back to the original background color:</p>
</li>
</ol>
<pre data-code-language="objc" data-type="programlisting">
# pragma mark - UI Actions
// Warn the user by changing the view's background color to the specified color
// during 2 seconds
- (void)warnUser:(NSString *)colorStr
{
// keep a reference to the original color
UIColor *originalColor = self.view.backgroundColor;
[UIView animateWithDuration:0.5
delay:0.0
options:0
animations:^{
// change it to the color passed in parameter
NSString *colorCode =
[NSString stringWithFormat:@"%@Color", colorStr];
SEL sel = NSSelectorFromString(colorCode);
UIColor* color = nil;
if ([UIColor respondsToSelector:sel]) {
color = [UIColor performSelector:sel];
} else {
color = [UIColor redColor];
}
self.view.backgroundColor = color;
}
completion:^(BOOL finished) {
// after a delay of 2 seconds, revert it to
// the original color
[UIView animateWithDuration:0.5
delay:2
options:0
animations:^{
self.view.backgroundColor =
originalColor;
}
completion:nil];
}];
}
</pre>
<p>To consume messages from an MQTT broker, the <code>client</code> must do the following:</p>
<ol>
<li>
<p>Subscribe to its topic of interest.</p>
</li>
<li>
<p>Set its <code>messageHandler</code> property, which will be called every time a message is delivered.</p>
</li>
</ol>
<p>Note that you can subscribe to many topics from the client but it has only one <code>messageHandler</code> property.<a contenteditable="false" data-primary="messageHandler property, MQTT client" data-type="indexterm"> </a> If the client is subscribed to different topics, its <code>messageHandler</code> must determine the topic from which the message is consumed.</p>
<section data-type="sect2" id="_subscription">
<h2>Subscription</h2>
<p>The Motions application will subscribe<a contenteditable="false" data-primary="publish/subscribe messaging model" data-secondary="subscription, MQTT iOS Motions application (example)" data-type="indexterm"> </a> to its device alert topic <code>/mwm/XXX/alert</code> by calling the method <code>subscribe:withQos:completionHandler:</code> on its <code>client</code> property.<a contenteditable="false" data-primary="mobile messaging with MQTT" data-secondary="receiving MQTT messages" data-tertiary="subscription" data-type="indexterm"> </a></p>
<p>The first parameter is the device alert topic. We will define it at the top of the <em>MWMViewController.m</em> file:</p>
<pre data-code-language="objc" data-type="programlisting">
#define kAlertTopic @"/mwm/%@/alert"</pre>
<p>The <code>subscribe:withQos:completionHandler:</code> method takes a <code>qos</code> parameter that corresponds to the level of quality of service at which the consumer wants to recieve messages from the topic.<a contenteditable="false" data-primary="Quality of Service (QoS)" data-secondary="receiving MQTT messages" data-type="indexterm"> </a></p>
<p>The completion handler will be called when the client is effectively subscribed to the topic. The handler has a <code>grantedQos</code> parameter that corresponds to the effective quality of service. The producer is responsible for determining the maximum quality of service at which a message can be delivered, but the consumer can decide to <em>downgrade</em> the quality of service according to its usage. For example, a producer may publish a message with a QoS of <code>ExactlyOnce</code>, but a consumer may decide that it is acceptable if there are message duplicates and downgrade its QoS to <code>AtLeastOnce</code>.</p>
<p>In our case, we will request to have messages delivered with a <code>qos</code> set to <code>AtLeastOnce</code>, as we do not want to lose messages but can accept duplicate messages:</p>
<pre data-code-language="objc" data-type="programlisting">
- (void)subscribe
{
NSString *topic = [NSString stringWithFormat:kAlertTopic, self.deviceID];
[self.client subscribe:topic
withQos:AtLeastOnce
completionHandler:^(NSArray *grantedQos) {
NSLog(@"subscribed to %@ with QoS %@", topic, grantedQos);
}];
}</pre>
<p>We will subscribe to the alert topic as soon as the <code>client</code> is connected to the MQTT broker by calling this <code>subscribe</code> method from inside the <code>completionHandler</code> in the <code>connect</code> method:</p>
<pre data-code-language="objc" data-type="programlisting">
- (void)connect
{
NSLog(@"Connecting to %@...", kMqttHost);
[self.client connectToHost:kMqttHost
completionHandler:^(MQTTConnectionReturnCode code) {
if (code == ConnectionAccepted) {
NSLog(@"connected to the MQTT broker");
[self subscribe];
} else {
NSLog(@"Failed to connect to the MQTT broker: code=%lu", code);
}
}];
}</pre>
</section>
<section data-type="sect2" id="_unsubscription">
<h2>Unsubscribing</h2>
<p>To unsubscribe from a topic and<a contenteditable="false" data-primary="unsubscribing from MQTT topics" data-type="indexterm"> </a> stop receiving<a contenteditable="false" data-primary="mobile messaging with MQTT" data-secondary="receiving MQTT messages" data-tertiary="unsubscription" data-type="indexterm"> </a> messages from it, we will call the <code>unsubscribe:withCompletionHandler:</code> method of the <code>client</code> where the first parameter is the topic to unsubscribe from (the alert topic in our case). The second parameter is a completion handler that is called back when the client has been acknowledged by the server that it is effectively unsubscribed. We do not have any need for this information so we just pass <code>nil</code> as the handler:</p>
<pre data-code-language="objc" data-type="programlisting">
- (void)unsubscribe
{
NSString *topic = [NSString stringWithFormat:kAlertTopic, self.deviceID];
[self.client unsubscribe:topic withCompletionHandler:nil];
}</pre>
<p>We will call this <code>unsubscribe</code> method just before disconnecting from the MQTT broker from the <code>dealloc</code> method:</p>
<pre data-code-language="objc" data-type="programlisting">
- (void)dealloc
{
[self.motionManager stopDeviceMotionUpdates];
[self unsubscribe];
[self disconnect];
}</pre>
<p>Because we disconnect just after unsubscribing, we could skip that step and just disconnect from the MQTT broker. At that moment, the MQTT broker will automatically unsubscribe the client from any topic. However, it is a good practice to explicitly unsubscribe from the subscribed topic. There are also many cases where unsubscribing may occur at a different time than the disconnection. In these cases, we cannot rely on the client disconnection to perfom the unsubscription.</p>
</section>
<section data-type="sect2" id="_define_a_mqttmessage_handler">
<h2>Define an MQTTMessage Handler</h2>
<p>Subscribing to a topic is the first step in receiving messages with MQTTKit.<a contenteditable="false" data-primary="MQTTKit" data-secondary="defining MQTTMessageHandler" data-type="indexterm"> </a> The second step is to define a block that will be called every time a message is received from a subscribed topic.<a contenteditable="false" data-primary="mobile messaging with MQTT" data-secondary="receiving MQTT messages" data-tertiary="defining MQTTMessageHandler" data-type="indexterm"> </a></p>
<p>The <code>client</code>'s <code>messageHandler</code> property defines an <code>MQTTMessageHandler</code> block. This block has an <code>MQTTMessage</code> parameter representing the MQTT message that is delivered to the client.</p>
<p>The <code>MQTTMessage</code> interface defines four properties corresponding to the message <span class="keep-together">data:</span></p>
<ul>
<li>
<p><code>mid</code> is a <code>unsigned short</code> corresponding to the <em>message ID</em>.</p>
</li>
<li>
<p><code>topic</code> is the name of the topic that this message is coming from. If the client is subscribed to many topics, we must use this property to determine the topic from which the received message is coming.</p>
</li>
<li>
<p><code>retained</code> is a <code>BOOL</code> to check whether the message was retained (and contains the last known good value) or not (in which case it is a <em>fresh</em> message).</p>
</li>
<li>
<p><code>payload</code> is an <code>NSData</code> object containing the binary content of the message payload.</p>
</li>
</ul>
<p>Because sending and receiving text messages is very common, the <code>MQTTMessage</code> interface also defines a <code>payloadString</code> method that returns an <code>NSString</code> decoded from the message binary payload using UTF-8.</p>
<p>In the <code>Motions</code> application, we expect to receive a text payload and will use this <code>payloadString</code> to extract the color string from the received message.</p>
<p>We need to set the <code>client</code>'s <code>messageHandler</code> <em>before</em> subscribing to the alert topic so that we do not miss any alert message sent after we subscribe but <em>before</em> the <code>messageHandler</code> is defined. We will do that in the <code>viewDidLoad</code> method just after creating the <code>client</code> instance:</p>
<pre data-code-language="objc" data-type="programlisting">
- (void)viewDidLoad
{
[super viewDidLoad];
self.deviceID = [UIDevice currentDevice].identifierForVendor.UUIDString;
NSLog(@"Device identifier is %@", self.deviceID);
self.deviceIDLabel.text = self.deviceID;
...
self.client = [[MQTTClient alloc] initWithClientId:self.deviceID];
// use a weak reference to avoid a retain/release cycle in the block
__weak MWMViewController *weakSelf = self;
self.client.messageHandler = ^(MQTTMessage *message) {
NSString *alertTopic =
[NSString stringWithFormat:kAlertTopic, weakSelf.deviceID];
if ([alertTopic isEqualToString:message.topic]) {
NSString *color = message.payloadString;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf warnUser:color];
});
}
};
[self connect];
}
</pre>
<p>We extracted the color using the message <code>payloadString</code> method after checking that it was indeed coming from the device alert topic. We then call the <code>warnUser:</code> method in a block that is run on the main queue, because it contains code related to <code>UIKit</code>.</p>
<p>To avoid a retain/release cycle between <code>self</code> and the <code>messageHandler</code> block, we need to create a <em>weak</em> reference of <code>self</code> in order to use it inside the block.</p>
<p>How can we verify that the Motions application is effectively receiving alert messages? To verify that the application was sending messages, we used the <code>mosquitto_sub</code> tool. We will now use the opposite tool, <code>mosquitto_pub</code>, to publish a message on the alert topic and verify that the application background color changes.<a contenteditable="false" data-primary="Mosquitto broker" data-secondary="publishing messages with mosquitto_pub tool" data-type="indexterm"> </a></p>
<p>The <code>mosquitto_pub</code> can send a text payload using the <code>-m</code> option. We will use this option to pass the background color (in this case, <code>green</code>):</p>
<pre data-code-language="bash" data-type="programlisting">
$ mosquitto_pub -h iot.eclipse.org -t /mwm/C0962483-7DD9-43CC-B1A0-2E7FBFC05060/alert -m green</pre>
<p>After this message is sent, the device will receive it and change its background color to green (<a data-type="xref" href="img_mobile_mqtt_225">img_mobile_mqtt_225</a>).</p>
<figure id="img_mobile_mqtt_225"><img alt="Alert message is received by the Motions iOS application" src="images/mawm_0611.png" />
<figcaption>Alert message is received by the Motions iOS application</figcaption>
</figure>
</section>
</section>
<section data-type="sect1" id="_summary_6">
<h1>Summary</h1>
<p>In this chapter, we learned to use MQTTKit to send and receive MQTT messages from an iOS application.</p>
<p>To send a message, the application must do the following:</p>
<ol>
<li>
<p>Connect to the MQTT broker.</p>
</li>
<li>
<p>Send the message to the topic.</p>
</li>
</ol>
<p>To consume a message, the application must do the following:</p>
<ol>
<li>
<p>Connect to the MQTT broker.</p>
</li>
<li>
<p>Subscribe to the topic.</p>
</li>
<li>
<p>Define a message handler block that is called every time a message is received. This block is executed on a dispatch queue. If there is any code that changes the user interface, it must be wrapped in a block executed on the main queue.</p>
</li>
</ol>
<p>We used two different types of message payloads:</p>
<ul>
<li>
<p>A binary payload to send the device motions values as three 64-bit floats.</p>
</li>
<li>
<p>A text payload to extract a background color from the messages received on the alert topic.<a contenteditable="false" data-primary="mobile messaging with MQTT" data-startref="mobmessMQTT" data-type="indexterm"> </a><a contenteditable="false" data-primary="MQTT" data-secondary="mobile messaging with" data-startref="MQTTmobmess" data-type="indexterm"> </a></p>
</li>
</ul>
</section>
</section>