السبت، 3 سبتمبر 2022

تتبع الأصول الداخلي باستخدام Wi-Fi Triangulation

 قم ببناء حل IoT كامل لتتبع الأصول الداخلية باستخدام Blues Wireless Notecard ، ومضيف ESP32 MCU ، و Notecarrier-F ، و Datacake.






الأشياء المستخدمة في هذا المشروع

Blues Wireless Notecard (Cellular)
Blues Wireless Feather Starter Kit for ESP32
SparkFun Atmospheric Sensor Breakout - BME280
Blues Wireless Notehub.io
Datacake

قصة

في إنترنت الأشياء ، عندما يقول شخص ما "تتبع الأصول" ، فمن المحتمل أن تفكر في مراقبة حالة وموقع الحزمة أو الحاوية أو السيارة. عادةً ما يتضمن ذلك واحدًا أو أكثر من أجهزة الاستشعار البيئية لتتبع درجة الحرارة أو الرطوبة أو الضغط الجوي. قد يشتمل أيضًا على مقياس تسارع لتتبع الحركة والحركات المفاجئة.

بالطبع ، يتضمن تتبع الأصول أيضًا مراقبة الموقع في مساحة فعلية. يتم تنفيذ ذلك عادةً باستخدام نظام GNSS / GPS ، وهو أكثر الوسائل ثباتًا وموثوقية للتحقق من موقع مادي في الهواء الطلق.

ومع ذلك ، ماذا لو منعك حاوية الجهاز من الحصول على موقع GPS بسبب حاجز مادي؟ ماذا لو كانت محاولة إصلاح القمر الصناعي GPS تستهلك الكثير من الطاقة؟ أو (وهذا هو الشيء الحقيقي) ماذا لو كان هدفك هو تتبع أحد الأصول في الداخل؟

حسنًا ، لدي حل لك اليوم! على الأقل حل إثبات المفهوم 😅.

باستخدام طريقة التثليث الخاصة بأصدقائنا القدامى من علم المثلثات والهندسة ، يمكننا بناء حل لتتبع الأصول الداخلية كامل الوظائف مبني على Blues Wireless Notecard.

يمكننا أيضًا الاستفادة من جهاز استشعار شائع الاستخدام لقياس الارتفاع ، مما يمنحنا القدرة على التأكد من أرضية المبنى وتوفير تتبع الأصول "ثلاثي الأبعاد".

هل أنت جاهز للغطس؟ لنبدأ بالمتطلبات عالية المستوى لحل التتبع الداخلي هذا.

المتطلبات: بيانات الموقع بدون GPS

يجب أن يكون نظام تحديد المواقع العالمي (GPS) دائمًا هو الخيار الأول عند محاولة التأكد من الموقع الفعلي. ولكن من الجيد أن يكون لديك نسخة احتياطية في حالة فشل إصلاح القمر الصناعي لنظام تحديد المواقع العالمي (والذي يمكن أن يكون هو الحال في كثير من الأحيان داخل المبنى).

قد تعلم بالفعل أن التثليث هو عملية تحديد موقع عن طريق تكوين مخططات متداخلة على نقطة اهتمام مشتركة ، من سلسلة من النقاط المعروفة الأخرى.





في هذا المشروع ، ستسمح لنا Notecard باستخدام كل من GPS والتثليث للتأكد بدقة من موقع الجهاز.

المتطلبات: استخدم الارتفاع لتتبع الأرضية

كان تتبع أحد الأصول على خريطة ثنائية الأبعاد في العام الماضي 😊.

يمكننا استخدام البيانات من جهاز استشعار BME280 لحساب ارتفاع دقيق بشكل معقول. ما قد لا تعرفه هو أن قراءات الارتفاع هذه تستند عادةً إلى مقياس قياسي لضغط مستوى سطح البحر يبلغ 1013.25 hPa.

ألن يكون من الأكثر برودة الاستعلام بنشاط عن ضغط مستوى سطح البحر لموقع معروف قبل مطالبة المستشعر بحساب الارتفاع؟ سيوفر هذا قراءة أكثر دقة ، مما يسمح لنا بحساب أرضية المبنى الذي نحن فيه تقريبًا.

