unit zdvbCtrl;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls, Buttons, Viszdvb, ScadaBase, VisButton, VisLabel,
  VisDataboard, VisControl;

type

  TzdvbCtrlChnlRec = record
    Name: string;
    tagidx: integer;
    tagvalue: integer;
    use: boolean;
  end;

  TzdvbCtrlFrame = class(TFrame)
    NamePanel: TPanel;
    DatPanel: TPanel;
    SostPanel: TPanel;
    BlokButton: TSpeedButton;
    Label2: TLabel;
    ChannelPanel: TPanel;
    ChnlListBox: TListBox;
    btChnlClose: TButton;
    Panel1: TPanel;
    Label4: TLabel;
    bt0: TVisButton;
    bt1: TVisButton;
    bt2: TVisButton;
    bt3: TVisButton;
    bt4: TVisButton;
    lb1: TVisLabel;
    lb2: TVisLabel;
    Panel2: TPanel;
    pnlParams: TPanel;
    Bevel4: TBevel;
    Label1: TLabel;
    dbrdParams: TVisDataboard;
    btParams: TBitBtn;
    TimePanel: TPanel;
    procedure NamePanelClick(Sender: TObject);
    procedure ChannelLabelClick(Sender: TObject);
    procedure BlokButtonClick(Sender: TObject);
    procedure ChnlListBoxDblClick(Sender: TObject);
    procedure btChnlCloseClick(Sender: TObject);
    procedure ChnlListBoxKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btModeClick(Sender: TObject);
    procedure bt0CanClick(Sender: TObject; var Can: Boolean);
    procedure btParamsClick(Sender: TObject);
    procedure TimePanelClick(Sender: TObject);
  private
    FMessageTag: string;

    FSost: integer;
    FOpen: integer;
    FClose: integer;
    FControl: integer;
    FBlok: integer;

    FTagSost: integer;
    FTagControl: integer;
    FTagBlok: integer;
    FTagClosed: integer;
    FTagOpened: integer;


    FTagTimeOpen : integer;
    FTagTime100Proc : integer;
    FTagProc : integer;


//    FTagFlags: integer;

    FChnl: array of TzdvbCtrlChnlRec;

    tagname: string;

  public
    M: TViszdvb;

    procedure Init;
    procedure Process;
  end;

implementation
uses
  RpVisualGlobal,
  RpVisualUtils,
  UserControlEx,
  Users,
  TrendWindow,
  MesConst,
  TagStorage,
  DatSetPanel,
  MesLogging,
  SetChannel,
  numbers;

{$R *.DFM}

{ TzdvbCtrlFrame }

procedure TzdvbCtrlFrame.Init;
var
  s: string;
  i: integer;
