Для работы с jCjS необходимо познакомиться с базовыми понятиями, описанием и алгоритмом его работы.
Для дальнейшего чтения вам понадобится описание терминов и аббревиатур, которые применяются в документации к jCjS.
| Термин | Описание |
|---|---|
| JS | JavaScript |
| JS-контекст | среда выполнения программы на JS |
| СКУ | Система контроля и управления |
| ОС | Операционная система (Windows, Lunux...) |
| Элеватор | Функционал, позволяющий выполнять опрос устройств подключеных к последователь-ным интерфейсам из раздельных JS-контекстов. |
| URL | Полный интернет адрес в формате xxx://addr:port/dir |
jCjS предоставляет собой среду исполнения и систему ввода-вывода для программ (скриптов) написанных на языке JavaScript (ECMA-262). Порядок выполнения скриптов, набор встроенных объектов, методы добавления встроенных объектов регламентируются действующей документацией.
jCjS предназначен для построения различных систем автоматизации и управления (СКУ), что отражено в методологии, структуре и правилах работы с программой. Область применения jCjS не ограничено СКУ и, в ряде случаев, jCjS может быть адаптирован для решения других задач, связанных с интеграцией интерпретатора JavaScript и компилируемого С++ кода с применением библиотеки Qt.
Как часть системы ввода-вывода jCjS содержит в своем составе HTTP сервер, поддерживающий минимально-достаточное подмножество протокола HTTP/1.1 (RFC2068).
Формирование HTTP ответа осуществляется выполнением специализированного скрипта-обработчика события, при этом доступ к параметрам HTTP запроса осуществляется через встроенный в JS-контекст объект.
Набор встроенных объектов JavaScript может быть расширен за счет плагин системы. Назначение каждого конкретного плагина не регламентируется, и может заключаться,
Порядок написания, компиляции и внедрения плагинов описан в документации. Предусмотрена возможность использования исходных кодов плагинов для "жесткой прошивки" их функционала в исполняемый файл jCjS.
В зависимости от настроек jCjS, возможна одновременная работа нескольких процессов jCjS с различными настройками HTTP порта и/или одновременная работа нескольких интерпретаторов JavaScript. Каждый экземпляр интерпретатора хранит набор параметров, отвечающих за логически выделенную и независимую подсистему. Встроенный сервер перенаправляет HTTP запросы определенному интерпретатору JavaScript в соответствии с параметрами URL.
jCjS содержит встроенные средства клиентской отправки HTTP запросов для сбора и выдачи данных серверам, в том числе серверам jCjS, выполняемых на удаленных машинах.
jCjS (Gui-версия) имеет в своем составе встроенный отладчик скриптов, позволяющий останавливать выполнение скрипта в точках останова, с возможностью просмотра локальных переменных.
Организация встроенных объектов скриптов имеющих доступ к файловой системе ограничивает их в доступе в пределах назначенных в настройках сервера директорий и их поддиректорий. Ограничение доступа к файлам сервера: настроечные файлы, файлы скриптов и страниц HTML осуществляется администратором ОС средствами ОС.
Настроечный файл в формате XML позволяет описать древовидную структуру настроечных данных сервера и постов (см. раздел Конфигурация).
Необязательные параметры настройки служат для передачи особых параметров во встроенные объекты скриптов, согласно установленных в документации правилам.
В ядро jCjS входит элеватор заданий на последовательных портах (далее элеватор). Он позволяет выполнять опрос устройств, подключеных к последовательным интерфейсам. Также он снимает ограничения, накладываемые требованиями на подключение устройств к последовательным интерфейсам (возможность опросить различные устройства с различными протоколами обмена и/или аппаратными настройками соединения расположенные на одном последовательном интерфейсе).
В описании работы фигурируют три объекта, которые необходимо описать
| Объект | Описание |
|---|---|
| server | Выполняет начальный запуск, чтение конфигурации, создание объектов post и обслуживание клиентских запросов |
| post | Объект, в котором запускается программа JS |
| http | server создает объект http при подключении клиетского браузера и передает его post-у |
В момент начального пуска, jCjS обращается к конфигурационному файлу jcjs.xml, читает из него настройки сервера и
описание постов, затем открывает HTTP порт и создает объекты post.
Каждый post, создает интерпретатор JavaScript (JS-контекст), объявляет в своем JS-контексте
глобальные объекты
server,
post,
jsext,
scriptEngine
а также специфические объекты описаные в конфигурации поста (см. строку 20 Листинга 2 раздела "Описание файла конфигурации").
Следующим шагом выполняется программа инициализации init.js и
отсылается уведомление серверу, с каким статусом инициализировался (ошибка/успех).
//debug=true;
//------------------------------------------------------------
// Авторизация действий на странице поста
var r_user="Admin"
var r_pass="system"
//------------------------------------------------------------
// Разрешить глобальную регистрацию
//server.makeRegistration = true;
if(server.makeRegistration)
post.evalScript("registration.js");
else
post.r_auth = (server.auth != "")
? server.auth
: server.toBase64(r_user+':'+r_pass);
//------------------------------------------------------------
// Выполнить системный скрипт
post.evalScript("jcjsHelper.js");
...
// Далее создание источников сигналов и их обработчиков,
// а также объектов опроса оборудования, записи в БД и т.д.
Сценарий инициализации - это JavaScript программа, в которой заложена вся автономная(не зависящая от запросов клинетских браузеров) логика работы поста.
Все посты инициализированны, server готов принимать входящие запросы от клиентских браузеров.
После того, как вы открыли браузер и ввели в адресную строку URL, браузер инициализирует соединение с сервером jCjS по протоколу HTTP. Как только содинение становиться установленным (established), server создает объект http, и если в первой директории встречается имя поста, передает созданный объект post-у. Пост принимает объект соединения, внедряет его в свой JS-контекст и выполняет коммандный скрипт cmd.js, задача которого обслужить запрос и ответить браузеру. Следующий схематический рисунок поясняет как это происходит.
Коммандный скрипт cmd.js выполнят необходимые функции по анализу аргументов HTTP запроса, и передает запрошенные данные браузеру.
//var ans = ifFunction(ans) ? ans :
function ans()
{
if(server.makeRegistration)
{
// Если в каком-то посте установлен флаг server.makeRegistration,
// то при первом вызове будет выполнен registration.js
if((typeof makeRegistration !== "function"))
post.evalScript("registration.js");
// а теперь проверка (функция из registration.js)
if(!makeRegistration())
return;
}
// Если есть аргументы GET http://adr/Post1/?arg1&arg2=2&arg3 то обслужить их
if(http.argCnt)
{
/* Можно заставить браузер предложить сохранить файл на диск
http.saveToDisk = true;
http.contentName = http.argKeyByNum(0) + '.txt';
*/
// Если первый агрумент server post http this, то отдать браузеру описание всех переменных запрошенного объекта
switch(http.argKeyByNum(0))
{
case 'server': http.respPlainText(JSON.stringify(server, null, 2)); return;
case 'post': http.respPlainText(JSON.stringify(post, null, 2)); return;
case 'http': http.respPlainText(JSON.stringify(http, null, 2)); return;
case 'this': http.respPlainText(JSON.stringify(this, null, 2)); return;
}
// Существует возможность авторизации запросов
switch(http.argKeyByNum(0))
{
case 'reg':{
if(!testAuth())
{
http.respError(403, 'запрос "' + http.argKeyByNum(0) + '" запрещен');
post.log("w", 'запрос клиента отклонен');
return;
}
http.respPlainText(JSON.stringify(server, null, 2));
}
return;
}
}//(http.argCnt)
// Отдать статические файлы из каталога поста.
// Функция jcjs_resp() объявлена в stuff/include/jcjsHelperResp.js
if(jcjs_resp())
return;
var mess = ": не найден";
http.respError(404, http.path + mess);
post.log("w", http.path + mess);
mess = '';
return;
}
// Обработка исключительных ситуаций в работе скрипта
try{
ans();
} // если будет ошибка в ans(), браузер получит заголовок с ошибкой 500
catch(e) // и будет произведено логирование детального описания ошибки в лог
{
http.respError(500, http.path);
post.log("e", e.fileName + ':' + e.lineNumber + ' "' + e.message + '"');
}
После того как jCjS получил сигнал к остановке,
server закрывает все соединения и рассылает команды постам на завершение работы.
Команды отсылаются в обратном инициализации порядке. Останавливается сначала последний инициализированный.
Последним останавливается серверный (первый) пост.
Пост, получив команду остановки, выполняет финальный скрипт end.js, на котором лежат обязанности по
завершению работы и приведению оборудованания в норамальное сотояние(закрытие клапанов, остановка двигателей и т.д).
server ожидает от постов сигнала о финале работы скрипта (функция post.finished() - обязательная в сценарии end.js)
// останов оборудования, закрытие соединений с БД и т.д. ... // Подать сигнал что пост завершил работу post.finished();
Если по каким-то причинам функция post.finished() не выполнена в сценарии end.js, сервер через 15 секунд принудительно завершит работу поста. (Это время можно изменить в контксте)