Computer >> 컴퓨터 >  >> 체계 >> MAC

파티클의 강력한 블루투스 API를 사용하는 방법

이 게시물의 출처는 www.jaredwolff.com입니다.

패배했습니다.

나는 Bluetooth Low Energy 프로젝트를 작동시키기 위해 밤새도록 노력했습니다. 고통스러웠다. 실망스러웠다. 저는 포기할 준비가 되어 있었습니다.

Bluetooth Low Energy의 초창기였습니다. 그 이후로 점점 더 쉽게 개발할 수 있게 되었습니다. 파티클 메시 블루투스 라이브러리도 예외는 아닙니다.

이 연습에서는 Particle의 Bluetooth API를 사용하는 방법을 보여 드리겠습니다. 일부 LED를 구성하고 메시 네트워크의 모든 장치에서 변경되는 것을 지켜보겠습니다. 우리는 아르곤과 제논 보드를 사용할 것입니다.

준비가 된? 시작하겠습니다!

추신 이 게시물은 깁니다. 다운로드할 항목이 있으면 여기를 클릭하여 멋진 형식의 PDF를 다운로드하십시오.

1단계:블루투스 설정

  1. Particle Workbench 다운로드/설치

  2. 새 프로젝트를 만듭니다. 적절한 위치를 선택한 다음 이름을 ble_mesh로 지정했습니다.

    파티클의 강력한 블루투스 API를 사용하는 방법

  3. /src/로 이동 디렉토리를 열고 <your project name>.ino을 엽니다. 파일

  4. 그런 다음 deviceOS의 버전을> 1.3.0으로 변경했는지 확인합니다.

    파티클의 강력한 블루투스 API를 사용하는 방법

코드 작성

