IOS BLE NSData int to byte issue - ios

I want to write values to BLE with writeValue:forCharacteristic:type:,
the value is an int value from 2000-01-01 00:00:00 to now in seconds.
int time_distance 468436137;
nsigned char *bytes=(unsigned char *)&time_distance;
NSData *da_sec=[NSData dataWithBytes: bytes length:sizeof(time_distance)];
da_sec is a9c4eb1b which is wrong, it rather should be 1bebc4a9.
a9 c4 eb 1b => 1b eb c4 a9.
this is reversed.. How can I solve this?

swift 3
var timeInterval:Int = Int(date.timeIntervalSince1970)
let data = NSData(bytes: &timeInterval, length:
MemoryLayout<Int>.size)
let sendData:Data = (data as Data)
self.selectPeripheral.writeValue(sendData, for: readWriteChar, type: .withResponse)

Related

SHA1 digest compare with String fingerprint in Swift

I have a string representation of web-site's fingerprint:
5D A8 E2 8A F7 D7 82 65 40 14 8C 8A 3C 4B 37 49 CE A4 B2 42
Then I need to match it with the certificate's hash, which I'm using CryptoKit for:
static func sha1FingerprintsForTrust(_ trust: SecTrust) -> [String] {
var sha1s: [String] = []
for index in 0..<SecTrustGetCertificateCount(trust) {
if let certificate = SecTrustGetCertificateAtIndex(trust, index) {
let der = SecCertificateCopyData(certificate) as NSData
let sha1 = Insecure.SHA1.hash(data: der)
print(sha1) //prints **SHA1 digest: 76e27ec14fdb82c1c0a675b505be3d29b4eddbbb**
}
}
return sha1s
}
how can I convert any of those to match it with the other? Either way: Insecure.SHA1.Digest into String or String into Digest to then compare them?
Side note: I am aware that SHA1 is deprecated and should not be used anymore.
As usual the answer is pretty simple:
sha1.hexString
That's the missing thing I was looking for. With that I get a String and the only thing left is to make format of those same (remove spaces and turn uppercased()) and then compare them.

Convert Swift struct to Data bytes

I want to pass bytes data to bluetooth service in a format that is expected by bluetooth firmware.
Expected data structure in c struct are:
typedef enum {
CMD_TX_INFO = 0,
CMD_DATA_REQ_START,
CMD_DATA_REQ_END,
CMD_DATA_REQ
} ble_cmd_type_t;
typedef struct ble_data_info_s
{
uint32_t data_size_bytes;
uint32_t info;
} ble_data_info_t;
typedef PACKED ( struct ble_cmd_info
{
ble_cmd_type_t cmd_type;
ble_data_info_t info;
uint8_t len;
uint8_t data[10];
}) ble_cmd_data_t;
I have converted the this to swift struct as follows:
enum BLECmdType : UInt8{
case CMD_TX_INFO = 0
case CMD_DATA_REQ_START
case CMD_DATA_REQ_END
case CMD_DATA_REQ
}
struct BLEDataInfo
{
let dataSizeBytes: UInt32
let info: UInt32
}
struct BLECmdData
{
let cmdType:BLECmdType
let info:BLEDataInfo
let len:UInt8
let data: Array<UInt8>?
}
Then i convert the swit struct object into bytes like this, i am not sure if this approach is correct? I am not getting the bytes in correct expected format:
var command = BLECmdData(cmdType:BLECmdType.CMD_DATA_REQ_START,
info: BLEDataInfo(dataSizeBytes: 100000, info: 10),
len: 1,
data: [1,2,3,4,5,6,7,8,9,10])
let bleData = Data(bytes: &command , count: MemoryLayout<BLECmdData>.stride)
Firstly is it possible to print the bytes generated for bleData object in string format so i can debug and see?
Secondly the bytes sent to BLE device are:
Bytes:
01 00 00 00 A0 86 01 00
E5 73 E0 98 0A 00 00 00
70 C5 CA 80
Firmware engineer mentioned, data should start with following:
Bytes:
01 00 A0 86 01 00
E5 73 E0 98
I am not sure if my approach to convert c struct to swift here is correct.
Looking forward for your reply.
Thanks
the result of the line
let bleData = Data(bytes: &command , count: MemoryLayout<BLECmdData>.stride)
it depends on what cpu architecture the programming you're running on. (32bits vs 64 bits, big-endian vs little-endian).
you have to ask Firmware engineer about the protocol to communicate with their devices, then you will encode the data as the format specified in the protocol. It isn't important that you store the data in a class/struct/enum etc..., the important thing is how the data is encoded.
I found a way to successfully push the data in correct format:
Set the values:
var cmdTypeCopy:UInt8 = BLECmdType.CMD_DATA_REQ_START
var imageInfo = BLEDataInfo(dataSizeBytes: 100000, info: 10)
var cmdLenCopy = 10
var cmdDataCopy:Array<UInt8> = [1,2,3,4,5,6,7,8,9,10]
Create Data:
var cmdTypeData = Data(bytes: &cmdTypeCopy, count: MemoryLayout<UInt8>.stride)
var imageInfoData = Data(bytes: &imageInfo, count: MemoryLayout<BLEImageInfo>.stride)
var cmdLenData = Data(bytes: &cmdLenCopy, count: MemoryLayout<UInt8>.stride)
var cmdDataData = Data(bytes: &cmdDataCopy, count: 10)
Then append one by one:
cmdTypeData.append(imageInfoData)
cmdTypeData.append(cmdLenData)
cmdTypeData.append(cmdDataData)
This worked perfectly and firmware got the data in correct format.

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...

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.

Resources