-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDLClient.m
260 lines (219 loc) · 9.73 KB
/
DLClient.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
//
// DLClient.m
// PenguinSample
//
// Created on 11/3/14.
// Copyright (c) 2014 AT&T. All rights reserved.
//
#import "DLClient.h"
#import "DLDevice.h"
#import "DLeServiceConnection.h"
#import "URLHelpers.h"
#import "JSONHelpers.h"
#import "Constants.h"
@interface DLClient ()
// info from user
@property (nonatomic,strong) NSString *userId;
@property (nonatomic,strong) NSString *password;
// info from backend
@property (nonatomic,strong) NSString *authToken;
@property (nonatomic,strong) NSString *requestToken;
@property (nonatomic,strong) NSString *gatewayGUID;
@property (nonatomic,strong) NSArray *devices;
// other
@property (nonatomic,strong) DLeServiceConnection *eService;
@property (nonatomic,strong) NSMutableArray *eServiceMessages;
@end
@implementation DLClient
+ (instancetype)shared
{
static DLClient *sharedInstance = nil;
static dispatch_once_t DDASLLoggerOnceToken;
dispatch_once(&DDASLLoggerOnceToken, ^{
sharedInstance = [[[self class] alloc] init];
});
return sharedInstance;
}
- (id)init
{
self = [super init];
if (self) {
NSAssert(![kAppID isEqualToString:@"<ENTER APP_ID HERE>"],@"Please entter your app id in Constants.m before running the app");
[[NSNotificationCenter defaultCenter] addObserverForName:@"eServiceMessageReceived" object:nil queue:nil usingBlock:^(NSNotification *note) {
[self handleEServiceMessage:note.userInfo];
}];
}
return self;
}
- (void)authenticateWithUsername:(NSString*)username password:(NSString*)password completion:(void (^)(BOOL success))completion
{
NSAssert(completion != nil,@"Must have completion block");
// save login info so we can re-login when authToken expires
self.userId = username;
self.password = password;
//NSLog(username);
//NSLog(password);
// setup URL Request for authentication
NSString *url = [NSString stringWithFormat:@"%@/authtokens",baseURL];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
urlRequest.HTTPMethod = @"POST";
NSDictionary *postParams = @{@"userId":username,@"password":password,@"domain":@"DL",@"appKey":kAppID};
NSString *postParamString = [postParams contentsAsURLQueryString];
NSData *postParamData = [postParamString dataUsingEncoding:NSUTF8StringEncoding];
[urlRequest setHTTPBody:postParamData];
// start request for authentication
[NSURLConnection sendAsynchronousRequest:urlRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// handle response for authentication
if (connectionError) {
NSLog(@"Connection Error");
completion(NO);
return;
}
// gather auth info from response
NSDictionary *content = [JSONHelpers contentDictionaryFromJsonResponse:data];
if (!content) {
NSLog(@"No Content");
completion(NO);
return;
}
self.authToken = [content objectForKey:@"authToken"];
self.requestToken = [content objectForKey:@"requestToken"];
self.gatewayGUID = [[[content objectForKey:@"gateways"] objectAtIndex:0] objectForKey:@"id"];
completion(YES);
}];
}
- (void)performHTTPRequestWithEndpoint:(NSString *)endpoint params:(NSDictionary *)params httpMethod:(NSString *)httpMethod completionHandler:(void (^)(BOOL success, id content))completionHandler
{
NSAssert(completionHandler != nil,@"must have completion block");
NSAssert(self.gatewayGUID,@"must be logged in before making api calls");
// set up url with selected endpoint as well as the parameters passed in
NSString *url = [NSString stringWithFormat:@"%@%@/%@",baseURL,self.gatewayGUID,endpoint];
if (params) {
NSString *postParamString = [params contentsAsURLQueryString];
url = [NSString stringWithFormat:@"%@?%@",url,postParamString];
}
// create url request and set authentication related http header values
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
urlRequest.HTTPMethod = httpMethod;
[urlRequest addValue:self.authToken forHTTPHeaderField:@"authToken"];
[urlRequest addValue:self.requestToken forHTTPHeaderField:@"requestToken"];
[urlRequest addValue:kAppID forHTTPHeaderField:@"appKey"];
// start the http request
[NSURLConnection sendAsynchronousRequest:urlRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (connectionError) {
completionHandler(NO,nil);
return;
}
id content = [JSONHelpers contentFromJsonResponse:data];
completionHandler(YES,content);
}];
}
- (void)loadDevicesWithCompletion:(void (^)(BOOL success, NSArray *devices))completion
{
[self performHTTPRequestWithEndpoint:@"devices" params:nil httpMethod:@"GET" completionHandler:^(BOOL success, id content) {
if (!success || ![content isKindOfClass:[NSArray class]]) {
completion(NO,nil);
}
// convert each json device entry to a DLDevice object
NSArray *jsonDeviceList = content;
NSMutableArray *deviceList = [[NSMutableArray alloc] init];
for (NSDictionary *deviceDict in jsonDeviceList) {
[deviceList addObject:[[DLDevice alloc] initWithDeviceDict:deviceDict]];
}
self.devices = [deviceList copy];
if (completion) completion(YES,[deviceList copy]);
}];
}
- (void)loadProgramsWithCompletion:(void (^)(BOOL success, NSArray *programs))completion
{
[self performHTTPRequestWithEndpoint:@"programs" params:nil httpMethod:@"GET" completionHandler:^(BOOL success, id content) {
if (!success || ![content isKindOfClass:[NSArray class]]) {
completion(NO,nil);
}
if (completion) completion(YES,[content copy]);
}];
}
- (void)loadDevicesLogsForDeviceID:(NSString *)deviceID withCompletion:(void (^)(BOOL success, NSArray *deviceLogItems))completion
{
[self performHTTPRequestWithEndpoint:@"inbox" params:@{@"deviceGUID":deviceID} httpMethod:@"GET" completionHandler:^(BOOL success, id content) {
if (!success || ![content isKindOfClass:[NSArray class]]) {
completion(NO,nil);
}
if (completion) completion(YES,[content copy]);
}];
}
- (void)updateDeviceWithDeviceID:(NSString *)deviceID forAction:(NSString *)action withValue:(NSString *)value completionHandler:(void (^)(BOOL success, NSNumber *transactionID))completion
{
NSString *endpoint = [NSString stringWithFormat:@"devices/%@/%@/%@",deviceID,action,value];
[self performHTTPRequestWithEndpoint:endpoint params:nil httpMethod:@"POST" completionHandler:^(BOOL success, id content) {
if (content && [content isKindOfClass:[NSNumber class]]) {
completion(success,content);
}
else {
completion(success, nil);
}
}];
}
- (void)updateProgramActiveStatusForProgramID:(NSString *)programId withActiveStatus:(BOOL)active completionHandler:(void (^)(BOOL success))completion
{
NSString *action = (active)?@"activate":@"deactivate";
NSString *endpoint = [NSString stringWithFormat:@"programs/%@/%@",programId,action];
[self performHTTPRequestWithEndpoint:endpoint params:nil httpMethod:@"POST" completionHandler:^(BOOL success, id content) {
completion(success);
}];
}
- (void)runProgramWithID:(NSString *)programId completionHandler:(void (^)(BOOL success))completion
{
NSString *endpoint = [NSString stringWithFormat:@"programs/%@/run",programId];
[self performHTTPRequestWithEndpoint:endpoint params:nil httpMethod:@"POST" completionHandler:^(BOOL success, id content) {
completion(success);
}];
}
- (void)startEServiceWithCompletion:(void (^)(BOOL success))completion
{
// make sure we already logged in
NSAssert(self.gatewayGUID, @"must be logged in before staring eService");
// if we already have an eService, shut it down before we start a new one
if (self.eService) {
[self.eService close];
self.eService = nil;
}
// create and connect new eService
self.eService = [[DLeServiceConnection alloc] initWithGatewayGuid:self.gatewayGUID];
[self.eService connectWithCompletionHandler:^(BOOL success) {
completion(success);
}];
}
- (DLDevice *)deviceWithID:(NSString *)deviceID
{
__block DLDevice *foundDevice = nil;
[self.devices enumerateObjectsUsingBlock:^(DLDevice *device, NSUInteger idx, BOOL *stop) {
if ([device.deviceGuid isEqualToString:deviceID]) {
foundDevice = device;
*stop = YES;
}
}];
return foundDevice;
}
#pragma mark - eService delegate methods
- (void)handleEServiceMessage:(NSDictionary *)message
{
if (!self.eServiceMessages) {
self.eServiceMessages = [[NSMutableArray alloc] init];
}
// add to our list of messages (we're only keeping these to be able to display in the eservice log, otherwise they can be discarded after they are used)
[self.eServiceMessages addObject:message];
NSDictionary *jsonMessage = message[@"message"];
// if the messsage is of type "device", find and update the device record
if ([jsonMessage[@"type"] isEqualToString:@"device"]) {
DLDevice *device = [self deviceWithID:jsonMessage[@"dev"]];
if (device) {
[device updateWithMessage:jsonMessage];
[[NSNotificationCenter defaultCenter] postNotificationName:@"DeviceUpdated" object:nil userInfo:@{@"device":device}];
}
else {
NSLog(@"got a device message but didn't find the device... message = %@",message);
}
}
}
@end