Модуль FsmManager


Модуль FsmManager является библиотечным добавлением к программному интерфейсу Конечных Автоматов - т.е. к функциям FSM API.
Модуль FsmManager (Менеджер Конечных Автоматов) содержит: константы (_con_FsmManager.inc), переменные (_var_FsmManager.inc) и функции (_fun_FsmManager.inc) для работы с конечными автоматами (FSM = FiniteStateMachine). FsmManager разработан в первую очередь для создания управляющих программ на основе Конечных Автоматов в рамках технологии SMI, но может использоваться и без этой технологии (автономно).


Подключение:

Использование библиотеки FsmManager предполагает использование следующего шаблона программы (код подключения выделен жирным шрифтом):
program Demo;                    { How to use FsmManager            }
const
 {------------------------------}{ Declare uses program constants:  }
 {$I _con_StdLibrary}            { Include all Standard constants,  }
 {------------------------------}{ And add User defined constants:  }
 {$I _con_FsmManager}            { FsmManager constants             }
 
 // User code - constants...
 
var
 {------------------------------}{ Declare uses program variables:  }
 {$I _var_StdLibrary}            { Include all Standard variables,  }
 {------------------------------}{ And add User defined variables:  }
 {$I _var_FsmManager}            { FsmManager variables             }
 
 // User code - variables...

 {------------------------------}{ Declare procedures & functions:  }
 {$I _fun_StdLibrary}            { Include all Standard functions,  }
 {------------------------------}{ And add User defined functions:  }
 {$I _fun_FsmManager}            { FsmManager functions             }
 
 // User code - functions...
 
 {
 Clear user application strings...
 }
 procedure ClearApplication;
 begin
  ClearFsmManager;
  // User code - clear...
 end;
 {
 User application Initialization...
 }
 procedure InitApplication;
 begin
  InitFsmManager;
  // User code - init...
 end;
 {
 User application Finalization...
 }
 procedure FreeApplication;
 begin
  FreeFsmManager;
  // User code - free...
 end;
 {
 User application Polling...
 }
 procedure PollApplication;
 begin
  PollFsmManager;
  // User code - poll...
 end;
 {
 Process data coming from standard input...
 }
 procedure StdIn_Processor(var Data:String);
 var cmd,arg:String; n:Integer;
 begin
  ViewImp('CON: '+Data);
  {
  Handle "@cmd=arg" or "@cmd arg" commands:
  }
  cmd:='';
  arg:='';
  if GotCommand(Data,cmd,arg) then begin
   
   // User code - handle stdin...
   
   {
   Handle other commands by default handler...
   }
   StdIn_DefaultHandler(Data,cmd,arg);
  end;
  Data:='';
  cmd:='';
  arg:='';
 end;

{***************************************************}
{***************************************************}
{***                                             ***}
{***  MMM    MMM        AAA   IIII   NNN    NN   ***}
{***  MMMM  MMMM       AAAA    II    NNNN   NN   ***}
{***  MM MMMM MM      AA AA    II    NN NN  NN   ***}
{***  MM  MM  MM     AA  AA    II    NN  NN NN   ***}
{***  MM      MM    AAAAAAA    II    NN   NNNN   ***}
{***  MM      MM   AA    AA   IIII   NN    NNN   ***}
{***                                             ***}
{***************************************************}
{$I _std_main}{*** Please never change this code ***}
{***************************************************}
 



Константы:

см. файл _con_FsmManager.inc


Переменные:

см. файл _var_FsmManager.inc


Функции:

см. файл _fun_FsmManager.inc

Функции API условно делятся на прикладные (которые бывают нужны для создания прикладных программ) и служебные (которые предназначены в основном для внутреннего использования и обычно не вызываются явно). Некоторые служебные функции вызывать напрямую запрещено, иначе это нарушит логику работы программы. Напротив, некоторые прикладные функции являются основными, то есть обычно должны присутствовать в прикладной программе.


