مکان Wi-Fi: محدوده با RTT

می توانید از عملکرد مکان Wi-Fi ارائه شده توسط Wi-Fi RTT (Round-Trip-Time) API برای اندازه گیری فاصله تا نقاط دسترسی Wi-Fi با قابلیت RTT نزدیک و دستگاه های Wi-Fi Aware همتا استفاده کنید.

اگر فاصله سه یا چند نقطه دسترسی را اندازه‌گیری کنید، می‌توانید از یک الگوریتم چندلایه‌ای برای تخمین موقعیت دستگاهی که به بهترین وجه با این اندازه‌ها منطبق است، استفاده کنید. نتیجه معمولاً در فاصله 1-2 متری دقیق است.

با این دقت، می‌توانید سرویس‌های مبتنی بر مکان دقیق، مانند ناوبری داخلی، کنترل صوتی مبهم (به عنوان مثال، «این چراغ را روشن کنید»)، و اطلاعات مبتنی بر مکان (به‌عنوان مثال، «آیا پیشنهادهای ویژه‌ای برای این محصول؟").

دستگاه درخواست کننده برای اندازه گیری فاصله با Wi-Fi RTT نیازی به اتصال به نقاط دسترسی ندارد. برای حفظ حریم خصوصی، فقط دستگاه درخواست کننده می تواند فاصله تا نقطه دسترسی را تعیین کند. نقاط دسترسی این اطلاعات را ندارند. عملیات RTT Wi-Fi برای برنامه های پیش زمینه نامحدود است اما برای برنامه های پس زمینه محدود می شود.

Wi-Fi RTT و قابلیت های Fine-Time-Measurement (FTM) مربوطه توسط استاندارد IEEE 802.11-2016 مشخص شده است. Wi-Fi RTT به اندازه‌گیری زمان دقیق ارائه شده توسط FTM نیاز دارد زیرا فاصله بین دو دستگاه را با اندازه‌گیری زمانی که یک بسته برای رفت و برگشت بین دستگاه‌ها طول می‌کشد و ضرب آن زمان در سرعت نور محاسبه می‌کند.

اندروید 15 (سطح API 35) پشتیبانی از محدوده غیر ماشه ای (NTB) IEEE 802.11az را معرفی کرد.

تفاوت های پیاده سازی بر اساس نسخه اندروید

Wi-Fi RTT در اندروید 9 (سطح API 28) معرفی شد. هنگام استفاده از این پروتکل برای تعیین موقعیت دستگاه با استفاده از چندلایه بودن با دستگاه های دارای Android 9، باید به داده های مکان های نقطه دسترسی (AP) از پیش تعیین شده در برنامه خود دسترسی داشته باشید. این شما هستید که تصمیم می گیرید چگونه این داده ها را ذخیره و بازیابی کنید.

در دستگاه‌های دارای Android 10 (سطح API 29) و بالاتر، داده‌های مکان AP را می‌توان به‌عنوان اشیاء ResponderLocation نشان داد که شامل طول، طول و عرض جغرافیایی و ارتفاع می‌شود. برای APهای Wi-Fi RTT که اطلاعات پیکربندی موقعیت مکانی/گزارش مدنی موقعیت مکانی (داده‌های LCI/LCR) را پشتیبانی می‌کنند، پروتکل یک شی ResponderLocation در طول فرآیند محدوده برمی‌گرداند.

این ویژگی به برنامه‌ها اجازه می‌دهد به جای اینکه نیاز به ذخیره این اطلاعات از قبل داشته باشند، از APها درخواست کنند تا موقعیت خود را مستقیماً از آنها بپرسند. بنابراین، برنامه شما می‌تواند APها را پیدا کند و موقعیت آنها را تعیین کند، حتی اگر APها قبلاً شناخته شده نبودند، مانند زمانی که کاربر وارد یک ساختمان جدید می‌شود.

پشتیبانی از محدوده IEEE 802.11az NTB در دستگاه‌های دارای Android 15 (سطح API 35) و بالاتر در دسترس است. این بدان معناست که اگر دستگاه از حالت آغازگر IEEE 802.11az NTB (که توسط WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR نشان داده شده است) پشتیبانی می کند، برنامه شما می تواند هر دو IEEE 802.11mc و IEEE 802.11az را با یک درخواست AP با قابلیت پیدا کند. RangingResult API گسترش یافته است تا اطلاعاتی درباره حداقل و حداکثر مقداری که می‌تواند برای فاصله بین اندازه‌گیری‌های محدوده استفاده شود، ارائه می‌کند و فاصله دقیق را در کنترل برنامه شما باقی می‌گذارد.

الزامات

  • سخت افزار دستگاهی که درخواست محدوده را ارائه می دهد باید استاندارد 802.11-2016 FTM یا استاندارد 802.11az (محدوده غیر محرک) را اجرا کند.
  • دستگاهی که درخواست محدوده را ارائه می‌کند باید دارای Android 9 (سطح API 28) یا بالاتر باشد. IEEE 802.11az بدون ماشه در دستگاه‌های دارای Android 15 (سطح API 35) و بالاتر فعال است.
  • دستگاهی که درخواست محدوده را ارائه می‌کند باید خدمات مکان را فعال و اسکن Wi-Fi را روشن کند (در تنظیمات > مکان ).
  • اگر برنامه ای که درخواست محدوده را ارائه می کند Android 13 (سطح API 33) یا بالاتر را هدف قرار می دهد، باید مجوز NEARBY_WIFI_DEVICES را داشته باشد. اگر چنین برنامه‌ای نسخه قبلی Android را هدف قرار دهد، باید مجوز ACCESS_FINE_LOCATION را داشته باشد.
  • وقتی برنامه قابل مشاهده است یا در یک سرویس پیش زمینه است، برنامه باید محدوده نقاط دسترسی را جستجو کند. برنامه نمی تواند به اطلاعات مکان از پس زمینه دسترسی پیدا کند .
  • نقطه دسترسی باید استاندارد IEEE 802.11-2016 FTM یا استاندارد IEEE 802.11az (محدوده غیر محرک) را اجرا کند.

راه اندازی

برای تنظیم برنامه خود برای استفاده از Wi-Fi RTT، مراحل زیر را انجام دهید.

1. درخواست مجوز

مجوزهای زیر را در مانیفست برنامه خود درخواست کنید:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!-- If your app targets Android 13 (API level 33)
     or higher, you must declare the NEARBY_WIFI_DEVICES permission. -->
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES"
                 <!-- If your app derives location information from Wi-Fi APIs,
                      don't include the "usesPermissionFlags" attribute. -->
                 android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
                 <!-- If any feature in your app relies on precise location
                      information, don't include the "maxSdkVersion"
                      attribute. -->
                 android:maxSdkVersion="32" />

مجوزهای NEARBY_WIFI_DEVICES و ACCESS_FINE_LOCATION مجوزهای خطرناکی هستند، بنابراین باید هر بار که کاربر می‌خواهد عملیات اسکن RTT را انجام دهد، آنها را در زمان اجرا درخواست کنید. اگر مجوز قبلاً اعطا نشده باشد، برنامه شما باید مجوز کاربر را درخواست کند. برای اطلاعات بیشتر درباره مجوزهای زمان اجرا، به درخواست مجوزهای برنامه مراجعه کنید.

2. بررسی کنید که آیا دستگاه از Wi-Fi RTT پشتیبانی می کند یا خیر

برای بررسی اینکه آیا دستگاه از Wi-Fi RTT پشتیبانی می‌کند، از PackageManager API استفاده کنید:

کاتلین

context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)