3가지 특징을 가진 서비스를 구축하고자 합니다. 특성은 각각 RGB LED의 강도와 관련이 있습니다. 블루투스 설정 방법은 다음과 같습니다.

  1. Setup()에서 기능 활성화 앱 제어 LED

    RGB.control(true);
    
  2. .ino 상단에 UUID를 설정하세요. 파일

     const char* serviceUuid = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E";
     const char* red         = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E";
     const char* green       = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E";
     const char* blue        = "6E400004-B5A3-F393-E0A9-E50E24DCCA9E";
    

    UUID는 고유 식별자 또는 주소입니다. 기기에서 다양한 서비스와 특성을 차별화하는 데 사용됩니다.

    위의 UUID는 이전 Particle 예제에서 사용되었습니다. 자신 만의 것을 만들고 싶다면 uuidgen을 사용할 수 있습니다. OSX 명령줄에서. 온라인 GUID 생성기와 같은 웹사이트로 이동할 수도 있습니다.

    파티클의 강력한 블루투스 API를 사용하는 방법

    위의 설정을 사용하여 고유한 UUID를 가져옵니다. 그런 다음 생성된 이 항목에서 서비스 및 특성 UUID를 만들 수 있습니다.

     const char* serviceUuid = "b425040**0**-fb4b-4746-b2b0-93f0e61122c6"; //service
     const char* red         = "b4250401-fb4b-4746-b2b0-93f0e61122c6"; //red char
     const char* green       = "b4250402-fb4b-4746-b2b0-93f0e61122c6"; //green char
     const char* blue        = "b4250403-fb4b-4746-b2b0-93f0e61122c6"; //blue char
    

    이 작업을 수행하는 데 옳고 그른 방법은 없습니다. 그러나 Bluetooth SIG에서 예약한 UUID를 사용하지 않도록 주의해야 합니다. 이것은 가능성이 매우 낮습니다. 재확인을 원하시면 여기와 여기로 가시면 됩니다.

    지금은 첫 번째 UUID 세트를 사용하겠습니다.

  3. Setup()에서 , 서비스를 초기화하십시오.

     // Set the RGB BLE service
     BleUuid rgbService(serviceUuid);
    

    서비스 "등록"의 첫 번째 단계입니다. 자세한 내용은 아래를 참조하세요.

  4. Setup()에서 각 특성을 초기화합니다.

     BleCharacteristic redCharacteristic("red", BleCharacteristicProperty::WRITE_WO_RSP, red, serviceUuid, onDataReceived, (void*)red);
     BleCharacteristic greenCharacteristic("green", BleCharacteristicProperty::WRITE_WO_RSP, green, serviceUuid, onDataReceived, (void*)green);
     BleCharacteristic blueCharacteristic("blue", BleCharacteristicProperty::WRITE_WO_RSP, blue, serviceUuid, onDataReceived, (void*)blue);
    

    이 설정에서는 WRITE_WO_RSP을 사용합니다. 재산. 이것은 우리가 데이터를 쓸 수 있게 하고 응답을 기대하지 않게 합니다.
    UUID를 다음 두 매개변수로 참조했습니다. 첫 번째는 특성 UUID입니다. 두 번째는 서비스 UUID입니다.

    다음 매개변수는 콜백 함수입니다. 이 콜백에 데이터가 기록되면 이 함수가 실행됩니다.

    마지막으로 마지막 매개변수는 컨텍스트입니다. 이것이 정확히 무엇을 의미합니까? 우리는 세 가지 특성 모두에 대해 동일한 콜백을 사용하고 있습니다. 어떤 특성이 기록되었는지 알 수 있는 유일한 방법은(적어도 deviceOS에서는) 컨텍스트를 설정하는 것입니다. 이 경우 이미 사용 가능한 UUID를 사용합니다.

  5. 특성을 정의한 직후 표시되도록 추가해 보겠습니다.

     // Add the characteristics
     BLE.addCharacteristic(redCharacteristic);
     BLE.addCharacteristic(greenCharacteristic);
     BLE.addCharacteristic(blueCharacteristic);
    
  6. 콜백 기능을 설정합니다.

     // Static function for handling Bluetooth Low Energy callbacks
     static void onDataReceived(const uint8_t* data, size_t len, const BlePeerDevice& peer, void* context) {
    
     }
    

    파일 상단(Setup() 이상)에서 이 작업을 수행할 수 있습니다. ) 나중에 더 자세히 정의하겠습니다.

  7. 마지막으로 장치를 연결할 수 있으려면 광고를 설정해야 합니다. 이 코드를 Setup() 끝에 배치합니다. 기능

     // Advertising data
     BleAdvertisingData advData;
    
     // Add the RGB LED service
     advData.appendServiceUUID(rgbService);
    
     // Start advertising!
     BLE.advertise(&advData);
    

    먼저 BleAdvertisingData를 만듭니다. 물체. rgbService을 추가합니다. 3단계부터. 마지막으로, 우리의 서비스와 특성을 발견할 수 있도록 광고를 시작할 수 있습니다!

테스트 시간

