From c70702e0d9e5bf5586c9e243ba77e254298ed117 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Sun, 7 Jun 2015 12:36:57 -0600 Subject: [PATCH 01/55] Issue #57: Added -cancelQueuedRequest: and -cancelAllQueuedRequests methods. --- Source/ORSSerialPort.h | 20 ++++++++++++++++++++ Source/ORSSerialPort.m | 18 ++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/Source/ORSSerialPort.h b/Source/ORSSerialPort.h index 8f1be513..bb156c30 100644 --- a/Source/ORSSerialPort.h +++ b/Source/ORSSerialPort.h @@ -263,6 +263,26 @@ NS_ASSUME_NONNULL_BEGIN */ - (BOOL)sendRequest:(ORSSerialRequest *)request; +/** + * Cancels a queued (not yet sent) request. The request is removed from the requests + * queue and will not be sent. + * + * Note that a pending request cannot be cancelled, as it has already been sent and is + * awaiting a response. If a pending request is passed in, this method will simply + * do nothing. + * + * @param request The pending request to be cancelled. + */ +- (void)cancelQueuedRequest:(ORSSerialRequest *)request; + +/** + * Cancels all queued requests. The requests queue is emptied. + * + * Note that if there is a pending request, it is not cancelled, as it has already + * been sent and is awaiting a response. + */ +- (void)cancelAllQueuedRequests; + /** --------------------------------------------------------------------------------------- * @name Delegate * --------------------------------------------------------------------------------------- diff --git a/Source/ORSSerialPort.m b/Source/ORSSerialPort.m index dfe5da6d..f94c6685 100644 --- a/Source/ORSSerialPort.m +++ b/Source/ORSSerialPort.m @@ -451,6 +451,24 @@ - (BOOL)sendRequest:(ORSSerialRequest *)request return success; } +- (void)cancelQueuedRequest:(ORSSerialRequest *)request +{ + if (!request) return; + dispatch_async(self.requestHandlingQueue, ^{ + if (request == self.pendingRequest) return; + NSInteger requestIndex = [self.requestsQueue indexOfObject:request]; + if (requestIndex == NSNotFound) return; + [self removeObjectFromRequestsQueueAtIndex:requestIndex]; + }); +} + +- (void)cancelAllQueuedRequests +{ + dispatch_async(self.requestHandlingQueue, ^{ + self.requestsQueue = [NSMutableArray array]; + }); +} + #pragma mark - Private Methods // Must only be called on requestHandlingQueue (ie. wrap call to this method in dispatch()) From 14e493f6f1fc0b54897f56b176070841b4d28009 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 29 Jun 2015 14:00:17 -0600 Subject: [PATCH 02/55] Issue #58: Annotated ORSSerialPort API using ObjC generics. --- Source/ORSSerialPort.h | 10 +++++++++- Source/ORSSerialPortManager.h | 12 +++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Source/ORSSerialPort.h b/Source/ORSSerialPort.h index 8f1be513..6d4fb244 100644 --- a/Source/ORSSerialPort.h +++ b/Source/ORSSerialPort.h @@ -37,6 +37,14 @@ #define __nullable #endif +#ifndef ORSArrayOf + #if __has_feature(objc_generics) + #define ORSArrayOf(TYPE) NSArray + #else + #define ORSArrayOf(TYPE) NSArray + #endif +#endif // #ifndef ORSArrayOf + //#define LOG_SERIAL_PORT_ERRORS typedef NS_ENUM(NSUInteger, ORSSerialPortParity) { ORSSerialPortParityNone = 0, @@ -301,7 +309,7 @@ NS_ASSUME_NONNULL_BEGIN * @note This array does not contain the pending request, a sent request for which * the port is awaiting a response. */ -@property (strong, readonly) NSArray *queuedRequests; +@property (strong, readonly) ORSArrayOf(ORSSerialRequest *) *queuedRequests; /** --------------------------------------------------------------------------------------- * @name Port Properties diff --git a/Source/ORSSerialPortManager.h b/Source/ORSSerialPortManager.h index d20df87c..d51c0981 100644 --- a/Source/ORSSerialPortManager.h +++ b/Source/ORSSerialPortManager.h @@ -35,6 +35,14 @@ #define __nullable #endif +#ifndef ORSArrayOf + #if __has_feature(objc_generics) + #define ORSArrayOf(TYPE) NSArray + #else + #define ORSArrayOf(TYPE) NSArray + #endif +#endif // #ifndef ORSArrayOf + NS_ASSUME_NONNULL_BEGIN /// Posted when a serial port is connected to the system @@ -48,6 +56,8 @@ extern NSString * const ORSConnectedSerialPortsKey; /// Key for disconnected port in ORSSerialPortWasDisconnectedNotification userInfo dictionary extern NSString * const ORSDisconnectedSerialPortsKey; +@class ORSSerialPort; + /** * `ORSSerialPortManager` is a singleton class (one instance per * application) that can be used to get a list of available serial ports. @@ -119,7 +129,7 @@ extern NSString * const ORSDisconnectedSerialPortsKey; * to easily give the user a way to select an available port * on the system. */ -@property (nonatomic, copy, readonly) NSArray *availablePorts; +@property (nonatomic, copy, readonly) ORSArrayOf(ORSSerialPort *) *availablePorts; @end From 4717ecd7e7f5d205f464ac1d172b70b6a4f95dc7 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 6 Jul 2015 16:13:41 -0600 Subject: [PATCH 03/55] Updated ObjC RequestResponseDemo project to latest recommended settings. --- .../RequestResponseDemo.xcodeproj/project.pbxproj | 5 ++++- .../RequestResponseDemo/Objective-C/Resources/Info.plist | 2 +- .../xcshareddata/xcschemes/ORSSerial.xcscheme | 5 ++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Examples/RequestResponseDemo/Objective-C/RequestResponseDemo.xcodeproj/project.pbxproj b/Examples/RequestResponseDemo/Objective-C/RequestResponseDemo.xcodeproj/project.pbxproj index 797231de..809e944d 100644 --- a/Examples/RequestResponseDemo/Objective-C/RequestResponseDemo.xcodeproj/project.pbxproj +++ b/Examples/RequestResponseDemo/Objective-C/RequestResponseDemo.xcodeproj/project.pbxproj @@ -172,7 +172,7 @@ isa = PBXProject; attributes = { CLASSPREFIX = ORS; - LastUpgradeCheck = 0610; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Open Reel Software"; TargetAttributes = { 9DCDDB921AB48F5300F8347E = { @@ -263,6 +263,7 @@ CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -326,6 +327,7 @@ COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -337,6 +339,7 @@ COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; diff --git a/Examples/RequestResponseDemo/Objective-C/Resources/Info.plist b/Examples/RequestResponseDemo/Objective-C/Resources/Info.plist index ff83c78c..ea5fbb59 100644 --- a/Examples/RequestResponseDemo/Objective-C/Resources/Info.plist +++ b/Examples/RequestResponseDemo/Objective-C/Resources/Info.plist @@ -9,7 +9,7 @@ CFBundleIconFile CFBundleIdentifier - com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcschemes/ORSSerial.xcscheme b/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcschemes/ORSSerial.xcscheme index 1f832b2e..f2c676fd 100644 --- a/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcschemes/ORSSerial.xcscheme +++ b/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcschemes/ORSSerial.xcscheme @@ -1,6 +1,6 @@ + + Date: Mon, 6 Jul 2015 16:15:23 -0600 Subject: [PATCH 04/55] RequestResponseDemo (ObjC): Fixed warning logged at runtime due to orphaned connection in Main.storyboard. --- .../Objective-C/Resources/Main.storyboard | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Examples/RequestResponseDemo/Objective-C/Resources/Main.storyboard b/Examples/RequestResponseDemo/Objective-C/Resources/Main.storyboard index f35e9e41..7c1292ee 100644 --- a/Examples/RequestResponseDemo/Objective-C/Resources/Main.storyboard +++ b/Examples/RequestResponseDemo/Objective-C/Resources/Main.storyboard @@ -1,8 +1,8 @@ - + - + @@ -728,7 +728,6 @@ - From 43edf1c08ea9eb80b20252eafdd07dd5916844fd Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 6 Jul 2015 16:35:44 -0600 Subject: [PATCH 05/55] Issue #52: Switched to using a dispatch source for reading from the underlying port. --- Source/ORSSerialPort.m | 65 +++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/Source/ORSSerialPort.m b/Source/ORSSerialPort.m index dfe5da6d..1767c24b 100644 --- a/Source/ORSSerialPort.m +++ b/Source/ORSSerialPort.m @@ -73,11 +73,13 @@ @interface ORSSerialPort () @property (nonatomic, readwrite) BOOL DCD; #if OS_OBJECT_USE_OBJC +@property (nonatomic, strong) dispatch_source_t readPollSource; @property (nonatomic, strong) dispatch_source_t pinPollTimer; @property (nonatomic, strong) dispatch_source_t pendingRequestTimeoutTimer; @property (nonatomic, strong) dispatch_queue_t requestHandlingQueue; @property (nonatomic, strong) dispatch_semaphore_t selectSemaphore; #else +@property (nonatomic) dispatch_source_t readPollSource; @property (nonatomic) dispatch_source_t pinPollTimer; @property (nonatomic) dispatch_source_t pendingRequestTimeoutTimer; @property (nonatomic) dispatch_queue_t requestHandlingQueue; @@ -202,6 +204,11 @@ - (void)dealloc [[self class] removeSerialPort:self]; self.IOKitDevice = 0; + if (_readPollSource) { + dispatch_source_cancel(_readPollSource); + ORS_GCD_RELEASE(_readPollSource); + } + if (_pinPollTimer) { dispatch_source_cancel(_pinPollTimer); ORS_GCD_RELEASE(_pinPollTimer); @@ -284,44 +291,24 @@ - (void)open; }); } - // Start a read poller in the background - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + // Start a read dispatch source in the background + dispatch_source_t readPollSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, self.fileDescriptor, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); + dispatch_source_set_event_handler(readPollSource, ^{ int localPortFD = self.fileDescriptor; - struct timeval timeout; - int result=0; + if (!self.isOpen) return; - while (self.isOpen) + // Data is available + char buf[1024]; + long lengthRead = read(localPortFD, buf, sizeof(buf)); + if (lengthRead>0) { - fd_set localReadFDSet; - FD_ZERO(&localReadFDSet); - FD_SET(localPortFD, &localReadFDSet); - - timeout.tv_sec = 0; - timeout.tv_usec = 100000; // Check to see if port closed every 100ms - - dispatch_semaphore_wait(self.selectSemaphore, DISPATCH_TIME_FOREVER); - result = select(localPortFD+1, &localReadFDSet, NULL, NULL, &timeout); - dispatch_semaphore_signal(self.selectSemaphore); - if (!self.isOpen) break; // Port closed while select call was waiting - if (result < 0) - { - [self notifyDelegateOfPosixError]; - continue; - } - - if (result == 0 || !FD_ISSET(localPortFD, &localReadFDSet)) continue; - - // Data is available - char buf[1024]; - long lengthRead = read(localPortFD, buf, sizeof(buf)); - if (lengthRead>0) - { - NSData *readData = [NSData dataWithBytes:buf length:lengthRead]; - if (readData != nil) [self receiveData:readData]; - } + NSData *readData = [NSData dataWithBytes:buf length:lengthRead]; + if (readData != nil) [self receiveData:readData]; } }); + dispatch_resume(readPollSource); + self.readPollSource = readPollSource; // Start another poller to check status of CTS and DSR dispatch_queue_t pollQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); @@ -365,6 +352,7 @@ - (BOOL)close; { if (!self.isOpen) return YES; + self.readPollSource = nil; // Stop and dispose of read dispatch source self.pinPollTimer = nil; // Stop polling CTS/DSR/DCD pins dispatch_semaphore_wait(self.selectSemaphore, DISPATCH_TIME_FOREVER); @@ -894,6 +882,19 @@ - (void)setDTR:(BOOL)flag #pragma mark Private Properties +- (void)setReadPollSource:(dispatch_source_t)readPollSource +{ + if (readPollSource != _readPollSource) { + if (_readPollSource) { + dispatch_source_cancel(_readPollSource); + ORS_GCD_RELEASE(_readPollSource); + } + + ORS_GCD_RETAIN(readPollSource); + _readPollSource = readPollSource; + } +} + - (void)setPinPollTimer:(dispatch_source_t)timer { if (timer != _pinPollTimer) From d998120595531f2d9af369824170f3a503f4f312 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 6 Jul 2015 16:37:03 -0600 Subject: [PATCH 06/55] Issue #52: Bumped deployment target for framework to 10.7 because dispatch source for reads doesn't work on 10.6. --- Framework Project/ORSSerialPort.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj b/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj index c187e19a..f8f21bc8 100644 --- a/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj +++ b/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj @@ -219,7 +219,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + MACOSX_DEPLOYMENT_TARGET = 10.7; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -257,7 +257,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + MACOSX_DEPLOYMENT_TARGET = 10.7; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; VERSIONING_SYSTEM = "apple-generic"; From ec30e6cde946736c83b924c5027a2221b4506fe0 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 6 Jul 2015 16:43:23 -0600 Subject: [PATCH 07/55] Issue #57: More documentation of -cancelQueuedRequest:. --- Source/ORSSerialPort.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Source/ORSSerialPort.h b/Source/ORSSerialPort.h index bb156c30..f002d325 100644 --- a/Source/ORSSerialPort.h +++ b/Source/ORSSerialPort.h @@ -264,12 +264,15 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)sendRequest:(ORSSerialRequest *)request; /** - * Cancels a queued (not yet sent) request. The request is removed from the requests - * queue and will not be sent. + * Requests the cancellation of a queued (not yet sent) request. The request + * is removed from the requests queue and will not be sent. * * Note that a pending request cannot be cancelled, as it has already been sent and is * awaiting a response. If a pending request is passed in, this method will simply - * do nothing. + * do nothing. Because the requests queue is handled in the background, occasionally + * a request may leave the queue and becoming pending after this method is called, + * causing cancellation to fail. If you need to absolutely guarantee that a request + * is not sent you should avoid sending it rather than depending on later cancellation. * * @param request The pending request to be cancelled. */ From 9157ba3f87931b245dffb943475116108515eaa8 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Fri, 31 Jul 2015 14:51:20 -0600 Subject: [PATCH 08/55] Issue #52: Removed selectSemaphore from ORSSerialPort (was already half gone). --- Source/ORSSerialPort.m | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/Source/ORSSerialPort.m b/Source/ORSSerialPort.m index 9e550125..e2adf6ac 100644 --- a/Source/ORSSerialPort.m +++ b/Source/ORSSerialPort.m @@ -77,13 +77,11 @@ @interface ORSSerialPort () @property (nonatomic, strong) dispatch_source_t pinPollTimer; @property (nonatomic, strong) dispatch_source_t pendingRequestTimeoutTimer; @property (nonatomic, strong) dispatch_queue_t requestHandlingQueue; -@property (nonatomic, strong) dispatch_semaphore_t selectSemaphore; #else @property (nonatomic) dispatch_source_t readPollSource; @property (nonatomic) dispatch_source_t pinPollTimer; @property (nonatomic) dispatch_source_t pendingRequestTimeoutTimer; @property (nonatomic) dispatch_queue_t requestHandlingQueue; -@property (nonatomic) dispatch_semaphore_t selectSemaphore; #endif @end @@ -174,7 +172,6 @@ - (instancetype)initWithDevice:(io_object_t)device; self.receiveBuffer = [NSMutableData data]; self.requestHandlingQueue = dispatch_queue_create("com.openreelsoftware.ORSSerialPort.requestHandlingQueue", 0); self.requestsQueue = [NSMutableArray array]; - self.selectSemaphore = dispatch_semaphore_create(1); self.baudRate = @B19200; self.allowsNonStandardBaudRates = NO; self.numberOfStopBits = 1; @@ -215,7 +212,6 @@ - (void)dealloc } self.requestHandlingQueue = nil; - self.selectSemaphore = nil; } - (NSString *)description @@ -355,7 +351,6 @@ - (BOOL)close; self.readPollSource = nil; // Stop and dispose of read dispatch source self.pinPollTimer = nil; // Stop polling CTS/DSR/DCD pins - dispatch_semaphore_wait(self.selectSemaphore, DISPATCH_TIME_FOREVER); // The next tcsetattr() call can fail if the port is waiting to send data. This is likely to happen // e.g. if flow control is on and the CTS line is low. So, turn off flow control before proceeding struct termios options; @@ -378,7 +373,6 @@ - (BOOL)close; [self notifyDelegateOfPosixError]; return NO; } - dispatch_semaphore_signal(self.selectSemaphore); if ([self.delegate respondsToSelector:@selector(serialPortWasClosed:)]) { @@ -951,13 +945,4 @@ - (void)setRequestHandlingQueue:(dispatch_queue_t)requestHandlingQueue } } -- (void)setSelectSemaphore:(dispatch_semaphore_t)selectSemaphore -{ - if (selectSemaphore != _selectSemaphore) { - ORS_GCD_RELEASE(_selectSemaphore); - ORS_GCD_RETAIN(selectSemaphore); - _selectSemaphore = selectSemaphore; - } -} - @end From 6679176359d860d0806cf9db9e6585be85ec1746 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Fri, 31 Jul 2015 14:52:49 -0600 Subject: [PATCH 09/55] Updated podspec for version 2.0 and 10.7 deployment target. --- ORSSerialPort.podspec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ORSSerialPort.podspec b/ORSSerialPort.podspec index 2c6d707f..c16f0303 100644 --- a/ORSSerialPort.podspec +++ b/ORSSerialPort.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "ORSSerialPort" - s.version = "1.8.1" + s.version = "2.0" s.summary = "Easy to use serial port library for Objective-C and Swift Mac apps." s.description = <<-DESC @@ -54,7 +54,7 @@ Pod::Spec.new do |s| # the deployment target. You can optionally include the target after the platform. # - s.platform = :osx, "10.6" + s.platform = :osx, "10.7" # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # # @@ -62,7 +62,7 @@ Pod::Spec.new do |s| # Supports git, hg, bzr, svn and HTTP. # - s.source = { :git => "https://github.com/armadsen/ORSSerialPort.git", :tag => "1.8.1" } + s.source = { :git => "https://github.com/armadsen/ORSSerialPort.git", :tag => "2.0" } # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # From 86e1239f79c51a7daa29e1a3540dec49d17c2c6e Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 3 Aug 2015 12:29:10 -0600 Subject: [PATCH 10/55] Issue #55: Added ORSSerialPacketDescriptor and associated API, along with unit tests. --- Framework Project/ORSSerial.h | 3 +- .../ORSSerialPort Tests/Info.plist | 24 +++ .../ORSSerialPacketDescriptor_Tests.m | 187 ++++++++++++++++++ .../ORSSerialPort Tests/ORSSerialPort_Tests.m | 40 ++++ .../ORSSerialPort.xcodeproj/project.pbxproj | 149 +++++++++++++- .../xcshareddata/xcschemes/ORSSerial.xcscheme | 19 ++ Source/ORSSerialPacketDescriptor.h | 80 ++++++++ Source/ORSSerialPacketDescriptor.m | 78 ++++++++ Source/ORSSerialPort.h | 20 ++ Source/ORSSerialPort.m | 53 ++++- Source/ORSSerialRequest.h | 7 +- Source/ORSSerialRequest.m | 6 +- 12 files changed, 654 insertions(+), 12 deletions(-) create mode 100644 Framework Project/ORSSerialPort Tests/Info.plist create mode 100644 Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m create mode 100644 Framework Project/ORSSerialPort Tests/ORSSerialPort_Tests.m create mode 100644 Source/ORSSerialPacketDescriptor.h create mode 100644 Source/ORSSerialPacketDescriptor.m diff --git a/Framework Project/ORSSerial.h b/Framework Project/ORSSerial.h index 05306af4..756f1cd4 100644 --- a/Framework Project/ORSSerial.h +++ b/Framework Project/ORSSerial.h @@ -8,4 +8,5 @@ #import #import -#import \ No newline at end of file +#import +#import \ No newline at end of file diff --git a/Framework Project/ORSSerialPort Tests/Info.plist b/Framework Project/ORSSerialPort Tests/Info.plist new file mode 100644 index 00000000..be2cb8f3 --- /dev/null +++ b/Framework Project/ORSSerialPort Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m b/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m new file mode 100644 index 00000000..7ec95c51 --- /dev/null +++ b/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m @@ -0,0 +1,187 @@ +// +// ORSSerialPacketDescriptor_Tests.m +// ORSSerialPort +// +// Created by Andrew Madsen on 8/1/15. +// Copyright (c) 2015 Open Reel Software. All rights reserved. +// + +#import +#import +#import + +#define ORSTStringToData_(x) [x dataUsingEncoding:NSASCIIStringEncoding] + +@interface ORSSerialPort (Private) + +- (void)receiveData:(NSData *)data; + +@end + +@interface ORSSerialPacketDescriptor_Tests : XCTestCase + +@property (nonatomic, strong) ORSSerialPort *port; + +@end + +@implementation ORSSerialPacketDescriptor_Tests + +- (void)setUp +{ + [super setUp]; + self.port = [[ORSSerialPort alloc] initWithDevice:-1]; + self.port.delegate = self; +} + +- (void)tearDown +{ + [super tearDown]; + self.port.delegate = nil; + self.port = nil; +} + +#pragma mark - Test Cases + +- (void)testPrefixSuffix +{ + NSData *prefix = [@"!" dataUsingEncoding:NSASCIIStringEncoding]; + NSData *suffix = [@";" dataUsingEncoding:NSASCIIStringEncoding]; + ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithPrefix:prefix suffix:suffix userInfo:nil]; + XCTAssertNotNil(descriptor, @"Creating packet descriptor with prefix and suffix failed."); + XCTAssertEqualObjects(descriptor.prefix, prefix, @"Desriptor prefix property incorrect."); + XCTAssertEqualObjects(descriptor.suffix, suffix, @"Desriptor suffix property incorrect."); + + XCTAssertTrue([descriptor dataIsValidPacket:ORSTStringToData_(@"!foo;")], @"Valid packet rejected by descriptor."); + XCTAssertTrue([descriptor dataIsValidPacket:ORSTStringToData_(@"!;")], @"Valid packet rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"!foo")], @"Invalid packet not rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"foo;")], @"Invalid packet not rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"foo")], @"Invalid packet not rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"x!foo;")], @"Invalid packet not rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"!foo;x")], @"Invalid packet not rejected by descriptor."); +} + +- (void)testRegex +{ + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^!.+;$" options:0 error:NULL]; + ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithRegularExpression:regex userInfo:nil]; + XCTAssertNotNil(descriptor, @"Creating packet descriptor with regular expression failed."); + XCTAssertEqualObjects(descriptor.regularExpression, regex, @"Descriptor regex property incorrect."); + + XCTAssertTrue([descriptor dataIsValidPacket:ORSTStringToData_(@"!foo;")], @"Valid packet rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"!;")], @"Invalid packet not rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"!foo")], @"Invalid packet not rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"foo;")], @"Invalid packet not rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"foo")], @"Invalid packet not rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"x!foo;")], @"Invalid packet not rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"!foo;x")], @"Invalid packet not rejected by descriptor."); +} + +- (void)testParsingWithLeadingBadData +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Leading bad data packet parsing expectation"]; + NSDictionary *userInfo = @{[@"!bar;" dataUsingEncoding:NSASCIIStringEncoding]: expectation}; + ORSSerialPacketDescriptor *descriptor = [self defaultPacketDescriptorWithUserInfo:userInfo]; + [self.port startListeningForPacketsMatchingDescriptor:descriptor]; + + NSData *buffer = [@"!fo!bar;" dataUsingEncoding:NSASCIIStringEncoding]; + [self.port receiveData:buffer]; + + [self waitForExpectationsWithTimeout:0.5 handler:^(NSError *error) { + if (error) { + NSLog(@"expectation %@ failed: %@", expectation, error); + } + }]; +} + +- (void)testParsingMultipleDifferentPackets +{ + XCTestExpectation *expectation1 = [self expectationWithDescription:@"Multiple packets type 1 parsing expectation"]; + XCTestExpectation *expectation2 = [self expectationWithDescription:@"Multiple packets type 2 parsing expectation"]; + + NSDictionary *userInfo1 = @{[@"!foo;" dataUsingEncoding:NSASCIIStringEncoding]: expectation1}; + NSDictionary *userInfo2 = @{[@"$bar;" dataUsingEncoding:NSASCIIStringEncoding]: expectation2}; + ORSSerialPacketDescriptor *descriptor1 = [self defaultPacketDescriptorWithUserInfo:userInfo1]; + ORSSerialPacketDescriptor *descriptor2 = [[ORSSerialPacketDescriptor alloc] initWithPrefix:[@"$" dataUsingEncoding:NSASCIIStringEncoding] + suffix:[@";" dataUsingEncoding:NSASCIIStringEncoding] + userInfo:userInfo2]; + [self.port startListeningForPacketsMatchingDescriptor:descriptor1]; + [self.port startListeningForPacketsMatchingDescriptor:descriptor2]; + + [self.port receiveData:[@"$bar" dataUsingEncoding:NSASCIIStringEncoding]]; + [self.port receiveData:[@";!foo;" dataUsingEncoding:NSASCIIStringEncoding]]; + + [self waitForExpectationsWithTimeout:0.5 handler:^(NSError *error) { + if (error) { + NSLog(@"expectations failed: %@", error); + } + }]; +} + +- (void)testParsingMultipleSimilarPackets +{ + XCTestExpectation *expectation1 = [self expectationWithDescription:@"Multiple packets parsing expectation 1"]; + XCTestExpectation *expectation2 = [self expectationWithDescription:@"Multiple packets parsing expectation 2"]; + NSDictionary *userInfo1 = @{[@"!foo;" dataUsingEncoding:NSASCIIStringEncoding]: expectation1}; + NSDictionary *userInfo2 = @{[@"!bar;" dataUsingEncoding:NSASCIIStringEncoding]: expectation2}; + ORSSerialPacketDescriptor *descriptor1 = [self defaultPacketDescriptorWithUserInfo:userInfo1]; + ORSSerialPacketDescriptor *descriptor2 = [self defaultPacketDescriptorWithUserInfo:userInfo2]; + + [self.port startListeningForPacketsMatchingDescriptor:descriptor1]; + [self.port startListeningForPacketsMatchingDescriptor:descriptor2]; + + [self.port receiveData:[@"!ba" dataUsingEncoding:NSASCIIStringEncoding]]; + [self.port receiveData:[@"r;!fo" dataUsingEncoding:NSASCIIStringEncoding]]; + [self.port receiveData:[@"o;!ba" dataUsingEncoding:NSASCIIStringEncoding]]; + + [self waitForExpectationsWithTimeout:0.5 handler:^(NSError *error) { + if (error) { + NSLog(@"expectations failed: %@", error); + } + }]; +} + +- (void)testParsingNestedPackets +{ + XCTestExpectation *expectation1 = [self expectationWithDescription:@"Nested packets parsing expectation 1"]; + XCTestExpectation *expectation2 = [self expectationWithDescription:@"Nested packets parsing expectation 2"]; + NSDictionary *userInfo1 = @{[@"!foo$bar%;" dataUsingEncoding:NSASCIIStringEncoding]: expectation1}; + NSDictionary *userInfo2 = @{[@"$bar%" dataUsingEncoding:NSASCIIStringEncoding]: expectation2}; + ORSSerialPacketDescriptor *descriptor1 = [self defaultPacketDescriptorWithUserInfo:userInfo1]; + ORSSerialPacketDescriptor *descriptor2 = [[ORSSerialPacketDescriptor alloc] initWithPrefix:[@"$" dataUsingEncoding:NSASCIIStringEncoding] + suffix:[@"%" dataUsingEncoding:NSASCIIStringEncoding] + userInfo:userInfo2]; + [self.port startListeningForPacketsMatchingDescriptor:descriptor1]; + [self.port startListeningForPacketsMatchingDescriptor:descriptor2]; + + [self.port receiveData:[@"!foo" dataUsingEncoding:NSASCIIStringEncoding]]; + [self.port receiveData:[@"$bar" dataUsingEncoding:NSASCIIStringEncoding]]; + [self.port receiveData:[@"%;" dataUsingEncoding:NSASCIIStringEncoding]]; + + [self waitForExpectationsWithTimeout:0.5 handler:^(NSError *error) { + if (error) { + NSLog(@"expectations failed: %@", error); + } + }]; +} + +#pragma mark - Utilties + +- (ORSSerialPacketDescriptor *)defaultPacketDescriptorWithUserInfo:(id)userInfo +{ + NSData *prefix = [@"!" dataUsingEncoding:NSASCIIStringEncoding]; + NSData *suffix = [@";" dataUsingEncoding:NSASCIIStringEncoding]; + return [[ORSSerialPacketDescriptor alloc] initWithPrefix:prefix suffix:suffix userInfo:userInfo]; +} + +#pragma mark - ORSSerialPortDelegate + +- (void)serialPortWasRemovedFromSystem:(ORSSerialPort * __nonnull)serialPort {} + +- (void)serialPort:(ORSSerialPort * __nonnull)serialPort didReceivePacket:(NSData * __nonnull)packetData matchingDescriptor:(ORSSerialPacketDescriptor * __nonnull)descriptor +{ + NSDictionary *userInfo = (NSDictionary *)descriptor.userInfo; + XCTestExpectation *expectation = userInfo[packetData]; + [expectation fulfill]; +} + +@end diff --git a/Framework Project/ORSSerialPort Tests/ORSSerialPort_Tests.m b/Framework Project/ORSSerialPort Tests/ORSSerialPort_Tests.m new file mode 100644 index 00000000..fbfe2052 --- /dev/null +++ b/Framework Project/ORSSerialPort Tests/ORSSerialPort_Tests.m @@ -0,0 +1,40 @@ +// +// ORSSerialPort_Tests.m +// ORSSerialPort Tests +// +// Created by Andrew Madsen on 8/1/15. +// Copyright (c) 2015 Open Reel Software. All rights reserved. +// + +#import +#import + +@interface ORSSerialPort_Tests : XCTestCase + +@end + +@implementation ORSSerialPort_Tests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample { + // This is an example of a functional test case. + XCTAssert(YES, @"Pass"); +} + +- (void)testPerformanceExample { + // This is an example of a performance test case. + [self measureBlock:^{ + // Put the code you want to measure the time of here. + }]; +} + +@end diff --git a/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj b/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj index c187e19a..9f3ea7dd 100644 --- a/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj +++ b/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + 9D7472181B6D7767002D8B10 /* ORSSerialPort_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D7472171B6D7767002D8B10 /* ORSSerialPort_Tests.m */; }; + 9D7472191B6D7767002D8B10 /* ORSSerial.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DCA89121A2BB106009285EB /* ORSSerial.framework */; }; + 9D7472201B6D7787002D8B10 /* ORSSerialPacketDescriptor_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D74721F1B6D7787002D8B10 /* ORSSerialPacketDescriptor_Tests.m */; }; 9DCA89321A2BB15A009285EB /* ORSSerial.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DCA89311A2BB15A009285EB /* ORSSerial.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9DCA893A1A2BB1E2009285EB /* ORSSerialPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DCA89341A2BB1E2009285EB /* ORSSerialPort.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9DCA893B1A2BB1E2009285EB /* ORSSerialPort.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DCA89351A2BB1E2009285EB /* ORSSerialPort.m */; }; @@ -14,11 +17,27 @@ 9DCA893D1A2BB1E2009285EB /* ORSSerialPortManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DCA89371A2BB1E2009285EB /* ORSSerialPortManager.m */; }; 9DCA893E1A2BB1E2009285EB /* ORSSerialRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DCA89381A2BB1E2009285EB /* ORSSerialRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9DCA893F1A2BB1E2009285EB /* ORSSerialRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DCA89391A2BB1E2009285EB /* ORSSerialRequest.m */; }; + 9DD6B1D21B5F4338000AB46E /* ORSSerialPacketDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DD6B1D01B5F4338000AB46E /* ORSSerialPacketDescriptor.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9DD6B1D31B5F4338000AB46E /* ORSSerialPacketDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DD6B1D11B5F4338000AB46E /* ORSSerialPacketDescriptor.m */; }; A933F5991AC33D1700461525 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A933F5981AC33D1700461525 /* IOKit.framework */; }; A933F59B1AC33D2700461525 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A933F59A1AC33D2700461525 /* Cocoa.framework */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 9D74721A1B6D7767002D8B10 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9DCA89091A2BB106009285EB /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9DCA89111A2BB106009285EB; + remoteInfo = ORSSerial; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXFileReference section */ + 9D7472131B6D7767002D8B10 /* ORSSerialPort Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ORSSerialPort Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 9D7472161B6D7767002D8B10 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9D7472171B6D7767002D8B10 /* ORSSerialPort_Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ORSSerialPort_Tests.m; sourceTree = ""; }; + 9D74721F1B6D7787002D8B10 /* ORSSerialPacketDescriptor_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORSSerialPacketDescriptor_Tests.m; sourceTree = ""; }; 9DCA89121A2BB106009285EB /* ORSSerial.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ORSSerial.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9DCA892E1A2BB14B009285EB /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9DCA89311A2BB15A009285EB /* ORSSerial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORSSerial.h; sourceTree = ""; }; @@ -28,11 +47,21 @@ 9DCA89371A2BB1E2009285EB /* ORSSerialPortManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORSSerialPortManager.m; sourceTree = ""; }; 9DCA89381A2BB1E2009285EB /* ORSSerialRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORSSerialRequest.h; sourceTree = ""; }; 9DCA89391A2BB1E2009285EB /* ORSSerialRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORSSerialRequest.m; sourceTree = ""; }; + 9DD6B1D01B5F4338000AB46E /* ORSSerialPacketDescriptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORSSerialPacketDescriptor.h; sourceTree = ""; }; + 9DD6B1D11B5F4338000AB46E /* ORSSerialPacketDescriptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORSSerialPacketDescriptor.m; sourceTree = ""; }; A933F5981AC33D1700461525 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; A933F59A1AC33D2700461525 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 9D7472101B6D7767002D8B10 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9D7472191B6D7767002D8B10 /* ORSSerial.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 9DCA890E1A2BB106009285EB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -45,6 +74,24 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 9D7472141B6D7767002D8B10 /* ORSSerialPort Tests */ = { + isa = PBXGroup; + children = ( + 9D7472171B6D7767002D8B10 /* ORSSerialPort_Tests.m */, + 9D74721F1B6D7787002D8B10 /* ORSSerialPacketDescriptor_Tests.m */, + 9D7472151B6D7767002D8B10 /* Supporting Files */, + ); + path = "ORSSerialPort Tests"; + sourceTree = ""; + }; + 9D7472151B6D7767002D8B10 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 9D7472161B6D7767002D8B10 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; 9DCA89081A2BB106009285EB = { isa = PBXGroup; children = ( @@ -52,6 +99,7 @@ 9DCA89331A2BB1E2009285EB /* Source */, 9DCA89301A2BB14E009285EB /* Resources */, 9DCCC2531AD1D289003E21FC /* Linked Frameworks */, + 9D7472141B6D7767002D8B10 /* ORSSerialPort Tests */, 9DCA89131A2BB106009285EB /* Products */, ); sourceTree = ""; @@ -60,6 +108,7 @@ isa = PBXGroup; children = ( 9DCA89121A2BB106009285EB /* ORSSerial.framework */, + 9D7472131B6D7767002D8B10 /* ORSSerialPort Tests.xctest */, ); name = Products; sourceTree = ""; @@ -81,6 +130,8 @@ 9DCA89371A2BB1E2009285EB /* ORSSerialPortManager.m */, 9DCA89381A2BB1E2009285EB /* ORSSerialRequest.h */, 9DCA89391A2BB1E2009285EB /* ORSSerialRequest.m */, + 9DD6B1D01B5F4338000AB46E /* ORSSerialPacketDescriptor.h */, + 9DD6B1D11B5F4338000AB46E /* ORSSerialPacketDescriptor.m */, ); name = Source; path = ../Source; @@ -104,6 +155,7 @@ files = ( 9DCA893A1A2BB1E2009285EB /* ORSSerialPort.h in Headers */, 9DCA893E1A2BB1E2009285EB /* ORSSerialRequest.h in Headers */, + 9DD6B1D21B5F4338000AB46E /* ORSSerialPacketDescriptor.h in Headers */, 9DCA89321A2BB15A009285EB /* ORSSerial.h in Headers */, 9DCA893C1A2BB1E2009285EB /* ORSSerialPortManager.h in Headers */, ); @@ -112,6 +164,24 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + 9D7472121B6D7767002D8B10 /* ORSSerialPort Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9D74721E1B6D7767002D8B10 /* Build configuration list for PBXNativeTarget "ORSSerialPort Tests" */; + buildPhases = ( + 9D74720F1B6D7767002D8B10 /* Sources */, + 9D7472101B6D7767002D8B10 /* Frameworks */, + 9D7472111B6D7767002D8B10 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 9D74721B1B6D7767002D8B10 /* PBXTargetDependency */, + ); + name = "ORSSerialPort Tests"; + productName = "ORSSerialPort Tests"; + productReference = 9D7472131B6D7767002D8B10 /* ORSSerialPort Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 9DCA89111A2BB106009285EB /* ORSSerial */ = { isa = PBXNativeTarget; buildConfigurationList = 9DCA89281A2BB106009285EB /* Build configuration list for PBXNativeTarget "ORSSerial" */; @@ -139,6 +209,9 @@ LastUpgradeCheck = 0640; ORGANIZATIONNAME = "Open Reel Software"; TargetAttributes = { + 9D7472121B6D7767002D8B10 = { + CreatedOnToolsVersion = 6.4; + }; 9DCA89111A2BB106009285EB = { CreatedOnToolsVersion = 6.1; }; @@ -157,11 +230,19 @@ projectRoot = ""; targets = ( 9DCA89111A2BB106009285EB /* ORSSerial */, + 9D7472121B6D7767002D8B10 /* ORSSerialPort Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 9D7472111B6D7767002D8B10 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 9DCA89101A2BB106009285EB /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -172,11 +253,21 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 9D74720F1B6D7767002D8B10 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9D7472201B6D7787002D8B10 /* ORSSerialPacketDescriptor_Tests.m in Sources */, + 9D7472181B6D7767002D8B10 /* ORSSerialPort_Tests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 9DCA890D1A2BB106009285EB /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 9DCA893F1A2BB1E2009285EB /* ORSSerialRequest.m in Sources */, + 9DD6B1D31B5F4338000AB46E /* ORSSerialPacketDescriptor.m in Sources */, 9DCA893B1A2BB1E2009285EB /* ORSSerialPort.m in Sources */, 9DCA893D1A2BB1E2009285EB /* ORSSerialPortManager.m in Sources */, ); @@ -184,7 +275,53 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 9D74721B1B6D7767002D8B10 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 9DCA89111A2BB106009285EB /* ORSSerial */; + targetProxy = 9D74721A1B6D7767002D8B10 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin XCBuildConfiguration section */ + 9D74721C1B6D7767002D8B10 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "ORSSerialPort Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 9D74721D1B6D7767002D8B10 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = "ORSSerialPort Tests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.10; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; 9DCA89261A2BB106009285EB /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -219,7 +356,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + MACOSX_DEPLOYMENT_TARGET = 10.7; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -257,7 +394,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + MACOSX_DEPLOYMENT_TARGET = 10.7; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; VERSIONING_SYSTEM = "apple-generic"; @@ -307,6 +444,14 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 9D74721E1B6D7767002D8B10 /* Build configuration list for PBXNativeTarget "ORSSerialPort Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9D74721C1B6D7767002D8B10 /* Debug */, + 9D74721D1B6D7767002D8B10 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; 9DCA890C1A2BB106009285EB /* Build configuration list for PBXProject "ORSSerialPort" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcschemes/ORSSerial.xcscheme b/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcschemes/ORSSerial.xcscheme index 1f832b2e..02e1458e 100644 --- a/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcschemes/ORSSerial.xcscheme +++ b/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcschemes/ORSSerial.xcscheme @@ -28,7 +28,26 @@ shouldUseLaunchSchemeArgsEnv = "YES" buildConfiguration = "Debug"> + + + + + + + + + +// Keep older versions of the compiler happy +#ifndef NS_ASSUME_NONNULL_BEGIN +#define NS_ASSUME_NONNULL_BEGIN +#define NS_ASSUME_NONNULL_END +#define nullable +#define nonnullable +#define __nullable +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** + * Block that parses input data and returns a packet extracted from that data, or nil + * if inputData doesn't contain a valid packet. + */ +typedef BOOL(^ORSSerialResponseEvaluator)(NSData * __nullable inputData); + +/** + * An instance of ORSSerialPacketDescriptor is used to describe a packet format. ORSSerialPort + * can use these to "packetize" incoming data. Normally, bytes received by a serial port are + * delivered as they are received, often one or two bytes at a time. Responsibility for buffering + * incoming bytes, determining when a complete packet has been received, then parsing and processing + * the packet is left to the client of ORSSerialPort. + * + * Rather than writing manual buffering and packet checking code, one or more packet descriptors + * can be installed on the port, and the port will call the -serialPort:didReceivePacket:matchingDescriptor: + * method on its delegate when a complete packet is received. + * + * Note that this API is intended to be used with data that is sent by a serial device periodically, + * or in response to real world events, rather than in response to serial requests sent by the computer. + * For request/response protocols, see ORSSerialRequest, etc. + * + */ +@interface ORSSerialPacketDescriptor : NSObject + +- (instancetype)initWithUserInfo:(nullable id)userInfo + responseEvaluator:(ORSSerialResponseEvaluator)responseEvaluator NS_DESIGNATED_INITIALIZER; + +- (instancetype)initWithPrefix:(nullable NSData *)prefix + suffix:(nullable NSData *)suffix + userInfo:(nullable id)userInfo; + +- (instancetype)initWithRegularExpression:(NSRegularExpression *)regex + userInfo:(nullable id)userInfo; + +/** + * Can be used to determine if a block of data is a valid packet matching the descriptor encapsulated + * by the receiver. + * + * @param packetData Data received from a serial port. + * + * @return YES if the data is a valid packet, NO otherwise. + */ +- (BOOL)dataIsValidPacket:(nullable NSData *)packetData; + +@property (nonatomic, strong, readonly, nullable) NSData *prefix; +@property (nonatomic, strong, readonly, nullable) NSData *suffix; +@property (nonatomic, strong, readonly, nullable) NSRegularExpression *regularExpression; + +/** + * Arbitrary object (e.g. NSDictionary) used to store additional data + * about the packet descriptor. + */ +@property (nonatomic, strong, readonly, nullable) id userInfo; + +@property (nonatomic, strong, readonly) NSUUID *uuid; + +@end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/Source/ORSSerialPacketDescriptor.m b/Source/ORSSerialPacketDescriptor.m new file mode 100644 index 00000000..4000aa2d --- /dev/null +++ b/Source/ORSSerialPacketDescriptor.m @@ -0,0 +1,78 @@ +// +// ORSSerialPacketDescriptor.m +// ORSSerialPort +// +// Created by Andrew Madsen on 7/21/15. +// Copyright (c) 2015 Open Reel Software. All rights reserved. +// + +#import "ORSSerialPacketDescriptor.h" + +@interface ORSSerialPacketDescriptor () + +@property (nonatomic, copy, readonly) ORSSerialResponseEvaluator responseEvaluator; + +@end + +@implementation ORSSerialPacketDescriptor + +- (instancetype)initWithUserInfo:(id)userInfo responseEvaluator:(ORSSerialResponseEvaluator)responseEvaluator +{ + self = [super init]; + if (self) { + _userInfo = userInfo; + _responseEvaluator = [responseEvaluator ?: ^BOOL(NSData *d){ return [d length] > 0; } copy]; + _uuid = [NSUUID UUID]; + } + return self; +} + +- (instancetype)initWithPrefix:(NSData *)prefix suffix:(NSData *)suffix userInfo:(id)userInfo +{ + self = [self initWithUserInfo:userInfo responseEvaluator:^BOOL(NSData *data) { + NSRange fullRange = NSMakeRange(0, [data length]); + NSRange prefixRange = NSMakeRange(0, 0); + if (prefix) prefixRange = [data rangeOfData:prefix options:NSDataSearchAnchored range:fullRange]; + NSRange suffixRange = NSMakeRange([data length]-1, 0); + if (suffix) suffixRange = [data rangeOfData:suffix options:NSDataSearchAnchored | NSDataSearchBackwards range:fullRange]; + + return prefixRange.location != NSNotFound && suffixRange.location != NSNotFound; + }]; + if (self) { + _prefix = prefix; + _suffix = suffix; + } + return self; +} + +- (instancetype)initWithRegularExpression:(NSRegularExpression *)regex + userInfo:(nullable id)userInfo +{ + self = [self initWithUserInfo:userInfo responseEvaluator:^BOOL(NSData *data) { + NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + if (!string) return NO; + + return [regex numberOfMatchesInString:string options:NSMatchingAnchored range:NSMakeRange(0, [string length])] > 0; + }]; + if (self) { + _regularExpression = regex; + } + return self; +} + +- (BOOL)isEqual:(id)object +{ + if (object == self) return YES; + if (![object isKindOfClass:[ORSSerialPacketDescriptor class]]) return NO; + return [[(ORSSerialPacketDescriptor *)object uuid] isEqual:self.uuid]; +} + +- (NSUInteger)hash { return [self.uuid hash]; } + +- (BOOL)dataIsValidPacket:(nullable NSData *)packetData +{ + if (!self.responseEvaluator) return YES; + return self.responseEvaluator(packetData); +} + +@end diff --git a/Source/ORSSerialPort.h b/Source/ORSSerialPort.h index 8f1be513..619d2ef4 100644 --- a/Source/ORSSerialPort.h +++ b/Source/ORSSerialPort.h @@ -47,6 +47,7 @@ typedef NS_ENUM(NSUInteger, ORSSerialPortParity) { @protocol ORSSerialPortDelegate; @class ORSSerialRequest; +@class ORSSerialPacketDescriptor; NS_ASSUME_NONNULL_BEGIN @@ -263,6 +264,15 @@ NS_ASSUME_NONNULL_BEGIN */ - (BOOL)sendRequest:(ORSSerialRequest *)request; +/** --------------------------------------------------------------------------------------- + * @name Listening For Packets + * --------------------------------------------------------------------------------------- + */ + +- (void)startListeningForPacketsMatchingDescriptor:(ORSSerialPacketDescriptor *)descriptor; + +- (void)stopListeningForPacketsMatchingDescriptor:(ORSSerialPacketDescriptor *)descriptor; + /** --------------------------------------------------------------------------------------- * @name Delegate * --------------------------------------------------------------------------------------- @@ -523,6 +533,16 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)serialPort:(ORSSerialPort *)serialPort didReceiveResponse:(NSData *)responseData toRequest:(ORSSerialRequest *)request; +/** + * Called when a valid, complete packet matching a descriptor installed with + * -startListeningForPacketsMatchingDescriptor: is received. + * + * @param serialPort The `ORSSerialPort` instance representing the port that received `packetData`. + * @param responseData The An `NSData` instance containing the received packet data. + * @param descriptor The packet descriptor object for which packetData is a match. + */ +- (void)serialPort:(ORSSerialPort *)serialPort didReceivePacket:(NSData *)packetData matchingDescriptor:(ORSSerialPacketDescriptor *)descriptor; + /** * Called when a the timeout interval for a previously sent request elapses without a valid * response having been received. diff --git a/Source/ORSSerialPort.m b/Source/ORSSerialPort.m index dfe5da6d..919965c9 100644 --- a/Source/ORSSerialPort.m +++ b/Source/ORSSerialPort.m @@ -64,6 +64,9 @@ @interface ORSSerialPort () @property (strong) NSMutableData *receiveBuffer; +// Packet descriptors +@property (nonatomic, strong) NSMapTable *packetDescriptorsAndBuffers; + // Request handling @property (nonatomic, strong) NSMutableArray *requestsQueue; @property (nonatomic, strong, readwrite) ORSSerialRequest *pendingRequest; @@ -171,6 +174,11 @@ - (instancetype)initWithDevice:(io_object_t)device; self.name = [[self class] modemNameFromDevice:device]; self.receiveBuffer = [NSMutableData data]; self.requestHandlingQueue = dispatch_queue_create("com.openreelsoftware.ORSSerialPort.requestHandlingQueue", 0); +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_8 + self.packetDescriptorsAndBuffers = [NSMapTable strongToStrongObjectsMapTable]; +#else + self.packetDescriptorsAndBuffers = [NSMapTable mapTableWithStrongToStrongObjects]; // Deprecated in 10.8. +#endif self.requestsQueue = [NSMutableArray array]; self.selectSemaphore = dispatch_semaphore_create(1); self.baudRate = @B19200; @@ -451,8 +459,44 @@ - (BOOL)sendRequest:(ORSSerialRequest *)request return success; } +- (void)startListeningForPacketsMatchingDescriptor:(ORSSerialPacketDescriptor *)descriptor; +{ + if ([self.packetDescriptorsAndBuffers objectForKey:descriptor]) return; // Already listening + + [self.packetDescriptorsAndBuffers setObject:[NSMutableData data] forKey:descriptor]; +} + +- (void)stopListeningForPacketsMatchingDescriptor:(ORSSerialPacketDescriptor *)descriptor; +{ + [self.packetDescriptorsAndBuffers removeObjectForKey:descriptor]; +} + #pragma mark - Private Methods +// Must only be called on requestHandlingQueue (ie. wrap call to this method in dispatch()) +- (void)checkForCompletedPacketsAndNotifyDelegate:(NSData *)receivedByte +{ + for (ORSSerialPacketDescriptor *descriptor in self.packetDescriptorsAndBuffers) + { + NSMutableData *buffer = [self.packetDescriptorsAndBuffers objectForKey:descriptor]; + [buffer appendData:receivedByte]; + for (NSUInteger i=1; i<=[buffer length]; i++) + { + NSData *window = [buffer subdataWithRange:NSMakeRange([buffer length]-i, i)]; + if ([descriptor dataIsValidPacket:window]) + { + if ([self.delegate respondsToSelector:@selector(serialPort:didReceivePacket:matchingDescriptor:)]) + { + dispatch_async(dispatch_get_main_queue(), ^{ + [self.delegate serialPort:self didReceivePacket:window matchingDescriptor:descriptor]; + }); + } + [buffer setData:[NSData data]]; // Clear buffer + } + } + } +} + // Must only be called on requestHandlingQueue (ie. wrap call to this method in dispatch()) - (BOOL)reallySendRequest:(ORSSerialRequest *)request { @@ -546,8 +590,13 @@ - (void)receiveData:(NSData *)data; } dispatch_async(self.requestHandlingQueue, ^{ - [self.receiveBuffer appendData:data]; - [self checkResponseToPendingRequestAndContinueIfValid]; + const void *bytes = [data bytes]; + for (NSUInteger i=0; i<[data length]; i++) { + NSData *byte = [NSData dataWithBytesNoCopy:(void *)(bytes+i) length:1 freeWhenDone:NO]; + [self checkForCompletedPacketsAndNotifyDelegate:byte]; + [self.receiveBuffer appendData:byte]; + [self checkResponseToPendingRequestAndContinueIfValid]; + } }); } diff --git a/Source/ORSSerialRequest.h b/Source/ORSSerialRequest.h index 1d9e61e5..214272e0 100644 --- a/Source/ORSSerialRequest.h +++ b/Source/ORSSerialRequest.h @@ -7,6 +7,7 @@ // #import +#import "ORSSerialPacketDescriptor.h" // Keep older versions of the compiler happy #ifndef NS_ASSUME_NONNULL_BEGIN @@ -17,8 +18,6 @@ #define __nullable #endif -typedef BOOL(^ORSSerialRequestResponseEvaluator)(NSData * __nullable inputData); - NS_ASSUME_NONNULL_BEGIN /** @@ -48,7 +47,7 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype)requestWithDataToSend:(NSData *)dataToSend userInfo:(nullable id)userInfo timeoutInterval:(NSTimeInterval)timeout - responseEvaluator:(nullable ORSSerialRequestResponseEvaluator)responseEvaluator; + responseEvaluator:(nullable ORSSerialResponseEvaluator)responseEvaluator; /** * Initializes an ORSSerialRequest instance. @@ -65,7 +64,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithDataToSend:(NSData *)dataToSend userInfo:(nullable id)userInfo timeoutInterval:(NSTimeInterval)timeout - responseEvaluator:(nullable ORSSerialRequestResponseEvaluator)responseEvaluator; + responseEvaluator:(nullable ORSSerialResponseEvaluator)responseEvaluator; /** * Can be used to determine if a block of data is a valid response to the request encapsulated diff --git a/Source/ORSSerialRequest.m b/Source/ORSSerialRequest.m index 8bca6843..810352e2 100644 --- a/Source/ORSSerialRequest.m +++ b/Source/ORSSerialRequest.m @@ -13,7 +13,7 @@ @interface ORSSerialRequest () @property (nonatomic, strong, readwrite) NSData *dataToSend; @property (nonatomic, strong, readwrite) id userInfo; @property (nonatomic, readwrite) NSTimeInterval timeoutInterval; -@property (nonatomic, strong) ORSSerialRequestResponseEvaluator responseEvaluator; +@property (nonatomic, strong) ORSSerialResponseEvaluator responseEvaluator; @property (nonatomic, strong, readwrite) NSString *UUIDString; @end @@ -23,7 +23,7 @@ @implementation ORSSerialRequest + (instancetype)requestWithDataToSend:(NSData *)dataToSend userInfo:(id)userInfo timeoutInterval:(NSTimeInterval)timeout - responseEvaluator:(ORSSerialRequestResponseEvaluator)responseEvaluator; + responseEvaluator:(ORSSerialResponseEvaluator)responseEvaluator; { return [[self alloc] initWithDataToSend:dataToSend userInfo:userInfo @@ -34,7 +34,7 @@ + (instancetype)requestWithDataToSend:(NSData *)dataToSend - (instancetype)initWithDataToSend:(NSData *)dataToSend userInfo:(id)userInfo timeoutInterval:(NSTimeInterval)timeout - responseEvaluator:(ORSSerialRequestResponseEvaluator)responseEvaluator; + responseEvaluator:(ORSSerialResponseEvaluator)responseEvaluator; { self = [super init]; if (self) { From c2395f3926cbc2f07220cb54c0faf310364976b4 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Sat, 8 Aug 2015 11:35:46 -0600 Subject: [PATCH 11/55] Issue #55: Refactored ORSSerialRequest so it uses ORSSerialPacketDescriptor. --- Source/ORSSerialPort.h | 2 +- Source/ORSSerialRequest.h | 36 +++++++++++++++++++++++++++++++++++- Source/ORSSerialRequest.m | 37 ++++++++++++++++++++++++++----------- 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/Source/ORSSerialPort.h b/Source/ORSSerialPort.h index 94ba02aa..e24d8b90 100644 --- a/Source/ORSSerialPort.h +++ b/Source/ORSSerialPort.h @@ -561,7 +561,7 @@ NS_ASSUME_NONNULL_BEGIN * -startListeningForPacketsMatchingDescriptor: is received. * * @param serialPort The `ORSSerialPort` instance representing the port that received `packetData`. - * @param responseData The An `NSData` instance containing the received packet data. + * @param packetData The An `NSData` instance containing the received packet data. * @param descriptor The packet descriptor object for which packetData is a match. */ - (void)serialPort:(ORSSerialPort *)serialPort didReceivePacket:(NSData *)packetData matchingDescriptor:(ORSSerialPacketDescriptor *)descriptor; diff --git a/Source/ORSSerialRequest.h b/Source/ORSSerialRequest.h index 214272e0..8c3e2146 100644 --- a/Source/ORSSerialRequest.h +++ b/Source/ORSSerialRequest.h @@ -32,6 +32,23 @@ NS_ASSUME_NONNULL_BEGIN */ @interface ORSSerialRequest : NSObject +/** + * Creates and initializes an ORSSerialRequest instance. + * + * @param dataToSend The data to be sent on the serial port. + * @param userInfo An arbitrary userInfo object. + * @param timeout The maximum amount of time in seconds to wait for a response. Pass -1.0 to wait indefinitely. + * @param responseDescriptor A packet descriptor used to evaluate whether received data constitutes a valid response to the request. + * May be nil. If responseDescriptor is nil, the request is assumed not to require a response, and the next request in the queue will + * be sent immediately. + * + * @return An initialized ORSSerialRequest instance. + */ ++ (instancetype)requestWithDataToSend:(NSData *)dataToSend + userInfo:(nullable id)userInfo + timeoutInterval:(NSTimeInterval)timeout + responseDescriptor:(nullable ORSSerialPacketDescriptor *)responseDescriptor; + /** * Creates and initializes an ORSSerialRequest instance. * @@ -49,13 +66,30 @@ NS_ASSUME_NONNULL_BEGIN timeoutInterval:(NSTimeInterval)timeout responseEvaluator:(nullable ORSSerialResponseEvaluator)responseEvaluator; +/** + * Initializes an ORSSerialRequest instance. + * + * @param dataToSend The data to be sent on the serial port. + * @param userInfo An arbitrary userInfo object. + * @param timeout The maximum amount of time in seconds to wait for a response. Pass -1.0 to wait indefinitely. + * @param responseDescriptor A packet descriptor used to evaluate whether received data constitutes a valid response to the request. + * May be nil. If responseDescriptor is nil, the request is assumed not to require a response, and the next request in the queue will + * be sent immediately. + * + * @return An initialized ORSSerialRequest instance. + */ +- (instancetype)initWithDataToSend:(NSData *)dataToSend + userInfo:(nullable id)userInfo + timeoutInterval:(NSTimeInterval)timeout + responseDescriptor:(nullable ORSSerialPacketDescriptor *)responseDescriptor; + /** * Initializes an ORSSerialRequest instance. * * @param dataToSend The data to be sent on the serial port. * @param userInfo An arbitrary userInfo object. * @param timeout The maximum amount of time in seconds to wait for a response. Pass -1.0 to wait indefinitely. - * @param responseEvaluator A block used to evaluate whether received data constitutes a valid response to the request. + * @param responseEvaluator A block used to evaluate whether received data constitutes a valid response to the request. * May be nil. If responseEvaluator is nil, the request is assumed not to require a response, and the next request in the queue will * be sent immediately. * diff --git a/Source/ORSSerialRequest.m b/Source/ORSSerialRequest.m index 810352e2..895ea169 100644 --- a/Source/ORSSerialRequest.m +++ b/Source/ORSSerialRequest.m @@ -7,41 +7,47 @@ // #import "ORSSerialRequest.h" +#import "ORSSerialPacketDescriptor.h" @interface ORSSerialRequest () @property (nonatomic, strong, readwrite) NSData *dataToSend; @property (nonatomic, strong, readwrite) id userInfo; @property (nonatomic, readwrite) NSTimeInterval timeoutInterval; -@property (nonatomic, strong) ORSSerialResponseEvaluator responseEvaluator; +@property (nonatomic, strong) ORSSerialPacketDescriptor *responseDescriptor; @property (nonatomic, strong, readwrite) NSString *UUIDString; @end @implementation ORSSerialRequest ++(instancetype)requestWithDataToSend:(NSData *)dataToSend + userInfo:(id)userInfo + timeoutInterval:(NSTimeInterval)timeout + responseDescriptor:(ORSSerialPacketDescriptor *)responseDescriptor +{ + return [[self alloc] initWithDataToSend:dataToSend userInfo:userInfo timeoutInterval:timeout responseDescriptor:responseDescriptor]; +} + + (instancetype)requestWithDataToSend:(NSData *)dataToSend userInfo:(id)userInfo timeoutInterval:(NSTimeInterval)timeout responseEvaluator:(ORSSerialResponseEvaluator)responseEvaluator; { - return [[self alloc] initWithDataToSend:dataToSend - userInfo:userInfo - timeoutInterval:timeout - responseEvaluator:responseEvaluator]; + return [[self alloc] initWithDataToSend:dataToSend userInfo:userInfo timeoutInterval:timeout responseEvaluator:responseEvaluator]; } - (instancetype)initWithDataToSend:(NSData *)dataToSend - userInfo:(id)userInfo - timeoutInterval:(NSTimeInterval)timeout - responseEvaluator:(ORSSerialResponseEvaluator)responseEvaluator; + userInfo:(id)userInfo + timeoutInterval:(NSTimeInterval)timeout + responseDescriptor:(ORSSerialPacketDescriptor *)responseDescriptor { self = [super init]; if (self) { _dataToSend = dataToSend; _userInfo = userInfo; _timeoutInterval = timeout; - _responseEvaluator = responseEvaluator; + _responseDescriptor = responseDescriptor; CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault); _UUIDString = CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuid)); CFRelease(uuid); @@ -49,6 +55,15 @@ - (instancetype)initWithDataToSend:(NSData *)dataToSend return self; } +- (instancetype)initWithDataToSend:(NSData *)dataToSend + userInfo:(id)userInfo + timeoutInterval:(NSTimeInterval)timeout + responseEvaluator:(ORSSerialResponseEvaluator)responseEvaluator; +{ + ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithUserInfo:nil responseEvaluator:responseEvaluator]; + return [self initWithDataToSend:dataToSend userInfo:userInfo timeoutInterval:timeout responseDescriptor:descriptor]; +} + - (NSString *)description { return [NSString stringWithFormat:@"%@ data: %@ userInfo: %@ timeout interval: %f", [super description], self.dataToSend, self.userInfo, self.timeoutInterval]; @@ -56,9 +71,9 @@ - (NSString *)description - (BOOL)dataIsValidResponse:(NSData *)responseData { - if (!self.responseEvaluator) return YES; + if (!self.responseDescriptor) return YES; - return self.responseEvaluator(responseData); + return [self.responseDescriptor dataIsValidPacket:responseData]; } @end From ba9675de0405ee66dde2768360afc025a9d34067 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Sat, 8 Aug 2015 12:15:29 -0600 Subject: [PATCH 12/55] Issue #55: Added -[ORSSerialPacketDescriptor initWithPrefixString:suffixString:userInfo:] and associated tests. --- .../ORSSerialPacketDescriptor_Tests.m | 16 ++++++++++++++++ Source/ORSSerialPacketDescriptor.h | 4 ++++ Source/ORSSerialPacketDescriptor.m | 9 +++++++++ 3 files changed, 29 insertions(+) diff --git a/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m b/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m index 7ec95c51..7286d3ec 100644 --- a/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m +++ b/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m @@ -60,6 +60,22 @@ - (void)testPrefixSuffix XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"!foo;x")], @"Invalid packet not rejected by descriptor."); } +- (void)testPrefixSuffixStrings +{ + ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithPrefixString:@"!" suffixString:@";" userInfo:nil]; + XCTAssertNotNil(descriptor, @"Creating packet descriptor with prefix and suffix failed."); + XCTAssertEqualObjects(descriptor.prefix, [@"!" dataUsingEncoding:NSASCIIStringEncoding], @"Desriptor prefix property incorrect."); + XCTAssertEqualObjects(descriptor.suffix, [@";" dataUsingEncoding:NSASCIIStringEncoding], @"Desriptor suffix property incorrect."); + + XCTAssertTrue([descriptor dataIsValidPacket:ORSTStringToData_(@"!foo;")], @"Valid packet rejected by descriptor."); + XCTAssertTrue([descriptor dataIsValidPacket:ORSTStringToData_(@"!;")], @"Valid packet rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"!foo")], @"Invalid packet not rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"foo;")], @"Invalid packet not rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"foo")], @"Invalid packet not rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"x!foo;")], @"Invalid packet not rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"!foo;x")], @"Invalid packet not rejected by descriptor."); +} + - (void)testRegex { NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^!.+;$" options:0 error:NULL]; diff --git a/Source/ORSSerialPacketDescriptor.h b/Source/ORSSerialPacketDescriptor.h index cb198ad6..b6d5de28 100644 --- a/Source/ORSSerialPacketDescriptor.h +++ b/Source/ORSSerialPacketDescriptor.h @@ -50,6 +50,10 @@ typedef BOOL(^ORSSerialResponseEvaluator)(NSData * __nullable inputData); suffix:(nullable NSData *)suffix userInfo:(nullable id)userInfo; +- (instancetype)initWithPrefixString:(nullable NSString *)prefixString + suffixString:(nullable NSString *)suffixString + userInfo:(nullable id)userInfo; + - (instancetype)initWithRegularExpression:(NSRegularExpression *)regex userInfo:(nullable id)userInfo; diff --git a/Source/ORSSerialPacketDescriptor.m b/Source/ORSSerialPacketDescriptor.m index 4000aa2d..f7e2cd0c 100644 --- a/Source/ORSSerialPacketDescriptor.m +++ b/Source/ORSSerialPacketDescriptor.m @@ -45,6 +45,15 @@ - (instancetype)initWithPrefix:(NSData *)prefix suffix:(NSData *)suffix userInfo return self; } +- (instancetype)initWithPrefixString:(nullable NSString *)prefixString + suffixString:(nullable NSString *)suffixString + userInfo:(nullable id)userInfo +{ + NSData *prefixData = [prefixString dataUsingEncoding:NSASCIIStringEncoding]; + NSData *suffixData = [suffixString dataUsingEncoding:NSASCIIStringEncoding]; + return [self initWithPrefix:prefixData suffix:suffixData userInfo:userInfo]; +} + - (instancetype)initWithRegularExpression:(NSRegularExpression *)regex userInfo:(nullable id)userInfo { From f00be3f4cc829ab78d795e640d4d8ca1fb2ece5e Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Sat, 8 Aug 2015 12:19:00 -0600 Subject: [PATCH 13/55] Issue #55: Added license text to comment header in ORSSerialPacketDescriptor.h/m. --- Source/ORSSerialPacketDescriptor.h | 18 ++++++++++++++++++ Source/ORSSerialPacketDescriptor.m | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/Source/ORSSerialPacketDescriptor.h b/Source/ORSSerialPacketDescriptor.h index b6d5de28..25a31e13 100644 --- a/Source/ORSSerialPacketDescriptor.h +++ b/Source/ORSSerialPacketDescriptor.h @@ -5,6 +5,24 @@ // Created by Andrew Madsen on 7/21/15. // Copyright (c) 2015 Open Reel Software. All rights reserved. // +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import diff --git a/Source/ORSSerialPacketDescriptor.m b/Source/ORSSerialPacketDescriptor.m index f7e2cd0c..c8ad62cf 100644 --- a/Source/ORSSerialPacketDescriptor.m +++ b/Source/ORSSerialPacketDescriptor.m @@ -5,6 +5,24 @@ // Created by Andrew Madsen on 7/21/15. // Copyright (c) 2015 Open Reel Software. All rights reserved. // +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "ORSSerialPacketDescriptor.h" From b835c46b1052fd4d2960ac77403bc6b4a97fae88 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Sun, 9 Aug 2015 12:37:42 -0600 Subject: [PATCH 14/55] Issue #64: Close underlying port file descriptor in read dispatch source's cancel handler (introduced by changes for #52). Prevents kernel panic when calling -close for FTDI adapters. --- Source/ORSSerialPort.m | 74 ++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/Source/ORSSerialPort.m b/Source/ORSSerialPort.m index e2adf6ac..3b10ca5a 100644 --- a/Source/ORSSerialPort.m +++ b/Source/ORSSerialPort.m @@ -303,6 +303,7 @@ - (void)open; if (readData != nil) [self receiveData:readData]; } }); + dispatch_source_set_cancel_handler(readPollSource, ^{ [self reallyClosePort]; }); dispatch_resume(readPollSource); self.readPollSource = readPollSource; @@ -347,42 +348,43 @@ - (void)open; - (BOOL)close; { if (!self.isOpen) return YES; - - self.readPollSource = nil; // Stop and dispose of read dispatch source - self.pinPollTimer = nil; // Stop polling CTS/DSR/DCD pins - - // The next tcsetattr() call can fail if the port is waiting to send data. This is likely to happen - // e.g. if flow control is on and the CTS line is low. So, turn off flow control before proceeding - struct termios options; - tcgetattr(self.fileDescriptor, &options); - options.c_cflag &= ~CRTSCTS; // RTS/CTS Flow Control - options.c_cflag &= ~(CDTR_IFLOW | CDSR_OFLOW); // DTR/DSR Flow Control - options.c_cflag &= ~CCAR_OFLOW; // DCD Flow Control - tcsetattr(self.fileDescriptor, TCSANOW, &options); - - // Set port back the way it was before we used it - tcsetattr(self.fileDescriptor, TCSADRAIN, &originalPortAttributes); - - int localFD = self.fileDescriptor; - self.fileDescriptor = 0; // So other threads know that the port should be closed and can stop I/O operations - - if (close(localFD)) - { - self.fileDescriptor = localFD; - LOG_SERIAL_PORT_ERROR(@"Error closing serial port with file descriptor %i:%i", self.fileDescriptor, errno); - [self notifyDelegateOfPosixError]; - return NO; - } - - if ([self.delegate respondsToSelector:@selector(serialPortWasClosed:)]) - { - [(id)self.delegate performSelectorOnMainThread:@selector(serialPortWasClosed:) withObject:self waitUntilDone:YES]; - dispatch_async(self.requestHandlingQueue, ^{ - self.requestsQueue = [NSMutableArray array]; // Cancel all queued requests - self.pendingRequest = nil; // Discard pending request - }); - } - return YES; + self.readPollSource = nil; // Cancel read dispatch source. Cancel handler will call -reallyClosePort + return YES; +} + +- (void)reallyClosePort +{ + self.pinPollTimer = nil; // Stop polling CTS/DSR/DCD pins + + // The next tcsetattr() call can fail if the port is waiting to send data. This is likely to happen + // e.g. if flow control is on and the CTS line is low. So, turn off flow control before proceeding + struct termios options; + tcgetattr(self.fileDescriptor, &options); + options.c_cflag &= ~CRTSCTS; // RTS/CTS Flow Control + options.c_cflag &= ~(CDTR_IFLOW | CDSR_OFLOW); // DTR/DSR Flow Control + options.c_cflag &= ~CCAR_OFLOW; // DCD Flow Control + tcsetattr(self.fileDescriptor, TCSANOW, &options); + + // Set port back the way it was before we used it + tcsetattr(self.fileDescriptor, TCSADRAIN, &originalPortAttributes); + + if (close(self.fileDescriptor)) + { + LOG_SERIAL_PORT_ERROR(@"Error closing serial port with file descriptor %i:%i", self.fileDescriptor, errno); + [self notifyDelegateOfPosixError]; + return; + } + + self.fileDescriptor = 0; + + if ([self.delegate respondsToSelector:@selector(serialPortWasClosed:)]) + { + [(id)self.delegate performSelectorOnMainThread:@selector(serialPortWasClosed:) withObject:self waitUntilDone:YES]; + dispatch_async(self.requestHandlingQueue, ^{ + self.requestsQueue = [NSMutableArray array]; // Cancel all queued requests + self.pendingRequest = nil; // Discard pending request + }); + } } - (void)cleanup; From d19e174295c13d8c7ba9753b9810ca17e21046a7 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 10 Aug 2015 12:51:50 -0600 Subject: [PATCH 15/55] Issue #55: ORSSerialPacketDescriptor uses UTF8 to encode prefix/suffix strings. --- Source/ORSSerialPacketDescriptor.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/ORSSerialPacketDescriptor.m b/Source/ORSSerialPacketDescriptor.m index c8ad62cf..8876c15e 100644 --- a/Source/ORSSerialPacketDescriptor.m +++ b/Source/ORSSerialPacketDescriptor.m @@ -67,8 +67,8 @@ - (instancetype)initWithPrefixString:(nullable NSString *)prefixString suffixString:(nullable NSString *)suffixString userInfo:(nullable id)userInfo { - NSData *prefixData = [prefixString dataUsingEncoding:NSASCIIStringEncoding]; - NSData *suffixData = [suffixString dataUsingEncoding:NSASCIIStringEncoding]; + NSData *prefixData = [prefixString dataUsingEncoding:NSUTF8StringEncoding]; + NSData *suffixData = [suffixString dataUsingEncoding:NSUTF8StringEncoding]; return [self initWithPrefix:prefixData suffix:suffixData userInfo:userInfo]; } From 76f04e9e15e588907e386dbe03cb37cf855fbf1c Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 10 Aug 2015 12:52:13 -0600 Subject: [PATCH 16/55] Issue #55: Added documentation for ORSSerialPacketDescriptor. --- Source/ORSSerialPacketDescriptor.h | 90 ++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/Source/ORSSerialPacketDescriptor.h b/Source/ORSSerialPacketDescriptor.h index 25a31e13..4af96202 100644 --- a/Source/ORSSerialPacketDescriptor.h +++ b/Source/ORSSerialPacketDescriptor.h @@ -58,20 +58,93 @@ typedef BOOL(^ORSSerialResponseEvaluator)(NSData * __nullable inputData); * or in response to real world events, rather than in response to serial requests sent by the computer. * For request/response protocols, see ORSSerialRequest, etc. * + * For more information about ORSSerialPort's packet descriptor API, see the ORSSerialPort Packet Parsing + * Programming Guide at */ @interface ORSSerialPacketDescriptor : NSObject +/** + * Creates an initializes an ORSSerialPacketDescriptor instance using a response evaluator block. + * + * This initializer can be used to creat a packet descriptor with complex packet matching + * rules. For most packet formats, the initializers that take prefix and suffix, or regular expression + * are easier to use. However, if the packet format cannot be described using a simple prefix/suffix + * or regular expression, a response evaulator block containing arbitrary validation code can be + * provided instead. + * + * @param userInfo An arbitrary userInfo object. + * @param responseEvaluator A block used to evaluate whether received data constitutes a valid packet. + * + * @return An initizliaized ORSSerialPacketDesciptor instance. + * + * @see -initWithPrefix:suffix:userInfo: + * @see -initWithPrefixString:suffixString:userInfo: + * @see -initWithRegularExpression:userInfo: + */ - (instancetype)initWithUserInfo:(nullable id)userInfo responseEvaluator:(ORSSerialResponseEvaluator)responseEvaluator NS_DESIGNATED_INITIALIZER; +/** + * Creates an initializes an ORSSerialPacketDescriptor instance using a prefix and/or suffix. + * + * If the packet format uses printable ASCII characters, -initWithPrefixString:suffixString:userInfo: + * may be more suitable. + * + * @note Either prefix or suffix may be nil, but not both. If suffix is nil, packets will be considered + * to consist soley of prefix. If prefix is nil, the complete contents of the packet buffer when suffix + * is received will be considered a packet. Usually, well-designed packet protocols will include both + * a prefix and a suffix. + * + * @param prefix An NSData instance containing a fixed packet prefix. May be nil. + * @param suffix An NSData instance containing a fixed packet suffix. May be nil. + * @param userInfo An arbitrary userInfo object. May be nil. + * + * @return An initizliaized ORSSerialPacketDesciptor instance. + * + * @see -initWithPrefixString:suffixString:userInfo: + */ - (instancetype)initWithPrefix:(nullable NSData *)prefix suffix:(nullable NSData *)suffix userInfo:(nullable id)userInfo; +/** + * Creates an initializes an ORSSerialPacketDescriptor instance using a prefix string and/or suffix string. + * + * This method assumes that prefixString and suffixString are ASCII or UTF8 strings. + * If the packet format does not use printable ASCII characters, -initWithPrefix:suffix:userInfo: + * may be more suitable. + * + * @note Either prefixString or suffixString may be nil, but not both. If the suffix is nil, packets will be considered + * to consist soley of prefix. If the prefix is nil, the complete contents of the packet buffer when a suffix + * is received will be considered a packet. Usually, well-designed packet protocols will include both + * a prefix and a suffix. + * + * @param prefixString A fixed packet prefix string. May be nil. + * @param suffixString A fixed packet suffix string. May be nil. + * @param userInfo An arbitrary userInfo object. May be nil. + * + * @return An initizliaized ORSSerialPacketDesciptor instance. + * + * @see -initWithPrefix:suffix:userInfo: + */ - (instancetype)initWithPrefixString:(nullable NSString *)prefixString suffixString:(nullable NSString *)suffixString userInfo:(nullable id)userInfo; +/** + * Creates an initializes an ORSSerialPacketDescriptor instance using a regular expression. + * + * A packet is considered valid as long as it contains at least one match for the provided + * regular expression. For this reason, the regex should match as conservatively (smallest match) as possible. + * + * Packets described by descriptors created using this method are assumed to be ASCII or UTF8 strings. + * If your packets are not naturally represented as strings, consider using -initWithUserInfo:responseEvaluator: instead. + * + * @param regex An NSRegularExpression instance for which valid packets are a match. + * @param userInfo An arbitrary userInfoObject. May be nil. + * + * @return An initizliaized ORSSerialPacketDesciptor instance. + */ - (instancetype)initWithRegularExpression:(NSRegularExpression *)regex userInfo:(nullable id)userInfo; @@ -85,8 +158,22 @@ typedef BOOL(^ORSSerialResponseEvaluator)(NSData * __nullable inputData); */ - (BOOL)dataIsValidPacket:(nullable NSData *)packetData; +/** + * The prefix for packets described by the receiver. Will be nil for packet + * descriptors not created using one of the prefix/suffix initializer methods. + */ @property (nonatomic, strong, readonly, nullable) NSData *prefix; + +/** + * The suffix for packets described by the receiver. Will be nil for packet + * descriptors not created using one of the prefix/suffix initializer methods. + */ @property (nonatomic, strong, readonly, nullable) NSData *suffix; + +/** + * A regular expression matching packets described by the receiver. Will be nil + * for packet descriptors not created using -initWithRegularExpression:userInfo:. + */ @property (nonatomic, strong, readonly, nullable) NSRegularExpression *regularExpression; /** @@ -95,6 +182,9 @@ typedef BOOL(^ORSSerialResponseEvaluator)(NSData * __nullable inputData); */ @property (nonatomic, strong, readonly, nullable) id userInfo; +/** + * Unique identifier for the descriptor. + */ @property (nonatomic, strong, readonly) NSUUID *uuid; @end From 48c9e6a49e59ed6c8c315c3230aa05063755f16b Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 10 Aug 2015 12:59:07 -0600 Subject: [PATCH 17/55] Issue #55: Initial commit of Objective-C version of PacketParsingDemo project.. --- .../project.pbxproj | 293 ++++++++ .../Resources/Base.lproj/Main.storyboard | 681 ++++++++++++++++++ .../AppIcon.appiconset/Contents.json | 58 ++ .../Objective-C/Resources/Info.plist | 34 + .../Objective-C/Sources/ORSAppDelegate.h | 15 + .../Objective-C/Sources/ORSAppDelegate.m | 25 + .../Sources/ORSMainViewController.h | 13 + .../Sources/ORSMainViewController.m | 22 + .../Objective-C/Sources/main.m | 13 + 9 files changed, 1154 insertions(+) create mode 100644 Examples/PacketParsingDemo/Objective-C/PacketParsingDemo.xcodeproj/project.pbxproj create mode 100644 Examples/PacketParsingDemo/Objective-C/Resources/Base.lproj/Main.storyboard create mode 100644 Examples/PacketParsingDemo/Objective-C/Resources/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Examples/PacketParsingDemo/Objective-C/Resources/Info.plist create mode 100644 Examples/PacketParsingDemo/Objective-C/Sources/ORSAppDelegate.h create mode 100644 Examples/PacketParsingDemo/Objective-C/Sources/ORSAppDelegate.m create mode 100644 Examples/PacketParsingDemo/Objective-C/Sources/ORSMainViewController.h create mode 100644 Examples/PacketParsingDemo/Objective-C/Sources/ORSMainViewController.m create mode 100644 Examples/PacketParsingDemo/Objective-C/Sources/main.m diff --git a/Examples/PacketParsingDemo/Objective-C/PacketParsingDemo.xcodeproj/project.pbxproj b/Examples/PacketParsingDemo/Objective-C/PacketParsingDemo.xcodeproj/project.pbxproj new file mode 100644 index 00000000..b47eef30 --- /dev/null +++ b/Examples/PacketParsingDemo/Objective-C/PacketParsingDemo.xcodeproj/project.pbxproj @@ -0,0 +1,293 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 9D3948231B792B550066DC1B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9D3948191B792B550066DC1B /* Main.storyboard */; }; + 9D3948241B792B550066DC1B /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9D39481B1B792B550066DC1B /* Images.xcassets */; }; + 9D3948261B792B550066DC1B /* ORSAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D39481F1B792B550066DC1B /* ORSAppDelegate.m */; }; + 9D3948271B792B550066DC1B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D3948201B792B550066DC1B /* main.m */; }; + 9D39482E1B792BC30066DC1B /* ORSMainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D39482D1B792BC30066DC1B /* ORSMainViewController.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 9D3947F21B792B1D0066DC1B /* PacketParsingDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PacketParsingDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 9D39481A1B792B550066DC1B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 9D39481B1B792B550066DC1B /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 9D39481C1B792B550066DC1B /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9D39481E1B792B550066DC1B /* ORSAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORSAppDelegate.h; sourceTree = ""; }; + 9D39481F1B792B550066DC1B /* ORSAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORSAppDelegate.m; sourceTree = ""; }; + 9D3948201B792B550066DC1B /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 9D39482C1B792BC30066DC1B /* ORSMainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORSMainViewController.h; sourceTree = ""; }; + 9D39482D1B792BC30066DC1B /* ORSMainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORSMainViewController.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 9D3947EF1B792B1D0066DC1B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9D3947E91B792B1D0066DC1B = { + isa = PBXGroup; + children = ( + 9D39481D1B792B550066DC1B /* Sources */, + 9D3948181B792B550066DC1B /* Resources */, + 9D3947F31B792B1D0066DC1B /* Products */, + ); + sourceTree = ""; + }; + 9D3947F31B792B1D0066DC1B /* Products */ = { + isa = PBXGroup; + children = ( + 9D3947F21B792B1D0066DC1B /* PacketParsingDemo.app */, + ); + name = Products; + sourceTree = ""; + }; + 9D3948181B792B550066DC1B /* Resources */ = { + isa = PBXGroup; + children = ( + 9D3948191B792B550066DC1B /* Main.storyboard */, + 9D39481B1B792B550066DC1B /* Images.xcassets */, + 9D39481C1B792B550066DC1B /* Info.plist */, + ); + path = Resources; + sourceTree = ""; + }; + 9D39481D1B792B550066DC1B /* Sources */ = { + isa = PBXGroup; + children = ( + 9D39481E1B792B550066DC1B /* ORSAppDelegate.h */, + 9D39481F1B792B550066DC1B /* ORSAppDelegate.m */, + 9D39482C1B792BC30066DC1B /* ORSMainViewController.h */, + 9D39482D1B792BC30066DC1B /* ORSMainViewController.m */, + 9D3948201B792B550066DC1B /* main.m */, + ); + path = Sources; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 9D3947F11B792B1D0066DC1B /* PacketParsingDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9D3948121B792B1D0066DC1B /* Build configuration list for PBXNativeTarget "PacketParsingDemo" */; + buildPhases = ( + 9D3947EE1B792B1D0066DC1B /* Sources */, + 9D3947EF1B792B1D0066DC1B /* Frameworks */, + 9D3947F01B792B1D0066DC1B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PacketParsingDemo; + productName = PacketParsingDemo; + productReference = 9D3947F21B792B1D0066DC1B /* PacketParsingDemo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 9D3947EA1B792B1D0066DC1B /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0640; + ORGANIZATIONNAME = "Open Reel Software"; + TargetAttributes = { + 9D3947F11B792B1D0066DC1B = { + CreatedOnToolsVersion = 6.4; + }; + }; + }; + buildConfigurationList = 9D3947ED1B792B1D0066DC1B /* Build configuration list for PBXProject "PacketParsingDemo" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 9D3947E91B792B1D0066DC1B; + productRefGroup = 9D3947F31B792B1D0066DC1B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 9D3947F11B792B1D0066DC1B /* PacketParsingDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 9D3947F01B792B1D0066DC1B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9D3948231B792B550066DC1B /* Main.storyboard in Resources */, + 9D3948241B792B550066DC1B /* Images.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 9D3947EE1B792B1D0066DC1B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9D3948271B792B550066DC1B /* main.m in Sources */, + 9D3948261B792B550066DC1B /* ORSAppDelegate.m in Sources */, + 9D39482E1B792BC30066DC1B /* ORSMainViewController.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 9D3948191B792B550066DC1B /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 9D39481A1B792B550066DC1B /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 9D3948101B792B1D0066DC1B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 9D3948111B792B1D0066DC1B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 9D3948131B792B1D0066DC1B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 9D3948141B792B1D0066DC1B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 9D3947ED1B792B1D0066DC1B /* Build configuration list for PBXProject "PacketParsingDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9D3948101B792B1D0066DC1B /* Debug */, + 9D3948111B792B1D0066DC1B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9D3948121B792B1D0066DC1B /* Build configuration list for PBXNativeTarget "PacketParsingDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9D3948131B792B1D0066DC1B /* Debug */, + 9D3948141B792B1D0066DC1B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 9D3947EA1B792B1D0066DC1B /* Project object */; +} diff --git a/Examples/PacketParsingDemo/Objective-C/Resources/Base.lproj/Main.storyboard b/Examples/PacketParsingDemo/Objective-C/Resources/Base.lproj/Main.storyboard new file mode 100644 index 00000000..621ef693 --- /dev/null +++ b/Examples/PacketParsingDemo/Objective-C/Resources/Base.lproj/Main.storyboard @@ -0,0 +1,681 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/PacketParsingDemo/Objective-C/Resources/Images.xcassets/AppIcon.appiconset/Contents.json b/Examples/PacketParsingDemo/Objective-C/Resources/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..2db2b1c7 --- /dev/null +++ b/Examples/PacketParsingDemo/Objective-C/Resources/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Examples/PacketParsingDemo/Objective-C/Resources/Info.plist b/Examples/PacketParsingDemo/Objective-C/Resources/Info.plist new file mode 100644 index 00000000..ff83c78c --- /dev/null +++ b/Examples/PacketParsingDemo/Objective-C/Resources/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2015 Open Reel Software. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/Examples/PacketParsingDemo/Objective-C/Sources/ORSAppDelegate.h b/Examples/PacketParsingDemo/Objective-C/Sources/ORSAppDelegate.h new file mode 100644 index 00000000..fa7c521f --- /dev/null +++ b/Examples/PacketParsingDemo/Objective-C/Sources/ORSAppDelegate.h @@ -0,0 +1,15 @@ +// +// ORSAppDelegate.h +// PacketParsingDemo +// +// Created by Andrew Madsen on 8/10/15. +// Copyright (c) 2015 Open Reel Software. All rights reserved. +// + +#import + +@interface ORSAppDelegate : NSObject + + +@end + diff --git a/Examples/PacketParsingDemo/Objective-C/Sources/ORSAppDelegate.m b/Examples/PacketParsingDemo/Objective-C/Sources/ORSAppDelegate.m new file mode 100644 index 00000000..a064e24b --- /dev/null +++ b/Examples/PacketParsingDemo/Objective-C/Sources/ORSAppDelegate.m @@ -0,0 +1,25 @@ +// +// ORSAppDelegate.m +// PacketParsingDemo +// +// Created by Andrew Madsen on 8/10/15. +// Copyright (c) 2015 Open Reel Software. All rights reserved. +// + +#import "ORSAppDelegate.h" + +@interface ORSAppDelegate () + +@end + +@implementation ORSAppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/Examples/PacketParsingDemo/Objective-C/Sources/ORSMainViewController.h b/Examples/PacketParsingDemo/Objective-C/Sources/ORSMainViewController.h new file mode 100644 index 00000000..2f52f3b9 --- /dev/null +++ b/Examples/PacketParsingDemo/Objective-C/Sources/ORSMainViewController.h @@ -0,0 +1,13 @@ +// +// ORSMainViewController.h +// PacketParsingDemo +// +// Created by Andrew Madsen on 8/10/15. +// Copyright (c) 2015 Open Reel Software. All rights reserved. +// + +#import + +@interface ORSMainViewController : NSViewController + +@end diff --git a/Examples/PacketParsingDemo/Objective-C/Sources/ORSMainViewController.m b/Examples/PacketParsingDemo/Objective-C/Sources/ORSMainViewController.m new file mode 100644 index 00000000..81a2e075 --- /dev/null +++ b/Examples/PacketParsingDemo/Objective-C/Sources/ORSMainViewController.m @@ -0,0 +1,22 @@ +// +// ORSMainViewController.m +// PacketParsingDemo +// +// Created by Andrew Madsen on 8/10/15. +// Copyright (c) 2015 Open Reel Software. All rights reserved. +// + +#import "ORSMainViewController.h" + +@interface ORSMainViewController () + +@end + +@implementation ORSMainViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do view setup here. +} + +@end diff --git a/Examples/PacketParsingDemo/Objective-C/Sources/main.m b/Examples/PacketParsingDemo/Objective-C/Sources/main.m new file mode 100644 index 00000000..4a7865c7 --- /dev/null +++ b/Examples/PacketParsingDemo/Objective-C/Sources/main.m @@ -0,0 +1,13 @@ +// +// main.m +// PacketParsingDemo +// +// Created by Andrew Madsen on 8/10/15. +// Copyright (c) 2015 Open Reel Software. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} From 948f807222fcbc92dc16e41d4ceb63dd3b3da9a0 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 10 Aug 2015 13:19:39 -0600 Subject: [PATCH 18/55] Issue #55: Implemented Objective-C PacketParsingDemo example. --- .../project.pbxproj | 110 +++++++++++++++++- .../Resources/Base.lproj/Main.storyboard | 53 ++++++++- .../Sources/ORSMainViewController.h | 7 ++ .../Sources/ORSMainViewController.m | 14 ++- .../Sources/ORSSerialCommunicator.h | 19 +++ .../Sources/ORSSerialCommunicator.m | 62 ++++++++++ 6 files changed, 255 insertions(+), 10 deletions(-) create mode 100644 Examples/PacketParsingDemo/Objective-C/Sources/ORSSerialCommunicator.h create mode 100644 Examples/PacketParsingDemo/Objective-C/Sources/ORSSerialCommunicator.m diff --git a/Examples/PacketParsingDemo/Objective-C/PacketParsingDemo.xcodeproj/project.pbxproj b/Examples/PacketParsingDemo/Objective-C/PacketParsingDemo.xcodeproj/project.pbxproj index b47eef30..6df9932e 100644 --- a/Examples/PacketParsingDemo/Objective-C/PacketParsingDemo.xcodeproj/project.pbxproj +++ b/Examples/PacketParsingDemo/Objective-C/PacketParsingDemo.xcodeproj/project.pbxproj @@ -12,8 +12,49 @@ 9D3948261B792B550066DC1B /* ORSAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D39481F1B792B550066DC1B /* ORSAppDelegate.m */; }; 9D3948271B792B550066DC1B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D3948201B792B550066DC1B /* main.m */; }; 9D39482E1B792BC30066DC1B /* ORSMainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D39482D1B792BC30066DC1B /* ORSMainViewController.m */; }; + 9D39483A1B792C280066DC1B /* ORSSerial.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D3948371B792C1E0066DC1B /* ORSSerial.framework */; }; + 9D39483B1B792C280066DC1B /* ORSSerial.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9D3948371B792C1E0066DC1B /* ORSSerial.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 9D3948421B792C900066DC1B /* ORSSerialCommunicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D3948411B792C900066DC1B /* ORSSerialCommunicator.m */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 9D3948361B792C1E0066DC1B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9D3948311B792C1E0066DC1B /* ORSSerialPort.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 9DCA89121A2BB106009285EB; + remoteInfo = ORSSerial; + }; + 9D3948381B792C1E0066DC1B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9D3948311B792C1E0066DC1B /* ORSSerialPort.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 9D7472131B6D7767002D8B10; + remoteInfo = "ORSSerialPort Tests"; + }; + 9D39483C1B792C280066DC1B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9D3948311B792C1E0066DC1B /* ORSSerialPort.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 9DCA89111A2BB106009285EB; + remoteInfo = ORSSerial; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9D39483E1B792C280066DC1B /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 9D39483B1B792C280066DC1B /* ORSSerial.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 9D3947F21B792B1D0066DC1B /* PacketParsingDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PacketParsingDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 9D39481A1B792B550066DC1B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; @@ -24,6 +65,9 @@ 9D3948201B792B550066DC1B /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 9D39482C1B792BC30066DC1B /* ORSMainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORSMainViewController.h; sourceTree = ""; }; 9D39482D1B792BC30066DC1B /* ORSMainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORSMainViewController.m; sourceTree = ""; }; + 9D3948311B792C1E0066DC1B /* ORSSerialPort.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ORSSerialPort.xcodeproj; path = "../../../../Framework Project/ORSSerialPort.xcodeproj"; sourceTree = ""; }; + 9D3948401B792C900066DC1B /* ORSSerialCommunicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORSSerialCommunicator.h; sourceTree = ""; }; + 9D3948411B792C900066DC1B /* ORSSerialCommunicator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORSSerialCommunicator.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -31,6 +75,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 9D39483A1B792C280066DC1B /* ORSSerial.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -42,6 +87,7 @@ children = ( 9D39481D1B792B550066DC1B /* Sources */, 9D3948181B792B550066DC1B /* Resources */, + 9D3948301B792C120066DC1B /* Frameworks */, 9D3947F31B792B1D0066DC1B /* Products */, ); sourceTree = ""; @@ -71,11 +117,39 @@ 9D39481F1B792B550066DC1B /* ORSAppDelegate.m */, 9D39482C1B792BC30066DC1B /* ORSMainViewController.h */, 9D39482D1B792BC30066DC1B /* ORSMainViewController.m */, - 9D3948201B792B550066DC1B /* main.m */, + 9D3948401B792C900066DC1B /* ORSSerialCommunicator.h */, + 9D3948411B792C900066DC1B /* ORSSerialCommunicator.m */, + 9D3948431B792C990066DC1B /* Supporting Files */, ); path = Sources; sourceTree = ""; }; + 9D3948301B792C120066DC1B /* Frameworks */ = { + isa = PBXGroup; + children = ( + 9D3948311B792C1E0066DC1B /* ORSSerialPort.xcodeproj */, + ); + name = Frameworks; + path = Sources; + sourceTree = ""; + }; + 9D3948321B792C1E0066DC1B /* Products */ = { + isa = PBXGroup; + children = ( + 9D3948371B792C1E0066DC1B /* ORSSerial.framework */, + 9D3948391B792C1E0066DC1B /* ORSSerialPort Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 9D3948431B792C990066DC1B /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 9D3948201B792B550066DC1B /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -86,10 +160,12 @@ 9D3947EE1B792B1D0066DC1B /* Sources */, 9D3947EF1B792B1D0066DC1B /* Frameworks */, 9D3947F01B792B1D0066DC1B /* Resources */, + 9D39483E1B792C280066DC1B /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( + 9D39483D1B792C280066DC1B /* PBXTargetDependency */, ); name = PacketParsingDemo; productName = PacketParsingDemo; @@ -121,6 +197,12 @@ mainGroup = 9D3947E91B792B1D0066DC1B; productRefGroup = 9D3947F31B792B1D0066DC1B /* Products */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 9D3948321B792C1E0066DC1B /* Products */; + ProjectRef = 9D3948311B792C1E0066DC1B /* ORSSerialPort.xcodeproj */; + }, + ); projectRoot = ""; targets = ( 9D3947F11B792B1D0066DC1B /* PacketParsingDemo */, @@ -128,6 +210,23 @@ }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + 9D3948371B792C1E0066DC1B /* ORSSerial.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ORSSerial.framework; + remoteRef = 9D3948361B792C1E0066DC1B /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 9D3948391B792C1E0066DC1B /* ORSSerialPort Tests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = "ORSSerialPort Tests.xctest"; + remoteRef = 9D3948381B792C1E0066DC1B /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ 9D3947F01B792B1D0066DC1B /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -148,11 +247,20 @@ 9D3948271B792B550066DC1B /* main.m in Sources */, 9D3948261B792B550066DC1B /* ORSAppDelegate.m in Sources */, 9D39482E1B792BC30066DC1B /* ORSMainViewController.m in Sources */, + 9D3948421B792C900066DC1B /* ORSSerialCommunicator.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 9D39483D1B792C280066DC1B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = ORSSerial; + targetProxy = 9D39483C1B792C280066DC1B /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin PBXVariantGroup section */ 9D3948191B792B550066DC1B /* Main.storyboard */ = { isa = PBXVariantGroup; diff --git a/Examples/PacketParsingDemo/Objective-C/Resources/Base.lproj/Main.storyboard b/Examples/PacketParsingDemo/Objective-C/Resources/Base.lproj/Main.storyboard index 621ef693..f8e7da73 100644 --- a/Examples/PacketParsingDemo/Objective-C/Resources/Base.lproj/Main.storyboard +++ b/Examples/PacketParsingDemo/Objective-C/Resources/Base.lproj/Main.storyboard @@ -1,5 +1,5 @@ - + @@ -650,11 +650,13 @@ - + - - + + + + @@ -669,13 +671,52 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/Examples/PacketParsingDemo/Objective-C/Sources/ORSMainViewController.h b/Examples/PacketParsingDemo/Objective-C/Sources/ORSMainViewController.h index 2f52f3b9..91e95157 100644 --- a/Examples/PacketParsingDemo/Objective-C/Sources/ORSMainViewController.h +++ b/Examples/PacketParsingDemo/Objective-C/Sources/ORSMainViewController.h @@ -8,6 +8,13 @@ #import +@class ORSSerialPortManager; +@class ORSSerialCommunicator; + @interface ORSMainViewController : NSViewController +@property (nonatomic, readonly) ORSSerialPortManager *serialPortManager; + +@property (nonatomic, readonly) ORSSerialCommunicator *serialCommunicator; + @end diff --git a/Examples/PacketParsingDemo/Objective-C/Sources/ORSMainViewController.m b/Examples/PacketParsingDemo/Objective-C/Sources/ORSMainViewController.m index 81a2e075..614c8013 100644 --- a/Examples/PacketParsingDemo/Objective-C/Sources/ORSMainViewController.m +++ b/Examples/PacketParsingDemo/Objective-C/Sources/ORSMainViewController.m @@ -7,6 +7,8 @@ // #import "ORSMainViewController.h" +@import ORSSerial; +#import "ORSSerialCommunicator.h" @interface ORSMainViewController () @@ -14,9 +16,15 @@ @interface ORSMainViewController () @implementation ORSMainViewController -- (void)viewDidLoad { - [super viewDidLoad]; - // Do view setup here. +#pragma mark - Properties + +- (ORSSerialPortManager *)serialPortManager { return [ORSSerialPortManager sharedSerialPortManager]; } + +@synthesize serialCommunicator = _serialCommunicator; +- (ORSSerialCommunicator *)serialCommunicator +{ + if (!_serialCommunicator) { _serialCommunicator = [[ORSSerialCommunicator alloc] init]; } + return _serialCommunicator; } @end diff --git a/Examples/PacketParsingDemo/Objective-C/Sources/ORSSerialCommunicator.h b/Examples/PacketParsingDemo/Objective-C/Sources/ORSSerialCommunicator.h new file mode 100644 index 00000000..325eac31 --- /dev/null +++ b/Examples/PacketParsingDemo/Objective-C/Sources/ORSSerialCommunicator.h @@ -0,0 +1,19 @@ +// +// ORSSerialCommunicator.h +// PacketParsingDemo +// +// Created by Andrew Madsen on 8/10/15. +// Copyright (c) 2015 Open Reel Software. All rights reserved. +// + +#import + +@class ORSSerialPort;; + +@interface ORSSerialCommunicator : NSObject + +@property (nonatomic, strong) ORSSerialPort *serialPort; + +@property (nonatomic, readonly) NSInteger sliderPosition; + +@end diff --git a/Examples/PacketParsingDemo/Objective-C/Sources/ORSSerialCommunicator.m b/Examples/PacketParsingDemo/Objective-C/Sources/ORSSerialCommunicator.m new file mode 100644 index 00000000..c19d02bf --- /dev/null +++ b/Examples/PacketParsingDemo/Objective-C/Sources/ORSSerialCommunicator.m @@ -0,0 +1,62 @@ +// +// ORSSerialCommunicator.m +// PacketParsingDemo +// +// Created by Andrew Madsen on 8/10/15. +// Copyright (c) 2015 Open Reel Software. All rights reserved. +// + +#import "ORSSerialCommunicator.h" +@import ORSSerial; + +@interface ORSSerialCommunicator () + +@property (nonatomic, readwrite) NSInteger sliderPosition; + +@end + +@implementation ORSSerialCommunicator + +#pragma mark - ORSSerialPortDelegate + +- (void)serialPortWasRemovedFromSystem:(ORSSerialPort *)serialPort +{ + self.serialPort = nil; +} + +- (void)serialPort:(ORSSerialPort *)serialPort didEncounterError:(NSError *)error +{ + NSLog(@"Serial port %@ encountered an error: %@", self.serialPort, error); +} + +- (void)serialPort:(ORSSerialPort *)serialPort didReceivePacket:(NSData *)packetData matchingDescriptor:(ORSSerialPacketDescriptor *)descriptor +{ + NSString *dataAsString = [[NSString alloc] initWithData:packetData encoding:NSASCIIStringEncoding]; + NSString *valueString = [dataAsString substringWithRange:NSMakeRange(4, [dataAsString length]-5)]; + self.sliderPosition = [valueString integerValue]; +} + +- (void)serialPortWasOpened:(ORSSerialPort *)serialPort +{ + ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithPrefixString:@"!pos" + suffixString:@";" + userInfo:nil]; + [serialPort startListeningForPacketsMatchingDescriptor:descriptor]; +} + +#pragma mark - Properties + +- (void)setSerialPort:(ORSSerialPort *)serialPort +{ + if (serialPort != _serialPort) { + [_serialPort close]; + _serialPort.delegate = nil; + + _serialPort = serialPort; + + _serialPort.baudRate = @57600; + _serialPort.delegate = self; + [_serialPort open]; + } +} +@end From 060a0e51141c41f530f8f53d0ff9dc21e3fcc109 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 10 Aug 2015 14:22:04 -0600 Subject: [PATCH 19/55] Issue #55: Added Swift version of PacketParsionDemo project. --- .../project.pbxproj | 383 ++++++++++ .../Resources/Base.lproj/Main.storyboard | 722 ++++++++++++++++++ .../AppIcon.appiconset/Contents.json | 58 ++ .../Swift/Resources/Info.plist | 34 + .../Swift/Sources/AppDelegate.swift | 14 + .../Swift/Sources/MainViewController.swift | 18 + .../Swift/Sources/SerialCommunicator.swift | 59 ++ 7 files changed, 1288 insertions(+) create mode 100644 Examples/PacketParsingDemo/Swift/PacketParsingDemo.xcodeproj/project.pbxproj create mode 100644 Examples/PacketParsingDemo/Swift/Resources/Base.lproj/Main.storyboard create mode 100644 Examples/PacketParsingDemo/Swift/Resources/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Examples/PacketParsingDemo/Swift/Resources/Info.plist create mode 100644 Examples/PacketParsingDemo/Swift/Sources/AppDelegate.swift create mode 100644 Examples/PacketParsingDemo/Swift/Sources/MainViewController.swift create mode 100644 Examples/PacketParsingDemo/Swift/Sources/SerialCommunicator.swift diff --git a/Examples/PacketParsingDemo/Swift/PacketParsingDemo.xcodeproj/project.pbxproj b/Examples/PacketParsingDemo/Swift/PacketParsingDemo.xcodeproj/project.pbxproj new file mode 100644 index 00000000..efdd5104 --- /dev/null +++ b/Examples/PacketParsingDemo/Swift/PacketParsingDemo.xcodeproj/project.pbxproj @@ -0,0 +1,383 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 9DEDA8481B793BDC009F4617 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9DEDA8411B793BDC009F4617 /* Main.storyboard */; }; + 9DEDA8491B793BDC009F4617 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9DEDA8431B793BDC009F4617 /* Images.xcassets */; }; + 9DEDA84B1B793BDC009F4617 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DEDA8461B793BDC009F4617 /* AppDelegate.swift */; }; + 9DEDA84C1B793BDC009F4617 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DEDA8471B793BDC009F4617 /* MainViewController.swift */; }; + 9DEDA85A1B793C12009F4617 /* ORSSerial.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DEDA8541B793BF4009F4617 /* ORSSerial.framework */; }; + 9DEDA85B1B793C12009F4617 /* ORSSerial.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9DEDA8541B793BF4009F4617 /* ORSSerial.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 9DEDA8601B793C27009F4617 /* SerialCommunicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DEDA85F1B793C27009F4617 /* SerialCommunicator.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 9DEDA8531B793BF4009F4617 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9DEDA84E1B793BF4009F4617 /* ORSSerialPort.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 9DCA89121A2BB106009285EB; + remoteInfo = ORSSerial; + }; + 9DEDA8551B793BF4009F4617 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9DEDA84E1B793BF4009F4617 /* ORSSerialPort.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 9D7472131B6D7767002D8B10; + remoteInfo = "ORSSerialPort Tests"; + }; + 9DEDA85C1B793C12009F4617 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9DEDA84E1B793BF4009F4617 /* ORSSerialPort.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 9DCA89111A2BB106009285EB; + remoteInfo = ORSSerial; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9DEDA85E1B793C12009F4617 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 9DEDA85B1B793C12009F4617 /* ORSSerial.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 9DEDA81D1B793B64009F4617 /* PacketParsingDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PacketParsingDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 9DEDA8421B793BDC009F4617 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 9DEDA8431B793BDC009F4617 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 9DEDA8441B793BDC009F4617 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9DEDA8461B793BDC009F4617 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 9DEDA8471B793BDC009F4617 /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = ""; }; + 9DEDA84E1B793BF4009F4617 /* ORSSerialPort.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ORSSerialPort.xcodeproj; path = "../../../Framework Project/ORSSerialPort.xcodeproj"; sourceTree = ""; }; + 9DEDA85F1B793C27009F4617 /* SerialCommunicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SerialCommunicator.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 9DEDA81A1B793B64009F4617 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9DEDA85A1B793C12009F4617 /* ORSSerial.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9DEDA8141B793B64009F4617 = { + isa = PBXGroup; + children = ( + 9DEDA8451B793BDC009F4617 /* Sources */, + 9DEDA8401B793BDC009F4617 /* Resources */, + 9DEDA84D1B793BE3009F4617 /* Frameworks */, + 9DEDA81E1B793B64009F4617 /* Products */, + ); + sourceTree = ""; + }; + 9DEDA81E1B793B64009F4617 /* Products */ = { + isa = PBXGroup; + children = ( + 9DEDA81D1B793B64009F4617 /* PacketParsingDemo.app */, + ); + name = Products; + sourceTree = ""; + }; + 9DEDA8401B793BDC009F4617 /* Resources */ = { + isa = PBXGroup; + children = ( + 9DEDA8411B793BDC009F4617 /* Main.storyboard */, + 9DEDA8431B793BDC009F4617 /* Images.xcassets */, + 9DEDA8441B793BDC009F4617 /* Info.plist */, + ); + path = Resources; + sourceTree = ""; + }; + 9DEDA8451B793BDC009F4617 /* Sources */ = { + isa = PBXGroup; + children = ( + 9DEDA8461B793BDC009F4617 /* AppDelegate.swift */, + 9DEDA8471B793BDC009F4617 /* MainViewController.swift */, + 9DEDA85F1B793C27009F4617 /* SerialCommunicator.swift */, + ); + path = Sources; + sourceTree = ""; + }; + 9DEDA84D1B793BE3009F4617 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 9DEDA84E1B793BF4009F4617 /* ORSSerialPort.xcodeproj */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9DEDA84F1B793BF4009F4617 /* Products */ = { + isa = PBXGroup; + children = ( + 9DEDA8541B793BF4009F4617 /* ORSSerial.framework */, + 9DEDA8561B793BF4009F4617 /* ORSSerialPort Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 9DEDA81C1B793B64009F4617 /* PacketParsingDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9DEDA8391B793B64009F4617 /* Build configuration list for PBXNativeTarget "PacketParsingDemo" */; + buildPhases = ( + 9DEDA8191B793B64009F4617 /* Sources */, + 9DEDA81A1B793B64009F4617 /* Frameworks */, + 9DEDA81B1B793B64009F4617 /* Resources */, + 9DEDA85E1B793C12009F4617 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 9DEDA85D1B793C12009F4617 /* PBXTargetDependency */, + ); + name = PacketParsingDemo; + productName = PacketParsingDemo; + productReference = 9DEDA81D1B793B64009F4617 /* PacketParsingDemo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 9DEDA8151B793B64009F4617 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0640; + ORGANIZATIONNAME = "Open Reel Software"; + TargetAttributes = { + 9DEDA81C1B793B64009F4617 = { + CreatedOnToolsVersion = 6.4; + }; + }; + }; + buildConfigurationList = 9DEDA8181B793B64009F4617 /* Build configuration list for PBXProject "PacketParsingDemo" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 9DEDA8141B793B64009F4617; + productRefGroup = 9DEDA81E1B793B64009F4617 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 9DEDA84F1B793BF4009F4617 /* Products */; + ProjectRef = 9DEDA84E1B793BF4009F4617 /* ORSSerialPort.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 9DEDA81C1B793B64009F4617 /* PacketParsingDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 9DEDA8541B793BF4009F4617 /* ORSSerial.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ORSSerial.framework; + remoteRef = 9DEDA8531B793BF4009F4617 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 9DEDA8561B793BF4009F4617 /* ORSSerialPort Tests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = "ORSSerialPort Tests.xctest"; + remoteRef = 9DEDA8551B793BF4009F4617 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 9DEDA81B1B793B64009F4617 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9DEDA8481B793BDC009F4617 /* Main.storyboard in Resources */, + 9DEDA8491B793BDC009F4617 /* Images.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 9DEDA8191B793B64009F4617 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9DEDA84B1B793BDC009F4617 /* AppDelegate.swift in Sources */, + 9DEDA84C1B793BDC009F4617 /* MainViewController.swift in Sources */, + 9DEDA8601B793C27009F4617 /* SerialCommunicator.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 9DEDA85D1B793C12009F4617 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = ORSSerial; + targetProxy = 9DEDA85C1B793C12009F4617 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 9DEDA8411B793BDC009F4617 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 9DEDA8421B793BDC009F4617 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 9DEDA8371B793B64009F4617 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 9DEDA8381B793B64009F4617 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 9DEDA83A1B793B64009F4617 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 9DEDA83B1B793B64009F4617 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 9DEDA8181B793B64009F4617 /* Build configuration list for PBXProject "PacketParsingDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9DEDA8371B793B64009F4617 /* Debug */, + 9DEDA8381B793B64009F4617 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9DEDA8391B793B64009F4617 /* Build configuration list for PBXNativeTarget "PacketParsingDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9DEDA83A1B793B64009F4617 /* Debug */, + 9DEDA83B1B793B64009F4617 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 9DEDA8151B793B64009F4617 /* Project object */; +} diff --git a/Examples/PacketParsingDemo/Swift/Resources/Base.lproj/Main.storyboard b/Examples/PacketParsingDemo/Swift/Resources/Base.lproj/Main.storyboard new file mode 100644 index 00000000..dd5f9049 --- /dev/null +++ b/Examples/PacketParsingDemo/Swift/Resources/Base.lproj/Main.storyboard @@ -0,0 +1,722 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/PacketParsingDemo/Swift/Resources/Images.xcassets/AppIcon.appiconset/Contents.json b/Examples/PacketParsingDemo/Swift/Resources/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..2db2b1c7 --- /dev/null +++ b/Examples/PacketParsingDemo/Swift/Resources/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Examples/PacketParsingDemo/Swift/Resources/Info.plist b/Examples/PacketParsingDemo/Swift/Resources/Info.plist new file mode 100644 index 00000000..ff83c78c --- /dev/null +++ b/Examples/PacketParsingDemo/Swift/Resources/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2015 Open Reel Software. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/Examples/PacketParsingDemo/Swift/Sources/AppDelegate.swift b/Examples/PacketParsingDemo/Swift/Sources/AppDelegate.swift new file mode 100644 index 00000000..c85738a6 --- /dev/null +++ b/Examples/PacketParsingDemo/Swift/Sources/AppDelegate.swift @@ -0,0 +1,14 @@ +// +// AppDelegate.swift +// PacketParsingDemo +// +// Created by Andrew Madsen on 8/10/15. +// Copyright (c) 2015 Open Reel Software. All rights reserved. +// + +import Cocoa + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { +} + diff --git a/Examples/PacketParsingDemo/Swift/Sources/MainViewController.swift b/Examples/PacketParsingDemo/Swift/Sources/MainViewController.swift new file mode 100644 index 00000000..da3bb93c --- /dev/null +++ b/Examples/PacketParsingDemo/Swift/Sources/MainViewController.swift @@ -0,0 +1,18 @@ +// +// MainViewController.swift +// PacketParsingDemo +// +// Created by Andrew Madsen on 8/10/15. +// Copyright (c) 2015 Open Reel Software. All rights reserved. +// + +import Cocoa +import ORSSerial + +class MainViewController: NSViewController { + + let serialPortManager = ORSSerialPortManager.sharedSerialPortManager() + let serialCommunicator = SerialCommunicator() + +} + diff --git a/Examples/PacketParsingDemo/Swift/Sources/SerialCommunicator.swift b/Examples/PacketParsingDemo/Swift/Sources/SerialCommunicator.swift new file mode 100644 index 00000000..dcd8049b --- /dev/null +++ b/Examples/PacketParsingDemo/Swift/Sources/SerialCommunicator.swift @@ -0,0 +1,59 @@ +// +// SerialCommunicator.swift +// PacketParsingDemo +// +// Created by Andrew Madsen on 8/10/15. +// Copyright (c) 2015 Open Reel Software. All rights reserved. +// + +import Cocoa +import ORSSerial + +class SerialCommunicator: NSObject, ORSSerialPortDelegate { + + deinit { + self.serialPort = nil + } + + // MARK - ORSSerialPortDelegate + + func serialPortWasRemovedFromSystem(serialPort: ORSSerialPort) { + self.serialPort = nil + } + + func serialPort(serialPort: ORSSerialPort, didEncounterError error: NSError) { + println("Serial port \(serialPort) encountered an error: \(error)") + } + + func serialPortWasOpened(serialPort: ORSSerialPort) { + let descriptor = ORSSerialPacketDescriptor(prefixString: "!pos", suffixString: ";", userInfo: nil) + serialPort.startListeningForPacketsMatchingDescriptor(descriptor) + } + + func serialPort(serialPort: ORSSerialPort, didReceivePacket packetData: NSData, matchingDescriptor descriptor: ORSSerialPacketDescriptor) { + if let dataAsString = NSString(data: packetData, encoding: NSASCIIStringEncoding) { + let valueString = dataAsString.substringWithRange(NSRange(location: 4, length: dataAsString.length-5)) + self.sliderPosition = valueString.toInt()! + } + } + + // MARK: - Properties + + dynamic private(set) var sliderPosition: Int = 0 + + dynamic var serialPort: ORSSerialPort? { + willSet { + if let port = serialPort { + port.close() + port.delegate = nil + } + } + didSet { + if let port = serialPort { + port.baudRate = 57600 + port.delegate = self + port.open() + } + } + } +} From bbe0ac943054e6b069769c617bcd4c68de1b8c44 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 10 Aug 2015 14:31:57 -0600 Subject: [PATCH 20/55] Issue #55: Renamed ORSSerialResponseEvaluator to ORSSerialPacketEvaluator. --- Source/ORSSerialPacketDescriptor.h | 2 +- Source/ORSSerialPacketDescriptor.m | 4 ++-- Source/ORSSerialRequest.m | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/ORSSerialPacketDescriptor.h b/Source/ORSSerialPacketDescriptor.h index 4af96202..59287477 100644 --- a/Source/ORSSerialPacketDescriptor.h +++ b/Source/ORSSerialPacketDescriptor.h @@ -41,7 +41,7 @@ NS_ASSUME_NONNULL_BEGIN * Block that parses input data and returns a packet extracted from that data, or nil * if inputData doesn't contain a valid packet. */ -typedef BOOL(^ORSSerialResponseEvaluator)(NSData * __nullable inputData); +typedef BOOL(^ORSSerialPacketEvaluator)(NSData * __nullable inputData); /** * An instance of ORSSerialPacketDescriptor is used to describe a packet format. ORSSerialPort diff --git a/Source/ORSSerialPacketDescriptor.m b/Source/ORSSerialPacketDescriptor.m index 8876c15e..74a10557 100644 --- a/Source/ORSSerialPacketDescriptor.m +++ b/Source/ORSSerialPacketDescriptor.m @@ -28,13 +28,13 @@ @interface ORSSerialPacketDescriptor () -@property (nonatomic, copy, readonly) ORSSerialResponseEvaluator responseEvaluator; +@property (nonatomic, copy, readonly) ORSSerialPacketEvaluator responseEvaluator; @end @implementation ORSSerialPacketDescriptor -- (instancetype)initWithUserInfo:(id)userInfo responseEvaluator:(ORSSerialResponseEvaluator)responseEvaluator +- (instancetype)initWithUserInfo:(id)userInfo responseEvaluator:(ORSSerialPacketEvaluator)responseEvaluator { self = [super init]; if (self) { diff --git a/Source/ORSSerialRequest.m b/Source/ORSSerialRequest.m index bf3feeee..04298b87 100644 --- a/Source/ORSSerialRequest.m +++ b/Source/ORSSerialRequest.m @@ -50,7 +50,7 @@ +(instancetype)requestWithDataToSend:(NSData *)dataToSend + (instancetype)requestWithDataToSend:(NSData *)dataToSend userInfo:(id)userInfo timeoutInterval:(NSTimeInterval)timeout - responseEvaluator:(ORSSerialResponseEvaluator)responseEvaluator; + responseEvaluator:(ORSSerialPacketEvaluator)responseEvaluator; { return [[self alloc] initWithDataToSend:dataToSend userInfo:userInfo timeoutInterval:timeout responseEvaluator:responseEvaluator]; } @@ -76,7 +76,7 @@ - (instancetype)initWithDataToSend:(NSData *)dataToSend - (instancetype)initWithDataToSend:(NSData *)dataToSend userInfo:(id)userInfo timeoutInterval:(NSTimeInterval)timeout - responseEvaluator:(ORSSerialResponseEvaluator)responseEvaluator; + responseEvaluator:(ORSSerialPacketEvaluator)responseEvaluator; { ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithUserInfo:nil responseEvaluator:responseEvaluator]; return [self initWithDataToSend:dataToSend userInfo:userInfo timeoutInterval:timeout responseDescriptor:descriptor]; From 97a95ec8f208a2a2366b2981ecb1777e4bc148f1 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 10 Aug 2015 14:33:11 -0600 Subject: [PATCH 21/55] Issue #55: Fixed incomplete rename in last commit. --- Source/ORSSerialPacketDescriptor.h | 2 +- Source/ORSSerialRequest.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/ORSSerialPacketDescriptor.h b/Source/ORSSerialPacketDescriptor.h index 59287477..b32898d6 100644 --- a/Source/ORSSerialPacketDescriptor.h +++ b/Source/ORSSerialPacketDescriptor.h @@ -82,7 +82,7 @@ typedef BOOL(^ORSSerialPacketEvaluator)(NSData * __nullable inputData); * @see -initWithRegularExpression:userInfo: */ - (instancetype)initWithUserInfo:(nullable id)userInfo - responseEvaluator:(ORSSerialResponseEvaluator)responseEvaluator NS_DESIGNATED_INITIALIZER; + responseEvaluator:(ORSSerialPacketEvaluator)responseEvaluator NS_DESIGNATED_INITIALIZER; /** * Creates an initializes an ORSSerialPacketDescriptor instance using a prefix and/or suffix. diff --git a/Source/ORSSerialRequest.h b/Source/ORSSerialRequest.h index f52b0bdd..055a5a11 100644 --- a/Source/ORSSerialRequest.h +++ b/Source/ORSSerialRequest.h @@ -82,7 +82,7 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype)requestWithDataToSend:(NSData *)dataToSend userInfo:(nullable id)userInfo timeoutInterval:(NSTimeInterval)timeout - responseEvaluator:(nullable ORSSerialResponseEvaluator)responseEvaluator; + responseEvaluator:(nullable ORSSerialPacketEvaluator)responseEvaluator; /** * Initializes an ORSSerialRequest instance. @@ -116,7 +116,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithDataToSend:(NSData *)dataToSend userInfo:(nullable id)userInfo timeoutInterval:(NSTimeInterval)timeout - responseEvaluator:(nullable ORSSerialResponseEvaluator)responseEvaluator; + responseEvaluator:(nullable ORSSerialPacketEvaluator)responseEvaluator; /** * Can be used to determine if a block of data is a valid response to the request encapsulated From 33c40598a19e6f5290f1f41a44053685d4621e76 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 10 Aug 2015 16:47:58 -0600 Subject: [PATCH 22/55] Issue #55: Added tests for missing prefix/suffix and updated documentation to reflect actual behavior. --- .../ORSSerialPacketDescriptor_Tests.m | 54 +++++++++++++++++++ .../ORSSerialPort Tests/ORSSerialPort_Tests.m | 22 -------- Source/ORSSerialPacketDescriptor.h | 14 +++-- 3 files changed, 60 insertions(+), 30 deletions(-) diff --git a/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m b/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m index 7286d3ec..ecf5565c 100644 --- a/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m +++ b/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m @@ -76,6 +76,60 @@ - (void)testPrefixSuffixStrings XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"!foo;x")], @"Invalid packet not rejected by descriptor."); } +- (void)testMissingPrefix +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Missing suffix packet parsing expectation."]; + NSDictionary *userInfo = @{[@";" dataUsingEncoding:NSASCIIStringEncoding] : expectation}; + NSData *suffix = [@";" dataUsingEncoding:NSASCIIStringEncoding]; + ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithPrefix:nil suffix:suffix userInfo:userInfo]; + XCTAssertNotNil(descriptor, @"Creating packet descriptor with prefix and suffix failed."); + XCTAssertEqualObjects(descriptor.suffix, suffix, @"Desriptor suffix property incorrect."); + XCTAssertNil(descriptor.prefix, @"Desriptor prefix property incorrect."); + + XCTAssertTrue([descriptor dataIsValidPacket:ORSTStringToData_(@"!foo;")], @"Valid packet rejected by descriptor."); + XCTAssertTrue([descriptor dataIsValidPacket:ORSTStringToData_(@"foobar;")], @"Valid packet rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"!foo")], @"Invalid packet not rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"foo")], @"Invalid packet not rejected by descriptor."); + + [self.port startListeningForPacketsMatchingDescriptor:descriptor]; + + NSData *buffer = [@"foobar;" dataUsingEncoding:NSASCIIStringEncoding]; + [self.port receiveData:buffer]; + + [self waitForExpectationsWithTimeout:0.5 handler:^(NSError *error) { + if (error) { + NSLog(@"expectation %@ failed: %@", expectation, error); + } + }]; +} + +- (void)testMissingSuffix +{ + XCTestExpectation *expectation = [self expectationWithDescription:@"Missing suffix packet parsing expectation."]; + NSDictionary *userInfo = @{[@"!" dataUsingEncoding:NSASCIIStringEncoding] : expectation}; + NSData *prefix = [@"!" dataUsingEncoding:NSASCIIStringEncoding]; + ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithPrefix:prefix suffix:nil userInfo:userInfo]; + XCTAssertNotNil(descriptor, @"Creating packet descriptor with prefix and suffix failed."); + XCTAssertEqualObjects(descriptor.prefix, prefix, @"Desriptor prefix property incorrect."); + XCTAssertNil(descriptor.suffix, @"Desriptor suffix property incorrect."); + + XCTAssertTrue([descriptor dataIsValidPacket:ORSTStringToData_(@"!foo;")], @"Valid packet rejected by descriptor."); + XCTAssertTrue([descriptor dataIsValidPacket:ORSTStringToData_(@"!foobar")], @"Valid packet rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"foo;")], @"Invalid packet not rejected by descriptor."); + XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"foo")], @"Invalid packet not rejected by descriptor."); + + [self.port startListeningForPacketsMatchingDescriptor:descriptor]; + + NSData *buffer = [@"!foobar" dataUsingEncoding:NSASCIIStringEncoding]; + [self.port receiveData:buffer]; + + [self waitForExpectationsWithTimeout:0.5 handler:^(NSError *error) { + if (error) { + NSLog(@"expectation %@ failed: %@", expectation, error); + } + }]; +} + - (void)testRegex { NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^!.+;$" options:0 error:NULL]; diff --git a/Framework Project/ORSSerialPort Tests/ORSSerialPort_Tests.m b/Framework Project/ORSSerialPort Tests/ORSSerialPort_Tests.m index fbfe2052..dc441f41 100644 --- a/Framework Project/ORSSerialPort Tests/ORSSerialPort_Tests.m +++ b/Framework Project/ORSSerialPort Tests/ORSSerialPort_Tests.m @@ -15,26 +15,4 @@ @interface ORSSerialPort_Tests : XCTestCase @implementation ORSSerialPort_Tests -- (void)setUp { - [super setUp]; - // Put setup code here. This method is called before the invocation of each test method in the class. -} - -- (void)tearDown { - // Put teardown code here. This method is called after the invocation of each test method in the class. - [super tearDown]; -} - -- (void)testExample { - // This is an example of a functional test case. - XCTAssert(YES, @"Pass"); -} - -- (void)testPerformanceExample { - // This is an example of a performance test case. - [self measureBlock:^{ - // Put the code you want to measure the time of here. - }]; -} - @end diff --git a/Source/ORSSerialPacketDescriptor.h b/Source/ORSSerialPacketDescriptor.h index b32898d6..ff4d885d 100644 --- a/Source/ORSSerialPacketDescriptor.h +++ b/Source/ORSSerialPacketDescriptor.h @@ -90,10 +90,9 @@ typedef BOOL(^ORSSerialPacketEvaluator)(NSData * __nullable inputData); * If the packet format uses printable ASCII characters, -initWithPrefixString:suffixString:userInfo: * may be more suitable. * - * @note Either prefix or suffix may be nil, but not both. If suffix is nil, packets will be considered - * to consist soley of prefix. If prefix is nil, the complete contents of the packet buffer when suffix - * is received will be considered a packet. Usually, well-designed packet protocols will include both - * a prefix and a suffix. + * @note Either prefix or suffix may be nil, but not both. If the suffix is nil, + * packets will be considered to consist solely of prefix. If either value is nil, packets + * will be considred to consist soley of the the non-nil value. * * @param prefix An NSData instance containing a fixed packet prefix. May be nil. * @param suffix An NSData instance containing a fixed packet suffix. May be nil. @@ -114,10 +113,9 @@ typedef BOOL(^ORSSerialPacketEvaluator)(NSData * __nullable inputData); * If the packet format does not use printable ASCII characters, -initWithPrefix:suffix:userInfo: * may be more suitable. * - * @note Either prefixString or suffixString may be nil, but not both. If the suffix is nil, packets will be considered - * to consist soley of prefix. If the prefix is nil, the complete contents of the packet buffer when a suffix - * is received will be considered a packet. Usually, well-designed packet protocols will include both - * a prefix and a suffix. + * @note Either prefixString or suffixString may be nil, but not both. If the suffix is nil, + * packets will be considered to consist solely of prefix. If either value is nil, packets + * will be considred to consist soley of the the non-nil value. * * @param prefixString A fixed packet prefix string. May be nil. * @param suffixString A fixed packet suffix string. May be nil. From 3bb44e420963c741265868fcbb7fdd5640318d38 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 10 Aug 2015 17:11:08 -0600 Subject: [PATCH 23/55] Issue #55: Rewrote request response logic to use new packet parsing logic. --- Source/ORSSerialPort.m | 149 ++++++++++++++++++++++---------------- Source/ORSSerialRequest.h | 40 +++++++--- 2 files changed, 114 insertions(+), 75 deletions(-) diff --git a/Source/ORSSerialPort.m b/Source/ORSSerialPort.m index 5ed42ed7..32473bd1 100644 --- a/Source/ORSSerialPort.m +++ b/Source/ORSSerialPort.m @@ -62,7 +62,7 @@ @interface ORSSerialPort () @property int fileDescriptor; @property (copy, readwrite) NSString *name; -@property (strong) NSMutableData *receiveBuffer; +@property (strong) NSMutableData *requestResponseReceiveBuffer; // Packet descriptors @property (nonatomic, strong) NSMapTable *packetDescriptorsAndBuffers; @@ -172,7 +172,7 @@ - (instancetype)initWithDevice:(io_object_t)device; self.ioKitDevice = device; self.path = bsdPath; self.name = [[self class] modemNameFromDevice:device]; - self.receiveBuffer = [NSMutableData data]; + self.requestResponseReceiveBuffer = [NSMutableData data]; self.requestHandlingQueue = dispatch_queue_create("com.openreelsoftware.ORSSerialPort.requestHandlingQueue", 0); #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_8 self.packetDescriptorsAndBuffers = [NSMapTable strongToStrongObjectsMapTable]; @@ -311,7 +311,7 @@ - (void)open; if (readData != nil) [self receiveData:readData]; } }); - dispatch_source_set_cancel_handler(readPollSource, ^{ [self reallyClosePort]; }); + dispatch_source_set_cancel_handler(readPollSource, ^{ [self reallyClosePort]; }); dispatch_resume(readPollSource); self.readPollSource = readPollSource; @@ -357,42 +357,42 @@ - (BOOL)close; { if (!self.isOpen) return YES; self.readPollSource = nil; // Cancel read dispatch source. Cancel handler will call -reallyClosePort - return YES; + return YES; } - (void)reallyClosePort { - self.pinPollTimer = nil; // Stop polling CTS/DSR/DCD pins - - // The next tcsetattr() call can fail if the port is waiting to send data. This is likely to happen - // e.g. if flow control is on and the CTS line is low. So, turn off flow control before proceeding - struct termios options; - tcgetattr(self.fileDescriptor, &options); - options.c_cflag &= ~CRTSCTS; // RTS/CTS Flow Control - options.c_cflag &= ~(CDTR_IFLOW | CDSR_OFLOW); // DTR/DSR Flow Control - options.c_cflag &= ~CCAR_OFLOW; // DCD Flow Control - tcsetattr(self.fileDescriptor, TCSANOW, &options); - - // Set port back the way it was before we used it - tcsetattr(self.fileDescriptor, TCSADRAIN, &originalPortAttributes); - - if (close(self.fileDescriptor)) - { - LOG_SERIAL_PORT_ERROR(@"Error closing serial port with file descriptor %i:%i", self.fileDescriptor, errno); - [self notifyDelegateOfPosixError]; - return; - } - - self.fileDescriptor = 0; - - if ([self.delegate respondsToSelector:@selector(serialPortWasClosed:)]) - { - [(id)self.delegate performSelectorOnMainThread:@selector(serialPortWasClosed:) withObject:self waitUntilDone:YES]; - dispatch_async(self.requestHandlingQueue, ^{ - self.requestsQueue = [NSMutableArray array]; // Cancel all queued requests - self.pendingRequest = nil; // Discard pending request - }); - } + self.pinPollTimer = nil; // Stop polling CTS/DSR/DCD pins + + // The next tcsetattr() call can fail if the port is waiting to send data. This is likely to happen + // e.g. if flow control is on and the CTS line is low. So, turn off flow control before proceeding + struct termios options; + tcgetattr(self.fileDescriptor, &options); + options.c_cflag &= ~CRTSCTS; // RTS/CTS Flow Control + options.c_cflag &= ~(CDTR_IFLOW | CDSR_OFLOW); // DTR/DSR Flow Control + options.c_cflag &= ~CCAR_OFLOW; // DCD Flow Control + tcsetattr(self.fileDescriptor, TCSANOW, &options); + + // Set port back the way it was before we used it + tcsetattr(self.fileDescriptor, TCSADRAIN, &originalPortAttributes); + + if (close(self.fileDescriptor)) + { + LOG_SERIAL_PORT_ERROR(@"Error closing serial port with file descriptor %i:%i", self.fileDescriptor, errno); + [self notifyDelegateOfPosixError]; + return; + } + + self.fileDescriptor = 0; + + if ([self.delegate respondsToSelector:@selector(serialPortWasClosed:)]) + { + [(id)self.delegate performSelectorOnMainThread:@selector(serialPortWasClosed:) withObject:self waitUntilDone:YES]; + dispatch_async(self.requestHandlingQueue, ^{ + self.requestsQueue = [NSMutableArray array]; // Cancel all queued requests + self.pendingRequest = nil; // Discard pending request + }); + } } - (void)cleanup; @@ -475,28 +475,21 @@ - (void)stopListeningForPacketsMatchingDescriptor:(ORSSerialPacketDescriptor *)d #pragma mark - Private Methods +- (void)clearBufferForPacketDescriptor:(ORSSerialPacketDescriptor *)descriptor +{ + NSMutableData *buffer = [self.packetDescriptorsAndBuffers objectForKey:descriptor]; + [buffer setData:[NSData data]]; // Clear buffer +} + // Must only be called on requestHandlingQueue (ie. wrap call to this method in dispatch()) -- (void)checkForCompletedPacketsAndNotifyDelegate:(NSData *)receivedByte +- (NSData *)packetMatchingDescriptor:(ORSSerialPacketDescriptor *)descriptor atEndOfBuffer:(NSData *)buffer { - for (ORSSerialPacketDescriptor *descriptor in self.packetDescriptorsAndBuffers) + for (NSUInteger i=1; i<=[buffer length]; i++) { - NSMutableData *buffer = [self.packetDescriptorsAndBuffers objectForKey:descriptor]; - [buffer appendData:receivedByte]; - for (NSUInteger i=1; i<=[buffer length]; i++) - { - NSData *window = [buffer subdataWithRange:NSMakeRange([buffer length]-i, i)]; - if ([descriptor dataIsValidPacket:window]) - { - if ([self.delegate respondsToSelector:@selector(serialPort:didReceivePacket:matchingDescriptor:)]) - { - dispatch_async(dispatch_get_main_queue(), ^{ - [self.delegate serialPort:self didReceivePacket:window matchingDescriptor:descriptor]; - }); - } - [buffer setData:[NSData data]]; // Clear buffer - } - } + NSData *window = [buffer subdataWithRange:NSMakeRange([buffer length]-i, i)]; + if ([descriptor dataIsValidPacket:window]) return window; } + return nil; } // Must only be called on requestHandlingQueue (ie. wrap call to this method in dispatch()) @@ -504,9 +497,9 @@ - (BOOL)reallySendRequest:(ORSSerialRequest *)request { if (!self.pendingRequest) { - [self.receiveBuffer replaceBytesInRange:NSMakeRange(0, [self.receiveBuffer length]) - withBytes:NULL - length:0]; + [self.requestResponseReceiveBuffer replaceBytesInRange:NSMakeRange(0, [self.requestResponseReceiveBuffer length]) + withBytes:NULL + length:0]; // Send immediately self.pendingRequest = request; @@ -520,7 +513,7 @@ - (BOOL)reallySendRequest:(ORSSerialRequest *)request } BOOL success = [self sendData:request.dataToSend]; // Immediately send next request if this one doesn't require a response - if (success) [self checkResponseToPendingRequestAndContinueIfValid]; + if (success) [self checkResponseToPendingRequestAndContinueIfValidWithReceivedByte:nil]; return success; } @@ -561,10 +554,18 @@ - (void)pendingRequestDidTimeout } // Must only be called on requestHandlingQueue -- (void)checkResponseToPendingRequestAndContinueIfValid +- (void)checkResponseToPendingRequestAndContinueIfValidWithReceivedByte:(NSData *)byte { - NSData *responseData = [self.receiveBuffer copy]; - if (![self.pendingRequest dataIsValidResponse:responseData]) return; + ORSSerialPacketDescriptor *packetDescriptor = self.pendingRequest.responseDescriptor; + + if (!byte) { + if (!packetDescriptor) [self sendNextRequest]; + return; + } + + [self.requestResponseReceiveBuffer appendData:byte]; + NSData *responseData = [self packetMatchingDescriptor:packetDescriptor atEndOfBuffer:self.requestResponseReceiveBuffer]; + if (!responseData) return; self.pendingRequestTimeoutTimer = nil; ORSSerialRequest *request = self.pendingRequest; @@ -594,10 +595,32 @@ - (void)receiveData:(NSData *)data; dispatch_async(self.requestHandlingQueue, ^{ const void *bytes = [data bytes]; for (NSUInteger i=0; i<[data length]; i++) { + NSData *byte = [NSData dataWithBytesNoCopy:(void *)(bytes+i) length:1 freeWhenDone:NO]; - [self checkForCompletedPacketsAndNotifyDelegate:byte]; - [self.receiveBuffer appendData:byte]; - [self checkResponseToPendingRequestAndContinueIfValid]; + + // Check for packets we're listening for + for (ORSSerialPacketDescriptor *descriptor in self.packetDescriptorsAndBuffers) + { + // Append byte to buffer + NSMutableData *buffer = [self.packetDescriptorsAndBuffers objectForKey:descriptor]; + [buffer appendData:byte]; + + // Check for complete packet + NSData *completePacket = [self packetMatchingDescriptor:descriptor atEndOfBuffer:buffer]; + if (![completePacket length]) continue; + + // Complete packet received, so notify delegate then clear buffer + if ([self.delegate respondsToSelector:@selector(serialPort:didReceivePacket:matchingDescriptor:)]) + { + dispatch_async(dispatch_get_main_queue(), ^{ + [self.delegate serialPort:self didReceivePacket:completePacket matchingDescriptor:descriptor]; + }); + } + [self clearBufferForPacketDescriptor:descriptor]; + } + + // Also check for response to pending request + [self checkResponseToPendingRequestAndContinueIfValidWithReceivedByte:byte]; } }); } diff --git a/Source/ORSSerialRequest.h b/Source/ORSSerialRequest.h index 055a5a11..c8df1002 100644 --- a/Source/ORSSerialRequest.h +++ b/Source/ORSSerialRequest.h @@ -118,17 +118,6 @@ NS_ASSUME_NONNULL_BEGIN timeoutInterval:(NSTimeInterval)timeout responseEvaluator:(nullable ORSSerialPacketEvaluator)responseEvaluator; -/** - * Can be used to determine if a block of data is a valid response to the request encapsulated - * by the receiver. If the receiver doesn't have a response data evaulator block, this method - * always returns YES. - * - * @param responseData Data received from a serial port. - * - * @return YES if the data is a valid response, NO otherwise. - */ -- (BOOL)dataIsValidResponse:(nullable NSData *)responseData; - /** * Data to be sent on the serial port when the receiver is sent. */ @@ -147,6 +136,11 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, readonly) NSTimeInterval timeoutInterval; +/** + * The descriptor describing the receiver's expected response. + */ +@property (nonatomic, strong, readonly) ORSSerialPacketDescriptor *responseDescriptor; + /** * Unique identifier for the request. */ @@ -154,4 +148,26 @@ NS_ASSUME_NONNULL_BEGIN @end -NS_ASSUME_NONNULL_END \ No newline at end of file +#pragma mark - Deprecated + +@interface ORSSerialRequest (Deprecated) + +/** + * @deprecated Use the receiver's responseDescriptor object's -dataIsValidPacket: method instead. + * Except in the special case where the response descriptor is nil, this method now simply calls + * through to that. + * + * Can be used to determine if a block of data is a valid response to the request encapsulated + * by the receiver. If the receiver doesn't have a response descriptor, this method + * always returns YES. + * + * @param responseData Data received from a serial port. + * + * @return YES if the data is a valid response, NO otherwise. + */ +- (BOOL)dataIsValidResponse:(nullable NSData *)responseData DEPRECATED_ATTRIBUTE; + +@end + +NS_ASSUME_NONNULL_END + From 9ff80b3d8bbf8865052313835fa52b284c2a3acf Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 31 Aug 2015 11:58:18 -0600 Subject: [PATCH 24/55] Documented -start/stopListeningForPacketsMatchingDescriptor:. (Issue #55). --- Source/ORSSerialPort.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Source/ORSSerialPort.h b/Source/ORSSerialPort.h index e24d8b90..659e493d 100644 --- a/Source/ORSSerialPort.h +++ b/Source/ORSSerialPort.h @@ -292,8 +292,33 @@ NS_ASSUME_NONNULL_BEGIN * --------------------------------------------------------------------------------------- */ +/** + * Tells the receiver to begin listening for incoming packets matching the specified + * descriptor. + * + * When incoming data that constitutes a packet as described by descriptor is received, + * the delegate method -serialPort:didReceivePacket:matchingDescriptor: will be called. + * + * @param descriptor An ORSerialPacketDescriptor instance describing the packets the receiver + * should listen for. + * + * @see -stopListeningForPacketsMatchingDescriptor: + * @see -serialPort:didReceivePacket:matchingDescriptor: + */ - (void)startListeningForPacketsMatchingDescriptor:(ORSSerialPacketDescriptor *)descriptor; +/** + * Tells the receiver to stop listening for incoming packets matching the specified + * descriptor. + * + * @note The passed in descriptor must be the exact same instance as was previously + * provided to -startListeningForPacketsMatchingDescriptor: + * + * @param descriptor An ORSSerialPacketDescriptor instance previously passed to + * -startListeningForPacketsMatchingDescriptor: + * + * @see -startListeningForPacketsMatchingDescriptor: + */ - (void)stopListeningForPacketsMatchingDescriptor:(ORSSerialPacketDescriptor *)descriptor; /** --------------------------------------------------------------------------------------- From 078aa2c2ab01bdba543140df17a6e51c2230ca95 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 31 Aug 2015 13:18:00 -0600 Subject: [PATCH 25/55] Added packetDescriptors property and associated tests (Issue #55). --- .../ORSSerialPacketDescriptor_Tests.m | 32 +++++++++++++++++++ Source/ORSSerialPort.h | 12 +++++++ Source/ORSSerialPort.m | 15 +++++++++ 3 files changed, 59 insertions(+) diff --git a/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m b/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m index ecf5565c..78c4c6ce 100644 --- a/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m +++ b/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m @@ -234,6 +234,38 @@ - (void)testParsingNestedPackets }]; } +- (void)testPacketDescriptorsPropertyAdd +{ + XCTAssertNotNil(self.port.packetDescriptors, @"-[ORSSerialPort packetDescriptors] returned nil."); + XCTAssert([self.port.packetDescriptors count] == 0, @"-[ORSSerialPort packetDescriptors] returned non-empty array with no descriptors added."); + + ORSSerialPacketDescriptor *descriptor = [self defaultPacketDescriptorWithUserInfo:nil]; + [self keyValueObservingExpectationForObject:self.port keyPath:@"packetDescriptors" expectedValue:@[descriptor]]; + [self.port startListeningForPacketsMatchingDescriptor:descriptor]; + + [self waitForExpectationsWithTimeout:0.1 handler:^(NSError *error) { + if (error) { + NSLog(@"expectations failed: %@", error); + } + }]; +} + +- (void)testPacketDescriptorsPropertyRemove +{ + ORSSerialPacketDescriptor *descriptor = [self defaultPacketDescriptorWithUserInfo:nil]; + [self.port startListeningForPacketsMatchingDescriptor:descriptor]; + XCTAssertEqualObjects(@[descriptor], self.port.packetDescriptors, @"-packetDescriptors did not return expected result."); + + [self keyValueObservingExpectationForObject:self.port keyPath:@"packetDescriptors" expectedValue:@[]]; + [self.port stopListeningForPacketsMatchingDescriptor:descriptor]; + + [self waitForExpectationsWithTimeout:0.1 handler:^(NSError *error) { + if (error) { + NSLog(@"expectations failed: %@", error); + } + }]; +} + #pragma mark - Utilties - (ORSSerialPacketDescriptor *)defaultPacketDescriptorWithUserInfo:(id)userInfo diff --git a/Source/ORSSerialPort.h b/Source/ORSSerialPort.h index 659e493d..b7c43a13 100644 --- a/Source/ORSSerialPort.h +++ b/Source/ORSSerialPort.h @@ -361,6 +361,18 @@ NS_ASSUME_NONNULL_BEGIN */ @property (strong, readonly) NSArray *queuedRequests; +/** --------------------------------------------------------------------------------------- + * @name Packet Parsing Properties + * --------------------------------------------------------------------------------------- + */ + +/** + * An array of packet descriptors for which the port is listening. + * + * Returns an empty array if no packet descriptors are installed. + */ +@property (nonatomic, strong, readonly) NSArray *packetDescriptors; + /** --------------------------------------------------------------------------------------- * @name Port Properties * --------------------------------------------------------------------------------------- diff --git a/Source/ORSSerialPort.m b/Source/ORSSerialPort.m index cd153a4f..d8e8b575 100644 --- a/Source/ORSSerialPort.m +++ b/Source/ORSSerialPort.m @@ -470,12 +470,16 @@ - (void)startListeningForPacketsMatchingDescriptor:(ORSSerialPacketDescriptor *) { if ([self.packetDescriptorsAndBuffers objectForKey:descriptor]) return; // Already listening + [self willChangeValueForKey:@"packetDescriptorsAndBuffers"]; [self.packetDescriptorsAndBuffers setObject:[NSMutableData data] forKey:descriptor]; + [self didChangeValueForKey:@"packetDescriptorsAndBuffers"]; } - (void)stopListeningForPacketsMatchingDescriptor:(ORSSerialPacketDescriptor *)descriptor; { + [self willChangeValueForKey:@"packetDescriptorsAndBuffers"]; [self.packetDescriptorsAndBuffers removeObjectForKey:descriptor]; + [self didChangeValueForKey:@"packetDescriptorsAndBuffers"]; } #pragma mark - Private Methods @@ -831,6 +835,17 @@ - (NSArray *)queuedRequests return [self.requestsQueue copy]; } ++ (NSSet *)keyPathsForValuesAffectingPacketDescriptors +{ + return [NSSet setWithObject:@"packetDescriptorsAndBuffers"]; +} + +- (NSArray *)packetDescriptors +{ + NSArray *result = NSAllMapTableKeys(self.packetDescriptorsAndBuffers); + return result ?: @[]; +} + - (BOOL)isOpen { return self.fileDescriptor != 0; } - (void)setIoKitDevice:(io_object_t)device From 4af7f7c0af5f21344da7fd82deb1214656d65935 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 31 Aug 2015 13:19:06 -0600 Subject: [PATCH 26/55] Issue #58: Annotated new packetDescriptors property for ObjC generics. --- Source/ORSSerialPort.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/ORSSerialPort.h b/Source/ORSSerialPort.h index 3399a1c0..5c529f00 100644 --- a/Source/ORSSerialPort.h +++ b/Source/ORSSerialPort.h @@ -379,7 +379,7 @@ NS_ASSUME_NONNULL_BEGIN * * Returns an empty array if no packet descriptors are installed. */ -@property (nonatomic, strong, readonly) NSArray *packetDescriptors; +@property (nonatomic, strong, readonly) ORSArrayOf(ORSPacketDescriptor *) *packetDescriptors; /** --------------------------------------------------------------------------------------- * @name Port Properties From 4bd0be6ffd30d609cfe5f2390ad05da4c0152e2d Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 31 Aug 2015 13:33:13 -0600 Subject: [PATCH 27/55] Issue #60: Converted Swift CommandLineDemo to Swift 2.0. --- .../CommandLineDemo.xcodeproj/project.pbxproj | 2 + .../CommandLineDemo/Swift/Sources/main.swift | 40 +++++++++---------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/Examples/CommandLineDemo/Swift/CommandLineDemo.xcodeproj/project.pbxproj b/Examples/CommandLineDemo/Swift/CommandLineDemo.xcodeproj/project.pbxproj index 66092275..cbe73dc1 100644 --- a/Examples/CommandLineDemo/Swift/CommandLineDemo.xcodeproj/project.pbxproj +++ b/Examples/CommandLineDemo/Swift/CommandLineDemo.xcodeproj/project.pbxproj @@ -108,6 +108,8 @@ 9D2B57F31ADC165D00B08D53 /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftMigration = 0700; + LastSwiftUpdateCheck = 0700; LastUpgradeCheck = 0630; ORGANIZATIONNAME = "Open Reel Software"; TargetAttributes = { diff --git a/Examples/CommandLineDemo/Swift/Sources/main.swift b/Examples/CommandLineDemo/Swift/Sources/main.swift index fb928dc3..8ebd3fdd 100644 --- a/Examples/CommandLineDemo/Swift/Sources/main.swift +++ b/Examples/CommandLineDemo/Swift/Sources/main.swift @@ -37,27 +37,27 @@ enum ApplicationState { struct UserPrompter { func printIntroduction() { - println("This program demonstrates the use of ORSSerialPort") - println("in a Foundation-based command-line tool.") - println("Please see http://github.com/armadsen/ORSSerialPort/\nor email andrew@openreelsoftware.com for more information.\n") + print("This program demonstrates the use of ORSSerialPort") + print("in a Foundation-based command-line tool.") + print("Please see http://github.com/armadsen/ORSSerialPort/\nor email andrew@openreelsoftware.com for more information.\n") } func printPrompt() { - print("\n> ") + print("\n> ", appendNewline: false) } func promptForSerialPort() { - println("\nPlease select a serial port: \n") - let availablePorts = ORSSerialPortManager.sharedSerialPortManager().availablePorts as! [ORSSerialPort] + print("\nPlease select a serial port: \n") + let availablePorts = ORSSerialPortManager.sharedSerialPortManager().availablePorts var i = 0 for port in availablePorts { - println("\(i++). \(port.name)") + print("\(i++). \(port.name)") } printPrompt() } func promptForBaudRate() { - print("\nPlease enter a baud rate: "); + print("\nPlease enter a baud rate: ", appendNewline: false); } } @@ -75,7 +75,7 @@ class StateMachine : NSObject, ORSSerialPortDelegate { func runProcessingInput() { setbuf(stdout, nil) - standardInputFileHandle.readabilityHandler = { (fileHandle: NSFileHandle!) in + standardInputFileHandle.readabilityHandler = { (fileHandle: NSFileHandle) in let data = fileHandle.availableData dispatch_async(dispatch_get_main_queue(), { () -> Void in self.handleUserInput(data) @@ -84,9 +84,9 @@ class StateMachine : NSObject, ORSSerialPortDelegate { prompter.printIntroduction() - let availablePorts = ORSSerialPortManager.sharedSerialPortManager().availablePorts as! [ORSSerialPort] + let availablePorts = ORSSerialPortManager.sharedSerialPortManager().availablePorts if availablePorts.count == 0 { - println("No connected serial ports found. Please connect your USB to serial adapter(s) and run the program again.\n") + print("No connected serial ports found. Please connect your USB to serial adapter(s) and run the program again.\n") exit(EXIT_SUCCESS) } prompter.promptForSerialPort() @@ -98,7 +98,7 @@ class StateMachine : NSObject, ORSSerialPortDelegate { // MARK: Port Settings func setupAndOpenPortWithSelectionString(var selectionString: String, availablePorts: [ORSSerialPort]) -> Bool { selectionString = selectionString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) - if let index = selectionString.toInt() { + if let index = Int(selectionString) { let clampedIndex = min(max(index, 0), availablePorts.count-1) self.serialPort = availablePorts[clampedIndex] return true @@ -109,9 +109,9 @@ class StateMachine : NSObject, ORSSerialPortDelegate { func setBaudRateOnPortWithString(var selectionString: String) -> Bool { selectionString = selectionString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) - if let baudRate = selectionString.toInt() { + if let baudRate = Int(selectionString) { self.serialPort?.baudRate = baudRate - print("Baud rate set to \(baudRate)") + print("Baud rate set to \(baudRate)", appendNewline: false) return true } else { return false @@ -124,20 +124,20 @@ class StateMachine : NSObject, ORSSerialPortDelegate { if string.lowercaseString.hasPrefix("exit") || string.lowercaseString.hasPrefix("quit") { - println("Quitting...") + print("Quitting...") exit(EXIT_SUCCESS) } switch self.currentState { case .WaitingForPortSelectionState(let availablePorts): if !setupAndOpenPortWithSelectionString(string, availablePorts: availablePorts) { - print("\nError: Invalid port selection.") + print("\nError: Invalid port selection.", appendNewline: false) prompter.promptForSerialPort() return } case .WaitingForBaudRateInputState: if !setBaudRateOnPortWithString(string) { - print("\nError: Invalid baud rate. Baud rate should consist only of numeric digits."); + print("\nError: Invalid baud rate. Baud rate should consist only of numeric digits.", appendNewline: false); prompter.promptForBaudRate(); return; } @@ -156,7 +156,7 @@ class StateMachine : NSObject, ORSSerialPortDelegate { func serialPort(serialPort: ORSSerialPort, didReceiveData data: NSData) { if let string = NSString(data: data, encoding: NSUTF8StringEncoding) { - print("\nReceived: \"\(string)\" \(data)") + print("\nReceived: \"\(string)\" \(data)", appendNewline: false) } prompter.printPrompt() } @@ -166,11 +166,11 @@ class StateMachine : NSObject, ORSSerialPortDelegate { } func serialPort(serialPort: ORSSerialPort, didEncounterError error: NSError) { - println("Serial port (\(serialPort)) encountered error: \(error)") + print("Serial port (\(serialPort)) encountered error: \(error)") } func serialPortWasOpened(serialPort: ORSSerialPort) { - print("Serial port \(serialPort) was opened") + print("Serial port \(serialPort) was opened", appendNewline: false) prompter.promptForBaudRate() currentState = .WaitingForBaudRateInputState } From 857b507ae7736abd39384d03f49cc48a90e0183b Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 31 Aug 2015 13:36:20 -0600 Subject: [PATCH 28/55] Fixed bad declaration of -packetDescriptors (Issue #58). --- Source/ORSSerialPort.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/ORSSerialPort.h b/Source/ORSSerialPort.h index 5c529f00..4ad2c071 100644 --- a/Source/ORSSerialPort.h +++ b/Source/ORSSerialPort.h @@ -379,7 +379,7 @@ NS_ASSUME_NONNULL_BEGIN * * Returns an empty array if no packet descriptors are installed. */ -@property (nonatomic, strong, readonly) ORSArrayOf(ORSPacketDescriptor *) *packetDescriptors; +@property (nonatomic, strong, readonly) ORSArrayOf(ORSSerialPacketDescriptor *) *packetDescriptors; /** --------------------------------------------------------------------------------------- * @name Port Properties From aec80e833e33937959796c23ca64522bc662ca37 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 31 Aug 2015 13:39:43 -0600 Subject: [PATCH 29/55] [Swift CommandLineDemo]: Updated to latest Xcode 7 recommended project settings. --- .../CommandLineDemo.xcodeproj/project.pbxproj | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Examples/CommandLineDemo/Swift/CommandLineDemo.xcodeproj/project.pbxproj b/Examples/CommandLineDemo/Swift/CommandLineDemo.xcodeproj/project.pbxproj index 66092275..0340676f 100644 --- a/Examples/CommandLineDemo/Swift/CommandLineDemo.xcodeproj/project.pbxproj +++ b/Examples/CommandLineDemo/Swift/CommandLineDemo.xcodeproj/project.pbxproj @@ -10,6 +10,8 @@ 9D2B58071ADC16B500B08D53 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D2B58061ADC16B500B08D53 /* main.swift */; }; 9D2B58141ADC170C00B08D53 /* ORSSerialPort.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2B58111ADC170C00B08D53 /* ORSSerialPort.m */; }; 9D2B58151ADC170C00B08D53 /* ORSSerialPortManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2B58131ADC170C00B08D53 /* ORSSerialPortManager.m */; }; + 9DFF14861B94E38D004B42B3 /* ORSSerialPacketDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DFF14851B94E38D004B42B3 /* ORSSerialPacketDescriptor.m */; }; + 9DFF14891B94E396004B42B3 /* ORSSerialRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DFF14881B94E396004B42B3 /* ORSSerialRequest.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -32,6 +34,10 @@ 9D2B58111ADC170C00B08D53 /* ORSSerialPort.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORSSerialPort.m; path = ../../../../Source/ORSSerialPort.m; sourceTree = ""; }; 9D2B58121ADC170C00B08D53 /* ORSSerialPortManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORSSerialPortManager.h; path = ../../../../Source/ORSSerialPortManager.h; sourceTree = ""; }; 9D2B58131ADC170C00B08D53 /* ORSSerialPortManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORSSerialPortManager.m; path = ../../../../Source/ORSSerialPortManager.m; sourceTree = ""; }; + 9DFF14841B94E38D004B42B3 /* ORSSerialPacketDescriptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORSSerialPacketDescriptor.h; path = ../../../../Source/ORSSerialPacketDescriptor.h; sourceTree = ""; }; + 9DFF14851B94E38D004B42B3 /* ORSSerialPacketDescriptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORSSerialPacketDescriptor.m; path = ../../../../Source/ORSSerialPacketDescriptor.m; sourceTree = ""; }; + 9DFF14871B94E396004B42B3 /* ORSSerialRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORSSerialRequest.h; path = ../../../../Source/ORSSerialRequest.h; sourceTree = ""; }; + 9DFF14881B94E396004B42B3 /* ORSSerialRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORSSerialRequest.m; path = ../../../../Source/ORSSerialRequest.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -78,6 +84,10 @@ 9D2B58111ADC170C00B08D53 /* ORSSerialPort.m */, 9D2B58121ADC170C00B08D53 /* ORSSerialPortManager.h */, 9D2B58131ADC170C00B08D53 /* ORSSerialPortManager.m */, + 9DFF14871B94E396004B42B3 /* ORSSerialRequest.h */, + 9DFF14881B94E396004B42B3 /* ORSSerialRequest.m */, + 9DFF14841B94E38D004B42B3 /* ORSSerialPacketDescriptor.h */, + 9DFF14851B94E38D004B42B3 /* ORSSerialPacketDescriptor.m */, ); name = ORSSerialPort; sourceTree = ""; @@ -108,7 +118,7 @@ 9D2B57F31ADC165D00B08D53 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0630; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Open Reel Software"; TargetAttributes = { 9D2B57FA1ADC165D00B08D53 = { @@ -139,8 +149,10 @@ buildActionMask = 2147483647; files = ( 9D2B58151ADC170C00B08D53 /* ORSSerialPortManager.m in Sources */, + 9DFF14861B94E38D004B42B3 /* ORSSerialPacketDescriptor.m in Sources */, 9D2B58071ADC16B500B08D53 /* main.swift in Sources */, 9D2B58141ADC170C00B08D53 /* ORSSerialPort.m in Sources */, + 9DFF14891B94E396004B42B3 /* ORSSerialRequest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From e272adfad2165e70d58a9de2c7f363cd8ad4225e Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 31 Aug 2015 13:40:40 -0600 Subject: [PATCH 30/55] [ObjC CommandLineDemo]: Updated to latest Xcode 7 recommended project settings. --- .../Objective-C/CommandLineDemo.xcodeproj/project.pbxproj | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Examples/CommandLineDemo/Objective-C/CommandLineDemo.xcodeproj/project.pbxproj b/Examples/CommandLineDemo/Objective-C/CommandLineDemo.xcodeproj/project.pbxproj index 1bc54a0d..4c71ae48 100644 --- a/Examples/CommandLineDemo/Objective-C/CommandLineDemo.xcodeproj/project.pbxproj +++ b/Examples/CommandLineDemo/Objective-C/CommandLineDemo.xcodeproj/project.pbxproj @@ -128,7 +128,7 @@ 9DF045221678333000DA0CDA /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0630; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Open Reel Software"; }; buildConfigurationList = 9DF045251678333000DA0CDA /* Build configuration list for PBXProject "CommandLineDemo" */; @@ -166,7 +166,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -177,6 +176,7 @@ CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; @@ -200,7 +200,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; From d1cb96b962e9827ecd403460dbe36d6c85025cd9 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 31 Aug 2015 13:43:36 -0600 Subject: [PATCH 31/55] Updated remaining example projects to Xcode 7's latest recommended project settings. --- .../project.pbxproj | 7 ++++--- .../Resources/ORSSerialPortDemo-Info.plist | 2 +- .../project.pbxproj | 6 +++++- .../Swift/Resources/Info.plist | 2 +- .../project.pbxproj | 5 ++++- .../Objective-C/Resources/Info.plist | 2 +- .../project.pbxproj | 6 +++++- .../Swift/Resources/Info.plist | 2 +- .../project.pbxproj | 21 ++++++++++++++++++- .../Swift/Resources/Info.plist | 2 +- .../xcshareddata/xcschemes/ORSSerial.xcscheme | 11 ++++++---- 11 files changed, 50 insertions(+), 16 deletions(-) diff --git a/Examples/ORSSerialPortDemo/Objective-C/ORSSerialPortDemo.xcodeproj/project.pbxproj b/Examples/ORSSerialPortDemo/Objective-C/ORSSerialPortDemo.xcodeproj/project.pbxproj index 89795a32..8ec14c95 100644 --- a/Examples/ORSSerialPortDemo/Objective-C/ORSSerialPortDemo.xcodeproj/project.pbxproj +++ b/Examples/ORSSerialPortDemo/Objective-C/ORSSerialPortDemo.xcodeproj/project.pbxproj @@ -164,7 +164,7 @@ isa = PBXProject; attributes = { CLASSPREFIX = ORS; - LastUpgradeCheck = 0640; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Open Reel Software"; }; buildConfigurationList = 9D66D808159BCAB800EE6D09 /* Build configuration list for PBXProject "ORSSerialPortDemo" */; @@ -244,9 +244,9 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_ENABLE_MODULES = YES; COPY_PHASE_STRIP = NO; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; @@ -272,7 +272,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_ENABLE_MODULES = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -296,6 +295,7 @@ COMBINE_HIDPI_IMAGES = YES; GCC_PRECOMPILE_PREFIX_HEADER = NO; INFOPLIST_FILE = "Resources/ORSSerialPortDemo-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = ORSSerialPortDemo; WRAPPER_EXTENSION = app; }; @@ -308,6 +308,7 @@ COMBINE_HIDPI_IMAGES = YES; GCC_PRECOMPILE_PREFIX_HEADER = NO; INFOPLIST_FILE = "Resources/ORSSerialPortDemo-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = ORSSerialPortDemo; WRAPPER_EXTENSION = app; }; diff --git a/Examples/ORSSerialPortDemo/Objective-C/Resources/ORSSerialPortDemo-Info.plist b/Examples/ORSSerialPortDemo/Objective-C/Resources/ORSSerialPortDemo-Info.plist index 8030b0bd..535d186c 100644 --- a/Examples/ORSSerialPortDemo/Objective-C/Resources/ORSSerialPortDemo-Info.plist +++ b/Examples/ORSSerialPortDemo/Objective-C/Resources/ORSSerialPortDemo-Info.plist @@ -9,7 +9,7 @@ CFBundleIconFile CFBundleIdentifier - com.openreelsoftware.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Examples/ORSSerialPortDemo/Swift/ORSSerialPortDemo.xcodeproj/project.pbxproj b/Examples/ORSSerialPortDemo/Swift/ORSSerialPortDemo.xcodeproj/project.pbxproj index 2ab34973..f65e3368 100644 --- a/Examples/ORSSerialPortDemo/Swift/ORSSerialPortDemo.xcodeproj/project.pbxproj +++ b/Examples/ORSSerialPortDemo/Swift/ORSSerialPortDemo.xcodeproj/project.pbxproj @@ -116,7 +116,8 @@ 9DFD06101A043BA400CE0294 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0610; + LastSwiftUpdateCheck = 0700; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Open Reel Software"; TargetAttributes = { 9DFD06171A043BA400CE0294 = { @@ -189,6 +190,7 @@ CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -255,6 +257,7 @@ INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Sources/ORSSerialPortDemo-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -270,6 +273,7 @@ INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Sources/ORSSerialPortDemo-Bridging-Header.h"; }; diff --git a/Examples/ORSSerialPortDemo/Swift/Resources/Info.plist b/Examples/ORSSerialPortDemo/Swift/Resources/Info.plist index 6d57c4c1..bbc0ee38 100644 --- a/Examples/ORSSerialPortDemo/Swift/Resources/Info.plist +++ b/Examples/ORSSerialPortDemo/Swift/Resources/Info.plist @@ -9,7 +9,7 @@ CFBundleIconFile CFBundleIdentifier - com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Examples/PacketParsingDemo/Objective-C/PacketParsingDemo.xcodeproj/project.pbxproj b/Examples/PacketParsingDemo/Objective-C/PacketParsingDemo.xcodeproj/project.pbxproj index 6df9932e..50fce5b3 100644 --- a/Examples/PacketParsingDemo/Objective-C/PacketParsingDemo.xcodeproj/project.pbxproj +++ b/Examples/PacketParsingDemo/Objective-C/PacketParsingDemo.xcodeproj/project.pbxproj @@ -178,7 +178,7 @@ 9D3947EA1B792B1D0066DC1B /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0640; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Open Reel Software"; TargetAttributes = { 9D3947F11B792B1D0066DC1B = { @@ -294,6 +294,7 @@ COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -359,6 +360,7 @@ COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -370,6 +372,7 @@ COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; diff --git a/Examples/PacketParsingDemo/Objective-C/Resources/Info.plist b/Examples/PacketParsingDemo/Objective-C/Resources/Info.plist index ff83c78c..ea5fbb59 100644 --- a/Examples/PacketParsingDemo/Objective-C/Resources/Info.plist +++ b/Examples/PacketParsingDemo/Objective-C/Resources/Info.plist @@ -9,7 +9,7 @@ CFBundleIconFile CFBundleIdentifier - com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Examples/PacketParsingDemo/Swift/PacketParsingDemo.xcodeproj/project.pbxproj b/Examples/PacketParsingDemo/Swift/PacketParsingDemo.xcodeproj/project.pbxproj index efdd5104..10e97c6c 100644 --- a/Examples/PacketParsingDemo/Swift/PacketParsingDemo.xcodeproj/project.pbxproj +++ b/Examples/PacketParsingDemo/Swift/PacketParsingDemo.xcodeproj/project.pbxproj @@ -160,7 +160,8 @@ 9DEDA8151B793B64009F4617 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0640; + LastSwiftUpdateCheck = 0700; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Open Reel Software"; TargetAttributes = { 9DEDA81C1B793B64009F4617 = { @@ -275,6 +276,7 @@ COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -341,6 +343,7 @@ COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -352,6 +355,7 @@ COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; diff --git a/Examples/PacketParsingDemo/Swift/Resources/Info.plist b/Examples/PacketParsingDemo/Swift/Resources/Info.plist index ff83c78c..ea5fbb59 100644 --- a/Examples/PacketParsingDemo/Swift/Resources/Info.plist +++ b/Examples/PacketParsingDemo/Swift/Resources/Info.plist @@ -9,7 +9,7 @@ CFBundleIconFile CFBundleIdentifier - com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Examples/RequestResponseDemo/Swift/RequestResponseDemo.xcodeproj/project.pbxproj b/Examples/RequestResponseDemo/Swift/RequestResponseDemo.xcodeproj/project.pbxproj index 4ee4286c..03643657 100644 --- a/Examples/RequestResponseDemo/Swift/RequestResponseDemo.xcodeproj/project.pbxproj +++ b/Examples/RequestResponseDemo/Swift/RequestResponseDemo.xcodeproj/project.pbxproj @@ -25,6 +25,13 @@ remoteGlobalIDString = 9DCA89121A2BB106009285EB; remoteInfo = ORSSerial; }; + 9DFF14901B94E5A9004B42B3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9D0F6B6F1AB5040E006BF3F0 /* ORSSerialPort.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 9D7472131B6D7767002D8B10; + remoteInfo = "ORSSerialPort Tests"; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -116,6 +123,7 @@ isa = PBXGroup; children = ( 9D0F6B741AB5040E006BF3F0 /* ORSSerial.framework */, + 9DFF14911B94E5A9004B42B3 /* ORSSerialPort Tests.xctest */, ); name = Products; sourceTree = ""; @@ -147,7 +155,8 @@ 9D0F6B311AB502F7006BF3F0 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0620; + LastSwiftUpdateCheck = 0700; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Open Reel Software"; TargetAttributes = { 9D0F6B381AB502F7006BF3F0 = { @@ -187,6 +196,13 @@ remoteRef = 9D0F6B731AB5040E006BF3F0 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 9DFF14911B94E5A9004B42B3 /* ORSSerialPort Tests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = "ORSSerialPort Tests.xctest"; + remoteRef = 9DFF14901B94E5A9004B42B3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ @@ -236,6 +252,7 @@ CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -300,6 +317,7 @@ COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -311,6 +329,7 @@ COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; diff --git a/Examples/RequestResponseDemo/Swift/Resources/Info.plist b/Examples/RequestResponseDemo/Swift/Resources/Info.plist index ff83c78c..ea5fbb59 100644 --- a/Examples/RequestResponseDemo/Swift/Resources/Info.plist +++ b/Examples/RequestResponseDemo/Swift/Resources/Info.plist @@ -9,7 +9,7 @@ CFBundleIconFile CFBundleIdentifier - com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcschemes/ORSSerial.xcscheme b/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcschemes/ORSSerial.xcscheme index f2e338c0..2ec9f977 100644 --- a/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcschemes/ORSSerial.xcscheme +++ b/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcschemes/ORSSerial.xcscheme @@ -23,10 +23,10 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -48,15 +48,18 @@ ReferencedContainer = "container:ORSSerialPort.xcodeproj"> + + Date: Mon, 31 Aug 2015 13:46:16 -0600 Subject: [PATCH 32/55] Issue #60: Converted Swift ORSSerialPortDemo project to Swift 2.0. --- .../Swift/ORSSerialPortDemo.xcodeproj/project.pbxproj | 1 + .../Swift/Sources/SerialPortDemoController.swift | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Examples/ORSSerialPortDemo/Swift/ORSSerialPortDemo.xcodeproj/project.pbxproj b/Examples/ORSSerialPortDemo/Swift/ORSSerialPortDemo.xcodeproj/project.pbxproj index f65e3368..49c3b823 100644 --- a/Examples/ORSSerialPortDemo/Swift/ORSSerialPortDemo.xcodeproj/project.pbxproj +++ b/Examples/ORSSerialPortDemo/Swift/ORSSerialPortDemo.xcodeproj/project.pbxproj @@ -116,6 +116,7 @@ 9DFD06101A043BA400CE0294 /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftMigration = 0700; LastSwiftUpdateCheck = 0700; LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Open Reel Software"; diff --git a/Examples/ORSSerialPortDemo/Swift/Sources/SerialPortDemoController.swift b/Examples/ORSSerialPortDemo/Swift/Sources/SerialPortDemoController.swift index 924b2240..fc0905cc 100644 --- a/Examples/ORSSerialPortDemo/Swift/Sources/SerialPortDemoController.swift +++ b/Examples/ORSSerialPortDemo/Swift/Sources/SerialPortDemoController.swift @@ -69,7 +69,7 @@ class SerialPortDemoController: NSObject, ORSSerialPortDelegate, NSUserNotificat // MARK: - Actions - @IBAction func send(AnyObject) { + @IBAction func send(_: AnyObject) { var string = self.sendTextField.stringValue if self.shouldAddLineEnding && !string.hasSuffix("\n") { string += self.lineEndingString @@ -113,7 +113,7 @@ class SerialPortDemoController: NSObject, ORSSerialPortDelegate, NSUserNotificat } func serialPort(serialPort: ORSSerialPort, didEncounterError error: NSError) { - println("SerialPort \(serialPort) encountered an error: \(error)") + print("SerialPort \(serialPort) encountered an error: \(error)") } // MARK: - NSUserNotifcationCenterDelegate @@ -134,7 +134,7 @@ class SerialPortDemoController: NSObject, ORSSerialPortDelegate, NSUserNotificat func serialPortsWereConnected(notification: NSNotification) { if let userInfo = notification.userInfo { let connectedPorts = userInfo[ORSConnectedSerialPortsKey] as! [ORSSerialPort] - println("Ports were connected: \(connectedPorts)") + print("Ports were connected: \(connectedPorts)") self.postUserNotificationForConnectedPorts(connectedPorts) } } @@ -142,7 +142,7 @@ class SerialPortDemoController: NSObject, ORSSerialPortDelegate, NSUserNotificat func serialPortsWereDisconnected(notification: NSNotification) { if let userInfo = notification.userInfo { let disconnectedPorts: [ORSSerialPort] = userInfo[ORSDisconnectedSerialPortsKey] as! [ORSSerialPort] - println("Ports were disconnected: \(disconnectedPorts)") + print("Ports were disconnected: \(disconnectedPorts)") self.postUserNotificationForDisconnectedPorts(disconnectedPorts) } } From a4ed2fa28c57a3488ed967690bfd94d1b3c3e51a Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 31 Aug 2015 13:47:23 -0600 Subject: [PATCH 33/55] Issue #60: Converted Swift PacketParsingDemo project to Swift 2.0. --- .../Swift/PacketParsingDemo.xcodeproj/project.pbxproj | 1 + .../Swift/Sources/SerialCommunicator.swift | 4 ++-- Framework Project/Info.plist | 2 +- Framework Project/ORSSerialPort Tests/Info.plist | 2 +- .../ORSSerialPort.xcodeproj/project.pbxproj | 9 ++++++++- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Examples/PacketParsingDemo/Swift/PacketParsingDemo.xcodeproj/project.pbxproj b/Examples/PacketParsingDemo/Swift/PacketParsingDemo.xcodeproj/project.pbxproj index 10e97c6c..81b62380 100644 --- a/Examples/PacketParsingDemo/Swift/PacketParsingDemo.xcodeproj/project.pbxproj +++ b/Examples/PacketParsingDemo/Swift/PacketParsingDemo.xcodeproj/project.pbxproj @@ -160,6 +160,7 @@ 9DEDA8151B793B64009F4617 /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftMigration = 0700; LastSwiftUpdateCheck = 0700; LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Open Reel Software"; diff --git a/Examples/PacketParsingDemo/Swift/Sources/SerialCommunicator.swift b/Examples/PacketParsingDemo/Swift/Sources/SerialCommunicator.swift index dcd8049b..bd5dbf2e 100644 --- a/Examples/PacketParsingDemo/Swift/Sources/SerialCommunicator.swift +++ b/Examples/PacketParsingDemo/Swift/Sources/SerialCommunicator.swift @@ -22,7 +22,7 @@ class SerialCommunicator: NSObject, ORSSerialPortDelegate { } func serialPort(serialPort: ORSSerialPort, didEncounterError error: NSError) { - println("Serial port \(serialPort) encountered an error: \(error)") + print("Serial port \(serialPort) encountered an error: \(error)") } func serialPortWasOpened(serialPort: ORSSerialPort) { @@ -33,7 +33,7 @@ class SerialCommunicator: NSObject, ORSSerialPortDelegate { func serialPort(serialPort: ORSSerialPort, didReceivePacket packetData: NSData, matchingDescriptor descriptor: ORSSerialPacketDescriptor) { if let dataAsString = NSString(data: packetData, encoding: NSASCIIStringEncoding) { let valueString = dataAsString.substringWithRange(NSRange(location: 4, length: dataAsString.length-5)) - self.sliderPosition = valueString.toInt()! + self.sliderPosition = Int(valueString)! } } diff --git a/Framework Project/Info.plist b/Framework Project/Info.plist index f614d3a2..bcd60914 100644 --- a/Framework Project/Info.plist +++ b/Framework Project/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Framework Project/ORSSerialPort Tests/Info.plist b/Framework Project/ORSSerialPort Tests/Info.plist index be2cb8f3..ba72822e 100644 --- a/Framework Project/ORSSerialPort Tests/Info.plist +++ b/Framework Project/ORSSerialPort Tests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj b/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj index 9f3ea7dd..f8637ba8 100644 --- a/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj +++ b/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj @@ -206,7 +206,8 @@ 9DCA89091A2BB106009285EB /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0640; + LastSwiftMigration = 0700; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Open Reel Software"; TargetAttributes = { 9D7472121B6D7767002D8B10 = { @@ -301,6 +302,7 @@ INFOPLIST_FILE = "ORSSerialPort Tests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.10; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -318,6 +320,7 @@ INFOPLIST_FILE = "ORSSerialPort Tests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.10; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -342,6 +345,7 @@ COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -418,6 +422,7 @@ INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; @@ -436,6 +441,7 @@ INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; @@ -451,6 +457,7 @@ 9D74721D1B6D7767002D8B10 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 9DCA890C1A2BB106009285EB /* Build configuration list for PBXProject "ORSSerialPort" */ = { isa = XCConfigurationList; From 1bcb151e89746504c096b55b696c9d8d98e580c4 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 31 Aug 2015 13:58:55 -0600 Subject: [PATCH 34/55] Issue #60: Converted Swift RequestResponseDemo project to Swift 2.0. --- .../project.pbxproj | 1 + .../Swift/Sources/MainViewController.swift | 4 ++-- .../Swift/Sources/SerialBoardController.swift | 18 +++++++++--------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Examples/RequestResponseDemo/Swift/RequestResponseDemo.xcodeproj/project.pbxproj b/Examples/RequestResponseDemo/Swift/RequestResponseDemo.xcodeproj/project.pbxproj index 03643657..0634eb6d 100644 --- a/Examples/RequestResponseDemo/Swift/RequestResponseDemo.xcodeproj/project.pbxproj +++ b/Examples/RequestResponseDemo/Swift/RequestResponseDemo.xcodeproj/project.pbxproj @@ -155,6 +155,7 @@ 9D0F6B311AB502F7006BF3F0 /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftMigration = 0700; LastSwiftUpdateCheck = 0700; LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Open Reel Software"; diff --git a/Examples/RequestResponseDemo/Swift/Sources/MainViewController.swift b/Examples/RequestResponseDemo/Swift/Sources/MainViewController.swift index 191e7fb1..81d1e062 100644 --- a/Examples/RequestResponseDemo/Swift/Sources/MainViewController.swift +++ b/Examples/RequestResponseDemo/Swift/Sources/MainViewController.swift @@ -34,13 +34,13 @@ class MainViewController: NSViewController { let boardController = SerialBoardController() override func viewDidLoad() { - self.boardController.addObserver(self, forKeyPath: "temperature", options: NSKeyValueObservingOptions.allZeros, context: MainViewControllerKVOContext) + self.boardController.addObserver(self, forKeyPath: "temperature", options: NSKeyValueObservingOptions(), context: MainViewControllerKVOContext) } // MARK: KVO let MainViewControllerKVOContext = UnsafeMutablePointer<()>() - override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer) { + override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer) { if context != MainViewControllerKVOContext { super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context) } diff --git a/Examples/RequestResponseDemo/Swift/Sources/SerialBoardController.swift b/Examples/RequestResponseDemo/Swift/Sources/SerialBoardController.swift index 406adddf..c0454e73 100644 --- a/Examples/RequestResponseDemo/Swift/Sources/SerialBoardController.swift +++ b/Examples/RequestResponseDemo/Swift/Sources/SerialBoardController.swift @@ -49,8 +49,8 @@ class SerialBoardController: NSObject, ORSSerialPortDelegate { let command = "$TEMP?;".dataUsingEncoding(NSASCIIStringEncoding)! let request = ORSSerialRequest(dataToSend: command, userInfo: SerialBoardRequestType.ReadTemperature.rawValue, - timeoutInterval: kTimeoutDuration) { (data) -> Bool in - return self.temperatureFromResponsePacket(data!) != nil + timeoutInterval: 0.5) { (data) -> ObjCBool in + return ObjCBool(self.temperatureFromResponsePacket(data!) != nil) } self.serialPort?.sendRequest(request) } @@ -59,8 +59,8 @@ class SerialBoardController: NSObject, ORSSerialPortDelegate { let command = "$LED?;".dataUsingEncoding(NSASCIIStringEncoding)! let request = ORSSerialRequest(dataToSend: command, userInfo: SerialBoardRequestType.ReadLED.rawValue, - timeoutInterval: kTimeoutDuration) { (data) -> Bool in - return self.LEDStateFromResponsePacket(data!) != nil + timeoutInterval: kTimeoutDuration) { (data) -> ObjCBool in + return ObjCBool(self.LEDStateFromResponsePacket(data!) != nil) } self.serialPort?.sendRequest(request) } @@ -70,8 +70,8 @@ class SerialBoardController: NSObject, ORSSerialPortDelegate { let command = commandString.dataUsingEncoding(NSASCIIStringEncoding)! let request = ORSSerialRequest(dataToSend: command, userInfo: SerialBoardRequestType.SetLED.rawValue, - timeoutInterval: kTimeoutDuration) { (data) -> Bool in - return self.LEDStateFromResponsePacket(data!) != nil + timeoutInterval: kTimeoutDuration) { (data) -> ObjCBool in + return ObjCBool(self.LEDStateFromResponsePacket(data!) != nil) } self.serialPort?.sendRequest(request) } @@ -85,7 +85,7 @@ class SerialBoardController: NSObject, ORSSerialPortDelegate { } let temperatureString = dataAsString.substringWithRange(NSRange(location: 5, length: dataAsString.length-6)) - return temperatureString.toInt() + return Int(temperatureString) } private func LEDStateFromResponsePacket(data: NSData) -> Bool? { @@ -95,7 +95,7 @@ class SerialBoardController: NSObject, ORSSerialPortDelegate { } let LEDStateString = dataAsString.substringWithRange(NSRange(location: 4, length: dataAsString.length-5)) - return LEDStateString.toInt()! != 0 + return Int(LEDStateString)! != 0 } // MARK: - ORSSerialPortDelegate @@ -105,7 +105,7 @@ class SerialBoardController: NSObject, ORSSerialPortDelegate { } func serialPort(serialPort: ORSSerialPort, didEncounterError error: NSError) { - println("Serial port \(serialPort) encountered an error: \(error)") + print("Serial port \(serialPort) encountered an error: \(error)") } func serialPort(serialPort: ORSSerialPort, didReceiveResponse responseData: NSData, toRequest request: ORSSerialRequest) { From ce5f603e7e4ca2a951e08cbf946b370bc6cdbd1b Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 31 Aug 2015 14:02:57 -0600 Subject: [PATCH 35/55] Fixed warning due to failure to override -init in ORSSerialPacketDescriptor. --- Source/ORSSerialPacketDescriptor.m | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/ORSSerialPacketDescriptor.m b/Source/ORSSerialPacketDescriptor.m index 74a10557..acc14520 100644 --- a/Source/ORSSerialPacketDescriptor.m +++ b/Source/ORSSerialPacketDescriptor.m @@ -34,6 +34,12 @@ @interface ORSSerialPacketDescriptor () @implementation ORSSerialPacketDescriptor +- (instancetype)init NS_UNAVAILABLE +{ + [NSException raise:NSInternalInconsistencyException format:@"You must initialize %@ with its designated initializers, or one of its convenience initializers.", NSStringFromClass([self class])]; + return nil; +} + - (instancetype)initWithUserInfo:(id)userInfo responseEvaluator:(ORSSerialPacketEvaluator)responseEvaluator { self = [super init]; From b05d831986b67bfe0de560c38fe58e7e0e371f0e Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 31 Aug 2015 14:08:23 -0600 Subject: [PATCH 36/55] Undid accidental changes to Framework project. --- Framework Project/Info.plist | 2 +- Framework Project/ORSSerialPort Tests/Info.plist | 2 +- .../ORSSerialPort.xcodeproj/project.pbxproj | 9 +-------- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/Framework Project/Info.plist b/Framework Project/Info.plist index bcd60914..f614d3a2 100644 --- a/Framework Project/Info.plist +++ b/Framework Project/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) + com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Framework Project/ORSSerialPort Tests/Info.plist b/Framework Project/ORSSerialPort Tests/Info.plist index ba72822e..be2cb8f3 100644 --- a/Framework Project/ORSSerialPort Tests/Info.plist +++ b/Framework Project/ORSSerialPort Tests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) + com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj b/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj index f8637ba8..9f3ea7dd 100644 --- a/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj +++ b/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj @@ -206,8 +206,7 @@ 9DCA89091A2BB106009285EB /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftMigration = 0700; - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0640; ORGANIZATIONNAME = "Open Reel Software"; TargetAttributes = { 9D7472121B6D7767002D8B10 = { @@ -302,7 +301,6 @@ INFOPLIST_FILE = "ORSSerialPort Tests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.10; - PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -320,7 +318,6 @@ INFOPLIST_FILE = "ORSSerialPort Tests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.10; - PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -345,7 +342,6 @@ COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -422,7 +418,6 @@ INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; @@ -441,7 +436,6 @@ INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; @@ -457,7 +451,6 @@ 9D74721D1B6D7767002D8B10 /* Release */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; }; 9DCA890C1A2BB106009285EB /* Build configuration list for PBXProject "ORSSerialPort" */ = { isa = XCConfigurationList; From 806d35d62e94f6eb50b5e6f502033f691f9edd22 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Sat, 5 Sep 2015 10:57:03 -0600 Subject: [PATCH 37/55] Added additional test for parsing multiple packets received in a single callback (already passed). --- .../ORSSerialPacketDescriptor_Tests.m | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m b/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m index 78c4c6ce..45927575 100644 --- a/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m +++ b/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m @@ -210,6 +210,27 @@ - (void)testParsingMultipleSimilarPackets }]; } +- (void)testMultipleIncomingPacketsInASingleReceive +{ + XCTestExpectation *expectation1 = [self expectationWithDescription:@"Multiple packets single receive parsing expectation 1"]; + XCTestExpectation *expectation2 = [self expectationWithDescription:@"Multiple packets single receive parsing expectation 2"]; + NSDictionary *userInfo1 = @{[@"!foo;" dataUsingEncoding:NSASCIIStringEncoding]: expectation1}; + NSDictionary *userInfo2 = @{[@"!bar;" dataUsingEncoding:NSASCIIStringEncoding]: expectation2}; + ORSSerialPacketDescriptor *descriptor1 = [self defaultPacketDescriptorWithUserInfo:userInfo1]; + ORSSerialPacketDescriptor *descriptor2 = [self defaultPacketDescriptorWithUserInfo:userInfo2]; + + [self.port startListeningForPacketsMatchingDescriptor:descriptor1]; + [self.port startListeningForPacketsMatchingDescriptor:descriptor2]; + + [self.port receiveData:[@"!foo;!bar;" dataUsingEncoding:NSASCIIStringEncoding]]; + + [self waitForExpectationsWithTimeout:0.5 handler:^(NSError *error) { + if (error) { + NSLog(@"expectations failed: %@", error); + } + }]; +} + - (void)testParsingNestedPackets { XCTestExpectation *expectation1 = [self expectationWithDescription:@"Nested packets parsing expectation 1"]; From e11d7124f6f85c4240b3cb7e9ea6c581ca012ba1 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Sun, 6 Sep 2015 10:02:33 -0600 Subject: [PATCH 38/55] Issue #75: Avoid checking for response to pending request if none is pending. --- Source/ORSSerialPort.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/ORSSerialPort.m b/Source/ORSSerialPort.m index d8e8b575..a8e2be73 100644 --- a/Source/ORSSerialPort.m +++ b/Source/ORSSerialPort.m @@ -565,6 +565,8 @@ - (void)pendingRequestDidTimeout // Must only be called on requestHandlingQueue - (void)checkResponseToPendingRequestAndContinueIfValidWithReceivedByte:(NSData *)byte { + if (!self.pendingRequest) return; // Nothing to do + ORSSerialPacketDescriptor *packetDescriptor = self.pendingRequest.responseDescriptor; if (!byte) { From 00e53d6a41efd5af05123ec8119b72ff9fb2897b Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Sun, 6 Sep 2015 11:16:28 -0600 Subject: [PATCH 39/55] Issue #75: Faster implementation of prefix/suffix checking in ORSSerialPacketDescriptor. --- Source/ORSSerialPacketDescriptor.m | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/Source/ORSSerialPacketDescriptor.m b/Source/ORSSerialPacketDescriptor.m index acc14520..75cc2f51 100644 --- a/Source/ORSSerialPacketDescriptor.m +++ b/Source/ORSSerialPacketDescriptor.m @@ -54,13 +54,23 @@ - (instancetype)initWithUserInfo:(id)userInfo responseEvaluator:(ORSSerialPacket - (instancetype)initWithPrefix:(NSData *)prefix suffix:(NSData *)suffix userInfo:(id)userInfo { self = [self initWithUserInfo:userInfo responseEvaluator:^BOOL(NSData *data) { - NSRange fullRange = NSMakeRange(0, [data length]); - NSRange prefixRange = NSMakeRange(0, 0); - if (prefix) prefixRange = [data rangeOfData:prefix options:NSDataSearchAnchored range:fullRange]; - NSRange suffixRange = NSMakeRange([data length]-1, 0); - if (suffix) suffixRange = [data rangeOfData:suffix options:NSDataSearchAnchored | NSDataSearchBackwards range:fullRange]; + if (prefix == nil && suffix == nil) { return NO; } + if (prefix && [prefix length] > [data length]) { return NO; } + if (suffix && [suffix length] > [data length]) { return NO; } - return prefixRange.location != NSNotFound && suffixRange.location != NSNotFound; + for (NSUInteger i=0; i<[prefix length]; i++) { + uint8_t prefixByte = ((uint8_t *)[prefix bytes])[i]; + uint8_t dataByte = ((uint8_t *)[data bytes])[i]; + if (prefixByte != dataByte) { return NO; } + } + + for (NSUInteger i=0; i<[suffix length]; i++) { + uint8_t suffixByte = ((uint8_t *)[suffix bytes])[([suffix length]-1-i)]; + uint8_t dataByte = ((uint8_t *)[data bytes])[([data length]-1-i)]; + if (suffixByte != dataByte) { return NO; } + } + + return YES; }]; if (self) { _prefix = prefix; From 183e91c2ecb26e1b751d78ea0b7ae9d0d55805f2 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Sun, 6 Sep 2015 12:07:35 -0600 Subject: [PATCH 40/55] Issue #75: Added test to measure performance of packet parsing with multiple installed packet descriptors. Currently at 0.974s. --- .../ORSSerialPacketDescriptor_Tests.m | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m b/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m index 45927575..a9e8cc5a 100644 --- a/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m +++ b/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m @@ -119,7 +119,7 @@ - (void)testMissingSuffix XCTAssertFalse([descriptor dataIsValidPacket:ORSTStringToData_(@"foo")], @"Invalid packet not rejected by descriptor."); [self.port startListeningForPacketsMatchingDescriptor:descriptor]; - + NSData *buffer = [@"!foobar" dataUsingEncoding:NSASCIIStringEncoding]; [self.port receiveData:buffer]; @@ -287,6 +287,41 @@ - (void)testPacketDescriptorsPropertyRemove }]; } +#pragma mark - Performance + +- (void)testPerformanceWithMultipleInstalledDescriptors +{ + [self measureMetrics:@[XCTPerformanceMetric_WallClockTime] automaticallyStartMeasuring:YES forBlock:^{ + XCTestExpectation *expectation1 = [self expectationWithDescription:@"Multiple packets type 1 parsing expectation"]; + + NSDictionary *userInfo1 = @{[@"!foo;" dataUsingEncoding:NSASCIIStringEncoding]: expectation1}; + ORSSerialPacketDescriptor *descriptor1 = [self defaultPacketDescriptorWithUserInfo:userInfo1]; + ORSSerialPacketDescriptor *descriptor2 = [[ORSSerialPacketDescriptor alloc] initWithPrefix:[@"$ba" dataUsingEncoding:NSASCIIStringEncoding] + suffix:[@";" dataUsingEncoding:NSASCIIStringEncoding] + userInfo:nil]; + + [self.port startListeningForPacketsMatchingDescriptor:descriptor1]; + [self.port startListeningForPacketsMatchingDescriptor:descriptor2]; + + for (NSUInteger i=0; i<320; i++) { + [self.port receiveData:[@"$bar" dataUsingEncoding:NSASCIIStringEncoding]]; + [self.port receiveData:[@";" dataUsingEncoding:NSASCIIStringEncoding]]; + } + [self.port receiveData:[@"!foo;" dataUsingEncoding:NSASCIIStringEncoding]]; + + [self waitForExpectationsWithTimeout:100 handler:^(NSError *error) { + if (error) { + NSLog(@"expectations failed: %@", error); + } + + [self.port stopListeningForPacketsMatchingDescriptor:descriptor1]; + [self.port stopListeningForPacketsMatchingDescriptor:descriptor2]; + }]; + + }]; + +} + #pragma mark - Utilties - (ORSSerialPacketDescriptor *)defaultPacketDescriptorWithUserInfo:(id)userInfo From 80872014ab2a4cc9d8f6ebb6f886abbb2a33a46b Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Sun, 6 Sep 2015 12:22:31 -0600 Subject: [PATCH 41/55] Issue #75: Added required maximumPacketLength property to ORSSerialPacketDescriptor. --- .../ORSSerialPacketDescriptor_Tests.m | 29 ++++++++++--- Source/ORSSerialPacketDescriptor.h | 42 ++++++++++++------- Source/ORSSerialPacketDescriptor.m | 28 ++++++++----- 3 files changed, 69 insertions(+), 30 deletions(-) diff --git a/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m b/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m index a9e8cc5a..654abc43 100644 --- a/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m +++ b/Framework Project/ORSSerialPort Tests/ORSSerialPacketDescriptor_Tests.m @@ -46,7 +46,10 @@ - (void)testPrefixSuffix { NSData *prefix = [@"!" dataUsingEncoding:NSASCIIStringEncoding]; NSData *suffix = [@";" dataUsingEncoding:NSASCIIStringEncoding]; - ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithPrefix:prefix suffix:suffix userInfo:nil]; + ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithPrefix:prefix + suffix:suffix + maximumPacketLength:5 + userInfo:nil]; XCTAssertNotNil(descriptor, @"Creating packet descriptor with prefix and suffix failed."); XCTAssertEqualObjects(descriptor.prefix, prefix, @"Desriptor prefix property incorrect."); XCTAssertEqualObjects(descriptor.suffix, suffix, @"Desriptor suffix property incorrect."); @@ -62,7 +65,10 @@ - (void)testPrefixSuffix - (void)testPrefixSuffixStrings { - ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithPrefixString:@"!" suffixString:@";" userInfo:nil]; + ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithPrefixString:@"!" + suffixString:@";" + maximumPacketLength:5 + userInfo:nil]; XCTAssertNotNil(descriptor, @"Creating packet descriptor with prefix and suffix failed."); XCTAssertEqualObjects(descriptor.prefix, [@"!" dataUsingEncoding:NSASCIIStringEncoding], @"Desriptor prefix property incorrect."); XCTAssertEqualObjects(descriptor.suffix, [@";" dataUsingEncoding:NSASCIIStringEncoding], @"Desriptor suffix property incorrect."); @@ -81,7 +87,10 @@ - (void)testMissingPrefix XCTestExpectation *expectation = [self expectationWithDescription:@"Missing suffix packet parsing expectation."]; NSDictionary *userInfo = @{[@";" dataUsingEncoding:NSASCIIStringEncoding] : expectation}; NSData *suffix = [@";" dataUsingEncoding:NSASCIIStringEncoding]; - ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithPrefix:nil suffix:suffix userInfo:userInfo]; + ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithPrefix:nil + suffix:suffix + maximumPacketLength:5 + userInfo:userInfo]; XCTAssertNotNil(descriptor, @"Creating packet descriptor with prefix and suffix failed."); XCTAssertEqualObjects(descriptor.suffix, suffix, @"Desriptor suffix property incorrect."); XCTAssertNil(descriptor.prefix, @"Desriptor prefix property incorrect."); @@ -108,7 +117,10 @@ - (void)testMissingSuffix XCTestExpectation *expectation = [self expectationWithDescription:@"Missing suffix packet parsing expectation."]; NSDictionary *userInfo = @{[@"!" dataUsingEncoding:NSASCIIStringEncoding] : expectation}; NSData *prefix = [@"!" dataUsingEncoding:NSASCIIStringEncoding]; - ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithPrefix:prefix suffix:nil userInfo:userInfo]; + ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithPrefix:prefix + suffix:nil + maximumPacketLength:5 + userInfo:userInfo]; XCTAssertNotNil(descriptor, @"Creating packet descriptor with prefix and suffix failed."); XCTAssertEqualObjects(descriptor.prefix, prefix, @"Desriptor prefix property incorrect."); XCTAssertNil(descriptor.suffix, @"Desriptor suffix property incorrect."); @@ -133,7 +145,9 @@ - (void)testMissingSuffix - (void)testRegex { NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^!.+;$" options:0 error:NULL]; - ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithRegularExpression:regex userInfo:nil]; + ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithRegularExpression:regex + maximumPacketLength:5 + userInfo:nil]; XCTAssertNotNil(descriptor, @"Creating packet descriptor with regular expression failed."); XCTAssertEqualObjects(descriptor.regularExpression, regex, @"Descriptor regex property incorrect."); @@ -173,6 +187,7 @@ - (void)testParsingMultipleDifferentPackets ORSSerialPacketDescriptor *descriptor1 = [self defaultPacketDescriptorWithUserInfo:userInfo1]; ORSSerialPacketDescriptor *descriptor2 = [[ORSSerialPacketDescriptor alloc] initWithPrefix:[@"$" dataUsingEncoding:NSASCIIStringEncoding] suffix:[@";" dataUsingEncoding:NSASCIIStringEncoding] + maximumPacketLength:5 userInfo:userInfo2]; [self.port startListeningForPacketsMatchingDescriptor:descriptor1]; [self.port startListeningForPacketsMatchingDescriptor:descriptor2]; @@ -240,6 +255,7 @@ - (void)testParsingNestedPackets ORSSerialPacketDescriptor *descriptor1 = [self defaultPacketDescriptorWithUserInfo:userInfo1]; ORSSerialPacketDescriptor *descriptor2 = [[ORSSerialPacketDescriptor alloc] initWithPrefix:[@"$" dataUsingEncoding:NSASCIIStringEncoding] suffix:[@"%" dataUsingEncoding:NSASCIIStringEncoding] + maximumPacketLength:5 userInfo:userInfo2]; [self.port startListeningForPacketsMatchingDescriptor:descriptor1]; [self.port startListeningForPacketsMatchingDescriptor:descriptor2]; @@ -298,6 +314,7 @@ - (void)testPerformanceWithMultipleInstalledDescriptors ORSSerialPacketDescriptor *descriptor1 = [self defaultPacketDescriptorWithUserInfo:userInfo1]; ORSSerialPacketDescriptor *descriptor2 = [[ORSSerialPacketDescriptor alloc] initWithPrefix:[@"$ba" dataUsingEncoding:NSASCIIStringEncoding] suffix:[@";" dataUsingEncoding:NSASCIIStringEncoding] + maximumPacketLength:5 userInfo:nil]; [self.port startListeningForPacketsMatchingDescriptor:descriptor1]; @@ -328,7 +345,7 @@ - (ORSSerialPacketDescriptor *)defaultPacketDescriptorWithUserInfo:(id)userInfo { NSData *prefix = [@"!" dataUsingEncoding:NSASCIIStringEncoding]; NSData *suffix = [@";" dataUsingEncoding:NSASCIIStringEncoding]; - return [[ORSSerialPacketDescriptor alloc] initWithPrefix:prefix suffix:suffix userInfo:userInfo]; + return [[ORSSerialPacketDescriptor alloc] initWithPrefix:prefix suffix:suffix maximumPacketLength:20 userInfo:userInfo]; } #pragma mark - ORSSerialPortDelegate diff --git a/Source/ORSSerialPacketDescriptor.h b/Source/ORSSerialPacketDescriptor.h index ff4d885d..f654de9b 100644 --- a/Source/ORSSerialPacketDescriptor.h +++ b/Source/ORSSerialPacketDescriptor.h @@ -38,7 +38,7 @@ NS_ASSUME_NONNULL_BEGIN /** - * Block that parses input data and returns a packet extracted from that data, or nil + * Block that parses input data and returns YES if inputData consists of a valid packet, or NO * if inputData doesn't contain a valid packet. */ typedef BOOL(^ORSSerialPacketEvaluator)(NSData * __nullable inputData); @@ -59,7 +59,7 @@ typedef BOOL(^ORSSerialPacketEvaluator)(NSData * __nullable inputData); * For request/response protocols, see ORSSerialRequest, etc. * * For more information about ORSSerialPort's packet descriptor API, see the ORSSerialPort Packet Parsing - * Programming Guide at + * Programming Guide at */ @interface ORSSerialPacketDescriptor : NSObject @@ -72,23 +72,25 @@ typedef BOOL(^ORSSerialPacketEvaluator)(NSData * __nullable inputData); * or regular expression, a response evaulator block containing arbitrary validation code can be * provided instead. * + * @param maxPacketLength The maximum length of a valid packet. This value _must_ be correctly specified. * @param userInfo An arbitrary userInfo object. * @param responseEvaluator A block used to evaluate whether received data constitutes a valid packet. * * @return An initizliaized ORSSerialPacketDesciptor instance. * - * @see -initWithPrefix:suffix:userInfo: - * @see -initWithPrefixString:suffixString:userInfo: - * @see -initWithRegularExpression:userInfo: + * @see -initWithPrefix:suffix:maximumPacketLength:userInfo: + * @see -initWithPrefixString:suffixString:maximumPacketLength:userInfo: + * @see -initWithRegularExpression:maximumPacketLength:userInfo: */ -- (instancetype)initWithUserInfo:(nullable id)userInfo - responseEvaluator:(ORSSerialPacketEvaluator)responseEvaluator NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithMaximumPacketLength:(NSUInteger)maxPacketLength + userInfo:(nullable id)userInfo + responseEvaluator:(ORSSerialPacketEvaluator)responseEvaluator NS_DESIGNATED_INITIALIZER; /** * Creates an initializes an ORSSerialPacketDescriptor instance using a prefix and/or suffix. * - * If the packet format uses printable ASCII characters, -initWithPrefixString:suffixString:userInfo: - * may be more suitable. + * If the packet format uses printable ASCII characters, + * -initWithPrefixString:suffixString:maximumPacketLength:userInfo: may be more suitable. * * @note Either prefix or suffix may be nil, but not both. If the suffix is nil, * packets will be considered to consist solely of prefix. If either value is nil, packets @@ -96,6 +98,7 @@ typedef BOOL(^ORSSerialPacketEvaluator)(NSData * __nullable inputData); * * @param prefix An NSData instance containing a fixed packet prefix. May be nil. * @param suffix An NSData instance containing a fixed packet suffix. May be nil. + * @param maxPacketLength The maximum length of a valid packet. This value _must_ be correctly specified. * @param userInfo An arbitrary userInfo object. May be nil. * * @return An initizliaized ORSSerialPacketDesciptor instance. @@ -104,29 +107,32 @@ typedef BOOL(^ORSSerialPacketEvaluator)(NSData * __nullable inputData); */ - (instancetype)initWithPrefix:(nullable NSData *)prefix suffix:(nullable NSData *)suffix + maximumPacketLength:(NSUInteger)maxPacketLength userInfo:(nullable id)userInfo; /** * Creates an initializes an ORSSerialPacketDescriptor instance using a prefix string and/or suffix string. * * This method assumes that prefixString and suffixString are ASCII or UTF8 strings. - * If the packet format does not use printable ASCII characters, -initWithPrefix:suffix:userInfo: + * If the packet format does not use printable ASCII characters, -initWithPrefix:suffix:maximumPacketLength:userInfo: * may be more suitable. * - * @note Either prefixString or suffixString may be nil, but not both. If the suffix is nil, + * @note Either prefixString or suffixString may be nil, but not both. If the suffix is nil, * packets will be considered to consist solely of prefix. If either value is nil, packets * will be considred to consist soley of the the non-nil value. * * @param prefixString A fixed packet prefix string. May be nil. * @param suffixString A fixed packet suffix string. May be nil. + * @param maxPacketLength The maximum length of a valid packet. This value _must_ be correctly specified. * @param userInfo An arbitrary userInfo object. May be nil. * * @return An initizliaized ORSSerialPacketDesciptor instance. * - * @see -initWithPrefix:suffix:userInfo: + * @see -initWithPrefix:suffix:maximumPacketLength:userInfo: */ - (instancetype)initWithPrefixString:(nullable NSString *)prefixString suffixString:(nullable NSString *)suffixString + maximumPacketLength:(NSUInteger)maxPacketLength userInfo:(nullable id)userInfo; /** @@ -136,14 +142,17 @@ typedef BOOL(^ORSSerialPacketEvaluator)(NSData * __nullable inputData); * regular expression. For this reason, the regex should match as conservatively (smallest match) as possible. * * Packets described by descriptors created using this method are assumed to be ASCII or UTF8 strings. - * If your packets are not naturally represented as strings, consider using -initWithUserInfo:responseEvaluator: instead. + * If your packets are not naturally represented as strings, consider using + * -initWithMaximumPacketLength:userInfo:responseEvaluator: instead. * * @param regex An NSRegularExpression instance for which valid packets are a match. + * @param maxPacketLength The maximum length of a valid packet. This value _must_ be correctly specified. * @param userInfo An arbitrary userInfoObject. May be nil. * * @return An initizliaized ORSSerialPacketDesciptor instance. */ - (instancetype)initWithRegularExpression:(NSRegularExpression *)regex + maximumPacketLength:(NSUInteger)maxPacketLength userInfo:(nullable id)userInfo; /** @@ -157,7 +166,7 @@ typedef BOOL(^ORSSerialPacketEvaluator)(NSData * __nullable inputData); - (BOOL)dataIsValidPacket:(nullable NSData *)packetData; /** - * The prefix for packets described by the receiver. Will be nil for packet + * The prefix for packets described by the receiver. Will be nil for packet * descriptors not created using one of the prefix/suffix initializer methods. */ @property (nonatomic, strong, readonly, nullable) NSData *prefix; @@ -174,6 +183,11 @@ typedef BOOL(^ORSSerialPacketEvaluator)(NSData * __nullable inputData); */ @property (nonatomic, strong, readonly, nullable) NSRegularExpression *regularExpression; +/** + * The maximum lenght of a packet described by the receiver. + */ +@property (nonatomic, readonly) NSUInteger maximumPacketLength; + /** * Arbitrary object (e.g. NSDictionary) used to store additional data * about the packet descriptor. diff --git a/Source/ORSSerialPacketDescriptor.m b/Source/ORSSerialPacketDescriptor.m index 75cc2f51..21d779d8 100644 --- a/Source/ORSSerialPacketDescriptor.m +++ b/Source/ORSSerialPacketDescriptor.m @@ -40,10 +40,13 @@ - (instancetype)init NS_UNAVAILABLE return nil; } -- (instancetype)initWithUserInfo:(id)userInfo responseEvaluator:(ORSSerialPacketEvaluator)responseEvaluator +- (instancetype)initWithMaximumPacketLength:(NSUInteger)maxPacketLength + userInfo:(id)userInfo + responseEvaluator:(ORSSerialPacketEvaluator)responseEvaluator { self = [super init]; if (self) { + _maximumPacketLength = maxPacketLength; _userInfo = userInfo; _responseEvaluator = [responseEvaluator ?: ^BOOL(NSData *d){ return [d length] > 0; } copy]; _uuid = [NSUUID UUID]; @@ -51,9 +54,12 @@ - (instancetype)initWithUserInfo:(id)userInfo responseEvaluator:(ORSSerialPacket return self; } -- (instancetype)initWithPrefix:(NSData *)prefix suffix:(NSData *)suffix userInfo:(id)userInfo +- (instancetype)initWithPrefix:(NSData *)prefix + suffix:(NSData *)suffix + maximumPacketLength:(NSUInteger)maxPacketLength + userInfo:(id)userInfo { - self = [self initWithUserInfo:userInfo responseEvaluator:^BOOL(NSData *data) { + self = [self initWithMaximumPacketLength:maxPacketLength userInfo:userInfo responseEvaluator:^BOOL(NSData *data) { if (prefix == nil && suffix == nil) { return NO; } if (prefix && [prefix length] > [data length]) { return NO; } if (suffix && [suffix length] > [data length]) { return NO; } @@ -79,19 +85,21 @@ - (instancetype)initWithPrefix:(NSData *)prefix suffix:(NSData *)suffix userInfo return self; } -- (instancetype)initWithPrefixString:(nullable NSString *)prefixString - suffixString:(nullable NSString *)suffixString - userInfo:(nullable id)userInfo +- (instancetype)initWithPrefixString:(NSString *)prefixString + suffixString:(NSString *)suffixString + maximumPacketLength:(NSUInteger)maxPacketLength + userInfo:(id)userInfo; { NSData *prefixData = [prefixString dataUsingEncoding:NSUTF8StringEncoding]; NSData *suffixData = [suffixString dataUsingEncoding:NSUTF8StringEncoding]; - return [self initWithPrefix:prefixData suffix:suffixData userInfo:userInfo]; + return [self initWithPrefix:prefixData suffix:suffixData maximumPacketLength:maxPacketLength userInfo:userInfo]; } - (instancetype)initWithRegularExpression:(NSRegularExpression *)regex - userInfo:(nullable id)userInfo + maximumPacketLength:(NSUInteger)maxPacketLength + userInfo:(id)userInfo; { - self = [self initWithUserInfo:userInfo responseEvaluator:^BOOL(NSData *data) { + self = [self initWithMaximumPacketLength:maxPacketLength userInfo:userInfo responseEvaluator:^BOOL(NSData *data) { NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; if (!string) return NO; @@ -112,7 +120,7 @@ - (BOOL)isEqual:(id)object - (NSUInteger)hash { return [self.uuid hash]; } -- (BOOL)dataIsValidPacket:(nullable NSData *)packetData +- (BOOL)dataIsValidPacket:(NSData *)packetData { if (!self.responseEvaluator) return YES; return self.responseEvaluator(packetData); From 246cadeee73f65f1d370bf7a8c41a8d839f352bc Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Sun, 6 Sep 2015 12:24:28 -0600 Subject: [PATCH 42/55] Issue #75: Deprecated ORSSerialRequest initializer methods that take a direct response evaluator block now that maximumPacketLength is required for underlying ORSSerialPacketDescriptor. --- Source/ORSSerialRequest.h | 71 ++++++++++++++++++++------------------- Source/ORSSerialRequest.m | 35 ++++++++++--------- 2 files changed, 57 insertions(+), 49 deletions(-) diff --git a/Source/ORSSerialRequest.h b/Source/ORSSerialRequest.h index c8df1002..8684c2ff 100644 --- a/Source/ORSSerialRequest.h +++ b/Source/ORSSerialRequest.h @@ -67,23 +67,6 @@ NS_ASSUME_NONNULL_BEGIN timeoutInterval:(NSTimeInterval)timeout responseDescriptor:(nullable ORSSerialPacketDescriptor *)responseDescriptor; -/** - * Creates and initializes an ORSSerialRequest instance. - * - * @param dataToSend The data to be sent on the serial port. - * @param userInfo An arbitrary userInfo object. - * @param timeout The maximum amount of time in seconds to wait for a response. Pass -1.0 to wait indefinitely. - * @param responseEvaluator A block used to evaluate whether received data constitutes a valid response to the request. - * May be nil. If responseEvaluator is nil, the request is assumed not to require a response, and the next request in the queue will - * be sent immediately. - * - * @return An initialized ORSSerialRequest instance. - */ -+ (instancetype)requestWithDataToSend:(NSData *)dataToSend - userInfo:(nullable id)userInfo - timeoutInterval:(NSTimeInterval)timeout - responseEvaluator:(nullable ORSSerialPacketEvaluator)responseEvaluator; - /** * Initializes an ORSSerialRequest instance. * @@ -101,23 +84,6 @@ NS_ASSUME_NONNULL_BEGIN timeoutInterval:(NSTimeInterval)timeout responseDescriptor:(nullable ORSSerialPacketDescriptor *)responseDescriptor; -/** - * Initializes an ORSSerialRequest instance. - * - * @param dataToSend The data to be sent on the serial port. - * @param userInfo An arbitrary userInfo object. - * @param timeout The maximum amount of time in seconds to wait for a response. Pass -1.0 to wait indefinitely. - * @param responseEvaluator A block used to evaluate whether received data constitutes a valid response to the request. - * May be nil. If responseEvaluator is nil, the request is assumed not to require a response, and the next request in the queue will - * be sent immediately. - * - * @return An initialized ORSSerialRequest instance. - */ -- (instancetype)initWithDataToSend:(NSData *)dataToSend - userInfo:(nullable id)userInfo - timeoutInterval:(NSTimeInterval)timeout - responseEvaluator:(nullable ORSSerialPacketEvaluator)responseEvaluator; - /** * Data to be sent on the serial port when the receiver is sent. */ @@ -152,6 +118,43 @@ NS_ASSUME_NONNULL_BEGIN @interface ORSSerialRequest (Deprecated) +/** + * @deprecated Use +requestWithDataToSend:userInfo:timeoutInterval:responseDescriptor: instead. + * + * Creates and initializes an ORSSerialRequest instance. + * + * @param dataToSend The data to be sent on the serial port. + * @param userInfo An arbitrary userInfo object. + * @param timeout The maximum amount of time in seconds to wait for a response. Pass -1.0 to wait indefinitely. + * @param responseEvaluator A block used to evaluate whether received data constitutes a valid response to the request. + * May be nil. If responseEvaluator is nil, the request is assumed not to require a response, and the next request in the queue will + * be sent immediately. + * + * @return An initialized ORSSerialRequest instance. + */ ++ (instancetype)requestWithDataToSend:(NSData *)dataToSend + userInfo:(nullable id)userInfo + timeoutInterval:(NSTimeInterval)timeout + responseEvaluator:(nullable ORSSerialPacketEvaluator)responseEvaluator DEPRECATED_ATTRIBUTE; + +/** + * @deprecated Use -initWithDataToSend:userInfo:timeoutInterval:responseDescriptor: instead. + * Initializes an ORSSerialRequest instance. + * + * @param dataToSend The data to be sent on the serial port. + * @param userInfo An arbitrary userInfo object. + * @param timeout The maximum amount of time in seconds to wait for a response. Pass -1.0 to wait indefinitely. + * @param responseEvaluator A block used to evaluate whether received data constitutes a valid response to the request. + * May be nil. If responseEvaluator is nil, the request is assumed not to require a response, and the next request in the queue will + * be sent immediately. + * + * @return An initialized ORSSerialRequest instance. + */ +- (instancetype)initWithDataToSend:(NSData *)dataToSend + userInfo:(nullable id)userInfo + timeoutInterval:(NSTimeInterval)timeout + responseEvaluator:(nullable ORSSerialPacketEvaluator)responseEvaluator DEPRECATED_ATTRIBUTE; + /** * @deprecated Use the receiver's responseDescriptor object's -dataIsValidPacket: method instead. * Except in the special case where the response descriptor is nil, this method now simply calls diff --git a/Source/ORSSerialRequest.m b/Source/ORSSerialRequest.m index 04298b87..2e750846 100644 --- a/Source/ORSSerialRequest.m +++ b/Source/ORSSerialRequest.m @@ -47,14 +47,6 @@ +(instancetype)requestWithDataToSend:(NSData *)dataToSend return [[self alloc] initWithDataToSend:dataToSend userInfo:userInfo timeoutInterval:timeout responseDescriptor:responseDescriptor]; } -+ (instancetype)requestWithDataToSend:(NSData *)dataToSend - userInfo:(id)userInfo - timeoutInterval:(NSTimeInterval)timeout - responseEvaluator:(ORSSerialPacketEvaluator)responseEvaluator; -{ - return [[self alloc] initWithDataToSend:dataToSend userInfo:userInfo timeoutInterval:timeout responseEvaluator:responseEvaluator]; -} - - (instancetype)initWithDataToSend:(NSData *)dataToSend userInfo:(id)userInfo timeoutInterval:(NSTimeInterval)timeout @@ -73,20 +65,33 @@ - (instancetype)initWithDataToSend:(NSData *)dataToSend return self; } +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ data: %@ userInfo: %@ timeout interval: %f", [super description], self.dataToSend, self.userInfo, self.timeoutInterval]; +} + +@end + +@implementation ORSSerialRequest (Deprecated) + ++ (instancetype)requestWithDataToSend:(NSData *)dataToSend + userInfo:(id)userInfo + timeoutInterval:(NSTimeInterval)timeout + responseEvaluator:(ORSSerialPacketEvaluator)responseEvaluator; +{ + return [[self alloc] initWithDataToSend:dataToSend userInfo:userInfo timeoutInterval:timeout responseEvaluator:responseEvaluator]; +} - (instancetype)initWithDataToSend:(NSData *)dataToSend userInfo:(id)userInfo timeoutInterval:(NSTimeInterval)timeout responseEvaluator:(ORSSerialPacketEvaluator)responseEvaluator; { - ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithUserInfo:nil responseEvaluator:responseEvaluator]; + ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithMaximumPacketLength:NSUIntegerMax + userInfo:nil + responseEvaluator:responseEvaluator]; return [self initWithDataToSend:dataToSend userInfo:userInfo timeoutInterval:timeout responseDescriptor:descriptor]; } -- (NSString *)description -{ - return [NSString stringWithFormat:@"%@ data: %@ userInfo: %@ timeout interval: %f", [super description], self.dataToSend, self.userInfo, self.timeoutInterval]; -} - - (BOOL)dataIsValidResponse:(NSData *)responseData { if (!self.responseDescriptor) return YES; @@ -94,4 +99,4 @@ - (BOOL)dataIsValidResponse:(NSData *)responseData return [self.responseDescriptor dataIsValidPacket:responseData]; } -@end +@end \ No newline at end of file From 13d2d07f64bd66c0491e46f47423fdf1768cb449 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Sun, 6 Sep 2015 12:41:27 -0600 Subject: [PATCH 43/55] Issue 75: Using maximumPacketLength property on ORSSerialPacketDescriptor to limit buffer sizes. Greatly improves packet parsing performance. --- .../ORSSerialPort.xcodeproj/project.pbxproj | 17 ++++++ ...3AB06FEE-1381-45AC-9379-B331E6DDAABC.plist | 22 ++++++++ .../Info.plist | 33 +++++++++++ Source/ORSSerialBuffer.h | 21 +++++++ Source/ORSSerialBuffer.m | 56 +++++++++++++++++++ Source/ORSSerialPort.m | 22 ++++---- Source/ORSSerialRequest.m | 2 +- 7 files changed, 161 insertions(+), 12 deletions(-) create mode 100644 Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcbaselines/9D7472121B6D7767002D8B10.xcbaseline/3AB06FEE-1381-45AC-9379-B331E6DDAABC.plist create mode 100644 Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcbaselines/9D7472121B6D7767002D8B10.xcbaseline/Info.plist create mode 100644 Source/ORSSerialBuffer.h create mode 100644 Source/ORSSerialBuffer.m diff --git a/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj b/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj index 9f3ea7dd..8f0660d8 100644 --- a/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj +++ b/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 9D64D0E71B9CBC99009D1AEB /* ORSSerialBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D64D0E51B9CBC99009D1AEB /* ORSSerialBuffer.h */; }; + 9D64D0E81B9CBC99009D1AEB /* ORSSerialBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D64D0E61B9CBC99009D1AEB /* ORSSerialBuffer.m */; }; 9D7472181B6D7767002D8B10 /* ORSSerialPort_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D7472171B6D7767002D8B10 /* ORSSerialPort_Tests.m */; }; 9D7472191B6D7767002D8B10 /* ORSSerial.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DCA89121A2BB106009285EB /* ORSSerial.framework */; }; 9D7472201B6D7787002D8B10 /* ORSSerialPacketDescriptor_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D74721F1B6D7787002D8B10 /* ORSSerialPacketDescriptor_Tests.m */; }; @@ -34,6 +36,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 9D64D0E51B9CBC99009D1AEB /* ORSSerialBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORSSerialBuffer.h; sourceTree = ""; }; + 9D64D0E61B9CBC99009D1AEB /* ORSSerialBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORSSerialBuffer.m; sourceTree = ""; }; 9D7472131B6D7767002D8B10 /* ORSSerialPort Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ORSSerialPort Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 9D7472161B6D7767002D8B10 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9D7472171B6D7767002D8B10 /* ORSSerialPort_Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ORSSerialPort_Tests.m; sourceTree = ""; }; @@ -74,6 +78,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 9D64D0EA1B9CBCA4009D1AEB /* Private */ = { + isa = PBXGroup; + children = ( + 9D64D0E51B9CBC99009D1AEB /* ORSSerialBuffer.h */, + 9D64D0E61B9CBC99009D1AEB /* ORSSerialBuffer.m */, + ); + name = Private; + sourceTree = ""; + }; 9D7472141B6D7767002D8B10 /* ORSSerialPort Tests */ = { isa = PBXGroup; children = ( @@ -132,6 +145,7 @@ 9DCA89391A2BB1E2009285EB /* ORSSerialRequest.m */, 9DD6B1D01B5F4338000AB46E /* ORSSerialPacketDescriptor.h */, 9DD6B1D11B5F4338000AB46E /* ORSSerialPacketDescriptor.m */, + 9D64D0EA1B9CBCA4009D1AEB /* Private */, ); name = Source; path = ../Source; @@ -158,6 +172,7 @@ 9DD6B1D21B5F4338000AB46E /* ORSSerialPacketDescriptor.h in Headers */, 9DCA89321A2BB15A009285EB /* ORSSerial.h in Headers */, 9DCA893C1A2BB1E2009285EB /* ORSSerialPortManager.h in Headers */, + 9D64D0E71B9CBC99009D1AEB /* ORSSerialBuffer.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -270,6 +285,7 @@ 9DD6B1D31B5F4338000AB46E /* ORSSerialPacketDescriptor.m in Sources */, 9DCA893B1A2BB1E2009285EB /* ORSSerialPort.m in Sources */, 9DCA893D1A2BB1E2009285EB /* ORSSerialPortManager.m in Sources */, + 9D64D0E81B9CBC99009D1AEB /* ORSSerialBuffer.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -451,6 +467,7 @@ 9D74721D1B6D7767002D8B10 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 9DCA890C1A2BB106009285EB /* Build configuration list for PBXProject "ORSSerialPort" */ = { isa = XCConfigurationList; diff --git a/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcbaselines/9D7472121B6D7767002D8B10.xcbaseline/3AB06FEE-1381-45AC-9379-B331E6DDAABC.plist b/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcbaselines/9D7472121B6D7767002D8B10.xcbaseline/3AB06FEE-1381-45AC-9379-B331E6DDAABC.plist new file mode 100644 index 00000000..4bbbf39c --- /dev/null +++ b/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcbaselines/9D7472121B6D7767002D8B10.xcbaseline/3AB06FEE-1381-45AC-9379-B331E6DDAABC.plist @@ -0,0 +1,22 @@ + + + + + classNames + + ORSSerialPacketDescriptor_Tests + + testPerformanceWithMultipleInstalledDescriptors + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.02 + baselineIntegrationDisplayName + Local Baseline + + + + + + diff --git a/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcbaselines/9D7472121B6D7767002D8B10.xcbaseline/Info.plist b/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcbaselines/9D7472121B6D7767002D8B10.xcbaseline/Info.plist new file mode 100644 index 00000000..0f1fa3a6 --- /dev/null +++ b/Framework Project/ORSSerialPort.xcodeproj/xcshareddata/xcbaselines/9D7472121B6D7767002D8B10.xcbaseline/Info.plist @@ -0,0 +1,33 @@ + + + + + runDestinationsByUUID + + 3AB06FEE-1381-45AC-9379-B331E6DDAABC + + localComputer + + busSpeedInMHz + 100 + cpuCount + 1 + cpuKind + Intel Core i7 + cpuSpeedInMHz + 3400 + logicalCPUCoresPerPackage + 8 + modelCode + iMac13,2 + physicalCPUCoresPerPackage + 4 + platformIdentifier + com.apple.platform.macosx + + targetArchitecture + x86_64 + + + + diff --git a/Source/ORSSerialBuffer.h b/Source/ORSSerialBuffer.h new file mode 100644 index 00000000..1ec06334 --- /dev/null +++ b/Source/ORSSerialBuffer.h @@ -0,0 +1,21 @@ +// +// ORSSerialBuffer.h +// ORSSerialPort +// +// Created by Andrew Madsen on 9/6/15. +// Copyright (c) 2015 Open Reel Software. All rights reserved. +// + +#import + +@interface ORSSerialBuffer : NSObject + +- (instancetype)initWithMaximumLength:(NSUInteger)maxLength NS_DESIGNATED_INITIALIZER; + +- (void)appendData:(NSData *)data; +- (void)clearBuffer; + +@property (nonatomic, strong, readonly) NSData *data; +@property (nonatomic, readonly) NSUInteger maximumLength; + +@end diff --git a/Source/ORSSerialBuffer.m b/Source/ORSSerialBuffer.m new file mode 100644 index 00000000..f58a863d --- /dev/null +++ b/Source/ORSSerialBuffer.m @@ -0,0 +1,56 @@ +// +// ORSSerialBuffer.m +// ORSSerialPort +// +// Created by Andrew Madsen on 9/6/15. +// Copyright (c) 2015 Open Reel Software. All rights reserved. +// + +#import "ORSSerialBuffer.h" + +@interface ORSSerialBuffer () + +@property (nonatomic, strong) NSMutableData *internalBuffer; + +@end + +@implementation ORSSerialBuffer + +- (instancetype)init NS_UNAVAILABLE +{ + [NSException raise:NSInternalInconsistencyException format:@"Use -[ORSSerialBuffer initWithMaximumLength:]"]; + return nil; +} + +- (instancetype)initWithMaximumLength:(NSUInteger)maxLength +{ + self = [super init]; + if (self) { + _internalBuffer = [NSMutableData data]; + _maximumLength = maxLength; + } + return self; +} + +- (void)appendData:(NSData *)data +{ + [self willChangeValueForKey:@"internalBuffer"]; + [self.internalBuffer appendData:data]; + if ([self.internalBuffer length] > self.maximumLength) { + NSRange rangeToDelete = NSMakeRange(0, [self.internalBuffer length] - self.maximumLength); + [self.internalBuffer replaceBytesInRange:rangeToDelete withBytes:NULL length:0]; + } + [self didChangeValueForKey:@"internalBuffer"]; +} + +- (void)clearBuffer +{ + self.internalBuffer = [NSMutableData data]; +} + +#pragma mark - Properties + ++ (NSSet *)keyPathsForValuesAffectingData { return [NSSet setWithObjects:@"internalData", nil]; } +- (NSData *)data { return self.internalBuffer; } + +@end diff --git a/Source/ORSSerialPort.m b/Source/ORSSerialPort.m index a8e2be73..d546700a 100644 --- a/Source/ORSSerialPort.m +++ b/Source/ORSSerialPort.m @@ -26,6 +26,7 @@ #import "ORSSerialPort.h" #import "ORSSerialRequest.h" +#import "ORSSerialBuffer.h" #import #import #import @@ -62,7 +63,7 @@ @interface ORSSerialPort () @property int fileDescriptor; @property (copy, readwrite) NSString *name; -@property (strong) NSMutableData *requestResponseReceiveBuffer; +@property (strong) ORSSerialBuffer *requestResponseReceiveBuffer; // Packet descriptors @property (nonatomic, strong) NSMapTable *packetDescriptorsAndBuffers; @@ -172,7 +173,6 @@ - (instancetype)initWithDevice:(io_object_t)device; self.ioKitDevice = device; self.path = bsdPath; self.name = [[self class] modemNameFromDevice:device]; - self.requestResponseReceiveBuffer = [NSMutableData data]; self.requestHandlingQueue = dispatch_queue_create("com.openreelsoftware.ORSSerialPort.requestHandlingQueue", 0); #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_8 self.packetDescriptorsAndBuffers = [NSMapTable strongToStrongObjectsMapTable]; @@ -471,7 +471,8 @@ - (void)startListeningForPacketsMatchingDescriptor:(ORSSerialPacketDescriptor *) if ([self.packetDescriptorsAndBuffers objectForKey:descriptor]) return; // Already listening [self willChangeValueForKey:@"packetDescriptorsAndBuffers"]; - [self.packetDescriptorsAndBuffers setObject:[NSMutableData data] forKey:descriptor]; + ORSSerialBuffer *buffer = [[ORSSerialBuffer alloc] initWithMaximumLength:descriptor.maximumPacketLength]; + [self.packetDescriptorsAndBuffers setObject:buffer forKey:descriptor]; [self didChangeValueForKey:@"packetDescriptorsAndBuffers"]; } @@ -486,8 +487,8 @@ - (void)stopListeningForPacketsMatchingDescriptor:(ORSSerialPacketDescriptor *)d - (void)clearBufferForPacketDescriptor:(ORSSerialPacketDescriptor *)descriptor { - NSMutableData *buffer = [self.packetDescriptorsAndBuffers objectForKey:descriptor]; - [buffer setData:[NSData data]]; // Clear buffer + ORSSerialBuffer *buffer = [self.packetDescriptorsAndBuffers objectForKey:descriptor]; + [buffer clearBuffer]; } // Must only be called on requestHandlingQueue (ie. wrap call to this method in dispatch()) @@ -506,9 +507,8 @@ - (BOOL)reallySendRequest:(ORSSerialRequest *)request { if (!self.pendingRequest) { - [self.requestResponseReceiveBuffer replaceBytesInRange:NSMakeRange(0, [self.requestResponseReceiveBuffer length]) - withBytes:NULL - length:0]; + NSUInteger bufferLength = request.responseDescriptor.maximumPacketLength; + self.requestResponseReceiveBuffer = [[ORSSerialBuffer alloc] initWithMaximumLength:bufferLength]; // Send immediately self.pendingRequest = request; @@ -575,7 +575,7 @@ - (void)checkResponseToPendingRequestAndContinueIfValidWithReceivedByte:(NSData } [self.requestResponseReceiveBuffer appendData:byte]; - NSData *responseData = [self packetMatchingDescriptor:packetDescriptor atEndOfBuffer:self.requestResponseReceiveBuffer]; + NSData *responseData = [self packetMatchingDescriptor:packetDescriptor atEndOfBuffer:self.requestResponseReceiveBuffer.data]; if (!responseData) return; self.pendingRequestTimeoutTimer = nil; @@ -613,11 +613,11 @@ - (void)receiveData:(NSData *)data; for (ORSSerialPacketDescriptor *descriptor in self.packetDescriptorsAndBuffers) { // Append byte to buffer - NSMutableData *buffer = [self.packetDescriptorsAndBuffers objectForKey:descriptor]; + ORSSerialBuffer *buffer = [self.packetDescriptorsAndBuffers objectForKey:descriptor]; [buffer appendData:byte]; // Check for complete packet - NSData *completePacket = [self packetMatchingDescriptor:descriptor atEndOfBuffer:buffer]; + NSData *completePacket = [self packetMatchingDescriptor:descriptor atEndOfBuffer:buffer.data]; if (![completePacket length]) continue; // Complete packet received, so notify delegate then clear buffer diff --git a/Source/ORSSerialRequest.m b/Source/ORSSerialRequest.m index 2e750846..dddc2f31 100644 --- a/Source/ORSSerialRequest.m +++ b/Source/ORSSerialRequest.m @@ -86,7 +86,7 @@ - (instancetype)initWithDataToSend:(NSData *)dataToSend timeoutInterval:(NSTimeInterval)timeout responseEvaluator:(ORSSerialPacketEvaluator)responseEvaluator; { - ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithMaximumPacketLength:NSUIntegerMax + ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithMaximumPacketLength:NSIntegerMax userInfo:nil responseEvaluator:responseEvaluator]; return [self initWithDataToSend:dataToSend userInfo:userInfo timeoutInterval:timeout responseDescriptor:descriptor]; From 33e6f28eb31ba7626380dffac2a0efe1390372d3 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 7 Sep 2015 11:28:36 -0600 Subject: [PATCH 44/55] Updated RequestResponseDemo projects for changes to request/response API (See 246cadeee). --- .../Objective-C/Resources/Main.storyboard | 4 +- .../Sources/ORSSerialBoardController.m | 53 +++++++++++-------- .../Swift/Sources/SerialBoardController.swift | 18 +++---- 3 files changed, 42 insertions(+), 33 deletions(-) diff --git a/Examples/RequestResponseDemo/Objective-C/Resources/Main.storyboard b/Examples/RequestResponseDemo/Objective-C/Resources/Main.storyboard index 7c1292ee..2fa9c087 100644 --- a/Examples/RequestResponseDemo/Objective-C/Resources/Main.storyboard +++ b/Examples/RequestResponseDemo/Objective-C/Resources/Main.storyboard @@ -1,8 +1,8 @@ - + - + diff --git a/Examples/RequestResponseDemo/Objective-C/Sources/ORSSerialBoardController.m b/Examples/RequestResponseDemo/Objective-C/Sources/ORSSerialBoardController.m index 720f91d1..e439d93a 100644 --- a/Examples/RequestResponseDemo/Objective-C/Sources/ORSSerialBoardController.m +++ b/Examples/RequestResponseDemo/Objective-C/Sources/ORSSerialBoardController.m @@ -58,26 +58,32 @@ - (void)pollingTimerFired:(NSTimer *)timer - (void)readTemperature { NSData *command = [@"$TEMP?;" dataUsingEncoding:NSASCIIStringEncoding]; - ORSSerialRequest *request = - [ORSSerialRequest requestWithDataToSend:command - userInfo:@(ORSSerialBoardRequestTypeReadTemperature) - timeoutInterval:kTimeoutDuration - responseEvaluator:^BOOL(NSData *data) { - return [self temperatureFromResponsePacket:data] != nil; - }]; + ORSSerialPacketDescriptor *responseDescriptor = + [[ORSSerialPacketDescriptor alloc] initWithMaximumPacketLength:10 + userInfo:nil + responseEvaluator:^BOOL(NSData *inputData) { + return [self temperatureFromResponsePacket:inputData] != nil; + }]; + ORSSerialRequest *request = [ORSSerialRequest requestWithDataToSend:command + userInfo:@(ORSSerialBoardRequestTypeReadTemperature) + timeoutInterval:kTimeoutDuration + responseDescriptor:responseDescriptor]; [self.serialPort sendRequest:request]; } - (void)readLEDState { NSData *command = [@"$LED?;" dataUsingEncoding:NSASCIIStringEncoding]; - ORSSerialRequest *request = - [ORSSerialRequest requestWithDataToSend:command - userInfo:@(ORSSerialBoardRequestTypeReadLED) - timeoutInterval:kTimeoutDuration - responseEvaluator:^BOOL(NSData *data) { - return [self LEDStateFromResponsePacket:data] != nil; - }]; + ORSSerialPacketDescriptor *responseDescriptor = + [[ORSSerialPacketDescriptor alloc] initWithMaximumPacketLength:10 + userInfo:nil + responseEvaluator:^BOOL(NSData *inputData) { + return [self LEDStateFromResponsePacket:inputData] != nil; + }]; + ORSSerialRequest *request = [ORSSerialRequest requestWithDataToSend:command + userInfo:@(ORSSerialBoardRequestTypeReadLED) + timeoutInterval:kTimeoutDuration + responseDescriptor:responseDescriptor]; [self.serialPort sendRequest:request]; } @@ -85,13 +91,16 @@ - (void)sendCommandToSetLEDToState:(BOOL)LEDState { NSString *commandString = [NSString stringWithFormat:@"$LED%@;", (LEDState ? @"1" : @"0")]; NSData *command = [commandString dataUsingEncoding:NSASCIIStringEncoding]; - ORSSerialRequest *request = - [ORSSerialRequest requestWithDataToSend:command - userInfo:@(ORSSerialBoardRequestTypeSetLED) - timeoutInterval:kTimeoutDuration - responseEvaluator:^BOOL(NSData *data) { - return [self LEDStateFromResponsePacket:data] != nil; - }]; + ORSSerialPacketDescriptor *responseDescriptor = + [[ORSSerialPacketDescriptor alloc] initWithMaximumPacketLength:10 + userInfo:nil + responseEvaluator:^BOOL(NSData *inputData) { + return [self LEDStateFromResponsePacket:inputData] != nil; + }]; + ORSSerialRequest *request = [ORSSerialRequest requestWithDataToSend:command + userInfo:@(ORSSerialBoardRequestTypeSetLED) + timeoutInterval:kTimeoutDuration + responseDescriptor:responseDescriptor]; [self.serialPort sendRequest:request]; } @@ -140,7 +149,7 @@ - (void)serialPort:(ORSSerialPort *)serialPort didReceiveResponse:(NSData *)resp case ORSSerialBoardRequestTypeReadTemperature: self.temperature = [[self temperatureFromResponsePacket:responseData] integerValue]; break; - + case ORSSerialBoardRequestTypeReadLED: case ORSSerialBoardRequestTypeSetLED: // Don't call the setter to avoid continuing to send set commands indefinitely diff --git a/Examples/RequestResponseDemo/Swift/Sources/SerialBoardController.swift b/Examples/RequestResponseDemo/Swift/Sources/SerialBoardController.swift index c0454e73..1f599167 100644 --- a/Examples/RequestResponseDemo/Swift/Sources/SerialBoardController.swift +++ b/Examples/RequestResponseDemo/Swift/Sources/SerialBoardController.swift @@ -47,32 +47,32 @@ class SerialBoardController: NSObject, ORSSerialPortDelegate { // MARK: Sending Commands private func readTemperature() { let command = "$TEMP?;".dataUsingEncoding(NSASCIIStringEncoding)! + let responseDescriptor = ORSSerialPacketDescriptor(prefixString: "!TEMP", suffixString: ";", maximumPacketLength: 10, userInfo: nil) let request = ORSSerialRequest(dataToSend: command, userInfo: SerialBoardRequestType.ReadTemperature.rawValue, - timeoutInterval: 0.5) { (data) -> ObjCBool in - return ObjCBool(self.temperatureFromResponsePacket(data!) != nil) - } + timeoutInterval: 0.5, + responseDescriptor: responseDescriptor) self.serialPort?.sendRequest(request) } private func readLEDState() { let command = "$LED?;".dataUsingEncoding(NSASCIIStringEncoding)! + let responseDescriptor = ORSSerialPacketDescriptor(prefixString: "!LED", suffixString: ";", maximumPacketLength: 10, userInfo: nil) let request = ORSSerialRequest(dataToSend: command, userInfo: SerialBoardRequestType.ReadLED.rawValue, - timeoutInterval: kTimeoutDuration) { (data) -> ObjCBool in - return ObjCBool(self.LEDStateFromResponsePacket(data!) != nil) - } + timeoutInterval: kTimeoutDuration, + responseDescriptor: responseDescriptor) self.serialPort?.sendRequest(request) } private func sendCommandToSetLEDToState(state: Bool) { let commandString = NSString(format: "$LED%@;", (state ? "1" : "0")) let command = commandString.dataUsingEncoding(NSASCIIStringEncoding)! + let responseDescriptor = ORSSerialPacketDescriptor(prefixString: "!LED", suffixString: ";", maximumPacketLength: 10, userInfo: nil) let request = ORSSerialRequest(dataToSend: command, userInfo: SerialBoardRequestType.SetLED.rawValue, - timeoutInterval: kTimeoutDuration) { (data) -> ObjCBool in - return ObjCBool(self.LEDStateFromResponsePacket(data!) != nil) - } + timeoutInterval: kTimeoutDuration, + responseDescriptor: responseDescriptor) self.serialPort?.sendRequest(request) } From d7661eefd853acd15b2c08ecc12a961822c65bad Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 7 Sep 2015 11:36:19 -0600 Subject: [PATCH 45/55] Updated PacketParsingDemo projects with changes to ORSSerialPacketDescriptor API. (See 246cadeee) --- .../Objective-C/Sources/ORSSerialCommunicator.m | 1 + .../Swift/Sources/SerialCommunicator.swift | 2 +- Framework Project/Info.plist | 2 +- Framework Project/ORSSerialPort Tests/Info.plist | 2 +- Framework Project/ORSSerialPort.xcodeproj/project.pbxproj | 7 ++++++- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Examples/PacketParsingDemo/Objective-C/Sources/ORSSerialCommunicator.m b/Examples/PacketParsingDemo/Objective-C/Sources/ORSSerialCommunicator.m index c19d02bf..068a5aa9 100644 --- a/Examples/PacketParsingDemo/Objective-C/Sources/ORSSerialCommunicator.m +++ b/Examples/PacketParsingDemo/Objective-C/Sources/ORSSerialCommunicator.m @@ -40,6 +40,7 @@ - (void)serialPortWasOpened:(ORSSerialPort *)serialPort { ORSSerialPacketDescriptor *descriptor = [[ORSSerialPacketDescriptor alloc] initWithPrefixString:@"!pos" suffixString:@";" + maximumPacketLength:8 userInfo:nil]; [serialPort startListeningForPacketsMatchingDescriptor:descriptor]; } diff --git a/Examples/PacketParsingDemo/Swift/Sources/SerialCommunicator.swift b/Examples/PacketParsingDemo/Swift/Sources/SerialCommunicator.swift index bd5dbf2e..b3d0428d 100644 --- a/Examples/PacketParsingDemo/Swift/Sources/SerialCommunicator.swift +++ b/Examples/PacketParsingDemo/Swift/Sources/SerialCommunicator.swift @@ -26,7 +26,7 @@ class SerialCommunicator: NSObject, ORSSerialPortDelegate { } func serialPortWasOpened(serialPort: ORSSerialPort) { - let descriptor = ORSSerialPacketDescriptor(prefixString: "!pos", suffixString: ";", userInfo: nil) + let descriptor = ORSSerialPacketDescriptor(prefixString: "!pos", suffixString: ";", maximumPacketLength: 8, userInfo: nil) serialPort.startListeningForPacketsMatchingDescriptor(descriptor) } diff --git a/Framework Project/Info.plist b/Framework Project/Info.plist index f614d3a2..bcd60914 100644 --- a/Framework Project/Info.plist +++ b/Framework Project/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Framework Project/ORSSerialPort Tests/Info.plist b/Framework Project/ORSSerialPort Tests/Info.plist index be2cb8f3..ba72822e 100644 --- a/Framework Project/ORSSerialPort Tests/Info.plist +++ b/Framework Project/ORSSerialPort Tests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj b/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj index 8f0660d8..57ce5124 100644 --- a/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj +++ b/Framework Project/ORSSerialPort.xcodeproj/project.pbxproj @@ -221,7 +221,7 @@ 9DCA89091A2BB106009285EB /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0640; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Open Reel Software"; TargetAttributes = { 9D7472121B6D7767002D8B10 = { @@ -317,6 +317,7 @@ INFOPLIST_FILE = "ORSSerialPort Tests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.10; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -334,6 +335,7 @@ INFOPLIST_FILE = "ORSSerialPort Tests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.10; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -358,6 +360,7 @@ COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -434,6 +437,7 @@ INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; @@ -452,6 +456,7 @@ INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.openreelsoftware.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; From 5b2f7d074531c9215989729640dc34b36953eb5b Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 7 Sep 2015 11:55:35 -0600 Subject: [PATCH 46/55] Issue #76: Serialized modification/reading of packet descriptors. --- Source/ORSSerialPort.m | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Source/ORSSerialPort.m b/Source/ORSSerialPort.m index d546700a..6b916421 100644 --- a/Source/ORSSerialPort.m +++ b/Source/ORSSerialPort.m @@ -471,26 +471,22 @@ - (void)startListeningForPacketsMatchingDescriptor:(ORSSerialPacketDescriptor *) if ([self.packetDescriptorsAndBuffers objectForKey:descriptor]) return; // Already listening [self willChangeValueForKey:@"packetDescriptorsAndBuffers"]; - ORSSerialBuffer *buffer = [[ORSSerialBuffer alloc] initWithMaximumLength:descriptor.maximumPacketLength]; - [self.packetDescriptorsAndBuffers setObject:buffer forKey:descriptor]; + dispatch_sync(self.requestHandlingQueue, ^{ + ORSSerialBuffer *buffer = [[ORSSerialBuffer alloc] initWithMaximumLength:descriptor.maximumPacketLength]; + [self.packetDescriptorsAndBuffers setObject:buffer forKey:descriptor]; + }); [self didChangeValueForKey:@"packetDescriptorsAndBuffers"]; } - (void)stopListeningForPacketsMatchingDescriptor:(ORSSerialPacketDescriptor *)descriptor; { [self willChangeValueForKey:@"packetDescriptorsAndBuffers"]; - [self.packetDescriptorsAndBuffers removeObjectForKey:descriptor]; + dispatch_sync(self.requestHandlingQueue, ^{ [self.packetDescriptorsAndBuffers removeObjectForKey:descriptor]; }); [self didChangeValueForKey:@"packetDescriptorsAndBuffers"]; } #pragma mark - Private Methods -- (void)clearBufferForPacketDescriptor:(ORSSerialPacketDescriptor *)descriptor -{ - ORSSerialBuffer *buffer = [self.packetDescriptorsAndBuffers objectForKey:descriptor]; - [buffer clearBuffer]; -} - // Must only be called on requestHandlingQueue (ie. wrap call to this method in dispatch()) - (NSData *)packetMatchingDescriptor:(ORSSerialPacketDescriptor *)descriptor atEndOfBuffer:(NSData *)buffer { @@ -627,7 +623,7 @@ - (void)receiveData:(NSData *)data; [self.delegate serialPort:self didReceivePacket:completePacket matchingDescriptor:descriptor]; }); } - [self clearBufferForPacketDescriptor:descriptor]; + [buffer clearBuffer]; } // Also check for response to pending request From f9d60b0405325ec9e4285a0868fb675331302984 Mon Sep 17 00:00:00 2001 From: Michael Koukoullis Date: Wed, 9 Sep 2015 22:38:33 +1000 Subject: [PATCH 47/55] Fix ORSSerialPortDemo build error --- .../Objective-C/ORSSerialPortDemo.xcodeproj/project.pbxproj | 6 ++++++ .../Swift/ORSSerialPortDemo.xcodeproj/project.pbxproj | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/Examples/ORSSerialPortDemo/Objective-C/ORSSerialPortDemo.xcodeproj/project.pbxproj b/Examples/ORSSerialPortDemo/Objective-C/ORSSerialPortDemo.xcodeproj/project.pbxproj index 8ec14c95..b284606c 100644 --- a/Examples/ORSSerialPortDemo/Objective-C/ORSSerialPortDemo.xcodeproj/project.pbxproj +++ b/Examples/ORSSerialPortDemo/Objective-C/ORSSerialPortDemo.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 2788B8001BA05EFC0018C0E7 /* ORSSerialBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 2788B7FF1BA05EFC0018C0E7 /* ORSSerialBuffer.m */; settings = {ASSET_TAGS = (); }; }; 9D52392E1AC859DF00AEB75F /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D52392D1AC859DF00AEB75F /* IOKit.framework */; }; 9D5239301AC859E700AEB75F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D52392F1AC859E700AEB75F /* Cocoa.framework */; }; 9D66D81D159BCAB800EE6D09 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9D66D81B159BCAB800EE6D09 /* InfoPlist.strings */; }; @@ -33,6 +34,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 2788B7FE1BA05EFC0018C0E7 /* ORSSerialBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORSSerialBuffer.h; sourceTree = ""; }; + 2788B7FF1BA05EFC0018C0E7 /* ORSSerialBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORSSerialBuffer.m; sourceTree = ""; }; 9D52392D1AC859DF00AEB75F /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; 9D52392F1AC859E700AEB75F /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 9D66D80E159BCAB800EE6D09 /* ORSSerialPortDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ORSSerialPortDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -131,6 +134,8 @@ 9D66D835159BCC2F00EE6D09 /* ORSSerialPort.m */, 9D66D836159BCC2F00EE6D09 /* ORSSerialPortManager.h */, 9D66D837159BCC2F00EE6D09 /* ORSSerialPortManager.m */, + 2788B7FE1BA05EFC0018C0E7 /* ORSSerialBuffer.h */, + 2788B7FF1BA05EFC0018C0E7 /* ORSSerialBuffer.m */, ); name = ORSSerialPort; path = ../../../Source; @@ -204,6 +209,7 @@ files = ( 9D66D81F159BCAB800EE6D09 /* main.m in Sources */, 9D66D826159BCAB900EE6D09 /* ORSAppDelegate.m in Sources */, + 2788B8001BA05EFC0018C0E7 /* ORSSerialBuffer.m in Sources */, 9D66D838159BCC2F00EE6D09 /* ORSSerialPort.m in Sources */, 9D66D839159BCC2F00EE6D09 /* ORSSerialPortManager.m in Sources */, 9D66D83D159BCC6400EE6D09 /* ORSSerialPortDemoController.m in Sources */, diff --git a/Examples/ORSSerialPortDemo/Swift/ORSSerialPortDemo.xcodeproj/project.pbxproj b/Examples/ORSSerialPortDemo/Swift/ORSSerialPortDemo.xcodeproj/project.pbxproj index 49c3b823..1d1044f5 100644 --- a/Examples/ORSSerialPortDemo/Swift/ORSSerialPortDemo.xcodeproj/project.pbxproj +++ b/Examples/ORSSerialPortDemo/Swift/ORSSerialPortDemo.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 2788B8031BA05F3E0018C0E7 /* ORSSerialBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 2788B8021BA05F3E0018C0E7 /* ORSSerialBuffer.m */; settings = {ASSET_TAGS = (); }; }; 9D0E21661A0441F500051960 /* SerialPortDemoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D0E21651A0441F500051960 /* SerialPortDemoController.swift */; }; 9D0E21681A04460000051960 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D0E21671A04460000051960 /* MainMenu.xib */; }; 9DFD06401A043BF300CE0294 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9DFD063B1A043BF300CE0294 /* Images.xcassets */; }; @@ -16,6 +17,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 2788B8011BA05F3E0018C0E7 /* ORSSerialBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORSSerialBuffer.h; sourceTree = ""; }; + 2788B8021BA05F3E0018C0E7 /* ORSSerialBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORSSerialBuffer.m; sourceTree = ""; }; 9D0E21651A0441F500051960 /* SerialPortDemoController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SerialPortDemoController.swift; sourceTree = ""; }; 9D0E21671A04460000051960 /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; 9DFD06181A043BA400CE0294 /* ORSSerialPortDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ORSSerialPortDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -85,6 +88,8 @@ 9DFD064E1A043D3600CE0294 /* ORSSerialPort.m */, 9DFD06501A043D5500CE0294 /* ORSSerialPortManager.h */, 9DFD06511A043D5500CE0294 /* ORSSerialPortManager.m */, + 2788B8011BA05F3E0018C0E7 /* ORSSerialBuffer.h */, + 2788B8021BA05F3E0018C0E7 /* ORSSerialBuffer.m */, ); name = ORSSerialPort; path = ../../../Source; @@ -165,6 +170,7 @@ 9DFD06421A043BF300CE0294 /* AppDelegate.swift in Sources */, 9DFD064F1A043D3600CE0294 /* ORSSerialPort.m in Sources */, 9D0E21661A0441F500051960 /* SerialPortDemoController.swift in Sources */, + 2788B8031BA05F3E0018C0E7 /* ORSSerialBuffer.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From bdd7b2a8a0552fe9c6ff162fe20a553dad8824ad Mon Sep 17 00:00:00 2001 From: Michael Koukoullis Date: Wed, 9 Sep 2015 22:45:56 +1000 Subject: [PATCH 48/55] Fix CommandLineDemo build error --- .../Objective-C/CommandLineDemo.xcodeproj/project.pbxproj | 6 ++++++ .../Swift/CommandLineDemo.xcodeproj/project.pbxproj | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/Examples/CommandLineDemo/Objective-C/CommandLineDemo.xcodeproj/project.pbxproj b/Examples/CommandLineDemo/Objective-C/CommandLineDemo.xcodeproj/project.pbxproj index 4c71ae48..d719d612 100644 --- a/Examples/CommandLineDemo/Objective-C/CommandLineDemo.xcodeproj/project.pbxproj +++ b/Examples/CommandLineDemo/Objective-C/CommandLineDemo.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 2788B8061BA05FFD0018C0E7 /* ORSSerialBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 2788B8051BA05FFD0018C0E7 /* ORSSerialBuffer.m */; settings = {ASSET_TAGS = (); }; }; 9D2B580C1ADC16E200B08D53 /* ORSSerialPort.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2B58091ADC16E200B08D53 /* ORSSerialPort.m */; }; 9D2B580D1ADC16E200B08D53 /* ORSSerialPortManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2B580B1ADC16E200B08D53 /* ORSSerialPortManager.m */; }; 9D2D68F71AC8524E00779F24 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D2D68F61AC8524E00779F24 /* IOKit.framework */; }; @@ -26,6 +27,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 2788B8041BA05FFD0018C0E7 /* ORSSerialBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORSSerialBuffer.h; path = ../../../../Source/ORSSerialBuffer.h; sourceTree = ""; }; + 2788B8051BA05FFD0018C0E7 /* ORSSerialBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORSSerialBuffer.m; path = ../../../../Source/ORSSerialBuffer.m; sourceTree = ""; }; 9D2B58081ADC16E200B08D53 /* ORSSerialPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORSSerialPort.h; path = ../../../../Source/ORSSerialPort.h; sourceTree = ""; }; 9D2B58091ADC16E200B08D53 /* ORSSerialPort.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORSSerialPort.m; path = ../../../../Source/ORSSerialPort.m; sourceTree = ""; }; 9D2B580A1ADC16E200B08D53 /* ORSSerialPortManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORSSerialPortManager.h; path = ../../../../Source/ORSSerialPortManager.h; sourceTree = ""; }; @@ -55,6 +58,8 @@ 9D2B58091ADC16E200B08D53 /* ORSSerialPort.m */, 9D2B580A1ADC16E200B08D53 /* ORSSerialPortManager.h */, 9D2B580B1ADC16E200B08D53 /* ORSSerialPortManager.m */, + 2788B8041BA05FFD0018C0E7 /* ORSSerialBuffer.h */, + 2788B8051BA05FFD0018C0E7 /* ORSSerialBuffer.m */, ); name = ORSSerialPort; sourceTree = ""; @@ -155,6 +160,7 @@ files = ( 9D2B580D1ADC16E200B08D53 /* ORSSerialPortManager.m in Sources */, 9DF0453E1678336E00DA0CDA /* main.m in Sources */, + 2788B8061BA05FFD0018C0E7 /* ORSSerialBuffer.m in Sources */, 9D2B580C1ADC16E200B08D53 /* ORSSerialPort.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Examples/CommandLineDemo/Swift/CommandLineDemo.xcodeproj/project.pbxproj b/Examples/CommandLineDemo/Swift/CommandLineDemo.xcodeproj/project.pbxproj index 6f1479e7..ed048f66 100644 --- a/Examples/CommandLineDemo/Swift/CommandLineDemo.xcodeproj/project.pbxproj +++ b/Examples/CommandLineDemo/Swift/CommandLineDemo.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 2720C0F11BA0612D00CC2BE3 /* ORSSerialBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 2720C0F01BA0612D00CC2BE3 /* ORSSerialBuffer.m */; settings = {ASSET_TAGS = (); }; }; 9D2B58071ADC16B500B08D53 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D2B58061ADC16B500B08D53 /* main.swift */; }; 9D2B58141ADC170C00B08D53 /* ORSSerialPort.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2B58111ADC170C00B08D53 /* ORSSerialPort.m */; }; 9D2B58151ADC170C00B08D53 /* ORSSerialPortManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2B58131ADC170C00B08D53 /* ORSSerialPortManager.m */; }; @@ -27,6 +28,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 2720C0EF1BA0612D00CC2BE3 /* ORSSerialBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ORSSerialBuffer.h; path = ../../../../Source/ORSSerialBuffer.h; sourceTree = ""; }; + 2720C0F01BA0612D00CC2BE3 /* ORSSerialBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ORSSerialBuffer.m; path = ../../../../Source/ORSSerialBuffer.m; sourceTree = ""; }; 9D2B57FB1ADC165D00B08D53 /* CommandLineDemo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CommandLineDemo; sourceTree = BUILT_PRODUCTS_DIR; }; 9D2B58061ADC16B500B08D53 /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 9D2B580F1ADC170C00B08D53 /* CommandLineDemo-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CommandLineDemo-Bridging-Header.h"; sourceTree = ""; }; @@ -84,6 +87,8 @@ 9D2B58111ADC170C00B08D53 /* ORSSerialPort.m */, 9D2B58121ADC170C00B08D53 /* ORSSerialPortManager.h */, 9D2B58131ADC170C00B08D53 /* ORSSerialPortManager.m */, + 2720C0EF1BA0612D00CC2BE3 /* ORSSerialBuffer.h */, + 2720C0F01BA0612D00CC2BE3 /* ORSSerialBuffer.m */, 9DFF14871B94E396004B42B3 /* ORSSerialRequest.h */, 9DFF14881B94E396004B42B3 /* ORSSerialRequest.m */, 9DFF14841B94E38D004B42B3 /* ORSSerialPacketDescriptor.h */, @@ -152,6 +157,7 @@ files = ( 9D2B58151ADC170C00B08D53 /* ORSSerialPortManager.m in Sources */, 9DFF14861B94E38D004B42B3 /* ORSSerialPacketDescriptor.m in Sources */, + 2720C0F11BA0612D00CC2BE3 /* ORSSerialBuffer.m in Sources */, 9D2B58071ADC16B500B08D53 /* main.swift in Sources */, 9D2B58141ADC170C00B08D53 /* ORSSerialPort.m in Sources */, 9DFF14891B94E396004B42B3 /* ORSSerialRequest.m in Sources */, From cd37f259dc743e78b5f7e9e46aab561bb7409696 Mon Sep 17 00:00:00 2001 From: Michael Koukoullis Date: Wed, 9 Sep 2015 22:55:10 +1000 Subject: [PATCH 49/55] Update to swift print with terminator --- Examples/CommandLineDemo/Swift/Sources/main.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Examples/CommandLineDemo/Swift/Sources/main.swift b/Examples/CommandLineDemo/Swift/Sources/main.swift index 8ebd3fdd..6f6753b5 100644 --- a/Examples/CommandLineDemo/Swift/Sources/main.swift +++ b/Examples/CommandLineDemo/Swift/Sources/main.swift @@ -43,7 +43,7 @@ struct UserPrompter { } func printPrompt() { - print("\n> ", appendNewline: false) + print("\n> ", terminator: "") } func promptForSerialPort() { @@ -57,7 +57,7 @@ struct UserPrompter { } func promptForBaudRate() { - print("\nPlease enter a baud rate: ", appendNewline: false); + print("\nPlease enter a baud rate: ", terminator: ""); } } @@ -111,7 +111,7 @@ class StateMachine : NSObject, ORSSerialPortDelegate { selectionString = selectionString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) if let baudRate = Int(selectionString) { self.serialPort?.baudRate = baudRate - print("Baud rate set to \(baudRate)", appendNewline: false) + print("Baud rate set to \(baudRate)", terminator: "") return true } else { return false @@ -131,13 +131,13 @@ class StateMachine : NSObject, ORSSerialPortDelegate { switch self.currentState { case .WaitingForPortSelectionState(let availablePorts): if !setupAndOpenPortWithSelectionString(string, availablePorts: availablePorts) { - print("\nError: Invalid port selection.", appendNewline: false) + print("\nError: Invalid port selection.", terminator: "") prompter.promptForSerialPort() return } case .WaitingForBaudRateInputState: if !setBaudRateOnPortWithString(string) { - print("\nError: Invalid baud rate. Baud rate should consist only of numeric digits.", appendNewline: false); + print("\nError: Invalid baud rate. Baud rate should consist only of numeric digits.", terminator: "") prompter.promptForBaudRate(); return; } @@ -156,7 +156,7 @@ class StateMachine : NSObject, ORSSerialPortDelegate { func serialPort(serialPort: ORSSerialPort, didReceiveData data: NSData) { if let string = NSString(data: data, encoding: NSUTF8StringEncoding) { - print("\nReceived: \"\(string)\" \(data)", appendNewline: false) + print("\nReceived: \"\(string)\" \(data)", terminator: "") } prompter.printPrompt() } @@ -170,7 +170,7 @@ class StateMachine : NSObject, ORSSerialPortDelegate { } func serialPortWasOpened(serialPort: ORSSerialPort) { - print("Serial port \(serialPort) was opened", appendNewline: false) + print("Serial port \(serialPort) was opened", terminator: "") prompter.promptForBaudRate() currentState = .WaitingForBaudRateInputState } From 66b50123721979784a16cd8f626d935eb47bf8f0 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Sun, 13 Sep 2015 12:36:39 -0600 Subject: [PATCH 50/55] Added (convenience) initializer for creating ORSSerialPacketDescriptors for packets consisting of a fixed sequence of bytes. --- Source/ORSSerialPacketDescriptor.h | 18 ++++++++++++++++++ Source/ORSSerialPacketDescriptor.m | 11 +++++++++++ 2 files changed, 29 insertions(+) diff --git a/Source/ORSSerialPacketDescriptor.h b/Source/ORSSerialPacketDescriptor.h index f654de9b..d248c384 100644 --- a/Source/ORSSerialPacketDescriptor.h +++ b/Source/ORSSerialPacketDescriptor.h @@ -86,6 +86,18 @@ typedef BOOL(^ORSSerialPacketEvaluator)(NSData * __nullable inputData); userInfo:(nullable id)userInfo responseEvaluator:(ORSSerialPacketEvaluator)responseEvaluator NS_DESIGNATED_INITIALIZER; +/** + * Creates an initializes an ORSSerialPacketDescriptor instance using fixed packet data. + * + * This can be used to create a packet descriptor for packets which consist of a fixed sequence of data. + * + * @param packetData An NSData instance containing a fixed sequence of bytes making up a packet. + * @param userInfo An arbitrary userInfo object. May be nil. + * + * @return An initizliaized ORSSerialPacketDesciptor instance. + */ +- (instancetype)initWithPacketData:(NSData *)packetData userInfo:(nullable id)userInfo; + /** * Creates an initializes an ORSSerialPacketDescriptor instance using a prefix and/or suffix. * @@ -165,6 +177,12 @@ typedef BOOL(^ORSSerialPacketEvaluator)(NSData * __nullable inputData); */ - (BOOL)dataIsValidPacket:(nullable NSData *)packetData; +/** + * The fixed packetData for packets described by the receiver. Will be nil for packet + * descriptors not created using -initWithPacketData:userInfo: + */ +@property (nonatomic, strong, readonly, nullable) NSData *packetData; + /** * The prefix for packets described by the receiver. Will be nil for packet * descriptors not created using one of the prefix/suffix initializer methods. diff --git a/Source/ORSSerialPacketDescriptor.m b/Source/ORSSerialPacketDescriptor.m index 21d779d8..6ed95d3e 100644 --- a/Source/ORSSerialPacketDescriptor.m +++ b/Source/ORSSerialPacketDescriptor.m @@ -54,6 +54,17 @@ - (instancetype)initWithMaximumPacketLength:(NSUInteger)maxPacketLength return self; } +- (instancetype)initWithPacketData:(NSData *)packetData userInfo:(nullable id)userInfo +{ + self = [self initWithMaximumPacketLength:[packetData length] userInfo:userInfo responseEvaluator:^BOOL(NSData *inputData) { + return [inputData isEqualToData:packetData]; + }]; + if (self) { + _packetData = packetData; + } + return self; +} + - (instancetype)initWithPrefix:(NSData *)prefix suffix:(NSData *)suffix maximumPacketLength:(NSUInteger)maxPacketLength From 6b2257e91ee10a26e11e740f7b922a01ea3b2d1d Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Sat, 19 Sep 2015 11:03:29 -0600 Subject: [PATCH 51/55] Minor reordering of methods in ORSSerialPortDelegate. --- Source/ORSSerialPort.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Source/ORSSerialPort.h b/Source/ORSSerialPort.h index 4ad2c071..e571f430 100644 --- a/Source/ORSSerialPort.h +++ b/Source/ORSSerialPort.h @@ -592,15 +592,6 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)serialPort:(ORSSerialPort *)serialPort didReceiveData:(NSData *)data; -/** - * Called when a valid, complete response is received for a previously sent request. - * - * @param serialPort The `ORSSerialPort` instance representing the port that received `responseData`. - * @param responseData The An `NSData` instance containing the received response data. - * @param request The request to which the responseData is a respone. - */ -- (void)serialPort:(ORSSerialPort *)serialPort didReceiveResponse:(NSData *)responseData toRequest:(ORSSerialRequest *)request; - /** * Called when a valid, complete packet matching a descriptor installed with * -startListeningForPacketsMatchingDescriptor: is received. @@ -611,6 +602,15 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)serialPort:(ORSSerialPort *)serialPort didReceivePacket:(NSData *)packetData matchingDescriptor:(ORSSerialPacketDescriptor *)descriptor; +/** + * Called when a valid, complete response is received for a previously sent request. + * + * @param serialPort The `ORSSerialPort` instance representing the port that received `responseData`. + * @param responseData The An `NSData` instance containing the received response data. + * @param request The request to which the responseData is a respone. + */ +- (void)serialPort:(ORSSerialPort *)serialPort didReceiveResponse:(NSData *)responseData toRequest:(ORSSerialRequest *)request; + /** * Called when a the timeout interval for a previously sent request elapses without a valid * response having been received. From 0e386431df365e940ce526dfe5417c1959a18686 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 21 Sep 2015 11:53:59 -0600 Subject: [PATCH 52/55] Updated RequestResponseDemo readme. --- Examples/RequestResponseDemo/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/RequestResponseDemo/README.md b/Examples/RequestResponseDemo/README.md index 7e5e4b44..52f1851e 100644 --- a/Examples/RequestResponseDemo/README.md +++ b/Examples/RequestResponseDemo/README.md @@ -1,4 +1,4 @@ -The RequestResponseDemo app demonstrates the use of the ORSSerialPort request/response API (`ORSSerialRequest`, etc.). Code is available for an [Arduino Esplora](http://arduino.cc/en/Main/arduinoBoardEsplora) to implement exactly this protocol in this repository: https://github.com/armadsen/ArduinoRequestResponse. +The RequestResponseDemo app demonstrates the use of the ORSSerialPort request/response API (`ORSSerialRequest`, etc.). Code is available for an [Arduino Esplora](http://arduino.cc/en/Main/arduinoBoardEsplora) to act as the device this app is designed to communicate with. The Arduino Esplora code can be found in this repository: [https://github.com/armadsen/ArduinoRequestResponse](https://github.com/armadsen/ArduinoRequestResponse). Both Swift and Objective-C versions of this example application are included. The functionality is identical in both versions. From 5d59bfbbbed48e2b870102c334034fcc3132789c Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 21 Sep 2015 11:54:12 -0600 Subject: [PATCH 53/55] Added README for PacketParsingDemo project. --- Examples/PacketParsingDemo/README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 Examples/PacketParsingDemo/README.md diff --git a/Examples/PacketParsingDemo/README.md b/Examples/PacketParsingDemo/README.md new file mode 100644 index 00000000..b0a7f7c5 --- /dev/null +++ b/Examples/PacketParsingDemo/README.md @@ -0,0 +1,5 @@ +The PacketParsingDemo app demonstrates the use of the ORSSerialPort packet parsing API (`ORSSerialPacketDescriptor`, etc.). Code is available for an [Arduino Esplora](http://arduino.cc/en/Main/arduinoBoardEsplora) to act as the device this app is designed to communicate with. The Arduino Esplora code can be found in this repository: [https://github.com/armadsen/ArduinoPacketSend](https://github.com/armadsen/ArduinoPacketSend) . + +Both Swift and Objective-C versions of this example application are included. The functionality is identical in both versions. + +For more information about the packe tparsing API and this example project, please see the [Packet Parsing API documentation](https://github.com/armadsen/ORSSerialPort/wiki/Packet-Parsing-API). From 29ba26597347f538674e1469c7449279d3a5a7b3 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 21 Sep 2015 11:58:47 -0600 Subject: [PATCH 54/55] Updated README, including adding information about the packet parsing API. --- README.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 133da165..0f0e9619 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # ORSSerialPort -ORSSerialPort is a modern, easy-to-use Objective-C serial port library for OS X. It is useful for programmers writing Objective-C or Swift Mac apps that must communicate with external devices through a serial port (most commonly RS-232). Using ORSSerialPort to open a port and send data can be as simple as this: +ORSSerialPort is an easy-to-use Objective-C serial port library for OS X. It is useful for programmers writing Objective-C or Swift Mac apps that communicate with external devices through a serial port (most commonly RS-232). Using ORSSerialPort to open a port and send data can be as simple as this: ```objective-c ORSSerialPort *serialPort = [ORSSerialPort serialPortWithPath:@"/dev/cu.KeySerial1"]; @@ -25,9 +25,9 @@ ORSSerialPort is released under an MIT license, meaning you're free to use it in If you have any questions about, suggestions for, or contributions to ORSSerialPort, please [contact me](mailto:andrew@openreelsoftware.com). I'd also love to hear about any cool projects you're using it in. -This readme provides an overview of the ORSSerialPort library and is meant to provide enough information to get up and running quickly. You can read complete technical documentation for ORSSerialPort on [http://cocoadocs.org/docsets/ORSSerialPort/](http://cocoadocs.org/docsets/ORSSerialPort/). +This readme provides an overview of the ORSSerialPort library and is meant to provide enough information to get up and running quickly. You can read complete technical documentation for ORSSerialPort on [http://cocoadocs.org/docsets/ORSSerialPort/](http://cocoadocs.org/docsets/ORSSerialPort/). The [ORSSerialPort wiki](https://github.com/armadsen/ORSSerialPort/wiki) also contains detailed documentation. -The example code in this readme is in Objective-C. However, ORSSerialPort can also easily be used from Swift code. The Examples folder contains Swift versions of all three example projects. See the Example Projects section below for more information. +The example code in this readme is in Objective-C. However, ORSSerialPort can also easily be used from Swift code. The Examples folder contains Swift versions of all four example projects. See the Example Projects section below for more information. # How to Use ORSSerialPort @@ -81,9 +81,15 @@ To receive data, you can implement the `ORSSerialPortDelegate` protocol's `-seri For more information about ORSSerialPortManager, see the [Getting Started Guide](https://github.com/armadsen/ORSSerialPort/wiki/Getting-Started#orsserialportmanager), or read the documentation in [ORSSerialPortManager.h](https://github.com/armadsen/ORSSerialPort/blob/master/Source/ORSSerialPortManager.h). +### ORSSerialPacketDescriptor + +Incoming serial data is delivered to your application as it is received. A low level library like ORSSerialPort has no way of knowing anything about the structure and format of the data you're sending and receiving. For example, you may be expecting a complete packet of data, but receive callbacks for each byte. Normally, this requires you to maintain a buffer which you fill up with incoming data, only processing it when a complete packet has been received. In order to eliminate the need for manual management and buffering of incoming data, ORSSerialPort includes a packet parsing API. This is implemented by `ORSSerialPacketDescriptor` and associated methods on `ORSSerialPort`. + +For more information about ORSSerialPort's packet parsing API, see the [Packet Parsing API Guide](https://github.com/armadsen/ORSSerialPort/wiki/Packet-Parsing-API), read the documentation in [ORSSerialPacketDescriptor.h](https://github.com/armadsen/ORSSerialPort/blob/master/Source/ORSSerialPacketDescriptor.h), and see the [PacketParsingDemo](https://github.com/armadsen/ORSSerialPort/tree/master/Examples/PacketParsingDemo) example app. + ### ORSSerialRequest -Incoming serial data is delivered to your application as it is received. A low level library like ORSSerialPort has no way of knowing anything about the structure and format of the data you're sending and receiving. For example, you may be expecting a complete packet of data, but receive callbacks for each byte. Normally, this requires you to maintain a buffer which you fill up with incoming data, only processing it when a complete packet has been received. In order to eliminate the need for manual management and buffering of incoming data, ORSSerialPort includes a request/response API. This is implemented by ORSSerialRequest. +Often, applications will want to send a command to a device, then wait to receive a specific response before continuing. To ease implementing this kind of scenario, ORSSerialPort includes a request/response API. This is implemented by `ORSSerialRequest` and associated methods on `ORSSerialPort`. For more information about ORSSerialPort's request/response API, see the [Request/Response API Guide](https://github.com/armadsen/ORSSerialPort/wiki/Request-Response-API), read the documentation in [ORSSerialRequest.h](https://github.com/armadsen/ORSSerialPort/blob/master/Source/ORSSerialRequest.h), and see the [RequestResponseDemo](https://github.com/armadsen/ORSSerialPort/tree/master/Examples/RequestResponseDemo) example app. @@ -93,6 +99,7 @@ Included with ORSSerialPort is a folder called Examples, containing Xcode projec - [ORSSerialPortDemo](https://github.com/armadsen/ORSSerialPort/wiki/ORSSerialPortDemo) - Simple graphical serial terminal example app. This is the main ORSSerialPort example. - [CommandLineDemo](https://github.com/armadsen/ORSSerialPort/wiki/Command-Line-Demo) - Command line app example. +- [PacketParsingDemo](https://github.com/armadsen/ORSSerialPort/wiki/Packet-Parsing-API) - GUI app demonstrating the use of ORSSerialPacketDescriptor. - [RequestResponseDemo](https://github.com/armadsen/ORSSerialPort/wiki/Request-Response-API) - GUI app demonstrating the use of ORSSerialRequest. You can read more about these examples on the [ORSSerialPort wiki](https://github.com/armadsen/ORSSerialPort/wiki). From d24a2003b33d4419ddd84bdfd03fe2753f7c4d64 Mon Sep 17 00:00:00 2001 From: Andrew Madsen Date: Mon, 21 Sep 2015 12:22:14 -0600 Subject: [PATCH 55/55] Updated podspec. --- ORSSerialPort.podspec | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ORSSerialPort.podspec b/ORSSerialPort.podspec index c16f0303..0d2d8726 100644 --- a/ORSSerialPort.podspec +++ b/ORSSerialPort.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "ORSSerialPort" - s.version = "2.0" + s.version = "2.0.0" s.summary = "Easy to use serial port library for Objective-C and Swift Mac apps." s.description = <<-DESC @@ -62,7 +62,7 @@ Pod::Spec.new do |s| # Supports git, hg, bzr, svn and HTTP. # - s.source = { :git => "https://github.com/armadsen/ORSSerialPort.git", :tag => "2.0" } + s.source = { :git => "https://github.com/armadsen/ORSSerialPort.git", :tag => s.version.to_s } # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # @@ -74,6 +74,7 @@ Pod::Spec.new do |s| # s.source_files = "Source/**/*.{h,m}" + s.private_header_files = "Source/ORSSerialBuffer.h" # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # # @@ -95,7 +96,7 @@ Pod::Spec.new do |s| # the lib prefix of their name. # - # s.framework = "IOKit" + s.framework = 'IOKit' # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # # @@ -104,5 +105,6 @@ Pod::Spec.new do |s| # you can include multiple dependencies to ensure it works. s.requires_arc = true + s.module_name = 'ORSSerial' end