From 55d7ec62bad244c6d3a07a388912449e32299ff8 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 6 Dec 2012 22:20:21 +0200 Subject: [PATCH] Hysteresis feature Let the user specify how many sequential detections of "in range" or "out of range" occur before executing a command. Specifically, this should help prevent the app from flipping into "out of range" mode if the user's Bluetooth device happens to be in a pocket or experiencing some other temporary out of range condition. Preferences Window: Allow user to specify number of sequential detections of in or out of range before executing the user specified command. ProximityAppController - Set and load values for in range and out of range detection count. ProximityBluetoothMonitor - Count number of sequential detections of the same state until user specified threshold is cleared and then call foundDevice or lostDevice. README.md - Update version to 1.8 --- English.lproj/MainMenu.xib | 293 ++++++++++++++++++++++------ Info.plist | 14 +- Proximity.xcodeproj/project.pbxproj | 6 +- ProximityAppController.h | 2 + ProximityAppController.m | 20 ++ ProximityBluetoothMonitor.h | 5 + ProximityBluetoothMonitor.m | 53 ++++- README.md | 7 +- 8 files changed, 326 insertions(+), 74 deletions(-) diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib index 22cd8a0..b04193f 100644 --- a/English.lproj/MainMenu.xib +++ b/English.lproj/MainMenu.xib @@ -2,13 +2,13 @@ 1050 - 12A269 - 2829 - 1187 - 624.00 + 12C60 + 2844 + 1187.34 + 625.00 com.apple.InterfaceBuilder.CocoaPlugin - 2829 + 2844 YES @@ -195,7 +195,7 @@ 3 2 - {{335, 320}, {480, 492}} + {{335, 320}, {517, 482}} 1946157056 Proximity Preferences NSWindow @@ -266,13 +266,13 @@ NO - {{1, 1}, {412, 49}} + {{1, 1}, {449, 49}} - {{15, 57}, {414, 51}} + {{15, 54}, {451, 51}} @@ -281,7 +281,7 @@ 67108864 0 Box - + LucidaGrande 11 3100 @@ -309,7 +309,7 @@ 268 - {{18, 11}, {126, 19}} + {{18, 8}, {126, 19}} @@ -336,7 +336,7 @@ 268 - {{326, 11}, {100, 19}} + {{363, 7}, {100, 19}} @@ -359,7 +359,7 @@ 1292 - {{152, 13}, {16, 16}} + {{152, 10}, {16, 16}} @@ -370,7 +370,7 @@ 268 - {{208, 37}, {96, 21}} + {{208, 34}, {96, 21}} @@ -396,7 +396,7 @@ 268 - {{17, 39}, {194, 17}} + {{17, 36}, {194, 17}} @@ -417,7 +417,7 @@ 267 - {{308, 40}, {33, 14}} + {{308, 37}, {33, 14}} _NS:9 @@ -442,7 +442,7 @@ 267 - {{173, 39}, {33, 14}} + {{173, 36}, {33, 14}} _NS:9 @@ -461,13 +461,13 @@ NO - {{1, 1}, {444, 116}} + {{1, 1}, {481, 113}} - {{17, 222}, {446, 132}} + {{17, 222}, {483, 132}} @@ -476,7 +476,7 @@ 67108864 0 Bluetooth Device - + 3 @@ -502,7 +502,7 @@ 268 - {{16, 72}, {287, 18}} + {{16, 69}, {287, 18}} @@ -532,7 +532,7 @@ 268 - {{306, 71}, {51, 22}} + {{306, 68}, {51, 22}} @@ -557,7 +557,7 @@ 268 - {{359, 73}, {56, 17}} + {{359, 70}, {56, 17}} @@ -576,7 +576,7 @@ 268 - {{16, 32}, {207, 18}} + {{16, 29}, {207, 18}} @@ -601,7 +601,7 @@ 268 - {{229, 30}, {122, 19}} + {{229, 27}, {122, 19}} @@ -624,7 +624,7 @@ 268 - {{16, 52}, {412, 18}} + {{16, 49}, {412, 18}} @@ -649,7 +649,7 @@ 268 - {{16, 12}, {412, 18}} + {{16, 9}, {412, 18}} @@ -672,13 +672,13 @@ NO - {{1, 1}, {444, 98}} + {{1, 1}, {481, 95}} - {{17, 358}, {446, 114}} + {{17, 358}, {483, 114}} @@ -687,7 +687,7 @@ 67108864 0 Preferences - + 3 @@ -713,7 +713,7 @@ 268 - {{15, 78}, {156, 17}} + {{15, 75}, {156, 17}} @@ -732,7 +732,7 @@ 268 - {{18, 48}, {404, 22}} + {{18, 45}, {445, 22}} @@ -752,7 +752,7 @@ 268 - {{265, 76}, {44, 19}} + {{306, 72}, {44, 19}} @@ -775,7 +775,7 @@ 268 - {{317, 76}, {39, 19}} + {{358, 72}, {39, 19}} @@ -798,7 +798,7 @@ 268 - {{364, 76}, {58, 19}} + {{405, 72}, {58, 19}} @@ -821,7 +821,7 @@ 268 - {{15, 133}, {128, 17}} + {{15, 130}, {162, 17}} @@ -829,7 +829,7 @@ 68157504 272630784 - In Range Command + In Range Command after @@ -837,10 +837,46 @@ NO + + + 268 + {{214, 130}, {78, 17}} + + + YES + + 68157504 + 272630784 + detection(s) + + + + + + NO + + + + 268 + {{214, 75}, {78, 17}} + + + YES + + 68157504 + 272630784 + detection(s) + + + + + + NO + 268 - {{18, 103}, {404, 22}} + {{18, 100}, {445, 22}} @@ -860,7 +896,7 @@ 268 - {{265, 131}, {44, 19}} + {{306, 127}, {44, 19}} @@ -883,7 +919,7 @@ 268 - {{317, 131}, {39, 19}} + {{358, 127}, {39, 19}} @@ -906,7 +942,7 @@ 268 - {{364, 131}, {58, 19}} + {{405, 127}, {58, 19}} @@ -929,7 +965,7 @@ 267 - {{15, 14}, {410, 26}} + {{56, 11}, {410, 26}} @@ -949,14 +985,56 @@ LyBBcHAgYnVuZGxlcwpBcmd1bWVudCBwYXNzZWQ6ICAnaW5SYW5nZScgT1IgJ291dE9mUmFuZ2UnA NO + + + 268 + {{182, 128}, {27, 22}} + + + _NS:9 + YES + + -1804599231 + 272630784 + 1 + + _NS:9 + + YES + + + + NO + + + + 268 + {{182, 73}, {27, 22}} + + + _NS:9 + YES + + -1804599231 + 272630784 + 1 + + _NS:9 + + YES + + + + NO + - {{1, 1}, {444, 160}} + {{1, 1}, {481, 157}} - {{17, 42}, {446, 176}} + {{17, 42}, {483, 176}} @@ -965,7 +1043,7 @@ LyBBcHAgYnVuZGxlcwpBcmd1bWVudCBwYXNzZWQ6ICAnaW5SYW5nZScgT1IgJ291dE9mUmFuZ2UnA67108864 0 Actions - + 3 @@ -981,10 +1059,9 @@ LyBBcHAgYnVuZGxlcwpBcmd1bWVudCBwYXNzZWQ6ICAnaW5SYW5nZScgT1IgJ291dE9mUmFuZ2UnA 268 - {{306, 19}, {154, 19}} + {{343, 14}, {154, 19}} - YES -2080374784 @@ -1002,12 +1079,12 @@ LyBBcHAgYnVuZGxlcwpBcmd1bWVudCBwYXNzZWQ6ICAnaW5SYW5nZScgT1IgJ291dE9mUmFuZ2UnANO - {480, 492} + {517, 482} - {{0, 0}, {2560, 1418}} + {{0, 0}, {1680, 1028}} {10000000000000, 10000000000000} YES @@ -1247,6 +1324,22 @@ LyBBcHAgYnVuZGxlcwpBcmd1bWVudCBwYXNzZWQ6ICAnaW5SYW5nZScgT1IgJ291dE9mUmFuZ2UnA 642 + + + inRangeDetectionsCountInput + + + + 655 + + + + outOfRangeDetectionsCountInput + + + + 656 + @@ -1397,8 +1490,8 @@ LyBBcHAgYnVuZGxlcwpBcmd1bWVudCBwYXNzZWQ6ICAnaW5SYW5nZScgT1IgJ291dE9mUmFuZ2UnAYES - + @@ -1517,15 +1610,19 @@ LyBBcHAgYnVuZGxlcwpBcmd1bWVudCBwYXNzZWQ6ICAnaW5SYW5nZScgT1IgJ291dE9mUmFuZ2UnAYES - - - - + + + + + + + + @@ -1719,11 +1816,11 @@ LyBBcHAgYnVuZGxlcwpBcmd1bWVudCBwYXNzZWQ6ICAnaW5SYW5nZScgT1IgJ291dE9mUmFuZ2UnA - + @@ -1839,6 +1936,62 @@ LyBBcHAgYnVuZGxlcwpBcmd1bWVudCBwYXNzZWQ6ICAnaW5SYW5nZScgT1IgJ291dE9mUmFuZ2UnA + + 647 + + + YES + + + + + + 648 + + + + + 649 + + + YES + + + + + + 650 + + + + + 651 + + + YES + + + + + + 652 + + + + + 653 + + + YES + + + + + + 654 + + + @@ -1925,6 +2078,14 @@ LyBBcHAgYnVuZGxlcwpBcmd1bWVudCBwYXNzZWQ6ICAnaW5SYW5nZScgT1IgJ291dE9mUmFuZ2UnA644.IBPluginDependency 645.IBPluginDependency 646.IBPluginDependency + 647.IBPluginDependency + 648.IBPluginDependency + 649.IBPluginDependency + 650.IBPluginDependency + 651.IBPluginDependency + 652.IBPluginDependency + 653.IBPluginDependency + 654.IBPluginDependency YES @@ -2008,6 +2169,14 @@ LyBBcHAgYnVuZGxlcwpBcmd1bWVudCBwYXNzZWQ6ICAnaW5SYW5nZScgT1IgJ291dE9mUmFuZ2UnAcom.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin @@ -2022,7 +2191,7 @@ LyBBcHAgYnVuZGxlcwpBcmd1bWVudCBwYXNzZWQ6ICAnaW5SYW5nZScgT1IgJ291dE9mUmFuZ2UnA - 646 + 656 @@ -2138,8 +2307,10 @@ LyBBcHAgYnVuZGxlcwpBcmd1bWVudCBwYXNzZWQ6ICAnaW5SYW5nZScgT1IgJ291dE9mUmFuZ2UnAYES checkUpdatesOnStartup deviceName + inRangeDetectionsCountInput inRangeScriptPath monitoringEnabled + outOfRangeDetectionsCountInput outOfRangeScriptPath prefsWindow progressIndicator @@ -2153,8 +2324,10 @@ LyBBcHAgYnVuZGxlcwpBcmd1bWVudCBwYXNzZWQ6ICAnaW5SYW5nZScgT1IgJ291dE9mUmFuZ2UnANSButton NSTextField NSTextField + NSTextField NSButton NSTextField + NSTextField NSWindow NSProgressIndicator NSSlider @@ -2169,8 +2342,10 @@ LyBBcHAgYnVuZGxlcwpBcmd1bWVudCBwYXNzZWQ6ICAnaW5SYW5nZScgT1IgJ291dE9mUmFuZ2UnAYES checkUpdatesOnStartup deviceName + inRangeDetectionsCountInput inRangeScriptPath monitoringEnabled + outOfRangeDetectionsCountInput outOfRangeScriptPath prefsWindow progressIndicator @@ -2189,6 +2364,10 @@ LyBBcHAgYnVuZGxlcwpBcmd1bWVudCBwYXNzZWQ6ICAnaW5SYW5nZScgT1IgJ291dE9mUmFuZ2UnAdeviceName NSTextField + + inRangeDetectionsCountInput + NSTextField + inRangeScriptPath NSTextField @@ -2197,6 +2376,10 @@ LyBBcHAgYnVuZGxlcwpBcmd1bWVudCBwYXNzZWQ6ICAnaW5SYW5nZScgT1IgJ291dE9mUmFuZ2UnAmonitoringEnabled NSButton + + outOfRangeDetectionsCountInput + NSTextField + outOfRangeScriptPath NSTextField diff --git a/Info.plist b/Info.plist index d020f11..45ea292 100644 --- a/Info.plist +++ b/Info.plist @@ -6,6 +6,8 @@ English CFBundleExecutable ${EXECUTABLE_NAME} + CFBundleGetInfoString + 1.8 CFBundleIconFile AppIcon CFBundleIdentifier @@ -16,19 +18,17 @@ ${PRODUCT_NAME} CFBundlePackageType APPL + CFBundleShortVersionString + 1.8 CFBundleSignature ???? CFBundleVersion - 1.7 + 1.8 + LSUIElement + NSMainNibFile MainMenu NSPrincipalClass NSApplication - LSUIElement - - CFBundleShortVersionString - 1.7 - CFBundleGetInfoString - 1.7 diff --git a/Proximity.xcodeproj/project.pbxproj b/Proximity.xcodeproj/project.pbxproj index b63b39a..d41d5fe 100644 --- a/Proximity.xcodeproj/project.pbxproj +++ b/Proximity.xcodeproj/project.pbxproj @@ -377,13 +377,14 @@ buildSettings = { CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = Proximity.entitlements; - CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = Proximity_Prefix.pch; INFOPLIST_FILE = Info.plist; + MACOSX_DEPLOYMENT_TARGET = 10.7; PRODUCT_NAME = Proximity; }; name = Debug; @@ -393,11 +394,12 @@ buildSettings = { CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = Proximity.entitlements; - CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_IDENTITY = ""; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = Proximity_Prefix.pch; INFOPLIST_FILE = Info.plist; + MACOSX_DEPLOYMENT_TARGET = 10.7; PRODUCT_NAME = Proximity; }; name = Release; diff --git a/ProximityAppController.h b/ProximityAppController.h index 6f68413..9a52eca 100644 --- a/ProximityAppController.h +++ b/ProximityAppController.h @@ -34,6 +34,8 @@ typedef enum _BPStatus { IBOutlet NSButton *runScriptsOnStartup; IBOutlet NSTextField *timerInterval; IBOutlet NSSlider *requiredSignalStrength; + IBOutlet NSTextField *inRangeDetectionsCountInput; + IBOutlet NSTextField *outOfRangeDetectionsCountInput; } // UI methods diff --git a/ProximityAppController.m b/ProximityAppController.m index a985afe..b9f59fc 100644 --- a/ProximityAppController.m +++ b/ProximityAppController.m @@ -37,6 +37,8 @@ - (void)windowWillClose:(NSNotification *)aNotification if(monitoringEnabled.state == NSOnState && monitor.device) { monitor.requiredSignalStrength = requiredSignalStrength.integerValue; monitor.timeInterval = timerInterval.doubleValue; + monitor.inRangeDetectionCount = inRangeDetectionsCountInput.integerValue; + monitor.outOfRangeDetectionCount = outOfRangeDetectionsCountInput.integerValue; [monitor refresh]; [monitor start]; } else { @@ -174,6 +176,18 @@ - (void)userDefaultsLoad monitor.timeInterval = timerInterval.doubleValue; } + //minimum IN range detections to trigger script + if( [[defaults stringForKey:@"inRangeDetectionsCount"] length] > 0 ) { + [inRangeDetectionsCountInput setStringValue:[defaults stringForKey:@"inRangeDetectionsCount"]]; + monitor.inRangeDetectionCount = inRangeDetectionsCountInput.integerValue; + } + + //minimum OUT OF range detections to trigger script + if( [[defaults stringForKey:@"outOfRangeDetectionsCount"] length] > 0 ) { + [outOfRangeDetectionsCountInput setStringValue:[defaults stringForKey:@"outOfRangeDetectionsCount"]]; + monitor.outOfRangeDetectionCount = outOfRangeDetectionsCountInput.integerValue; + } + //require StrongSignal [requiredSignalStrength setIntegerValue:[defaults integerForKey:@"requiredSignalStrength"]]; monitor.requiredSignalStrength = requiredSignalStrength.integerValue; @@ -255,7 +269,13 @@ - (void)userDefaultsSave // Timer interval [defaults setObject:[timerInterval stringValue] forKey:@"timerInterval"]; + + //minimum IN range detections to trigger script + [defaults setObject:[inRangeDetectionsCountInput stringValue] forKey:@"inRangeDetectionsCount"]; + //minimum OUT OF range detections to trigger script + [defaults setObject:[outOfRangeDetectionsCountInput stringValue] forKey:@"outOfRangeDetectionsCount"]; + // In range script [defaults setURL:inRangeScriptURL forKey:@"inRangeScriptURL"]; diff --git a/ProximityBluetoothMonitor.h b/ProximityBluetoothMonitor.h index a68855b..8149e02 100644 --- a/ProximityBluetoothMonitor.h +++ b/ProximityBluetoothMonitor.h @@ -28,6 +28,8 @@ NS_ENUM(NSInteger, ProximityBluetoothStatus) { - (void)proximityBluetoothMonitor:(ProximityBluetoothMonitor*)monitor foundDevice:(IOBluetoothDevice*)device; - (void)proximityBluetoothMonitor:(ProximityBluetoothMonitor*)monitor lostDevice:(IOBluetoothDevice*)device; +- (void)setMenuIconInRange; +- (void)setMenuIconOutOfRange; @end @@ -35,11 +37,14 @@ NS_ENUM(NSInteger, ProximityBluetoothStatus) { @property(weak) id delegate; @property(nonatomic, assign) NSTimeInterval timeInterval; +@property(nonatomic, assign) NSInteger inRangeDetectionCount; +@property(nonatomic, assign) NSInteger outOfRangeDetectionCount; @property(assign) BOOL requiredSignalStrength; @property(retain) IOBluetoothDevice *device; // could be an array and statuses too @property(readonly) enum ProximityBluetoothStatus priorStatus; @property(readonly) enum ProximityBluetoothStatus status; +@property(readonly) enum ProximityBluetoothStatus iconStatus; - (void)start; - (void)stop; diff --git a/ProximityBluetoothMonitor.m b/ProximityBluetoothMonitor.m index 97a1f63..ca059f0 100644 --- a/ProximityBluetoothMonitor.m +++ b/ProximityBluetoothMonitor.m @@ -10,12 +10,15 @@ @implementation ProximityBluetoothMonitor { NSTimer *_timer; + NSInteger _changedStatusCounter; } +@synthesize inRangeDetectionCount, outOfRangeDetectionCount; + - (id)init { self = [super init]; if(self) { - _priorStatus = _status = ProximityBluetoothStatusUndefined; + _iconStatus = _priorStatus = _status = ProximityBluetoothStatusUndefined; _timeInterval = kDefaultPageTimeout; _requiredSignalStrength = NO; } @@ -24,6 +27,7 @@ - (id)init { - (void)start { [_timer invalidate]; + _changedStatusCounter = 0; _timer = [NSTimer scheduledTimerWithTimeInterval:_timeInterval target:self selector:@selector(handleTimer:) @@ -35,7 +39,7 @@ - (void)stop { [_timer invalidate]; _timer = nil; - _priorStatus = _status; + _iconStatus = _priorStatus = _status; _status = ProximityBluetoothStatusUndefined; } @@ -60,26 +64,59 @@ - (void)handleTimer:(NSTimer *)theTimer BOOL inRange = [self isInRange]; #ifdef DEBUG NSLog(@"BT device %@ inRange:%d",_device.name, inRange); + NSLog(@"Changed counter %ld", _changedStatusCounter); #endif _status = inRange ? ProximityBluetoothStatusInRange : ProximityBluetoothStatusOutOfRange; + + if(_status != _iconStatus) + { + if(_status == ProximityBluetoothStatusInRange) + { + [_delegate setMenuIconInRange]; + } + else + { + [_delegate setMenuIconOutOfRange]; + } + _iconStatus = _status; + } + if( inRange ) { if( _priorStatus != ProximityBluetoothStatusInRange ) { - _priorStatus = ProximityBluetoothStatusInRange; - [_delegate proximityBluetoothMonitor:self foundDevice:_device]; + _changedStatusCounter++; + if(_changedStatusCounter >= inRangeDetectionCount) + { + _changedStatusCounter = 0; + _priorStatus = ProximityBluetoothStatusInRange; + [_delegate proximityBluetoothMonitor:self foundDevice:_device]; #ifdef DEBUG - NSLog(@"-- found"); + NSLog(@"-- found"); #endif + } } + else + { + _changedStatusCounter = 0; + } } else { if( _priorStatus != ProximityBluetoothStatusOutOfRange ) { - _priorStatus = ProximityBluetoothStatusOutOfRange; - [_delegate proximityBluetoothMonitor:self lostDevice:_device]; + _changedStatusCounter++; + if(_changedStatusCounter >= outOfRangeDetectionCount) + { + _changedStatusCounter = 0; + _priorStatus = ProximityBluetoothStatusOutOfRange; + [_delegate proximityBluetoothMonitor:self lostDevice:_device]; #ifdef DEBUG - NSLog(@"-- lost"); + NSLog(@"-- lost"); #endif + } } + else + { + _changedStatusCounter = 0; + } } } diff --git a/README.md b/README.md index 4e11cde..c858110 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,16 @@ Proximity monitors the proximity of your mobile phone or other bluetooth device The intent of this project is for the source code to be critiqued by other developers in hopes of improving my Cocoa programming abilities, as well as my programming skills in general. ###Credits -This version is based on proximity 1.5 from reduxcomputing +This version is based on proximity 1.71 from [Daij-Djan](https://github.com/Daij-Djan/proximity) which in turn is based on proximity 1.5 from [reduxcomputing](https://github.com/revned/proximity/). +Including fixes from [fivemicro](https://github.com/fivemicro/proximity) ###Changes - +#####1.8 +* added the option to delay running the script for in/out of range only after a set number of detections have occured #####1.71 -added the option to require a good signal strength (defined as the Golden Cut in the BT4 Specification) +* added the option to require a good signal strength (defined as the Golden Cut in the BT4 Specification) #####1.7 * Added sandboxing & mac appstore compatible way to open the app at login