IOS:Convert hex values from the characterstic.value result - ios

i am able to retrieve value from the peripheral as hex value and i need to convert as per my requirement.[24/12/14 11:37:00 am] sonali_phatak: I can see that i have received proper response.from 01117100352e36302e313100000000e55a
01 - 01-start byte
11 - 17(Dec) - length of responce packet
71 - response ID
00 - Ignore this byte
So now out of total length 17, first 4 bytes are header, last 2 bytes are CRC. We
need to read remaining 11 bytes and convert them to ASCII.
35 - 5
2e - .
36 - 6
30 - 0
2e - .
31 - 1
31 - 1
So Iam getting version number from watch as 5.60.11
But i need to show the above value 5.60.11 in string and print in console . how to convert it pleas help me

Please try this :
NSString *strOriginalHex= #"01117100352e36302e313100000000e55a";
NSString *strNewHexForVersion = [strOriginalHex substringWithRange:NSMakeRange(8, 14)];
NSLog(#"%#",[self stringFromHexString:strNewHexForVersion]);//5.60.11
- (NSString *)stringFromHexString:(NSString *)aStrHexString
{
// The hex codes should all be two characters.
if (([aStrHexString length] % 2) != 0)
return nil;
NSMutableString *aMutStrNewString = [NSMutableString string];
for (NSInteger i = 0; i < [aStrHexString length]; i += 2)
{
NSString *hex = [aStrHexString substringWithRange:NSMakeRange(i, 2)];
NSInteger decimalValue = 0;
sscanf([hex UTF8String], "%x", &decimalValue);
[aMutStrNewString appendFormat:#"%c", decimalValue];
}
return aMutStrNewString;
}

Related

How to reinterpret data given by AVAudioRecorder as const char *?

PROBLEM:
The problem I am trying to solve is the following. I have audio data recorded by AVAudioRecorder. I can get the NSData by:
NSData *data = [NSData dataWithContentsOfURL: self.audioRecorder.url];
But then I need to convert/reinterpret this NSData to a const char* form which would essentially look like
00 01 00 ff
which are bytes in hex or at least the equivalent string. They don't have to be actually in hex but just needs to be convertible to hex.
QUESTION:
My question is that the NSData has "\0" in them. So if I do something like this:
NSUInteger len = [data length];
Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, [data bytes], len);
It would not work as the data will be cutoff when it meets the first "\0". I am super new to audio files, but I think it is because of the x00 values in the header. So basically, I don't want to them to be interpreted as "\0" but as "00". Is there a way to do this?
Not sure I understand the question or what you are trying to do. Your memcpy will copy all the bytes to the byteData buffer, it is only when you try to use the byteData buffer as a string (char*) and pass them into a format function (NSLog(%"%s", val)) will it cut off. If you want a string representation of the data as hex:
NSString* bytesToHex(Byte* bytes, NSUInteger count) {
NSMutableString *hex = [NSMutableString string];
for(int i = 0; i < count; i++) [hex appendFormat:#"%.2x " , *(bytes+i)];
return hex;
}
NSString* dataToHex(NSData* data) {
return bytesToHex((Byte*)data.bytes, data.length);
}
will do it, ie:
Byte* bytes = (Byte*)"t\0h\0i\0s\0 i\0s\0 a\0 t\0e\0st";
NSData* data = [NSData dataWithBytes:bytes length:24];
NSLog(#"%#",NSLog(#"%#", dataToHex(data));
will print:
74 00 68 00 69 00 73 00 20 69 00 73 00 20 61 00 20 74 00 65 00 73 74 00
or
Byte* bytes = (Byte*)"t\0h\0i\0s\0 i\0s\0 a\0 t\0e\0st";
NSData* data = [NSData dataWithBytes:bytes length:24];
NSUInteger len = [data length];
Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, [data bytes], len);
NSLog(#"%#", bytesToHex(byteData, len));
will print:
74 00 68 00 69 00 73 00 20 69 00 73 00 20 61 00 20 74 00 65 00 73 74 00
Just remembered something
Even easier, if you use the NSData description property, it gives you the data in hex already!
Byte* bytes = (Byte*)"t\0h\0i\0s\0 i\0s\0 a\0 t\0e\0st";
NSData* data = [NSData dataWithBytes:bytes length:24];
NSLog(#"%#", data.description);
Will print
<74006800 69007300 20690073 00206100 20740065 00737400>
Not as pretty, but the same thing...

iOS CoreMIDI Skipping MidiPackets

I'm having issues with implementing MIDI into my iOS app as the receiver callback seems to be skipping MIDI messages and packets. I'm using Midi Monitor to check what MIDI messages I'm missing, skipping over, etc.
So the million dollar question is why is iOS skipping certain MIDI messages? Sometimes it doesn't skip MIDI messages, but other times it does. I'm not sure how to approach debugging this as I have exhausted my brain at this point.
My receiver code:
void MidiReceiver(const MIDIPacketList *packets,
void *context, void *sourceContext) {
dispatch_async(dispatch_get_main_queue(), ^{
if (packets->numPackets > 0) {
MIDIPacket *packet = (MIDIPacket *)packets->packet;
// Loop through total number of packets
for (int i = 0; i < packets->numPackets; i++) {
// Go through each packet, iOS sometimes clumps all data into one packet
// if the MIDI messages are triggered at the same time
for (int j = 0; j < packet->length; j += 3) {
NSArray *array = [[NSArray alloc] initWithObjects:[NSNumber numberWithUnsignedInt:packet->data[j]],
[NSNumber numberWithUnsignedInt:packet->data[j+1]],
[NSNumber numberWithUnsignedInt:packet->data[j+2]], nil];
// Use the data to create do meaningful in the app
[myViewController processMidiData:array];
}
// Next packet
packet = MIDIPacketNext(packet);
}
}
});
The monitor code format is : (TIME) - (MIDI Command Type) - (CC Val or Velocity)
Midi Monitor Debug:
12:45:32.697 Control 0
12:45:32.720 Control 1
12:45:32.737 Control 1
12:45:32.740 Control 2
12:45:32.750 Control 3
12:45:32.763 Note Off A♯1 0
12:45:32.763 Note Off F2 0
12:45:32.763 Note Off D3 0
12:45:32.763 Control 4
12:45:32.770 Control 5
12:45:32.780 Control 6
12:45:32.790 Control 8
12:45:32.800 Control 9
12:45:32.810 Control 11
12:45:32.820 Control 13
12:45:32.832 Control 14
12:45:32.845 Control 16
12:45:32.850 Control 18
12:45:32.873 Control 21
12:45:32.883 Control 22
12:45:32.898 Control 24
12:45:32.913 Control 26
12:45:32.933 Control 27
12:45:32.948 Control 28
12:45:33.020 Control 27
12:45:33.030 Control 26
12:45:33.040 Control 25
12:45:33.050 Control 24
12:45:33.060 Control 22
My App's Debug Monitor:
12:45:33.050 Control 0
12:45:33.051 Control 1
12:45:33.051 Control 1
12:45:33.051 Control 2
12:45:33.051 Control 3
12:45:33.083 Note Off D3 0 <----- Where's A#1 and F2!!! :(
12:45:33.087 Control 4
12:45:33.087 Control 4
12:45:33.097 Control 5
12:45:33.100 Control 6
12:45:33.110 Control 8
12:45:33.120 Control 9
12:45:33.130 Control 11
12:45:33.140 Control 13
12:45:33.153 Control 14
12:45:33.165 Control 16
12:45:33.170 Control 18
12:45:33.193 Control 21
12:45:33.203 Control 22
12:45:33.218 Control 24
12:45:33.233 Control 26
12:45:33.256 Control 27
12:45:33.268 Control 28
12:45:33.341 Control 27
12:45:33.351 Control 26
12:45:33.361 Control 25
12:45:33.374 Control 24
12:45:33.381 Control 22
Got some help from Kurt Revis and it seemed like I was sending the packets too late due to my usage of dispatch_async.
My revised code (I parsed the packets first):
void MidiReceiver(const MIDIPacketList *packets,
void *context, void *sourceContext) {
NSMutableArray *packetData = [[NSMutableArray alloc] init];
if (packets->numPackets > 0 && object != nil) {
MIDIPacket *packet = &packets->packet[0];
// Loop through total number of packets
for (int i = 0; i < packets->numPackets; ++i) {
int idx = 0;
while (idx < packet->length) {
NSArray *array = [[NSArray alloc] initWithObjects:[NSNumber numberWithUnsignedInt:packet->data[idx]],
[NSNumber numberWithUnsignedInt:packet->data[idx+1]],
[NSNumber numberWithUnsignedInt:packet->data[idx+2]], nil];
[packetData addObject:array];
idx += 3;
}
packet = MIDIPacketNext(packet);
}
}
dispatch_async(dispatch_get_main_queue(), ^{
for (NSArray *packet in packetData) {
[object receiveMIDIInput:packet];
}
});
}

simple midi file writer in Objective C

I'm writing a program in Objective C to generate a MIDI file. As a test, I'm asking it to write a file which plays one note and stops it a delta tick afterwards.
But I'm trying to open it with Logic and Sibelius, and they both say that the file is corrupted.
Here's the hex readout of the file..
4D 54 68 64 00 00 00 06 00 01 00 01 00 40 - MThd header
4D 54 72 6B 00 00 00 0D - MTrk - with length of 13 as 32bit hex [00 00 00 0D]
81 00 90 48 64 82 00 80 48 64 - the track
delta noteOn delta noteOff
FF 2F 00 - end of file
And here's my routines to write the delta time, and write the note -
- (void) appendNote:(int)note state:(BOOL)on isMelody:(BOOL)melodyNote{ // generate a MIDI note and add it to the 'track' NSData object
char c[3];
if( on ){
c[0] = 0x90;
c[2] = volume;
} else {
c[0] = 0x80;
c[2] = lastVolume;
}
c[1] = note;
[track appendBytes:&c length:3];
}
- (void) writeVarTime:(int)value{ // generate a MIDI delta time and add it to the 'track' NSData object
char c[2];
if( value < 128 ){
c[0] = value;
[track appendBytes:&c length:1];
} else {
c[0] = value/128 | 0x80;
c[1] = value % 128;
[track appendBytes:&c length:2];
}
}
are there any clever MIDI gurus out there who can tell what's wrong with this MIDI file?
The delta time of the EOF event is missing.

Unable to convert NSData to NSString or any other format of informationElementData of CWNetwork

Friends,
It might look like familiar question but i really need help to convert NSData to any other understandable form. Basically i am using CoreWLAN framework and CWNetwork has properly called informationElement and it's data type is NSData. I have tried to convert it to any other readable format but not working. I have tried with all available string encoding. Below is sample code:
- (void) printNSData:(NSData *) dataToPrint forKey:(NSString *) key{
for(int i = 1 ; i < 16 ; i++){
size_t length = [dataToPrint length]+1;
unsigned char aBuffer[length];
[dataToPrint getBytes:aBuffer length:length];
aBuffer[length] = 0;
NSString *content = [[NSString alloc] initWithBytes:aBuffer
length:[dataToPrint length] encoding: i];
NSLog(#"%# : %# ", key,content);
}
/*
NSUTF16BigEndianStringEncoding = 0x90000100,
NSUTF16LittleEndianStringEncoding = 0x94000100,
NSUTF32StringEncoding = 0x8c000100,
NSUTF32BigEndianStringEncoding = 0x98000100,
NSUTF32LittleEndianStringEncoding = 0x9c000100,
NSProprietaryStringEncoding = 65536
*/
NSString *content = [[NSString alloc] initWithBytes:[dataToPrint bytes]
length:[dataToPrint length] encoding: NSUTF16BigEndianStringEncoding];
NSLog(#"%# : %# ",key, content);
content = [[NSString alloc] initWithBytes:[dataToPrint bytes]
length:[dataToPrint length] encoding: NSUTF16LittleEndianStringEncoding];
NSLog(#"%# : %# ",key, content);
content = [[NSString alloc] initWithBytes:[dataToPrint bytes]
length:[dataToPrint length] encoding: NSUTF32StringEncoding];
NSLog(#"%# : %# ", key,content);
content = [[NSString alloc] initWithBytes:[dataToPrint bytes]
length:[dataToPrint length] encoding: NSUTF32BigEndianStringEncoding];
NSLog(#"%# : %# ", key,content);
content = [[NSString alloc] initWithBytes:[dataToPrint bytes]
length:[dataToPrint length] encoding: NSUTF32LittleEndianStringEncoding];
NSLog(#"%# : %# ", key,content);
content = [[NSString alloc] initWithBytes:[dataToPrint bytes]
length:[dataToPrint length] encoding: NSProprietaryStringEncoding];
NSLog(#"%# : %#", key,content);
}
But i am getting either Null or empty response. Please please help.
Regards,
MP
You can't convert arbitrary data into a string. That only works for data that actually represents a string. Which is usually not the case if an API exposes a NSData object.
To get some meaning into the data you have to know what the data represents.
You might be able to get some structure into it by simply looking at it.
If I look at the first few bytes you have posted it looks like the data is well structured and not arbitrary.
The data seams to be split into packets. Each packet starts with a type identifier, which is followed by a $length byte. And then there will be $length bytes of data
The first packet contains the string "SYmantak"
00 08 53 79 6d 61 6e 74 61 6b
^^ Type Identifier
^^ Length
^^^^^^^^^^^^^^^^^^^^^^^ Data. In this case the ASCII string "SYmantak"
If you find a bunch of bytes that all lay between 0x20 and 0x7E you are probably looking at ASCII. That's basically how I figured out the payload of this packet. And because we have 8 bytes that are ASCII the 0x08 in front of the ASCII most likely means 8 bytes of data.
The next packets look like this:
01 08 82 84 0b 16 24 30 48 6c
^^ Type Identifier
^^ Length
^^^^^^^^^^^^^^^^^^^^^^^ Data. But not a ASCII string
03 01 06
2a 01 00
2f 01 00
30 14 01 00 00 0f ac 04 01 00 00 0f ac 04 01 00 00 0f ac 02 0c 00
32 04 0c 12 18 60
2d 1a 6e 18 1b ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
and so on. The general packet structure is quite easy to parse.
Though it will be very hard to turn these bytes into meaningful data. As you can see from the other packets, it's not always as easy as with the first packet that contained ASCII.
But please don't take this quickly reverse engineered structure for granted. I might be completely wrong about the meaning of these fields.
You should try to find the specification of this data. It should be somewhere in the IEEE 802.11 documents.

How to read a NSInputStream with UTF-8?

I try to read a large file in iOS using NSInputStream to separate the files line by newlines (I don't want to use componentsSeparatedByCharactersInSet as it uses too much memory).
But as not all lines seem to be UTF-8 encoded (as they can appear just as ASCII, same bytes) I often get the Incorrect NSStringEncoding value 0x0000 detected. Assuming NSASCIIStringEncoding. Will stop this compatiblity mapping behavior in the near future. warning.
My question is: Is there a way to surpress this warning by e.g. setting a compiler flag?
Furthermore: Is it save to append/concatenate two buffer reads, as reading from the byte stream, then converting the buffer to string and then appending the string could make the string corrupted?
Below an example method that demonstrates that the byte to string conversion will discard the first and second half of the UTF-8 character, as being invalid.
- (void)NSInputStreamTest {
uint8_t testString[] = {0xd0, 0x91}; // #"Б"
// Test 1: Read max 1 byte at a time of UTF-8 string
uint8_t buf1[1], buf2[1];
NSString *s1, *s2, *s3;
NSInteger c1, c2;
NSInputStream *inStream = [[NSInputStream alloc] initWithData:[[NSData alloc] initWithBytes:testString length:2]];
[inStream open];
c1 = [inStream read:buf1 maxLength:1];
s1 = [[NSString alloc] initWithBytes:buf1 length:1 encoding:NSUTF8StringEncoding];
NSLog(#"Test 1: Read %d byte(s): %#", c1, s1);
c2 = [inStream read:buf2 maxLength:1];
s2 = [[NSString alloc] initWithBytes:buf2 length:1 encoding:NSUTF8StringEncoding];
NSLog(#"Test 1: Read %d byte(s): %#", c2, s2);
s3 = [s1 stringByAppendingString:s2];
NSLog(#"Test 1: Concatenated: %#", s3);
[inStream close];
// Test 2: Read max 2 bytes at a time of UTF-8 string
uint8_t buf4[2];
NSString *s4;
NSInteger c4;
NSInputStream *inStream2 = [[NSInputStream alloc] initWithData:[[NSData alloc] initWithBytes:testString length:2]];
[inStream2 open];
c4 = [inStream2 read:buf4 maxLength:2];
s4 = [[NSString alloc] initWithBytes:buf4 length:2 encoding:NSUTF8StringEncoding];
NSLog(#"Test 2: Read %d byte(s): %#", c4, s4);
[inStream2 close];
}
Output:
2013-02-10 21:16:23.412 Test[11144:c07] Test 1: Read 1 byte(s): (null)
2013-02-10 21:16:23.413 Test[11144:c07] Test 1: Read 1 byte(s): (null)
2013-02-10 21:16:23.413 Test[11144:c07] Test 1: Concatenated: (null)
2013-02-10 21:16:23.413 Test[11144:c07] Test 2: Read 2 byte(s): Б
First of all, in line: s3 = [s1 stringByAppendingString:s2]; you are trying to concatenate to 'nil' values. The result would be 'nil' also. So, you may want to concatenate bytes instead of strings:
uint8_t buf3[2];
buf3[0] = buf1[0];
buf3[1] = buf2[0];
s3 = [[NSString alloc] initWithBytes:buf3 length:2 encoding:NSUTF8StringEncoding];
Output:
2015-11-06 12:57:40.304 Test[10803:883182] Test 1: Read 1 byte(s): (null)
2015-11-06 12:57:40.305 Test[10803:883182] Test 1: Read 1 byte(s): (null)
2015-11-06 12:57:40.305 Test[10803:883182] Test 1: Concatenated: Б
Secondary, length of UTF-8 character may lay in [1..6] bytes.
(1 byte) 0aaa aaaa //if symbol lays in 0x00 .. 0x7F (ASCII)
(2 bytes) 110x xxxx 10xx xxxx
(3 bytes) 1110 xxxx 10xx xxxx 10xx xxxx
(4 bytes) 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
(5 bytes) 1111 10xx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx
(6 bytes) 1111 110x 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx
So, if you are intended to read from NSInputStream raw bytes and then translate them into UTF-8 NSString, you probably want to read byte by byte from NSInputStream until you will get valid string:
#define MAX_UTF8_BYTES 6
NSString *utf8String;
NSMutableData *_data = [[NSMutableData alloc] init]; //for easy 'appending' bytes
int bytes_read = 0;
while (!utf8String) {
if (bytes_read > MAX_UTF8_BYTES) {
NSLog(#"Can't decode input byte array into UTF8.");
return;
}
else {
uint8_t byte[1];
[_inputStream read:byte maxLength:1];
[_data appendBytes:byte length:1];
utf8String = [NSString stringWithUTF8String:[_data bytes]];
bytes_read++;
}
}
ASCII (and hence the newline character) is a subset of UTF-8, so there should not be any conflict.
It should be possible to divide your stream at the newline characters, as you would in a simple ASCII stream. Then you can convert each chunk ("line") into an NSString using UTF-8.
Are you sure the encoding errors are not real, i.e., that your stream may actually contain erroneous characters with respect to a UTF-8 encoding?
Edited to add from the comments:
This presumes that the lines consist of sufficiently few characters to keep a whole line in memory before converting from UTF-8.

Resources