我正在尝试创建完整的eddystone Beacon仿真器。URL、UID帧没有问题。但是,当我尝试发送TLM额外数据时,没有任何工作。
BeaconParser extraparser,广告是什么时候开始收录的?
这是我的代码:
//create BeaconParse Like UID and add extraparser for TLM
BeaconParser beaconParser = new BeaconParser();
beaconParser.addExtraDataParser(new BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_TLM_LAYOUT));
beaconParser.setBeaconLayout(BeaconParser.EDDYSTONE_UID_LAYOUT);
BeaconTransmitter mBeaconTransmitter = new BeaconTransmitter(this, beaconParser);
//this is the beacon with info for UID and ExtraData with 5 values of TLM
Beacon beacon = new Beacon.Builder()
.setId1("0x2F234454F4911BA9FFA6")//UID
.setId2("0x0BDB87539B67") //UID
.setManufacturer(0xfeaa) //0x00E0 eddystone
.setBeaconTypeCode(0x00) //0X00 withTLM
.setMultiFrameBeacon(true) //TLM
.setServiceUuid(0xfeaa) //TLM
.setTxPower(-65) //UID
.setDataFields(Arrays.asList(new Long[]{0l}))//?
.setExtraDataFields(Arrays.asList(new Long[]{0L, 3580L,5776L, 289780991L, 28978000L}))//TLM extradata
.build();
//then create the Transmitter and start it
BeaconTransmitter bt = new BeaconTransmitter(this, beaconParser);
bt.startAdvertising(beacon);问题是,当我检测到信标时,它带有MExtraDataFields =null;
我认为TLM信息不包括在BeaconTransmitter发出的advertisingData中。
是否支持TLM信标传输?是BeaconTransmitter限制还是问题是信标引起的?
也许我需要使用标识符来发送这种信息。
我尝试过,三星S5和三星s7Edge,并使用2.9.1版本的AltBeacon
发布于 2016-10-26 01:08:38
抱歉,这不管用。BeaconTransmitter类不会基于额外的数据字段自动发出Eddystone-TLM。尽管我从未显式测试过它,但我认为它根本不能用于传输该帧,因为不可能仅使用数据字段来构造Beacon对象实例,这对于使用现有的BeaconTransmitter类传输Eddystone-TLM是必要的。
这就是说,这是一个合理的功能请求,如果你想增加对它的支持,我当然欢迎你的拉取请求。
完全披露:我是Android Beacon Library开源项目的首席开发人员。
发布于 2016-10-26 16:23:57
好的,非常感谢你的快速响应。
昨天不要加载你的代码,从主和Eddystone Eid,分析如果问题的BEaconEmmitter没有广告的ExtraData。
在阅读了您网站上的一些文档后,我了解到TLM信息在另一个广告包中,通过方法与其他EddyStone/Ibeacon相匹配:
private String getBeaconKey(Beacon beacon) {
if (matchBeaconsByServiceUUID) {
return beacon.getBluetoothAddress() + beacon.getServiceUuid();
} else {
return beacon.getBluetoothAddress();
}
}如果匹配,则将extraData添加到信标中。
为此,我修改了BeaconTransmitter startAdvertising方法,尝试使用相同的beaconTransmitter发送tlm的通告数据(因为需要在UID信标和TLM信标中具有相同的bTMac ),如下所示:
if (mBeacon.isMultiFrameBeacon()) {
byte[] advertisingExtraDataBytes = mBeaconParser.getBeaconAdvertisementDataFromTLM(mBeacon);
//segun https://github.com/google/eddystone/blob/master/eddystone-tlm/tlm-plain.md 14 bytes
//solo con esa info cmo matchea? typebeacon 0x20
try {
AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder();
//always bigger than 0
if (serviceUuid > 0) {
byte[] serviceUuidBytes = new byte[]{
(byte) (serviceUuid & 0xff),
(byte) ((serviceUuid >> 8) & 0xff)};
ParcelUuid parcelUuid = parseUuidFrom(serviceUuidBytes);
dataBuilder.addServiceData(parcelUuid, advertisingExtraDataBytes);
dataBuilder.addServiceUuid(parcelUuid);
// dataBuilder.setIncludeTxPowerLevel(false); //no in tlm
// dataBuilder.setIncludeDeviceName(false);//no in tlm
} else {
dataBuilder.addManufacturerData(manufacturerCode, advertisingExtraDataBytes);// in tlm?
}
AdvertiseSettings.Builder settingsBuilder = new AdvertiseSettings.Builder();
settingsBuilder.setAdvertiseMode(mAdvertiseMode); //need?
settingsBuilder.setTxPowerLevel(mAdvertiseTxPowerLevel);//need?
settingsBuilder.setConnectable(false);
mBluetoothLeAdvertiser.startAdvertising(settingsBuilder.build(), dataBuilder.build(), getAdvertiseCallback());
LogManager.d(TAG, "Started advertisement with callback: %s", getAdvertiseCallback());
} catch (Exception e) {
LogManager.e(e, TAG, "Cannot start advertising due to exception");
}
}仍然不能工作,但我还不知道AltBeacon是否已经支持它,没有花更多的时间在它上面。
我现在使用这段代码,为了获得字节数组的正确格式,欢迎您的所有意见。如果它工作得很好,那就谈拉请求吧,因为我不知道将代码放在BeaconTransmitter中是否是实现这种extraData框架的最好方法。
再次感谢David,你和你的合作者正在使用Altbeacon做着非常棒的工作,所以如果我能在这个功能上提供帮助,它确实做到了。
发布于 2017-01-26 01:15:42
@Davidgyoung,promises I ^_^对不起,为了等待,我终于找到时间重新考虑传输TLM帧的问题。
这是传输TLM帧(不含AltBeacon)的完整代码,但您需要BeaconTransmitter来创建UID或URL Eddystone帧,以便检查它。
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void createEddyStone_TLM2() {
final int len = 12;
final byte TLM_FRAME = 0x20;
byte[] ServiceData = new byte[2 + len];
ServiceData[0] = TLM_FRAME;
ServiceData[1] = 0;
ParcelUuid parcelUuid = parcelUuidFromShortUUID(0xFEAA);
final int pos = 0;//4 TLM
byte[] frameData = generateTLMFrameData();
System.arraycopy(frameData, pos, ServiceData, 2, len);
AdvertiseData advertiseData = new AdvertiseData.Builder().setIncludeDeviceName(false)
.setIncludeTxPowerLevel(false)
.addServiceData(parcelUuid, ServiceData)
.addServiceUuid(parcelUuid)
.build();
AdvertiseSettings advertiseSettings = new AdvertiseSettings.Builder().setAdvertiseMode(1)
.setTxPowerLevel(2)
.setConnectable(false)
.build();
try {
BluetoothManager bluetoothManager =
(BluetoothManager) this.getSystemService(Context.BLUETOOTH_SERVICE);
if (bluetoothManager != null) {
BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
BluetoothLeAdvertiser bleAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
bleAdvertiser.stopAdvertising(getAdvertiseCallback());
bleAdvertiser.startAdvertising(advertiseSettings, advertiseData, null,
getAdvertiseCallback());
}
} catch (IllegalStateException e) {
Log.e("", "error", e);
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP) private AdvertiseCallback getAdvertiseCallback() {
AdvertiseCallback advertiseCallback = new AdvertiseCallback() {
@Override public void onStartFailure(int errorCode) {
Log.e("","Something wrong with Advertising");
}
@Override public void onStartSuccess(AdvertiseSettings settingsInEffect) {
Log.i("","Advertising start succesfully");
}
};
return advertiseCallback;
}
public static ParcelUuid parcelUuidFromShortUUID(long serviceId) {
long leastSigBits = 0x800000805f9b34fbL;
return new ParcelUuid(new UUID(0x1000 | (serviceId << 32),leastSigBits));
}
private byte[] generateTLMFrameData() {
byte[] data = new byte[12];
ByteBuffer buffer = ByteBuffer.wrap(data);
buffer.putShort((short) getTLMBattery());
int temperature = getTLMTemperature();
buffer.putShort((short) (temperature << 8));
buffer.putInt((int) getTLMPduCount());
buffer.putInt((int) getTLMPowerOnTime() / 100);
return data;
}
private int getTLMTemperature() {
//todo make random, now 10º
return 266;
}
private int getTLMBattery() {
//todo make random
return 1234;
}
private int getTLMPduCount() {
//todo make random
return 0;
}
private long getTLMPowerOnTime() {
//todo - createtime, but don't care
return SystemClock.elapsedRealtime();
}我在我的:app中这样做,如果你愿意,我可以在AltBeacon中添加这个。
向您致敬,阿尔贝托
https://stackoverflow.com/questions/40239128
复制相似问题