begin
  NamePanel.Caption := M.DeviceName;
  SetLength(FChnl, 4);

  tagname := 'zdvb_' + M.TagName + '_';
  s := tagname + 'Control';

  bt0.TagPath := M.TagPath;
  bt0.TagName := s ;
  bt0.Init;

  bt1.TagPath := M.TagPath;
  bt1.TagName := s ;
  bt1.Init;

  bt2.TagPath := M.TagPath;
  bt2.TagName := s ;
  bt2.CaptionUp := M.StateClose;
  bt2.CaptionDown := M.StateClose;
  bt2.Init;

  bt3.TagPath := M.TagPath;
  bt3.TagName := s ;
  bt3.CaptionUp := 'Открыть частично';
  bt3.CaptionDown := 'Открыть частично';
  bt3.Init;

  bt4.TagPath := M.TagPath;
  bt4.TagName := s ;
  bt4.CaptionUp := 'Открыть полностью';
  bt4.CaptionDown := 'Открыть полностью';
  bt4.Init;

  lb1.TagPath := M.TagPath;
  lb1.TagRoot := M.TagName;
  lb1.Init;

  lb2.TagPath := M.TagPath;
  lb2.TagRoot := M.TagName;
  lb2.Init;

  s := M.TagPath + '.zdvb_' + M.TagName;

  FTagSost := GetTagIndex(s + '_Sost');

  FTagClosed := GetTagIndex(s + '_Closed');
  FTagOpened := GetTagIndex(s + '_Opened');

  FTagControl := GetTagIndex(s + '_Control');
  FTagBlok := GetTagIndex(s + '_Blok');
  FMessageTag := M.DeviceName;


  FTagTimeOpen := GetTagIndex(s + '_TimeOpen');
  FTagTime100Proc := GetTagIndex(s + '_Time100Proc');
  FTagProc := GetTagIndex(s + '_Proc');



  with FChnl[0] do begin
    name := 'Упр ' + M.StateClose;
    tagidx := GetTagIndex(s + '_Chnl2Out');
    tagvalue := -1;
    use := M.ChnlOutNum=2;
  end;

  with FChnl[1] do begin
    name := 'Упр ' + M.StateOpen;
    tagidx := GetTagIndex(s + '_Chnl1Out');
    tagvalue := -1;
    use := M.ChnlOutNum>0;
  end;

  with FChnl[2] do begin
    name := 'Дат ' + M.StateClose;
    tagidx := GetTagIndex(s + '_Chnl2In');
    tagvalue := -1;
    use := M.ChnlInNum=2;
  end;
  with FChnl[3] do begin
    name := 'Дат ' + M.StateOpen;
    tagidx := GetTagIndex(s + '_Chnl1In');
    tagvalue := -1;
    use := true;
  end;



  ChnlListBox.Items.Clear;

  for i:=0 to 3 do
    if FChnl[i].use then
      ChnlListBox.Items.AddObject(FChnl[i].Name + ': ' , TObject(i));

  FBlok := -1;
  FControl := -1;
  FSost := -1;
  FOpen := -1;
  FClose := -1;

  Process;
end;

procedure TzdvbCtrlFrame.Process;
var
  i, k, value, valueo, valuec: integer;
begin
  bt0.Process;
  bt1.Process;
  bt2.Process;
  bt3.Process;
  bt4.Process;

  lb1.Process;
  lb2.Process;



  value  := GetTagValue( FTagSost   );
  valuec := GetTagValue( FTagClosed );
  valueo := GetTagValue( FTagOpened );


  if (value <> FSost) OR (valueo <> FOpen) OR (valuec <> FClose) then begin
    if (valuec > 0) and (valueo > 0) then SostPanel.Caption := 'Залип конечник'
      else
        begin

          case Value of
            88: SostPanel.Caption := 'Неверный адрес';
            30: SostPanel.Caption := 'Инициализация';
             0:  SostPanel.Caption := 'Ждем команды';

            15,25:  SostPanel.Caption := 'Закрываем';
            17,27:  SostPanel.Caption := M.StateClose;
            18,28:  SostPanel.Caption := 'Не закрылась';

            11,21:  SostPanel.Caption := 'Открываем частично';

            10,20:  SostPanel.Caption := 'Предв. Закрытие';
            19,29:  SostPanel.Caption := 'Нет предв. Закр.';

            16,26:  SostPanel.Caption := M.StateOpen + ' частично';

            12,22:  SostPanel.Caption := 'Открываем полн.';

            14,24:  SostPanel.Caption := M.StateOpen + ' полн.';
            13,23:  SostPanel.Caption := 'Не открылась';
          end;



        end;

    FSost := value;
    FOpen := valueo;
    FClose := valuec;
  end;



  value  := GetTagValue( FTagTime100Proc   );
  if value > 0 then
    begin
      //Режим работы по процентам
      valuec := GetTagValue( FTagProc );
      if valuec >= 0 then TimePanel.Caption := 'Процент открывания: ' + inttostr(valuec) + '%'
                     else TimePanel.Caption := 'Процент открывания: ????';

    end
  else
    begin
      //Режим по времени
      valuec := GetTagValue( FTagTimeOpen );
      if valuec >= 0 then TimePanel.Caption := 'Время открывания: ' + inttostr(valuec) + ' сек'
                     else TimePanel.Caption := 'Время открывания: ????';
    end;




  value := GetTagValue( FTagBlok );
  if value <> FBlok then begin
    if value > 0 then begin
      BlokButton.Down := true;
      BlokButton.Font.Style := [fsBold];
    end else begin
      BlokButton.Down := false;
      BlokButton.Font.Style := [];
    end;
    FBlok := value;
  end;

  for i:=0 to 3 do begin
    value := GetTagValue( FChnl[i].tagidx );
    if value <> FChnl[i].tagvalue then begin

      k := ChnlListBox.Items.IndexOfObject(TObject(i));

      if k<>-1 then
        ChnlListBox.Items[k] := copy(ChnlListBox.Items[k], 1,
            pos(':', ChnlListBox.Items[k])+1) +  StringOfChar(' ', 15-length(FChnl[i].Name)) + // '        ' +
            IntToStr(value shr 8) + '-' +
            IntToStr(value and $7F) + iif((value and $80)>0, 'f','');

      FChnl[i].tagvalue := value;
    end;
  end;