جاوا

context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT);

3. بررسی کنید که آیا Wi-Fi RTT در دسترس است یا خیر

Wi-Fi RTT ممکن است در دستگاه وجود داشته باشد، اما ممکن است در دسترس نباشد زیرا کاربر Wi-Fi را غیرفعال کرده است. بسته به قابلیت‌های سخت‌افزار و میان‌افزار، ممکن است برخی از دستگاه‌ها در صورت استفاده از SoftAP یا تترینگ از Wi-Fi RTT پشتیبانی نکنند. برای بررسی اینکه آیا Wi-Fi RTT در دسترس است یا خیر، با isAvailable() تماس بگیرید.

در دسترس بودن Wi-Fi RTT می تواند در هر زمان تغییر کند. برنامه شما باید یک BroadcastReceiver برای دریافت ACTION_WIFI_RTT_STATE_CHANGED ثبت کند که در صورت تغییر در دسترس بودن ارسال می شود. وقتی برنامه شما هدف پخش را دریافت می کند، برنامه باید وضعیت فعلی در دسترس بودن را بررسی کند و رفتار خود را بر اساس آن تنظیم کند.

به عنوان مثال:

کاتلین

val filter = IntentFilter(WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED)
val myReceiver = object: BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        if (wifiRttManager.isAvailable) {
            …
        } else {
            …
        }
    }
}
context.registerReceiver(myReceiver, filter)

