How to get desired values from BLE manufacturer data flutter - flutter

I am new to flutter and I am working on an app that reads data from a BLE beacon. I have scanned the device and got the manufacturer data as {256:[0,0,0,16,1,57,33,18,0,0,154,10,0,0,94,0]}
the device manufacturer told me to device data like :
KCBAdvDataManufacturerData = <.. .. .. .. .. .. .. .. be 21 01 00 50 08 00 00 5e ..>
The UUID - kCBAdvDataManufacturerData packet contains the sensor data as shown below:
Byte index 8 – 11 = Pressure 32bit value
Byte index 12 – 15 = Temperature 32bit value
Byte index 16 = Battery level in percentage
I am totally not getting any idea that in Dart how can I achieve it from
{256:[0,0,0,16,1,57,33,18,0,0,154,10,0,0,94,0]}
to
Byte index 8 – 11 = Pressure 32bit value
Byte index 12 – 15 = Temperature 32bit value
Byte index 16 = Battery level in percentage
and then
in a human-understandable form
here temperature is in C pressure in PSI and battery is in %.

There is a list of bytes so you can get sublists from that list with https://api.dart.dev/stable/2.9.1/dart-core/List/sublist.html
That sublist can be converted from 4 bytes into a signed integer for the pressure and temperature values:
Convert 4 byte into a signed integer
I am not sure the index values you have been given look quite right. I am assuming the data is in little endian format so my assumption on the data is:
Pressure = [33,18,0,0] = 4641 (Are you expecting a value of about 46.41psi?)
Temperature = [154,10,0,0] = 2714 (Are you expecting a value of about 27.14c?)
Battery = [94] = 94 (Are you expecting a value of 94%?)
This might be done like the following:
import 'dart:typed_data';
var manufacturerData = Uint8List.fromList([0,0,0,16,1,57,33,18,0,0,154,10,0,0,94,0]);
var pressure = ByteData.sublistView(manufacturerData, 6, 10);
var temperature = ByteData.sublistView(manufacturerData, 10, 14);
var battery = ByteData.sublistView(manufacturerData, 14, 15);
main() {
print(pressure.getUint32(0, Endian.little));
print(temperature.getUint32(0, Endian.little));
print(battery.getUint8(0));
}
Gives me the output:
4641
2714
94

Related

Packetsize in Gamepsparks Realtime

My packet in gamesparks contains:
Two vector2: 8bytes x 2 = 16bytes
key values with vector 2 = 8bytes
peerid present in packet = 4bytes
opCode present in packet = 4bytes
Total = 32bytes.
However my packet size is a little big bigger than this. Am i missing something in the packet that i should account for ?

Find most significant bit in Swift

