Skip to main content

Південні Плагіни

Південні Плагіни використовуються для зв'язку з датчиками та виконавчими пристроями, є два режими роботи плагінів; asyncio та polled.

Режим опитування

Режим опитування - це найпростіша форма південного плагіна, яку можна написати, процедура опитування викликається з інтервалом, визначеним у конфігурації плагіна. Південний сервіс визначає тип плагіна, перевіряючи властивість mode в інформації, яку плагін повертає після виклику plugin_info.

Опитування плагіну

Метод плагіна poll викликається періодично для збору показань з датчика в режимі опитування. Як і у всіх інших викликах, аргументом, що передається методу, є хендл, повернутий викликом ініціалізації, поверненням методу має бути JSON-дані з показаннями, що повертаються.

Повернуте корисне навантаження у форматі JSON, як словник Python, повинно містити властивості: актив, мітка часу, ключ та показання.

ВластивістьОпис
assetКлюч активу сенсорного пристрою, який зчитується
timestampПозначка часу для даних читання
keyUUID, який є унікальним ключем цього читання
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)