2. Move Vapor – Communicate between iPhone and Raspberry Pi with Vapor 3

Move Vapor – Communicate between iPhone and Raspberry Pi with Vapor 3

This article is based on the session presented at iOSDC2022, Make your home more convenient and safe with Swift! This is the third article that summarizes the contents of Part 2 of the announcement.
This article is a continuation of the article “2. Moving Vapor – Communication between iPhone and Raspberry Pi with Vapor 2“. If you haven’t read it yet, please read it!
This article summarizes how to use CoreMotion to send iPhone altitude information to the Raspberry Pi.

2. Move Vapor - Communicate between iPhone and Raspberry Pi with Vapor 2This article is an article that summarizes part of the contents of the second part of the announcement of "Make your home more convenient and safe with Swift", "2. Moving Vapor - Communication between iPhone and Raspberry Pi with Vapor"!...

Obtain Altitude Information on iPhone

In order to send the location information and altitude information used to determine whether the landlord is at home to the Raspberry Pi, first let’s get the data on the iPhone

I will omit how to get location information this time (because there are plenty of reference articles on the net!)

Using CoreMotion to get altitude information

To get altitude information in swift, use the CMAltimeter class of CoreMotion.
There are two types of altitude information that can be obtained from CMAltimeter: absolute altitude and relative altitude.

What is absolute and relative altitude?

Absolute altitude → how many meters above sea level
Relative altitude → how many meters since the start of data acquisition

This time, we will use the absolute altitude!
By the way, the SwiftHomeApp app uses relative altitude for reference. is also implemented.

Also, to actually get the data on the iPhone, you need to add the following to Info.plist

Privacy - Motion Usage Description

Next is the code to actually get altitude information. (GitHub is here)

① Create an instance of CMAltimeter and ② check if altitude information can be acquired by the device.
And when you call the CMAltimeter instance’s startAbsoluteAltitudeUpdates method, that closure will be called periodically and you can get altitude information from it.
For absolute altitude, you can get the data in meters from data!.altitude.

import CoreMotion

private let altimeterMeter = CMAltimeter() // ① setup instance
if CMAltimeter.isAbsoluteAltitudeAvailable() { // ②Check if CMAltimeter is enable or not
    altimeterMeter.startAbsoluteAltitudeUpdates(to: OperationQueue.main) { data, error in
        // ③Called at a certain timing and can acquire data
        if error != nil { return }
        print(data!.altitude) // 25.007457757686876868(e.g, unit is m)

I tried to print the relative altitude ↓
If you hold the actual device and raise it, lower it, bend it, you can output various relative altitudes (laughs)
(When I took a capture, I had both an iPhone and a Mac connected with a lightning cable, but I should have done wireless debugging lol)

By the way, wireless debugging was introduced in the previous article ↓!

【Xcode】How to build in real device without connecting with a cableI tried to summarize how to build the actual machine with Xcode without connecting with a cable!...

We were able to confirm that the location information and altitude information can be displayed correctly even on the screen ↓ that actually displays the device information of SwiftHomeApp! (It’s completely personal information, so I’m masking some!)

Send altitude information to Raspberry Pi via Heroku

Lastly, let’s send it to the API implemented in the first and second articles and the Heroku server!

First, set the acquired data to the common model DeviceInfoModel defined in SwiftHomeCore.
Then convert that model to a Dictionary type.
By the way, this asDictionary method is defined in a package called SwiftExtensions, which is a collection of extensions that I created for common use in application development. (details are in the article below)

Publish Local Package from Xcode as PackageI have summarized how to publish the Local Package created by the app from Xcode to GitHub as a Package!...
// ①Use common Model defined in SwiftHomeCore
let model = DeviceInfoModel(deviceId: UIDevice.current.identifierForVendor!.uuidString,
                            deviceLatitude: userCoordinate.latitude,
                            deviceLongitude: userCoordinate.longitude,
                            absoluteAltimeter: absoluteAltimeterValue)
let parameters = try! model.asDictionary(using: encoder) // ②extension to convert to Dictionary

All you have to do is post it.
The code below posts using Alamofire.
In the header, we set basic authentication in the same way as when using WebSocket.

By the way, the setting of emptyResponseCodes: [200] means that the API implemented this time only returns a response of .ok when the response is 200, and json etc. Empty because it doesn’t return.
However, in Alamofire, if an empty response is returned, an error occurs as a decoding failure, so I explicitly wrote “If it is 200, it will be empty!”.

           method: .post, parameters: parameters, // ①Set DeviceInfoModel parameters
           headers: headers) // ②Same setting as webSocket header
.responseDecodable(of: Empty.self, emptyResponseCodes: [200]) { response in
    switch response.result {
    case .success: print("Success")
    // (Omit: error handling)

After posting, let’s check if the data is actually saved in Postgres on Heroku!

Heroku has a feature called Dataclips to check the data stored in Postgres, you can run postgresql to check the data (Reference).
Dashboard of Heroku > Menu on the left side of the user icon > Dataclips > Select the created app to proceed to the query input screen ↓

This time, the following query was executed to display all the saved device information. It seems that it is converted to lower case by , and if it is executed as it is, it is not possible to search for the table name registered with capital letters.
By specifying “DeviceInfo”, you can execute a query using the table name that begins with capital letters.

SELECT * FROM "DeviceInfo";

As a result, I was able to confirm that the data was properly saved as shown below! 🎉

Wrap up

This is the end of Part 2, “Running Vapor – Communication between iPhone and Raspberry Pi with Vapor“.
It turned out to be quite a long story! !
By using Vapor, you can easily build a server with Swift and share some code on the client side, which I thought was a great development experience!

Next is a summary article of “3. Read sensor value with Raspberry Pi – Get weight sensor value

3. Read sensor value with Raspberry Pi - Get weight sensor valueThis article is an article that summarizes the contents of Part 3 "3. Read the sensor value with Raspberry Pi - Get the weight sensor value" of the announcement "Make your home more convenient and safe with Swift"!...


Your email address will not be published. Required fields are marked *