function fsm_init(arg:String):Integer;
Функция создает экземпляр менеджера Конечных Автоматов - FSM (Finite State Machine manager) с начальными параметрами, заданными списком аргументов arg, состоящим из слов, разделенных пробелами. Функция возвращает ссылку (reference) на созданный менеджер FSM и используется для создания экземпляров FSM в прикладных программах.

При вызове fsm_init(arg) параметр arg содержит разделенные пробелами опции в форме -option value или -option=value. Опции могут принимать следующие значения:
  -dns node     - задает имя (node) компьютера для сервера имен (DNS) в сети DIM
                  это имя может быть использовано для взаимодействия с DIM сервером
  -dom domain   - задает имя домена (domain), который надо создать в Менеджере FSM
                  имя домена должно удовлетворять обычным требованиям для имен (см. fsm_is_valid_name)
  -sml smlfile  - задает имя файла (smlfile) на языке SML, который надо загрузить в этом домене
                  имя файла задается относительно каталога основного файла конфигурации (обычно ..\Config)
  -verbose n    - задает режим (n) печати fsm_verbose_mode, n=(0/1)=(кратко/подробно)
                  значение по умолчанию (1) задается также в переменной конфигурации fsm_verbose_mode
  -listing n    - задает режим (n) вывода в отладочный файл fsm_listing_mode, n=(0/1)=(не/создавать файл *.lst)
                  значение по умолчанию (1) задается также в переменной конфигурации fsm_listing_mode
  -name id      - задает имя (id) для создаваемого менеджера FSM
  
При задании аргументов они обрабатываются последовательно (слева направо), поэтому домен (-dom) надо задавать перед заданием файла (-sml). При этом возможно последовательное задание и чтение нескольких доменов. Например:
  fsm:=fsm_init('-name FsmTest -dns localhost -dom DEMO -sml demo.sml -dom TEST -sml test.sml');
   -name FsmTest    - задает имя для Менеджера FSM
   -dns localhost   - задает DIM DNS равным localhost
   -dom DEMO        - создает в Менеджере домен DEMO
   -sml demo.sml    - загружает в домен DEMO файл demo.sml на языке SML
   -dom TEST        - создает в Менеджере домен TEST
   -sml test.sml    - загружает в домен TEST файл test.sml на языке SML
  
Примечание: Прикладная программа несет всю ответственность за созданные экземпляры FSM. Все созданные прикладной программой FSM-ссылки (fsm) должны быть очищены в конце работы программы (например, в процедуре FreeApplication) вызовом fsm_kill(fsm).


procedure fsm_kill(var fsm:Integer);
Процедура удаляет экземпляр менеджера Конечных Автоматов - FSM (Finite State Machine) со ссылкой fsm и очищает (обнуляет) ссылку. Все созданные прикладной программой FSM-ссылки (fsm) должны быть очищены в конце работы программы (например, в процедуре FreeApplication) вызовом fsm_kill(fsm). При выполнении процедура fsm_kill(fsm) вызывает fsm_free(fsm), а затем обнуляет ссылку fsm.


procedure procedure fsm_trouble(errno:Integer; msg:String);
Сервисная процедура, которая фиксирует ошибку в работе менеджера Конечных Автоматов (FSM) с номером (errno) и выводит сообщение (msg), если установлено значение fsm_verbose_mode.


function fsm_is_valid_name(name:String; typ:Integer):Boolean;
Проверяет, является ли строка (name) допустимым именем (идентификатором) для элементов с типом (typ) (fsm_type_domain,object,state,action,parameter). Имя (domain,parameter,class,objectset,function) допустимо, если оно содержит символы [a-zA-Z_0-9] и начинается с символов [a-zA-Z_]. Это соответствует шаблону регулярного выражения /[a-zA-Z_]+[a-zA-Z_0-9]*/i. В именах элементов (object,state,action) также допустимо использовать символы [&:.-]. Имена (идентификаторы) являются не чувствительными к регистру.


