Skip to content

Getting Started

Andrew Madsen edited this page Sep 19, 2015 · 2 revisions

After you've added ORSSerialPort to your project, you're ready to start using it.

This document is meant to be a fairly brief overview of the most important parts of the ORSSerialPort API and how to use them. For more in depth discussion of various topics, see the rest of the documentation. As well, the example projects provided with ORSSerialPort are a good way to see the concepts described here used in an actual application.

Quick note: This document uses Objective-C in all code examples. However, everything described here works in Swift as well, using the Swift equivalents. The Swift versions of the ORSSerialPort example projects are useful for seeing how the things described here work in Swift.

Opening a Port and Setting It Up

You can get an ORSSerialPort instance either of two ways. The easiest is to use ORSSerialPortManager's availablePorts array (explained below). The other way is to get a new ORSSerialPort instance using the serial port's BSD device path:

Objective-C:

ORSSerialPort *port = [ORSSerialPort serialPortWithPath:@"/dev/cu.KeySerial1"];

Note that you must give +serialPortWithPath: the full path to the device, as shown in the example above.

Each instance of ORSSerialPort represents a serial port device. That is, there is a 1:1 correspondence between port devices on the system and instances of ORSSerialPort. That means that repeated requests for a port object for a given device or device path will return the same instance of ORSSerialPort.

After you've got a port instance, you can open it with the -open method. When you're done using the port, close it using the -close method.

Port settings such as baud rate, number of stop bits, parity, and flow control settings can be set using the various properties ORSSerialPort provides. Note that all of these properties are Key Value Observing (KVO) compliant. This KVO compliance also applies to read-only properties for reading the state of the CTS, DSR and DCD pins. Among other things, this means it's easy to be notified when the state of one of these pins changes, without having to continually poll them, as well as making them easy to connect to a UI with Cocoa bindings.

ORSSerialPort's various settings, including baud rate, can be changed even while the port is open.

Sending Data

Send raw data by passing an NSData object to the -sendData: method:

NSData *dataToSend = [self.sendTextField.stringValue dataUsingEncoding:NSUTF8StringEncoding];
[self.serialPort sendData:dataToSend];

The specifics of your data sending code will be entirely dependent on the specifics of the data you receive from the device on the other end of the port. This is just an example.

If the device you're communicating with will respond to the data you send in a predictable way, it is often better to use ORSSerialPort's request/response API, which greatly simplifies robustly recognizing its responses. See the Request Response API Guide for more information.

Receiving Data

To receive data, you can implement the ORSSerialPortDelegate protocol's -serialPort:didReceiveData: method, and set the ORSSerialPort instance's delegate property. As noted below, this method is always called on the main queue. An example implementation is included below:

- (void)serialPort:(ORSSerialPort *)serialPort didReceiveData:(NSData *)data
{
    NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    [self.receivedDataTextView.textStorage.mutableString appendString:string];
    [self.receivedDataTextView setNeedsDisplay:YES];
}

Your implementation of this method will be entirely dependent on the specifics of the data you receive from the device on the other end of the port. This is just an example.

ORSSerialPort delivers data as it is received. Usually, a single call to -serialPort:didReceiveData: will not contain an entire "packet" of data. Most applications will want to use ORSSerialPort's Packet Parsing API. Alternatively, if the data you expect to receive is in response to specific requests you send, it is often better to use ORSSerialPort's request/response API (itself built on top of the Packet Parsing API).

ORSSerialPortDelegate

ORSSerialPort includes a delegate property, and a delegate protocol called ORSSerialPortDelegate. ORSSerialPort calls the methods in the ORSSerialPortDelegate on its delegate to notify it of various events. The ORSSerialPortDelegate protocol includes one required method:

- (void)serialPortWasRemovedFromSystem:(ORSSerialPort *)serialPort;

Also included are a number optional methods:

- (void)serialPort:(ORSSerialPort *)serialPort didReceiveData:(NSData *)data;
- - (void)serialPort:(ORSSerialPort *)serialPort didReceivePacket:(NSData *)packetData matchingDescriptor:(ORSSerialPacketDescriptor *)descriptor;
- (void)serialPort:(ORSSerialPort *)serialPort didReceiveResponse:(NSData *)responseData toRequest:(ORSSerialRequest *)request;
- (void)serialPort:(ORSSerialPort *)serialPort didEncounterError:(NSError *)error;
- (void)serialPortWasOpened:(ORSSerialPort *)serialPort;
- (void)serialPortWasClosed:(ORSSerialPort *)serialPort;

Note: All ORSSerialPortDelegate methods are always called on the main queue. If you need to handle them on a background queue, you must dispatch your handling to a background queue in your implementation of the delegate method.

-serialPortserialPortWasRemovedFromSystem: is called when a serial port is removed from the system, for example because a USB to serial adapter was unplugged. This method is required because you must release your reference to an ORSSerialPort instance when it is removed. The behavior of ORSSerialPort instances whose underlying serial port has been removed from the system is undefined.

The optional methods' function can easily be discerned from their name. Note that -serialPort:didEncounterError: is always used to report errors. None of ORSSerialPort's methods take an NSError object passed in by reference.

As its name implies, -serialPort:didReceiveData: is always called when data is received from the serial port. Internally, ORSSerialPort receives data on a background queue to avoid burdening the main queue with waiting for data. As with all other delegate methods, -serialPort:didReceiveData: is called on the main queue.

-serialPort:didReceivePacket:matchingDescriptor: is called when a complete packet matching a descriptor previously passed to -startListeningForPacketsMatchingDescriptor: is received. See the Packet Parsing API Documentation for more information. Note that -serialPort:didReceiveData: is always also called when data is received, even if the data is (possibly) part of a larget incoming packet. If you're exclusively using the packet parsing API (or request/response API), you should probably ignore or not implement -serialPort:didReceiveData:.

-serialPort:didReceiveResponse:toRequest: is called when a complete, valid response packet to a previously sent ORSSerialRequest is received. Again note that -serialPort:didReceiveData: is always also called when data is received, even if the data is (possibly) in response to a pending request.