Write BLE gatt characteristic on Android — error status 255 - android-ble

Experimenting with sample kotlin program, trying to read/write BLE device with channels from 0-7
When reading it gives me value like this: (0x06)
onCharacteristicRead(), status=0, value=[uuid='ba7e7814-5b67-43d3-bd80-e72cc83ae801', hexValue=[06]]
but when trying to write same output it gives me, it gives me error GATT 255, out of range:
CharacteristicWriteOperation{MAC='00:A0:50:E8:78:86', characteristic=[uuid='ba7e7814-5b67-43d3-bd80-e72cc83ae801', hexValue=[30, 36]]}
onCharacteristicWrite(), status=255, value=[uuid='ba7e7814-5b67-43d3-bd80-e72cc83ae801']

What you read: [0x06]
onCharacteristicRead(), status=0, value=[uuid='ba7e7814-5b67-43d3-bd80-e72cc83ae801', hexValue=[06]]
What you wrote: [0x30, 0x36] (which may correspond to String "06" as ASCII hex value for '0' is 0x30 and for '6' is 0x36)
CharacteristicWriteOperation{MAC='00:A0:50:E8:78:86', characteristic=[uuid='ba7e7814-5b67-43d3-bd80-e72cc83ae801', hexValue=[30, 36]]}
You probably want to write back hexadecimal value 0x06, not the string "06"
Status 255 is GATT_OUT_OF_RANGE which means that the written value is outside of range accepted by your peripheral.

Related

NRF52 java unsigned byte issue

I am using ble with nrf52 and sending a byte array command from android with java like below
byte[] header=new byte[]{
(byte )0x5f,
(byte) 0xf0,
(byte) 0xf1,
(byte) 0xf2,
};
when I log these bytes to console, I see as below
[111,-16,-15,-14]
Device gots the command but doesn't send answer
However, if I send the same command from iOS with swift, command data showns as below
[111,240,241,242]
and works as aspected.
What may cause this behavior? May it be related java's unsingned byte support?
You are on the right track. While your iOS App handles the received data as 'unsigned bytes' the Android App interprets them as 'signed bytes'. You might want to treat them as unsigned values with the corresponding *unsigned methods, for example Byte.compareUnsigned

Sending a program change with a program number (patch number)

I have two Roland midi devices that behave the same when I try to send a bank and program change. It always sets it to the first patch of the bank. It won't change the patch I choose in the bank. Pro Logic can, however, switch to different banks.
The following example cause the devices to change to the bank but the program (patch) on the device defaults to the first in that bank and not number 9.
var event = AKMIDIEvent(controllerChange: 0, value: 89, channel: 0)
midiOut.sendEvent(event)
event = AKMIDIEvent(controllerChange: 32, value: 64, channel: 0)
midiOut.sendEvent(event)
event = AKMIDIEvent(programChange: 9, channel: 0)
midiOut.sendEvent(event)
Anyone have experience with sending this MIDI messages?
I was going through the same issue and was about to go crazy. It turns out the Program Change values in various MIDI data specifications, from various vendors, are 1 based. Not 0. Or perhaps it is the AudioKit implementation that is wrong?
So, instead of a programChange value of 9 you should use a value of 8. Here is my code for changing the current instrument on channel 0 to the Bösendorfer grand piano on a Yamaha Clavinova keyboard, where the programChange value in the MIDI data specification is designated as 1.
midiOut.sendControllerMessage(0, value: 108) // MSB sound bank selection
midiOut.sendControllerMessage(32, value: 0) // LSB sound bank selection
midiOut.sendEvent(AKMIDIEvent(programChange: 0, channel: 0)) // Initiate program change based on MSB and LSB selections
While reading various documentation about how MIDI works I also saw some forum posts describing keyboards that expect the LSB bank selection before the MSB bank selection. That is however not my understanding of how MIDI should work, but worth a try if you still cannot make it work with your Roland keyboards.

Preparing data in TLV8

