Как разделить числа с плавающей запятой на элементы шестнадцатеричного массива - PullRequest
0 голосов
/ 01 февраля 2019

В следующем примере BLE: я хотел бы разделить число с плавающей запятой на элементы, которые я мог бы назначить в CUSTOM_UUID.

Например: взять 12345.67 и каким-то образом назначить его в CUSTOM_UUID [] как

    const uint8_t CUSTOM_UUID[] =
    {
        0X00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x67
    };

    BLEUuid uuid = BLEUuid(CUSTOM_UUID);

Текущий формат отображается в объявлении BLE как: 00000000-0000-0000-0000-000000000000, поэтому я хотел бы получить что-то вроде: 00000000-0000-0000-0000-000001234567 в качестве первого шага.,Следующий шаг будет иметь дело с десятичной дробью.

 /*********************************************************************
 This is an example for our nRF52 based Bluefruit LE modules

 Pick one up today in the adafruit shop!

 Adafruit invests time and resources providing this open source code,
 please support Adafruit and open-source hardware by purchasing
 products from Adafruit!

 MIT license, check LICENSE for more information
 All text above, and the splash screen below must be included in
 any redistribution

 Author: KTOWN (Kevin Townsend)
 Copyright (C) Adafruit Industries 2017
*********************************************************************/

/*  This example constantly advertises a custom 128-bit UUID, and is
 *  intended to be used in combination with a Central sketch that scans
 *  for this UUID, and then displays an alert message, sorting matching
 *  devices by their RSSI level which is an approximate indication of
 *  distance (although highly subject to environmental obstacles).
 *  
 *  By including a custom UUID in the advertising packet, we can easily
 *  filter the scan results on the Central device, rather than manually
 *  parsing the advertising packet(s) of every device in range.
 *  
 *  This example is intended to be run with the *_central.ino version
 *  of this application.
 */

#include <bluefruit.h>
#include <ble_gap.h>

//int test_hex = 0x55;

// Software Timer for blinking RED LED
SoftwareTimer blinkTimer;