جاوا

IntentFilter filter =
    new IntentFilter(WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED);
BroadcastReceiver myReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (wifiRttManager.isAvailable()) {
            …
        } else {
            …
        }
    }
};
context.registerReceiver(myReceiver, filter);

برای اطلاعات بیشتر، به پخش‌ها مراجعه کنید.

یک درخواست دامنه دار ایجاد کنید

یک درخواست محدوده ( RangingRequest ) با تعیین لیستی از AP ​​یا همتایان Wi-Fi Aware که محدوده درخواست شده برای آنها ایجاد می شود. چندین نقطه دسترسی یا همتایان Wi-Fi Aware را می توان در یک درخواست محدوده مشخص کرد. فاصله تا همه دستگاه ها اندازه گیری و برگردانده می شود.

به عنوان مثال، یک درخواست می تواند از متد addAccessPoint() برای تعیین نقطه دسترسی برای اندازه گیری فاصله استفاده کند:

کاتلین

val req: RangingRequest = RangingRequest.Builder().run {
    addAccessPoint(ap1ScanResult)
    addAccessPoint(ap2ScanResult)
    build()
}

جاوا

RangingRequest.Builder builder = new RangingRequest.Builder();
builder.addAccessPoint(ap1ScanResult);
builder.addAccessPoint(ap2ScanResult);

RangingRequest req = builder.build();

یک نقطه دسترسی با شیء ScanResult آن شناسایی می‌شود که با فراخوانی WifiManager.getScanResults() قابل دریافت است. می توانید از addAccessPoints(List<ScanResult>) برای اضافه کردن چندین نقطه دسترسی در یک دسته استفاده کنید.

اشیاء ScanResult می‌توانند شامل هر دو IEEE 802.11mc ( is80211mcResponder() ) و IEEE 802.11az با محدوده غیر محرک ( is80211azNtbResponder() ) APهای پشتیبانی شده باشند. دستگاه‌هایی که از محدوده IEEE 802.11az NTB پشتیبانی می‌کنند، بسته به قابلیت AP، محدوده 802.11mc یا 802.11az را انجام می‌دهند، زمانی که AP از هر دو پشتیبانی می‌کند، پیش‌فرض 802.11az می‌شود. دستگاه هایی که از IEEE 802.11az پشتیبانی نمی کنند، همه محدوده ها را با استفاده از پروتکل IEEE 802.11mc انجام می دهند.