المتطلبات: مضخة بيانات من جهاز إلى سحابة

نحن بحاجة إلى وسيلة لمزامنة بيانات الموقع والارتفاع التي تم جمعها مع السحابة. ونعم ، لقد تخلت بالفعل عن المكون السري الخاص بنا: Blues Wireless Notecard.

تعد Notecard نظامًا خلويًا مدفوعًا مسبقًا على وحدة ، وهي مفيدة بشكل خاص لاتصالات إنترنت الأشياء الخلوية ذات النطاق الترددي المنخفض. يأتي محملاً مسبقًا بـ 500 ميجابايت من البيانات و 10 سنوات من الخدمة الخلوية العالمية ، بدءًا من 49 دولارًا أمريكيًا.



على الرغم من أن Notecard عبارة عن جهاز خلوي ، فلا يلزمك برمجة المودم بأوامر AT قديمة. واجهة برمجة تطبيقات Notecard هي JSON كلها ، طوال الوقت. على سبيل المثال ، لنفترض أنك تريد الاستعلام عن آخر موقع معروف على Notecard ، فأنت تستخدم card.location API:

// Request
{ "req": "card.location" }

// Response
{
"status": "GPS updated (58 sec, 41dB SNR, 9 sats),
"mode": "periodic",
"lat": 42.577600,
"lon": -70.871340,
"time": 1598554399

والأهم من ذلك ، أن الأمان والتكامل السحابي يعد أمرًا جاهزًا. يتصل Notecard "خارج الإنترنت العام" من خلال أنفاق VPN الخاصة ، باستخدام خدمة Blues Wireless السحابية Notehub.

Notehub هو أيضًا الصلصة السرية الخاصة بنا عندما يتعلق الأمر بتوفير بيانات الموقع عبر التثليث. كما سنرى لاحقًا ، عندما نوفر بيانات نقطة وصول Wi-Fi معروفة إلى Notehub ونقوم بتمكين card.triangulate API ، يمكن لـ Notehub بالفعل البحث عن بيانات الموقع الدقيقة بشكل صادم.

الشرط: طاقة منخفضة

يجب أن يكون أي حل IoT يعمل بالبطارية موفرًا للطاقة. لحسن الحظ ، فإن Notecard هي طاقة منخفضة بشكل افتراضي (لتصل إلى ~ 8uA عند الخمول) وتتضمن مقياس تسارع داخلي ، والذي يسمح لنا بحساب موقع الأصل فقط عندما يكتشف الحركة!

مع وضع كل هذه المتطلبات في الاعتبار ، فلنقم بتجميع أجهزتنا.

الأجهزة

تعد بطاقة المفكرة الخلوية جوهر الحل الذي نقدمه ، حيث توفر نظام تحديد المواقع العالمي (GPS) على متن الطائرة ومقياس تسارع لاكتشاف الحركة والاتصال الخلوي لترحيل البيانات المجمعة إلى السحابة.


نظرًا لأنني لست على استعداد للتخلي عن نظام تحديد المواقع العالمي (حتى بالنسبة للنشر الداخلي) ، سأستخدم هوائي GPS صغيرًا نشطًا جنبًا إلى جنب مع هوائي LTE للبيانات الخلوية



لجمع البيانات البيئية وحساب الارتفاع ، أقوم بتضمين جهاز استشعار BME280 الموقر من Bosch.



بالنسبة إلى متحكم مضيف ، ذهبت مع ESP32-S2 Feather. لقد اخترت MCU بشكل أساسي بسبب وحدة Wi-Fi المدمجة الخاصة بها ودعمها لـ CircuitPython. على الرغم من أننا لا نستطيع استخدام Wi-Fi للاتصال (نظرًا لأنه نظام متحرك ولن نتمكن من تسجيل الدخول إلى نقاط وصول Wi-Fi المتغيرة) ، فإننا سنستخدمها لجمع بيانات نقطة وصول Wi-Fi العامة.


إذن كيف نجمع كل القطع معًا؟ هذا هو الغرض من Blues Wireless Notecarrier-F الجديد!

Notecarriers هي لوحات حاملة تتيح لك إنشاء نماذج أولية لحلول إنترنت الأشياء التي تستخدم Notecard بسرعة. يعد Notecarrier-F خيارًا رائعًا لوحدات MCU المتوافقة مع Feather ويوفر منفذين Qwiic لإضافة الأجهزة الطرفية (مثل BME280) وموصلات JST لتوصيل بطاريات LiPo.



وهنا الإعداد النهائي للأجهزة ، كلها متصلة وجاهزة للبرمجة:


البرامج فيرموير

أنا من محبي بايثون بلا حرج ، لذا كان CircuitPython خيارًا سهلاً بالنسبة لي.

لماذا CircuitPython؟ سؤال صحيح! في رأيي المتواضع ، ساعدت CircuitPython في فتح إنترنت الأشياء لسلسلة جديدة من المطورين الذين نشأوا مع Python. مثل MicroPython "الأم" (التي تستند إليها CircuitPython) ، فإن القدرة على استخدام لغة Python المشهورة uber لبرمجة هذه "الأشياء" وربطها بالعالم قد وسع نطاق حلول إنترنت الأشياء ونطاقها.

لذلك دعونا نكتب بعض البرامج الثابتة CircuitPython!

ملاحظة: يتوفر رمز مصدر CircuitPython الكامل لهذا المشروع في مستودع Github هذا.

مكتبات وواردات بايثون

التبعيات الخارجية الوحيدة التي لدينا هي Notecard ومستشعر BME280. يحتوي كلاهما على مكتبات Python المدعومة جيدًا والتي تعمل بشكل رائع مع CircuitPython: note-python و adafruit-circpython-bme280.

تبدو المجموعة النهائية من الواردات كما يلي:

mport board
import busio
import notecard
from adafruit_bme280 import basic as adafruit_bme280
import utils
import keys
import time
from time import sleep

تهيئة الجهاز

نحن بحاجة إلى تهيئة الوصول إلى الأجهزة الطرفية لدينا. تتواصل كل من Notecard و BME280 عبر I2C ، مما يجعل خطوات init بسيطة للغاية:

# initialize the Blues Wireless Notecard (blues.io)
i2c = busio.I2C(board.SCL, board.SDA)
card = notecard.OpenI2C(i2c, 0, 0, debug=True)

# create reference to BME280
bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c)

