محدوده بین دستگاه ها

اندروید ۱۶ ماژول مسافت‌یابی را معرفی می‌کند که یک رابط کاربری یکپارچه و استاندارد برای مسافت‌یابی دقیق بین دستگاه‌ها فراهم می‌کند. می‌توانید از این سطح API برای اندازه‌گیری فاصله و موقعیت دستگاه‌های همتا بدون نیاز به مدیریت جداگانه هر فناوری مسافت‌یابی استفاده کنید.

ماژول مسافت‌یابی از فناوری‌های زیر پشتیبانی می‌کند:

قابلیت‌ها و دسترسی‌های برد

کلاس RangingManager اطلاعاتی در مورد فناوری‌های مسافت‌یابی پشتیبانی‌شده توسط دستگاه محلی و همچنین در دسترس بودن و قابلیت‌های هر فناوری در اختیار برنامه‌ها قرار می‌دهد. برنامه‌ها می‌توانند برای دریافت به‌روزرسانی‌ها در مورد هرگونه تغییر در دسترس بودن یا قابلیت‌های هر فناوری پشتیبانی‌شده، در یک Callback ثبت‌نام کنند.

نقش‌های دستگاه

دستگاهی که در یک جلسه‌ی تعیین محدوده شرکت می‌کند، باید یا آغازگر (initiator) باشد یا پاسخ‌دهنده (responder) . دستگاه آغازگر، جلسه‌ی تعیین محدوده را با یک یا چند دستگاه پاسخ‌دهنده آغاز می‌کند. یک دستگاه پاسخ‌دهنده در هر زمان فقط به درخواست‌های تعیین محدوده از یک آغازگر پاسخ می‌دهد. می‌توانید نقش یک دستگاه مشخص را در یک جلسه‌ی تعیین محدوده با کلاس RangingPreference مشخص کنید.

انواع جلسات

هنگام شروع یک جلسه مسافت‌یابی بین دستگاه‌ها، اغلب لازم است یک انتقال داده خارج از باند (OOB) برای تبادل پارامترها برای جلسه برقرار شود.

ماژول تعیین محدوده می‌تواند مذاکرات OOB را برای شما انجام دهد، اما از پیاده‌سازی‌های OOB سفارشی نیز پشتیبانی می‌کند.

شکل ۱. جریان OOB برای انواع جلسات

پیاده‌سازی پیش‌فرض OOB

در این نوع جلسه ( RANGING_SESSION_OOB )، ماژول مسافت‌یابی، مذاکرات OOB را برای شروع یک جلسه مسافت‌یابی مدیریت می‌کند. این ماژول پارامترهای مناسب را بر اساس تنظیمات مسافت‌یابی ارائه شده توسط برنامه انتخاب می‌کند و از فناوری‌های مناسب بر اساس آنچه هر دو دستگاه پشتیبانی می‌کنند، استفاده می‌کند. این نوع جلسه از OOB specification استاندارد استفاده می‌کند.

ماژول تعیین محدوده فقط قالب و توالی داده‌های OOB را که برای تعامل با یک دستگاه نظیر استفاده می‌شود، تعریف می‌کند. این ماژول کشف دستگاه نظیر یا برقراری اتصال را مدیریت نمی‌کند.

پیاده‌سازی سفارشی OOB

در این نوع جلسه ( RANGING_SESSION_RAW )، برنامه جریان OOB ماژول مسافت‌یابی را دور می‌زند و مذاکره OOB و پارامترهای خود را مدیریت می‌کند. این بدان معناست که برنامه باید تعیین کند که دستگاه همتا از کدام فناوری‌ها پشتیبانی می‌کند، پارامترهای مسافت‌یابی را مذاکره کند و جلسه مسافت‌یابی را آغاز کند.

تنظیمات برگزیده‌ی محدوده

از یک شیء RangingPreference برای مشخص کردن پارامترهای انتخاب شده برای یک جلسه تعیین محدوده استفاده کنید. این شامل موارد زیر است:

  • نقش دستگاه. این نشان می‌دهد که آیا دستگاه آغازگر خواهد بود یا پاسخ‌دهنده.
  • پیکربندی محدوده‌بندی. یک شیء RangingConfig نوع جلسه محدوده‌بندی و سایر پارامترهای مورد نیاز برای شروع یک جلسه محدوده‌بندی را مشخص می‌کند.
  • پیکربندی جلسه. یک شیء SessionConfig پارامترهایی را که باید در جلسه مسافت‌یابی اعمال شوند، مانند محدودیت اندازه‌گیری، ادغام حسگرها، پیکربندی حصار جغرافیایی و موارد دیگر، مشخص می‌کند.