I need to find the value (or position) of the most significant bit (MSB) of an integer in Swift.
Eg:
Input number: 9
Input as binary: 1001
MS value as binary: 1000 -> (which is 8 in decimal)
MS position as decimal: 3 (because 1<<3 == 1000)
Many processors (Intel, AMD, ARM) have instructions for this. In c, these are exposed. Are these instructions similarly available in Swift through a library function, or would I need to implement some bit twiddling?
The value is more useful in my case.
If a position is returned, then the value can be easily derived by a single shift.
Conversely, computing position from value is not so easy unless a fast Hamming Weight / pop count function is available.
You can use the flsl() function ("find last set bit, long"):
let x = 9
let p = flsl(x)
print(p) // 4
The result is 4 because flsl() and the related functions number the bits starting at 1, the least significant bit.
On Intel platforms you can use the _bit_scan_reverse intrinsic,
in my test in a macOS application this translated to a BSR
instruction.
import _Builtin_intrinsics.intel
let x: Int32 = 9
let p = _bit_scan_reverse(x)
print(p) // 3
You can use the the properties leadingZeroBitCount and trailingZeroBitCount to find the Most Significant Bit and Least Significant Bit.
For example,
let i: Int = 95
let lsb = i.trailingZeroBitCount
let msb = Int.bitWidth - 1 - i.leadingZeroBitCount
print("i: \(i) = \(String(i, radix: 2))") // i: 95 = 1011111
print("lsb: \(lsb) = \(String(1 << lsb, radix: 2))") // lsb: 0 = 1
print("msb: \(msb) = \(String(1 << msb, radix: 2))") // msb: 6 = 1000000
If you look at the disassembly(ARM Mac) in LLDB for the Least Significant Bit code, it uses a single instruction, clz, to count the zeroed bits. (ARM Reference)
** 15 let lsb = i.trailingZeroBitCount
0x100ed947c <+188>: rbit x9, x8
0x100ed9480 <+192>: clz x9, x9
0x100ed9484 <+196>: mov x10, x9
0x100ed9488 <+200>: str x10, [sp, #0x2d8]

Bitwise operations in Swift, reading values from beacon data

I need some help interpreting a formula. This is from the documentation of a beacon I am experimenting with. I have written it in Swift but I can't get it to work. No matter the values the temperature variable ends up as 0.
From documentation:
*The major ID broadcasts the most significant 8 bits of the humidity and the most significant 8 bits of the temperature, and the
minor ID broadcasts the next 2 bits of temperature (for a total of the 10 most significant bits) and the 14 least significant bits
of the minor ID as the really Minor configured by user.
So the humidity is 8 bits in total, and the temperature is 10 bits in total.
Example:
So the humidity:
uint16_t Humidity = Major(As Hex value) & 0xFF00;
The temperature:
uint16_t temperature = ((Major(As Hex value) & 0x00FF) << 8 ) & ((Minor(As Hex value) &
0xC000) >> 8);
The really Minor:
uint16_t Real Minor = Minor(As Hex value) & 0x03FF;
This is what I came up with and it seems correct but the result from the last bitwise AND returns 0*
let majorAnd = UInt16(beacon.major) & 0x00FF
let majorShift = majorAnd << 8
let minorAnd = UInt16(beacon.minor) & 0xC000
let minorShift = minorAnd >> 8
let temperatureResult = majorShift & minorShift
Your problem is here:
let temperatureResult = majorShift & minorShift
replace it with:
let temperatureResult = majorShift | minorShift
Bitwise AND & is only going to give a result when there are bits in common between the two operands. In your case, they are mutually exclusive, You should combine them with bitwise OR |.
There is also a problem with the way you are shifting the values. Here is the corrected solution:
let majorAnd = UInt16(beacon.major) & 0x00FF
let majorShift = majorAnd << 2 // make space for the last 2 bits
let minorAnd = UInt16(beacon.minor) & 0xC000
let minorShift = minorAnd >> 14 // shift off the unwanted 14 bits
let temperatureResult = majorShift | minorShift
You'll need to shift your humidity as well:
let humidity = UInt16(beacon.major) & 0xFF00 >> 8
In the two shift right >> cases above, as a shortcut, you can skip the masking because those bits are being tossed anyway:
let minorShift = UInt16(beacon.minor) >> 14
let humidity = UInt16(beacon.major) >> 8

Bluetooth in SWIFT: Get 19 bytes data and convert to UInt

I would like to connect the Concept2 rower to my iPhone.
The corresponding Bluetooth data sheet can be found here : http://www.concept2.com/files/pdf/us/monitors/PM5_BluetoothSmartInterfaceDefinition.pdf
I would like to get back the different data: ElapsedTime, Distance, Split/interval, etc..
From the UUID adress 0X0031 I get a 19 bytes data in the following order:Elapsed Time Lo (0.01 sec lsb), Elapsed Time Mid, Elapsed Time High, Distance Lo (0.1 m lsb), Distance Mid, Distance Hi, ...
So 1 byte corresponds to 1 attribute.
I need to extract the bytes corresponding to the attribute and convert them.
I think all bytes data are unsigned types (for extraction).
The ElapsedTime variable is on 3 bytes. SO to build the ElapsedTime variable I was computing like this:
class func dataToUnsignedBytes8(value:NSData) -> [UInt8]{
let count = value.length
var array = [UInt8](count: count, repeatedValue: 0)
value.getBytes(&array, length: count * sizeof(UInt8))
return array
}
class func getElapsedTime(value : NSData) -> Double {
let dataFromSensor = dataToSignedBytes8(value)
let elapsedTime = Double(dataFromSensor[2] * 65536 + dataFromSensor[1]*256 + dataFromSensor[0])
return elapsedTime
}
But I'm not sure about what I'm doing.
Does the ElapsedTime_Hi byte is at index 3 of dataFromSensor, ElapsedTime_Mid is at index 2 of dataFromSensor and ElapsedTime_Lo at index 0 dataFromSensor ?
What is the best way to extract the corresponding byte for other attributes ?
Thank you in advance
Regards

Amount of data to be sent to peripheral using bluetooth in ios 8

I am working in data transferring using bluetooth from BLE device to peripheral hardware. I want to write data from binary file in chunks as total data length is 143233. I found one line "Maximal MTU was 132 bytes for iOS 7 devices and 20 B for iOS 6" but what about iOS 8?
What will be maximum size of chunks for iOS 8? This is the code which I have used, I dont know whether i am going right way or not so help me and guide me if i am going wrong. Thanks in advance.
var count:Int = 0
var counter:Int = 0
var str:NSString = NSBundle.mainBundle().pathForResource("spp", ofType: "bin")!
println("string value is \(str)")
var dataFile:NSString = NSString.stringWithContentsOfFile(str, encoding: NSASCIIStringEncoding, error: nil)
data = dataFile.dataUsingEncoding(NSUTF8StringEncoding)
println(data!.length)
println(dataFile.length)
var dataLen:Int = data!.length
if (dataLen > 132)
{
while(count < dataLen && dataLen - count > 132)
{
peripheral.writeValue(data!.subdataWithRange(NSMakeRange(count, 132)), forCharacteristic: arrCharacteristics!.objectAtIndex(1) as CBCharacteristic , type: CBCharacteristicWriteType.WithResponse)
NSThread.sleepForTimeInterval(0.005)
println("Write performed \(counter++ )")
count += 132
}
} if (count < dataLen)
{
peripheral.writeValue(data!.subdataWithRange(NSMakeRange(count, dataLen - count)), forCharacteristic: arrCharacteristics!.objectAtIndex(1) as CBCharacteristic , type: CBCharacteristicWriteType.WithResponse)
}
I'm guessing Jalek found his answer but for anyone else seeking the figures.
iOS 7 requests a 135 byte MTU (132 bytes data + 3 overhead).
iOS 8 requests a 158 byte MTU (155 bytes data + 3 overhead).
Obviously, it will depend on the other device whether these values are accepted or a lower value returned.