function fsm_is_valid_host(name:String):Boolean;
Проверяет, является ли строка (name) допустимым именем сервера (hostname) согласно стандартам (RFC 952, RFC 1123). Имя сервера допустимо, если оно содержит символы [a-z\-\.0-9] и начинается с символов [a-z0-9]. Длина имени не должна превышать 253 символа. Имена серверов являются не чувствительными к регистру.


function fsm_extract_name(path:String; typ:Integer):String;
Функция, используя путь (path) вида DOMAIN::OBJECT/STATE/ACTION#PARAMETER, извлекает (extract) имя (name) элемента заданного типа, например:
  name:=fsm_extract_name('EGP::UPS/OFF/SWITCH_ON#VOLTAGE',fsm_type_domain);    // домен     EGP
  name:=fsm_extract_name('EGP::UPS/OFF/SWITCH_ON#VOLTAGE',fsm_type_object);    // объект    UPS
  name:=fsm_extract_name('EGP::UPS/OFF/SWITCH_ON#VOLTAGE',fsm_type_state);     // состояние OFF
  name:=fsm_extract_name('EGP::UPS/OFF/SWITCH_ON#VOLTAGE',fsm_type_action);    // действие  SWITCH_ON
  name:=fsm_extract_name('EGP::UPS/OFF/SWITCH_ON#VOLTAGE',fsm_type_parameter); // параметр  VOLTAGE
  
При отсутствии заданного компонента имени или неверном имени возвращается пустая строка.


function fsm_dump(fsm:Integer; mode:Integer; filter:String):String;
Отладочная функция, которая возвращает краткое содержимое Менеджера FSM: в виде ключа Path (при mode=0) или в виде ключа со значением Path => Declaration (при mode=1) для каждого элемента FSM. Параметр фильтра (filter) задает список слов, которые надо включать или ^пропускать при выводе. Функция используется для отладочного вывода при разработке прикладного кода.
Команда @smiuisrv_fsm_dump mode filter позволяет вызывать функцию в консоли (при использовании модуля SmiuiSrv). Например:
  @smiuisrv_fsm_dump                    - вывод списка всех ключей
  @smiuisrv_fsm_dump 1 demo::run        - вывод (подробный) ключей, содержащих DEMO::RUN
  @smiuisrv_fsm_dump 1 demo::run ^class - вывод (подробный) ключей, содержащих DEMO::RUN и не содержащих CLASS
  



procedure fsm_add_iparam(ref:Integer; name:String; data:Integer);
procedure fsm_add_fparam(ref:Integer; name:String; data:Real);
procedure fsm_add_sparam(ref:Integer; name:String; data:String);
procedure fsm_put_iparam(ref:Integer; name:String; data:Integer);
procedure fsm_put_fparam(ref:Integer; name:String; data:Real);
procedure fsm_put_sparam(ref:Integer; name:String; data:String);
function fsm_ask_iparam(ref:Integer; name:String):Integer;
function fsm_ask_fparam(ref:Integer; name:String):Real;
function fsm_ask_sparam(ref:Integer; name:String):String;
Процедуры и функции для добавления (add), записи (put) и запроса (ask) значения параметров разного типа (int,float,string) с именем (name) в контейнерном элементе (ref). Базовые функции чтения/записи (get/set) FSM API используют для обращения к параметрам ссылки, а не имена, что не всегда бывает удобно. Эти процедуры позволяют использовать параметры удобной для программирования форме. Например:
   obj:=fsm_find(fsm,'DEMO::LOGGER');      // Найти ссылку объекта DEMO::LOGGER
   fsm_add_iparam(obj,'RUN_NUMBER',123);   // Задать параметр int RUN_NUMBER = 123
   run:=fsm_ask_iparam(obj,'RUN_NUMBER');  // Прочитать параметр RUN_NUMBER
  