اجازه محدوده‌بندی

ماژول مسافت‌یابی برای دسترسی به تمام فناوری‌های مسافت‌یابی فعلی و آینده به یک مجوز یکپارچه جدید ( android.permission.RANGING ) نیاز دارد. این مجوز در لیست NEARBY_DEVICES_PERMISSIONS قرار دارد.

<uses-permission android:name="android.permission.RANGING" />

محدودیت‌ها و قیود

ماژول مسافت‌یابی ممکن است به دلایل مختلفی، از جمله موارد زیر، مسافت‌یابی را محدود کند:

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

ماژول مسافت‌یابی همچنین محدودیت‌های شناخته‌شده‌ی زیر را دارد:

  • ماژول مسافت‌یابی فقط از تحویل داده‌های مسافت‌یابی به دستگاه‌های همتا برای پهنای باند فوق وسیع پشتیبانی می‌کند. برای سایر فناوری‌ها، ماژول مسافت‌یابی فقط داده‌های مسافت‌یابی را به دستگاه آغازگر تحویل می‌دهد.
  • ماژول مسافت‌یابی فقط از افزودن پویای دستگاه‌ها در حالت مسافت‌یابی خام و فقط برای پهنای باند فوق وسیع پشتیبانی می‌کند.
  • ماژول Rangeing از نشست‌های یک به چند با پهنای باند فوق العاده بالا برای پیاده‌سازی‌های پیش‌فرض OOB پشتیبانی نمی‌کند. اگر چندین شناسه دستگاه را وارد کنید، ماژول برای هر دستگاه همتا که از پهنای باند فوق العاده بالا پشتیبانی می‌کند، یک نشست یک به یک ایجاد می‌کند.

یک جلسه رنگ‌آمیزی برگزار کنید

برای انجام یک جلسه تعیین محدوده با استفاده از ماژول تعیین محدوده، مراحل زیر را دنبال کنید:

  1. تأیید کنید که همه دستگاه‌ها با اندروید ۱۶ یا بالاتر کار می‌کنند.
  2. درخواست مجوز android.permission.RANGING در مانیفست برنامه.
  3. قابلیت‌ها و در دسترس بودن فناوری‌های مسافت‌یابی را ارزیابی کنید.
  4. یک دستگاه همتا برای عملیات مسافت‌یابی کشف کنید.
  5. با استفاده از هر یک از انواع جلسه شرح داده شده در تعیین محدوده انواع جلسه ، اتصالی را برای تبادل خارج از باند برقرار کنید.
  6. شروع به اندازه‌گیری مسافت کنید و به طور مداوم داده‌های اندازه‌گیری مسافت را جمع‌آوری کنید.
  7. جلسه تعیین محدوده را خاتمه دهید.

نمونه کد زیر این مراحل را برای هر دو نقش آغازگر و پاسخ‌دهنده نشان می‌دهد.

کاتلین

class RangingApp {

    // Starts a ranging session on the initiator side.
    fun startRangingInitiator(
        context: Context,
        deviceHandle: DeviceHandle,
        executor: Executor,
        callback: RangingSessionCallback
    ) {

        // Get the RangingManager which is the entry point for ranging module.
        val manager = context.getSystemService(RangingManager::class.java)

        // Create a new RangingSession using the provided executor and callback.
        val session = manager.createRangingSession(executor, callback)

        // Create an OobInitiatorRangingConfig, which specifies the ranging parameters for
        // the initiator role.
        val config = OobInitiatorRangingConfig.Builder()
            .setFastestRangingInterval(Duration.ofMillis(100))
            .setSlowestRangingInterval(Duration.ofMillis(5000))
            .setRangingMode(RANGING_MODE_AUTO)
            .setSecurityLevel(SECURITY_LEVEL_BASIC)
            .addDeviceHandle(deviceHandle)
            .build()

        // Create a RangingPreference, which specifies the role (initiator) and
        // configuration for the ranging session.
        val preference =
            RangingPreference.Builder(DEVICE_ROLE_INITIATOR, config).build()

        // Start ranging session.
        session.start(preference)

        // If successful, the ranging data will be sent through callback#onResults

        // Stop ranging session
        session.stop()
    }

