| /*  | 
|  * Copyright Cypress Semiconductor Corporation, 2014-2015 All rights reserved.  | 
|  *  | 
|  * This software, associated documentation and materials ("Software") is  | 
|  * owned by Cypress Semiconductor Corporation ("Cypress") and is  | 
|  * protected by and subject to worldwide patent protection (UnitedStates and foreign), United States copyright laws and international  | 
|  * treaty provisions. Therefore, unless otherwise specified in a separate license agreement between you and Cypress, this Software  | 
|  * must be treated like any other copyrighted material. Reproduction,  | 
|  * modification, translation, compilation, or representation of this  | 
|  * Software in any other form (e.g., paper, magnetic, optical, silicon)  | 
|  * is prohibited without Cypress's express written permission.  | 
|  *  | 
|  * Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO WARRANTY OF ANY  | 
|  * KIND, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,  | 
|  * NONINFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS  | 
|  * FOR A PARTICULAR PURPOSE. Cypress reserves the right to make changes  | 
|  * to the Software without notice. Cypress does not assume any liability  | 
|  * arising out of the application or use of Software or any product or  | 
|  * circuit described in the Software. Cypress does not authorize its  | 
|  * products for use as critical components in any products where a  | 
|  * malfunction or failure may reasonably be expected to result in  | 
|  * significant injury or death ("High Risk Product"). By including  | 
|  * Cypress's product in a High Risk Product, the manufacturer of such  | 
|  * system or application assumes all risk of such use and in doing so  | 
|  * indemnifies Cypress against all liability.  | 
|  *  | 
|  * Use of this Software may be limited by and subject to the applicable  | 
|  * Cypress software license agreement.  | 
|  *  | 
|  *  | 
|  */  | 
|   | 
| #import "GlucoseModel.h"  | 
| #import "CBMoralManager.h"  | 
| #import "Constants.h"  | 
|   | 
| /*!  | 
|  *  @class GlucoseModel  | 
|  *  | 
|  *  @discussion Class to handle the glucose service related operations  | 
|  *  | 
|  */  | 
|   | 
| @interface GlucoseModel () <cbCharacteristicManagerDelegate>  | 
|   | 
| @end  | 
|   | 
| @implementation GlucoseModel  | 
| {  | 
|     void(^cbCharacteristicHandler)(BOOL success, NSError *error);  | 
|     void(^cbcharacteristicDiscoverHandler)(BOOL success, NSError *error);  | 
|       | 
|     CBCharacteristic *glucoseMeasurementChar;  | 
| }  | 
|   | 
|   | 
| /*!  | 
|  *  @method startDiscoverChar:  | 
|  *  | 
|  *  @discussion Discovers the specified characteristics of a service..  | 
|  */  | 
| -(void)startDiscoverChar:(void (^) (BOOL success, NSError *error))handler  | 
| {  | 
|     cbcharacteristicDiscoverHandler = handler;  | 
|       | 
|     [[CBMoralManager sharedManager] setCbCharacteristicDelegate:self];  | 
|     [[[CBMoralManager sharedManager] myPeripheral] discoverCharacteristics:nil forService:[[CBMoralManager sharedManager] myService]];  | 
| }  | 
|   | 
| /*!  | 
|  *  @method updateCharacteristicWithHandler:  | 
|  *  | 
|  *  @discussion Sets notifications or indications for the value of a specified characteristic.  | 
|  */  | 
|   | 
| -(void)updateCharacteristicWithHandler:(void (^) (BOOL success, NSError *error))handler  | 
| {  | 
|     cbCharacteristicHandler = handler;  | 
|       | 
|     if (glucoseMeasurementChar)  | 
|     {  | 
|         [Utilities logDataWithService:[ResourceHandler getServiceNameForUUID:GLUCOSE_SERVICE_UUID] characteristic:[ResourceHandler getCharacteristicNameForUUID:GLUCOSE_MEASUREMENT_CHARACTERISTIC_UUID] descriptor:nil operation:START_NOTIFY];  | 
|   | 
|         [[[CBMoralManager sharedManager] myPeripheral] setNotifyValue:YES forCharacteristic:glucoseMeasurementChar];  | 
|     }  | 
| }  | 
|   | 
| /*!  | 
|  *  @method stopUpdate  | 
|  *  | 
|  *  @discussion Stop notifications or indications for the value of a specified characteristic.  | 
|  */  | 
|   | 
|   | 
| -(void) stopUpdate  | 
| {  | 
|     if (glucoseMeasurementChar)  | 
|     {  | 
|         if (glucoseMeasurementChar.isNotifying)  | 
|         {  | 
|             [Utilities logDataWithService:[ResourceHandler getServiceNameForUUID:GLUCOSE_SERVICE_UUID] characteristic:[ResourceHandler getCharacteristicNameForUUID:GLUCOSE_MEASUREMENT_CHARACTERISTIC_UUID] descriptor:nil operation:STOP_NOTIFY];  | 
|             [[[CBMoralManager sharedManager] myPeripheral] setNotifyValue:NO forCharacteristic:glucoseMeasurementChar];  | 
|         }  | 
|     }  | 
| }  | 
|   | 
|   | 
|   | 
|   | 
| #pragma mark - CBCharacteristicManager delegate  | 
|   | 
| /*!  | 
|  *  @method peripheral: didDiscoverCharacteristicsForService: error:  | 
|  *  | 
|  *  @discussion Method invoked when characteristics are discovered for a service  | 
|  *  | 
|  */  | 
|   | 
| -(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error  | 
| {  | 
|     if ([service.UUID isEqual:GLUCOSE_SERVICE_UUID])  | 
|     {  | 
|         for (CBCharacteristic *aChar in service.characteristics)  | 
|         {  | 
|             // Check for the required characteristic  | 
|             if ([aChar.UUID isEqual:GLUCOSE_MEASUREMENT_CHARACTERISTIC_UUID])  | 
|             {  | 
|                 glucoseMeasurementChar = aChar;  | 
|                 cbcharacteristicDiscoverHandler(YES,nil);  | 
|             }  | 
|         }  | 
|     }  | 
|     else  | 
|     {  | 
|         cbcharacteristicDiscoverHandler(NO,error);  | 
|     }  | 
| }  | 
|   | 
| /*!  | 
|  *  @method peripheral: didUpdateValueForCharacteristic: error:  | 
|  *  | 
|  *  @discussion Method invoked when the characteristic value changes  | 
|  *  | 
|  */  | 
|   | 
| -(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error  | 
| {  | 
|     if ([characteristic.UUID isEqual:GLUCOSE_MEASUREMENT_CHARACTERISTIC_UUID])  | 
|     {  | 
|         if (error == nil)  | 
|         {  | 
|             [self getGlucoseData:characteristic];  | 
|             cbCharacteristicHandler(YES,nil);  | 
|         }  | 
|         else  | 
|         {  | 
|             cbCharacteristicHandler(NO,error);  | 
|         }  | 
|     }  | 
| }  | 
|   | 
| /*!  | 
|  *  @method getGlucoseData:  | 
|  *  | 
|  *  @discussion  Instance method to parse the data received from the peripheral  | 
|  */  | 
|   | 
| -(void) getGlucoseData:(CBCharacteristic *)characteristic  | 
| {  | 
|     NSData *charData = [characteristic value];  | 
|     uint8_t *dataPointer = (uint8_t *)[charData bytes];  | 
|     uint8_t flags = dataPointer[0];  | 
|       | 
|     if (flags & 0x01)  | 
|     {  | 
|         // Time stamp data is present  | 
|           | 
|         dataPointer+=2;  | 
|           | 
|         uint16_t timeStamp = (uint16_t)CFSwapInt16LittleToHost(*((uint16_t *) dataPointer));  | 
|         dataPointer+=2;  | 
|           | 
|         NSLog(@"timestamp = %hu",timeStamp);  | 
|     }  | 
|     // Checking whether Glucose concentration,type or sample location present  | 
|   | 
|     else if (flags & 0x02)  | 
|     {  | 
|         // Checking Glucose concentration unit  | 
|   | 
|         uint16_t concentrationValue;  | 
|           | 
|         if (!(flags & 0x04))  | 
|         {  | 
|             // Unit is kg/L  | 
|               | 
|             _concentrationUnitString = @"kg/L";  | 
|             concentrationValue = (uint16_t )CFSwapInt16LittleToHost(*((uint16_t *) dataPointer));  | 
|               | 
|             dataPointer +=4;  | 
|         }  | 
|         else  | 
|         {  | 
|             // Unit is mol/L  | 
|               | 
|             _concentrationUnitString = @"mol/L";  | 
|             dataPointer +=2;  | 
|             concentrationValue = (uint16_t )CFSwapInt16LittleToHost(*((uint16_t *) dataPointer));  | 
|             dataPointer +=2;  | 
|         }  | 
|           | 
|         _glucoseConcentrationValue = concentrationValue;  | 
|           | 
|         // Get type  | 
|           | 
|         uint8_t tempValue = *(uint8_t *)dataPointer;  | 
|         uint8_t typeValue = (tempValue >> 4) & 0x0F;  | 
|         _type = [self getTypeNameForValue:typeValue];  | 
|           | 
|         // Get sample location  | 
|           | 
|         uint8_t locationValue = tempValue & 0x0F;  | 
|         _sampleLocation = [self getSampleLocationForValue:locationValue];  | 
|           | 
|           | 
|         // Get date  | 
|          | 
|         dataPointer = (uint8_t *)[charData bytes];  | 
|         dataPointer+=3;  | 
|         uint16_t year = CFSwapInt16LittleToHost(*(uint16_t*)dataPointer); dataPointer += 2;  | 
|         uint8_t month = *(uint8_t*)dataPointer; dataPointer++;  | 
|         uint8_t day = *(uint8_t*)dataPointer; dataPointer++;  | 
|         uint8_t hour = *(uint8_t*)dataPointer; dataPointer++;  | 
|         uint8_t min = *(uint8_t*)dataPointer; dataPointer++;  | 
|         uint8_t sec = *(uint8_t*)dataPointer; dataPointer++;  | 
|           | 
|         NSString * dateString = [NSString stringWithFormat:@"%d %d %d %d %d %d", year, month, day, hour, min, sec];  | 
|           | 
|         NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];  | 
|         [dateFormat setDateFormat: @"yyyy MM dd HH mm ss"];  | 
|         NSDate* date = [dateFormat dateFromString:dateString];  | 
|           | 
|         /*EEE for day, yyyy for Year, dd for date, MM for month*/  | 
|           | 
|         [dateFormat setDateFormat:@"yyyy MMM dd"];  | 
|         NSString* dateFormattedString = [dateFormat stringFromDate:date];  | 
|           | 
|         [dateFormat setDateFormat:@"hh:mm:ss"];  | 
|         NSString* timeFormattedString = [dateFormat stringFromDate:date];  | 
|           | 
|           | 
|         if( dateFormattedString && timeFormattedString )  | 
|         {  | 
|             _timeString = [NSString stringWithFormat:@"%@ %@", dateFormattedString, timeFormattedString];  | 
|             NSLog(@"time string = %@",_timeString);  | 
|         }  | 
|           | 
|     }  | 
|       | 
|     [Utilities logDataWithService:[ResourceHandler getServiceNameForUUID:GLUCOSE_SERVICE_UUID] characteristic:[ResourceHandler getCharacteristicNameForUUID:GLUCOSE_MEASUREMENT_CHARACTERISTIC_UUID] descriptor:nil operation:[NSString stringWithFormat:@"%@%@ %@",NOTIFY_RESPONSE,DATA_SEPERATOR,[Utilities convertDataToLoggerFormat:charData]]];  | 
| }  | 
|   | 
|   | 
| /*!  | 
|  *  @method getTypeNameForValue:  | 
|  *  | 
|  *  @discussion  Instance method to get the Type Name  | 
|  */  | 
|   | 
| -(NSString *) getTypeNameForValue:(uint8_t)value  | 
| {  | 
|     NSString *typeName = nil;  | 
|       | 
|     switch (value)  | 
|     {  | 
|         case 0x00:  | 
|             typeName = @"Reserved for future use";  | 
|             break;  | 
|               | 
|         case 0x01:  | 
|             typeName = @"Capillary Whole blood";  | 
|             break;  | 
|         case 0x02:  | 
|             typeName = @"Capillary Plasma";  | 
|             break;  | 
|         case 0x03:  | 
|             typeName = @"Venous Whole blood";  | 
|             break;  | 
|         case 0x04:  | 
|             typeName = @"Venous Plasma";  | 
|             break;  | 
|         case 0x05:  | 
|             typeName = @"Arterial Whole blood";  | 
|             break;  | 
|         case 0x06:  | 
|             typeName = @"Arterial Plasma";  | 
|             break;  | 
|         case 0x07:  | 
|             typeName = @"Undetermined Whole blood";  | 
|             break;  | 
|         case 0x08:  | 
|             typeName = @"Undetermined Plasma";  | 
|             break;  | 
|         case 0x09:  | 
|             typeName = @"Interstitial Fluid (ISF)";  | 
|             break;  | 
|         case 0x0A:  | 
|             typeName = @"Control Solution";  | 
|             break;  | 
|         default:  | 
|             typeName = @"Reserved for future use";  | 
|             break;  | 
|     }  | 
|       | 
|     return typeName;  | 
| }  | 
|   | 
| /*!  | 
|  *  @method getSampleLocationForValue:  | 
|  *  | 
|  *  @discussion  Instance method to get the sample location  | 
|  */  | 
|   | 
| -(NSString *) getSampleLocationForValue:(uint8_t)value  | 
| {  | 
|     NSString *locationName = nil;  | 
|       | 
|     switch (value)  | 
|     {  | 
|         case 0x00:  | 
|             locationName = @"Reserved for future use";  | 
|             break;  | 
|         case 0x01:  | 
|             locationName = @"Finger";  | 
|             break;  | 
|         case 0x02:  | 
|             locationName = @"Alternate Site Test (AST)";  | 
|             break;  | 
|         case 0x03:  | 
|             locationName = @"Earlobe";  | 
|             break;  | 
|         case 0x04:  | 
|             locationName = @"Control solution";  | 
|             break;  | 
|         case 0x0F:  | 
|             locationName = @"Sample Location value not available";  | 
|             break;  | 
|           | 
|         default:  | 
|             locationName = @" Reserved for future use ";  | 
|             break;  | 
|     }  | 
|       | 
|     return locationName;  | 
| }  | 
|   | 
|   | 
| @end  |