// // CommunicationProtocol.m // DUREX Vendor Control // // Created by Imanol Barba on 5/23/14. // Copyright (c) 2014 Emmoco. All rights reserved. // #import "CommunicationProtocol.h" @interface CommunicationProtocol () @property Boolean messageAvailableMobile; @property Boolean messageAvailableDevice; @end @implementation CommunicationProtocol + (id)sharedProtocol { static CommunicationProtocol *shared = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ shared = [[self alloc] init]; [shared setMessageAvailableDevice:FALSE]; [shared setMessageAvailableMobile:FALSE]; }); return shared; } -(void) readMessageAvailableMobile { [[EMConnectionManager sharedManager] readResource:@"messageAvailableMobile" onSuccess:^(id readValue) { [self setMessageAvailableMobile:[readValue intValue]]; if([self messageAvailableMobile]) { NSLog(@"[CommunicationProtocol.m]: messageAvailableMobile read: TRUE"); } else { NSLog(@"[CommunicationProtocol.m]: messageAvailableMobile read: FALSE"); } } onFail:^(NSError *error) { NSLog(@"[CommunicationProtocol.m]: %@",error); }]; } -(void) readMessageAvailableDevice { [[EMConnectionManager sharedManager] readResource:@"messageAvailableDevice" onSuccess:^(id readValue) { [self setMessageAvailableDevice:[readValue intValue]]; if([self messageAvailableDevice]) { NSLog(@"[CommunicationProtocol.m]: messageAvailableDevice read: TRUE"); } else { NSLog(@"[CommunicationProtocol.m]: messageAvailableDevice read: FALSE"); } } onFail:^(NSError *error) { NSLog(@"[CommunicationProtocol.m]: %@",error); }]; } -(Boolean) waitForMessageAvailableMobile: (Boolean) status { uint8_t retries = 0; [self readMessageAvailableMobile]; while([self messageAvailableMobile] != status) { [NSThread sleepForTimeInterval:5]; [self readMessageAvailableMobile]; if([self messageAvailableMobile] != status) { if(retries++ == MAX_RETRIES) { NSLog(@"[CommunicationProtocol.m]: Timeout while waiting for answer"); return FALSE; } } } return TRUE; } -(Boolean) waitForMessageAvailableDevice: (Boolean) status { uint8_t retries = 0; [self readMessageAvailableDevice]; while([self messageAvailableDevice] != status) { [NSThread sleepForTimeInterval:5]; [self readMessageAvailableDevice]; if([self messageAvailableDevice] != status) { if(retries++ == MAX_RETRIES) { NSLog(@"[CommunicationProtocol.m]: Timeout while waiting for answer"); return FALSE; } } } return TRUE; } -(NSString*) readMessage { __block uint8_t numPackets = 1, numBytes; //HACK! __block NSMutableString *message = [[NSMutableString alloc] init]; [message setString:@""]; //if([self waitForMessageAvailableDevice:TRUE]) if(1) //HACK! { [[EMConnectionManager sharedManager] readResource:@"numPackets" onSuccess:^(id readValue) { numPackets = (uint8_t) [readValue unsignedCharValue]; NSLog(@"[CommunicationProtocol.m]: numPackets read: %d",numPackets); } onFail:^(NSError *error) { NSLog(@"[CommunicationProtocol.m]: %@",error); numPackets = 0; }]; if(numPackets) { for(int i = 0; i < numPackets; i++) { //if([self waitForMessageAvailableDevice:TRUE]) if(1)//HACK! { [[EMConnectionManager sharedManager] readResource:@"numBytes" onSuccess:^(id readValue) { numBytes = (uint8_t) [readValue unsignedCharValue]; NSLog(@"[CommunicationProtocol.m]: numBytes read: %d",numBytes); } onFail:^(NSError *error) { NSLog(@"[CommunicationProtocol.m]: %@",error); numBytes = 0; }]; if(numBytes) { [[EMConnectionManager sharedManager] readResource:@"data" onSuccess:^(id readValue) { [message appendString: readValue]; [message setString: [message substringToIndex:numBytes]]; NSLog(@"[CommunicationProtocol.m]: data read: %@",message); } onFail:^(NSError *error) { NSLog(@"[CommunicationProtocol.m]: %@",error); }]; } [[EMConnectionManager sharedManager] writeValue:@"0" toResource:@"messageAvailableDevice" onSuccess:^ { NSLog(@"[CommunicationProtocol.m]: messageAvailableDevice set to FALSE"); NSLog(@"[CommunicationProtocol.m]: packet read"); } onFail:^(NSError *error) { NSLog(@"[CommunicationProtocol.m]: %@",error); } ]; } else { NSLog(@"[CommunicationProtocol.m]: Error, resetting message"); [message setString:@""]; } } } } NSLog(@"[CommunicationProtocol.m]: Message received: %@",message); return message; } -(Boolean) writeMessage: (NSString*) message { unsigned long remainingBytes = [message length]; uint8_t numBytes, current_index = 0; __block Boolean status = TRUE; //HACK __block Boolean blockCompleted = TRUE; //HACK! [[EMConnectionManager sharedManager] writeValue:@"0" toResource:@"messageAvailableMobile" onSuccess:^ { status = TRUE; NSLog(@"[CommunicationProtocol.m]: messageAvailableMobile set to FALSE"); blockCompleted = TRUE; } onFail:^(NSError *error) { NSLog(@"[CommunicationProtocol.m]: %@",error); status = FALSE; blockCompleted = TRUE; }]; while(blockCompleted != TRUE) { [NSThread sleepForTimeInterval:1]; } NSLog(@"[CommunicationProtocol.m]: messageAvailableMobile write block completed"); blockCompleted = FALSE; [[EMConnectionManager sharedManager] writeValue:[NSNumber numberWithUnsignedChar:(unsigned char)([message length]/MAX_STRING_LENGTH)+1] toResource:@"numPackets" onSuccess:^ { status = TRUE; NSLog(@"[CommunicationProtocol.m]: numPackets set to %u",([message length]/MAX_STRING_LENGTH) + 1); } onFail:^(NSError *error) { NSLog(@"[CommunicationProtocol.m]: %@",error); status = FALSE; } ]; NSLog(@"[CommunicationProtocol.m]: status is: %d",status); if(status != FALSE) { NSLog(@"[CommunicationProtocol.m]: Carrying on after numPackets..."); while(remainingBytes) { if(![self waitForMessageAvailableMobile:FALSE]) { status = FALSE; break; } NSLog(@"[CommunicationProtocol.m]: Device is ready for next packet"); if(remainingBytes > MAX_STRING_LENGTH) { numBytes = MAX_STRING_LENGTH; remainingBytes -= MAX_STRING_LENGTH; } else { numBytes = remainingBytes; remainingBytes = 0; } [[EMConnectionManager sharedManager] writeValue:[NSNumber numberWithUnsignedChar:(unsigned char)numBytes] toResource:@"numBytes" onSuccess:^ { NSLog(@"[CommunicationProtocol.m]: numBytes set to %d", numBytes); status = TRUE; } onFail:^(NSError *error) { NSLog(@"[CommunicationProtocol.m]: %@",error); status = FALSE; } ]; if(status != FALSE) { NSLog(@"[CommunicationProtocol.m]: Carrying on after numBytes..."); NSString *data = [message substringWithRange:NSMakeRange(current_index, numBytes)]; current_index += numBytes; [[EMConnectionManager sharedManager] writeValue:data toResource:@"data" onSuccess:^ { NSLog(@"[CommunicationProtocol.m]: data set to: %@",data); status = TRUE; } onFail:^(NSError *error) { NSLog(@"[CommunicationProtocol.m]: %@",error); status = FALSE; } ]; if(status != FALSE) { NSLog(@"[CommunicationProtocol.m]: Carrying on after data..."); [[EMConnectionManager sharedManager] writeValue:@"1" toResource:@"messageAvailableMobile" onSuccess:^ { status = TRUE; NSLog(@"[CommunicationProtocol.m]: messageAvailableMobile set to TRUE"); NSLog(@"[CommunicationProtocol.m]: Packet written"); } onFail:^(NSError *error) { NSLog(@"[CommunicationProtocol.m]: %@",error); status = FALSE; } ]; NSLog(@"[CommunicationProtocol.m]: Carrying on after messageAvailableMobile..."); } } } } if(![self waitForMessageAvailableMobile:FALSE]) { NSLog(@"[CommunicationProtocol.m]: Device has processed the message"); } return status; } -(Boolean) establishConnection { NSLog(@"[CommunicationProtocol.m]: Establishing connection..."); if([self writeMessage:@"Hello"]) { NSLog(@"[CommunicationProtocol.m]: Hello sent"); NSString *answer = [self readMessage]; NSLog(@"[CommunicationProtocol.m]: Answer received"); if([answer isEqualToString:@"Hello"]) { NSLog(@"[CommunicationProtocol.m]: Connection established"); return TRUE; } } NSLog(@"[CommunicationProtocol.m]: Error while establishing connection"); return TRUE; //HACK! } -(Boolean) updateTime: (NSDateComponents*) date { NSMutableString *command = [NSMutableString stringWithFormat: @"A5"]; NSInteger year = [date year]; year = year - (year/100)*100; [command appendString:[NSString stringWithFormat:@"%02ld",(long)year]]; [command appendString:[NSString stringWithFormat:@"%02ld%02ld%02ld%02ld%02ld",(long)[date month],(long)[date day],(long)[date hour],(long)[date minute],(long)[date second]]]; [self writeMessage:command]; NSString *answer = [self readMessage]; if([answer isEqualToString:@"P51"]) { return TRUE; } return FALSE; } -(Boolean) updatePrice: (uint8_t) channel : (uint8_t) product : (uint8_t) eur : (uint8_t) cents { NSMutableString *command = [NSMutableString stringWithFormat: @"A6%01d%01d%02d%02d",channel,product,eur,cents]; [self writeMessage:command]; NSString *answer = [self readMessage]; if([answer isEqualToString:@"P61"]) { return TRUE; } return FALSE; } -(Boolean) updateProductName: (uint8_t) channel : (uint8_t) product : (NSString*) name { if([name length] > MAX_PRODUCT_NAME_LENGTH) { name = [name substringToIndex:MAX_PRODUCT_NAME_LENGTH-1]; } NSMutableString *command = [NSMutableString stringWithFormat: @"A7%01d%01d%@",channel,product,name]; [self writeMessage:command]; NSString *answer = [self readMessage]; if([answer isEqualToString:@"P71"]) { return TRUE; } return FALSE; } -(NSString*) readSensorData { NSString *command = @"A4"; [self writeMessage:command]; //NSString *answer = [self readMessage]; NSMutableString *answer = [[NSMutableString alloc]initWithString:@"P400015000150001500000001001003005002000001002"]; for(int i = 0; i < 4; i++) { [answer appendString:@"0"]; [answer appendString:@"1"]; } for(int i = 0; i < 12; i++) { [answer appendString:@"0"]; [answer appendString:@"0"]; } [answer appendString:@"0"]; [answer appendString:@"0"]; if([answer length] > 1 && [[answer substringToIndex:2]isEqualToString:@"P4"]) { NSLog(@"[CommunicationProtocol.m]: sensorStatus returned: %@",answer); return answer; } return nil; } -(NSString*) readSalesLog : (NSDateComponents*) start : (NSDateComponents*) end { NSMutableString *startDate = [NSMutableString stringWithString:@""]; NSMutableString *endDate = [NSMutableString stringWithString:@""]; NSMutableString *command = [NSMutableString stringWithString:@"A2"]; if(start == nil) { [startDate setString:@""]; } else { NSInteger year = [start year]; year = year - (year/100)*100; [startDate appendString:[NSString stringWithFormat:@"%02ld",(long)year]]; [startDate appendString:[NSString stringWithFormat:@"%02ld%02ld%02ld%02ld",(long)[start month],(long)[start day],(long)[start hour],(long)[start minute]]]; } if(end == nil) { [endDate setString:@""]; } else { NSInteger year = [end year]; year = year - (year/100)*100; [endDate appendString:[NSString stringWithFormat:@"%02ld",(long)year]]; [endDate appendString:[NSString stringWithFormat:@"%02ld%02ld%02ld%02ld",(long)[end month],(long)[end day],(long)[end hour],(long)[end minute]]]; } [command appendString:startDate]; [command appendString:@"-"]; [command appendString:endDate]; [self writeMessage:command]; //NSString *answer = [self readMessage]; NSMutableString *answer = [[NSMutableString alloc]initWithString:@"P21408161036000001000000110450000001P21409012216000100000000220900000100P21409032307000000010502330800000000P21409070540000000020000440350000001P2P2"]; if([answer length] > 1 && [[answer substringToIndex:2]isEqualToString:@"P2"]) { NSLog(@"[CommunicationProtocol.m]: saleLog returned: %@",answer); return answer; } return nil; } @end