Следует иметь в виду, что функции доступа к параметрам по имени (ask/add/put) работают несколько медленнее, чем функции доступа к параметрам по ссылке (get/set). При необходимости высокоскоростной обработки предпочтение надо отдавать работе по ссылкам. Кроме того, функции (ask/add/put) регистрируют счетчик ошибки при неверном доступе (несуществующий параметр или неверный тип).


function fsm_get_cookies(ref:Integer):String;
function fsm_get_cookie(ref:Integer; name:String):String;
procedure fsm_set_cookie(ref:Integer; name,value:String);
Функции чтения/записи дополнительных данных (cookie) с именем (name) и значением (value) для контейнерного элемента со ссылкой (ref). Дополнительные данные (Куки) отличаются от регулярных параметров (parameter). Во-первых, Куки - это всегда строковые данные (параметры бывают разных типов). Во-вторых, доступ к Кукам намного "дороже" по времени, т.к. они хранятся в одной длинной строке (fsm_ctrl(ref,'cookie')) в виде списка строк (name=value), разделенных EOL. Поэтому в Куках хранятся данные, которые используются эпизодически, а не постоянно (в цикле опроса). Также надо иметь в виду, что в Куках нельзя гранить строки, содержащие разделитель EOL, т.к. он уже используется для разделения записей Куки. В файлах SML куки сохраняются в виде строк вида !name: value, то есть в комментариях SML (за исключением специальных опций !color:, !visible:, которые обрабатываются особым образом).


procedure fsm_insert_in(ref:Integer; id:String);
procedure fsm_remove_from(ref:Integer; id:String);
procedure fsm_remove_all_from(ref:Integer);
- процедуры вставки(insert)/удаления(remove) объекта или набора объектов с именем (id), в набор объектов со ссылкой (ref). Вставка набора объектов (objectset) возможна, если набор имеет атрибут union, в противном случае предполагается вставка объектов (object).
Процедура fsm_remove_all_from(ref) удаляет все объекты из набора, т.е. очищает его, в результате чего получается пустой набор {}.


function fsm_is_includes(ref:Integer; id:String):Boolean;
- функция проверяет, входит ли объект с именем (id) в набор объектов со ссылкой (ref).


function fsm_validate_dns(ref:Integer; dns:String):String;
Вспомогательная функция, которая корректирует (validate) имя сервера имен (dns). При этом в качестве имени (dns) можно использовать псевдонимы: пустая строка (dns='') задает значение по умолчанию (подставляется hostname), а точка (dns='.') задает полное имя локального компьютера (computername).


function fsm_readback_sml(ref:Integer):String;
Отладочная функция, которая возвращает содержимое Менеджера FSM в виде текста SML. Функция используется для отладочного вывода при разработке прикладного кода.


function fsm_parse_sml(fsm,txt:Integer; domain:String):Integer;
Функция разбора (parse) текста (txt) формата языка SML, в домене (domain) менеджера (fsm). Функция возвращает счетчик ошибок разбора или ноль при успешном разборе текста. В результате разбора содержимого теста создает в домене (domain) элементы и структуры данных, описанные в тексте SML. Обычно функция вызывается не явно, а косвенно, при вызовах fsm_init или fsm_read_sml.


function fsm_read_sml(fsm:Integer; domain,sml:String):Integer;
Функция чтения (read) файла с именем (sml) в формате языка SML, в (существующем) домене (domain) менеджера (fsm). Функция возвращает счетчик ошибок чтения и разбора или ноль при успешном чтении и разборе текста. В результате разбора содержимого файла создает в домене (domain) элементы и структуры данных, описанные в файле SML. Обычно функция вызывается не явно, а косвенно, при вызове fsm_init.


procedure ClearFsmManager;
procedure InitFsmManager;
procedure FreeFsmManager;
procedure PollFsmManager;
Стандартные процедуры очистки/инициализации/завершения/опроса модуля FsmManager. Они должны вызываться так, как показано в шаблоне.


Желаю успешного использования FsmManager!