- Автор: Роман Савоченко
- Спонсорування, повної ревізії на 1.8 ЛД[!]: SINGE SOFTWARE
- Початково створено: у старій Wiki
Цей посібник первинно покликано допомогти у створені модулів для OpenSCADA. Створення модуля може знадобитися за бажання додати підтримку нового джерела даних або іншого розширення до OpenSCADA. Оскільки OpenSCADA є гранично модульною, то всі інтерфейси взаємодії із зовнішнім середовищем здійснюється за посередництвом розширення модулями типів:
- бази даних;
- комунікаційні інтерфейси, транспорти;
- протоколи комунікаційних інтерфейсів;
- джерела даних та збір даних;
- архіви-історія (повідомлень та значень);
- інтерфейси користувача (GUI, TUI, WebGUI, speach, signal ...);
- додаткові модулі, спеціальні.
Але оскільки транспортні інтерфейси, реалізовані модулями, дозволяють зв'язуватися із різними пристроями на них, то цей документ розширено короткою інструкцією з посиланнями щодо створення внутрішніх Функцій, DAQ-Шаблонів, UI-Віджетів, а також оформлення Бібліотек із ними для розташування і публікації у офіційній колекції бібліотек OpenSCADA.
Contents
[hide]1 Creating a New Module
In order to post the developed module to the OpenSCADA source tree repository, you must do the following and comply with the following requirements:
- be the copyright holder or the author of the module code and distribute it under any free license, GPL preferred;
- prepare and store the module code as a separated archive of the module folder for any module subsystem of OpenSCADA with demands to the content:
- the source texts of the module at the beginning of each file must include correct copyrights information, be written and formatted according to some system where preference should be given to the formatting style of the main OpenSCADA modules;
- the localisation files of the module must be also correct, actual and proper formed.
- write a short information page of the module for placing it to the OpenSCADA Wiki in way like to the other ones there;
- for placing of this module, write a direct request in the forum topic "OpenSCADA development", including proof of functionality from the OpenSCADA developer or a short demonstration video.
Модулі в OpenSCADA представляють із себе поділювані бібліотеки, які підключаються до ядра OpenSCADA динамічно при запуску або під час функціювання програми. Багато модулів у процесі функціювання можуть бути відключені, підключені та оновлені із менеджера модулів. Модулі також можуть бути вбудовані-включені до ядра OpenSCADA під час складання за посередництвом аргументу --enable-{ModName}=incl до скрипту конфігурації configure, про що можна дізнатися із посібника по збірці. Модулі OpenSCADA можуть бути семи типів згідно присутнім модульним підсистемам. Наразі модулі до OpenSCADA пишуться на мові програмування "C++", хоча у подальшому можлива поява біндінгів на інші мови.
Для створення модулів до OpenSCADA необхідні знання програмування на мові C/C++, складальної системи AutoTools, а також базові знання ОС Linux та використовуваного дистрибутиву Linux.
У дереві вихідних текстів, у гілці кожної підсистеми, для спрощення створення нових модулів передбачено теку "=Tmpl=" із шаблоном модуля відповідної підсистеми. Розробник нового модуля може взяти цю теку та скопіювати її з ім'ям свого нового модуля, хоча він також завжди може використати у якості зразка будь який реальний функціонуючий модуль якщо його новий близький за структурою. Передбачено можливість створення модулів у дереві вихідних текстів проєкту OpenSCADA або як незалежного проєкту зовнішнього модуля до OpenSCADA.
1.1 Створення у дереві вихідних текстів проєкту OpenSCADA
Створювати нові модулі у дереві вихідних текстів проєкту OpenSCADA має сенс у випадку подальших планів передачі нового модуля проєкту OpenSCADA. Оскільки модуль не має суперечити духу відкритого проєкту та ліцензії на основі якої розробляється та розповсюджується OpenSCADA то ліцензією нового модуля вочевидь має бути одна із вільних ліцензій.
Процедура створення нового модуля з включенням до дерева вихідних текстів на основі шаблону в цілому є простішою за процедуру для зовнішнього модуля та включає в себе кроки:
- 1. Отримати дерево вихідних текстів проєкту OpenSCADA для:
- Робочої (Work) гілки:
- svn co svn://oscada.org/trunk/OpenSCADA
- гілки стабільного релізу — НЕБАЖАНО, оскільки до стабільних LTS релізів приймаються лише виправлення та ця інструкція потребує версії 0.9 або вище:
- svn co svn://oscada.org/tags/openscada_0.9
- 2. Скопіювати теку шаблону з назвою нового модуля "NewMod", наприклад, для підсистеми "БД":
- cd OpenSCADA/src/moduls/bd; cp -r =Tmpl= NewMod; cd NewMod; rm -f configure.ac
- для підсистеми "Збір Даних" шлях наступний — "OpenSCADA/src/moduls/daq"
- для підсистеми "Архіви-Історія" шлях наступний — "OpenSCADA/src/moduls/arhiv"
- для підсистеми "Транспорти" шлях наступний — "OpenSCADA/src/moduls/transport"
- для підсистеми "Транспортні Протоколи" шлях наступний — "OpenSCADA/src/moduls/protocol"
- для підсистеми "Користувацькі Інтерфейси" шлях наступний — "OpenSCADA/src/moduls/ui"
- для підсистеми "Спеціальні" шлях наступний — "OpenSCADA/src/moduls/special"
- cd OpenSCADA/src/moduls/bd; cp -r =Tmpl= NewMod; cd NewMod; rm -f configure.ac
- 3. Редагувати файл "module.cpp" щодо:
- також може здійснюватися автоматично за допомогою: sed -i "s/Tmpl/NewMod/g" *.{cpp,h}
- зміни назви функцій вбудування-включення модуля згідно назви нового модуля:
- "TModule::SAt bd_Tmpl_module( int n_mod )" —> "TModule::SAt bd_NewMod_module( int n_mod )"
- "TModule *bd_Tmpl_attach( const TModule::SAt &AtMod, const string &source )" —> "TModule *bd_NewMod_attach( const TModule::SAt &AtMod, const string &source )"
- інформації про модуль у файлі "module.cpp", а саме ділянка:
//************************************************
//* Modul info! *
#define MOD_ID "NewMod"
#define MOD_NAME _("DB NewMod")
#define MOD_TYPE SDB_ID
#define VER_TYPE SDB_VER
#define MOD_VER "0.0.1"
#define AUTHORS _("MyName MyFamily")
#define DESCRIPTION _("BD NewMod description.")
#define MOD_LICENSE "GPL2"
- 4. Відредагувати конфігурацію складання модуля у файлі "Makefile.am" щодо:
- також може здійснюватися автоматично за допомогою: sed -i "s/Tmpl/NewMod/g" Makefile.am
EXTRA_DIST = *.h po/* if NewModIncl noinst_LTLIBRARIES = db_NewMod.la db_NewMod_la_CXXFLAGS = -DMOD_INCL -fpic db_NewMod_la_LIBTOOLFLAGS = --tag=disable-shared db_NewMod_la_LDFLAGS = -module else oscd_modul_LTLIBRARIES = db_NewMod.la db_NewMod_la_CXXFLAGS = db_NewMod_la_LIBTOOLFLAGS = --tag=disable-static db_NewMod_la_LDFLAGS = -module -avoid-version $(top_builddir)/src/liboscada.la endif db_NewMod_la_CXXFLAGS += $(NewMod_CFLAGS) db_NewMod_la_LDFLAGS += $(NewMod_LDLAGS) db_NewMod_la_SOURCES = module.cpp I18N_mod = $(oscd_modulpref)NewMod include ../../../../I18N.mk
- 5. Додати запис нового модуля в кінець секції підсистеми конфігураційного файлу "OpenSCADA/configure.ac" складальної системи OpenSCADA:
- в кінець секції "DB modules" для підсистеми "БД":
AX_MOD_DB_EN(NewMod, [disable or enable[=incl] compilation module DB.NewMod], disable, incl, [ # Код перевірки зовнішніх бібліотек модуля ])
- в кінець секції "DAQ modules" для підсистеми "Збір Даних":
AX_MOD_DAQ_EN(NewMod, [disable or enable[=incl] compilation module DAQ.NewMod], disable, incl, [ # Код перевірки зовнішніх бібліотек модуля ])
- в кінець секції "Archive modules" для підсистеми "Архіви-Історія":
AX_MOD_Archive_EN(NewMod, [disable or enable[=incl] compilation module Archive.NewMod], disable, incl, [ # Код перевірки зовнішніх бібліотек модуля ])
- в кінець секції "Transport modules" для підсистеми "Транспорти":
AX_MOD_Transport_EN(NewMod, [disable or enable[=incl] compilation module Transport.NewMod], disable, incl, [ # Код перевірки зовнішніх бібліотек модуля ])
- в кінець секції "Transport protocol modules" для підсистеми "Транспортні Протоколи":
AX_MOD_TrProt_EN(NewMod, [disable or enable[=incl] compilation module Protocol.NewMod], disable, incl, [ # Код перевірки зовнішніх бібліотек модуля ])
- в кінець секції "UI modules" для підсистеми "Користувацькі Інтерфейси":
AX_MOD_UI_EN(NewMod, [disable or enable[=incl] compilation module UI.NewMod], disable, incl, [ # Код перевірки зовнішніх бібліотек модуля ])
- в кінець секції "Special modules" для підсистеми "Спеціальні":
AX_MOD_Special_EN(NewMod, [disable or enable[=incl] compilation module Special.NewMod], disable, incl, [ # Код перевірки зовнішніх бібліотек модуля ])
- 6. Тепер новий модуль можна скласти у складі OpenSCADA після переформування складальної системи:
- autoreconf -if; ./configure --enable-NewMod; make
- 7. Опублікувати — сформувати латку із вашим модулем та надіслати її розробникам OpenSCADA:
- cd OpenSCADA; make distclean; rm -rf src/moduls/bd/NewMod/{Makefile.in,.deps}
- svn add src/moduls/bd/NewMod; svn diff > NewMod.patch
1.2 Створення зовнішнього модуля до OpenSCADA
Створення зовнішнього модуля до OpenSCADA може мати сенс у випадку розробки інтерфейсу інтеграції з комерційними системами, які вимагають закриття коду взаємодії, а також у випадку інших реалізацій комерційних інтерфейсів при яких модуль до OpenSCADA отримує статус окремого проєкту, розповсюджується та підтримується незалежно, часто у вигляді бінарних збірок під конкретну платформу та версію OpenSCADA. Ліцензія таких модулів відповідно може бути будь якою.
Процедура створення нового зовнішнього модуля на основі шаблону багато в чому схожа на попередню процедуру та включає в себе кроки:
- 1. Отримати вихідні текстів проєкту OpenSCADA — для зовнішнього модуля у якості джерела шаблону можна використати будь які файли OpenSCADA версії більш 0.9, оскільки із них потрібно скопіювати лише теку "=Tmpl=" та декілька файлів для збірки.
- 2. Скопіювати теку шаблону з ім'ям нового модуля "NewMod", наприклад, для підсистеми "БД"; та вже в ній створити та скопіювати потрібні файли зовнішнього модуля. В подальшому інформаційні файли проєкту "COPYING", "NEWS", "README", "AUTHORS" та "ChangeLog" потрібно заповнити згідно сутності нового модуля:
- cp -r OpenSCADA/src/moduls/bd/=Tmpl= NewMod; touch NewMod/{NEWS,README,AUTHORS,ChangeLog}; cp OpenSCADA/I18N.mk NewMod/
- для підсистеми "Збір Даних" шлях наступний — "OpenSCADA/src/moduls/daq/=Tmpl="
- для підсистеми "Архіви-Історія" шлях наступний — "OpenSCADA/src/moduls/arhiv/=Tmpl="
- для підсистеми "Транспорти" шлях наступний — "OpenSCADA/src/moduls/transport/=Tmpl="
- для підсистеми "Транспортні Протоколи" шлях наступний — "OpenSCADA/src/moduls/protocol/=Tmpl="
- для підсистеми "Користувацькі Інтерфейси" шлях наступний — "OpenSCADA/src/moduls/ui/=Tmpl="
- для підсистеми "Спеціальні" шлях наступний — "OpenSCADA/src/moduls/special/=Tmpl="
- cp -r OpenSCADA/src/moduls/bd/=Tmpl= NewMod; touch NewMod/{NEWS,README,AUTHORS,ChangeLog}; cp OpenSCADA/I18N.mk NewMod/
- 3. Відредагувати інформацію модуля у файлі "module.cpp" аналогічно цьому пункту попереднього розділу.
- 4. Відредагувати конфігурацію збірки модуля у файлі "Makefile.am" аналогічно цьому пункту попереднього розділу, окрім:
- замість "db_NewMod_la_LDFLAGS = -module -avoid-version $(top_builddir)/src/liboscada.la" записати "db_NewMod_la_LDFLAGS = -module -avoid-version", тобто видалити "$(top_builddir)/src/liboscada.la"
- замість "include ../../../../I18N.mk" записати "include I18N.mk", тобто видалити шлях "../../../../"
- 5. Відредагувати файл конфігурації складальної системи "configure.ac" щодо:
- також може здійснюватися автоматично за допомогою: sed -i "s/Tmpl/NewMod/g" configure.ac
- "AC_INIT([Tmpl],[0.0.1],[my@email.org])" — інформація про модуль: ім'я, версія та Ел.Пошта проєкту
- "AM_CONDITIONAL([TmplIncl],[test])" — "AM_CONDITIONAL([NewModIncl],[test])"
- 6. Встановити пакет розробки OpenSCADA "openscada-dev" або "openscada-devel" — у зв'язку з тим, що модуль зовнішній та вихідні файли OpenSCADA потрібні лише на першому етапі його створення, то необхідно встановлювати пакет розробки OpenSCADA, який містить заголовні файли та бібліотеки.
- 7. Тепер новий модуль можна скласти, після формування складальної системи:
- autoreconf -if; ./configure; make
1.3 API of the module
OpenSCADA API for the developer of OpenSCADA and modules to it is described in the document "OpenSCADA API", which should always be on hand at development for OpenSCADA. This document focuses on the detailed explanation of the main points of the modular API.
Modules in OpenSCADA are implemented as shared libraries and one such library can contain many modules of the OpenSCADA subsystems, actually acting as a container. Those containers also can be included-builtin in the OpenSCADA Core Library if you build very tightly solutions.
The first step in connecting the shared libraries (SO — Shared Object) is the connection of the initialization functions. These functions should be defined as usual "C" functions to avoid distortion of them names. Usually this is done as follows:
//================== CUT =========================
extern "C"
{
#ifdef MOD_INCL
TModule::SAt bd_Tmpl_module( int n_mod )
#else
TModule::SAt module( int n_mod )
#endif
{
if(n_mod == 0) return TModule::SAt(MOD_ID, MOD_TYPE, VER_TYPE);
return TModule::SAt("");
}
<!--T:348-->
#ifdef MOD_INCL
TModule *bd_Tmpl_attach( const TModule::SAt &AtMod, const string &source )
#else
TModule *attach( const TModule::SAt &AtMod, const string &source )
#endif
{
if(AtMod == TModule::SAt(MOD_ID,MOD_TYPE,VER_TYPE)) return new BDTmpl::BDMod(source);
return NULL;
}
}
//================== CUT =========================
The entry point of any module are the following functions:
- TModule::SAt module( int n_mod ), TModule::SAt {modTp}_{modNm}_module( int n_mod ) — are used to scan the list and information about all modules in the library. The first function is used during the implementation of modules in an external shared library, and the second during their including-embedding in the OpenSCADA core, where modTp corresponds to the type of the module, and modNm is its ID.
- TModule *attach( const TModule::SAt &AtMod, const string &source ), TModule *{modTp}_{modNm}_attach( const TModule::SAt &AtMod, const string &source ) — is used to directly connect-open the selected module by creating a root object of the module inherited from TModule. The first function is used during the implementation of modules in an external shared library, and the second during the including-embedding of them into the OpenSCADA core, where modTp and modNm correspond to the previous function.
Common to all modules is the inheritance of the root object-class of the module from the class of the module subsystem TModule, which indicates the presence of a common part of the module interface, which we will consider further. To get a vision of the architecture of the modules in the context of the overall OpenSCADA architecture, it is strongly recommended to have the overall OpenSCADA class diagram in front of your eyes!
All module interface objects inherit the node class TCntrNode, which provides the control interface mechanism. One task of the mechanism is to provide the object configuration interface in any OpenSCADA configurator.
Common API |
---|
TCntrNode — OpenSCADA Node:
|
TModule — OpenSCADA Module:
|
API of the modules of the "Data Bases (DB)" subsystem |
Intended for the integration of OpenSCADA with a database or DBMS which is implemented by the module. Provides two common approaches in the modules implementation:
|
TTypeBD->TModule — the root module object of the "DB" subsystem:
|
TBD — the database object:
|
TTable — the table object in the database:
|
API of the modules of the "Transports" subsystem |
Provides OpenSCADA communications through the interface, often it is the network one which is implemented by the module. |
TTypeTransport->TModule — the root module object of the "Transports" subsystem:
|
TTransportIn — the input transport object:
|
TTransportOut — the output transport object:
|
API of the modules of the "Transport protocols" subsystem |
Provides OpenSCADA with the protocol layer communications, implemented by the module, for the data access from the external systems and for the OpenSCADA data providing for the external systems. |
TProtocol->TModule — the root module object of the "Transport protocols" subsystem:
|
TProtocolIn — the input object of the transport protocol of the input requests processing from the input transport object TTransportIn. For each session of the input request the object of the associated input protocol is created, which remains alive until completion of the full "request->answer" session. Address of the transport, which opened the protocol instance, is specified in srcTr():
|
API of the modules of the "Data AcQuisition" subsystem |
Provides the realtime data acquisition from the external systems or it formation in the calculators, implemented by the module. That is the main subsystem since SCADA is about the Data Acquisition primarily. As the main subsystem it provides several approaches in the modules implementation, which mostly about the attributes structure formation and storing:
|
TTypeDAQ->TModule — the root module object of the "Data AcQuisition" subsystem:
|
TController — the data source controller object. In the context of the object is usually run a task of the periodic or scheduled polling of the realtime data of one physical controller or physically separated block of data. In the case of data getting by the packages, they are placed directly into the archive associated with the parameter attribute TVAl::arch(), and the current value is set by the TVAl::set() function with the attribute "sys"=TRUE:
|
TParamContr->TValue — the controller parameter object of the data source. Contains attributes with real data in a set defined by physically available data. The values to the attributes come from the polling task of the controller, in the asynchronous mode, or are requested during the access, in the synchronous mode, and through the methods of the inherited type TValue:
|
API of the modules of the "Archives-History" subsystem |
Used for archiving and maintaining the history of messages and realtime values received in the "Data AcQuisition" subsystem, and in the means implemented by the module. |
TTypeArchivator->TModule — the root module object of the "Archives-History" subsystem:
|
TMArchivator — the message archiver object.
|
TVArchivator — the value archiver object.
|
TVArchEl — the element object of the value archiver.
|
API of the modules of the "User Interfaces" subsystem |
The user interface is formed according to the concept and mechanisms of external known standards and libraries. |
TUI->TModule — the root module object of the "User Interfaces" subsystem: |
API of the modules of the "Special" subsystem |
Implements the specific functions that are not included in any of the above subsystems. The specific functions are formed accordingly to their own need and with using all features of the OpenSCADA API. |
TSpecial->TModule — the root module object of the "User Interfaces" subsystem: |
Для зручності прямої адресації до кореневого об'єкта модуля із будь якого об'єкта нижче за ієрархією, рекомендується визначити глобальну змінну "mod" у області імен модуля, з ініціалізацією її у конструкторі кореневого об'єкта. Також, для прозорого перекладу текстових повідомлень модуля рекомендується визначити шаблони функцій виклику перекладу повідомлень модуля "_({Повідомлення})" та "trS({Повідомлення})" як:
#undef _
#define _(mess) mod->I18N(mess).c_str()
#undef trS
#define trS(mess) mod->I18N(mess,mess_PreSave)
У конструкторі кореневого об'єкту модуля успадкованого від TModule необхідно встановити основну інформацію модуля викликом функції void modInfoMainSet({Ім'я}, {Тип}, {Версія}, {Автори}, {Опис}, {Ліцензія}, {Джерело}) після ініціалізації швидкого посилання "mod" на кореневий об'єкт цього модуля.
Подальше отримання файлу шаблону перекладів "po/oscd_NewMod.pot" текстових повідомлень "_({Повідомлення})" та "trS({Повідомлення})", а також оновлення-актуалізація файлів вже існуючих перекладів "po/{uk|de|ru|...}.po" здійснюється командою у теці модуля make messages.
При вирішенні завдань нового модуля може знадобитися розширення параметрів конфігурації, що здійснюється у віртуальній функції void cntrCmdProc( XMLNode *req );. Вміст цієї функції, який додає властивості, у модулі SQLite має вигляд:
void MBD::cntrCmdProc( XMLNode *opt )
{
//Getting the page info
if(opt->name() == "info") {
TBD::cntrCmdProc(opt);
ctrMkNode("fld",opt,-1,"/prm/cfg/ADDR",EVAL_STR,enableStat()?R_R___:RWRW__,"root",SDB_ID,3,
"dest","sel_ed","select","/prm/cfg/dbFsList","help",
_("SQLite DB address must be written as: \"{FileDBPath}\".\n"
"Where:\n"
" FileDBPath - full path to DB file (./oscada/Main.db).\n"
" Use the empty path to create a temporary database on the disk.\n"
" Use \":memory:\" to create a temporary database in memory."));
if(reqCnt)
ctrMkNode("comm",opt,-1,"/prm/st/end_tr",_("Close opened transaction"),RWRW__,"root",SDB_ID);
}
//Processing for commands to the page
string a_path = opt->attr("path");
if(a_path == "/prm/cfg/dbFsList" && ctrChkNode(opt)) {
opt->childAdd("el")->setText(":memory:");
TSYS::ctrListFS(opt, addr(), "db;");
}
else if(a_path == "/prm/st/end_tr" && ctrChkNode(opt,"set",RWRW__,"root",SDB_ID,SEC_WR) && reqCnt) transCommit();
else TBD::cntrCmdProc(opt);
}
Перша половина цієї функції обслуговує інформаційні запити "info" з переліком та властивостями полів конфігурації. Друга половина обслуговує решту команд на отримання, встановлення значення та інше. Виклик TBD::cntrCmdProc(opt); використовується для отримання успадкованого інтерфейсу. Детальніше про призначення використаних функцій дивіться у інтерфейсі управління, а також у вихідних текстах існуючих модулів.
Об'єкт TCntrNode окрім функції інтерфейсу управління надає уніфіковані механізми контролю за модифікацією конфігурації об'єкта, завантаження, збереження та видалення дублікатів конфігурації у сховищі. Для встановлення прапорця модифікації даних об'єкта можна використовувати функції modif() та modifG(), а специфічні до модуля дії із завантаження та збереження можна розташовувати у віртуальні функції:
- void load_( TConfig *cfg );, void load_( ); — завантаження об'єкта зі сховища.
- void save_( ); — збереження об'єкта у сховищі.
Дії із конфігурацією типово відбуваються за посередництвом об'єкта TConfig, яких містить набір визначених властивостей зі структурою та значеннями. Для прямого відображення властивостей об'єкта модуля він успадковується від TConfig, а нові властивості додаються командою:
fldAdd(new TFld("MOD_PRMS",trS("Module addition parameters"),TFld::String,TFld::FullText|TCfg::NoVal,"100000"));
Завантаження/збереження/видалення властивостей, вказаних у об'єкті TConfig, із/у/в сховище здійснюється командами:
TBDS::dataGet(fullDB(), owner().nodePath()+tbl(), *this);
TBDS::dataSet(fullDB(), owner().nodePath()+tbl(), *this);
TBDS::dataDel(fullDB(flag&NodeRemoveOnlyStor), owner().nodePath()+tbl(), *this, TBDS::UseAllKeys);
Де:
- fullDB() — повна назва сховища у загальній формі;
- owner().nodePath()+tbl() — загальний шлях до вузла об'єкта у конфігураційному файлі, представлений таблицею;
- *this — цей об'єкт, успадкований від TConfig.
Для генерації налагоджувальних повідомлень відповідно до загальної концепції налаштувань необхідно використовувати функцію mess_debug() з умовою виклику залежно від ділянки вихідного тексту програми:
- рідко викликувана ділянка — прямий виклик функції mess_debug(...);;
- часто викликувана ділянка — умовний виклик if(mess_lev() == TMess::Debug) mess_debug(...);;
- критична до продуктивності ділянка коду — обгортання у визначення OSC_DEBUG:
#ifdef OSC_DEBUG
mess_debug(...);
#endif
2 Creating New Internal Items and Libraries with them
Для подальшого розміщення бібліотеки розробленого внутрішнього коду до репозиторію дерева вихідних текстів OpenSCADA, маєте виконати наступне і дотримуватися вимог:
- бути правовласником або автором коду і розповсюджувати його за вільною ліцензією, віддаючи перевагу GPL;
- створити окреме експортне сховище і бібліотеку у ньому, куди розташувати ваші Функції, DAQ-Шаблони, UI-Віджети; якщо-ж це нова бібліотека, то назвати її відповідним чином із описом, як зазначено нижче;
- приготувати і зберігати внутрішній код як архів файлу БД SQLite із вимогами до вмісту:
- Функції, DAQ-Шаблони, UI-Віджети, а також їх бібліотека, мають міжнародною мовою і у полі опису містити сам опис, та загальну інформацію із правами копіювання у кінці:
Author: Name Family <nick@email.org> Total complexity: N.N HD Version: N.N.N License: GPLvN
- вихідні тексти Функцій, DAQ-Шаблонів, UI-Віджетів не мають містити локалізованих текстів, а лише тексти міжнародною мовою із обгортанням функцією перекладу tr();
- ІД та ім'я ВВ мають також бути міжнародною мовою;
- усі зазначені тексти можуть перекладатися локальною мовою автора або і декількома на його розсуд.
- написати коротку інформаційну сторінку для нової бібліотеки, або частину до існуючої для розташування її на OpenSCADA Wiki таким-же чином, як і інші бібліотеки поряд;
- для розташування бібліотеки написати прямий запит у темі форуму "Розробка OpenSCADA", включаючи доказ працездатності від розробника OpenSCADA або коротке демонстраційне відео.