이 시점에서 우리는 최소한의 실행 가능한 프로그램을 가지고 있습니다. 이를 컴파일하고 파티클 하드웨어에 프로그래밍해 보겠습니다. 이것은 모든 Mesh 지원 장치에서 작동해야 합니다. (제논, 아르곤, 붕소)

  1. 테스트를 시작하기 전에 임시로 SYSTEM_MODE(MANUAL);를 추가하세요. 파일 상단으로 이동합니다. 이렇게 하면 장치가 메시 네트워크에 연결되지 않습니다. 시작 시 기기가 파란색으로 깜박이면 계속하기 전에 파티클 앱으로 기기를 설정해야 합니다.

  2. 여기에서 1.3.0-rc.1 이미지를 다운로드하십시오. Xenon의 경우 [email protected]이 필요합니다. 다른 사람들은 [email protected]을 찾으세요. 및 [email protected] 파일은 저작물 아래 페이지 하단에 있습니다.

    파티클의 강력한 블루투스 API를 사용하는 방법

  3. 장치를 DFU 모드로 전환하십시오. 모드 버튼 길게 누르기 잠시 후 재설정을 클릭합니다. 버튼. 모드 버튼을 계속 누르고 있습니다. LED가 노란색으로 깜박일 때까지

  4. 명령줄 창에서 다운로드한 파일을 저장한 디렉터리로 변경합니다. 제 경우 명령은 cd ~/Downloads/입니다.

  5. 그런 다음 실행:

     particle flash --usb [email protected]
    

    그러면 Xenon에 최신 OS가 설치됩니다. 완료되면 노란색으로 계속 빠르게 깜박입니다. 다른 파티클 메시 장치가 있는 경우 다시 일치하도록 파일 이름을 변경합니다.

  6. Visual Code에서 Command + Shift + P 사용 명령 메뉴를 팝업하는 키 조합. 입자:애플리케이션 컴파일(로컬)을 선택합니다.

    파티클의 강력한 블루투스 API를 사용하는 방법

  7. 나타날 수 있는 오류를 수정하십시오.

  8. 그런 다음 동일한 메뉴를 열고 Flash 애플리케이션(로컬)을 선택합니다.

    파티클의 강력한 블루투스 API를 사용하는 방법

  9. 프로그래밍이 완료되면 전화기를 꺼냅니다. 그런 다음 좋아하는 Bluetooth Low Energy 앱을 엽니다. 가장 좋은 것은 NRF Connect입니다. 및 하늘색 탐색기 이 예에서는 Light Blue Explorer를 사용하겠습니다.

  10. 이름이 "Xenon-"인 기기인지 확인 광고하고 있습니다. 삽입 장치의 고유 ID로.

    파티클의 강력한 블루투스 API를 사용하는 방법

  11. 기기를 찾아 이름을 클릭합니다.

  12. 서비스 및 특성 목록을 확인하세요. 지금까지 설정한 서비스 및 특성 UUID가 포함되어 있습니까? 예를 들어 서비스 UUID는 6E400001-B5A3-F393-E0A9-E50E24DCCA9E로 표시됩니까? ?

    파티클의 강력한 블루투스 API를 사용하는 방법

    모든 것이 예상대로 표시되면 좋은 위치에 있는 것입니다. 모든 항목이 일치하는지 확인하려면 이전 지침을 따르세요.

2단계:데이터 처리

우리 프로젝트의 다음 단계는 쓰기 이벤트를 처리하는 것입니다. onDataReceived를 업데이트하겠습니다. 기능.

코드 작성

  1. 먼저 LED의 상태를 유지할 구조체를 만들어 보겠습니다. 파일 상단에서 수행할 수 있습니다.

     // Variables for keeping state
     typedef struct {
       uint8_t red;
       uint8_t green;
       uint8_t blue;
     } led_level_t;
    
  2. 후반부는 이 데이터 유형을 사용하여 정적 변수를 만드는 것입니다.

     // Static level tracking
     static led_level_t m_led_level;
    

    처음 두 단계에서는 하나의 단일 변수를 사용하여 RGB LED의 세 가지 값을 나타낼 수 있습니다.

  3. 다음으로 onDataReceive 내부의 기본 오류를 확인하겠습니다. function 예를 들어 우리는 1바이트만 수신하고 있는지 확인하고 싶습니다.

     // We're only looking for one byte
       if( len != 1 ) {
         return;
     	}
    
  4. 다음으로 이 이벤트가 어떤 특성에서 비롯되었는지 확인하고 싶습니다. context을 사용할 수 있습니다. 이를 결정하는 변수입니다.

     // Sets the global level
       if( context == red ) {
         m_led_level.red = data[0];
       } else if ( context == green ) {
         m_led_level.green = data[0];
       } else if ( context == blue ) {
         m_led_level.blue = data[0];
       }
    

    이 경우 컨텍스트는 빨간색, 녹색 또는 파란색 UUID 문자열의 포인터와 같습니다. 또한 m_led_level를 설정하고 있음을 알 수 있습니다. . 이렇게 하면 값이 하나만 변경되더라도 RGB led를 업데이트할 수 있습니다.

  5. 마지막으로, 일단 설정되면 RGB에 쓸 수 있습니다. 개체

     // Set RGB color
     	RGB.color(m_led_level.red, m_led_level.green, m_led_level.blue);
    

코드 테스트