end;




procedure TzdvbCtrlFrame.NamePanelClick(Sender: TObject);
begin
  ShowTrendWindow(
    M.DeviceName,
    GetTagName(FTagSost),
    '',
    'zdvb_',
    '',
    'Состояние: '#13+
    '30 - Инициализация'#13+
    '0  - Ждем команды'#13+
    '88 - неверный адрес (входа или выхода)'#13+
    ' При автоматическом режиме: '#13+
    '  10 - команда на закрытие (при DoOpen=1), т.е. предварительное закрытие перед будущим открытием'#13+
    '  11 - команда на открытие (при DoOpen=1)'#13+
    '  12 - идет открытие до конечника'#13+
    '  13 - открытие до конечника закончилось неудачей'#13+
    '  14 - удачно закончилось открытие до конечника'#13+
    '  15 - команда на закрытие (при DoOpen=0)'#13+
    '  16 - открытие при DoOpen=1 завершилось, ждем дальнейших команд'#13+
    '  17 - команда на закрытие (при DoOpen=0) выполнена успешно'#13+
    '  18 - команда на закрытие (при DoOpen=0) закончилась ошибкой'#13+
    '  19 - команда на открытие (при DoOpen=1) закончилась ошибкой предварительного закрытия'#13+
    ' При ручном режиме:'#13+
    '  20 - команда на закрытие (при DoOpen=1), т.е. предварительное закрытие перед будущим открытием'#13+
    '  21 - команда на открытие (при DoOpen=1)'#13+
    '  22 - идет открытие до конечника'#13+
    '  23 - открытие до конечника закончилось неудачей'#13+
    '  24 - удачно закончилось открытие до конечника'#13+
    '  25 - команда на закрытие (при DoOpen=0)'#13+
    '  26 - открытие при DoOpen=1 завершилось, ждем дальнейших команд'#13+
    '  27 - команда на закрытие (при DoOpen=0) выполнена успешно'#13+
    '  28 - команда на закрытие (при DoOpen=0) закончилась ошибкой'#13+
    '  29 - команда на открытие (при DoOpen=1) закончилась ошибкой предварительного закрытия'
  );

end;

procedure TzdvbCtrlFrame.ChannelLabelClick(Sender: TObject);
begin
  ChannelPanel.Visible := not ChannelPanel.Visible;
end;

procedure TzdvbCtrlFrame.BlokButtonClick(Sender: TObject);
var
  blokstr: string;
begin
  if GetTagValue(FTagBlok) = 0 then
    blokstr := 'Вкл'
  else
    blokstr := 'Выкл';

  if isModeUserEx then
    if not isPermitted(ClassName + '~' + NamePanel.Caption + '~' + (Sender as TSpeedButton).Caption + '~' + blokstr) then
      Exit;


  SaveMessageText(mcBlok_text, FMessageTag, blokstr, mcBlok_bc, mcBlok_fc);

  SetTagValue( FTagBlok, (GetTagValue(FTagBlok) xor 1) );