    // Starts a ranging session on the responder side.
    fun startRangingResponder(
        context: Context,
        deviceHandle: DeviceHandle,
        executor: Executor,
        callback: RangingSessionCallback
    ) {

        // Get the RangingManager which is the entry point for ranging module.
        val manager = context.getSystemService(RangingManager::class.java)

        // Create a new RangingSession using the provided executor and callback.
        val session = manager.createRangingSession(executor, callback)

        // Create an OobResponderRangingConfig, which specifies the ranging parameters for
        // the responder role.
        val config = OobResponderRangingConfig.Builder(deviceHandle).build()

        // Create a RangingPreference, which specifies the role (responder) and
        // configuration for the ranging session.
        val preference =
            RangingPreference.Builder(DEVICE_ROLE_RESPONDER, config).build()

        // Start the ranging session.
        session.start(preference)

        // Stop the ranging session
        session.stop()
    }
}

جاوا

public class RangingApp {

    // Starts a ranging session on the initiator side.
    void startRangingInitiator(Context context, DeviceHandle deviceHandle, Executor executor, RangingSessionCallback callback) {

        // Get the RangingManager which is the entry point for ranging module.
        RangingManager manager = context.getSystemService(RangingManager.class);

        // Create a new RangingSession using the provided executor and callback.
        RangingSession session = manager.createRangingSession(executor, callback);

        // Create an OobInitiatorRangingConfig, which specifies the ranging parameters for
        // the initiator role.
        OobInitiatorRangingConfig config = new OobInitiatorRangingConfig.Builder()
                .setFastestRangingInterval(Duration.ofMillis(100))
                .setSlowestRangingInterval(Duration.ofMillis(5000))
                .setRangingMode(RANGING_MODE_AUTO)
                .setSecurityLevel(SECURITY_LEVEL_BASIC)
                .addDeviceHandle(deviceHandle)
                .build();

        // Create a RangingPreference, which specifies the role (initiator) and
        // configuration for the ranging session.
        RangingPreference preference =
                new RangingPreference.Builder(DEVICE_ROLE_INITIATOR, config).build();

        // Start ranging session.
        session.start(preference);

        // If successful, the ranging data will be sent through callback#onResults

        // Stop ranging session
        session.stop();

    }

    // Starts a ranging session on the responder side.
    void startRangingResponder(Context context,  DeviceHandle deviceHandle, Executor executor, RangingSessionCallback callback) {

        // Get the RangingManager which is the entry point for ranging module.
        RangingManager manager = context.getSystemService(RangingManager.class);

        // Create a new RangingSession using the provided executor and callback.
        RangingSession session = manager.createRangingSession(executor, callback);

        // Create an OobResponderRangingConfig, which specifies the ranging parameters for
        // the responder role.
        OobResponderRangingConfig config = new OobResponderRangingConfig.Builder(  deviceHandle).build();

        // Create a RangingPreference, which specifies the role (responder) and
        // configuration for the ranging session.
        RangingPreference preference =
                new RangingPreference.Builder(DEVICE_ROLE_RESPONDER, config).build();

        // Start the ranging session.
        session.start(preference);

        // Stop the ranging session
        session.stop();
    }
}

قابلیت همکاری UWB با دستگاه‌های iOS

ماژول مسافت‌یابی از قابلیت همکاری با دستگاه‌های iOS با استفاده از پهنای باند فوق وسیع (UWB) پشتیبانی می‌کند. برای مسافت‌یابی با یک دستگاه iOS، باید از یک پیاده‌سازی OOB سفارشی استفاده کنید و جلسه مسافت‌یابی را با پارامترهای خاصی که با پروتکل لوازم جانبی تعامل نزدیک اپل مطابقت دارند، پیکربندی کنید. برای مرجع به برنامه نمونه مراجعه کنید.

هنگام ایجاد RangingPreference ، RawRangingDevice و UwbRangingParams برای مشخص کردن پیکربندی استفاده کنید. پارامترهای زیر برای قابلیت همکاری iOS بسیار مهم هستند:

  • شناسه پیکربندی: از UwbRangingParams.CONFIG_UNICAST_DS_TWR استفاده کنید.
  • اطلاعات کلیدی جلسه: یک آرایه بایتی حاوی شناسه فروشنده و Static STS IV ارائه دهید.
  • کانال پیچیده: شماره کانال و شاخص مقدمه را طوری تنظیم کنید که با پیکربندی دستگاه iOS مطابقت داشته باشد.