장치를 플래시하기 위해 이전과 동일한 절차를 진행해 봅시다.

  1. 장치를 DFU 모드로 전환하십시오. 모드 버튼 길게 누르기 재설정을 클릭합니다. 버튼. 모드 버튼을 계속 누르고 있습니다. LED가 노란색으로 깜박일 때까지

  2. 그런 다음 동일한 메뉴를 열고 Flash 애플리케이션(로컬)을 선택합니다.

    파티클의 강력한 블루투스 API를 사용하는 방법

  3. 프로그래밍이 완료되면 Light Blue Explorer를 사용하여 기기에 연결합니다. .

  4. 빨간색 LED에 적용되는 특성을 탭하세요.

  5. FF 쓰기 . 빨간색 LED가 켜져야 합니다.

    파티클의 강력한 블루투스 API를 사용하는 방법

    파티클의 강력한 블루투스 API를 사용하는 방법

  6. 00 쓰기 . 빨간색 LED가 꺼져야 합니다.

  7. 다른 두 특성에 대해서도 동일한 작업을 수행합니다. 이제 Bluetooth Low Energy를 통해 RGB LED를 완전히 제어할 수 있습니다!

3단계:메시를 통한 공유

마지막으로 BLE 메시지를 성공적으로 수신했으므로 이제 메시 네트워크로 전달할 차례입니다.

코드 작성

  1. 먼저 MANUAL 모드를 제거하겠습니다. SYSTEM_MODE(MANUAL); 주석 처리

  2. 파일 상단에 게시해야 하는 경우 추적하는 데 사용할 변수를 추가합니다.

     // Tracks when to publish to Mesh
     static bool m_publish;
    
  3. 그런 다음 Setup()에서 초기화합니다.

     // Set to false at first
     m_publish = false;
    
  4. 그런 다음 onDataReceived에서 RGB led를 설정한 후 콜백을 true로 설정해 보겠습니다.

     // Set RGB color
     RGB.color(m_led_level.red, m_led_level.green, m_led_level.blue);
    
     // Set to publish
     m_publish = true;
    
  5. loop()에 조건문을 추가해 보겠습니다. 기능. 그러면 메시 네트워크에 LED 상태가 게시됩니다.

     if( m_publish ) {
     	// Reset flag
     	m_publish = false;
    
     	// Publish to Mesh
       Mesh.publish("red", String::format("%d", m_led_level.red));
       Mesh.publish("green", String::format("%d", m_led_level.green));
       Mesh.publish("blue", String::format("%d", m_led_level.blue));
     }
    

    Mesh.publish 두 입력 모두에 문자열이 필요합니다. 따라서 String::format를 사용하고 있습니다. 빨강, 초록, 파랑 ​​값으로 문자열을 만듭니다.

  6. 그런 다음 Setup()에서 동일한 변수를 구독해 보겠습니다. . 그렇게 하면 다른 장치로 인해 이 장치의 LED도 업데이트될 수 있습니다.

     Mesh.subscribe("red", meshHandler);
     Mesh.subscribe("green", meshHandler);
     Mesh.subscribe("blue", meshHandler);
    
  7. meshHandler을 생성하려는 파일의 상단으로

     // Mesh event handler
     static void meshHandler(const char *event, const char *data)
     {
     }
    
  8. 이 애플리케이션에서는 event가 필요합니다. 매개변수 및 data 매개변수. 사용하려면 String으로 변경해야 합니다. 유형. 그렇게 하면 내장된 변환 및 비교 기능을 사용할 수 있습니다. 따라서 meshHandler 내부 기능 추가:

       // Convert to String for useful conversion and comparison functions
       String eventString = String(event);
       String dataString = String(data);
    
  9. 마지막으로 우리는 몇 가지 비교를 수행합니다. 먼저 이벤트 이름이 일치하는지 확인합니다. 그런 다음 dataString 값을 설정합니다. 해당 led 수준으로.

       // Determine which event we recieved
       if( eventString.equals("red") ) {
         m_led_level.red = dataString.toInt();
       } else if ( eventString.equals("green") ) {
         m_led_level.green = dataString.toInt();
       } else if ( eventString.equals("blue") ) {
         m_led_level.blue = dataString.toInt();
       } else {
     		return;
     	}
    
       // Set RGB color
       RGB.color(m_led_level.red, m_led_level.green, m_led_level.blue);
    

    그런 다음 마지막에 새로운 RGB 색상을 설정합니다. return를 추가하여 알 수 없는 상태를 처리하는 방법에 주목하세요. else의 문 부분. 혼란을 일으키기 전에 오류 조건을 걸러내는 것은 항상 좋은 일입니다!