من أجل حساب ارتفاع دقيق ، نحتاج إلى معرفة ضغط مستوى سطح البحر الحالي في موقعنا المحدد. المزيد عن هذا لاحقًا ، لكننا سنبدأ بتزويد المستشعر بمقياس قياسي لضغط مستوى سطح البحر يبلغ 1013.25 hPa.

في وقت لاحق ، عند استخدام خدمة عن بُعد لجمع بيانات الضغط ، سنحتاج إلى استخدام إحداثيات خطوط الطول / العرض. يمكننا البرمجة في بعض الإعدادات الافتراضية وتحديثها لاحقًا إذا / عندما يصبح GPS متاحًا:

bme280.sea_level_pressure = 1013.25
lat_def = 43.05769554337394
lon_def = -89.5070545945101

بعد ذلك ، نحتاج إلى ربط Notecard بمشروع قائم على السحابة في خدمة Blues Wireless السحابية Notehub. يمكّن هذا Notecard من نقل البيانات بأمان إلى موقع معروف في السحابة:

# associate Notecard with a project on Notehub.io
req = {"req": "hub.set"}
req["product"] = "your-notehub-product-uid"
req["mode"] = "periodic"
rsp = card.Transaction(req)

ثم نريد تمكين وحدة GPS على Notecard. مرة أخرى ، هذا ليس مطلوبًا تمامًا ، ولكنه بالتأكيد أفضل ممارسة لمحاولة تجميع موقع GPS على الأقل إذا كانت الأقمار الصناعية مرئية:

