اتصال به یک دستگاه

درایورهای IoT به هر ماژول Odoo اجازه می‌دهند به‌صورت بی‌درنگ با هر دستگاهی که به IoT Box متصل است ارتباط برقرار کند. ارتباط با IoT Box دوطرفه است، بنابراین کلاینت Odoo می‌تواند به هر یک از دستگاه‌های پشتیبانی‌شده فرمان ارسال کند و از آن‌ها اطلاعات دریافت کند.

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

  • یک Interface، برای شناسایی دستگاه‌های متصلِ از یک نوع خاص

  • یک Driver، برای ارتباط با یک دستگاه منفرد

در هر راه‌اندازی، IoT Box همهٔ Interfaceها و Driverهایی را که می‌توان روی نمونهٔ Odoo متصل قرار داد، بارگذاری می‌کند. هر ماژول می‌تواند شامل یک دایرکتوری iot_handlers باشد که به IoT Box کپی خواهد شد. ساختار این دایرکتوری به این صورت است

your_module
├── ...
└── iot_handlers
    ├── drivers
    │   ├── DriverName.py
    │   └── ...
    │
    └── interfaces
        ├── InterfaceName.py
        └── ...

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

دستگاه‌های متصل به IoT Box از طریق Interfaces شناسایی می‌شوند. برای هر نوع اتصال پشتیبانی‌شده (USB، Bluetooth، Video، Printers، Serial و غیره) یک Interface وجود دارد. این Interface فهرستی از دستگاه‌های شناسایی‌شده را نگه می‌دارد و آن‌ها را با Driver مناسب مرتبط می‌کند.

دستگاه‌های پشتیبانی‌شده هم در صفحهٔ اصلی IoT Box که می‌توانید از طریق آدرس IP آن دسترسی پیدا کنید و هم در ماژول IoT نمونهٔ Odoo متصل ظاهر خواهند شد.

Interface

نقش Interface این است که فهرستی از دستگاه‌های متصل از طریق یک نوع اتصال مشخص را نگه دارد. ایجاد یک Interface جدید نیازمند موارد زیر است

  • گسترش کلاس Interface

  • تنظیم ویژگی کلاس connection_type

  • پیاده‌سازی متد get_devices که باید دیکشنری حاوی داده‌های هر دستگاه شناسایی‌شده را بازگرداند. این داده به‌عنوان آرگومان به سازنده‌ها و متد supported Driverها داده خواهد شد.

توجه

تنظیم ویژگی _loop_delay فاصلهٔ بین فراخوانی‌های get_devices را تغییر می‌دهد. به‌صورت پیش‌فرض، این فاصله روی ۳ ثانیه تنظیم شده است.

from odoo.addons.hw_drivers.interface import Interface

class InterfaceName(Interface):
    connection_type = 'ConnectionType'

    def get_devices(self):
        return {
            'device_identifier_1': {...},
            ...
        }

Driver

وقتی Interface فهرست دستگاه‌های شناسایی‌شده را بازیابی کرد، روی همهٔ Driverهایی که دارای همان ویژگی connection_type هستند حلقه می‌زند و متد supported مربوط به هر کدام را روی همهٔ دستگاه‌های شناسایی‌شده آزمایش می‌کند. اگر متد supported یک Driver مقدار True بازگرداند، یک نمونه از این Driver برای دستگاه متناظر ایجاد می‌شود.

توجه

متدهای supported درایورها از ترتیب اولویت پیروی می‌کنند. متد supported یک کلاس فرزند همیشه قبل از کلاس والد آن آزمایش می‌شود. این اولویت را می‌توان با تغییر ویژگی priority Driver تنظیم کرد.

ایجاد یک Driver جدید نیازمند موارد زیر است:

  • گسترش Driver

  • تنظیم ویژگی کلاس connection_type.

  • تنظیم ویژگی‌های device_type، device_connection و device_name.

  • تعریف متد supported

from odoo.addons.hw_drivers.driver import Driver

class DriverName(Driver):
    connection_type = 'ConnectionType'

    def __init__(self, identifier, device):
        super(NewDriver, self).__init__(identifier, device)
        self.device_type = 'DeviceType'
        self.device_connection = 'DeviceConnection'
        self.device_name = 'DeviceName'

    @classmethod
    def supported(cls, device):
        ...

ارتباط با دستگاه‌ها

وقتی دستگاه جدید شما شناسایی شد و در ماژول IoT ظاهر شد، گام بعدی برقراری ارتباط با آن است. از آنجا که جعبه تنها یک آدرس IP محلی دارد، تنها از همان شبکهٔ محلی قابل دسترسی است. بنابراین، ارتباط باید در سمت مرورگر و در JavaScript رخ دهد.

این فرآیند به جهت ارتباط بستگی دارد: - از مرورگر به جعبه، از طریق Actions - از جعبه به مرورگر، از طریق Longpolling

هر دو کانال از طریق همان شیء JS، یعنی DeviceProxy، قابل دسترسی هستند که با استفاده از IP جعبهٔ IoT و شناسهٔ دستگاه نمونه‌سازی می‌شود.

var DeviceProxy = require('iot.DeviceProxy');

var iot_device = new DeviceProxy({
    iot_ip: iot_ip,
    identifier: device_identifier
});

اقدامات

از Actionها برای گفتن به یک دستگاه انتخاب‌شده برای انجام یک اکشن خاص، مانند گرفتن عکس، چاپ رسید و غیره استفاده می‌شود.

توجه

باید توجه داشت که در این مسیر هیچ «پاسخی» توسط جعبه ارسال نخواهد شد، فقط وضعیت درخواست. پاسخ به اکشن، در صورت وجود، باید از طریق longpolling بازیابی شود.

یک اکشن را می‌توان روی شیء DeviceProxy انجام داد.

iot_device.action(data);

در درایور خود، یک متد action تعریف کنید که هنگام فراخوانی از یک ماژول Odoo اجرا خواهد شد. این متد دادهٔ ارائه‌شده در فراخوانی را به‌عنوان آرگومان دریافت می‌کند.

def action(self, data):
    ...

Longpolling

وقتی هر ماژولی در Odoo بخواهد داده‌ای را از یک دستگاه خاص بخواند، یک listener ایجاد می‌کند که با IP/دامنهٔ جعبه و شناسهٔ دستگاه شناسایی می‌شود و یک تابع callback به آن می‌دهد که هر بار وضعیت دستگاه تغییر می‌کند فراخوانی شود. این callback با دادهٔ جدید به‌عنوان آرگومان فراخوانی می‌شود.

iot_device.add_listener(this._onValueChange.bind(this));

_onValueChange: function (result) {
    ...
}

در Driver، یک رویداد با فراخوانی تابع device_changed از event_manager آزاد می‌شود. تمام callbackهای تنظیم‌شده روی listener سپس با self.data به‌عنوان آرگومان فراخوانی خواهند شد.

from odoo.addons.hw_drivers.event_manager import event_manager

class DriverName(Driver):
    connection_type = 'ConnectionType'

    def methodName(self):
        self.data = {
            'value': 0.5,
            ...
        }
        event_manager.device_changed(self)