I'm writing a HomeKit (so perhaps Bluetooth) characteristic in TLV8 format. Apple doc says
The value is an NSData object containing a set of one or more TLV8's,
which are packed type-length-value items with an 8-bit type, 8-bit
length, and N-byte value.
According to Wikipeida a type-length value is
Type
A binary code, often simply alphanumeric, which indicates the kind of field that this part of the message represents;
Length
The size of the value field (typically in bytes);
Value
Variable-sized series of bytes which contains data for this part of the message.
I have no idea how to pack one. I suppose I can write raw bytes to NSData, but what do I write for pad, if I need any padding, etc. So is there an example of how to do that?
Oh I figured it out.
TLV8 consist of three sections: "Tag", "Length", and "Value". I don't know what 8 means.
Both tag and length are UInt8. I believe what the tag may be depend on where the TLV8 is used. Length is the length of the value. Value is the content it self.
So when I want to send a simple 1 as a value, I use:
let tag = 0x02 // For example
let length = 0x01
let value = 0x01
let data = Data(bytes: [tag, length, value]) // NSData

Usocket unsigned byte 8 doesn't receive data while character element type does

I've run into some truly puzzling behavior with the USocket library. Consider the following snippet:
(defvar server-socket (usocket:socket-listen "localhost" 43593
:element-type
'(unsigned-byte 8)))
(defvar client-connection (usocket:socket-accept server-socket))
;in a separate terminal, type "telnet localhost 43593".
;then type some text and hit enter.
(listen (usocket:socket-stream client-connection))
=> NIL
Why is this happening? When I leave out :element-type '(unsigned-byte 8) from the arguments to usocket:socket-listen, it works just fine. I could understand if any arbitrary bytes couldn't be represented as characters (utf-8 encoding for example has invalid sequences of bytes), but the inverse - characters that can't be represented by bytes - makes no sense, especially in a network context.
(I'm running clisp-2.49 on Lubuntu 15.10, USocket 0.6.3.2, in case that helps).
Turns out the issue was in the precise wording used by the documentation for listen in the hyperspec (http://www.lispworks.com/documentation/HyperSpec/Body/f_listen.htm).
Returns true if there is a character immediately available from input-stream; otherwise, returns false. On a non-interactive input-stream, listen returns true except when at end of file[1]. If an end of file is encountered, listen returns false. listen is intended to be used when input-stream obtains characters from an interactive device such as a keyboard.
Since the socket-stream doesn't produce characters if it's told to produce '(unsigned-byte 8)'s, listen will return NIL for the stream regardless of whether it has data ready to be read.
As far as I know, there is no alternative to listen for non-character types in the standard. Use usocket's wait-for-input instead, with :timeout set to 0 for polling (http://quickdocs.org/usocket/api).

Writing negative integer as 0xnn hex into peripheral

I am dealing with a hardware peripheral which exposes a writable characteristics for Measured Power. As per the specs from the hardware vendor Measured Power should be sent in the format "0xnn". I am not sure how do we convert a negative integer (-59) into 1 byte hex representation (0xnn).
By far I have tried below
int iPower = -59;
int16_t power = CFSwapInt16HostToBig(iPower);
NSData *powerData = [NSData dataWithBytes:&power length:sizeof(power)];
But this writes 0xFF into peripheral which is 255 in decimal. Any idea?
Even tried sending raw bytes by below code and this reaches as 0xC5 which is 197 in decimal.
NSInteger index = -59;
NSData *powerData = [NSData dataWithBytes:&index length:sizeof(index)];
I am not sure how do we convert a negative integer (-59) into 2 bytes hex representation (0xnn).
When you have two bytes for hex representation that means you can have a range of 0x0000 ~ 0xFFFF numbers or 0~65535 for non-negative integers or in 2's compliment representation -32768 ~ 23767.
By using 2's complement representation -59 in two byte hex will be 0xFFC5.
Also check if you really need to use this: "CFSwapInt16HostToBig"

Resources