به طور مشابه، یک درخواست محدوده می‌تواند یک همتای Wi-Fi Aware را با استفاده از آدرس MAC یا PeerHandle خود، با استفاده از روش‌های addWifiAwarePeer(MacAddress peer) و addWifiAwarePeer(PeerHandle peer) اضافه کند. برای اطلاعات بیشتر درباره پیدا کردن همتایان Wi-Fi Aware، به مستندات Wi-Fi Aware مراجعه کنید.

محدوده درخواست

یک برنامه با استفاده از متد WifiRttManager.startRanging() درخواست محدوده ای را صادر می کند و موارد زیر را ارائه می دهد: RangingRequest برای مشخص کردن عملیات، Executor برای مشخص کردن زمینه پاسخگویی، و RangingResultCallback برای دریافت نتایج.

به عنوان مثال:

کاتلین

val mgr = context.getSystemService(Context.WIFI_RTT_RANGING_SERVICE) as WifiRttManager
val request: RangingRequest = myRequest
mgr.startRanging(request, executor, object : RangingResultCallback() {

    override fun onRangingResults(results: List<RangingResult>) { … }

    override fun onRangingFailure(code: Int) { … }
})

جاوا

WifiRttManager mgr =
      (WifiRttManager) Context.getSystemService(Context.WIFI_RTT_RANGING_SERVICE);

RangingRequest request ...;
mgr.startRanging(request, executor, new RangingResultCallback() {

  @Override
  public void onRangingFailure(int code) { … }

  @Override
  public void onRangingResults(List<RangingResult> results) { … }
});

عملیات محدوده به صورت ناهمزمان انجام می شود و نتایج دامنه در یکی از فراخوانی های RangingResultCallback برگردانده می شود:

  • اگر کل عملیات محدوده ناموفق باشد، پاسخ به تماس onRangingFailure با کد وضعیتی که در RangingResultCallback توضیح داده شده است، راه اندازی می شود. اگر سرویس نتواند یک عملیات محدوده را در آن زمان اجرا کند، چنین شکستی ممکن است اتفاق بیفتد - برای مثال، به دلیل غیرفعال بودن Wi-Fi، به دلیل اینکه برنامه عملیات محدوده زیادی را درخواست کرده است و درنگ است، یا به دلیل یک مشکل مجوز.
  • هنگامی که عملیات محدوده به پایان رسید، پاسخ به تماس onRangingResults با فهرستی از نتایج که با فهرست درخواست‌ها مطابقت دارد راه‌اندازی می‌شود—یک نتیجه برای هر درخواست. ترتیب نتایج لزوماً با ترتیب درخواست ها مطابقت ندارد. توجه داشته باشید که عملیات محدوده ممکن است کامل شود اما هر نتیجه همچنان ممکن است نشان دهنده شکست آن اندازه گیری خاص باشد.

نتایج دامنه ای را تفسیر کنید

هر یک از نتایجی که با فراخوانی onRangingResults برگردانده می شود توسط یک شی RangingResult مشخص می شود. در مورد هر درخواست، موارد زیر را انجام دهید.

1. درخواست را شناسایی کنید

درخواست را بر اساس اطلاعات ارائه شده هنگام ایجاد RangingRequest شناسایی کنید: اغلب یک آدرس MAC ارائه شده در ScanResult که یک نقطه دسترسی را شناسایی می کند. آدرس MAC را می توان با استفاده از متد getMacAddress() از نتیجه محدوده بدست آورد.

فهرست نتایج محدوده ممکن است به ترتیب متفاوت با همتاها (نقاط دسترسی) مشخص شده در درخواست محدوده باشد، بنابراین باید از آدرس MAC برای شناسایی همتا استفاده کنید نه ترتیب نتایج.

2. تعیین کنید که آیا هر اندازه گیری موفقیت آمیز بوده است یا خیر

