프로젝트에 현재 상태 또는 위치 추적 기능을 추가하고 싶으십니까? 솔루션(또는 솔루션의 부족)이 실망스럽습니까?
걱정하지 마십시오. 당신이 유일한 사람이 아닙니다!
이 게시물에서는 매우 기본적인 추적 및 알림 애플리케이션을 구현하는 방법을 배우게 됩니다. 입자 아르곤과 타일 메이트를 사용할 것입니다.
결국 타일이 있는지 여부를 알 수 있습니다. 또한 Pushover를 사용하여 선택한 기기에 푸시 알림을 보냅니다.
가자!
참고 시작하기 전에 이 게시물은 긴입니다. . PDF 버전을 다운로드하여 저장하고 나중에 볼 수 있습니다.
초기 조사
타일을 사용한다는 아이디어는 언뜻 보기에는 명확하지 않았습니다. 이상적으로는 전화를 사용하는 것이 더 합리적으로 보였습니다. 불행히도 이것은 실행 가능한 옵션이 아니었습니다. 좀 더 연구하고 블루투스 iOS 앱을 만들어야 합니다.
그래서 전화를 사용할 생각은 사라졌습니다.
그런 다음 저는 "어떤 기기가 어떤 역할을 항상 광고하시겠습니까?"
그것이 나를 Tile과 같은 트래커의 길로 인도한 것입니다.
도착한 후 몇 가지 관습적인 테스트가 있었습니다. 첫 번째 중지는 Tile 애플리케이션입니다.
기기를 연결하여 사용할 수 있었습니다. 흥겨운 곡을 연주하기도 했습니다. ?
그런 다음 Bluetooth 스캐너 앱 중 하나를 사용하기 시작했습니다. 나는 모든 결과와 빙고를 스크롤했습니다. 타일이 있었습니다!
몇 시간을 기다렸다가 다시 확인했습니다. 나는 그것이 잠시 후에 잠들지 않는지 확인하고 싶었다. 결과적으로 항상 광고입니다. 내가 말할 수 있는 한, 약 8초마다.
이 모든 테스트는 하나의 결론으로 이어집니다. 존재 감지에 쉽게 사용할 수 있다는 것입니다.
프로세스의 다음 단계는 아르곤과 함께 작동하는 방법을 알아내는 것이었습니다.
광고
이전 단계에서 수집한 것처럼 Tile이 약 8초마다 광고하고 있음을 알고 있습니다. 즉, Argon, Zenon 또는 Boron을 포함한 모든 장치를 사용하여 쉽게 스캔해야 합니다.
이 예에서는 아르곤을 사용하는 것이 좋습니다. 블루투스와 메시가 같은 라디오를 공유하기 때문입니다. Tile을 스캔할 때 Mesh에 연결된 Xenon은 광고 패킷을 놓치는 경우가 많습니다. 이것은 거짓 부정(그리고 좌절감!)으로 이어질 것입니다.
같은 맥락에서 아르곤이 메시 네트워크에 연결되지 않았는지 확인해야 합니다. CLI를 사용하여 제거할 수 있습니다. 장치를 컴퓨터에 연결하고 다음 명령을 실행하십시오.
particle mesh remove <device name/ID>
<기기 이름/ID>을(를) 바꿔야 합니다. 기기 이름 또는 ID로.
좋습니다. 좋은 내용으로 돌아갑니다.
광고는 블루투스에서 몇 가지 다른 목적을 가질 수 있습니다. 일반적으로 페어링 단계의 시작을 나타냅니다. 그렇게 하면 다른 장치에서 광고 장치를 사용할 수 있음을 알 수 있습니다.
또한 광고 장치에는 어떤 서비스가 있는지 표시됩니다. 이 정보를 사용하여 일치하지 않는 기기를 필터링할 수 있습니다.
예를 들어 다음은 Tile 장치에서 사용할 수 있는 서비스의 스크린샷입니다.
스캔할 때 연결하는 장치에 0xfeed
의 서비스 UUID가 있는지 다시 확인합니다. .
하지만 Bluetooth 영역에 대해 자세히 알아보기 전에 Logger를 사용하여 디버깅을 위해 앱을 설정해 보겠습니다.
로깅
이 튜토리얼에서는 Logger를 사용할 것입니다. particle serial monitor
을 사용하여 앱의 로그 메시지를 표시할 수 있습니다. .
로거의 멋진 기능 중 하나는 메시지 계층 구조라는 아이디어입니다. 이를 통해 디자이너는 필요하지 않은 메시지를 선택적으로 음소거할 수 있습니다.
예를 들어 디버깅에 사용되는 메시지가 있는 경우. 제거하거나 주석 처리할 수 있습니다. 또는 LOG_LEVEL
을 늘릴 수 있습니다. 따라서 효과적으로 무시됩니다.
다음은 logging.h
에서 사용할 수 있는 로깅 수준입니다. Particle의 device-os 저장소에서:
// Log level. Ensure log_level_name() is updated for newly added levels
typedef enum LogLevel {
LOG_LEVEL_ALL = 1, // Log all messages
LOG_LEVEL_TRACE = 1,
LOG_LEVEL_INFO = 30,
LOG_LEVEL_WARN = 40,
LOG_LEVEL_ERROR = 50,
LOG_LEVEL_PANIC = 60,
LOG_LEVEL_NONE = 70, // Do not log any messages
// Compatibility levels
DEFAULT_LEVEL = 0,
ALL_LEVEL = LOG_LEVEL_ALL,
TRACE_LEVEL = LOG_LEVEL_TRACE,
LOG_LEVEL = LOG_LEVEL_TRACE, // Deprecated
DEBUG_LEVEL = LOG_LEVEL_TRACE, // Deprecated
INFO_LEVEL = LOG_LEVEL_INFO,
WARN_LEVEL = LOG_LEVEL_WARN,
ERROR_LEVEL = LOG_LEVEL_ERROR,
PANIC_LEVEL = LOG_LEVEL_PANIC,
NO_LOG_LEVEL = LOG_LEVEL_NONE
} LogLevel;
멋진 로그 수준. 하지만 어떻게 사용합니까?
다음 함수 중 하나를 호출하여 사용할 수 있습니다.
Log.trace
, Log.info
, Log.warn
, Log.error
.
예:
Log.trace("This is a TRACE message.");
로그 수준을 LOG_LEVEL_INFO
로 설정하면 Log.info
의 메시지만 표시됩니다. , Log.warn
및 Log.error
. LOG_LEVEL_WARN
? Log.warn
만 및 Log.error
나타납니다. (당신이 아이디어를 얻기를 바랍니다.)
이를 설정하기 위해 기본 수준을 LOG_LEVEL_ERROR
으로 설정합니다. . 앱별 LOG_LEVEL
도 설정합니다. LOG_LEVEL_TRACE
로 . 최종 결과는 다음과 같아야 합니다.
// For logging
SerialLogHandler logHandler(115200, LOG_LEVEL_ERROR, {
{ "app", LOG_LEVEL_TRACE }, // enable all app messages
});
이렇게 하면 DeviceOS 로그 메시지로 스팸을 받지 않습니다. 또한 앱 자체에서 해당하는 모든 메시지를 받습니다.
그런데 장치를 단일 LOG_LEVEL
로 설정하려면 다음과 같이 설정할 수 있습니다.
SerialLogHandler logHandler(LOG_LEVEL_INFO);
Particle의 DeviceOS를 계속 사용하면서 이것이 얼마나 편리한지 곧 깨닫게 될 것입니다. 이제 좋은 내용으로 넘어갑시다!
설정
먼저 올바른 버전의 DeviceOS를 사용하고 있는지 확인해야 합니다. 1.3 이후의 모든 버전에는 Bluetooth가 있습니다. 여기에서 지침을 얻을 수 있습니다.
다음으로 타일 스캔을 시작하겠습니다. loop()
에서 이 작업을 수행하려고 합니다. 지정된 간격으로 기능합니다. millis()
를 사용하겠습니다. 이 경우 타이머:
// Scan for devices
if( (millis() > lastSeen + TILE_RE_CHECK_MS) ){
BLE.scan(scanResultCallback, NULL);
}
lastSeen
을 정의했는지 확인하십시오. 다음과 같이 파일 상단에:
system_tick_t lastSeen = 0;
타일이 "본" 마지막 시간을 추적하는 데 사용할 것입니다. 즉, Argon이 Tile에서 광고 패킷을 마지막으로 본 시간입니다.
TILE_RE_CHECK_MS
다음과 같이 정의할 수 있습니다.
#define TILE_RE_CHECK_MS 7500
이런 식으로 우리는 광고 패킷을 위해 최소한 7.5초마다 확인하고 있습니다.
Tile 장치를 찾기 위해 BLE.scan
를 사용할 것입니다. . 호출하면 스캔 프로세스가 시작됩니다. 기기가 발견됨에 따라 scanResultCallback
발사됩니다.
지금은 scanResultCallback
를 정의할 수 있습니다. 파일 상단:
void scanResultCallback(const BleScanResult *scanResult, void *context) {
}
BleScanResult
이 포함되어 있음을 알 수 있습니다. . 여기에는 주소, RSSI 및 장치 이름(사용 가능한 경우) 및 사용 가능한 서비스 정보가 포함됩니다. 이것은 나중에 Tile 장치를 찾을 때 유용할 것입니다!
BLE.scan
스캔이 완료될 때까지 반환되지 않습니다. 스캔의 기본 시간 제한은 5초입니다. BLE.setScanTimeout()
을 사용하여 해당 값을 변경할 수 있습니다. . setScanTimeout
10ms 단위로 단위를 취합니다. 따라서 500ms 시간 제한의 경우 값 50이 필요합니다.
이 앱의 경우 8초(8000ms) 값을 사용하는 것이 좋습니다. 다음과 같이 설정할 수 있습니다.
BLE.setScanTimeout(800);
이 경우 장치는 Tile이 광고하는 데 걸리는 시간 동안 검색합니다. 그렇게 하면 광고 패킷을 놓칠 가능성이 줄어듭니다.
스캔 결과 처리
이제 scanResultCallback
이 있습니다. 내부에서 무슨 일이 일어나고 있는지 정의할 수 있습니다.
먼저 광고 데이터 내에서 서비스 정보를 얻고 싶습니다. 가장 좋은 방법은 scanResult->advertisingData.serviceUUID
를 사용하는 것입니다. . 복사할 UUID 배열을 전달합니다.
BleUuid uuids[4];
int uuidsAvail = scanResult->advertisingData.serviceUUID(uuids,sizeof(uuids)/sizeof(BleUuid));
그러면 uuids
가 채워집니다. 그런 식으로 반복할 수 있습니다. uuidsAvail
사용 가능한 UUID의 양과 같습니다.
우리의 경우 특정 UUID를 찾고 있습니다. 파일의 맨 위에 정의하겠습니다.
#define TILE_UUID 0xfeed
일반적으로 UUID는 많습니다 더 길게. 이와 같은 짧은 UUID는 예약되었거나 Bluetooth 사양의 일부임을 의미합니다. 두 경우 모두 32비트 또는 128비트 버전을 확인하는 것과 같은 방식으로 확인합니다.
진단을 위해 장치 정보를 인쇄할 수도 있습니다. 이 경우 RSSI 및 장치 MAC 주소가 유용합니다.
// Print out mac info
BleAddress addr = scanResult->address;
Log.trace("MAC: %02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
Log.trace("RSSI: %dBm", scanResult->rssi);
마지막으로 찾은 장치에 UUID가 있는지 확인하기 위해 루프를 설정해 보겠습니다.
// Loop over all available UUIDs
// For tile devices there should only be one
for(int i = 0; i < uuidsAvail; i++){
// Print out the UUID we're looking for
if( uuids[i].shorted() == TILE_UUID ) {
Log.trace("UUID: %x", uuids[i].shorted());
// Stop scanning
BLE.stopScanning();
return;
}
}
UUID의 "단축" 버전을 TILE_UUID
과 쉽게 비교할 수 있습니다. . 단순한 정수이므로 복잡한 메모리 비교 작업이 필요하지 않습니다. 따라서 if( uuids[i].shorted() == TILE_UUID )
을 사용하여 잘 작동합니다.
Log.trace
을(를) 사용할 수도 있습니다. 진단 정보를 인쇄합니다. 이 경우 shorted()
을 인쇄하는 데 사용합니다. UUID의 버전입니다.
테스트해보세요!
지금까지 가지고 있는 것을 테스트해 봅시다!
아르곤에 앱을 프로그래밍하십시오. 터미널을 열고 particle serial monitor
을 실행합니다. 디버그 메시지를 보려면 다음은 볼 수 있는 항목의 예입니다.
0000005825 [app] TRACE: MAC: 65:C7:B3:AF:73:5C
0000005827 [app] TRACE: RSSI: -37Bm
0000005954 [app] TRACE: MAC: B3:D9:F1:F0:5D:7E
0000005955 [app] TRACE: RSSI: -62Bm
0000006069 [app] TRACE: MAC: C5:F0:74:3D:13:77
0000006071 [app] TRACE: RSSI: -62Bm
0000006217 [app] TRACE: MAC: 65:C7:B3:AF:73:5C
0000006219 [app] TRACE: RSSI: -39Bm
0000006224 [app] TRACE: MAC: B3:D9:F1:F0:5D:7E
0000006225 [app] TRACE: RSSI: -62Bm
0000006296 [app] TRACE: MAC: D7:E7:FE:0C:A5:C0
0000006298 [app] TRACE: RSSI: -60Bm
0000006299 [app] TRACE: UUID: feed
메시지에 TRACE
이 어떻게 포함되어 있는지 확인하세요. 또한 [app]
? 즉, 애플리케이션 코드에서 시작된 추적 메시지입니다. 편리하죠?
이 코드는 특히 광고하는 Bluetooth 장치가 많은 환경에 있는 경우 스팸을 빠르게 받습니다. Tile이 켜져 있고 결국 실행 중인 경우 UUID: feed
메시지가 표시됩니다. . 아르곤이 타일을 찾았다는 뜻입니다!
다음으로 온보드 모드 버튼을 사용하여 Tile의 주소를 메모리에 "프로그래밍"합니다. 그렇게 하면 신경 쓰지 않는 모든 기기를 걸러낼 수 있습니다.
버튼 누름 시 장치 추가
먼저 모드 버튼을 모니터링하는 방법을 알아야 합니다. 문서에 따르면 가장 좋은 방법은 System.on
를 사용하는 것입니다. .
System.on(button_click, eventHandler);
첫 번째 인수는 시스템 이벤트의 이름입니다. 우리의 경우 button_click
입니다. . 두 번째 인수는 이벤트 핸들러 함수입니다. eventHandler
이라고 부를 것입니다. 지금은.
이제 eventHandler
을 생성해 보겠습니다.
void eventHandler(system_event_t event, int duration, void* )
{
}
중요: Log
를 사용할 수 없습니다. eventHandler
내부의 함수 . 그것을 테스트하는 쉬운 방법은 D7의 LED를 토글하는 것입니다. 설정합시다!
setup()
에서 LED를 초기화합니다.
// Set LED pin
pinMode(D7,OUTPUT);
그런 다음 eventHandler
안에 이것을 추가할 수 있습니다.
if( event == button_click ) {
if( digitalRead(D7) ) {
digitalWrite(D7,LOW);
} else {
digitalWrite(D7,HIGH);
}
}
그런 다음 D7(온보드 파란색 LED)에 쓸 수 있습니다. digitalRead
도 사용할 수 있습니다. LED의 상태를 읽는다. HIGH
로 응답합니다. 또는 LOW
상황에 따라.
펌웨어를 장치에 로드하면 파란색 LED를 멋지게 제어할 수 있습니다!
다음 섹션에서는 모드 버튼을 사용하여 장치를 "학습" 모드로 전환합니다. 이렇게 하면 대상 Tile 장치로 원터치 설정을 수행할 수 있습니다.
EEPROM에 주소 저장
이 다음 단계에서는 타일의 주소를 EEPROM에 저장합니다. 그렇게 하면 기기가 다시 시작되거나 전원이 꺼지더라도 나중에 타일을 계속 식별할 수 있습니다.
그래도 한 가지 남는 질문이 있습니다. 처음에 주소를 저장하려면 어떻게 해야 합니까?
버튼 누름을 모니터링하여 장치를 "학습" 모드로 전환할 수 있습니다. 장치는 타일을 검색하고 타일을 찾으면 주소를 저장합니다.
먼저 if( uuids[i].shorted() == TILE_UUID )
내에 조건문을 추가해 보겠습니다. :
// If we're in learning mode. Save to EEPROM
if( isLearningModeOn() ) {
searchAddress = scanResult->address;
EEPROM.put(TILE_EEPROM_ADDRESS, searchAddress);
setLearningModeOff();
}
우리는 우리가 "학습 모드"에 있다는 것을 아는 방법으로 D7의 상태를 사용할 것입니다. digitalRead(D7)
를 사용하여 D7을 읽음으로써 이를 수행합니다. . 이를 보다 명확하게 해주는 함수를 만들어 보겠습니다.
bool isLearningModeOn() {
return (digitalRead(D7) == HIGH);
}
digitalWrite(D7,LOW);
를 대체할 수도 있습니다. 및 digitalWrite(D7,HIGH);
유사한 기능으로. 그렇게 하면 우리가 하고 있는 일이 더 명확해집니다.
// Set "Learning mode" on
void setLearningModeOn() {
digitalWrite(D7,HIGH);
}
// Set "Learning mode" off
void setLearningModeOff() {
digitalWrite(D7,LOW);
}
그런 다음 전역 변수 searchAddress
를 할당합니다. 스캔 결과로. searchAddress
를 설정합니다. 파일 상단에 다음과 같이 표시됩니다.
BleAddress searchAddress;
다음으로 EEPROM.put
을 사용하여 비휘발성 메모리에 저장하려고 합니다. . TILE_EEPROM_ADDRESS
0xa
으로 정의됩니다. . TILE_EEPROM_ADDRESS
을 정의할 수 있습니다. 당신의 공상을 간지럽히는 메모리 주소를 사용하십시오. 다음은 파일 상단에 있는 전체 정의입니다.
#define TILE_EEPROM_ADDRESS 0xa
마지막으로 setLearningModeOff()
를 사용하여 LED와 "학습 모드"를 끕니다.
기기가 발견될 때마다 millis()
을 사용합니다. lastSeen
설정 . 또한 lastRSSI
을 사용하여 마지막 RSSI를 추적할 수 있습니다. . 장치가 얼마나 가까운지 대략적으로 알 수 있는 저렴한 방법입니다. scanResult->rssi
을 사용하겠습니다. 이 정보를 가져오고 lastRSSI
로 설정하려면 변수.
전반적으로 변경 사항은 다음과 같아야 합니다.
...
// Print out the UUID we're looking for
if( uuids[i].shorted() == TILE_UUID ) {
Log.trace("UUID: %x", uuids[i].shorted());
// If we're in learning mode. Save to EEprom
if( isLearningModeOn() ) {
searchAddress = scanResult->address;
EEPROM.put(TILE_EEPROM_ADDRESS, searchAddress);
setLearningModeOff();
}
// Save info
lastSeen = millis();
lastRSSI = scanResult->rssi;
// Stop scanning
BLE.stopScanning();
return;
}
이 기능을 사용하기 전에 searchAddress
과 일치하지 않는 기기를 필터링할 수 있습니다. . if( uuids[i].shorted() == TILE_UUID )
앞에 다음을 추가하세요. :
// If device address doesn't match or we're not in "learning mode"
if( !(searchAddress == scanResult->address) && !isLearningModeOn() ) {
return;
}
일치하지 않는 장치는 건너뜁니다. 주소가 일치하거나 "학습 모드"에 있는 경우에만 진행됩니다.
이제 searchAddress
을 로드하기 위해 시작할 때 플래시에서 로드해야 합니다. 이 줄을 setup():
에 추가하세요.
EEPROM.get(TILE_EEPROM_ADDRESS, searchAddress);
그런 다음 주소가 유효한지 확인하십시오. 모든 바이트가 0xFF
이면 유효하지 않습니다. :
// Warning about address
if( searchAddress == BleAddress("ff:ff:ff:ff:ff:ff") ) {
Log.warn("Place this board into learning mode");
Log.warn("and keep your Tile near by.");
}
우리는 타일의 주소를 아르곤에 "가르칠" 수 있어야 합니다. 테스트해봅시다!
테스트해 보세요.
이제 앱을 컴파일하고 실행하면 더 이상 로그 출력이 없다는 것을 알 수 있습니까? 타일 주소를 파티클 장치에 "가르쳐야" 합니다. 따라서 모드 버튼을 누르십시오. 파란색 LED가 켜져야 합니다.
타일을 찾으면 LED가 꺼지고 명령줄에 일부 출력이 표시됩니다. 이전에 본 것과 유사:
0000006296 [app] TRACE: MAC: D7:E7:FE:0C:A5:C0
0000006298 [app] TRACE: RSSI: -60Bm
0000006299 [app] TRACE: UUID: feed
장치가 메모리에 커밋되었습니다!
재설정 후에도 여전히 저장되어 있는지 확인할 수 있습니다. 재설정을 누르세요. 버튼을 누르고 위와 동일한 출력을 확인합니다. 그것이 나타나면 우리는 여전히 좋습니다!
클라우드 업데이트
마지막으로 checkTileStateChanged
라는 함수를 설정해 보겠습니다. . 이를 사용하여 정기적으로 Tile 상태의 변경 사항을 확인합니다.
bool checkTileStateChanged( TilePresenceType *presence ) {
}
이 함수의 주요 목적은 lastSeen
를 비교하는 것입니다. "시간 초과" 기간이 있는 변수입니다. 우리의 경우 시간 초과 기간은 TILE_NOT_HERE_MS
입니다. 다음으로 설정해야 합니다.
#define TILE_NOT_HERE_MS 30000
프로그램 상단 근처에 있습니다. 또한 두 가지 조건이 더 있습니다. lastSeen
는 0과 같습니다. 이는 일반적으로 앱이 시작 후 아직 Tile을 찾지 못했기 때문입니다.
마지막 경우는 기기가 표시되고 lastSeen
인 경우입니다. 0이 아닙니다. 따라서 checkTileStateChanged
내에서 모든 것을 하나로 합치자.
// Check to see if it's here.
if( millis() > lastSeen+TILE_NOT_HERE_MS ) {
} else if ( lastSeen == 0 ) {
} else {
}
return false;
이제 이 함수가 상태가 변경된 경우 true를 반환하기를 원합니다. . 따라서 TilePresenceType
계약서의 포인터.
TilePresenceType
가능한 모든 상태의 단순히 열거입니다. 파일 상단에도 붙일 수 있습니다. 여기 있습니다:
typedef enum {
PresenceUnknown,
Here,
NotHere
} TilePresenceType;
또한 함수에 전달할 수 있는 전역 변수가 필요합니다. 파일 상단에도 설정하세요.
// Default status
TilePresenceType present = PresenceUnknown;
이제 각 단계에서 비교할 수 있습니다. 기준을 충족합니까? 상태가 지난번과 다른가요? 그렇다면 true를 반환하십시오.
presence
를 설정해야 함을 기억하십시오. 새로 업데이트된 값으로 따라서 각 조건은 현재 상태 값을 업데이트해야 합니다. 예:
*presence = NotHere;
완전히 플러시된 함수는 다음과 같습니다.
bool checkTileStateChanged( TilePresenceType *presence ) {
// Check to see if it's here.
if( millis() > lastSeen+TILE_NOT_HERE_MS ) {
if( *presence != NotHere ) {
*presence = NotHere;
Log.trace("not here!");
return true;
}
// Case if we've just started up
} else if ( lastSeen == 0 ) {
if( *presence != PresenceUnknown ) {
*presence = PresenceUnknown;
Log.trace("unknown!");
return true;
}
// Case if lastSeen is < TILE_NOT_HERE_MS
} else {
if( *presence != Here ) {
*presence = Here;
Log.trace("here!");
return true;
}
}
return false;
}
이제 타이머 아래의 메인 루프에서 이 함수를 사용하여 Ble.scan()
를 시작할 수 있습니다. . 이를 사용하여 JSON 페이로드를 보낼 수 있습니다. 이 경우 Bluetooth 주소, lastSeen
와 같은 중요한 정보가 포함됩니다. 데이터, lastRSSI
데이터 및 메시지.
// If we have a change
if( checkTileStateChanged(&present) ) {
}
char
배열을 사용하겠습니다. 주소를 문자열 형식으로 가져옵니다. toString()
를 함께 연결할 수 있습니다. toCharArray
사용 필요한 것을 얻기 위해.
// Get the address string
char address[18];
searchAddress.toString().toCharArray(address,sizeof(address));
페이로드 문자열의 예는 다음과 같습니다.
// Create payload
status = String::format("{\"address\":\"%s\",\"lastSeen\":%d,\"lastRSSI\":%i,\"status\":\"%s\"}",
address, lastSeen, lastRSSI, messages[present]);
status
파일의 맨 위에 정의된 단순히 문자열입니다.
// The payload going to the cloud
String status;
messages
이라는 변수도 있음을 알 수 있습니다. . 이것은 문자열의 정적 const 배열입니다. TilePresenceType
의 값에 매핑됩니다. . 이렇게 생겼습니다
const char * messages[] {
"unknown",
"here",
"not here"
};
그렇게 하면 PresenceUnknown
"unknown"
와 일치 , Here
"here"
와 일치 등. 문자열을 열거형과 연결하는 저렴하고 쉬운 방법입니다.
마지막으로 게시하고 처리합니다. 이렇게 하면 업데이트를 즉시 보낼 수 있습니다.
// Publish the RSSI and Device Info
Particle.publish("status", status, PRIVATE, WITH_ACK);
// Process the publish event immediately
Particle.process();
전체 기능은 결국 다음과 같아야 합니다.
// If we have a change
if( checkTileStateChanged(&present) ) {
// Get the address string
char address[18];
searchAddress.toString().toCharArray(address,sizeof(address));
// Create payload
status = String::format("{\"address\":\"%s\",\"lastSeen\":%d,\"lastRSSI\":%i,\"status\":\"%s\"}",
address, lastSeen, lastRSSI, messages[present]);
// Publish the RSSI and Device Info
Particle.publish("status", status, PRIVATE, WITH_ACK);
// Process the publish event immediately
Particle.process();
}
이제 테스트해 봅시다!
테스트 중입니다!
Particle Workbench를 떠나는 이벤트 없이 Publish 이벤트가 발생하는지 테스트할 수 있습니다. 보기 → 터미널로 이동하여 새 터미널을 엽니다. 그런 다음 다음 명령을 사용하십시오.
particle subscribe --device <device_name> <event_name>
<device_name>
바꾸기 장치의 이름 또는 ID로.
<event_name>
바꾸기 이벤트 이름으로. 우리의 경우 status
입니다. .
그런 다음 배터리를 제거하고 "여기에 없음" 경고를 기다리면 모든 것을 테스트할 수 있습니다. 배터리를 다시 연결하면 "여기" 알림이 표시됩니다.
다음은 출력의 예입니다.
> particle subscribe --device hamster_turkey status
Subscribing to "status" from hamster_turkey's stream
Listening to: /v1/devices/hamster_turkey/events/status
{"name":"status","data":"{\"address\":\"C0:A5:0C:FE:E7:D7\",\"lastSeen\":40154002,\"lastRSSI\":-82,\"status\":\"not here\"}","ttl":60,"published_at":"2019-09-07T02:29:42.232Z","coreid":"e00fce68d36c42ef433428eb"}
{"name":"status","data":"{\"address\":\"C0:A5:0C:FE:E7:D7\",\"lastSeen\":40193547,\"lastRSSI\":-83,\"status\":\"here\"}","ttl":60,"published_at":"2019-09-07T02:29:50.352Z","coreid":"e00fce68d36c42ef433428eb"}
웹훅 구성
이 자습서의 마지막 부분에서는 웹훅을 사용하여 푸시 알림을 설정합니다. 앞서 언급했듯이 Pushover와 편리한 API를 사용하여 선택한 기기로 푸시 알림을 보냅니다.
Pushover에는 사용하기 매우 쉬운 API가 있습니다. 푸시 알림을 보내도록 앱을 코딩하고 싶지 않은 상황을 위한 스위스 군용 칼입니다.
가장 먼저 기록해야 할 것은 사용자 키입니다. Pushover에 로그인하면 얻을 수 있습니다. 참고:아직 계정을 설정하지 않은 경우 먼저 계정을 설정해야 합니다.
다음과 같아야 합니다.
로그인했는데 이 페이지가 표시되지 않으면 Pushover 로고를 클릭하세요. 그러면 다시 돌아올 수 있습니다.
다음으로 애플리케이션을 생성해 보겠습니다. 앱 및 플러그인을 클릭합니다. 화면 상단에 있습니다.
그런 다음 새 애플리케이션 만들기를 클릭해야 합니다. 이렇게 하면 API 토큰을 얻을 수 있습니다. Particle Webhook 설정에 필요합니다.
적절하다고 생각되는 이름을 설정합니다. 알림을 받으려면 설명을 입력하세요. 상자 클릭 그런 다음 응용 프로그램 만들기를 클릭합니다.
다음 페이지로 이동해야 합니다. API 토큰/키 복사 및 저장 몇 단계를 거치면 이 정보도 필요합니다.
이제 Webhook을 설정해 보겠습니다. https://console.particle.io로 이동하여 새 통합을 만드세요.
이벤트 이름을 설정하겠습니다. 상태로 .
URL https://api.pushover.net/1/messages.json으로
또한 특정 기기로 필터링하려면 기기 드롭다운에서 선택해야 합니다.
고급 설정 아래 몇 가지 필드를 설정하여 마치겠습니다.
다음 필드를 만듭니다. 토큰, 사용자 , 제목 , 및 메시지 . 그런 다음 토큰을 API 토큰으로 설정합니다. 우리는 더 일찍 얻었다. 사용자 키에 대해서도 동일한 작업을 수행합니다.
제목 메시지 제목으로 표시됩니다. 당신에게 의미가 있는 대로 만드십시오.
메시지를 설정할 수 있습니다. The Tile is currently {{{status}}}. RSSI: {{{lastRSSI}}}
으로 .
여기서는 콧수염 템플릿을 사용하고 있습니다. 게시된 페이로드의 데이터를 사용하고 원하는 대로 다시 포맷할 수 있습니다. 우리의 경우 "공백 채우기"에 사용하고 있습니다. 메시지 일단 처리되면 다음과 같이 보일 것입니다:
The Tile is currently here. RSSI: -77
참고로 이 템플릿에 대해서는 내 가이드에서 더 자세히 설명하겠습니다. 그러니 계속 지켜봐 주십시오!
테스트하기
통합이 완료되면 이전 단계에서 수행한 작업을 테스트할 수 있습니다. 배터리를 제거하고 "not here" 메시지를 기다립니다. 다시 넣고 "여기" 메시지를 기다립니다.
iPhone에서는 다음과 같이 표시됩니다.
보시다시피, 나는 그것을 잔뜩 테스트했습니다! ?
여기까지 했고 모든 것이 제대로 작동한다면 훌륭한 일입니다. 이제 집, 사무실 등 어디에서나 사용할 수 있는 Tile 추적기가 있습니다.
코드
이 예제의 완성된 코드를 찾고 계십니까? 나도 그럴거야! Github에서 호스팅되며 여기에서 사용할 수 있습니다.
결론
상상할 수 있듯이 이 기사에서 사용된 기술과 기술은 다양한 방식으로 사용될 수 있습니다. 몇 가지 핵심 내용을 요약해 보겠습니다.
- Bluetooth Central을 사용하여 기성 Tile 기기 검색 및 식별
- 타일 식별 정보를 EEPROM에 저장합니다. 그렇게 하면 시작 시 검색할 수 있습니다.
- 익숙한
Particle.publish
사용 업데이트를 클라우드에 푸시합니다. - 입자 통합 웹훅을 사용하여 상태 변경에 대한 푸시 알림 생성
이제 모든 작업이 완료되었으므로 확장하고 해킹하여 자신의 것으로 만드십시오. 아 그리고 공유하는 것도 잊지 마세요! 당신의 의견을 듣고 싶습니다. [email protected]
이 게시물을 좋아합니까? 아래 공유 링크 중 하나를 클릭하고 전 세계와 공유하십시오. :)
내 블로그의 교차 게시물입니다. 여기에서 원본을 확인할 수 있습니다.
더 배우고 싶으신가요? 파티클 플랫폼을 최대한 활용하는 방법에 대한 가이드를 작성 중입니다. 여기에서 자세히 알아보세요.