# enable GPS module on Notecard
req = {"req": "card.location.mode"}
req["mode"] = "periodic"
rsp = card.Transaction(req)

أخيرًا ، نقوم بتمكين تتبع الحركة على Notecard ، مما سيسمح لنا بالتأكد من موقع الجهاز فقط إذا كان قد تحرك (على عكس أخذ العينات في فاصل زمني محدد ، حتى لو كان الجهاز ثابتًا ، ويستهلك طاقة غير ضرورية).

# enable motion tracking on Notecard
req = {"req": "card.motion.mode"}
req["start"] = True
rsp = card.Transaction(req)

ملاحظة: هل تشعر بالفضول حيال طلبات Notecard API هذه؟ راجع مرجع Notecard API الكامل.

تحقق من وجود الحركة

سنحتاج إلى طريقة لاكتشاف ما إذا كان الجهاز قد تحرك قبل محاولة التأكد من موقعه. يمكننا القيام بذلك باستخدام card.motion API.

تخبرنا معلمة العد في الاستجابة عن عدد أحداث الحركة التي تم تسجيلها منذ أن تم التحقق منها مؤخرًا:

def check_motion():
""" check for Notecard movement to see if we need to update its location """

req = {"req": "card.motion"}
rsp = card.Transaction(req)

if "count" in rsp and rsp["count"] > 0:
# movement detected since last check!

using_gps = False
using_wifi = False

# attempt to ascertain the current gps location
using_gps = get_gps_location()

if using_gps is False:
# gps location timed out, switch to wi-fi triangulation
using_wifi = set_wifi_triangulation()

# send readings from the sensor to the cloud
send_sensor_data(using_gps, using_wifi)


هناك طريقتان أخريان تعتمدان على الموقع مذكورتان هنا ، get_gps_location و set_wifi_triangulation. دعونا نلقي نظرة سريعة على هذه.

احصل على موقع GPS

ما يلي هو نسخة مكثفة للغاية من كود Python تستخدم للتأكد من موقع GPS. النسخة الكاملة متاحة كجزء من مستودع جيثب للمشروع ، وهي باختصار القصة الطويلة تحتوي على منطق إضافي لتجاوز طبيعة الطاقة المنخفضة لوحدة GPS.

def get_gps_location():
""" attempt to ascertain the latest gps location """

# get the latest GPS location
req = {"req": "card.location"}
rsp = card.Transaction(req)

if "lat" in rsp and "lon" in rsp:
# got an updated gps location
lat_def = rsp["lat"]
lon_def = rsp["lon"]

مرة أخرى ، نظرًا لأن هذا نشر داخلي ، فنادراً ما نحصل على موقع GPS صالح. لذلك دعونا ننظر إلى استخدام تثليث Wi-Fi بدلاً من ذلك!


قم بإعداد Wi-Fi Triangulation

هل تعلم أن هواتفنا الذكية تجمع باستمرار البيانات حول نقاط وصول Wi-Fi المتاحة ، وتجمع هذه البيانات مع إحداثيات خطوط الطول / العرض ، وشحن البيانات إلى Apple و Google؟ مرحبًا بكم في ممارسة خصوصية أخرى مشكوك فيها بواسطة شركة Big Tech!

على الجانب المشرق ، يتيح لنا أيضًا الاستفادة من قدرة Notehub على جمع بيانات تحديد الموقع من نقاط وصول Wi-Fi القريبة.

من خلال توفير قائمة بنقاط وصول Wi-Fi إلى card.triangulate API ، يمكننا إخبار Notehub بحساب بيانات تحديد الموقع لنا (غالبًا مع نتائج دقيقة بشكل صادم).

ملاحظة: أوصي بشدة بقراءة وثائق تثليث برج الخلية / شبكة Wi-Fi. هناك إعدادات إضافية في Notehub قد تحتاج إلى تحديثها بناءً على عدد المرات التي تريد فيها استخدام التثليث.