قطعه کد زیر نحوه ایجاد یک RangingPreference برای یک دستگاه آغازگر با قابلیت فاصله‌یابی به همراه یک پاسخ‌دهنده iOS را نشان می‌دهد:

کاتلین

// Create UwbRangingParams with iOS-specific configuration
val uwbRangingParams = UwbRangingParams.Builder(
    sessionId,
    UwbRangingParams.CONFIG_UNICAST_DS_TWR,
    sourceAddress,
    destinationAddress
)
    .setComplexChannel(
        UwbComplexChannel.Builder()
            .setChannel(channelNumber)
            .setPreambleIndex(preambleIndex)
            .build()
    )
    .setRangingUpdateRate(updateRate)
    .setSessionKeyInfo(sessionKeyInfo) // Vendor ID + STS IV
    .setSlotDuration(slotDuration)
    .build()

// Create RawRangingDevice
val rawRangingDevice = RawRangingDevice.Builder()
    .setRangingDevice(RangingDevice.Builder().build())
    .setUwbRangingParams(uwbRangingParams)
    .build()

// Create SessionConfig
val sessionConfig = SessionConfig.Builder()
    .setAngleOfArrivalNeeded(true)
    .setDataNotificationConfig(DataNotificationConfig.Builder()
        .setNotificationConfigType(DataNotificationConfig.NOTIFICATION_CONFIG_ENABLE)
        .build())
    .build()

// Create RangingPreference for the initiator
val preference = RangingPreference.Builder(
    RangingPreference.DEVICE_ROLE_INITIATOR,
    RawInitiatorRangingConfig.Builder()
        .addRawRangingDevice(rawRangingDevice)
        .build()
)
    .setSessionConfig(sessionConfig)
    .build()

جاوا

// Create UwbRangingParams with iOS-specific configuration
UwbRangingParams uwbRangingParams = new UwbRangingParams.Builder(
        sessionId,
        UwbRangingParams.CONFIG_UNICAST_DS_TWR,
        sourceAddress,
        destinationAddress)
        .setComplexChannel(new UwbComplexChannel.Builder()
                .setChannel(channelNumber)
                .setPreambleIndex(preambleIndex)
                .build())
        .setRangingUpdateRate(updateRate)
        .setSessionKeyInfo(sessionKeyInfo) // Vendor ID + STS IV
        .setSlotDuration(slotDuration)
        .build();

// Create RawRangingDevice
RawRangingDevice rawRangingDevice = new RawRangingDevice.Builder()
        .setRangingDevice(new RangingDevice.Builder().build())
        .setUwbRangingParams(uwbRangingParams)
        .build();

// Create SessionConfig
SessionConfig sessionConfig = new SessionConfig.Builder()
        .setAngleOfArrivalNeeded(true)
        .setDataNotificationConfig(new DataNotificationConfig.Builder()
                .setNotificationConfigType(DataNotificationConfig.NOTIFICATION_CONFIG_ENABLE)
                .build())
        .build();

// Create RangingPreference for the initiator
RangingPreference preference = new RangingPreference.Builder(
        RangingPreference.DEVICE_ROLE_INITIATOR,
        new RawInitiatorRangingConfig.Builder()
                .addRawRangingDevice(rawRangingDevice)
                .build())
        .setSessionConfig(sessionConfig)
        .build();

نمونه برنامه

برای یک مثال کامل از نحوه استفاده از ماژول مسافت‌یابی، به برنامه نمونه در AOSP مراجعه کنید. این برنامه نمونه تمام فناوری‌های مسافت‌یابی پشتیبانی‌شده توسط ماژول مسافت‌یابی را پوشش می‌دهد و شامل جریان‌هایی برای هر دو نوع جلسه پشتیبانی‌شده است.

قابلیت همکاری UWB با دستگاه‌های iOS

برنامه نمونه اندروید از شروع یک جلسه مسافت‌یابی UWB با برنامه نمونه iOS پشتیبانی می‌کند.

شکل 2. استفاده از UWB در اندروید و iOS.