iOS reading data from bluetooth 4.2 BLE device - ios

I'm trying to read data from a BLE device getting the data from delegate method
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error.
I am reading the data from CBCharacteristic object by using property value.
This returns the NSData.
I converted this NSData to Bytes.
How to Calculate the Weight from this Bytes data?. By this code i am not getting exact value.
Here is MyCode
/** This callback lets us know more data has arrived via notification on the characteristic
*/
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
NSLog(#"peripheral %#", peripheral);
NSLog(#"chacteristic %#", characteristic);
NSLog(#"chacteristic value %#", [characteristic value]);
Response Is Like This
peripheral <CBPeripheral: 0x15e469e90, identifier = A4B7E3A0-A988-02CF-3FAE-3B62056F465B, name = eBody-Fat-Scale, state = connected>
chacteristic <CBCharacteristic: 0x15e250980, UUID = 2A9D, properties = 0x20, value = <0ee803df 07010116 390901ff ff0000>, notifying = YES>
chacteristic value <0ee803df 07010116 390901ff ff0000>
if (error) {
NSLog(#"Error discovering characteristics: %# and %#", [error localizedDescription],[error localizedFailureReason]);
return;
}
int height;
self.targetPeripheral = peripheral;
NSData *tempData=characteristic.value;
NSString *stringFromData = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
NSString *str = [NSString stringWithUTF8String:[tempData bytes]];
NSLog(#"string data %#",str);
NSData *lol = characteristic.value;
NSLog(#"length %lu", (unsigned long)[lol length]);
Byte *byte = (Byte *)[lol bytes];
for(int i = 0;i<[lol length];i++)
{
NSLog(#"Receive byte:%d",byte[i]);
}
/* self.targetPeripheral = peripheral;
NSString *stringFromData = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
NSData *lol = characteristic.value;
Byte *byte = (Byte *)[lol bytes];
for(int i = 0;i<[lol length];i++)
{
NSLog(#"Received bytes:%d",byte[i]);
}*/
if(byte[0] == 0xfc)
{
Byte weightHigh = 0;
if(byte[1] >= 0xc0)
{
weightHigh = byte[1] - 0xc0;
}
else if(byte[1] >= 0x80)
{
weightHigh = byte[1] - 0x80;
}
else if(byte[1]>= 0x40)
{
weightHigh = byte[1] - 0x40;
}
float weightdata = (float)(weightHigh * 256 + byte[2])/10;
NSUserDefaults *prefers = [NSUserDefaults standardUserDefaults];
if([[prefers objectForKey:#"units"] isEqualToString:#"ft"])
{
NSString *weight = [[NSString alloc]initWithFormat:#"%.1f",[UnitParse convertKgToLb:weightdata]];
_weightDataLabel.text = [[NSString alloc] initWithFormat:#"%#",weight];
}
else
{
NSString *weight = [[NSString alloc]initWithFormat:#"%.1f",weightdata];
_weightDataLabel.text = [[NSString alloc] initWithFormat:#"%#",weight];
}
if(weightdata != _lastWeightData)
{
[RCCircleAnimation stopAnimation:_circleImageView.layer];
_lastWeightData = weightdata;
if(weightHigh * 256 + byte[2] == 0x3f*256+255)//overload
{
_weightDataLabel.text = #"overload";
}
else
{
NSThread* myThread1 = [[NSThread alloc] initWithTarget:self selector:#selector(mySoundPlayer)object:nil];
[myThread1 start];
NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];
[dic setObject:[[NSString alloc] initWithFormat:#"%2f",weightdata] forKey:#"Weight"];
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSString *datestr = [formatter stringFromDate:[NSDate date]];
[dic setObject:datestr forKey:#"TestTime"];
/* // First Time
NSUserDefaults *userDefaults ;
userDefaults = [NSUserDefaults standardUserDefaults];
if ([userDefaults objectForKey:#"UserWeightDataArray"] == nil)
{
[_valuesArray addObject:dic];
[userDefaults setObject:_valuesArray forKey:#"UserWeightDataArray"];
[userDefaults synchronize];
}
else
{
// second Time
[_dateArray addObject:dic];
_finalArray = [[_dateArray arrayByAddingObjectsFromArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"UserWeightDataArray"]] mutableCopy];
[userDefaults setObject:_finalArray forKey:#"UserWeightDataArray"];
[userDefaults synchronize];
}
*/
height = [[[MySingleton sharedSingleton].nowuserinfo valueForKey:#"Height"] intValue];
float bmi = weightdata/((height/100.0f)*(height/100.0f));
_bmiDataLabel.text = [[NSString alloc] initWithFormat:#"%.1f",bmi];
NSLog(#"_weightDataLabel.text %#", _weightDataLabel.text);
[self uploadDeviceInformationToServer:height weight:[[NSString alloc]initWithFormat:#"%.1f",weightdata]];
NSThread* myThread2 = [[NSThread alloc] initWithTarget:self selector:#selector(uploadWeightData:)object:dic];
[myThread2 start];
NSThread* myThread3 = [[NSThread alloc] initWithTarget:self selector:#selector(getAdviceByWeightData:)object:dic];
[myThread3 start];
NSThread* myThread = [[NSThread alloc] initWithTarget:self selector:#selector(sendCloseCmd)object:nil];
[myThread start];
}
}
}
else
{
_lastWeightData = 0;
Byte weightHigh = 0;
if(byte[1] >= 0xc0)
{
weightHigh = byte[1] - 0xc0;
}
else if(byte[1] >= 0x80)
{
weightHigh = byte[1] - 0x80;
}
else if(byte[1]>= 0x40)
{
weightHigh = byte[1] - 0x40;
}
float weightdata = (float)(weightHigh * 256 + byte[2])/10;
NSUserDefaults *prefers = [NSUserDefaults standardUserDefaults];
NSLog(#"data is %#",[prefers objectForKey:#"units"]);
if([[prefers objectForKey:#"units"] isEqualToString:#"ft"])
{
double temp=[UnitParse convertKgToLb:weightdata];
double temp1=[UnitParse convertLbToKg:weightdata];
NSString *weight = [[NSString alloc]initWithFormat:#"%.1f",temp];
NSLog(#"weight in if .... %# and lb is %.1f and kg %.1f",weight,temp,temp1);
_weightDataLabel.text = [[NSString alloc] initWithFormat:#"%#",weight];
}
else
{
double temp=[UnitParse convertKgToLb:weightdata];
double temp1=[UnitParse convertLbToKg:weightdata];
NSLog(#"weight in if .... %f and lb is %.1f and kg %.1f",weightdata,temp,temp1);
NSString *weight = [[NSString alloc]initWithFormat:#"%.1f",temp1];
NSLog(#"weight in else .... %#",weight);
_weightDataLabel.text = [[NSString alloc] initWithFormat:#"%#",weight];
}
// NSString *weight = [[NSString alloc]initWithFormat:#"%.1f",[UnitParse convertKgToLb:weightdata]];
// _weightDataLabel.text = [[NSString alloc] initWithFormat:#"%#",weight];
}
// Have we got everything we need?
if ([stringFromData isEqualToString:#"EOM"]) {
// We have, so show the data,
//[self.textview setText:[[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding]];
NSLog(#"GetDataValue : %#",[[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding]);
// Cancel our subscription to the characteristic
[peripheral setNotifyValue:NO forCharacteristic:characteristic];
// and disconnect from the peripehral
[self.centralManager cancelPeripheralConnection:peripheral];
}
}
output of bytes data is:
Receive byte:14 byte data is 0xe
Receive byte:176 byte data is 0xb0
Receive byte:4 byte data is 0x4
Receive byte:223 byte data is 0xdf
Receive byte:7 byte data is 0x7
Receive byte:1 byte data is 0x1
Receive byte:1 byte data is 0x1
Receive byte:23 byte data is 0x17
Receive byte:48 byte data is 0x30
Receive byte:17 byte data is 0x11
Receive byte:1 byte data is 0x1

Use this code for read the byte data of weight or heart rate or temperature.
Lol is the nsdata object.
const uint8_t *reportData = [lol bytes];
uint16_t bpm = (uint16_t)reportData;
CGFloat weightdata = 0;
if ((reportData[1] & 0x01) == 0)
{
/* uint8 bpm */
NSLog(#"if reportData is %d",reportData[1]);
bpm = CFSwapInt16LittleToHost(*(uint16_t *)(&reportData[1]));
NSLog(#"if bpm data is %d",bpm);
weightdata = bpm/200.0;
}
else
{
/* uint16 bpm */
NSLog(#"reportData is %d",reportData[1]);
bpm = CFSwapInt16LittleToHost(*(uint16_t *)(&reportData[1]));
NSLog(#"bpm data is %d",bpm);
weightdata = bpm/200.0;
}

Related

NSString from NSData is incomplete

When I use [[NSString alloc] initWithData:subdata encoding:encoding] method , I find the string is incomplete. Why? Any restrictions in NSString?
Then,I suspect that the data is too large,so I create a new method to Transfer.
-(NSString *)stringFromData:(NSData *)data encoding:(NSStringEncoding)encoding{
NSInteger DataLen = data.length;
NSInteger segLen = 5000;
NSInteger times = DataLen/segLen;
NSInteger fristLen = DataLen%segLen;
NSMutableString *str = [NSMutableString string];
[str appendString:[[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, fristLen)] encoding:encoding]];
NSLog(#"%#",str);
while (times--) {
NSData *subdata = [data subdataWithRange:NSMakeRange(fristLen, segLen)] ;
if (subdata) {
NSString*substr = [[NSString alloc] initWithData:subdata encoding:encoding]; //tag1
NSLog(#"%#",substr);
if (substr) {
[str appendString:substr];
}
fristLen += segLen;
}else{
break;
}
}
return str;
}
but in tag1, I find the string is null in some conditions. What is the problem?

User Interaction causes a for loop to move onto the next object

I have an array of objects in which this for loop iterates through. Each object is an IP Address that I test for. However, once the for loop gets to a specific object that fails, the for loop takes roughly 15seconds to a minute to move onto the next object. However, if I interact with the display on my device by tapping, the for loop moves onto the next object. I find this odd because I do call [[UIApplication sharedApplication] beginIgnoringInteractionEvents];. So A) Why is the application still detecting touch events which affect the for loop. And B) I verified that the [[UIApplication sharedApplication] beginIgnoringInteractionEvents]; does work because if I try to tap a barButtonItem nothing happens. So here's my question, how can user interaction that's ignored temporarily still cause a for loop to move onto the next object? I've verified that there's no issues with threading/GCD. I know this may be rough to understand without a code sample, however I want to know the principal behind a UI interaction event affecting a for loop.
UPDATE!
Code:
-(void)beginConnectivitySetupAndTests {
for (int i = 0; i<[extractedDataArray count]; i++) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
NSString *inStoreObject = [[extractedDataArray objectAtIndex:i] valueForKey:#"ConnectabilityObjectType"];
NSString *objectTitle = [[extractedDataArray objectAtIndex:i] valueForKey:#"ConnectabilityObjectTechnicalTitle"];
NSString *objectLastOctet = [[extractedDataArray objectAtIndex:i] valueForKey:#"ConnectabilityObjectLastOctet"];
NSString *isInfrastructureObject = [[extractedDataArray objectAtIndex:i] valueForKey:#"ConnectabilityObjectIsInfrastructureObject"];
NSString *needsAlternateSecondOctet = [[extractedDataArray objectAtIndex:i] valueForKey:#"ConnectablityObjectNeedsAlternateSecondOctet"];
NSLog(#"Working with: %#",objectTitle);
if ([inStoreObject isEqualToString:#"InStoreObject"]) {
if ([needsAlternateSecondOctet isEqualToString:#"YES"]) {
// self.deviceIPAddress = nil;
NSLog(#"%#", self.deviceIPAddress);
NSMutableArray <NSString *> *octets = [self.deviceIPAddress componentsSeparatedByString:#"."];
NSString *firstOctetString = [octets objectAtIndex:0];
NSString *secondOctetString = [octets objectAtIndex:1];
NSString *thirdOctetString = [octets objectAtIndex:2];
int secondInt = secondOctetString.intValue;
if (secondInt >= 40 && secondInt <= 47) {
[octets removeObjectAtIndex:1];
secondOctetString = [NSString stringWithFormat:#"%d", secondInt +40];
}
else if (secondInt >= 52 && secondInt <= 53) {
[octets removeObjectAtIndex:1];
secondOctetString = [NSString stringWithFormat:#"%d", secondInt +100];
}
else if (secondInt >= 120 && secondInt <= 121) {
[octets removeObjectAtIndex:1];
secondOctetString = [NSString stringWithFormat:#"%d", secondInt +100];
}
else if (secondInt >= 122 && secondInt <= 123) {
[octets removeObjectAtIndex:1];
secondOctetString = [NSString stringWithFormat:#"%d", secondInt +40];
}
else if (secondInt >= 124 && secondInt <= 125) {
[octets removeObjectAtIndex:1];
secondOctetString = [NSString stringWithFormat:#"%d", secondInt +40];
}
else if (secondInt >= 126 && secondInt <= 127) {
[octets removeObjectAtIndex:1];
secondOctetString = [NSString stringWithFormat:#"%d", secondInt +40];
} else {
}
NSString *finalString = [NSString stringWithFormat:#"%#.%#.%#.%#", firstOctetString, secondOctetString, thirdOctetString, objectLastOctet];
[[extractedDataArray objectAtIndex:i] setValue:[NSString stringWithFormat:#"%#",finalString]forKey:#"ConnectabilityObjectFullIPAddress"];
finalIPAddress = finalString;
octets = nil;
} else {
NSMutableArray <NSString*> *octets = [self.deviceIPAddress componentsSeparatedByString:#"."];
NSString *firstOctetString = [octets objectAtIndex:0];
NSString *secondOctetString = [octets objectAtIndex:1];
NSString *thirdOctetString = [octets objectAtIndex:2];
[octets removeObjectAtIndex:3];
NSString *lastOctet = [NSString stringWithFormat:#"%#", objectLastOctet];
NSString *constructedIPAddress = [NSString stringWithFormat:#"%#.%#.%#.%#", firstOctetString, secondOctetString, thirdOctetString, lastOctet];
finalIPAddress = constructedIPAddress;
[[extractedDataArray objectAtIndex:i] setValue:[NSString stringWithFormat:#"%#",constructedIPAddress]forKey:#"ConnectabilityObjectFullIPAddress"];
NSLog(#"%# IP: %#", objectTitle, constructedIPAddress);
}
} else {
finalIPAddress = [[extractedDataArray objectAtIndex:i] valueForKey:#"ConnectabilityObjectFullIPAddress"];
}
self.ping = [[SimplePing alloc] initWithHostName:finalIPAddress];
NSLog(#"pinging: %#",finalIPAddress);
self.ping.delegate = self;
[self.ping start];
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (self.ping != nil);
if (pingableObjectAddress) {
if (_deviceLatencyString == NULL) {
[[extractedDataArray objectAtIndex:i] setValue:[NSString stringWithFormat:#"Successful"] forKey:#"ConnectivityPingTestResultValue"];
} else {
[[extractedDataArray objectAtIndex:i] setValue:[NSString stringWithFormat:#"Successful: latency: %# ms",_deviceLatencyString] forKey:#"ConnectivityPingTestResultValue"];
}
pingableObjectAddress = nil;
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
portNumberValue = [[[extractedDataArray objectAtIndex:i] valueForKey:#"ConnectabilityObjectPorts"] intValue];
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)finalIPAddress, portNumberValue, &readStream, &writeStream);
inputStream = (NSInputStream*)CFBridgingRelease(readStream);
outputStream = (NSOutputStream*)CFBridgingRelease(writeStream);
[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
NSLog(#"Opening Port for %lu at IP Address %#", (unsigned long)portNumberValue, finalIPAddress);
NSString *response = #"Fly with me!";
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
[outputStream write:[data bytes] maxLength:[data length]];
if ([[extractedDataArray objectAtIndex:i] valueForKey:#"ConnectabilityObjectPorts"] != nil ) {
if (_connectedPortNumber != 0) {
NSLog(#"Port Connection %lu succeeded for %#", (unsigned long)portNumberValue, finalIPAddress);
[[extractedDataArray objectAtIndex:i] setValue:#"Successful" forKey:#"ConnectivityPortConnectResultValue"];
if (!isInfrastructureObject) {
_portConnectionSucceeded = _portConnectionSucceeded + 1;
NSLog(#"port connect is not for infrastructure object");
}
self.connectedPortNumber = 0;
} else {
if (!isInfrastructureObject) {
_portConnectionFailed = _portConnectionFailed + 1;
}
}
}
} else {
if (!isInfrastructureObject) {
pingFailed = pingFailed + 1;
}
}
NSLog(#"%lu",(unsigned long)i);
}
}
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
// does have a valid IP address
-(void)simplePing:(SimplePing *)pinger didStartWithAddress:(NSData *)address {
[self.ping sendPingWithData:nil];
}
// device did send packet
-(void)simplePing:(SimplePing *)pinger didSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber address:(nonnull NSString *)address {
// NSLog(#"Sending 64 bytes to %#: icmp_seq=%hu ttl=64", address, sequenceNumber);
pingTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:PING_TIMEOUT target:self selector:#selector(timerFired) userInfo:nil repeats:NO];
_dateRef = [NSDate date];
NSLog(#"Packet Sent to: %#", address);
}
// timeout timer, fires when a ping back is never recieved
-(void)timerFired {
NSLog(#"timeout timer fired");
[pingTimeoutTimer invalidate];
//self.pingableObjectAddress = nil;
self.pingTimeoutTimer = nil;
self.ping = nil;
}
// failed to send packet error handler
-(void)simplePing:(SimplePing *)pinger didFailToSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber error:(NSError *)error {
[self.pingTimeoutTimer invalidate];
pingTimeoutTimer = nil;
self.ping = nil;
if (error) {
NSLog(#"Ping Error: %#", error);
}
}
// device did recieve unexpected ping packet, handle this when this happens
-(void)simplePing:(SimplePing *)pinger didReceiveUnexpectedPacket:(NSData *)packet {}
// did recieve response packet
-(void)simplePing:(SimplePing *)pinger didReceivePingResponsePacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber address:(NSString *)address {
[pingTimeoutTimer invalidate];
NSDate *end = [NSDate date];
double latency = [end timeIntervalSinceDate:_dateRef] *1000;
self.deviceLatencyString = [NSString stringWithFormat:#"%.f", latency];
self.pingTimeoutTimer = nil;
// NSLog(#"64 bytes sent to %#: icmp_seq=%hu ttl=64 time = %f ms", address, sequenceNumber, _latency);
self.pingableObjectAddress = address;
// NSLog(#"%#", pingableObjectAddress);
NSLog(#"did recieve packet from: %#", address);
self.ping = nil;
}
// device failed to ping for failed reason
-(void)simplePing:(SimplePing *)pinger didFailWithError:(NSError *)error {
NSLog(#"Failed With Error %#", error);
assert(pinger == self.ping);
[self.ping stop];
self.ping = nil;
}

Reading received packets in didUpdateValueForCharacteristic

I need to read the received bytes and parse them with a custom method, which basically goes through bytes and skips every 0x7D (or a } ). But what happens now is that it does that for only one received packet, and I dont know why that is happening since im calling my method in didUpdateValueForCharacteristic :
- (void) peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
if (error)
{
NSLog(#"Error receiving notification for characteristic %#: %#", characteristic, error);
return;
}
NSLog(#"Received data on a characteristic.");
if (characteristic == self.rxCharacteristic)
{
self.bluetoothData = [[NSMutableData alloc] initWithData:[characteristic value]];
[self unstuff1:[characteristic value]];
NSLog(#"First NSDAta %#", self.bluetoothData);
[self unstuff1:self.bluetoothData];
NSLog(#"Parsed First NSDATA %#", self.bluetoothData);
NSString *stringForPrintingOutToConsole = [[NSString alloc] initWithData:self.bluetoothData encoding:NSASCIIStringEncoding];
[self.delegate didReceiveData:stringForPrintingOutToConsole];
}
else if ([characteristic.UUID isEqual:self.class.hardwareRevisionStringUUID])
{
NSString *hwRevision = #"";
const uint8_t *bytes = characteristic.value.bytes;
for (int i = 0; i < characteristic.value.length; i++)
{
NSLog(#"%x", bytes[i]);
hwRevision = [hwRevision stringByAppendingFormat:#"0x%02x, ", bytes[i]];
}
// this one reads the hardware revision
[self.delegate didReadHardwareRevisionString:[hwRevision substringToIndex:hwRevision.length-2]];
}
}
and a custom method for parsing :
- (NSMutableData *)unstuff1:(NSMutableData *)mutableData {
NSUInteger dataLength = [self.bluetoothData length];
unsigned char *bytes = [self.bluetoothData bytes];
uint16_t i, j = 0;
for (int i = 0; i < dataLength; i++)
{
if (bytes[i] == 0x7D)
{
bytes[j] = bytes[i+1] ^ 0x20;
i++;
} else
{
bytes[j] = bytes[i];
j++;
}
}
return mutableData;
}
if anyone has a clue, i'd highly appreciate help.

Interpret bytes received from bluetooth weight scale device in iOS

I am integrating a weight scale device in our iOS Application. The Device name nutriscale weight scale. I am using apple provided API -CBCentralManager for connecting and getting data from weight scale. I am able to detect services and characteristics of bluetooth device and getting some data from weight scale device after connecting but not able to interpret that data. I am able to get weight if it's below 255 gram. If it goes beyond 255. it gives me weight-255 answer.
Kindly correct me for this.
Here it's my code:
When i call [aPeripheral readValueForCharacteristic:aChar]; A delegate method below is being called.
- (void) peripheral:(CBPeripheral *)aPeripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {// NSLog(#"Descriptor %#",[characteristic properties]);if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:HELLOBLUETOOTH_CHARACTERISTICS_NAME_UUID]])
{
pName = [[NSString alloc] initWithUTF8String:[[characteristic value]bytes]];
NSError *errorVa;
NSLog(#"KeyfobViewController didUpdateValueForCharacteristic %#", characteristic);
[aPeripheral setNotifyValue:YES forCharacteristic:characteristic];
[self getWeightData:characteristic error:errorVa];
}}
To interpret bytes i wrote this method
(void) getWeightData:(CBCharacteristic *)characteristic error:(NSError *)error{
// Get the Heart Rate Monitor BPM
NSData *data = [characteristic value];// 1
const uint8_t *reportData = [data bytes];
const uint16_t *reportData1 = [data bytes];
uint16_t weightValue = 0;
uint16_t weightValue1 = 0;
if(reportData)
{
if ((reportData[0] & 0x01) == 0) { // 2
// Retrieve the weight from the scale
weightValue = reportData[1];
int result= CFSwapInt16LittleToHost(*(uint16_t *)(&reportData[1]));
}
else
{
weightValue = CFSwapInt32LittleToHost(*(uint32_t *)(&reportData[1])); // 3
int result= CFSwapInt32LittleToHost(*(uint32_t *)(&reportData[1]));
NSLog(#"weightValue1 - %hhu",weightValue);
}
NSMutableArray *arrr = [NSMutableArray new];
uint8_t byte1 = reportData[0];
for (int i = 0; i < 8; i++) {int mask = 1 << i;if ((byte1 & mask) == 0) {[arrr addObject:#"0"];} else {[arrr addObject:#"1"];}}
NSLog(#"values1 - %#%#%#%#%#%#%#%#",arrr[7],arrr[6],arrr[5],arrr[4],arrr[3],arrr[2],arrr[1],arrr[0]);
[arrr removeAllObjects];
for (int i = 0; i < 16; i++) {int mask = 1 << i;if ((weightValue1 & mask) == 0) {[arrr addObject:#"0"];} else {[arrr addObject:#"1"];}}
NSLog(#"values2 - %#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#",arrr[15],arrr[14],arrr[13],arrr[12],arrr[11],arrr[10],arrr[9],arrr[8],arrr[7],arrr[6],arrr[5],arrr[4],arrr[3],arrr[2],arrr[1],arrr[0]);
// NSLog(#"values0 - %#%#%#%#%#%#%#%#",arrr[0],arrr[1],arrr[2],arrr[3],arrr[4],arrr[5],arrr[6],arrr[7]);
// NSLog(#"values2 - %#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#",arrr[0],arrr[1],arrr[2],arrr[3],arrr[4],arrr[5],arrr[6],arrr[7],arrr[8],arrr[9],arrr[10],arrr[11],arrr[12],arrr[13],arrr[14],arrr[15]);
}
// Display the weight value to the UI if no error occurred
if( (characteristic.value) || !error )
{ //
NSString *weight = [NSString stringWithFormat:#"%i", weightValue];
if([weight floatValue])
{
NSUserDefaults *defaultObject = [NSUserDefaults standardUserDefaults];
[defaultObject setObject:data forKey:#"data"];
[defaultObject synchronize];
NSString *strWeight=#"";
strWeight = [NSString stringWithFormat:#"%#",weight];
strWeight = [NSString stringWithFormat:#"%.1f",[strWeight floatValue]*0.035274];//
//[self bluetoothResponseToClass];
}
}
return;}
Kindly help me in this code. What am i doing wrong ?
Replace your function with below function
-(void) getWeightData:(CBCharacteristic *)characteristic error:(NSError *)error
{
// Get the Heart Rate Monitor BPM
NSData *data = [characteristic value];// 1
const uint8_t *reportData = [data bytes];
uint16_t weightValue = 0;
uint16_t chkValue = 0;
if(reportData)
{
chkValue = reportData[0];
weightValue = CFSwapInt32LittleToHost(*(uint32_t *)(&reportData[1]));
int var = (chkValue % 160);
weightValue = weightValue + var * 256;
NSMutableArray *arrr = [NSMutableArray new];
uint8_t byte1 = reportData[0];
for (int i = 0; i < 8; i++) {int mask = 1 << i;if ((byte1 & mask) == 0) {[arrr addObject:#"0"];} else {[arrr addObject:#"1"];}}
NSLog(#"values1 - %#%#%#%#%#%#%#%#",arrr[7],arrr[6],arrr[5],arrr[4],arrr[3],arrr[2],arrr[1],arrr[0]);
[arrr removeAllObjects];
for (int i = 0; i < 16; i++) {int mask = 1 << i;if ((chkValue & mask) == 0) {[arrr addObject:#"0"];} else {[arrr addObject:#"1"];}}
NSLog(#"values2 - %#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#",arrr[15],arrr[14],arrr[13],arrr[12],arrr[11],arrr[10],arrr[9],arrr[8],arrr[7],arrr[6],arrr[5],arrr[4],arrr[3],arrr[2],arrr[1],arrr[0]);
}
// Display the weight value to the UI if no error occurred
if( (characteristic.value) || !error )
{ //
NSString *weight = [NSString stringWithFormat:#"%i", weightValue];
lbl_Weight.text = [NSString stringWithFormat:#"%hu", weightValue];
if([weight floatValue])
{
NSUserDefaults *defaultObject = [NSUserDefaults standardUserDefaults];
[defaultObject setObject:data forKey:#"data"];
[defaultObject synchronize];
NSString *strWeight=#"";
strWeight = [NSString stringWithFormat:#"%#",weight];
strWeight = [NSString stringWithFormat:#"%.1f",[strWeight floatValue]*0.035274];//
//[self bluetoothResponseToClass];
}
}
return;
}

Storing and Retrieving compressed texts as BLOB from Sqlite via FMDB

I am trying to store text data as compressed blobs.
[db executeUpdate:#"create table blobTable (a text, b blob)"];
[db executeUpdate:#"insert into blobTable (a, b) values (?, compressMe('random text string'))", #"lord of the rings"];
And then I try to query them using:
FMResultSet *rs = [db executeQuery:#"select uncompressMe(b) as k from blobTable where a = ?", #"lord of the rings"];
Where compressMe and uncompressMe are defined as:
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
[queue inDatabase:^(FMDatabase *adb) {
[adb makeFunctionNamed:#"compressMe" maximumArguments:1 withBlock:^(sqlite3_context *context, int aargc, sqlite3_value **aargv) {
if (sqlite3_value_type(aargv[0]) == SQLITE_TEXT) {
#autoreleasepool {
const char *c = (const char *)sqlite3_value_text(aargv[0]);
NSString *s = [NSString stringWithUTF8String:c];
NSLog(#"string to compress: %#", s);
NSData *compressedBody = [self gzipDeflate:[s dataUsingEncoding:NSUTF8StringEncoding]];
sqlite3_result_blob(context, (__bridge const void *)(compressedBody), [compressedBody length], nil);
}
}
else {
NSLog(#"Unknown formart for StringStartsWithH (%d) %s:%d", sqlite3_value_type(aargv[0]), __FUNCTION__, __LINE__);
sqlite3_result_null(context);
}
}];
}];
[queue inDatabase:^(FMDatabase *adb) {
[adb makeFunctionNamed:#"uncompressMe" maximumArguments:1 withBlock:^(sqlite3_context *context, int aargc, sqlite3_value **aargv) {
if (sqlite3_value_type(aargv[0]) == SQLITE_BLOB) {
#autoreleasepool {
NSLog(#"inside uncompressMe");
NSUInteger len = sqlite3_value_bytes(aargv[0]);
Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, sqlite3_value_blob(aargv[0]), len);
NSData *data = [[NSData alloc] initWithBytes:byteData length:len];
NSData *deflatedBody = [self gzipInflate:data];
NSString *deflatedString = [[NSString alloc] initWithData:deflatedBody encoding:NSUTF8StringEncoding];
sqlite3_result_text(context, (__bridge const void *)(deflatedString), -1, SQLITE_UTF8);
}
}
else {
NSLog(#"Unknown formart for StringStartsWithH (%d) %s:%d", sqlite3_value_type(aargv[0]), __FUNCTION__, __LINE__);
sqlite3_result_null(context);
}
}];
}];
For the sake of completeness, the zip functions are defined as such:
- (NSData *)gzipInflate:(NSData*)data
{
if ([data length] == 0) return data;
unsigned full_length = [data length];
unsigned half_length = [data length] / 2;
NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length];
BOOL done = NO;
int status;
z_stream strm;
strm.next_in = (Bytef *)[data bytes];
strm.avail_in = [data length];
strm.total_out = 0;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
if (inflateInit2(&strm, (15+32)) != Z_OK) return nil;
while (!done)
{
// Make sure we have enough room and reset the lengths.
if (strm.total_out >= [decompressed length])
[decompressed increaseLengthBy: half_length];
strm.next_out = [decompressed mutableBytes] + strm.total_out;
strm.avail_out = [decompressed length] - strm.total_out;
// Inflate another chunk.
status = inflate (&strm, Z_SYNC_FLUSH);
if (status == Z_STREAM_END) done = YES;
else if (status != Z_OK) break;
}
if (inflateEnd (&strm) != Z_OK) return nil;
// Set real length.
if (done)
{
[decompressed setLength: strm.total_out];
return [NSData dataWithData: decompressed];
}
else return nil;
}
- (NSData *)gzipDeflate:(NSData*)data
{
if ([data length] == 0) return data;
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.total_out = 0;
strm.next_in=(Bytef *)[data bytes];
strm.avail_in = [data length];
// Compresssion Levels:
// Z_NO_COMPRESSION
// Z_BEST_SPEED
// Z_BEST_COMPRESSION
// Z_DEFAULT_COMPRESSION
if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY) != Z_OK) return nil;
NSMutableData *compressed = [NSMutableData dataWithLength:16384]; // 16K chunks for expansion
do {
if (strm.total_out >= [compressed length])
[compressed increaseLengthBy: 16384];
strm.next_out = [compressed mutableBytes] + strm.total_out;
strm.avail_out = [compressed length] - strm.total_out;
deflate(&strm, Z_FINISH);
} while (strm.avail_out == 0);
deflateEnd(&strm);
[compressed setLength: strm.total_out];
return [NSData dataWithData:compressed];
}
However, the uncompressMe function doesnt seem to succeed. It fails in the Inflate method, which always returns a nil. Any thoughts what I might be doing wrong? I have checked to make sure that the blob column does get populated.
I feel like issue is from below code:
NSUInteger len = sqlite3_value_bytes(aargv[0]);
Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, sqlite3_value_blob(aargv[0]), len);
NSData *data = [[NSData alloc] initWithBytes:byteData length:len];
Try this to load NSData from database instead of creating byte variable and copying it.
const void *bytes = sqlite3_column_blob(statement, 3);
NSData *data = [[NSData alloc] initWithBytes:bytes length:size];

Resources