Skip to content

Commit

Permalink
add Pebble support for trips
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronpk committed Oct 27, 2015
1 parent 2a4a6ed commit f3cac8e
Show file tree
Hide file tree
Showing 9 changed files with 209 additions and 2 deletions.
14 changes: 14 additions & 0 deletions GPSLogger.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

/* Begin PBXBuildFile section */
0F444F0C1BD04A7E00106C2E /* TripModeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F444F0B1BD04A7E00106C2E /* TripModeViewController.m */; settings = {ASSET_TAGS = (); }; };
0FB85ABC1BE0048300F25126 /* PebbleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0FB85ABB1BE0048300F25126 /* PebbleManager.m */; settings = {ASSET_TAGS = (); }; };
0FB85ABE1BE0151300F25126 /* CoreBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0FB85ABD1BE0151300F25126 /* CoreBluetooth.framework */; };
0FB85AC01BE0151800F25126 /* ExternalAccessory.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0FB85ABF1BE0151800F25126 /* ExternalAccessory.framework */; };
0FFD31571BAB7A34009B3A03 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0FFD31561BAB7A34009B3A03 /* main.m */; };
0FFD315A1BAB7A34009B3A03 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0FFD31591BAB7A34009B3A03 /* AppDelegate.m */; };
0FFD315D1BAB7A34009B3A03 /* FirstViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0FFD315C1BAB7A34009B3A03 /* FirstViewController.m */; };
Expand All @@ -27,6 +30,10 @@
/* Begin PBXFileReference section */
0F444F0A1BD04A7E00106C2E /* TripModeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TripModeViewController.h; sourceTree = "<group>"; };
0F444F0B1BD04A7E00106C2E /* TripModeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TripModeViewController.m; sourceTree = "<group>"; };
0FB85ABA1BE0048300F25126 /* PebbleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PebbleManager.h; sourceTree = "<group>"; };
0FB85ABB1BE0048300F25126 /* PebbleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PebbleManager.m; sourceTree = "<group>"; };
0FB85ABD1BE0151300F25126 /* CoreBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBluetooth.framework; path = System/Library/Frameworks/CoreBluetooth.framework; sourceTree = SDKROOT; };
0FB85ABF1BE0151800F25126 /* ExternalAccessory.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ExternalAccessory.framework; path = System/Library/Frameworks/ExternalAccessory.framework; sourceTree = SDKROOT; };
0FFD31521BAB7A34009B3A03 /* GPSLogger.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GPSLogger.app; sourceTree = BUILT_PRODUCTS_DIR; };
0FFD31561BAB7A34009B3A03 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
0FFD31581BAB7A34009B3A03 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -57,6 +64,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0FB85AC01BE0151800F25126 /* ExternalAccessory.framework in Frameworks */,
0FB85ABE1BE0151300F25126 /* CoreBluetooth.framework in Frameworks */,
0FFD31781BAB7C7F009B3A03 /* CoreLocation.framework in Frameworks */,
0FFD31791BAB7C7F009B3A03 /* CoreMotion.framework in Frameworks */,
0FFD317A1BAB7C7F009B3A03 /* libsqlite3.tbd in Frameworks */,
Expand All @@ -71,6 +80,8 @@
0BE775F16162CE9DF6AE0775 /* Frameworks */ = {
isa = PBXGroup;
children = (
0FB85ABF1BE0151800F25126 /* ExternalAccessory.framework */,
0FB85ABD1BE0151300F25126 /* CoreBluetooth.framework */,
0FFD31741BAB7C7F009B3A03 /* CoreLocation.framework */,
0FFD31751BAB7C7F009B3A03 /* CoreMotion.framework */,
0FFD31761BAB7C7F009B3A03 /* libsqlite3.tbd */,
Expand Down Expand Up @@ -111,6 +122,8 @@
0FFD315F1BAB7A34009B3A03 /* SecondViewController.m */,
0FFD31711BAB7BEA009B3A03 /* GLManager.h */,
0FFD31721BAB7BEA009B3A03 /* GLManager.m */,
0FB85ABA1BE0048300F25126 /* PebbleManager.h */,
0FB85ABB1BE0048300F25126 /* PebbleManager.m */,
0FFD31611BAB7A34009B3A03 /* Main.storyboard */,
0FFD31641BAB7A34009B3A03 /* Assets.xcassets */,
0FFD31661BAB7A34009B3A03 /* LaunchScreen.storyboard */,
Expand Down Expand Up @@ -264,6 +277,7 @@
0FFD315D1BAB7A34009B3A03 /* FirstViewController.m in Sources */,
0FFD317F1BAB7CC7009B3A03 /* LOLDatabase.m in Sources */,
0FFD31571BAB7A34009B3A03 /* main.m in Sources */,
0FB85ABC1BE0048300F25126 /* PebbleManager.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
4 changes: 3 additions & 1 deletion GPSLogger/FirstViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#import "FirstViewController.h"
#import "GLManager.h"
#import "PebbleManager.h"

static NSString *const GLTripTrackingEnabledDefaultsName = @"GLTripTrackingEnabledDefaults";

Expand Down Expand Up @@ -215,7 +216,8 @@ - (void)updateTripState {
[self.tripStartStopButton setTitle:@"Stop" forState:UIControlStateNormal];
self.tripStartStopButton.backgroundColor = [UIColor colorWithRed:252.f/255.f green:109.f/255.f blue:111.f/255.f alpha:1];
self.tripDurationLabel.text = [FirstViewController timeFormatted:[GLManager sharedManager].currentTripDuration];
self.tripDistanceLabel.text = [NSString stringWithFormat:@"%0.2f", [GLManager sharedManager].currentTripDistance * 0.000621371];
self.tripDistanceLabel.text = [NSString stringWithFormat:@"%0.2f", [GLManager sharedManager].currentTripDistance * MetersToMiles];
[[PebbleManager sharedManager] refreshWatchface];
} else {
[self.tripStartStopButton setTitle:@"Start" forState:UIControlStateNormal];
self.tripStartStopButton.backgroundColor = [UIColor colorWithRed:106.f/255.f green:212.f/255.f blue:150.f/255.f alpha:1];
Expand Down
2 changes: 2 additions & 0 deletions GPSLogger/GLManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ static NSString *const GLTripModeTrain = @"train";
static NSString *const GLTripModePlane = @"plane";

static int const PointsPerBatch = 200;
static double const MetersToMiles = 0.000621371;

typedef enum {
kGLSignificantLocationDisabled,
Expand Down Expand Up @@ -89,6 +90,7 @@ typedef enum {
- (NSDate *)currentTripStart;
- (CLLocationDistance)currentTripDistance;
- (NSTimeInterval)currentTripDuration;
- (double)currentTripSpeed;
- (void)startTrip;
- (void)endTrip;

Expand Down
21 changes: 20 additions & 1 deletion GPSLogger/GLManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#import "AFHTTPSessionManager.h"
#import "LOLDatabase.h"
#import "FMDatabase.h"
#import "PebbleManager.h"

@interface GLManager()

Expand Down Expand Up @@ -238,6 +239,7 @@ - (void)restoreTrackingState {
if(self.tripInProgress) {
// If a trip is in progress, open the trip DB now
[self.tripdb open];
[[PebbleManager sharedManager] startWatchSession];
}
} else {
[self disableTracking];
Expand Down Expand Up @@ -409,11 +411,25 @@ - (CLLocationDistance)currentTripDistance {
return distance;
}

/**
* speed in miles per hour
*/
- (double)currentTripSpeed {
if(!self.tripInProgress) {
return -1;
}

double speedMS = self.currentTripDistance / self.currentTripDuration;
return speedMS * 2.23694;
}

- (void)startTrip {
if(self.tripInProgress) {
return;
}

[[PebbleManager sharedManager] startWatchSession];

NSDate *startDate = [NSDate date];
[[NSUserDefaults standardUserDefaults] setObject:startDate forKey:GLTripStartTimeDefaultsName];
[[NSUserDefaults standardUserDefaults] synchronize];
Expand All @@ -434,6 +450,8 @@ - (void)endTripFromAutopause:(BOOL)autopause {
return;
}

[[PebbleManager sharedManager] stopWatchSession];

[self.db accessCollection:GLLocationQueueName withBlock:^(id<LOLDatabaseAccessor> accessor) {
NSString *timestamp = [GLManager iso8601DateStringFromDate:[NSDate date]];
NSMutableDictionary *update = [NSMutableDictionary dictionaryWithDictionary:@{
Expand Down Expand Up @@ -669,7 +687,7 @@ - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray

NSLog(@"Received %d locations", (int)locations.count);

NSLog(@"%@", locations);
// NSLog(@"%@", locations);

// Queue the point in the database
[self.db accessCollection:GLLocationQueueName withBlock:^(id<LOLDatabaseAccessor> accessor) {
Expand Down Expand Up @@ -735,6 +753,7 @@ - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray
// If a trip is in progress, add to the trip's list too
if(self.tripInProgress && loc.horizontalAccuracy <= 100) {
[self.tripdb executeUpdate:@"INSERT INTO trips (timestamp, latitude, longitude) VALUES (?, ?, ?)", [NSNumber numberWithInt:[loc.timestamp timeIntervalSince1970]], [NSNumber numberWithDouble:loc.coordinate.latitude], [NSNumber numberWithDouble:loc.coordinate.longitude]];
[[PebbleManager sharedManager] refreshWatchface];
_currentTripHasNewData = YES;
}

Expand Down
7 changes: 7 additions & 0 deletions GPSLogger/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
<string>Please enable location services</string>
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-central</string>
<string>bluetooth-peripheral</string>
<string>external-accessory</string>
<string>fetch</string>
<string>location</string>
<string>remote-notification</string>
Expand All @@ -52,6 +55,10 @@
<false/>
</dict>
</dict>
<key>UISupportedExternalAccessoryProtocols</key>
<array>
<string>com.getpebble.public</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
Expand Down
22 changes: 22 additions & 0 deletions GPSLogger/PebbleManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// PebbleManager.h
// GPSLogger
//
// Created by Aaron Parecki on 10/27/15.
// Copyright © 2015 Aaron Parecki. All rights reserved.
//

#import <Foundation/Foundation.h>
@import PebbleKit;

@interface PebbleManager : NSObject <PBPebbleCentralDelegate>

+ (PebbleManager *)sharedManager;

- (void)startWatchSession;
- (void)stopWatchSession;

- (void)refreshWatchface;
- (void)updateTripInfoWithTime:(NSTimeInterval)time distance:(double)distance speed:(double)speed;

@end
137 changes: 137 additions & 0 deletions GPSLogger/PebbleManager.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
//
// PebbleManager.m
// GPSLogger
//
// Created by Aaron Parecki on 10/27/15.
// Copyright © 2015 Aaron Parecki. All rights reserved.
//

#import "PebbleManager.h"
#import "GLManager.h"

@implementation PebbleManager {
PBWatch *_targetWatch;
bool sportsEnabled;
}

+ (PebbleManager *)sharedManager {
static PebbleManager *_instance = nil;

@synchronized (self) {
if (_instance == nil) {
_instance = [[self alloc] init];

[[PBPebbleCentral defaultCentral] setDelegate:_instance];
// Configure our communications channel to target the sports app:
[[PBPebbleCentral defaultCentral] setAppUUID:PBSportsUUID];
[[PBPebbleCentral defaultCentral] run];
NSLog(@"Registered watches: %@", [[PBPebbleCentral defaultCentral] registeredWatches]);
}
}

return _instance;
}

- (void)startWatchSession {
NSLog(@"Pebble: Starting watch session with last connected watch: %@", [[PBPebbleCentral defaultCentral] lastConnectedWatch]);

[self setTargetWatch:[[PBPebbleCentral defaultCentral] lastConnectedWatch]];

// if(!sportsEnabled) return;
[self configureWatchSession];
}

- (void)configureWatchSession {
[_targetWatch sportsAppSetLabel:NO onSent:^(PBWatch *watch, NSError *error) {
if(error) {
NSLog(@"Pebble: Failed setting label to 'speed'");
} else {
NSLog(@"Pebble: Set label to 'speed'");
}
}];
[_targetWatch sportsAppSetMetric:NO onSent:^(PBWatch *watch, NSError *error) {
if(error) {
NSLog(@"Pebble: Failed to set units to imperial");
} else {
NSLog(@"Pebble: Set units to imperial");
}
}];
[_targetWatch sportsAppLaunch:^(PBWatch *watch, NSError *error) {
if(error) {
NSLog(@"Pebble: Failed sending launch command");
} else {
NSLog(@"Pebble: launch command sent");
}
}];
}

- (void)stopWatchSession {
if(!sportsEnabled) return;

[_targetWatch sportsAppKill:^(PBWatch *watch, NSError *error) {
if(error) {
NSLog(@"Pebble: Failed to kill session");
} else {
NSLog(@"Pebble: Successfully killed session");
}
}];
[_targetWatch releaseSharedSession];
}

- (void)refreshWatchface {
GLManager *m = [GLManager sharedManager];
[self updateTripInfoWithTime:m.currentTripDuration distance:m.currentTripDistance*MetersToMiles speed:m.currentTripSpeed];
}

- (void)updateTripInfoWithTime:(NSTimeInterval)time distance:(double)distance speed:(double)speed {
NSDictionary *pebbleDict = @{
PBSportsTimeKey: [PBSportsUpdate timeStringFromFloat:time],
PBSportsDistanceKey: [NSString stringWithFormat:@"%2.02f", distance],
PBSportsDataKey: [NSString stringWithFormat:@"%2.02f", speed]
};
[_targetWatch sportsAppUpdate:pebbleDict onSent:^(PBWatch *watch, NSError *error) {
if(error) {
NSLog(@"Pebble: Failed to send update");
} else {
}
}];
}


#pragma mark -

- (void)setTargetWatch:(PBWatch*)watch {
_targetWatch = watch;

// Test if the Pebble's firmware supports AppMessages / Sports:
[watch appMessagesGetIsSupported:^(PBWatch *watch, BOOL isAppMessagesSupported) {
if (isAppMessagesSupported) {
[[PBPebbleCentral defaultCentral] setAppUUID:PBSportsUUID];

NSLog(@"Pebble: %@ supports AppMessages :D", [watch name]);
sportsEnabled = YES;

[self configureWatchSession];
} else {

NSLog(@"Pebble: %@ does NOT support AppMessages :'(", [watch name]);
sportsEnabled = NO;
}
}];
}

#pragma mark - Pebble delegate

- (void)pebbleCentral:(PBPebbleCentral*)central watchDidConnect:(PBWatch*)watch isNew:(BOOL)isNew {
NSLog(@"Pebble: watch %@ connected", watch.name);
[self setTargetWatch:watch];
}

- (void)pebbleCentral:(PBPebbleCentral*)central watchDidDisconnect:(PBWatch*)watch {
NSLog(@"Pebble: Watch %@ disconnected", watch.name);
if (_targetWatch == watch || [watch isEqual:_targetWatch]) {
[self setTargetWatch:nil];
}
}

@end
1 change: 1 addition & 0 deletions Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
target 'GPSLogger' do
pod 'AFNetworking'
pod 'FMDB'
pod 'PebbleKit'
end

3 changes: 3 additions & 0 deletions Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@ PODS:
- FMDB/common (2.5)
- FMDB/standard (2.5):
- FMDB/common
- PebbleKit (3.0.0)

DEPENDENCIES:
- AFNetworking
- FMDB
- PebbleKit

SPEC CHECKSUMS:
AFNetworking: 79f7eb1a0fcfa7beb409332b2ca49afe9ce53b05
FMDB: 96e8f1bcc1329e269330f99770ad4285d9003e52
PebbleKit: 575087dc3e7ca1687929dd4903baabcf8f224cff

COCOAPODS: 0.38.2

0 comments on commit f3cac8e

Please sign in to comment.