مرة أخرى ، نظرًا لأننا نستخدم MCU المستندة إلى ESP32 ، يمكننا استخدام مكتبة wifi المدمجة CircuitPython لإنشاء قائمة بنقاط وصول Wi-Fi المرئية. تتوفر الوظيفة المساعدة ، get_wifi_access_points ، في مستودع Github أيضًا.

def set_wifi_triangulation():
""" use the card.triangulate api to set the local wifi access points """

req = {"req": "card.triangulate"}
req["mode"] = "wifi"
rsp = card.Transaction(req)

all_wifi_aps = utils.get_wifi_access_points()

if len(all_wifi_aps) > 0:
req = {"req": "card.triangulate"}
req["text"] = all_wifi_aps + "\n"
rsp = card.Transaction(req)
return True
else:
return False

احصل على ضغط مستوى سطح البحر المحدث

من أجل حساب أدق ارتفاع ممكن ، نحتاج إلى معرفة الضغط الجوي لموقعنا الحالي عند مستوى سطح البحر. الطريقة الوحيدة للقيام بذلك بشكل موثوق هي الاتصال بخدمة الطقس عن بُعد للوصول إلى هذه البيانات عند الطلب.

هذا هو المكان الذي تصبح فيه واجهة OpenWeather API المدمجة مع واجهات برمجة تطبيقات الويب من Notecard مفيدة. يوفر OpenWeather طريقة سهلة للمطورين للوصول إلى مجموعة متنوعة من البيانات المتعلقة بالطقس.

تسمح واجهات برمجة ت بيقات الويب الخاصة بـ Notecard لـ Notecard بإرسال / استقبال البيانات إلى / من واجهات برمجة تطبيقات RESTful البعيدة. الطريقة أدناه مختصرة للمساحة:

def get_sea_level_pressure(card, lat, lon):
""" get the sea level pressure from openweather api """

# call openweather api to get latest pressure reading
weatherURL = "/weather?lat=" + \
str(lat) + "&lon=" + str(lon) + "&appid=" + keys.WEATHER_API_KEY

req = {"req": "web.get"}
req["route"] = "GetWeather"
req["name"] = weatherURL
rsp = card.Transaction(req)

pressure = 0

if rsp and "body" in rsp and "main" in rsp["body"] and "pressure" in rsp["body"]["main"]:
pressure = rsp["body"]["main"]["pressure"]

return pressure

لاحظ استدعاء سلسلة GetWeather في هذه الطريقة؟ هذا هو اسم مسار Notehub الذي تم تكوينه للاستعلام عن خدمة بعيدة (OpenWeather) وإرجاع بيانات الطقس الحالية لإحداثيات خطوط الطول / العرض المحددة. يبدو هذا المسار الخاص بهذا الشكل في واجهة مستخدم Notehub:



إرسال البيانات إلى السحابة
بمجرد حصولنا على ضغط مستوى سطح البحر المحدث ، يمكننا تحديث مستشعر BME280 بهذه القيمة وأخيرًا إرسال بيانات الاستشعار البيئي إلى Notehub للمزامنة مع لوحة معلومات Datacake التي سيتم إنشاؤها:
def send_sensor_data(using_gps, using_wifi):
""" send sensor data to the cloud with the Notecard """

# first get the updated sea level pressure
sl_pressure = utils.get_sea_level_pressure(card, lat_def, lon_def)

bme280.sea_level_pressure = sl_pressure
sleep(1)

note_body = {}

# get 50 readings from the sensor and use the median values
temp_list = []
humidity_list = []
pressure_list = []
altitude_list = []

for x in range(50):
temp_list.append(bme280.temperature)
humidity_list.append(bme280.relative_humidity)
pressure_list.append(bme280.pressure)
altitude_list.append(bme280.altitude)
sleep(0.1)

med_temp = utils.get_median(temp_list)
med_humidity = utils.get_median(humidity_list)
med_pressure = utils.get_median(pressure_list)
med_altitude = utils.get_median(altitude_list)

note_body["temperature"] = med_temp
note_body["humidity"] = med_humidity
note_body["pressure"] = med_pressure
note_body["altitude"] = med_altitude
note_body["sealevelpressure"] = sl_pressure