// Custom UUID used to differentiate this device.
// Use any online UUID generator to generate a valid UUID.
// Note that the byte order is reversed ... CUSTOM_UUID
// below corresponds to the follow value:
// df67ff1a-718f-11e7-8cf7-a6006ad3dba0
const uint8_t CUSTOM_UUID[] =
{
    0X00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

BLEUuid uuid = BLEUuid(CUSTOM_UUID);




void setup() 
{
  Serial.begin(115200);
  while ( !Serial ) delay(10);   // for nrf52840 with native usb

  Serial.println("Bluefruit52 Peripheral Proximity Example");
  Serial.println("----------------------------------------\n");


  // Initialize blinkTimer for 1000 ms and start it
  blinkTimer.begin(1000, blink_timer_callback);
  blinkTimer.start();

  err_t err = Bluefruit.begin();
  if (err)
  {
    Serial.print("Unable to init Bluefruit (ERROR CODE: ");
    Serial.print(err);
    Serial.println(")");
    while(1)
    {
      digitalToggle(LED_RED);
      delay(100);
    }
  }
  else
  {
    Serial.println("Bluefruit initialized (peripheral mode)");
  }

  // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
  Bluefruit.setTxPower(4);
  Bluefruit.setName("Bluefruit52");

  // Set up and start advertising
  startAdv();

  Serial.println("Advertising started"); 

}

void startAdv(void)
{   
  // Note: The entire advertising packet is limited to 31 bytes!

  // Advertising packet
  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();

  // Preferred Solution: Add a custom UUID to the advertising payload, which
  // we will look for on the Central side via Bluefruit.Scanner.filterUuid(uuid);
  // A valid 128-bit UUID can be generated online with almost no chance of conflict
  // with another device or etup
  Bluefruit.Advertising.addUuid(uuid);


  // Alternative Solution: Manufacturer Specific Data (MSD)
  // You could also send a custom MSD payload and filter for the 'Company ID'
  // via 'Bluefruit.Scanner.filterMSD(CID);', although this does require a
  // valid CID, which is why the UUID method above is more appropriate in
  // most situations. For a complete list of valid company IDs see:
  // https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers
  // For test purposes, 0xFFFF CAN be used, but according to the Bluetooth SIG:
  // > "This value may be used in the internal and interoperability tests before a
  // >  Company ID has been assigned. This value shall not be used in shipping end
  // >  products."
  uint8_t msd_payload[4]; // Two bytes are required for the CID, so we have 2 bytes user data, expand as needed
  uint16_t msd_cid = 0xFFFF;
  memset(msd_payload, 0, sizeof(msd_payload));
  memcpy(msd_payload, (uint8_t*)&msd_cid, sizeof(msd_cid));
  msd_payload[2] = 0x11;
  msd_payload[3] = 0x22;

  Bluefruit.Advertising.addData(BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, msd_payload, sizeof(msd_payload));


  // Not enough room in the advertising packet for name
  // so store it in the Scan Response instead
  Bluefruit.ScanResponse.addName();

  /* Start Advertising
   * - Enable auto advertising if disconnected
   * - Interval:  fast mode = 20 ms, slow mode = 152.5 ms
   * - Timeout for fast mode is 30 seconds
   * - Start(timeout) with timeout = 0 will advertise forever (until connected)
   * 
   * For recommended advertising interval
   * https://developer.apple.com/library/content/qa/qa1931/_index.html
   */
  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(32, 244);    // in units of 0.625 ms
  Bluefruit.Advertising.setFastTimeout(30);      // number of seconds in fast mode
  Bluefruit.Advertising.start();
}

void loop() 
{
}

/**
 * Software Timer callback is invoked via a built-in FreeRTOS thread with
 * minimal stack size. Therefore it should be as simple as possible. If
 * a periodically heavy task is needed, please use Scheduler.startLoop() to
 * create a dedicated task for it.
 * 
 * More information http://www.freertos.org/RTOS-software-timer.html
 */
void blink_timer_callback(TimerHandle_t xTimerID)
{
  (void) xTimerID;
  digitalToggle(LED_RED);
}

Ответы [ 3 ]

0 голосов
/ 02 февраля 2019

Это интересный способ получить немного больше пропускной способности рекламного пакета, но он идет вразрез с предполагаемым использованием UUID, которые предназначены для определения профилей обслуживания периферийного устройства и доступных характеристик.(Я предполагаю, что вы намереваетесь динамически генерировать UUID на основе некоторого значения датчика с плавающей запятой.)

Изменение UUID вызовет много проблем, когда вы попытаетесь подключиться к устройству с помощью стека связи BLE.центрального (главного) устройства, например телефона Android или IOS.Центральные устройства BLE ожидают сбора статической иерархии характеристических UUID от данного периферийного устройства, а затем используют эти UUID для идентификации соответствующих характеристических значений.Например, стек IOS BLE имеет константы для идентификации этих известных UUID рекламы, все они доступны перед подключением: CBAdvertisingDataLocalNameKey, CBAdvertisingDataManufacturerDataKey, CBAdvertisingDataServiceUUIDsKey, CBAdvertisingDataSolicitedServiceUUIDsKey.

Вместо этого обратите внимание, что профили универсальных атрибутов включают в себя типизацию данных, что позволяет вам напрямую устанавливать и восстанавливать значения с плавающей и двойной плавающей точкой IEEE-754 с характеристиками с плавающей точкой, а также типы характеристик с фиксированной точкой, которые могут лучше служить вашим целям,

Для поиска констант, используемых для идентификации типа, поищите в документации на стеке BLE вашего хоста «Дескриптор формата характеристического представления».

Я бы посоветовал вам потратить некоторое время на изучение iOS или Androidпримеры кода для связи BLE и различные учебные пособия по Bluetooth / GATT, которые описывают иерархическую структуру профилей устройства BLE.Найдите дешевое устройство BLE, которое соответствует одному из профилей GATT, здесь: https://www.bluetooth.com/specifications/gatt (вам может потребоваться создать бесплатную учетную запись.) И поэкспериментируйте с ним, связавшись со своим телефоном или ПК.Кроме того, посмотрите, можете ли вы найти образец кода Arduino, который обеспечивает соответствие устройства хорошо известному профилю GATT, и использовать его в качестве периферийного устройства.

0 голосов
/ 20 марта 2019

Как уже говорили другие, изменение UUID во время выполнения на самом деле не является ожидаемым поведением, тем более что центральные устройства (например, смартфоны) могут сохранять профиль периферийного устройства в кеше.Поэтому его динамическое изменение может вызвать некоторые проблемы.

Ожидаемым способом отправки пользовательских данных через рекламные пакеты BLE будет использование поля данных, специфичных для производителя.Он начинается с 2 байтов идентификатора компании, а затем может сопровождаться пользовательскими данными.Пока вы управляете как центральным, так и периферийным приложением, вы можете хранить свои плавающие числа по своему усмотрению.

Кроме того, будьте осторожны, поскольку отправка как пользовательских UUID, так и данных, специфичных для производителя, в рекламном пакете может занять некоторое пространство и рекламные пакетыограничены.Посмотрите ответ сканирования, если вам нужно отправить больше данных (например, несколько операций с плавающей запятой)

0 голосов
/ 01 февраля 2019

Я использую эту стандартную процедуру, чтобы объединить 2 байта в 1. Точка в float становится 'E', если вы этого не хотите, вы можете изменить float в long.

uint8_t CUSTOM_UUID[16];

void setup() {
  Serial.begin(115200);
}

void loop() {
  /* example with standard UUID: */
  stringToByte("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0");
  for (int i = 0; i < 16; i++) {
    Serial.println(CUSTOM_UUID[i], HEX);
  }
  Serial.println();

  /* example with float: */
  float number = 12345.67;
  char floatToString[32];
  dtostrf(number, 32, 2, floatToString);
  stringToByte(floatToString);
  for (int i = 0; i < 16; i++) {
    Serial.println(CUSTOM_UUID[i], HEX);
  }
  while(1);
}

void stringToByte(char * data)
{
  // Create two pointers that point to the start of the data
  char *leader = data;
  char *follower = leader;
  int counter = 0;

  // Iterate till at the end of the string
  while (*leader) {
      // Check to see if the current character is a -
      if (*leader != '-') {

          // Grab the next two characters and move leader forwards
          char high = *leader;
          leader++;
          char low = *leader;

          // Convert ASCII 0-9A-F to a value 0-15
          if (high > 0x39) high -= 7;
          high &= 0x0f;

          // Same again for the low byte:
          if (low > 0x39) low -= 7;
          low &= 0x0f;

          // Combine the two into a single byte and store in follower:
          *follower = (high << 4) | low;
          CUSTOM_UUID[counter] = *follower;

      } else {
          counter--;
      }

      // Move both pointers to the next character:
      leader++;
      follower++;
      // increase counter:
      counter++;
  }
}
...