코드 테스트

  1. 휴대전화에서 파티클 앱을 엽니다.

  2. 먼저 아르곤을 설정해 보겠습니다. 파란색으로 깜박이지 않으면 파란색으로 깜박일 때까지 모드 버튼을 누르고 있습니다.

    파티클의 강력한 블루투스 API를 사용하는 방법

    참고:이미 앱을 프로그래밍한 경우 LED는 기본적으로 꺼집니다. 모드 버튼을 5초 동안 누른 다음 계속합니다.

  3. 페어링 과정을 거칩니다. 앱이 모든 단계를 안내합니다. 메시 네트워크의 관리자 비밀번호를 기억해야 합니다.

    파티클의 강력한 블루투스 API를 사용하는 방법

    파티클의 강력한 블루투스 API를 사용하는 방법

    파티클의 강력한 블루투스 API를 사용하는 방법

    파티클의 강력한 블루투스 API를 사용하는 방법

  4. 최신 펌웨어(1.3.0)로 아르곤 프로그래밍(1단계 - 테스트 시간 - 2단계 참조) 이 작업을 수행하는 방법에 대한 알림)

  5. 노란색으로 빠르게 깜박이면 Tinker 앱으로 아르곤을 프로그래밍합니다. 출시 페이지에서 다운로드할 수 있습니다.

  6. 멋진 시안색 LED(파티클 클라우드에 연결됨)가 생기면 앱을 프로그래밍합니다. 클라우드 플래시 사용 드롭다운 메뉴의 옵션입니다.

    파티클의 강력한 블루투스 API를 사용하는 방법

    내가 말할 수 있는 한, 파티클은 클라우드에 연결할 때 로컬로 플래시된 모든 장치를 안전 모드로 강제 실행합니다. 제 설정일 수도 있습니다. 마일리지는 여기에서 다를 수 있습니다. Cloud Flash를 사용하는 것이 가장 좋습니다. .

    올바른 deviceOS 버전(1.3.0-rc1 ), 기기 유형(아르곤 ) 및 기기 이름(설정 시 지정한 이름 )

  7. 전화 앱을 사용하여 Xenon에 연결

  8. 전화 앱을 사용하여 Xenon을 Mesh 네트워크에 연결합니다.

  9. Cloud Flash를 사용하여 Xenon 플래시 . 전화 앱을 설정할 때 지정한 이름을 사용합니다. 장치가 Particle Cloud에 연결되어 있거나 안전 모드(보라색 LED)에 있는 한 프로그래밍해야 합니다.

    파티클의 강력한 블루투스 API를 사용하는 방법

    파티클의 강력한 블루투스 API를 사용하는 방법

  10. 일단 연결되면 재미있는 부분으로 가자. 하늘색 탐색기를 엽니다. 아르곤 또는 제논 .

    파티클의 강력한 블루투스 API를 사용하는 방법

  11. LED 특성 중 하나를 선택하고 값을 변경합니다.

    파티클의 강력한 블루투스 API를 사용하는 방법

    모든 장치에서 LED가 변경되어야 합니다!

최종 코드

다음은 모든 조각을 합친 최종 코드입니다. 이것을 사용하여 올바른 위치에 놓았는지 확인할 수 있습니다!!

/*
 * Project ble_mesh
 * Description: Bluetooth Low Energy + Mesh Example
 * Author: Jared Wolff
 * Date: 7/13/2019
 */

//SYSTEM_MODE(MANUAL);

// UUIDs for service + characteristics
const char* serviceUuid = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E";
const char* red         = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E";
const char* green       = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E";
const char* blue        = "6E400004-B5A3-F393-E0A9-E50E24DCCA9E";

