banner



How To Start Building An Ios App

Building an iOS hardware app

An easy-to-use printer for iPhone, you plug it in your iPhone and you can instantly print your pictures and see them video-animated in the Prynt app. With the spread of smart things (IoT) and increased use of AI as a differentiator for hardware, understanding the connection between a hardware device and an iOS app can be a nice to have skill. The protocol used to communicate with your accessory is iAP2 (iPod Accessory Protocol 2) It's the same protocol on Bluetooth.

image

Remy Virin Hacker Noon profile picture

As a software engineer, it is really exciting to work at the crossing of software and hardware. It is also a trend on the rise — with the spread of smart things (IoT) and increased use of AI as a differentiator for hardware (think Google's Pixel Buds), understanding the connection between a hardware device and an iOS app can be a nice to have skill. It's not something really common as an iOS developer, so I was glad to have this opportunity at Prynt.

Prynt builds a portable, easy-to-use printer for iPhone, you plug it in your iPhone and you can instantly print your pictures and see them video-animated in the Prynt app (think turning your smartphone into a Polaroid camera mixed with Harry Potter-style features).

So how do we connect to a hardware device?

image

image

First, you need to have a prototype board with the required hardware (at least a lightning connector). Then the goal is just to do a simple project, that can light a LED for instance, or compute an addition.

Let's code!

Apple provides a great sample project in Objective-C, don't forget to turn on Wireless Accessory Configuration in the capabilities of your target. This project demonstrates the basic use of

              ExternalAccessory.framework            

. The protocol used to communicate with your accessory is iAP2 (iPod Accessory Protocol 2). It's the same protocol on Bluetooth.

You have 3 main classes:

  •                   EAAccessoryManager                
    : responsible to give you the list of accessories (plugged on the lightning port, via bluetooth etc..) your app can connect to.
  •                   EAAccessory                
    : an accessory connected to your iPhone ( not necessarily connected to your app). It has property like name, manufacturer, serial number etc..
  •                   EASession                
    : Responsible for the connection and exchanging data with the accessory

Here is how to create a session and set up its output and input stream:

                                  let                  accessory =                  EAAccessoryManager.shared().connectedAccessories.first!                  let                  session =                  EASession(accessory: accessory, forProtocol: protocolString)  session.outputStream?.delegate =                  self                  session.outputStream?.schedule(in:                  RunLoop.main, forMode:                  RunLoopMode.defaultRunLoopMode) session.outputStream?.open()  session.inputStream?.delegate =                  self                  session.inputStream?.schedule(in:                  RunLoop.main, forMode:                  RunLoopMode.defaultRunLoopMode) session.inputStream?.open()              

The

              outputStream            

and

              inputStream            

inherit from

              [NS]Stream            

. Basically you will write data on the

              outputStream            

which your hardware device can read and it can send you data on the

              inputStream            

 , which will be read by your app.

Note: The output & input streams are scheduled on the main thread. We tried to scheduled them on a background queue, it may work for a simple project, but in the end we didn't received / send all the data. I recommend to schedule them on the main thread and dispatch the parsing and serialization on background queues.

image

Data exchange between your app and your device

This is how you write and read bytes:

                                  var                  session:                  EASession                  // Write bytes on the output buffer                  var                  bytesToWrite : [UInt8] = [0x00,                  0x01,                  0xFA] session.outputStream?.write(&bytesToWrite, maxLength: bytesToWrite.count)                  // ----------------------------------                  // Read bytes on the input buffer                  let                  bufferSize =                  16                  var                  buffer = [UInt8](repeating:                  0,                  count: bufferSize)                  if                  session.inputStream!.hasBytesAvailable {    session.inputStream!.read(&buffer, maxLength: bufferSize)                  // buffer contains maximum 16 bytes read on the buffer                  }              

At this point it may not work on the first time, you are sending data, don't really know if your hardware received them. Your app is supposed to get some data, but nothing on the input stream…

You need to investigate, to understand why your data are not sent or retrieved.

Depending on your project you may need a Beagle and an ATS to analyse the bytes transmitted between the iPhone and your hardware device in real time. Basically you will have access to all the bytes that are going from and to the lighting port in real time. I found Hex Fiend really useful to read, parse (with regex) and understand all the data sent and received.

If your cables between the ATS, the beagle, your mac, iPhone and the hardware board are too long or of poor quality, it may not work (seriously, we had this problem with too long cables).

About Code Quality…

Sending and receiving bytes can become a nightmare if you don't have a good specification and you stick to it. Organising bytes as frames is really helpful, here is how we organised our data exchange at Prynt:

image

  • Header: A fixed size amount of bytes. It's main goal is to transmit a command.
  • Payload: (Optional) Data you want to send, it can be a firmware update, a photo to print, the battery level, status of the hardware etc…
  • Frame: Header + Payload
  • Sync Bytes: We use the first two bytes to verify we're reading the beginning of the header. In our case we arbitrary choose 0x0F and 0xF0 for the sync bytes, but you can choose any value
  • Packet Number: Just a counter, you increment each time you send a new command, it helps to check if a frame is missing
  • Command: The information you want to ask / send (Print a picture, get the status, get the battery level etc…)
  • CRC (Cyclic Redundancy Check): Useful if you want to be sure your payload or header as not been altered.

Having bytes organised as a frame is easier to parse, one thing that is helpful for us having our model made of UInt8 (= a byte), like for instance, the

              BatteryLevel            

 :

                                                      enum                    BatteryLevel:                    UInt8                  {                  case                  low =                  0x01                  case                  normal =                  0x02                  case                  high =                  0x03                  case                  notInitialized =                  0xFF                  }                  let                  data:                  Data                  // data read from inputStream                  // Here is how we parse it if the battery information is on the 3rd byte of data.                  let                  battery =                  BatteryLevel(rawValue: (data[3])) ?? .notInitialized              

And of course, the parsing and serialization of those data should be well tested.

Conclusion

Playing with hardware is really fun for several reasons, your code has a material impact on something else, something physical, I remembered the feeling the first picture was printed with our Prynt Pocket, it was breathtaking. One thing I really enjoyed is dealing with data from a lower level perspective (rather than a REST API). It was fun to learn! But the MFi process might be complicated for a side project, you need to have a company and the tools can be costly.

For a side project, a great way to play with hardware is via Bluetooth and with a Raspberry Pi.

If you like this article or have any questions, I'll be happy to read them in the comments!

Icon credit

Tags

# ios# swift# external-accessory# mfi# ios-hardware-app# ios-hardware# software-engineer# hardware

How To Start Building An Ios App

Source: https://hackernoon.com/building-an-ios-hardware-app-401eb4869012

Posted by: gingrichlailes.blogspot.com

0 Response to "How To Start Building An Ios App"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel