कभी किसी प्रोजेक्ट में उपस्थिति या स्थान ट्रैकिंग जोड़ना चाहते हैं? समाधान (या उसके अभाव) से निराश हैं?
चिंता न करें, केवल आप ही नहीं हैं!
इस पोस्ट में आप सीखेंगे कि एक बहुत ही बुनियादी ट्रैकिंग और अधिसूचना एप्लिकेशन को कैसे कार्यान्वित किया जाए। हम एक कण आर्गन और एक टाइल मेट का उपयोग करेंगे।
अंत तक आप बता पाएंगे कि टाइल कब मौजूद है या नहीं। साथ ही हम पुशओवर का उपयोग आपके द्वारा चुने गए डिवाइस पर पुश नोटिफिकेशन भेजने के लिए करेंगे।
चलो चलते हैं!
नोट आरंभ करने से पहले, यह पोस्ट लंबी है . आप पीडीएफ संस्करण डाउनलोड कर सकते हैं ताकि आप इसे बाद में सहेज सकें और देख सकें।
प्रारंभिक जांच
टाइल का उपयोग करने का विचार पहली नज़र में स्पष्ट नहीं था। आदर्श रूप से, फ़ोन का उपयोग करना अधिक समझ में आता था। दुर्भाग्य से, यह एक व्यवहार्य विकल्प के रूप में नहीं था। इसके लिए कुछ और शोध और ब्लूटूथ आईओएस ऐप बनाने की आवश्यकता होगी।
तो, फ़ोन का उपयोग करने का विचार समाप्त हो गया था।
फिर मैंने सोचा, "क्या डिवाइस करते हैं हर समय विज्ञापन दें?"
यही मुझे टाइल जैसे ट्रैकर के रास्ते पर ले गया।
इसके आने के बाद कुछ प्रथागत परीक्षण हुआ। पहला पड़ाव, टाइल एप्लिकेशन।
मैं डिवाइस को कनेक्ट और उपयोग करने में सक्षम था। मैंने इसे एक आकर्षक धुन भी बजाई। ?
फिर, मैं ब्लूटूथ स्कैनर ऐप्स में से एक का उपयोग करने के लिए आगे बढ़ा। मैंने सभी परिणामों और बिंगो को स्क्रॉल किया। टाइल थी!
मैंने कुछ घंटे भी इंतजार किया और इसे फिर से चेक किया। मैं यह सुनिश्चित करना चाहता था कि थोड़ी देर बाद वह सो न जाए। पता चला, यह हमेशा विज्ञापन होता है। जहाँ तक मैं बता सकता हूँ, हर 8 सेकंड के बारे में।
इस सभी परीक्षण से एक निष्कर्ष निकलता है:इसका उपयोग उपस्थिति का पता लगाने के लिए आसानी से किया जा सकता है।
प्रक्रिया का अगला चरण यह पता लगाने की कोशिश कर रहा था कि इसे आर्गन के साथ कैसे काम करना है।
विज्ञापन
जैसा कि हम पिछले चरण में एकत्र हुए थे, हम जानते हैं कि टाइल हर 8 सेकंड में विज्ञापन कर रही है। इसका मतलब है कि आर्गन, ज़ेनॉन या बोरॉन सहित किसी भी उपकरण का उपयोग करने के लिए इसे आसानी से स्कैन किया जाना चाहिए।
इस उदाहरण के लिए मेरा सुझाव है कि आप एक आर्गन का उपयोग करें। ऐसा इसलिए है क्योंकि ब्लूटूथ और मेश एक ही रेडियो साझा करते हैं। टाइल के लिए स्कैन करते समय, मेष से जुड़े क्सीनन अक्सर विज्ञापन पैकेटों को याद करते हैं। यह झूठी नकारात्मकता (और निराशा!) को जन्म देगा।
उसी तर्ज पर, आप सुनिश्चित करना चाहेंगे कि आपका आर्गन बिना मेश नेटवर्क से जुड़ा है। आप इसे सीएलआई का उपयोग करके हटा सकते हैं। अपने डिवाइस को अपने कंप्यूटर से कनेक्ट करें और निम्न कमांड चलाएँ:
particle mesh remove <device name/ID>
सुनिश्चित करें कि आपने <डिवाइस का नाम/आईडी> . को बदल दिया है आपके डिवाइस के नाम या आईडी के साथ।
ठीक है, अच्छी बातों पर वापस जाएँ।
ब्लूटूथ में विज्ञापन के कुछ अलग उद्देश्य हो सकते हैं। आमतौर पर हालांकि, यह युग्मन चरण की शुरुआत का प्रतीक है। इस तरह अन्य उपकरणों को पता चलता है कि विज्ञापन उपकरण उपलब्ध है।
इसके अतिरिक्त, विज्ञापन उपकरण इंगित करेगा कि उसके पास कौन सी सेवाएं हैं। हम इस ज्ञान का उपयोग मेल नहीं खाने वाले उपकरणों को फ़िल्टर करने के लिए कर सकते हैं।
उदाहरण के लिए, टाइल डिवाइस पर उपलब्ध सेवाओं का स्क्रीनशॉट यहां दिया गया है:
स्कैन करते समय हम दोबारा जांच करेंगे कि जिस डिवाइस से हम कनेक्ट कर रहे हैं उसमें 0xfeed
सर्विस UUID है। ।
इससे पहले कि हम ब्लूटूथ की गहराई में उतरें, आइए लॉगर का उपयोग करके डिबगिंग के लिए अपना ऐप सेट करें।
लॉगिंग
इस ट्यूटोरियल में हम लॉगर का उपयोग करेंगे। यह आपको particle serial monitor
. का उपयोग करके अपने ऐप से लॉग संदेश प्रदर्शित करने की अनुमति देता है ।
लॉगर के बारे में कूलर सुविधाओं में से एक संदेश पदानुक्रम का विचार है। यह आपको, डिज़ाइनर को, उन संदेशों को चुनिंदा रूप से म्यूट करने की अनुमति देता है जो आवश्यक नहीं हो सकते हैं।
उदाहरण के लिए, यदि आपके पास डिबगिंग के लिए उपयोग किए गए संदेश हैं। आप उन्हें हटा सकते हैं या उन पर टिप्पणी कर सकते हैं। या, आप LOG_LEVEL
बढ़ा सकते हैं इसलिए उन्हें प्रभावी रूप से अनदेखा कर दिया जाता है।
यहां लॉगिंग स्तर हैं जो logging.h
. में उपलब्ध हैं पार्टिकल के डिवाइस-ओएस रिपॉजिटरी में:
// 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);
जैसे-जैसे आप पार्टिकल्स डिवाइसओएस का उपयोग करते हुए अपनी यात्रा जारी रखेंगे, आपको जल्द ही एहसास होगा कि यह कितना उपयोगी हो सकता है। अब, अच्छी बातों पर चलते हैं!
इसे सेट करना
सबसे पहले, हम यह सुनिश्चित करना चाहेंगे कि हम DeviceOS के सही संस्करण का उपयोग कर रहे हैं। 1.3 के बाद के किसी भी संस्करण में ब्लूटूथ होगा। आप यहां निर्देश प्राप्त कर सकते हैं।
आगे हम टाइल के लिए स्कैनिंग शुरू करना चाहेंगे। हम इसे loop()
. में करना चाहेंगे एक निश्चित अंतराल पर कार्य करते हैं। हम एक millis()
. का उपयोग करेंगे इस मामले में टाइमर:
// Scan for devices
if( (millis() > lastSeen + TILE_RE_CHECK_MS) ){
BLE.scan(scanResultCallback, NULL);
}
सुनिश्चित करें कि आपने lastSeen
. को परिभाषित किया है फ़ाइल के शीर्ष पर इस तरह:
system_tick_t lastSeen = 0;
हम इसका उपयोग यह पता लगाने के लिए करेंगे कि पिछली बार टाइल कब "देखी गई" थी। यानी जब पिछली बार आर्गन ने टाइल से एक विज्ञापन पैकेट देखा था।
TILE_RE_CHECK_MS
के रूप में परिभाषित किया जा सकता है
#define TILE_RE_CHECK_MS 7500
इस तरह हम कम से कम हर 7.5 सेकंड में विज्ञापन पैकेट की जांच कर रहे हैं।
टाइल डिवाइस को खोजने के लिए हम BLE.scan
. का उपयोग करेंगे . जब हम इसे कॉल करेंगे, तो यह स्कैनिंग प्रक्रिया शुरू कर देगा। जैसे ही डिवाइस मिलते हैं scanResultCallback
आग लग जाएगी।
अभी के लिए, हम scanResultCallback
. को परिभाषित कर सकते हैं फ़ाइल के शीर्ष पर:
void scanResultCallback(const BleScanResult *scanResult, void *context) {
}
आपने देखा कि इसमें एक BleScanResult
. शामिल है . इसमें पता, RSSI और डिवाइस का नाम (यदि उपलब्ध हो) और उपलब्ध सेवा जानकारी शामिल होगी। यह बाद में तब काम आएगा जब हम अपने टाइल डिवाइस की तलाश में होंगे!
याद रखें, कि BLE.scan
स्कैनिंग पूरी होने तक वापस नहीं आता है। स्कैनिंग के लिए डिफ़ॉल्ट टाइमआउट 5 सेकंड है। आप BLE.setScanTimeout()
. का उपयोग करके उस मान को बदल सकते हैं . setScanTimeout
10ms वेतन वृद्धि में इकाइयाँ लेता है। तो, 500ms टाइमआउट के लिए 50 के मान की आवश्यकता होगी।
इस ऐप के मामले में, मैं 8s (8000ms) के मान का उपयोग करने की सलाह दूंगा। आप इसे इस तरह सेट कर सकते हैं:
BLE.setScanTimeout(800);
इस मामले में, उपकरण तब तक स्कैन करेगा जब तक वह टाइल को विज्ञापित करने के लिए लेता है। इस तरह इसके विज्ञापन पैकेट छूटने की संभावना कम है।
स्कैन परिणामों को संभालना
अब जबकि हमारे पास scanResultCallback
है आइए परिभाषित करें कि अंदर क्या चल रहा है।
हम पहले विज्ञापन डेटा के अंदर सेवा की जानकारी प्राप्त करना चाहते हैं। सबसे अच्छा तरीका है scanResult->advertisingData.serviceUUID
. का उपयोग करना . हम यूयूआईडी की एक सरणी में पास करेंगे जो हमारे उपयोग के लिए कॉपी की जाएगी।
BleUuid uuids[4];
int uuidsAvail = scanResult->advertisingData.serviceUUID(uuids,sizeof(uuids)/sizeof(BleUuid));
यह uuids
को पॉप्युलेट करेगा इस तरह आप उन पर पुनरावृति कर सकते हैं। uuidsAvail
उपलब्ध यूयूआईडी की मात्रा के बराबर होगा।
हमारे मामले में हम एक विशेष यूयूआईडी की तलाश कर रहे हैं। हम इसे फ़ाइल के शीर्ष पर परिभाषित करेंगे:
#define TILE_UUID 0xfeed
आम तौर पर UUIDs बहुत होते हैं लंबा। इस तरह एक छोटा यूयूआईडी का मतलब है कि इसे आरक्षित किया गया है या ब्लूटूथ विनिर्देश का हिस्सा है। किसी भी मामले में हम इसकी जांच उसी तरह करेंगे जैसे हम 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()
. का प्रिंट आउट लेने के लिए कर रहे हैं यूयूआईडी का संस्करण।
इसका परीक्षण करें!
आइए परीक्षण करें कि हमारे पास अब तक क्या है!
ऐप को अपने आर्गन में प्रोग्राम करें। टर्मिनल खोलें और 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]
. भी ? इसका मतलब है कि यह एप्लिकेशन कोड से उत्पन्न होने वाला एक ट्रेस संदेश है। सही है?
यह कोड जल्दी स्पैमी हो जाता है, खासकर यदि आप ऐसे वातावरण में हैं जहां बहुत सारे विज्ञापन ब्लूटूथ डिवाइस हैं। यदि आप टाइल चालू हैं और अंत में चल रहे हैं तो आपको एक संदेश दिखाई देगा UUID: feed
. इसका मतलब है कि आपके आर्गन को टाइल मिल गई है!
आगे हम टाइल के पते को मेमोरी में "प्रोग्राम" करने के लिए ऑनबोर्ड मोड बटन का उपयोग करेंगे। इस तरह हम उन सभी डिवाइस को फ़िल्टर कर सकते हैं जिनकी हमें परवाह नहीं है।
डिवाइस ऑन बटन पुश जोड़ें
सबसे पहले हमें यह पता लगाने की जरूरत है कि मोड बटन की निगरानी कैसे करें। प्रलेखन के अनुसार सबसे अच्छा दांव 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()
. में इनिशियलाइज़ करें
// Set LED pin
pinMode(D7,OUTPUT);
फिर हम इसे eventHandler
. के अंदर जोड़ सकते हैं
if( event == button_click ) {
if( digitalRead(D7) ) {
digitalWrite(D7,LOW);
} else {
digitalWrite(D7,HIGH);
}
}
फिर हम D7 (ऑनबोर्ड ब्लू एलईडी) को लिख सकते हैं। हम digitalRead
. का भी उपयोग कर सकते हैं एलईडी की स्थिति क्या है यह पढ़ने के लिए। यह HIGH
. के साथ जवाब देगा या LOW
स्थिति के आधार पर।
डिवाइस पर फ़र्मवेयर लोड करें और नीली एलईडी पर हमारा अच्छा नियंत्रण होगा!
अगले भाग में, हम डिवाइस को "लर्निंग" मोड में डालने के लिए मोड बटन का उपयोग करेंगे। यह हमें लक्ष्य टाइल डिवाइस के साथ एक स्पर्श सेटअप करने की अनुमति देगा।
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()
. का उपयोग करके एलईडी और "लर्निंग मोड" को बंद कर देते हैं
जब भी कोई उपकरण मिलेगा हम 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.");
}
हमें अपने आर्गन को अपनी टाइल का पता "सिखाने" में सक्षम होना चाहिए। आइए इसका परीक्षण करें!
इसका परीक्षण करें।
अब अगर हम ऐप को संकलित और चलाते हैं, तो ध्यान दें कि कैसे कोई और लॉग आउटपुट नहीं है? हमें पार्टिकल डिवाइस को टाइल का पता "सिखाना" है। तो, मोड बटन दबाएं। नीली एलईडी चालू होनी चाहिए।
एक बार आपकी टाइल मिल जाने के बाद एलईडी बंद हो जाएगी और आपको कमांड लाइन पर कुछ आउटपुट दिखाई देगा। जैसा हमने पहले देखा है वैसा ही:
0000006296 [app] TRACE: MAC: D7:E7:FE:0C:A5:C0
0000006298 [app] TRACE: RSSI: -60Bm
0000006299 [app] TRACE: UUID: feed
डिवाइस स्मृति के लिए प्रतिबद्ध है!
आप यह भी जांच सकते हैं कि रीसेट के बाद भी यह सहेजा गया है या नहीं। रीसेट दबाएं बटन और ऊपर के समान आउटपुट की जांच करें। अगर यह दिख रहा है, तो हम अभी भी अच्छे हैं!
क्लाउड अपडेट करें
अंत में checkTileStateChanged
. नामक एक फ़ंक्शन सेट करते हैं . हम इसका उपयोग नियमित अंतराल पर टाइल की स्थिति में परिवर्तन की जांच करने के लिए करेंगे।
bool checkTileStateChanged( TilePresenceType *presence ) {
}
इस फ़ंक्शन का मुख्य उद्देश्य lastSeen
. की तुलना करना है "टाइमआउट" अवधि के साथ चर। हमारे मामले में, हमारी टाइमआउट अवधि TILE_NOT_HERE_MS
. है जिसे
#define TILE_NOT_HERE_MS 30000
आपके कार्यक्रम के शीर्ष के पास। देखने के लिए दो और शर्तें भी हैं। एक जहां lastSeen
0 के बराबर है। ऐसा आमतौर पर इसलिए होता है क्योंकि स्टार्टअप के बाद भी ऐप को टाइल नहीं मिली है।
आखिरी मामला तब होगा जब डिवाइस को देखा गया हो और lastSeen
0 नहीं है। तो checkTileStateChanged
. के भीतर चलो सब कुछ एक साथ रखते हैं।
// Check to see if it's here.
if( millis() > lastSeen+TILE_NOT_HERE_MS ) {
} else if ( lastSeen == 0 ) {
} else {
}
return false;
अब हम केवल यह चाहते हैं कि यह फ़ंक्शन सही हो यदि राज्य बदल गया है . इसलिए हमें TilePresenceType
. का लाभ उठाना होगा समझौते में सूचक।
TilePresenceType
बस सभी संभावित राज्यों की एक गणना है। आप इसे अपनी फ़ाइल के शीर्ष पर भी चिपका सकते हैं। यहाँ यह है:
typedef enum {
PresenceUnknown,
Here,
NotHere
} TilePresenceType;
आपको एक वैश्विक चर की भी आवश्यकता होगी जिसे हम फ़ंक्शन में पास कर सकते हैं। इसे अपनी फ़ाइल के शीर्ष पर भी सेट करें:
// Default status
TilePresenceType present = PresenceUnknown;
अब, हम प्रत्येक चरण में तुलना कर सकते हैं। क्या यह मानदंडों को पूरा करता है? क्या राज्य पिछले वाले से अलग है? अगर ऐसा है, तो सही लौटें।
याद रखें, हम presence
set सेट करना चाहेंगे नए अद्यतन मूल्य के लिए। इसलिए प्रत्येक शर्त को उपस्थिति मान को अद्यतन करना चाहिए। उदाहरण के लिए:
*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 पेलोड भेजने के लिए कर सकते हैं। इस मामले में हम ब्लूटूथ एड्रेस, 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
. नामक एक वेरिएबल भी है . यह तारों की एक स्थिर स्थिरांक सरणी है। वे 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 subscribe --device <device_name> <event_name>
<device_name>
बदलें आपके डिवाइस के नाम या आईडी के साथ।
बदलें <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"}
वेबहुक को कॉन्फ़िगर करना
इस ट्यूटोरियल के अंतिम भाग में हम वेबहुक का उपयोग करके पुश नोटिफिकेशन सेट करेंगे। जैसा कि पहले उल्लेख किया गया है, हम आपकी पसंद के डिवाइस (डिवाइसों) पर पुश सूचना (सूचनाएं) भेजने के लिए पुशओवर और उनके आसान एपीआई का उपयोग करेंगे।
पुशओवर का उपयोग करने के लिए एक काल्पनिक रूप से आसान एपीआई है। उनका आवेदन उन स्थितियों के लिए स्विस सेना चाकू है जहां आप पुश नोटिफिकेशन भेजने के लिए किसी ऐप को कोड नहीं करना चाहते हैं।
पहली बात जो आपको ध्यान रखनी होगी वह है आपकी उपयोगकर्ता कुंजी। आप इसे पुशओवर में लॉग इन करके प्राप्त कर सकते हैं। नोट:यदि आपने पहले से खाता नहीं बनाया है तो आपको पहले एक खाता सेट करना होगा।
यह कुछ इस तरह दिखना चाहिए:
यदि आप लॉग इन हैं और यह पृष्ठ नहीं देखते हैं, तो पुशओवर लोगो . पर क्लिक करें और वह आपको वापस लाएगा।
आगे हम एक एप्लीकेशन बनाना चाहेंगे। एप्लिकेशन और प्लगइन्स पर क्लिक करें स्क्रीन के शीर्ष पर।
फिर आपको नया एप्लिकेशन बनाएं पर क्लिक करना चाहिए। यह हमें API टोकन . प्राप्त करने की अनुमति देगा कण वेबहुक सेटअप में इसकी आवश्यकता होगी।
एक नाम सेट करें जैसा आप फिट देखते हैं। यदि आप रिमाइंडर चाहते हैं तो विवरण भरें। बॉक्स पर क्लिक करें और फिर एप्लिकेशन बनाएं click क्लिक करें
आपको अगले पेज पर जाना चाहिए। API टोकन/कुंजी को कॉपी और सेव करें हमें इसकी भी कुछ ही चरणों में आवश्यकता होगी।
अब, वेबहुक को सेटअप करते हैं। https://console.particle.io पर जाएं और एक नया एकीकरण बनाएं।
हम ईवेंट का नाम . सेट करेंगे करने के लिए स्थिति ।
यूआरएल करने के लिए https://api.pushover.net/1/messages.json
साथ ही, यदि आप किसी विशिष्ट उपकरण द्वारा फ़िल्टर करना चाहते हैं, तो सुनिश्चित करें कि आपने इसे डिवाइस ड्रॉपडाउन में चुना है।
उन्नत सेटिंग . के अंतर्गत हम कुछ फ़ील्ड सेट करके समाप्त करेंगे।
निम्नलिखित फ़ील्ड बनाएं:टोकन, उपयोगकर्ता , शीर्षक , और संदेश . फिर टोकन को API टोकन . पर सेट करें हमें पहले मिल गया। उपयोगकर्ता कुंजी . के लिए भी ऐसा ही करें
शीर्षक आपके संदेश के शीर्षक के रूप में दिखाई देगा। जो कुछ भी आपके लिए समझ में आता है उसे बनाएं।
आप संदेश . सेट कर सकते हैं The Tile is currently {{{status}}}. RSSI: {{{lastRSSI}}}
. के रूप में ।
हम यहां मूंछों के टेम्प्लेट का उपयोग कर रहे हैं। वे आपको प्रकाशित पेलोड में डेटा का उपयोग करने और अपनी पसंद के अनुसार इसे पुन:स्वरूपित करने की अनुमति देते हैं। हमारे मामले में, हम उनका उपयोग "रिक्त स्थान भरने" के लिए कर रहे हैं। संदेश एक बार संसाधित होने पर कुछ इस तरह दिखाई देगा:
The Tile is currently here. RSSI: -77
एक साइड नोट के रूप में, मैं अपने गाइड में इन टेम्प्लेट के बारे में अधिक बात करूंगा। तो उसके लिए बने रहें!
इसका परीक्षण करें
एक बार आपका एकीकरण हो जाने के बाद, आप वह परीक्षण कर सकते हैं जो हमने पहले चरण में किया था। बैटरी निकालें, और "यहां नहीं" संदेश की प्रतीक्षा करें। इसे वापस रखें और "यहां" संदेश की प्रतीक्षा करें।
यहां बताया गया है कि यह iPhone पर कैसा दिखाई देगा:
जैसा कि आप देख सकते हैं, मैंने इसे एक गुच्छा का परीक्षण किया! ?
यदि आपने इसे इतना आगे कर दिया है और सब कुछ काम कर रहा है, तो बढ़िया काम। अब आपके पास अपने घर, कार्यालय या कहीं भी एक टाइल ट्रैकर है।
कोड
इस उदाहरण के लिए तैयार कोड खोज रहे हैं? मैं भी होगा! यह Github पर होस्ट किया गया है और यहां उपलब्ध है।
निष्कर्ष
जैसा कि आप कल्पना कर सकते हैं, इस लेख में उपयोग की जाने वाली तकनीकों और तकनीकों का कई तरह से उपयोग किया जा सकता है। आइए कुछ मुख्य बातों का सारांश प्रस्तुत करें:
- एक ऑफ-द-शेल्फ टाइल डिवाइस को स्कैन करने और पहचानने के लिए ब्लूटूथ सेंट्रल का उपयोग करना
- टाइल की पहचान करने वाली जानकारी को EEPROM में संग्रहीत करना। इस तरह इसे स्टार्टअप पर पुनः प्राप्त किया जा सकता है।
- हमारे परिचित
Particle.publish
का उपयोग करना क्लाउड पर अपडेट पुश करने के लिए। - राज्य परिवर्तन पर पुश सूचनाएं बनाने के लिए कण एकीकरण वेबहुक का उपयोग करना।
अब जब आपके पास यह सब काम कर रहा है, तो इसका विस्तार करें, इसे हैक करें और इसे अपना बनाएं। ओह और शेयर करना न भूलें! मुझे आपसे सुनना अच्छा लगेगा। [email protected]
इस डाक की तरह? नीचे दिए गए शेयर लिंक में से किसी एक पर क्लिक करें और इसे दुनिया के साथ साझा करें। :)पी>
यह मेरे ब्लॉग की एक क्रॉस पोस्ट है। आप मूल यहां देख सकते हैं।
अधिक सीखने में रुचि रखते हैं? मैं इस बारे में एक गाइड लिख रहा हूं कि पार्टिकल प्लेटफॉर्म का अधिकतम लाभ कैसे उठाया जाए। इसके बारे में यहाँ और जानें।