Південні Плагіни
Південні Плагіни використовуються для зв'язку з датчиками та виконавчими пристроями, є два режими роботи плагінів; asyncio та polled.
Режим опитування
Режим опитування - це найпростіша форма південного плагіна, яку можна написати, процедура опитування викликається з інтервалом, визначеним у конфігурації плагіна. Південний сервіс визначає тип плагіна, перевіряючи властивість mode в інформації, яку плагін повертає після виклику plugin_info.
Опитування плагіну
Метод плагіна poll викликається періодично для збору показань з датчика в режимі опитування. Як і у всіх інших викликах, аргументом, що передається методу, є хендл, повернутий викликом ініціалізації, поверненням методу має бути JSON-дані з показаннями, що повертаються.
Повернуте корисне навантаження у форматі JSON, як словник Python, повинно містити властивості: актив, мітка часу, ключ та показання.
| Властивість | Опис |
|---|---|
| asset | Ключ активу сенсорного пристрою, який зчитується |
| timestamp | Позначка часу для даних читання |
| key | UUID, який є унікальним ключем цього читання |
| readings | Самі дані для зчитування у вигляді JSON-об'єкта |
Важливо, щоб метод poll не блокувався, оскільки це перешкоджатиме належній роботі мікросервісу South. На прикладі нашого простого пристрою DHT11, підключеного до виводу GPIO, процедура poll може бути такою:
def plugin_poll(handle):
""" Extracts data from the sensor and returns it in a JSON document as a Python dict.
Available for poll mode only.
Args:
handle: handle returned by the plugin initialisation call
Returns:
returns a sensor reading in a JSON document, as a Python dict, if it is available
None - If no reading is available
Raises:
DataRetrievalError
"""
try:
humidity, temperature = Adafruit_DHT.read_retry(Adafruit_DHT.DHT11, handle)
if humidity is not None and temperature is not None:
time_stamp = str(datetime.now(tz=timezone.utc))
readings = { 'temperature': temperature , 'humidity' : humidity }
wrapper = {
'asset': 'dht11',
'timestamp': time_stamp,
'key': str(uuid.uuid4()),
'readings': readings
}
return wrapper
else:
return None
except Exception as ex:
raise exceptions.DataRetrievalError(ex)
return None
Режим асинхронного введення-виведення
У режимі асинхронної роботи плагін вставляється в цикл обробки подій самого Південного сервісу. Це більш складний механізм і призначений для плагінів, яким потрібно блокувати або прослуховувати вхідні дані через мережу.
Запуск Плагіна
Метод plugin_start, як і інші виклики плагіна, викликається з даними дескриптора плагіна, які було повернуто з виклику plugin_init. Виклик plugin_start буде викликано лише один раз для плагіна, саме plugin_start відповідає за встановлення коду плагіна у систему обробки подій python для asyncIO. Якщо припустити, що інтерфейс до датчика здійснюєтьс я через HTTP, і датчик буде здійснювати HTTP POST-дзвінки до нашого плагіну, щоб надсилати дані до Fledge, то plugin_start для цього сценарію створить кінцеву точку веб-додатку для отримання команди POST.
loop = asyncio.get_event_loop()
app = web.Application(middlewares=[middleware.error_middleware])
app.router.add_route('POST', '/', SensorPhoneIngest.render_post)
handler = app.make_handler()
coro = loop.create_server(handler, host, port)
server = asyncio.ensure_future(coro)
Цей код спочатку отримує цикл обробки подій для цього виконання Python, потім створює веб-додаток і додає маршрут для POST-запиту. У цьому випадку він викликає метод render_post об'єкта SensorPhone. Потім він переходить до створення обробника та встановлення екземпляра веб-сервера в систему подій.
Зворотний виклик асинхронних даних
Асинхронний зворотний виклик даних використовується для отримання даних з датчиків і передачі цих даних у процес поглинання Fledge. На відміну від механізму опитування, це робиться зсередини зворотного виклику, а не шляхом передачі даних назад до самого пвіденного сервісу. Точка входу плагіна, plugin_register_ingest, викликається південним сервісом перед запуском плагіна для реєстрації зворотного дзвінка в плагіні. Зазвичай плагін зберігає функцію зворотного виклику та довідкові дані для подальшого використання.
def plugin_register_ingest(handle, callback, ingest_ref):
"""Required plugin interface component to communicate to South C server
Args:
handle: handle returned by the plugin initialisation call
callback: C opaque object required to passed back to C->ingest method
ingest_ref: C opaque object required to passed back to C->ingest method
"""
global c_callback, c_ingest_ref
c_callback = callback
c_ingest_ref = ingest_ref
Потім плагін використовує ці збережені посилання, коли йому потрібно отримати дані для читання. Нове читання створюється і передається до функції зворотного виклику за допомогою об'єкта async_ingest, який має бути імпортований плагіном.
import async_ingest
Потім для кожного зчитування, яке потрібно отримати, дані надсилаються до потоку прийому південного плагіна за допомогою такої конструкції.
data = {
'asset': self.asset_name,
'timestamp': utils.local_timestamp(),
'readings': reads
}
async_ingest.ingest_callback(c_callback, c_ingest_ref, data)
message['status'] = code
return web.json_response(message)