برای تعیین موفقیت آمیز بودن اندازه گیری، از متد getStatus() استفاده کنید. هر مقداری غیر از STATUS_SUCCESS نشان دهنده خرابی است. خطا به این معنی است که تمام فیلدهای دیگر این نتیجه (به جز شناسایی درخواست بالا) نامعتبر هستند و متد get* مربوطه با یک استثناء IllegalStateException ناموفق خواهد بود.

3. برای هر اندازه گیری موفقیت آمیز نتیجه بگیرید

برای هر اندازه گیری موفق ( RangingResult )، می توانید مقادیر نتیجه را با روش های get مربوطه بازیابی کنید:

  • فاصله، بر حسب میلی متر و انحراف استاندارد اندازه گیری:

    getDistanceMm()

    getDistanceStdDevMm()

  • RSSI بسته های مورد استفاده برای اندازه گیری:

    getRssi()

  • زمان بر حسب میلی ثانیه که در آن اندازه گیری انجام شد (نشان دهنده زمان از زمان راه اندازی):

    getRangingTimestampMillis()

  • تعداد اندازه‌گیری‌هایی که انجام شد و تعداد اندازه‌گیری‌هایی که موفقیت‌آمیز شدند (و اندازه‌گیری‌های فاصله بر آن‌ها استوار است):

    getNumAttemptedMeasurements()

    getNumSuccessfulMeasurements()

  • حداقل و حداکثر زمانی که یک دستگاه مشتری باید بین اندازه گیری های NTB 11az صبر کند:

    getMinTimeBetweenNtbMeasurementsMicros() و getMaxTimeBetweenNtbMeasurementsMicros() حداقل و حداکثر زمان را برمی گرداند. اگر اندازه گیری محدوده بعدی قبل از سپری شدن حداقل زمان درخواست شود، API نتیجه محدوده ذخیره شده را برمی گرداند. اگر اندازه‌گیری محدوده بعدی پس از سپری شدن حداکثر زمان درخواست شود، API جلسه محدوده غیر محرک را خاتمه می‌دهد و یک جلسه محدوده جدید با ایستگاه پاسخ‌دهنده مذاکره می‌کند. شما باید از درخواست یک جلسه محدوده جدید خودداری کنید، زیرا این کار سربار را به زمان اندازه گیری محدوده اضافه می کند. برای بهره‌مندی کامل از راندمان محدوده غیر ماشه‌ای 802.11az، درخواست محدوده بعدی را بین حداقل و حداکثر زمان اندازه‌گیری مشخص‌شده در اندازه‌گیری قبلی RangingResult فعال کنید.

  • تکرارهای Long Training Field (LTF) که ایستگاه های پاسخ دهنده و آغازگر در مقدمه نتیجه IEEE 802.11az NTB استفاده کردند:

    get80211azResponderTxLtfRepetitionsCount()

    get80211azInitiatorTxLtfRepetitionsCount()

  • تعداد انتقال و دریافت جریان های زمانی مکانی (STS) که ایستگاه آغازگر برای نتیجه IEEE 802.11az NTB استفاده کرد:

    get80211azNumberOfTxSpatialStreams()

    get80211azNumberOfRxSpatialStreams()

دستگاه های اندرویدی که از WiFi-RTT پشتیبانی می کنند

در جداول زیر برخی از تلفن‌ها ، نقاط دسترسی و دستگاه‌های خرده‌فروشی، انبارداری و توزیع که از WiFi-RTT پشتیبانی می‌کنند، فهرست شده‌اند. اینها به دور از جامعیت هستند. ما شما را تشویق می کنیم که با ما تماس بگیرید تا محصولات با قابلیت RTT خود را در اینجا لیست کنید.

نقاط دسترسی