end;



procedure TzdvbCtrlFrame.ChnlListBoxDblClick(Sender: TObject);
var
  i: integer;
begin
  if ChnlListBox.ItemIndex = -1 then exit;


  i := integer(pointer(ChnlListBox.Items.Objects[ChnlListBox.ItemIndex]));
  if i=-1 then exit;

  SetChannelForm.Channel := FChnl[i].tagvalue;
  SetChannelForm.DeviceName := FChnl[i].Name;

  if isModeUserEx then
    if not isPermitted(ClassName + '~Установка адреса~' + FChnl[i].Name ) then
      exit;


    if SetChannelForm.ShowModal = mrOk then begin

      SaveMessageText(mcSetChannel_text, FMessageTag,
          IntToStr(SetChannelForm.Channel shr 8) + '-' +
          IntToStr(SetChannelForm.Channel and $7F) +
          iif((SetChannelForm.Channel and $80)>0, 'f',''), mcSetChannel_bc, mcSetChannel_fc);

      SetTagValue( FChnl[i].tagidx, SetChannelForm.Channel );
    end;

end;

procedure TzdvbCtrlFrame.btChnlCloseClick(Sender: TObject);
begin
  ChannelPanel.Visible := false;
end;

procedure TzdvbCtrlFrame.ChnlListBoxKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if key = 13 then ChnlListBoxDblClick(nil);
end;

procedure TzdvbCtrlFrame.btModeClick(Sender: TObject);
begin
//
  with sender as TVisButton do
  begin
    SaveMessageText('Изменение положения задвижки', FMessageTag, CaptionDown, mcMode_bc, mcMode_fc);
  end
end;

procedure TzdvbCtrlFrame.bt0CanClick(Sender: TObject; var Can: Boolean);
begin
//  M
  if isModeUserEx then
    Can := isPermitted(ClassName + '~' + NamePanel.Caption + '~Режим работы~' + (Sender as TVisButton).CaptionDown);
  if ((Can)and(lb1.Visible=true)) then
    with Sender as TVisButton do
    begin
       if((Name='bt0')and(M.PosAShowMsg))then Can:=(MessageDlg('Задвижка может использоваться в маршруте, повернуть?',mtConfirmation,[mbYes, mbNo],0) = mrYes);
       if((Name='bt2')and(M.Pos1ShowMsg))then Can:=(MessageDlg('Задвижка может использоваться в маршруте, повернуть?',mtConfirmation,[mbYes, mbNo],0) = mrYes);
       if((Name='bt3')and(M.Pos2ShowMsg))then Can:=(MessageDlg('Задвижка может использоваться в маршруте, повернуть?',mtConfirmation,[mbYes, mbNo],0) = mrYes);
       if((Name='bt4')and(M.Pos2ShowMsg))then Can:=(MessageDlg('Задвижка может использоваться в маршруте, повернуть?',mtConfirmation,[mbYes, mbNo],0) = mrYes);
    end;

end;

procedure TzdvbCtrlFrame.btParamsClick(Sender: TObject);
//var
//  Flags,
//  i: integer;
begin
  if isModeUserEx then begin
    if not isPermitted(M.ClassName + '~' + M.DeviceName + '~Параметры') then
      exit;
  end else
    if not CheckAccess(PREVILEG_SET_PARAMETERS, true) then
      exit;

