I am writing an app which is receiving values from a Light Sensor of a BLE device. I am trying to determine what it is that I am receiving. I am trying to get the Lux value which is provided by the sensor, but am concerned that it needs conversion. I do not know what the unit of measure is for this sensor. For example, the unit for an Android phone is SI Lux. Should be easy enough, but for this sensor, the specs do not state.
Here is the code which is giving me output:
case MSG_LIGHT:
characteristic = (BluetoothGattCharacteristic) msg.obj;
if (characteristic.getValue() == null) {
Log.w(TAG, "Error obtaining light value");
return;
}
int formatlgt1 = -1;
formatlgt1 = BluetoothGattCharacteristic.FORMAT_SINT8;
Log.i(LIGHT, "Light RawValue1 " + characteristic.getIntValue(formatlgt1, 0));
Log.i(LIGHT, "Light RawValue2 " + characteristic.getIntValue(formatlgt1, 1));
Log.w(LIGHT, "Light UUID " + characteristic.getUuid());
Log.w(LIGHT, "Light Stored Value " + characteristic.getValue());
Log.w(LIGHT, "Light Descriptors " + characteristic.getDescriptors());
Log.d(LIGHT, "Light Characteristic " + characteristic);
updateLightValues(characteristic);
break;
Simple enough, just read the sensor and give me the various outputs from that sensor at the time of reading. Next here is the output:
Light RawValue1 4
Light RawValue2 9
Light UUID 0000aa91-0000-1000-8000-00805f9b34fb
Light Stored Value [B#431d30b0
Light Descriptors [android.bluetooth.BluetoothGattDescriptor#4300e508, android.bluetooth.BluetoothGattDescriptor#4300eaf8]
Light Characteristic android.bluetooth.BluetoothGattCharacteristic#43002b10
I am interpreting that the measurement of this is the RawValues 1 & 2 but am logging what is stored to help. Problem is that the StoredValue is [B#431d30b0 which is beyond me. According to the description form the manufacturer, it states that the first byte is the HILUX at address 00x03 and the second is LOLUX at address 00x04 with a default value of 00:00.
What am I looking at here and where am I going wrong? Where I am hurting is my understanding of what I am reading. Can't seem to get a good search context to learn about it.
Thanks
Related
I'm trying to get use the magnetometer from this Sensor API but I'm not sure if I'm doing so correctly.
I copied and edited the example code from the their site into my test site;
let sensor = new Magnetometer();
sensor.start();
sensor.onreading = () => {
console.log("Magnetic field along the X-axis " + sensor.x);
console.log("Magnetic field along the Y-axis " + sensor.y);
console.log("Magnetic field along the Z-axis " + sensor.z);
document.getElementById("x").innerHTML = "X = " + sensor.x;
document.getElementById("y").innerHTML = "Y = " + sensor.y;
document.getElementById("z").innerHTML = "Z = " + sensor.z;
};
sensor.onerror = event => console.log(event.error.name, event.error.message);
But when I load the page it doesn't give me any readings. Checking the site on my laptop brings back this error message;
Uncaught ReferenceError: Magnetometer is not defined
at magnetometer.js:1
Any insight into this would be greatly appreciated.
I found the answer. After looking around I found that you need to go to chrome://flags/#enable-generic-sensor-extra-classes and enable Generic Sensor Extra Classes.
I'm not sure why this is the case but I am now getting the readings I was after.
Here is the thing a device that we have transmits regular updates of a custom characteristic of a custom service. The service and characteristic in this device is defined via a XML file. This, of course, is referring to the Bluetooth BLE protocol.
What I'm trying to do is create a simple Qt Android App that connects to the device and monitors the update. I've gotten as far as discovering the service and connecting it signal to it. I've done that using this code:
void BLETest::on_stateChanged(QLowEnergyService::ServiceState state){
Q_UNUSED(state);
// Only printing data if all services are in correct state.
for (qint32 i = 0; i < monitoredServices.size(); i++){
if (monitoredServices.at(i)->state() != QLowEnergyService::ServiceDiscovered){
logger->out("There are still services that have not been discoverd",Logger::LC_ORANGE);
return;
}
}
QString msg = "PRINTING SERVICE DATA<br>";
for (qint32 i = 0; i < monitoredServices.size(); i++){
QLowEnergyService *monitoredService = monitoredServices.at(i);
QList<QLowEnergyCharacteristic> clist = monitoredService->characteristics();
msg = msg + "SERVICE: " + monitoredService->serviceName() + ". UUID: " + monitoredService->serviceUuid().toString() + "<br>";
// Checking if this is the service that need connection.
if (monitoredService->serviceUuid() == QBluetoothUuid(QString("0a464eef-af72-43fd-8a8b-1f26f6319dab"))){
QString res;
if (connect(monitoredService,SIGNAL(characteristicChanged(QLowEnergyCharacteristic,QByteArray)),this,SLOT(on_charastericChanged(QLowEnergyCharacteristic,QByteArray)))) res = "true";
else res = "false";
logger->out("CONNECTED TO TARGET SERVICE: " + res,Logger::LC_ORANGE);
}
for (int i = 0; i < clist.size(); i++){
QString name = clist.at(i).name();
if (name.isEmpty()) name = "UNDEFINED NAME";
QByteArray buffer = clist.at(i).value();
//QString value = QString(clist.at(i).value());
QString value = QByteArray(buffer.toHex()) + " (BS = " + QString::number(buffer.size()) + ")";
QString properties = QString::number(clist.at(i).properties());
msg = msg + "CHARACTERISTIC: " + clist.at(i).uuid().toString() + " - " + name + ": " + value + ". PROPERTIES: " + properties + "<br>";
}
if (clist.isEmpty()){
msg = msg + "No characteristics found<br>";
}
}
logger->out(msg);
}
The above functions waits for all services to be discovered then prints the UUID, name and Value for all characteristics of all services. When the service I want to monitored is processed a connection is done to the changedCharacteristic signal.
When I do this the printed value of the characteristic of the service I want to monitor is the original value for that characteristic. However as that value updates I'm not notified (the signal never triggers) and so the value never changes in my app.
Do I need to write some code to actually trigger the signals?
PD: Using the Blue Gecko Demo App I can see the values changing.
EDIT: I decided to use a timer to Poll the value of the characteristic and it never changes. Which might indicate why the signal is never generated either.
You should connect a chracteristic changed handler to the service:
connect(service, SIGNAL(characteristicChanged(QLowEnergyCharacteristic, QByteArray)), this, SLOT(on_characteristicChanged(QLowEnergyCharacteristic, QByteArray)));
In the slot you can explore the data array.
However, the signal (characteristicChanged()) will only emitted by the service if the for this chracteristic notification is enabled. This works only, if the characteritic has a notify property, that should the case in your application.
using Bluetooth Low Energy (BLE) scan on Android, I noticed that sometimes RSSI values are incorrect.
My code simply calls the start scan function:
mBluetoothAdapter.startLeScan(mLeScanCallback);
and then I read results in the callback and save results in a file:
private static BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
String objScanRec = bytesToHex(scanRecord);
outStr = rssi + ";" + objScanRec + ";" + device.getName() + ";" + beaconLocation + ";\n";
try {
Raw_log.write(outStr);
Raw_log.flush();
} catch (IOException e) {
e.printStackTrace();
}
// }
}
};
the problem is that I read positive RSSI values, also if the beacon is at a fixed distance.
E.g. I have the beacon 30 cm from the phone (or smartwatch) I read a values around -45 which are realistic, but also values around +80 or +100 (which are not realistic) those values are around 20% of measurements.
Is there something that I'm missing?
thanks
thanks for your help I figured out it's a problem related only to Samsung Gear Live. I came up with this s solution:
if(rssi > 0){
rssi = rssi - 128;
}
I've tested the solution and it works fine. (e.g. the obtained positive values after correction are now similar to negative values, for example I read
-44 -45 -43 84 82
that after correctio become:
-44 -45 -43 -44 -46)
This is definitely not normal. I have never seen a rssi value in that callback be positive. Typical values are from -30 to -120.
I suspect there is something wrong with the way the data are written out to the log, or read back. What happens if you just do a regular Log.d(TAG, "rssi="+rssi); Do you ever see positive values? If so, can you share an excerpt, along with the device model you are using to detect and the device you are detecting?
I am struggling with the accelerometer sampling rate of my app.
So I decided to develope a little app just for testing the sampling rate.
Are there any mistakes in my code? The sampling rate is pretty much changing :-/
private PowerManager.WakeLock mWakeLock;
private TextView infotext;
private SensorManager sensorManager;
private long nanoNow;
private long nanoOld;
private long nanodiffsum=0;
private int i=0;
private int values=2000;
private long[] nanodiff=new long[values];
DescriptiveStatistics myDescrStat = new DescriptiveStatistics();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int tid=android.os.Process.myTid()
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
infotext = (TextView) findViewById(R.id.textView);
sensorManager=(SensorManager)getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this,sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_FASTEST);
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
mWakeLock.acquire();
}
public void onSensorChanged(SensorEvent event){
if(event.sensor.getType()==Sensor.TYPE_ACCELEROMETER){
if (i==0){
nanoOld=event.timestamp;
}
if (i == values) {
for (int i=1; i<nanodiff.length; i++){
myDescrStat.addValue(nanodiff[i]);
nanodiffsum+=nanodiff[i];
}
infotext.setText(
"Average:" + nanodiffsum / values + "ms\n" + " = " + (double) 1000 / (nanodiffsum /values) + "Hz" + "\n" +
"mean: " + 1000 / myDescrStat.getMean() + "\n" +
"std:" + 1000 / myDescrStat.getStandardDeviation() + "\n" +
"max:" + 1000 / myDescrStat.getMin() + "\n" +
"min:" + 1000 / myDescrStat.getMax() + "\n");
mWakeLock.release();
sensorManager.unregisterListener(this);
}else{
nanoNow=event.timestamp;
nanodiff[i]=(nanoNow-nanoOld)/1000000;
if (i%20==0)
infotext.setText("Aktuell: " + nanodiff[i] + "ms" + " = " + Math.round((double)1000/ nanodiff[i]) + "Hz" );
nanoOld=nanoNow;
i++;
}
}
}
Kindly regards,
Arthur
After a cursory look at your code I cannot see anything wrong with it (except perhaps the overzealous update of the thread priority, which makes sense in a testing app but I wouldn't use without a good reason in actual production code).
As for the irregular rate of the the SensorManager's data (spoiler alert: the same behavior applies to other sensor streams ;-) ), it is meant to be that way, and the frequency specified with SensorManager.SENSOR_DELAY_FASTEST is meant to be only a hint (which is the reason why actually you receive the time of the measurement with such accuracy at each event). This is stated in the official documentation:
rateUs : The rate sensor events are delivered at. This is only a hint to the system.
Events may be received faster or slower than the specified rate. Usually events are received faster. Source: registerListener reference page
For one part, keep in mind that Android is Linux at the core, and linux is not a real-time system (and therefore can't provide data with realtime accuracy); on the other side, Android has to cope with a lot of different hardware implementations (and sensor brands), therefore the Android developers team has probably done a wise choice to avoid any kind of commitment about the ratio of the sensor data.
Those are my 50 cents, if you want to get serious about Android Sensors programming I would suggest this book:
Professional Android Sensor Programming (Greg Milette, Adam Stroud)
I read about 1/4 of it and so far, so good (I'm in no way related to the publisher or the author).
Hope this helps
When the android text to speech functionality translates audio waves to text, is it possible to determine the 'confidence levels' of spoken text? So for example, if someone speaks too far away from the mic and the android device picks up distorted sounds, would it both output translated text along with a low confidence interval to state it isn't sure how accurate that particular translation was.
if you are implementing the RecognitionListener examine this code clip from my onResults method.
#Override
public void onResults(Bundle results) {
String LOG = "SpeechRecognizerActivity"
Log.d(LOG, "onResults");
ArrayList<String> strlist = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
float [] confidence = results.getFloatArray(SpeechRecognizer.CONFIDENCE_SCORES);
for (int i = 0; i < strlist.size(); i++) {
Log.d(LOG, "result=" + strlist.get(i));
}
Log.d(LOG + " result", strlist.get(0));
if (confidence != null){
if (confidence.length > 0){
Log.d(LOG + " confidence", String.valueOf(confidence[0]));
} else {
Log.d(LOG + " confidence score not available", "unknown confidence");
}
} else {
Log.d(LOG, "confidence not found");
}
}
You won't see anything unless you add this to your recognizer intent:
iSpeechIntent.putExtra(RecognizerIntent.EXTRA_CONFIDENCE_SCORES, true);
Yes. In the returned Bundle, there's a float array called CONFIDENCE_SCORES. From the docs:
Key used to retrieve a float array from the Bundle passed to the onResults(Bundle) and onPartialResults(Bundle) methods. The array should be the same size as the ArrayList provided in RESULTS_RECOGNITION, and should contain values ranging from 0.0 to 1.0, or -1 to represent an unavailable confidence score.
Confidence values close to 1.0 indicate high confidence (the speech recognizer is confident that the recognition result is correct), while values close to 0.0 indicate low confidence.
This value is optional and might not be provided.
Please note that it is not guaranteed to be there. Check for it and use if present. Gamble if not.