.. _ref-first-step:
Первые шаги в написании собственного приложения
===============================================
Вы можете писать свои приложения для управления сетью.
Введиение
---------
Так как RUNOS написан на языке с++, то для эффективности приложения дописываются к существующему коду, то есть после написания вашего приложения вам придется пересобирать RUNOS.
Предполгается, что вы хорошо владете языком C++ и `фреймворком qt `_. Так же полезны базовые знанияе утилиты `cmake `_.
Все файлы, которые вы создаете вам необходимо указывать в подходящем CMakeList.txt, в соответсвии с тем в какой директории находится ваш модуль.
После этого RUNOS будет компилироваться с вашими файлами.
.. _ref-application:
класс Application
------------------
Приложение в RUNOS это класс, который наследован от абстрактного класса Application, который объявлен в файле Application.hh:
.. cpp:class:: Application : public QObject
..
Вам надо будет перегразуить некоторые виртуальные функции для корректной работы (См. AIP Reference).
Методы, необходимые для перегрузки :
* .. cpp:function:: DependencyList Application::DependsOn(const Config& config) const
Список приложений, от которых зависит ваше приложение.
* .. cpp:function:: std::string Application::provides() const
Уникальная строка, которая идентифицирует ваше приложение и может быть использовано остальными для получения доступа к вашему приложению.
* .. cpp:function:: void Application::init(class Loader*)
Метод, который инициализирует ваше приложение.
Вам необходимо вставить макрос внутрь вашего класса
(как в `Q_OBJECT `_),
для того, чтобы ваш класс удовлетоврял необходимым требованиям :
.. c:function:: SIMPLE_APPLICATION(your_klass, provides_val)
your_klass -- Ваш класс.
provides_val -- имя вашего класса.
Данный макрос так же добавит в ваш класс статический метод ``get(Loader *)`` который позволит остальным приложениями получать доступ к вашему приложению.
Например::
#include "Application.hh"
#include "Loader.hh"
class YourApp : public Application
{
SIMPLE_APPLICATION(YourApp, "your-application-name")
public:
void init(Loader*, const Config&) override;
};
Инициализация
-------------
.. cpp:function:: void Application::init(Loader* ,const Config&)
Вам необходимо переопредилить данный метод, который вызывается при запуске контроллера, и приложение готово к инициализации, т.е. все зависимости готовы к старту.
Данный метод должен реализовывать все связи вашего приложения с
остальными приложением (Например `connect сигналов `_ или регистрации обработчиков)
Пример::
#include "Common.hh"
void YourApp::init(Loader *, const Config& )
{
LOG(INFO) << "Hello World";
}
Старт приложения
----------------
.. cpp:function:: void Application::startUp(Loader *)
Данный метод вызывается, когда все приложения проиницилизированы.
В нем вам необходимо выполнить все побочные эффекты вашего приложения, напиример прослушание портов.
Пример::
#include "Common.hh" // For log
void YourApp::startUp(Loader *)
{
LOG(INFO) << "All services inited";
}
Регестрация приложения
-----------------------
После того, как вы создали класс для вашего приложения, вам необходимо сообщить ядру контроллера о сущестовании вашего приложения.
Для этого необходимо зарегестрировать ваше приложение с помощью макроса
.. c:function:: REGISTER_APPLICATION(your_class, list_of_dependeces)
your_class -- имя вашего класса.
list_of_depenedeces -- Список, приложений, от которых заваисит ваше приложение. Последним необходимо указать ``""``.
.. attention::
Данный макрос нельзя прописывать в заголовочном файле!
.. warning::
Нельзя зацикиливать зависимости.
Теперь будет создаваться объект вашего приложения,
однако все еще не будут вызываться методы
:cpp:func:`Application::init`
и
:cpp:func:`Application::startUp`, потому что контроллер не считает нужным запускать ваше приложение.
Вам необходимо указать имя своего приложения в ``network-settings.json`` в списке ``services``, чтобы ваше приложение запустилось.
После этого ваше приложение запуститься и может управлять сетью.
Loader
------
.. cpp:class:: Loader
Методы :cpp:func:`Application::init` и :cpp:func:`Application::startUp` принимают как парметр указатель на :cpp:class:`Loader`.
:cpp:class:`Loader` это загрузчик приложений, который и инициализирует ваши приложения.
.. cpp:function:`Application* Loader::app(std::string interface)`
Данным методом можно получить указатели на стороние приложения.
interface -- имя стороннего приолжения.
Вы можете получать объекты других приложений с помощью статического метода ``get`` этих приложений, и передав им :cpp:class:`Loader` как аргумент.
Например::
#include "Controller.hh"
#include "Loader.hh"
#include "SwitchConnection.hh"
#include "Common.hh"
REGISTER_APPLICATION(YourApp, {"controller", ""})
...
void YourApp::init(Loader *loader, const Config& )
{
Controller *ctrl = Controller::get(loader);
QObject::connect(ctrl, &Controller::switchUp,
[](SwitchConnectionPtr conn, of13::FeaturesReply fr)
{
LOG(INFO) << "This is SWITCH!!!!";
};)
}
.. attention::
Добавляйте приложения, которые вы используется в список зависимостей! Это гарантирует, то что эти приложения будут проиницилизированы.
..
.. note::
Чтобы ваше приложение имело хоть какую-нибудь практическую пользу, вам придется взаимодействовать с другими приложениями, чтобы от них узнавать о событиях в сети.
Работа с конфигурационным файлом
--------------------------------
Ваше приложение может считывать настройки из конфигурационного файла.
.. cpp:type: json11:Json::object Config
С помощью этого класса, вы можете считываать настройки из файла ``network-settings.json``.
.. cpp:function:: Type config_get(const Config& config,\
const std::string& key,\
const Type& defval)
Считать из файла настроек ``network-settings.json`` значение по ключу.
Если данный ключ не найдет, будет возвращен defval.
На данный момент поддерживаются следующие типы :
* ``std::string``
* ``int``
* ``double``
* ``bool``
.. cpp:function:: Config config_cd(const Config& config,\
const std::string& key)
получить описание объекта json по ключу.
Дополнительные возможности см в `документации по json11 `_.