Bluetooth - Output Stream - android

I have connected an arduino with my android device and I have set up the connection and obtained Output Stream.
ANDROID PART
String one = "1";
byte[] input = one.getBytes(Charset.forName("UTF-8"));
mConnectedThread.write(input);
ARDUINO PART
How can I process the received byte[] and convert it back to String?

There is a 128byte buffer on the incoming stream. Use
In your loop():
char inByte;
// check for bytes in the buffer
if (Serial.available() > 0) {
// read the available bytes one at a
// time and purge from buffer
inByte = Serial.read();
// print out byte so you can see it on
// the serial monitor
Serial.print(inByte);
}
If the buffer is big enough for your needs then you won't need to worry about coding anything else. You can deal with the incoming bytes in a char array or read the individual chars into a String object.
There is lots of good information here:
http://arduino.cc/en/Reference/string
...on char arrays and a link at the top of that page to the String object. Let me know if you have further questions, hopefully this gets you at least started and debugging the incoming code correctly

Related

Underrun in Oboe/AAudio playback stream

I'm working on an Android app dealing with a device which is basically a USB microphone. I need to read the input data and process it. Sometimes, I need to send data the device (4 shorts * the number of channels which is usually 2) and this data does not depend on the input.
I'm using Oboe, and all the phones I use for testing use AAudio underneath.
The reading part works, but when I try to write data to the output stream, I get the following warning in logcat and nothing is written to the output:
W/AudioTrack: releaseBuffer() track 0x78e80a0400 disabled due to previous underrun, restarting
Here's my callback:
oboe::DataCallbackResult
OboeEngine::onAudioReady(oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) {
// check if there's data to write, agcData is a buffer previously allocated
// and h2iaudio::getAgc() returns true if data's available
if (h2iaudio::getAgc(this->agcData)) {
// padding the buffer
short* padPos = this->agcData+ 4 * playStream->getChannelCount();
memset(padPos, 0,
static_cast<size_t>((numFrames - 4) * playStream->getBytesPerFrame()));
// write the data
oboe::ResultWithValue<int32_t> result =
this->playStream->write(this->agcData, numFrames, 1);
if (result != oboe::Result::OK){
LOGE("Failed to create stream. Error: %s",
oboe::convertToText(result.error()));
return oboe::DataCallbackResult::Stop;
}
}else{
// if there's nothing to write, write silence
memset(this->agcData, 0,
static_cast<size_t>(numFrames * playStream->getBytesPerFrame()));
}
// data processing here
h2iaudio::processData(static_cast<short*>(audioData),
static_cast<size_t>(numFrames * oboeStream->getChannelCount()),
oboeStream->getSampleRate());
return oboe::DataCallbackResult::Continue;
}
//...
oboe::AudioStreamBuilder *OboeEngine::setupRecordingStreamParameters(
oboe::AudioStreamBuilder *builder) {
builder->setCallback(this)
->setDeviceId(this->recordingDeviceId)
->setDirection(oboe::Direction::Input)
->setSampleRate(this->sampleRate)
->setChannelCount(this->inputChannelCount)
->setFramesPerCallback(1024);
return setupCommonStreamParameters(builder);
}
As seen in setupRecordingStreamParameters, I'm registering the callback to the input stream. In all the Oboe examples, the callback is registered on the output stream, and the reading is blocking. Does this have an importance? If not, how many frames do I need to write to the stream to avoid underruns?
EDIT
In the meantime, I found the source of the underruns. The output stream was not reading the same amount of frames as the input stream (which in hindsight seems logical), so writing the amount of frames given by playStream->getFramesPerBurst() fix my issue. Here's my new callback:
oboe::DataCallbackResult
OboeEngine::onAudioReady(oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) {
int framesToWrite = playStream->getFramesPerBurst();
memset(agcData, 0, static_cast<size_t>(framesToWrite *
this->playStream->getChannelCount()));
h2iaudio::getAgc(agcData);
oboe::ResultWithValue<int32_t> result =
this->playStream->write(agcData, framesToWrite, 0);
if (result != oboe::Result::OK) {
LOGE("Failed to write AGC data. Error: %s",
oboe::convertToText(result.error()));
}
// data processing here
h2iaudio::processData(static_cast<short*>(audioData),
static_cast<size_t>(numFrames * oboeStream->getChannelCount()),
oboeStream->getSampleRate());
return oboe::DataCallbackResult::Continue;
}
It works this way, I'll change which stream has the callback attached if I notice any performance issue, for now I'll keep it this way.
Sometimes, I need to send data the device
You always need to write data to the output. Generally you need to write at least numFrames, maybe more. If you don't have any valid data to send then write zeros.
Warning: in your else block you are calling memset() but not writing to the stream.
->setFramesPerCallback(1024);
Do you need 1024 specifically? Is that for an FFT? If not then AAudio can optimize the callbacks better if the FramesPerCallback is not specified.
In all the Oboe examples, the callback is registered on the output stream,
and the reading is blocking. Does this have an importance?
Actually the read is NON-blocking. Whatever stream does not have the callback should be non-blocking. Use a timeoutNanos=0.
It is important to use the output stream for the callback if you want low latency. That is because the output stream can only provide low latency mode with callbacks and not with direct write()s. But an input stream can provide low latency with both callback and with read()s.
Once the streams are stabilized then you can read or write the same number of frames in each callback. But before it is stable, you may need to to read or write extra frames.
With an output callback you should drain the input for a while so that it is running close to empty.
With an input callback you should fill the output for a while so that it is running close to full.
write(this->agcData, numFrames, 1);
Your 1 nanosecond timeout is very small. But Oboe will still block. You should use a timeoutNanos of 0 for non-blocking mode.
According to Oboe documentation, during the onAudioReady callback, you have to write exactly numFrames frames directly into the buffer pointed to by *audioData. And you do not have to call Oboe "write" function but, instead, fill the buffer by yourself.
Not sure how your getAgc() function works but maybe you can give that function the pointer audioData as an argument to avoid having to copy data again from one buffer to another one.
If you really need the onAudioReady callback to request the same amount of frames, then you have to set that number while building the AudioStream using:
oboe::AudioStreamBuilder::setFramesPerCallback(int framesPerCallback)
Look here at the things that you should not do during an onAudioReady callback and you will find that oboe write function is forbidden:
https://google.github.io/oboe/reference/classoboe_1_1_audio_stream_callback.html

