iOS: wrong value for characteristic with low energy bluetooth device? - ios

I have a low energy bluetooth device which picks up signal comparable to a heart-monitoring device. This data is plotted in real-time on a separate plotting screen.
My issue is that I think the values I'm getting from the hardware is wrong.
In my method didUpdateValueForCharacteristic a few lines of relevant info is:
case TI_KEYFOB_ACCEL_X_UUID: // x value characteristic
{
UInt8 xval[20];
[characteristic.value getBytes:&xval length:TI_KEYFOB_ACCEL_READ_LEN];
I then proceed to do some calculations on each value in the array which should each be a byte. Through each iteration (I think 256 Hz) I get 20 bytes of data and this gets pushed into an array of size 20.
These are the values from the characteristic.value that I'm getting for all 20 bytes:
[0] UInt8 '\x9b'
[1] UInt8 '\xe1'
[2] UInt8 '\xba'
[3] UInt8 '9'
[4] UInt8 '\x01'
[5] UInt8 '\0'
[6] UInt8 '\0'
[7] UInt8 '\0'
[8] UInt8 '\x01'
[9] UInt8 '\0'
[10] UInt8 '\0'
[11] UInt8 '\0'
[12] UInt8 '\b'
[13] UInt8 'M'
[14] UInt8 '\xd5'
[15] UInt8 '''
[16] UInt8 '\x1f'
[17] UInt8 '\xe6'
[18] UInt8 '\xbb'
[19] UInt8 '9'
I'm not sure what these values are actually representing. It looks like part is binary and part is maybe hexidecimal values of addresses.
All I know is that I can multiply these values by other integers and somehow get a constant string of the same numbers.
1,0,0,0,1,0,0,0,8,125,214,39,31,230,187,57,49,225,186,57
But this isn't the value that I want. I'm kind of lost, I've tried switching the characteristic.value to characteristic.valueHandle and other things, but I think it should be importing the data into the portion of value so the way it's written should be good.
I've also tried changing the TI_KEYFOB_ACCEL_X_UUID to other characteristics like ...Y_UUID but I'm pretty sure it should be obtaining the relevant data from X_UUID.
Anyways, any help at all or pointing me in the right direction would help.

Looking around, I am seeing that TI_KEYFOB_ACCEL_READ_LEN should only by 1.
case TI_KEYFOB_ACCEL_X_UUID: {
char xval;
[characteristic.value getBytes:&xval length:TI_KEYFOB_ACCEL_READ_LEN];
float x = (float)xval;
...

Related

Convert bytes to signed integers in lua 5.1.5

I'm looking for how to turn bytes into a signed int using lua 5.1.5, so far I've only been able to find solutions for lua 5.2 onward, and they are not backward compatible.
I have solutions for how to turn bytes into unsigned integers, like so:
payload_t.temperature=tonumber(utility.hex2str(string.sub(payload,32,33)),16)
First of all I'll assume that you actually have a byte string rather than a hex string given; if your string is a hex string, you can trivially convert it to a byte string using gsub:
function hex2bytes(str)
-- assert that it is indeed a string of hex digit pairs
assert(#str % 2 == 0 and not str:match"[^%x]")
return str:gsub("%x%x", function(hex) return tonumber(hex, 16) end)
end
Now, let's convert this byte string to an integer. I'll assume little endian (least significant byte first); should your string be big endian (most significant byte first) you'll have to reverse it using str:reverse() before you read it.
Reading an unsigned integer is pretty straightforward:
function bytes2uint(str)
local uint = 0
for i = 1, #str do
uint = uint + str:byte(i) * 0x100^(i-1)
end
return uint
end
I'll assume your integers are stored using Two's complement. In this case the higher 2^n values (equivalent to the first bit being set or the value being >= 2^(n-1)) the uint can take represent negative numbers, with the smallest value (2^(n-1)) representing the largest negative value (-2^(n-1)). Thus you can simply subtract the unsigned value from 2^n, the (exclusive) max value for the uint:
function bytes2int(str)
local uint = bytes2uint(str)
local max = 0x100 ^ #str
if uint >= max / 2 then
return uint - max
end
return uint
end

How to convert two 4-bit chunk into 1 byte in Dart?

byte 0: min_value (0-3 bit)
max_value (4-7 bit)
The byte0 should be the min and max values combined.
min and max values are both integers (in 0-15 range).
I should convert them into 4-bit binary, and combine them somehow? (how?)
E.g.
min_value=2 // 0010
max_value=3 // 0011
The result should be an Uint8, and the value: 00100011
You can use the shift left operator << to get the result you want:
result = ((min_value << 4) + max_value).toRadixString(2).padLeft(8, '0');

Unpack byte array from BLE packet

Im developing an app using BLE where iPhone device is the peripheral, and will respond to write requests of type CBATTRequest from the Central.
My take is that this represents a byte array from value of CBATTRequest via request.value of type NSData that I can unpack to read packet # etc. Given the size (octets) and position of each field, how can I unpack and read each value, conceptually and technically?. And how would I go about constructing/packing this same byte array as if I was preparing to send this request? Since I will have to pack data in the same manner for the response.
When you receive the data, it's probably in a CBATTRequest. The data is contained in a member value of type NSData. The member length tells the length in bytes/octects.
CBATTRequest* request = ...;
NSData* value = request.value;
int packetLen = value.length;
It then makes sense to cast this to a struct that corresponds to the structure of the packet:
struct Packet {
unsgined char pktNo;
unsigned char ctrlCmd;
unsigned char txPowerRequest;
unsigned char uuid[2];
unsigned char txCnt;
unsigned char userPayload[14];
};
Packet* packet= (Packet)value.bytes;
Note that packet is of variable length. So only part of the userPayload is valid. The valid length is:
int userPayloadLength = packetLen - 6;
Now you can easily access the members:
int packetNumber = packet->pktNo;
To construct a similar packet, you would approach is slightly similarly.
Packet reponse;
response.pktNo = ...;
reponse.ctrlCmd = ...;
int userPayloadLength = 5;
NSData* value = [NSData dataWithBytes: &response length: userPayloadLength + 6];
Bit 4 to 0 set to 0x01 for..
This most likely is relative to a single octect, e.g. to ctrlCmd. To test it:
if (((packet->ctrlCmd >> 0) & 0x1f) == 0x01) ...
0x1f is the bit mask for 5 consecutive bits set (bit 0 to 5). >> 0 doesn't do anything but would be required if the bits were shifted, e.g. for bit 2 to 5 you would need to shift by 2.
A typical UUID is 16 bytes long. So I assume byte index 13 & 12 refers to bytes 12 and 13 within a 16 byte UUID (as only two bytes are transmitted). The remaining bytes are probably fixed to the base Bluetooth UUID:
00000000-0000-1000-8000-00805F9B34FB

PGMidi changing pitch sendBytes example

I'm trying the second day to send a midi signal. I'm using following code:
int pitchValue = 8191 //or -8192;
int msb = ?;
int lsb = ?;
UInt8 midiData[] = { 0xe0, msb, lsb};
[midi sendBytes:midiData size:sizeof(midiData)];
I don't understand how to calculate msb and lsb. I tried pitchValue << 8. But it's working incorrect, When I'm looking to events using midi tool I see min -8192 and +8064 max. I want to get -8192 and +8191.
Sorry if question is simple.
Pitch bend data is offset to avoid any sign bit concerns. The maximum negative deviation is sent as a value of zero, not -8192, so you have to compensate for that, something like this Python code:
def EncodePitchBend(value):
''' return a 2-tuple containing (msb, lsb) '''
if (value < -8192) or (value > 8191):
raise ValueError
value += 8192
return (((value >> 7) & 0x7F), (value & 0x7f))
Since MIDI data bytes are limited to 7 bits, you need to split pitchValue into two 7-bit values:
int msb = (pitchValue + 8192) >> 7 & 0x7F;
int lsb = (pitchValue + 8192) & 0x7F;
Edit: as #bgporter pointed out, pitch wheel values are offset by 8192 so that "zero" (i.e. the center position) is at 8192 (0x2000) so I edited my answer to offset pitchValue by 8192.

Reading a Shapefile with ColdFusion

I am trying to read a binary file and parse the bytes I have the white paper spec on Shapefiles to know how to parse the file, however I cannot seem to find the correct functions in ColdFusion to handle reading bytes and deciding what to do with them.
<cffile action="READBINARY"
file="mypath/www/_Dev/tl_2009_25_place.shp"
variable="infile" >
PDF file with spec:http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf
For example I have the spec:
Position Field Value Type Order
Byte 0 File Code 9994 Integer Big
Byte 4 Unused 0 Integer Big
Byte 8 Unused 0 Integer Big
Byte 12 Unused 0 Integer Big
Byte 16 Unused 0 Integer Big
Byte 20 Unused 0 Integer Big
Byte 24 File Length File Length Integer Big
Byte 28 Version 1000 Integer Little
Byte 32 Shape Type Shape Type Integer Little
Byte 36 Bounding Box Xmin Double Little
Byte 44 Bounding Box Ymin Double Little
Byte 52 Bounding Box Xmax Double Little
Byte 60 Bounding Box Ymax Double Little
Byte 68* Bounding Box Zmin Double Little
Byte 76* Bounding Box Zmax Double Little
Byte 84* Bounding Box Mmin Double Little
Byte 92* Bounding Box Mmax Double Little
If this was just a flat text file i would use mid function to read my positions.
Can this be done in ColdFusion and Which functions can achieve my goal?
I found this function inside of FarStream.as found at http://code.google.com/p/vanrijkom-flashlibs/wiki/SHP which is an Actionscript3 file, but it represents the kind of task i need to do.
private function readHeader(e: ProgressEvent): void {
// check header:
if (! ( readByte()==0x46
&& readByte()==0x41
&& readByte()==0x52
))
{
dispatchEvent(new IOErrorEvent
( IOErrorEvent.IO_ERROR
, false,false
, "File is not FAR formatted")
);
close();
return;
}
// version:
vMajor = readByte();
vMinor = readByte();
if (vMajor>VMAJOR) {
dispatchEvent(new IOErrorEvent
( IOErrorEvent.IO_ERROR
, false,false
, "Unsupported archive version (v."+vMajor+"."+vMinor+")")
);
close();
return;
}
// table size:
tableSize = readUnsignedInt();
// done processing header:
gotHeader= true;
}
And here is the final solution
<cfset shapeFile = createObject("java","com.bbn.openmap.layer.shape.ShapeFile").init('/www/_Dev/tl_2009_25_place.shp')>
<cfdump var="#shapeFile.getFileLength()#">
<cffile action="READBINARY" file="mypath/www/_Dev/tl_2009_25_place.shp" variable="infile" >
<cfset shapeFile = createObject("java","com.bbn.openmap.layer.shape.ShapeFile").init(infile)>
<cfdump var="#shapeFile#">
Maybe something like this?

Resources