# get the battery voltage
req = {"req": "card.voltage"}
rsp = card.Transaction(req)
note_body["voltage"] = rsp["value"]

# get the wireless bars and rssi values
req = {"req": "card.wireless"}
rsp = card.Transaction(req)
note_body["bars"] = rsp["net"]["bars"]
note_body["rssi"] = rsp["net"]["rssi"]

# deliver note to the notecard and sync immediately
req = {"req": "note.add"}
req["sync"] = True
req["file"] = "indoor_tracker.qo"
req["body"] = note_body
rsp = card.Transaction(req)
خذ ملاحظة (نعم ، التورية المقصودة) للطلب النهائي في هذه الطريقة ، note.add. "الملاحظة" هي ببساطة كائن JSON يتضمن بيانات عشوائية تريد إرسالها إلى السحابة.

في هذه الحالة ، نرسل عناصر البيانات التالية في نص ملاحظتنا:

درجة الحرارة
رطوبة
الضغط
ارتفاع
ضغط مستوى سطح البحر
الجهد (من بطارية LiPo المتصلة)
أشرطة و rssi (بيانات جودة الاتصال من المودم الخلوي)
لوحة القيادة السحابية
من خلال كتابة البرامج الثابتة ونشرها في وحدة التحكم الدقيقة ، يمكننا التحقق من Notehub للتأكد من جمع البيانات الصالحة ومزامنتها:

لكن هذه البيانات مفيدة إلى حد ما فقط كونها مرئية في Notehub. ما نحتاج إليه حقًا هو توجيه هذه البيانات إلى لوحة معلومات سحابية لجعلها سهلة الهضم (وجميلة!).

للقيام بذلك ، أنشأت لوحة تحكم كاملة الوظائف باستخدام Datacake:



ملاحظة: يوجد برنامج تعليمي كامل شامل حول إنشاء لوحة معلومات سحابية على Datacake متوفرة في موقع مطوري Blues Wireless.
دعنا نقوم بتكبير أداة الخريطة ، لأنني بذلت التضحية القصوى من خلال اختبار هذا المشروع في الداخل ... في المركز التجاري:


بعد قضاء حوالي 20 دقيقة سيرًا على الأقدام من نهاية إلى نهاية هذا التسوق الداخلي الضخم (من المسلم به أن بعض الأقسام الكبيرة التي تبدأ في الزوايا تم إغلاقها للأسف) تمكنت من جمع بيانات تثليث Wi-Fi للتأكد من مجموعة نقاط موقع دقيقة بشكل صادم:

لقد قمت الآن بعمل كبير حول استخدام بيانات الارتفاع في وقت سابق. بينما لا يمكننا تقديم تصور حقيقي "ثلاثي الأبعاد" لموقعنا على Datacake (أو بصراحة أي لوحة معلومات سحابية أعرفها حتى الآن) ، يمكننا ربط بيانات الموقع على الخريطة ببيانات الارتفاع المقدمة من مستشعر BME280. عند تحديد "ارتفاع خط الأساس" للطابق الأول (أو صفر بالنسبة إلى الأشخاص خارج الولايات المتحدة) ، يمكننا تقريبًا تتبع الأرضية التي نتواجد عليها أيضًا استنادًا إلى الارتفاع النسبي المقاس:


ملخص
دعني أكون واضحًا تمامًا: يجب أن تحاول دائمًا على الأقل استخدام GPS عند التحقق من موقع الجهاز. سيكون الخيار الأكثر دقة ، وعند استخدام المجموعة الصحيحة من الأجهزة والبرامج الثابتة ، يستخدم الحد الأدنى من الطاقة في جهاز يعمل بالبطارية.

ومع ذلك ، إذا لزم الأمر ، فمن الرائع أن يكون لديك خيار مثل Blues Wireless Notecard مع Notehub وقدرات التثليث الخاصة به.

فضولي لمعرفة المزيد؟ احصل على مجموعة المبتدئين Blues Wireless ESP32 اليوم!