I am developing an android application with BLE. The requirement of this application is to update the voltage variation in a specific hardware with various inputs.
So I am writing the characters to the BLE as 8-bit input. Each bit value contains its own representations. Based on each request hardware will respond and provide various output combinations. The output contains 24 bytes of information. Each byte position represents different value. eg: position 1& 2 represent current, 3 & 4 represent voltage etc.
My problem here is, I am getting the output as 4 parts. Each message contains 6 bytes. Is it possible to get the same in a single message?
Implementation
public void writeCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) { //Check that we have access to a Bluetooth radio
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
int test = characteristic.getProperties(); //Get the properties of the characteristic
if ((test & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0 && (test & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) { //Check that the property is writable
return;
}
DebugLogs.writeToFile("BLE MODULE Before Write " + characteristic);
if (mBluetoothGatt.writeCharacteristic(characteristic)) { //Request the BluetoothGatt to do the Write
Log.v(TAG, "****************WRITE CHARACTERISTIC SUCCESSFULL**" + characteristic); //The request was accepted, this does not mean the write completed
DebugLogs.writeToFile("BLE MODULE AFTER Write SUCCESS " + characteristic);
} else {
Log.d(TAG, "writeCharacteristic failed"); //Write request was not accepted by the BluetoothGatt
DebugLogs.writeToFile("BLE MODULE AFTER Write FAIL " + characteristic);
}
}
And the response is getting in the Gatt callback
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.w(TAG, "**ACTION_DATA_AVAILABLE**" + characteristic.getUuid());//Indication or notification was received
broadcastUpdate(BLEConstants.ACTION_DATA_AVAILABLE, characteristic); //Go broadc
ast an intent with the characteristic data
}
Unfortunately not. While you could reduce the number of transmissions IF you are the author of the code in the BLE peripheral, you cannot fit 24 bites into a single characteristic, because BLE limits the width of a characteristic to 20 bytes. If you are the BLE peripheral author, you could perhaps change it to send 2 12 byte packets.
If you aren't, then you are probably trying to collect all the data before sending it. An easy way to do this would be create a byte array of length 24 when onCharacteristicWrite is called. Then, every time onCharacteristicChanged is called, add the data to the array. Once you've added all 24 bytes to the array, broadcast it.
Hope this helps!
Related
How do I test if my Bluetooth Headset is connected to my phone? I know that the Bluetooth API supports a BluetoothHeadset profile and that it outputs either 2,1,or 0 but I don't know how to use it. Thanks!
^disregard this
Edit: Can I test if Bluetooth.Headset is two?
Like-
if (Bluetooth.Headset = true){
action
}else (blah blah)
Would that let me know if my phone is connected to a Bluetooth headset?
Edit again: So the three states are connecting, connected, and disconnected. How can I test for connected?
For iOS and, if Google is correct, Android, you can look in Settings> Bluetooth> Devices. You should see your device there if it’s connected.
//to prevent repeated alerts
var h = 1
if (BluetoothHeadset == 2 && h == 1) {
alert("You have been connected to your Bluetooth headset.");
h = 0;
} else if (h == 0) {
alert("You have been disconnected from your Bluetooth headset.");
h = 1
}
This is an oddly specific question but I'm trying to get the EventWaiter from JDA Utilities to work. (https://github.com/jagrosh/ExampleBot/tree/master/src/main/java/com/jagrosh/examplebot)
I have a method set up and the time out section works, but the waiter doesn't seem to pick up any new messages sent to discord like it is supposed to and I'm not sure why. Here is what I have:
public static void askQuestions(int numLeft, MessageReceivedEvent event, String level) {
if(numLeft==0) {
Writer.listWords(event);
Writer.clearWords();
return;
}
//Get random line from text file and store in text.
text = Reader.fileReader(level);
//Get the question
word = getQuestion(text);
//Get the answer
ans = getAnswer(text, event);
//Write word to txt file to print out later at end of game.
Writer.playedWordsWrite(word, ans);
//Create image of word and send to discord
imageCreator(word, event);
//Set up waiter to get players' answers. Mention user who gets it right and then call the method again.
waiter.waitForEvent(MessageReceivedEvent.class,
//Make sure it's the right answer in the same channel
e -> e.getChannel().equals(event.getChannel()) && e.getMessage().getRawContent().equals(ans),
//Respond, inserting the name they listed into the response
e -> {
e.getChannel().sendMessage(e.getAuthor().getAsMention()+ " got it right!").queue();
askQuestions(numLeft-1, e, level);
},
//If the user takes more than 10 seconds, time out
7, TimeUnit.SECONDS, () -> {
event.getTextChannel().sendMessage("Correct answer: "+ans).queue();
askQuestions(numLeft-1, event, level);
}
);
}
The best practice is not to store JDA objects, such as channels, because it would be better to compare their IDs as longs. It's possible that that's the issue. Try e.getChannel().getIdLong() == event.getChannel().getIdLong() otherwise, I'd guess its one of your methods such as imageCreator or playedWordsWrite
I want to retrieve the frameRate from the MediaCodec, but i always got the NullPointerException. The code as following:
public void handleWriteSampleData(MediaCodec encoder, int trackIndex, int bufferIndex, ByteBuffer encodedData, MediaCodec.BufferInfo bufferInfo) {
super.writeSampleData(encoder, trackIndex, bufferIndex, encodedData, bufferInfo);
int rc = -1;
if (((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0)) {
if (VERBOSE) Log.i(TAG, "handling BUFFER_FLAG_CODEC_CONFIG for track " + trackIndex);
if (trackIndex == VIDEO_TRACK_INDEX) {
// Capture H.264 SPS + PPS Data
Log.d(TAG, "Capture SPS + PPS");
captureH264MetaData(encodedData, bufferInfo);
mFFmpeg.setVideoCodecExtraData(videoConfig, videoConfig.length);
fps = encoder.getOutputFormat().getInteger(MediaFormat.KEY_FRAME_RATE);
Log.i(TAG, "fps:" + fps);
}
....
The exception as following:
E/AndroidRuntime( 1419): java.lang.NullPointerException
E/AndroidRuntime( 1419): at android.media.MediaFormat.getInteger(MediaFormat.java:282)
I have gone through the source code:
/**
* Returns the value of an integer key.
*/
public final int getInteger(String name) {
return ((Integer)mMap.get(name)).intValue();
}
How to get the right fps value from MediaCodec ?
The information is not available from MediaCodec, because timing information is not necessarily present in H.264 (see e.g. this link). KEY_FRAME_RATE is an argument for the encoder.
A nominal frame rate value may be present in the wrapper (e.g. .mp4) that MediaExtractor handles, but I don't know if there's a consistent way to access that.
You can dig through SPS, or calculate an fps value by looking at the presentation time stamps on a series of frames. If the video uses a variable frame rate, like "screenrecord" output does, then you may get an incorrect number from this... but I would argue that, for VFR video, there is no correct number for The Frame Rate, just maximum and average values.
You need to wait for the MediaCodec.INFO_OUTPUT_FORMAT_CHANGED flag if you want to read the MediaFormat from the Codec.
int bufferIndex = mMediaCodec.dequeueOutputBuffer(this.mBufferInfo, QUEUEING_TIMEOUT);
if (bufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
MediaFormat mMediaFormat = mMediaCodec.getOutputFormat();
}
I'm listing all MIDI devices in a combobox, but for the loopback drivers I get duplicate entries.
The first entries don't work and contain no description (
getDescription() returns "No details available" )
The others, which are the working ones, return "External MIDI Port"
description.
Now, I would like to know why rtpMidi, LoopBE, LoopMidi and all loopback drivers cause these duplicate entries, so that I can exclude them from the list in a secure way.
I could simply avoid the entries without a valid description, but I don't like acting without knowing the reason why those entries are reported in the first place.
Another thing that puzzles me is that if I try filtering the results via "if(dev instanceof Receiver)" I get a blank list, the same with instanceof Transmitter, Synthesizer and Sequencer. So it seems like none of the midi devices are instance of one of those classes, but only instance of MidiDevice class, which doesn't help me with filtering the list...
Could someone please suggest a different solution?
// Get MIDI device list
info = MidiSystem.getMidiDeviceInfo();
device = new ArrayList<MidiDevice>();
deviceDetails = new ArrayList<String>();
int j=0;
for (int i = 0; i < info.length; i++) {
MidiDevice dev = MidiSystem.getMidiDevice(info[i]);
//if ( dev instanceof Receiver ) { // tried Receiver, Transmitter, Synthesizer and Sequencer
// Detailed List
deviceDetails.add("Device ID: " + j);
deviceDetails.set(j, deviceDetails.get(j) + "\nName: " + info[i].getName());
deviceDetails.set(j, deviceDetails.get(j) + "\nDescription: " + info[i].getDescription());
device.add(dev);
deviceDetails.set(j, deviceDetails.get(j) + "\nDevice: " + device.get(j));
//Combo Box (Dev names only)
MidiOutCombo.add(info[i].getName());
j++;
//}
}
Here's the temporary solution I found, it works but it's string-based and I don't know if it works crossplatform...
if (info[i].getDescription().compareTo("External MIDI Port") == 0 ) {
Loopback drivers typically have two ports, one for receiving, and one for transmitting.
To determine if a MIDIDevice has any receivers or transmitters, you must call its getMaxReceivers/getMaxTransmitters methods.
In my application I generate a location every 5 minutes and send it to the db if it fits my standards.
One of the standards is that the new location that generated is not equal to the old one.
The following condition should cover it (and some other things) but in real time it doesn't.
if(newLocation != null)
{
if(location != null)
{
if(location.getAccuracy() > newLocation.getAccuracy() + 100)
sendTask();
else
if(newLocation.distanceTo(location) > 1800)
sendTask();
}
else
sendTask();
}
The send task method means, send to db. If the newLocation and the Location has the same coordinates the sendTask method shouldn't be exceuted and it is!
Why?