Wi-Fi signal strength unit - android

I using this code for get wifi signal set.(BSSID, SSID, RSSI.. etc.).
public void sortScanResult()
{
wifiScan.scanWifiSignal();
scanedResults = new ArrayList<ScanResult>(wifiScan.getScanResults());
Comparator<ScanResult> comparator = new Comparator<ScanResult>() {
#Override
public int compare(ScanResult lhs, ScanResult rhs) {
return (lhs.level > rhs.level ? -1 : (lhs.level == rhs.level ? 0 : 1));
}
};
Collections.sort(scanedResults, comparator); //sorting result
if (scanedResults.size() > 10) {
int resultSize = scanedResults.size();
for (int index = resultSize - 1; ; index--) {
scanedResults.remove(index);
if (scanedResults.size() == 10) break;
}
}
}
but the scanResults of this code return RSSI level by INT.
I want get rssi level value by float for precision because I use for indoor navigation.(Finger Print).
Is there no way to get RSSI level value by float?
ps. sorry, I'm poor at English.

Even if it were in float, that doesn't imply greater accuracy as float is 32bit same as int.
But anyway it's just not available at the hardware level:
Vendors and chipset makers provide their own accuracy, granularity.
Cisco Systems cards have a RSSI_Max value of 100 and will report 101 different power levels, where the RSSI value is 0 to 100. Another popular Wi-Fi chipset is made by Atheros. An Atheros based card will return an RSSI value of 0 to 127 (0x7f) with 128 (0x80) indicating an invalid value.
So that's what you have to work with, around 7 bits.
P.S. you won't have much luck with your approach according to the wiki article:
RSSI doesn't always provide measurements that are sufficiently accurate to properly determine the location.

Related

Store the scanned value in array and find the largest value in Android

