- На языке SML описывается логика конечного автомата FSM.
Созданный SML файл нужен также для запуска SMI сервера,
так что создавать его все равно придется.
Например (здесь и далее рассматривается "сборщик событий" EvtBuilder):
object: EVT_BUILDER /associated
parameters: int NUMBER_T, int NUMBER_P
state: DEAD /dead_state !color: DarkGray
state: READY !color: Aqua
action: START(TYPE, int NR)
state: RUNNING !color: Lime
action: STOP
state: ERROR !color: Red
action: RECOVER
|
|
Обратите внимание: цвета состояний объектов можно задавать в SML файле (через !color:).
- Создается DAQ конфигурация, где описываются параметры устройства.
- Включается библиотека SmiProxy:
program SmiProxyEvtBuilder;
const
{------------------------------}{ Declare uses program constants: }
{$I _con_StdLibrary} { Include all Standard constants, }
{------------------------------}{ And add User defined constants: }
{$I _con_SmiProxy} { Include SMI Proxy constants }
var
{------------------------------}{ Declare uses program variables: }
{$I _var_StdLibrary} { Include all Standard variables, }
{------------------------------}{ And add User defined variables: }
{$I _var_SmiProxy} { Include SMI Proxy variables }
................. { User defined variables }
{------------------------------}{ Declare procedures & functions: }
{$I _fun_StdLibrary} { Include all Standard functions, }
{------------------------------}{ And add User defined functions: }
{$I _fun_SmiProxy} { Include SMI Proxy functions }
...
- Создается прикладная процедура SmiProxyLogic с описанием логики конечного автомата:
//
// SMI Proxy Logic.
//
procedure SmiProxyLogic;
var complete:Boolean; typ:String; nr:Integer;
begin
typ:='';
//
// SMI Proxy BUSY operations.
// SMI actions handler there.
//
if smi_proxy_handler_busy then begin
complete:=false;
if smi_test_action('START') then begin
complete:=true;
if complete then begin
KickTime:=mSecNow; // Set marker of START to generate ERROR later for demo
typ:=smi_proxy_handler_params_value_byname('TYPE');
nr:=Val(smi_proxy_handler_params_value_byname('NR'));
if IsSameText(typ,'PHYSICS') then smi_set_par('NUMBER_P',Str(nr+1),SMI_INTEGER);
if IsSameText(typ,'TEST') then smi_set_par('NUMBER_T',Str(nr+1),SMI_INTEGER);
smi_terminate_action('RUNNING');
end;
end else
if smi_test_action('STOP') then begin
complete:=(smi_proxy_handler_uptime>1500);
if complete then begin
KickTime:=0; // Reset marker
smi_terminate_action('READY');
end;
end else
if smi_test_action('RECOVER') then begin
complete:=(smi_proxy_handler_uptime>1500);
if complete then begin
KickTime:=0; // Reset marker
smi_terminate_action('READY');
end;
end else
begin // Unknown action came
KickTime:=0; // Reset marker
smi_terminate_action('ERROR');
Problem('Unknown action came: '+smi_proxy_handler_action);
end;
end else
//
// SMI Proxy IDLE operations.
// Do when actions completed.
//
if smi_proxy_handler_idle then begin
if msElapsedSinceMarker(KickTime)>7000 then begin
smi_set_state('ERROR');
KickTime:=0;
end;
end;
typ:='';
end;
При создании процедуры рекомендуется использовать ранее созданный файл *.SML,
который транслируется в код на языке C с помощью программы smiTrans.exe.
Этот код довольно легко переводится в код DaqPascal (имена основных процедур одинаковы).
Обработка команд SMI осуществляется в блоке smi_proxy_handler_busy,
что означает наличие принятой и необработанной команды.
С помощью функции smi_test_action выясняется, какая команда поступила
и какое действие надо предпринять.
Далее выполняется содержательная работа по выполнению принятой команды.
Когда работа завершена, вызывается функция smi_terminate_action,
которая завершает обработку команды и устанавливает новое состояние объекта.
Обработка фоновых событий, не связанных напрямую с SMI,
осуществляется в блоке smi_proxy_handler_idle,
что означает отсутствие необработанных команд.
- В стандартных местах добавляется вызов процедур очистки ClearSmiProxy,
инициализации InitSmiProxy,
завершения FreeSmiProxy,
опроса PollSmiProxy
и созданной на предыдущем шаге процедуры прикладной логики PollSmiLogic:
{
Clear user application strings...
}
procedure ClearApplication;
begin
ClearSmiProxy;
end;
{
User application Initialization...
}
procedure InitApplication;
begin
StdIn_SetScripts('@StartupScript','@FinallyScript');
StdIn_SetTimeouts(0,60000,0,3000);
iNul(ClickFilter(ClickFilter(1)));
iNul(ClickAwaker(ClickAwaker(1)));
InitSmiProxy;
KickTime:=0;
end;
{
User application Finalization...
}
procedure FreeApplication;
begin
FreeSmiProxy;
end;
{
User application Polling...
}
procedure PollApplication;
begin
PollSmiProxy;
SmiProxyLogic;
end;
- В обработчик консольных команд добавляется вызов smi_proxy_default_handler:
{
Process data coming from standard input...
}
procedure StdIn_Processor(var Data:String);
var cmd,arg:String; cmdid:Integer;
begin
if DebugFlagEnabled(dfViewImp) then ViewImp('CON: '+Data);
{
Handle "@cmd=arg" or "@cmd arg" commands:
}
cmd:='';
arg:='';
if GotCommandId(Data,cmd,arg,cmdid) then begin
{
!!! Handle SMI Proxy by default handler !!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
if smi_proxy_default_handler(Data,cmd,arg,cmdid) then begin
Success(smi_proxy_prompt+Data);
Data:='';
end else
{
Handle other commands by default handler...
}
StdIn_DefaultHandler(Data,cmd,arg);
end;
Data:='';
cmd:='';
arg:='';
end;