Hello,
I bought several receivers and various beacons to test their potential of application in BLE Real Time Location System. I just used iPhone 5s and AprilBeacon App from iStore to check the distance accuracy first and the 227L beacon provides best results. The problem that I encountered is very low accuracy of distance measured using iBeacon Receiver, JAVA and MQTT server. What may be the reason, lower quality of the bluetooth module inside, or maybe you have used better algorithms in IOS SDK?
For example using iPhone I have distance Approx. 4-5meters, but using beacon receiver located in the same place where iPhone I have output results Aprprox. 0,8m - 1.2 m.
My settings are:
Tx power: 0dBm (in fact it’s working as +10dBm, right?)
measuredPower: 57 (checked using calibration function from your IOS APP).
Advertising Freq: 8
Please find my code below, I will be grateful if you could take a look at this, maybe I mixed up something.
package testm;
import java.net.URISyntaxException;
import org.fusesource.mqtt.client.BlockingConnection;
import org.fusesource.mqtt.client.MQTT;
import org.fusesource.mqtt.client.Message;
import org.fusesource.mqtt.client.QoS;
import org.fusesource.mqtt.client.Topic;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
public class MClient {
public static Topic[] topics = {new Topic("/beacons", QoS.AT_MOST_ONCE)};
public static double getDistance(int measuredPower, double rssi) {
if (rssi >= 0) {
return -1.0;
}
if (measuredPower == 0) {
return -1.0;
}
double ratio = rssi * 1.0 / measuredPower;
if (ratio < 1.0) {
System.out.println("measuredPower (ratio <1.0)" + measuredPower);
System.out.println("rssi (ratio <1.0)" + rssi);
return Math.pow(ratio, 10);
} else {
double distance = (0.42093) * Math.pow(ratio, 6.9476) + 0.54992;
System.out.println("measuredPower" + measuredPower);
System.out.println("rssi" + rssi);
//double distance = (0.89976) * Math.pow(ratio, 7.7095) + 0.111;
return distance;
}
}
public static long parseUnsignedHex(String text) {
if (text.length() == 16) {
return (parseUnsignedHex(text.substring(0, 1)) << 60)
| parseUnsignedHex(text.substring(1));
}
return Long.parseLong(text, 16);
}
public static void main(String[] args) {
MQTT mqtt = new MQTT();
try {
// MQTT parameters
mqtt.setHost("tcp://192.168.0.206:1883");
mqtt.setClientId("beacons");
mqtt.setCleanSession(true);
mqtt.setReconnectAttemptsMax(6);
mqtt.setReconnectDelay(2000);
mqtt.setKeepAlive((short) 30);
mqtt.setSendBufferSize(2 * 1024 * 1024);
// MQTT BlockingConnection
BlockingConnection connection = mqtt.blockingConnection();
connection.connect();
if (connection.isConnected()) {
System.out.println("connection success");
} else {
System.out.println("connection failed");
}
while (true) {
Thread.sleep(1000);
byte[] qoses = connection.subscribe(topics);
Message message = connection.receive();
byte[] payload = message.getPayload();
message.ack();
JSONParser parser = new JSONParser();
Object obj = parser.parse(message.getPayloadBuffer().ascii().toString());
JSONObject jsonObject = (JSONObject) obj;
String[] splited = jsonObject.get("raw_beacons_data").toString().split(";");
for (int i = 0; i < splited.length; i++) {
// SHOW 227L BEACON (150m range) DATA ONLY
if ("2091482669C7".equals(splited[i].substring(0, 12))) {
System.out.println("BEACON= " + splited[i].substring(0, 12));
// Get rssi value from raw data
String rssiHex = splited[i].substring(56, 58);
long rssiLong = parseUnsignedHex(rssiHex);
double rssi = Double.valueOf(rssiLong) - 256; // We need to subtract 255 for real rssi
// Get measured power from raw data
String measuredPowerHex = splited[i].substring(52, 54);
int measuredPower = Integer.parseInt(measuredPowerHex, 16) - 256; // We need to subtract 255 for real measuredPower
// Print out distance in meters
System.out.println(getDistance(measuredPower, rssi) + "m");
}
}
}
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}