I’m participating in nuggets Creator camp # 4, click here to learn more and sign up now!

preface

Recently, I did some scheme research on some remote control devices of the company’s App, and the general process is as follows:

This is one of the more mainstream questions:

App sends the operation instruction to the background through network request, and the background sends it to the corresponding device. After receiving the instruction, the device performs the corresponding operation. After the operation is completed, the background receives the notification from the device.

Here are some things to be clear about:

  • Requests and callbacks before App <=> Server <=> Device are asynchronous.
  • The operation of Device is very time-consuming, which may last for more than 2min. How to effectively feed back the operation result of Device to the App end is an urgent problem for us to deal with.

Fortunately, two-way communication before Server <=> Device has been built before, and data transmission is stable and efficient. Here we mainly talk about the scheme of App <=> Server.

Plan 1: round tour

This is actually the first, simplest, most violent thing we can think of.

After completing the remote control operation on the App end, we can start a timer task to complete a request to query the operation result of Device on the Server end. The code is also very simple to write. Here are just some simple code examples:

timer = Timer.scheduledTimer(withTimeInterval: timeInterval, repeats: true, block: {[weak self] (t) in guard let strongSelf = self else {return} /// network request /// return Response, end timer /// timer timeout, end timer})Copy the code

This round operation through the timer has the following advantages:

  • Simple logic;
  • Easy to code;

Of course, the disadvantages are also prominent:

  • Timers can be dangerous;
  • Rotation, resulting in the need for network requests at regular intervals, consumption of traffic and consumption of performance;
  • Poor user experience. Users may need to wait on a page to ensure that the timer is working during rotation.

Therefore, when we first thought of round robin, in fact, we have basically rejected this method. This scheme of initiating requests to the Server through App is not suitable for this scenario.

Scheme 2: Push

Since it is not possible for the App to request the results from the Server, the best solution is for the Server to inform the App of the results.

How about push? During our discussion, when the direction was changed to Server actively pushing messages to App, we immediately came up with the current scheme:

The diagram above is actually the schematic diagram of the entire iOS App. In fact, we mainly use the lower part of the diagram in the actual push process:

Server => APNS => App

Consider that in general, we use third-party push so the link looks like this:

Server => Third Server => APNS => App

But whatever the change, it’s still essentially receiving remote messages through this code:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {print(" remote notification ")}Copy the code

Using a third party is nothing more than calling push callbacks from a third party SDK, which is not described here.

The advantages of pushing this scheme are as follows:

  • Mature technology, accurate APNS push;
  • The coding difficulty is low. You only need to agree the type and format of the message to know whether the message is sent from the Device side, and then perform logical judgment.

As we consider the feasibility of such an approach, we also discuss some of the risks involved:

  • What is the push experience on Android?
  • Will there be any exceptions when integrating third-party push?
  • If this application needs to be made into SDK for other service providers to use, is it ok to use push?

Considering that this part of our application may be used by other apps, the whole push link becomes longer:

SDK Server => App Server => Third Server => APNS => App => SDK

We immediately realized that the longer the link, the higher the cost of debugging and communication, and that any one of these factors could cause messages not to be delivered to the SDK side.

Since there is nothing wrong with the Server telling the App the results, we will continue to expand along this path.

Scheme 3: Websocket Or MQTT

We use Websocket to communicate between Server and App. Considering some risks of push, we immediately came up with this technical solution we have used before.

WebSocket makes it easier to exchange data between the client and the server, allowing the server to actively push data to the client. In the WebSocket API, the browser and server only need to complete a handshake to create a persistent connection and two-way data transfer.

Basically implemented the server-side to client-side, initiative, which we value very much.

At the same time, we learned the communication mode between Server and Device — MQTT.

Since the Server already has MQTT service, it will be complicated to establish Websocket communication between the Server and App. We want to directly integrate and use MQTT protocol to carry out end-to-end communication. This figure also shows that MQTT is very suitable for our application:

We refer to some documents and conclusions:

Key differences between MQTT and Websocket:

1.MQTT does not depend on long connections and is suitable for weak networks. Cache information through topic. This conforms to the application scenarios of Internet of Things devices.

2. Because information is cached through topics, one-to-many connections can be realized between topics and multiple terminals instead of many-to-many connections between devices, saving energy consumption and bandwidth.

3.MQTT has less heartbeat and non-information packets than Websocket, saving bandwidth and energy consumption. More applicable to the physical network of a variety of network protocols.

Now that MQTT meets the requirements we envisioned, all that remains is initial debugging and validation.

Analogies and summaries

So far, our preliminary investigation on the network communication between Server and App has been basically completed. We can make some comparisons and summaries through a table:

Round round push MQTT
advantages Simple logic and easy coding The technology is mature and easy to use Active message sending, suitable for weak networks, saving bandwidth and power consumption
disadvantages Rough way, bad experience If third-party services are required and links are too long, troubleshooting and communication costs are high Currently, it is not used in the App end, and preliminary debugging is needed. Considering that this technology has been applied in many aspects, the risk should be small

In this survey, we started with the most common network requests as a starting point for mutual communication, and then found that HTTP protocol is not the way to complete the usage scenario.

Then, we abandoned the idea of App taking the initiative to the Server, and then considered the active communication between the Server and App, and considered the ready-made way of push. Then, we considered some special scenarios in the application, but did not adopt them.

Finally, based on the idea of active communication between Server and App, we consider Websocket and the existing communication modes of Server and Device, and we take MQTT protocol as the network communication mode between Server and App.

In the next section, I’ll cover some simple debugging of MQTT.

Reference documentation

What is the difference between MQTT and Websocket?