In my Beacon application I am getting different values of RSSI through beacon.getRSSI(). Now I want to get the max value of RSSI of all the scanned beacons. So I thought the possible solution will be array. Can anyone helpout how to do this?
Put all the Beacon objects into a Collection (List, Set), then use Collections.max to get the beacon with the highest RSSI. javadoc
List<Beacon> beacons = new ArrayList<Beacon>();
// add all the beacons
beacons.add(beacon);
(...)
Beacon maxBeacon = Collections.max(beacons, new Comparator<Beacon>(){
public int compare(Beacon b1, Beacon b2) {
return Integer.compare(b1.getRSSI(), b2.getRSSI);
}
}

onLeScan callback returns oddly positive RSSI values

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?

NaN values in Android filter

I use the following function to filter a signal. The code works perfectly for order 4, but when I use a higher order, like 5, I get NaN values in the output. Your help is highlly appreciated
void filt(int ord, double a[], double b[], int np, double x[], ArrayList<Double> array)
{
int i,j;
// y[0]=b[0]*x[0];
array.add(0, b[0]*x[0]);
for (i=1;i<ord+1;i++)
{
array.add(i, 0.0);
for (j=0;j<i+1;j++)
array.add(i, array.get(i)+b[j]*x[i-j]);
for (j=0;j<i;j++)
array.add(i, array.get(i)-a[j+1]*array.get(i-j-1));
}
for (i=ord+1;i<np;i++)
{
array.add(i, 0.0);
for (j=0;j<ord+1;j++)
array.add(i, array.get(i)+b[j]*x[i-j]);
for (j=0;j<ord;j++)
array.add(i, array.get(i)-a[j+1]*array.get(i-j-1));
}
}
I tried the same functionality of Matlab, and got NaN values. I dig in Matlab documentation and found the following which explains the NaN values:
"For higher order filters (possibly starting as low as order 8), numerical problems due to roundoff errors may occur when forming the transfer function using the [b,a] syntax."
Therefor the butterworth filter is unstable for higher orders.
To get over this problem in Matlab, try the following:
n = 6; Wn = [2.5e6 29e6]/500e6;
ftype = 'bandpass';
% Transfer Function design
[b,a] = butter(n,Wn,ftype);
h1=dfilt.df2(b,a); % This is an unstable filter.
% Zero-Pole-Gain design
[z, p, k] = butter(n,Wn,ftype);
[sos,g]=zp2sos(z,p,k);
h2=dfilt.df2sos(sos,g);
% Plot and compare the results
hfvt=fvtool(h1,h2,'FrequencyScale','log');
legend(hfvt,'TF Design','ZPK Design')

Android Speech Recognitoin Confidence Levels

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.

Retrieve GSM signal strength in Android

I'm a newbie to Android.
How do I get the GSM signal Strength in terms of percentage (1 - 100%)?
The user who asked should have provided more information or feedback. That said...
The question is not trivial at all: since it's a scale in decibels it's not linear and thus smaller changes have a greater impact when the signal is low, while bigger changes are less important when the value is high. That's why I'm sorry to say that all the other answers will be getting inaccurate values that would not match the one displayed on the phone.
Assuming you already have a SignalStrength object (if not, there's another nice answer that shows how to do it), in Marshmallow it's solved with the method getGsmLevel() (there are also methods for all other signals and even combined) that returns a linearized scale 0-4. You can check the source code from the class SignalStrength.
/**
* Get gsm as level 0..4
*
* #hide
*/
public int getGsmLevel() {
int level;
// ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
// asu = 0 (-113dB or less) is very weak
// signal, its better to show 0 bars to the user in such cases.
// asu = 99 is a special case, where the signal strength is unknown.
int asu = getGsmSignalStrength();
if (asu <= 2 || asu == 99) level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
else if (asu >= 12) level = SIGNAL_STRENGTH_GREAT;
else if (asu >= 8) level = SIGNAL_STRENGTH_GOOD;
else if (asu >= 5) level = SIGNAL_STRENGTH_MODERATE;
else level = SIGNAL_STRENGTH_POOR;
if (DBG) log("getGsmLevel=" + level);
return level;
}
Having a 0-100% scale it's not significative because it's a small granularity for this matter, that's why it's more commonly used a 0-4 range and in this method it's already linearized. If not in Marshmallow, just adapt this method to receive the object as a value. If you'd really need a 0-100 range for some reason you should use a dB to linear conversion function, but I'm unaware of the gain factor in GSM signals.
public class MyActivity extends Activity {
public static final int UNKNOW_CODE = 99;
int MAX_SIGNAL_DBM_VALUE = 31;
TelephonyManager tel;
MyPhoneStateListener myPhoneStateListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = getLayoutInflater().inflate(R.layout.activity_about, null);
setContentView(view);
myPhoneStateListener = new MyPhoneStateListener();
tel = (TelephonyManager) PpsApplication.getAppContext().getSystemService(Context.TELEPHONY_SERVICE);
tel.listen(myPhoneStateListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
}
private class MyPhoneStateListener extends PhoneStateListener {
/* Get the Signal strength from the provider, each tiome there is an update */
#Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
super.onSignalStrengthsChanged(signalStrength);
if (null != signalStrength && signalStrength.getGsmSignalStrength() != UNKNOW_CODE) {
int signalStrengthPercent = calculateSignalStrengthInPercent(signalStrength.getGsmSignalStrength());
viewModel.setSignalStrengthString(IntegerHelper.getString(signalStrengthPercent));
}
}
}
private int calculateSignalStrengthInPercent(int signalStrength) {
return (int) ((float) signalStrength / MAX_SIGNAL_DBM_VALUE * 100);
}
}
Be aware that .getGsmSignalStrength(); now only returns bars: 0-5,99
The actual values are now hidden. You can still get to them using reflection:
int strength=signalStrength.getGsmSignalStrength();//number of bars not ASU
Log.v("Mobile","BARS: "+strength);
try{//Actual signal strength is hidden
Class classFromName = Class.forName(SignalStrength.class.getName());
java.lang.reflect.Method method = classFromName.getDeclaredMethod("getAsuLevel");//getDbm
strength = (int) method.invoke(signalStrength);
}catch (Exception ex){Log.v("Mobile","cant retreive");}
if (strength == 99 ) { Log.v("Mobile", "ERROR! GSM signal strength not available!");return;}//99 = Unknown
if (strength == 255) { Log.v("Mobile", "ERROR! UMTS signal strength not available!");return;}//255 = Unknown
The above example is for ASU only, which seems to work better than Dbm. After you get the ASU value, you can then dump it into percentage:
Log.v("Mobile","ASU: "+strength);
//Data.mobile_signal=strength*20;//Number of bars 0-5
//Data.mobile_signal = 100-((strength-113)/62);//GSM DBM
Data.mobile_signal =(int)((double)strength*100/31);//GSM ASU
Data.mobile_signal =(int)((double)strength*100/91);//UMTS ASU
Log.v("Mobile","Set GSM signal from "+strength+" to "+Data.mobile_signal);
As a reminder, this is for when you have a GSM signal not a CDMA signal. Use TelephonyManager.getPhoneType(); to determine which:
1=GSM, 2=CDMA, 3=SIP
BUT WAIT! This says I only have a 50% signal strength yet I have 5 bars! This is wrong!
Well, not exactly. Unless your phone is right in front of the transmitter, it's probably not going to be 100%. But 50% signal is about 100% quality. So from here you have to get creative.
A better solution is to use:
signalStrength.level
This returns a 0 to 4 value that you should be familiar with from your android device. Think of it as the number of bars of signal. This is compatible across GSM and CDMA.

Categories

Resources