android can not receive a data of 512bytes in usb Accessory mode

when android communicate with pc via usb accessory mode, the android can not receive a data if pc send 512bytes data to android.
but, there are no problem if over(or below) than 512bytes data transfer.
And if android receive other byte data after receive 512bytes data then incoming both missing data and other byte data(512bytes + other data).
my read code on thread is below.
#Override
public void run() {
byte[] readbuffer = new byte[16384];
int bytesRead = 0;
try {
while ((bytesRead = mInputStream.read(readbuffer, 0, readbuffer.length)) != -1) {
//my code here afrer read.
....
mHandler.sendMessage(msg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
this is happened not only 512bytes but some other specific lengths(512bytes, 1024bytes, 2048 bytes...).
is this android accessory mode bug?
anybody know this issue?
It is not a bug with AOA but your sender not finishing the USB transaction. Unlike USB control transfers, bulk transfer does not transmit the data size, so for a bulk transfer to finish one of these conditions must be satisfied:
The amount of data received is the amount of data requested.
The size of the data is less than maximum buffer size.
A Zero-length package is received.
For high speed mode, the maximum buffer size is 512 bytes, so if you send 0-511 bytes, condition 2 is satisfied. In case data is 513-1023 length, it will be split in two packages 512 bytes + 1-511 bytes, so again, the last package satisfies the 2nd condition.
In case you send exactly 512 bytes, the receiver does not know either you have finish the transaction or there is remaining data (in an additional package) so it keeps waiting and freezes. So, for lengths multiple of buffer size (512 on high speed and 64 in full-speed) you need to send an additional zero length package for finishing the USB transfer.

Unpack array of integers from a bluetooth socket

I'm currently working on a PiBot project in Python (chassis with 4 wheels, controlled by Android app via bluetooth for now).
I made a prototype in Python, i can create a BT server, subscribe to it and pair the device via Android, and send information through the BT socket : a joystick gives me the strength and angle on Android, and i succesfully read them from the server. I use Struct for decoding the integers array from the stream bytes.
Here's a piece of my BTServer class, the loop where i display values on server :
def goToControls(self):
while True:
data = self.client_sock.recv(1024)
size = len(data)
print size, 'bits'
try:
angle, strength = struct.unpack('>ii', data)
print angle, strength
#self.cHandler.move(angle, strength)
except struct.error:
print 'bad scheme...'
On Android side, the function which sends data :
if (btDevice.getMmSocket().isConnected()){
int[] values = {angle, strength};
ByteBuffer byteBuffer = ByteBuffer.allocate(values.length * 4);
IntBuffer intBuffer = byteBuffer.asIntBuffer();
intBuffer.put(values);
byte[] array = byteBuffer.array();
try {
btDevice.getMmSocket().getOutputStream().write(array);
btDevice.getMmSocket().getOutputStream().flush();
} catch (IOException e) {
e.printStackTrace();
}
}
Here's my console output, from server :
So it works great. As soon as i uncomment the line self.cHandler.move(angle, strength), which gives data to my controls handler and make wheels turn, or if i replace it with anything, such as a time.sleep(0.1), here's what i get :
It looks like the scheme is changing, i can't understand anything... Has someone got a clue ?
Thanks a lot
-- EDIT :
I found a part of the answer : I was trying to send 8 bytes from android and receiving 1024 from struct.
So I changed it for that :
data = self.client_sock.recv(8)
angle, strength = struct.unpack('>ii', data)
print angle, strength
self.cHandler.move(angle, strength)
And it works, but it's now terribly slow. How can I decode those 8 bytes without slowing the process like this ?

Android via NFC IsoDep(ISO14443-4) communication with chip's FIFO cache area no way to more than 12 bytes

I'm pretty troubled with android NFC transacting with chip's FIFO cache area. Another side(B) and android app(A): B was electrify to chip,and B write data to chip's FIFO cache area by C language. The chip's FIFO cache area can not save data after outage, and when chip's FIFO cache area send all data, the chip's FIFO cache area will clear.
The situation is, A close to chip, send a APDU command, now chip receives the command and produces a signal. Then, the B detects the chip's signal, and grabs the command, then, B gets the command's first byte(fb), more then, B write [fb+data+9000] to chip's FIFO cache area. Finally, the transaction of send data back to A manage with chip self and we don't know the chip how to manage the send back.
The problem is, when B's write [fb+data+9000] less than 15 bytes(means data only 12 bytes), A can receive the [fb+data+9000] from chip. But the [fb+data+9000] more than 15 bytes, A throws TagLostException.
The chip use ISO14443-4 protocol.
The command:
The transact code:
`
try {
isoDep.close();
isoDep.connect();
}catch (IOException e){
errorfound = true;
onMessageReceived.onError(e);
}
if (!errorfound) {
if (isoDep.isConnected()) {
try {
isoDep.setTimeout(1200);
response = isoDep.transceive(newtest1_apdu);
int status = ((0xff & response[response.length - 2]) << 8) | (0xff & response[response.length - 1]);
if (status != 0x9000) {
log.error("retrieve data ,read failure");
}else {
log.info("retrieve data, result=" + numeralParse.toReversedHex(response));
}
onMessageReceived.onMessage(response);
}
catch (TagLostException e) {
log.info("catch tag lost exception, tag isConnected=" + isoDep.isConnected());
onMessageReceived.onError(e);
}
catch (IOException e) {
log.info("catch IOException, isoDep isConnected=" + isoDep.isConnected());
onMessageReceived.onError(e);
}
}else {
log.error("isoDep not connect");
}
}
`
Android app(A) try to a variety of commands, contains this format: .
And another side(B) only gets first byte in command and write [fb+data+9000] to chip's FIFO cache area. this isn't timeout reason, except setTimeOut(1200), also try setTimeOut(5000) or not setTimeOut. Other, A and B were not appoint the APDU command specific meaning. Other, by different APDU command, A work well with read Public transportation card(may be this read to block area, and now work with cache area, both work way not same). Other, the configuration of chip is basic default. Other, with other card reader test, chip's send data out success.
I go to Google,Bing,Baidu,Android office issues,stackoverflow and so on to search answer, but cannot find. This problem very bothered us. Apologetic with my poor English. Please help, extremely thank you.
(the chip is FM11NC08.)
New progress, We found, giving up using APDU command, if A send 1 byte, A can receive maximum 16 bytes. And if A send 2 bytes, A can receive maximum 15 bytes. And if A send 15 bytes, A can receive maximum 2 bytes. The chip's FIFO cache area has 32 bytes space. After B receive A's data, B will clear FIFO cache area, then write data to FIFO cache area.
Thanks in advance.
Today, B changes the chip's communication rate(from 1M to 2M) and a part of codes. Then A work well with chip! So, we found the communication rate has an impact on NFC communication. If you have the same trouble with NFC communication, might to try our way!
Thanks for people who consider this problem in not-solve days.

Android app shall wait for specific amount of bytes from BLE source

in my app i receive a string via BLE. It is a protocol from a sensor, so it has a start and end byte, several identification bytes and data bytes. After i received a full protocol string i need to cut the string into pieces. The start/end flag is 0xA8.
If data is found, the following method empties the buffer and calls "onUiReceiveData(final String dataReceived)" for further string cutting operation:
public void onVspReceiveData(BluetoothGatt gatt,
BluetoothGattCharacteristic ch)
{
mRxBuffer.write(ch.getStringValue(0));
while (mRxBuffer.read(mRxDest) != 0)
{
/*
* found data
*/
String rxBufferDataRead = mRxDest.toString();
mRxDest.delete(0, mRxDest.length());
mSerialManagerUiCallback.onUiReceiveData(rxBufferDataRead);
}
}
mRxBuffer is a FifoQueue
mRxDest is a StringBuilder
My problem is that the app is crashing everytime it is receiving data via BLE. The reason lies in the app handing over just a few bytes of the data to "onUiReceiveData(...)" and not the whole string. So the further methods cut the string, but it becomes too soon too short and the app crashes.
So how do i wait for a specific amount of data, or especially to the point that i have received a full protocol from "0xA8" as start and another "0xA8" as end flag?
Thanks in advance!

Categories

Resources