I have no prior experience of working with bluetooth sensors and parsing raw values. I am trying to parse the characteristic value but I am not really sure how to actually read and parse it. Data description of the characteristic I am trying to parse is here: https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.csc_measurement.xml
Here is following code
func peripheral(peripheral: CBPeripheral, didUpdateNotificationStateForCharacteristic characteristic: CBCharacteristic, error: NSError?) {
parseData(characteristic.value)
}
private func parseData(data: NSData?) {
if let data = data {
var values = [UInt8](count:data.length, repeatedValue:0)
data.getBytes(&values, length:data.length)
print(values)
}
}
The output looks something like this
[2, 14, 0, 16, 56]
[2, 16, 0, 249, 62]
[2, 18, 0, 175, 191]
[2, 23, 0, 90, 195]
[1, 2, 0, 0, 0, 251, 206]
[1, 3, 0, 0, 0, 145, 208]
[1, 4, 0, 0, 0, 5, 212]
[1, 5, 0, 0, 0, 25, 217]
Now first, I am not really sure if I have to parse this into UInt8, that's the part which is not clear and I cannot understand what bluetooth website says coz there are UInt32 and UInt16 variables. How would I parse that from a single raw data. I think I am getting this whole thing wrong but thats what I am trying to understand. Thanks in advance.
Related
connecting TCP Socket server and sending Request. and also Server sends the response in Byte array. How to read byte array data in dart.
Socket.connect('localhost', 8081)
.then((socket) {
//Establish the onData, and onDone callbacks
socket.listen((data) {
print(new String.fromCharCodes(data).trim()); //Here data is byte[]
//How to read byte array data
},
onDone: () {
print("Done");
// socket.destroy();
},
onError: (e) {
print('Server error: $e');
});
socket.add([255, 12, 0, 11, 0, 9, 34, 82, 69, 70, 84, 65, 72, 73, 76]);
});
}
It depends on with data type was encoded to bytes. Let's suppose it's String
Then you can do it with dart:convert library.
import 'dart:convert' show utf8;
final decoded = utf8.decode(data);
It's pretty clear that there's a message structure in those bytes. You give two examples of messages:
[255, 12, 0, 11, 0, 9, 34, 82, 69, 70, 84, 65, 72, 73, 76]
and
[255, 20, 0, 11, 0, 0, 0, 15, 80, 82, 69, 77, 84, 65, 72, 73, 76, 45, 53, 53, 57, 55, 48]
Both start with 255, followed by what looks like two or three little endian 16 bit words (12 and 11) and (20, 11 and 0) followed by a string, who's length is encoded in a leading byte. If you are expected to inter-operate with another system, you really need the protocol spec.
Assuming I've guessed the structure correctly, this code
main() {
Uint8List input = Uint8List.fromList([
255,
20,
0,
11,
0,
0,
0,
15,
80,
82,
69,
77,
84,
65,
72,
73,
76,
45,
53,
53,
57,
55,
48
]);
ByteData bd = input.buffer.asByteData();
print(bd.getUint16(1, Endian.little)); // print the first short
print(bd.getUint16(3, Endian.little)); // and the second
print(bd.getUint16(5, Endian.little)); // and the third
int stringLength = input[7]; // get the length of the string
print(utf8.decode(input.sublist(8, 8 + stringLength))); // decode the string
}
produces
20
11
0
PREMTAHIL-55970
as expected
I am trying to read data from UDP socket. I am using Xcode 9.2 and Swift and I want to implement communication without external libraries. I can send the data (testing using Packet Sender), but the problem is when I send the packet back and try to read data. My socket callback function gets called and callback type matches data callback. If I try to load CFData from memory using the pointer, the operation doesn't crash. Then when I try to use a CFDataGetLength or similar function on that object, the app crashes.
func socketCallback(socket: CFSocket?, callbackType: CFSocketCallBackType, address: CFData?, data: UnsafeRawPointer?, info: UnsafeMutableRawPointer?) {
if callbackType == CFSocketCallBackType.dataCallBack {
print("dataCallback called.")
let cf = data!.load(as: CFData.self)
print(cf) // prints __NSCFData
print(CFDataGetLength(cf)) // crashes
}
}
The exception being thrown:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[__NSCFData length]: unrecognized selector sent to class 0x10ca08348'
Same exception for other CFData functions, not just CFDataGetLength, for example
var bytes = [UInt8]()
print(CFDataGetBytes(cf, CFRange(location: 0, length: 3), &bytes))
I have tried to read some data from memory as unsigned bytes, at pointer (data) and with offset:
var array = [UInt8]()
for i in 0...55 {
let pointer = data! + i
array.append(pointer.load(as: UInt8.self))
}
print(array, separator: ", ", terminator: "\n")
It prints the following:
[72, 67, 103, 5, 1, 0, 0, 0, 132, 20, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 97, 97, 0, 0, 0, 0, 0]
I noticed that the number 3 is the length of the message, and bytes 48, 49 and 50 are the data (I have send "aaa", 97 is "a" in ascii).
Socket initialization code:
var socket = CFSocketCreate(nil, PF_INET, SOCK_DGRAM, IPPROTO_UDP, CFSocketCallBackType.dataCallBack.rawValue, socketCallback, nil)
let runLoopSource = CFSocketCreateRunLoopSource(nil, socket, 0)
CFRunLoopAddSource(CFRunLoopGetMain(), runLoopSource, CFRunLoopMode.defaultMode)
Most information that I found was for ObjC and I am not very familiar with ObjC.
What could I have done wrong?
I am iOS developer & I have JSON file in my project. I am getting below JSON array from a file saved as below
["fa", "pinfield", [
[0, 0, 26082730, ["pt", 213.3332769870769, 584.3332864443584, 414, 226]],
[1, 0, 26082819, ["pt", 0, 0, 414, 226]]
]],
["fa", "pinfield", [
[0, 0, 26084394, ["pt", 195.999944249791, 529.3332950671626, 414, 226]],
[1, 0, 26084475, ["pt", 0, 0, 414, 226]]
]],
["fa", "pinfield", [
[0, 0, 26082219, ["pt", 221.3332726558057, 555.9999453624226, 414, 226]],
[1, 0, 26082310, ["pt", 0, 0, 414, 226]]
]],
["fa", "pinfield", [
[0, 0, 26083275, ["pt", 200.3332853317256, 641.3332811991493, 414, 226]],
[1, 0, 26083364, ["pt", 0, 0, 414, 226]]
]],
["fa", "pinfield", [
[0, 0, 26083755, ["pt", 224.3332901000954, 705.3332707087325, 414, 226]],
[1, 0, 26083836, ["pt", 0, 0, 414, 226]]
]]
There are five objects in this array & each array have sub-arrays.
Now is there any way to calculate the average of above values & put into a signle array as below
["fa", "pinfield", [
[0, 0, xxx, ["pt", xxx.xxxxx, xxx.xxxxx, xxx.xxxxx, xxx.xxxxx]],
[1, 0, xxx, ["pt", 0, 0, xxx.xxxxx, xxx.xxxxx]]
]]
I can run for loops but it will be a time taking approach. Any help would be great.
At some level solving this problem will involve looping through your array of data, building sum and average values.
You could use the Swift reduce higher-order function to build a sum of all of the other values, and then calculate the average in a final step.
An example of using reduce to calculate the sum and average of a simpler array:
let array = [1, 7, 14, 35, 14, 12, 17]
let sum = array.reduce(0, +)
let average = Double(sum) / Double(array.count)
print("Sum = \(sum), avrage = \(average)")
How to convert signed array of [Int8] to unsigned array of [UInt8].
let arryData: [Int8] = [-108, 11, -107, -14, 35, -57, -116, 118, 54, 91, 12, 67, 21, 29, -44, 111]
I just want to convert this above into array of Unsigned [UInt8]. How to achieve this in swift.? Thanks in advance.
If your intention is to convert signed 8-bit integers to
unsigned ones with the same bit representation (e.g. -1 -> 255):
let intArray: [Int8] = [0, 1, 2, 127, -1, -2, -128]
let uintArray = intArray.map { UInt8(bitPattern: $0) }
print(uintArray)
// [0, 1, 2, 127, 255, 254, 128]
[Int8] -> [UInt8]
You haven't specified how you want to treat negative values; by flipping them to their positive counterpart or by removing them. Below follows both cases.
Transforming negative values to positive ones by flipping sign:
let arrayData: [Int8] = [-108, 11, -107, -14, 35, -57, -116, 118, 54, 91, 12, 67, 21, 29, -44, 111]
let arrayDataUnsigned = arrayData.map { UInt8(abs($0)) }
/* [108, 11, 107, 14, 35, 57, 116, 118, 54, 91,
12, 67, 21, 29, 44, 111] */
Or, by removing the negative values:
let arrayDataUnsigned = arrayData.flatMap { $0 < 0 ? nil : UInt8($0) }
/* [11, 35, 118, 54, 91, 12, 67, 21, 29, 111] */
I'm trying to work out an example which is provided on developer.apple.com website 'Swift Playground'. I had to adapt it a little since swift 2 is, what looks like, different in handling 'inout' variables. In the example showed on the presentation 'inout' was not used in the function declaration. Anyway the result of 'data' is not showing in the Playground although the code doesn't show any compile errors.
import UIKit
var data = [16, 97, 13, 55, 95, 53, 18, 10, 79, 53, 79, 34, 50, 34, 0, 91, 94, 55, 6, 38, 7]
func exchange<T>(inout data:[T], i: Int, j: Int) {
let temp = data[i]
data[i] = data[j]
data[j] = temp
}
func swapLeft<T: Comparable>(inout data: [T], index: Int) {
for i in reverse(1...index) {
if data[i] < data[i-1] {
exchange(&data, i, i-1)
}else {
break
}
}
}
func isort<T: Comparable>(inout data: [T]) {
for i in 1...data.count {
swapLeft(&data,i)
}
}
data //result [16, 97, 13, 55, 95, 53, 18, 10, 79, 53, 79, 34, 50, 34, 0, 91, 94, 55, 6, 38, 7]
isort(&data)
data //no result shown
Screenshot
It isn't showing a result because it is crashing with Array index out of range. Try this for isort:
func isort<T: Comparable>(inout data: [T]) {
for i in 1..<data.count {
swapLeft(&data,i)
}
}
You can always use println(data)
Make sure your Debug Area is shown. See this post for more info.