Convert Unsigned Int to Hexadecimal value - ios

How can I convert a integer 6 digit number such as "1234674" to a hexadecimal 4 byte NSData in Objective-C ?
This is the part of our code that sends passkey:
#define HSL_PRIVATE_SERVICE_UUID 0xFF20
#define HSL_PRIVATE_NEW_PASSKEY_UUID 0xFF35
unsigned int newPassKey = [_confirmNewPassKey.text intValue];
NSLog(#"newPasskey %d", newPassKey);
NSData *d = [NSData dataWithBytes:&newPassKey length:sizeof(unsigned int)];
[_t writeValue:HSL_PRIVATE_SERVICE_UUID characteristicUUID:HSL_PRIVATE_NEW_PASSKEY_UUID p:_peripheral data:d];
I did an air capture comparing BTOOL versus iPhone passkey writes.
BTOOL (A simulator tool) wrote (the correct result) :
0x40e201
iPhone wrote(wrong data):
0x0001e240
Not sure what is going on and how to fix it in the app so that the result matches what the Bluetooth device is expecting . I would like the result to be same as BTOOL one.

Try this:
uint32_t value = [_confirmNewPassKey.text intValue];
uint32_t swapped = CFSwapInt32HostToBig(value);
NSData *d = [NSData dataWithBytes:&swapped length:sizeof(swapped)];
This assumes you want big endian for the output.

Related

Convert Hex NSData to int in Objective C

Our custom Smart Router is giving me NSData response
<800c01ff 0001ffff ffff29ff>
Here, 800c is my deviceId. How to convert it to int ?
deviceId =32780;
When I send command to router I constructed it like,
Byte mqttData[12];
mqttData[0] =[[NSNumber numberWithUnsignedChar:(deviceID >> 8) & 0xFF] intValue];
//mqttData[0]=128 or 80 in Hex
mqttData[1] =[[NSNumber numberWithUnsignedChar:deviceID & 0xFF] intValue];
//mqttData[1]=12 or 'C' in Hex
return [NSData dataWithBytes:mqttData length:sizeof(mqttData)];
int deviceId = CFSwapInt16BigToHost(*(int*)([deviceIDData bytes]))
Answer taken from Larme's comment.

Print UIImage with Zerba iMZ320 printer in CPCL Language

I tried to convert UIImage to bytes(NSData) and then converted it to hex string but no use. it prints only a black bar instead of image.I thought of converting UIImage to PCX format but unable to find good tutorials. Let me know a way to print UIImage with zebra printers.
Note: ONLY CPCL Language
Tried Below Methods
Method 1:
-(void)PrintImage
{
NSData *data = UIImagePNGRepresentation(image);
NSString* hex = [self hexRepresentationWithSpaces_AS:NO data:data];
NSMutableString * str = [NSMutableString new];
[str appendString:#"! 0 200 200 210 1\r\nEG 40 80 0 0\n"];
[str appendString:hex];
[str appendString:#"\r\nPRINT\r\n"];
//Sending this command to Zebra Printer
}
Method 2:
-(void)PrintImage
{
id<ZebraPrinter,NSObject> printer = [ZebraPrinterFactory getInstance:connection error:&error];
id<GraphicsUtil, NSObject> graphicsUtil = [printer getGraphicsUtil];
[graphicsUtil storeImage:#"1234.jpg" withImage:[image CGIImage] withWidth:-1 andWithHeight:-1 error:&error];
//What ever the format I send it stores in GRF file but the CPCL command accepts only .PCX file to print stored image
NSString str = #"\n! 0 200 200 500 1 \nPCX 0 30 !<1234.PCX \nPRINT\n";
//Sending this command to Zebra Printer
}
Other Methods
-(NSString*)hexRepresentationWithSpaces_AS:(BOOL)spaces data:(NSData *)data
{
const unsigned char* bytes = (const unsigned char*)[data bytes];
NSUInteger nbBytes = [data length];
//If spaces is true, insert a space every this many input bytes (twice this many output characters).
static const NSUInteger spaceEveryThisManyBytes = 4UL;
//If spaces is true, insert a line-break instead of a space every this many spaces.
static const NSUInteger lineBreakEveryThisManySpaces = 4UL;
const NSUInteger lineBreakEveryThisManyBytes = spaceEveryThisManyBytes * lineBreakEveryThisManySpaces;
NSUInteger strLen = 2*nbBytes + (spaces ? nbBytes/spaceEveryThisManyBytes : 0);
NSMutableString* hex = [[NSMutableString alloc] initWithCapacity:strLen];
for(NSUInteger i=0; i<nbBytes; ) {
[hex appendFormat:#"%02X", bytes[i]];
//We need to increment here so that the every-n-bytes computations are right.
++i;
if (spaces) {
if (i % lineBreakEveryThisManyBytes == 0) [hex appendString:#"\n"];
else if (i % spaceEveryThisManyBytes == 0) [hex appendString:#" "];
}
}
return hex;
}
You can use Zebra's iOS SDK to print images. It supports the iMZ320. You would use the same logic of extracting the data from a UIImage (or specifically the CGImageRef from a UIImage) and sending it to the printer via the printImage command.
SDK: http://www.zebra.com/us/en/products-services/software/link-os/link-os-sdk.html
If you cannot use the SDK, you will instead need to parse the image data from the UIImage yourself and wrap it with the CPCL command EG (or one of its variants). You can find CPCL graphics commands on section 7 page 7 here: http://www.zebra.com/content/dam/zebra/manuals/en-us/printer/cpcl-pm-en.pdf. If you have already done this much, perhaps you can post your code and someone can show you where you went wrong.
Update July 27th, 2014
I have a couple of thoughts now that you have posted some code.
Try using the SDK method 'printImage' after you have stored the image. There is no reason to send the CPCL command yourself since the SDK should take care of it for you. The SDK should manage the whole PCX vs JPG thing for you. Note: You should only store the image once once on the printer, no need to call storeImage multiple times. While storing extra times doesn't break anything, it is unnecessary and slows down your routine!
The printer supports multiple languages (ZPL, CPCL, Line print, etc.). If I recall correctly, the printers may always accept CPCL commands but still be in ZPL mode. Not sure. Anyway, it is worth checking what language the printer thinks it is in. You can ask with the following query:
! U1 getvar "device.languages"
[Notice there should be a newline or carriage return after that command]

Convert NSData to a NSString returns random characters

I am working on a bluetooth iOS project and have managed to get some data from the bluetooth device.
However, I am struggling to convert this data into something useful, such as an NSString. Whenever I try to NSLog the NSString that was converted from the NSData received, it is a bunch of gibberish. The output is:
ēဥ၆䄀
The bluetooth device is a heart monitor from a manufacturer in Asia and they have provided the protocol reference on how to make calls to the device. This one thing they mention in the protocol reference:
The PC send 16-byte packets to the device, then the device sent back the 16-byte packets. Except for some special commands, all others can use this communication mode.
Can anyone tell me what I am doing wrong? I have tried everything I know, including every single encoding in the apple docs as well as both initWithData and initWithBytes. Thanks!
-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error {
if (error)
{
NSLog(#"erorr in read is %#", error.description);
return;
}
NSData *data= characteristic.value;
NSString *myString = [[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF16StringEncoding];
NSLog(#"Value from device is %#", myString); //OUTPUT IS ēဥ၆䄀
}
What you have here is a string of raw data that can't be directly converted into a human readable string - unless you consider hex-representation to be human readable :)
To make sense of this data you need to either have a protocol specification at hand or prepare for hours (sometimes) days of reverse-engineering.
This byte-sequence can be composed of multiple values formatted in standard (float IEEE 754, uint8_t, uint16_t...) or even proprietary formats.
One important thing to consider when communicating with the outside world is also endianness (ie: does the 'biggest' byte in multi-byte format come first or last).
There are many ways to manipulate this data. To get the raw array of bytes you could do:
NSData *rxData = ...
uint8_t *bytes = (uint8_t *)[rxData bytes];
And then if (for example) first byte tells you what type of payload the string holds you can switch like:
switch (bytes[0])
{
case 0x00:
//first byte 0x00: do the parsing
break;
case 0x01:
//first byte 0x01: do the parsing
break;
// ...
default:
break;
}
Here would be an example of parsing data that consists of:
byte 0: byte holding some bit-coded flags
bytes 1,2,3,4: 32-bit float
bytes 5,6: uint16_t
bool bitFlag0;
bool bitFlag1;
bool bitFlag2;
bool bitFlag3;
uint8_t firstByte;
float theFloat;
uint16_t theInteger;
NSData *rxData = ...
uint8_t *bytes = (uint8_t *)[rxData bytes];
// getting the flags
firstByte = bytes[0];
bitFlag0 = firstByte & 0x01;
bitFlag1 = firstByte & 0x02;
bitFlag2 = firstByte & 0x04;
bitFlag3 = firstByte & 0x08;
//getting the float
[[rxData subdataWithRange:NSMakeRange(1, 4)] getBytes:&theFloat length:sizeof(float)];
NSLog (#"the float is &.2f",theFloat);
//getting the unsigned integer
[[data subdataWithRange:NSMakeRange(6, 2)] getBytes:&theInteger length:sizeof(uint16_t)];
NSLog (#"the integer is %u",theInteger);
One note: depending on the endianness you might need to reverse the 4-float or the 2-uint16_t bytes before converting them. Converting this byte arrays can also be done with unions.
union bytesToFloat
{
uint8_t b[4];
float f;
};
and then:
bytesToFloat conv;
//float would be written on bytes b1b2b3b4 in protocol
conv.b[0] = bytes[1]; //or bytes[4] .. endianness!
conv.b[1] = bytes[2]; //or bytes[3] .. endianness!
conv.b[2] = bytes[3]; //or bytes[2] .. endianness!
conv.b[3] = bytes[4]; //or bytes[1] .. endianness!
theFloat = conv.f,
If for example you know that byte6 and byte7 represent an uint16_t value you can calculate it from raw bytes:
value = uint16_t((bytes[6]<<8)+bytes[7]);
or (again - endianness):
value = uint16_t((bytes[7]<<8)+bytes[6]);
One more note: using simply sizeof(float) is a bit risky since float can be 32-bit on one platform and 64-bit on another.

NSData to primitive

I have NSData *data. It's value is 000e.
Hence decimal value is 14.
Now I want to get this value into primitive NSUInteger.
I've tried
NSUInteger *hereIWant14 = (NSUInteger *)data.bytes;
but *hereIWant14 value is 3584 what is e00 in hexa. Now I don't know if there is problem with endians or type size or my thinking is completely wrong and 000e and e00 similarity is just pure accident.
It's related to endianness. Use the conversion macros defined in Endian.h:
EndianU16_BtoN(value)
EndianU16_NtoB(value)
EndianS32_BtoN(value)
EndianS32_NtoB(value)
EndianU32_BtoN(value)
EndianU32_NtoB(value)
EndianS64_BtoN(value)
EndianS64_NtoB(value)
EndianU64_BtoN(value)
EndianU64_NtoB(value)
etc.
Method signatures mean:
Endian + U for unsigned S for signed + number of bits + N is native endianness of the system, L is little endian, B is big endian
So if you have an NSData with the content (0x00, 0xE0), and you'd like to interpret it as the value 14, then it contains the data in big endian order, therefore you'll have to use EndianU32_BtoN (of course, this macro is the identity transform on big-endian systems and swaps the bytes only on little-endian machines).
Important: to be future-proof, I'd recommend you to use something else instead of NSUInteger, since the width of this type can vary between different systems (e.g. Apple defines NSUInteger as 64 bit on arm64 systems). So, to be explicit about the number of bits, use uint32_t or uint64_t etc.
Edit: Usage for Big-Endian short value
NSMutableData * data = [[NSMutableData alloc] initWithLength:2];
((unsigned char *)data.mutableBytes)[0] = 0x00;
((unsigned char *)data.mutableBytes)[1] = 0x0E;
NSUInteger integer = NSSwapBigShortToHost(*(unsigned short *)data.mutableBytes);
NSLog(#"%d", integer); // prints 14
Yes, it's because of the endianess as said.
If you need down here two pieces of code to read from a NSData:
u_int16_t signature;
[data getBytes:&signature range:NSMakeRange(0, 2)];
signature = CFSwapInt16(signature);
Usually I use CFSwapInt16 or CFSwapInt32 (for u_int32_t). Otherwise if you have to read for example a string:
char charArray[length];
[data getBytes:charArray range:NSMakeRange(0, length)];
NSData* data = [NSData dataWithBytes:charArray length:length];
NSString* string = [[NSString alloc]initWithData:data encoding:NSStringEncodingConversionAllowLossy];
Hope it can help!

Obfuscating a number(in a string) Objective C

I'm using the following code to obfuscate a passcode for a test app of mine.
- (NSString *)obfuscate:(NSString *)string withKey:(NSString *)key
{
// Create data object from the string
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
// Get pointer to data to obfuscate
char *dataPtr = (char *) [data bytes];
// Get pointer to key data
char *keyData = (char *) [[key dataUsingEncoding:NSUTF8StringEncoding] bytes];
// Points to each char in sequence in the key
char *keyPtr = keyData;
int keyIndex = 0;
// For each character in data, xor with current value in key
for (int x = 0; x < [data length]; x++)
{
// Replace current character in data with
// current character xor'd with current key value.
// Bump each pointer to the next character
*dataPtr = *dataPtr++ ^ *keyPtr++;
// If at end of key data, reset count and
// set key pointer back to start of key value
if (++keyIndex == [key length])
keyIndex = 0, keyPtr = keyData;
}
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
This works like a charm with all strings, but i've ran into a bit of a problem comparing the following results
NSLog([[self obfuscate:#"0000", #"maki"]); //Returns 0]<W
NSLog([[self obfuscate:#"0809", #"maki"]); //Returns 0]<W
As you can see, the two strings with numbers in, while different, return the same result! Whats gone wrong in the code i've attached to result in the same result for these two numbers?
Another example:
NSLog([self obfuscate:#"8000" withKey:#"maki"]); //Returns 8U4_
NSLog([self obfuscate:#"8290" withKey:#"maki"]); //Returns 8U4_ as well
I may be misunderstanding the concept of obfuscation, but I was under the impression that each unique string returns a unique obfuscated string!
Please help me fix this bug/glitch
Source of Code: http://iosdevelopertips.com/cocoa/obfuscation-encryption-of-string-nsstring.html
The problem is your last line. You create the new string with the original, unmodified data object.
You need to create a new NSData object from the modified dataPtr bytes.
NSData *newData = [NSData dataWithBytes:dataPtr length:data.length];
return [[NSString alloc] initWithData:newData encoding:NSUTF8StringEncoding];
But you have some bigger issues.
The calls to bytes returns a constant, read-only reference to the bytes in the NSData object. You should NOT be modifying that data.
The result of your XOR on the character data could, in theory, result in a byte stream that is no longer a valid UTF-8 encoded string.
The obfuscation algorithm that you have selected is based on XORing the data and the "key" values together. Generally, this is not very strong. Moreover, since XOR is symmetric, the results are very prone to producing duplicates.
Although your implementation is currently broken, fixing it would not be of much help in preventing the algorithm from producing identical results for different data: it is relatively straightforward to construct key/data pairs that produce the same obfuscated string - for example,
[self obfuscate:#"0123" withKey:#"vwxy"]
[self obfuscate:#"pqrs" withKey:#"6789"]
will produce identical results "FFJJ", even though both the strings and the keys look sufficiently different.
If you would like to "obfuscate" your strings in a cryptographically strong way, use a salted secure hash algorithm: it will produce very different results for even slightly different strings.

Resources