【问题标题】:BeaconTransmitting Eddystone TLM frame AltBeacon no workBeaconTransmitting Eddystone TLM 帧 AltBeacon 不起作用
【发布时间】:2016-10-25 11:47:35
【问题描述】:

我正在尝试创建完整的 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)   //0x00​E0 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);

问题是当我检测到 Beacon 时,它带有 MExtraDataFields =null;

我认为 TLM 信息不包含在 BeaconTransmitter 发出的广告数据中。

是否支持 TLM 信标传输?是 BeaconTransmitter 限制还是问题是我关心的信标?

也许我需要使用标识符来发送此类信息。

我尝试使用三星 S5 和三星 s7Edge,并使用 2.9.1 版本的 AltBeacon

【问题讨论】:

    标签: android ibeacon altbeacon


    【解决方案1】:

    抱歉,这行不通。 BeaconTransmitter 类不会根据额外的数据字段自动发出 Eddystone-TLM。尽管我从未明确测试过它,但我认为它根本不能用于传输该帧,因为不可能构造一个只有数据字段的 Beacon 对象实例,而传输 Eddystone-TLM 是必需的与现有的 BeaconTransmitter 类。

    也就是说,这是一个合理的功能请求,如果您想增加对此的支持,我当然欢迎您提出拉取请求。

    全面披露:我是 Android Beacon Library 开源项目的首席开发人员。

    【讨论】:

      【解决方案2】:

      好的,非常感谢您的快速回复。

      昨天从 master 和 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 Beacon 和 TLM Beacon 中具有相同的 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 是否已经支持此功能,并且不会花更多时间使用它。

      我现在使用此代码,为了获得正确格式的字节数组,欢迎您的所有 cmets。如果它工作正常,谈谈 pull request,因为我不知道将代码放在 BeaconTransmitter 中是否是实现这种 extraData Frame 的最佳方式。

      我有另一个改进 AltBeacon 的想法,关于电池消耗和后台扫描仪,我们也会讨论。

      再次感谢 David,您和您的合作者正在使用 Altbeacon 进行出色的工作,因此,如果我能在此功能上提供帮助,它已经提供了。

      【讨论】:

      • 嘿! @davidgyoung 我还没有时间进行开发,但我可以搜索有关 TLM 广告数据中的信息的信息:eddystone Preamble 数据广告包 0x02,0x01,0x06,0x03,0x03,0xAA,0xFE,0x11,0x16, 0xAA,0xFE加Tlm服务数据
      • 0x32,0x00(version)... 但重要的是 TLM 帧的交错是信标读取器的责任,这通过蓝牙地址将 TLM 帧与 URL/UID 匹配。 BeaconTransmitter 或 bluetooh Scanner LE 每次都分配不同的 btAddress。
      【解决方案3】:

      @Davidgyoung,承诺就是债务^_^ 抱歉,久等了,终于有时间重新解决传输TLM Frame的问题了。

      这是传输TLM帧的完整代码(不带AltBeacon),但您需要BeaconTransmitter来创建UID或URL Eddystone Frame,以供查看。

      @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 中添加它。

      问候,阿尔贝托

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多