سازنده و مدل تاریخ پشتیبانی
Nest Wifi Pro (Wi-Fi 6E) پشتیبانی می شود
Compulab WILD AP پشتیبانی می شود
گوگل وای فای پشتیبانی می شود
روتر Wi-Fi Google Nest پشتیبانی می شود
Google Nest Wi-Fi Point پشتیبانی می شود
آروبا AP-635 پشتیبانی می شود
سیسکو 9130 پشتیبانی می شود
سیسکو 9136 پشتیبانی می شود
سیسکو 9166 پشتیبانی می شود
سیسکو 9164 پشتیبانی می شود
آروبا AP-505 پشتیبانی می شود
آروبا AP-515 پشتیبانی می شود
آروبا AP-575 پشتیبانی می شود
آروبا AP-518 پشتیبانی می شود
آروبا AP-505H پشتیبانی می شود
آروبا AP-565 پشتیبانی می شود
آروبا AP-535 پشتیبانی می شود

تلفن ها

سازنده و مدل نسخه اندروید
پیکسل 6 9.0+
پیکسل 6 پرو 9.0+
پیکسل 5 9.0+
پیکسل 5a 9.0+
Pixel 5a 5G 9.0+
شیائومی می 10 پرو 9.0+
شیائومی می 10 9.0+
شیائومی ردمی می 9 تی پرو 9.0+
شیائومی می 9 تی 9.0+
شیائومی می 9 9.0+
شیائومی می نوت 10 9.0+
شیائومی می نوت 10 لایت 9.0+
شیائومی ردمی نوت 9 اس 9.0+
شیائومی ردمی نوت 9 پرو 9.0+
شیائومی ردمی نوت 8 تی 9.0+
شیائومی ردمی نوت 8 9.0+
شیائومی ردمی K30 پرو 9.0+
شیائومی ردمی K20 پرو 9.0+
شیائومی ردمی K20 9.0+
شیائومی ردمی نوت 5 پرو 9.0+
Xiaomi Mi CC9 Pro 9.0+
LG G8X ThinQ 9.0+
LG V50S ThinQ 9.0+
LG V60 ThinQ 9.0+
ال جی وی 30 9.0+
Samsung Galaxy Note 10+ 5G 9.0+
Samsung Galaxy S20+ 5G 9.0+
Samsung Galaxy S20+ 9.0+
Samsung Galaxy S20 5G 9.0+
Samsung Galaxy S20 Ultra 5G 9.0+
سامسونگ گلکسی اس 20 9.0+
سامسونگ گلکسی نوت 10 پلاس 9.0+
سامسونگ گلکسی نوت 10 5G 9.0+
سامسونگ گلکسی نوت 10 9.0+
سامسونگ A9 پرو 9.0+
Google Pixel 4 XL 9.0+
گوگل پیکسل 4 9.0+
گوگل پیکسل 4a 9.0+
گوگل پیکسل 3 ایکس ال 9.0+
گوگل پیکسل 3 9.0+
Google Pixel 3a XL 9.0+
گوگل پیکسل 3a 9.0+
Google Pixel 2 XL 9.0+
گوگل پیکسل 2 9.0+
گوگل پیکسل 1 ایکس ال 9.0+
گوگل پیکسل 1 9.0+
پوکو ایکس 2 9.0+
شارپ Aquos R3 SH-04L 9.0+

دستگاه های خرده فروشی، انبارداری و مرکز توزیع

سازنده و مدل نسخه اندروید
Zebra PS20 10.0+
زبرا TC52/TC52HC 10.0+
زبرا TC57 10.0+
زبرا TC72 10.0+
زبرا TC77 10.0+
زبرا MC93 10.0+
زبرا TC8300 10.0+
Zebra VC8300 10.0+
زبرا EC30 10.0+
زبرا ET51 10.0+
زبرا ET56 10.0+
زبرا L10 10.0+
زبرا CC600/CC6000 10.0+
Zebra MC3300x 10.0+
زبرا MC330x 10.0+
زبرا TC52x 10.0+
زبرا TC57x 10.0+
Zebra EC50 (LAN و HC) 10.0+
Zebra EC55 (WAN) 10.0+
زبرا WT6300 10.0+
Skorpio X5 10.0+