//  Flags := GetTagValueByName( tagname + 'Flags' );

  dbrdParams.Caption := M.DeviceName;
  dbrdParams.DataPar.Clear;

  dbrdParams.DataPar.Add('Адреса ввода/вывода;;;;0');
  dbrdParams.DataPar.Add('out1 - Управление Закрыто;' + tagname + 'Chnl1Out;A;;0');
  dbrdParams.DataPar.Add('out2 - Управление Открыто;' + tagname + 'Chnl2Out;A;;0');
  dbrdParams.DataPar.Add('in1 - Датчик Закрыто;' + tagname + 'Chnl1In;A;;0');
  dbrdParams.DataPar.Add('in2 - Датчик Открыто;' + tagname + 'Chnl2In;A;;0');

  dbrdParams.DataPar.Add('Параметры управления и контроля;;;;0');

  dbrdParams.DataPar.Add('Режимы выходов управления;' + tagname + 'Flags;& 3;0=0 (закр/откр),1=1 (откр/закр),2=2 (закр+откр);0;1');
  dbrdParams.DataPar.Add('Режимы входов сигналов;' + tagname + 'Flags;& 12;0=0 (закр/откр),4=1 (откр/закр),8=2 (закр+откр);0;1');
  dbrdParams.DataPar.Add('Выставляь выхода в сработку;' + tagname + 'Flags;& 16;0=0 (по 0),16=1 (по 1);0;1');
  dbrdParams.DataPar.Add('Сработка входов по занчению;' + tagname + 'Flags;& 32;0=0 (по 0),32=1 (по 1);0;1');


  dbrdParams.DataPar.Add('Открытие на угол по ;' + tagname + 'Flags;& 64;0=0 (по времени),64=1 (по резистору);0;1');

  dbrdParams.DataPar.Add('Процент открытия брать ;' + tagname + 'Flags;& 128;0=0 (из выхода),128=1 (из входа);0;1');

  dbrdParams.DataPar.Add('Время открытия, с;' + tagname + 'TimeOpen;;;0');

  dbrdParams.DataPar.Add('Макс.время сигнала закрытия, с;' + tagname + 'MaxCloseTime;;;0');
  dbrdParams.DataPar.Add('Макс.время сигнала открытия, с;' + tagname + 'MaxOpenTime;;;0');

  dbrdParams.DataPar.Add('Время полного открытия, с;' + tagname + 'Time100Proc;;;0');
  dbrdParams.DataPar.Add('Процент открытия, %;' + tagname + 'Proc;;;0');

  dbrdParams.DataPar.Add('Текущий процент открытия, %;' + tagname + 'RealProc;;;0');

  dbrdParams.DataPar.Add('Выход управления Control;' + tagname + 'Control;;;0');

  dbrdParams.DataPar.Add('Значение с резистора, которое соотвествует "Закрыто";' + tagname + 'CloseVal;;;0');
  dbrdParams.DataPar.Add('Значение с резистора, которое соотвествует "Открыто";' + tagname + 'OpenVal;;;0');

  dbrdParams.DataPar.Add('Текущее значение резистора;' + tagname + 'Value;;;0');


//    dbrdParams.DataPar.Add('Режим;MCHB_^_Flags;& 3;0=тип упр1,1=тип упр2,2=индикация,3=эмуляция;0;1');

  {
  if not M.OnlyDat then begin
    if (flags and 3) = 0 then begin
      dbrdParams.DataPar.Add('Управление;MCHB_^_Channel1;A;;0');
      dbrdParams.DataPar.Add('Контроль;MCHB_^_Channel2;A;;0');
    end;

    if (flags and 3) = 1 then
      dbrdParams.DataPar.Add('Управление/Контроль;MCHB_^_Channel1;A;;0');

    if (flags and 3) = 2 then
      dbrdParams.DataPar.Add('Контроль;MCHB_^_Channel1;A;;0');
  end;

  for i:=0 to M.DatCount-1 do
    dbrdParams.DataPar.Add(M.Datchik[i].Name + ';MDTA_^' + M.Datchik[i].TagPostfix + '_Channel;A;;0');
}


//    dbrdParams.DataPar.Add('Время останова, с;MCHB_^_TimeStop;;;0');