// Set the RGB BLE service
BleUuid rgbService(serviceUuid);

// Variables for keeping state
typedef struct {
  uint8_t red;
  uint8_t green;
  uint8_t blue;
} led_level_t;

// Static level tracking
static led_level_t m_led_level;

// Tracks when to publish to Mesh
static bool m_publish;

// Mesh event handler
static void meshHandler(const char *event, const char *data)
{

  // Convert to String for useful conversion and comparison functions
  String eventString = String(event);
  String dataString = String(data);

  // Determine which event we recieved
  if( eventString.equals("red") ) {
    m_led_level.red = dataString.toInt();
  } else if ( eventString.equals("green") ) {
    m_led_level.green = dataString.toInt();
  } else if ( eventString.equals("blue") ) {
    m_led_level.blue = dataString.toInt();
  } else {
		return;
	}

  // Set RGB color
  RGB.color(m_led_level.red, m_led_level.green, m_led_level.blue);

}

// Static function for handling Bluetooth Low Energy callbacks
static void onDataReceived(const uint8_t* data, size_t len, const BlePeerDevice& peer, void* context) {

  // We're only looking for one byte
  if( len != 1 ) {
    return;
  }

  // Sets the global level
  if( context == red ) {
    m_led_level.red = data[0];
  } else if ( context == green ) {
    m_led_level.green = data[0];
  } else if ( context == blue ) {
    m_led_level.blue = data[0];
  }

  // Set RGB color
  RGB.color(m_led_level.red, m_led_level.green, m_led_level.blue);

  // Set to publish
  m_publish = true;

}

// setup() runs once, when the device is first turned on.
void setup() {

  // Enable app control of LED
  RGB.control(true);

  // Init default level
  m_led_level.red = 0;
  m_led_level.green = 0;
  m_led_level.blue = 0;

  // Set to false at first
  m_publish = false;

  // Set the subscription for Mesh updates
  Mesh.subscribe("red",meshHandler);
  Mesh.subscribe("green",meshHandler);
  Mesh.subscribe("blue",meshHandler);

  // Set up characteristics
  BleCharacteristic redCharacteristic("red", BleCharacteristicProperty::WRITE_WO_RSP, red, serviceUuid, onDataReceived, (void*)red);
  BleCharacteristic greenCharacteristic("green", BleCharacteristicProperty::WRITE_WO_RSP, green, serviceUuid, onDataReceived, (void*)green);
  BleCharacteristic blueCharacteristic("blue", BleCharacteristicProperty::WRITE_WO_RSP, blue, serviceUuid, onDataReceived, (void*)blue);

  // Add the characteristics
  BLE.addCharacteristic(redCharacteristic);
  BLE.addCharacteristic(greenCharacteristic);
  BLE.addCharacteristic(blueCharacteristic);

  // Advertising data
  BleAdvertisingData advData;

  // Add the RGB LED service
  advData.appendServiceUUID(rgbService);

  // Start advertising!
  BLE.advertise(&advData);
}

// loop() runs over and over again, as quickly as it can execute.
void loop() {

  // Checks the publish flag,
  // Publishes to a variable called "red" "green" and "blue"
  if( m_publish ) {

    // Reset flag
    m_publish = false;

    // Publish to Mesh
    Mesh.publish("red", String::format("%d", m_led_level.red));
    Mesh.publish("green", String::format("%d", m_led_level.green));
    Mesh.publish("blue", String::format("%d", m_led_level.blue));
  }

}

결론

이 튜토리얼에서는 파티클 메시 프로젝트에 블루투스를 추가하는 방법을 배웠습니다. 상상할 수 있듯이 가능성은 무한합니다. 예를 들어 사용자/관리 앱을 경험에 추가할 수 있습니다. 정말 대단합니다. ?

다음 책에서 이와 같은 콘텐츠를 더 기대할 수 있습니다. 파티클 메시에 대한 궁극적인 가이드 . 업데이트 및 내부 콘텐츠에 대한 내 목록을 구독하십시오. 또한 모든 초기 구독자는 출시될 때 할인을 받습니다! 여기를 클릭하여 가입하세요.