{
  for i:=0 to M.DatCount-1 do begin
    dbrdParams.DataPar.Add(M.Datchik[i].Name + ';;;;0');
    dbrdParams.DataPar.Add('Текущее значение (только чтение);MDTA_^' + M.Datchik[i].TagPostfix + '_Value;;;0');
    dbrdParams.DataPar.Add('Не преобразованное значение (только чтение);MDTA_^' + M.Datchik[i].TagPostfix + '_Primeval;;;0');
    dbrdParams.DataPar.Add('Нижний предел;MDTA_^' + M.Datchik[i].TagPostfix + '_Low;;;0');
    dbrdParams.DataPar.Add('Верхний предел;MDTA_^' + M.Datchik[i].TagPostfix + '_High;;;0');
    dbrdParams.DataPar.Add('Задержка предварительная, с;MDTA_^' + M.Datchik[i].TagPostfix + '_DlyDrebezg;;;0');
    dbrdParams.DataPar.Add('Задержка срабатывания, с;MDTA_^' + M.Datchik[i].TagPostfix + '_DlyOutput;;;0');
    dbrdParams.DataPar.Add('Преобразование: треб.значение;MDTA_^' + M.Datchik[i].TagPostfix + '_PointV;;;0;1');
    dbrdParams.DataPar.Add('Преобразование: исход.значение;MDTA_^' + M.Datchik[i].TagPostfix + '_PointP;;;0;1');
    dbrdParams.DataPar.Add('Преобразование: треб.значение1;MDTA_^' + M.Datchik[i].TagPostfix + '_PointV1;;;0;1');
    dbrdParams.DataPar.Add('Преобразование: исход.значение1;MDTA_^' + M.Datchik[i].TagPostfix + '_PointP1;;;0;1');
    dbrdParams.DataPar.Add('Запрет действия при сработке;MDTA_^' + M.Datchik[i].TagPostfix + '_Flags;& 64;0=нет,64=да;1');
    dbrdParams.DataPar.Add('Запрет сигнализации;MDTA_^' + M.Datchik[i].TagPostfix + '_Flags;& 128;0=нет,128=да;1');
  end;
}


  SetPathRootScadaObjects(pnlParams, M.TagPath, M.TagRoot );
  dbrdParams.OnControlClick(sender);
end;

procedure TzdvbCtrlFrame.TimePanelClick(Sender: TObject);
var i, code, value, valuec:integer;
    s : string;
    w:boolean;
begin
  //PREVILEG_SET_PARAMETERS
  if isModeUserEx then begin
    if not isPermitted(M.ClassName + '~' + M.DeviceName + '~ПараметрыВремя') then
      exit;
  end else
    if not CheckAccess(PREVILEG_SET_PARAMETERS, true) then
      exit;




  value  := GetTagValue( FTagTime100Proc   );
  if value > 0 then
    begin
      //Режим работы по процентам
      valuec := GetTagValue( FTagProc );

      s := inttostr(valuec);

      w := InputQuery('Выбор степени открывания задвижки', 'Введите % открытия', s);

      if valuec >= 0 then TimePanel.Caption := 'Процент открывания: ' + inttostr(valuec) + '%'
                     else TimePanel.Caption := 'Процент открывания: ????';

    end
  else
    begin
      //Режим по времени
      valuec := GetTagValue( FTagTimeOpen );
      s := inttostr(valuec);

      w := InputQuery('Выбор степени открывания задвижки', 'Введите время открытия в секундах', s);

    end;


  if w then
   begin
         {$R-}
         Val(s, I, Code);

         if (Code <> 0) or (i < 0) or (i>32768)
           then
             begin
               MessageDlg('Ошибка ввода занчения, введите целое число без букв', mtWarning, [mbOk], 0);
             end
           else
             begin

               if value > 0 then
                 begin
                   SetTagValue( FTagProc, i );
                   SaveMessageText('Сменили % открытия: ', FMessageTag, inttostr(i)+'%', mcBlok_bc, mcBlok_fc);
                 end
               else
                 begin
                   SetTagValue( FTagTimeOpen, i );
                   SaveMessageText('Сменили время открытия: ', FMessageTag, inttostr(i)+' сек',  mcBlok_bc, mcBlok_fc);
                 end;
             end;
   end;



end;

end.
