unit ZdvaCtrl;

interface

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

type

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

  TZdvaCtrlFrame = class(TFrame)
    NamePanel: TPanel;
    DatPanel: TPanel;
    SostPanel1: TPanel;
    BlokButton: TSpeedButton;
    Label2: TLabel;
    ChannelPanel: TPanel;
    ChnlListBox: TListBox;
    btChnlClose: TButton;
    Panel1: TPanel;
    Label4: TLabel;
    bt0: TVisButton;
    bt1: TVisButton;
    bt2: TVisButton;
    bt3: TVisButton;
    lb1: TVisLabel;
    lb2: TVisLabel;
    Panel2: TPanel;
    pnlParams: TPanel;
    Bevel4: TBevel;
    Label1: TLabel;
    dbrdParams: TVisDataboard;
    btParams: TBitBtn;
    pnlNotes: TPanel;
    SostPanel: TLabel;
    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);
  private
    FMessageTag: string;

    FSost: integer;
    FControl: integer;
    FBlok: integer;

    FTagSost: integer;
    FTagControl: integer;
    FTagBlok: integer;
//    FTagFlags: integer;

    FChnl: array of TZdvaCtrlChnlRec;

    tagname: string;

  public
    M: TVisZdva;

    procedure Init;
    procedure Process;
  end;

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

{$R *.DFM}

{ TZdvaCtrlFrame }


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

  tagname := 'ZDVA_' + 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 := M.StateOpen;
  bt3.CaptionDown := M.StateOpen;
  bt3.Init;

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

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

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

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

  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;

  Process;
end;

procedure TZdvaCtrlFrame.Process;
var
  i, k, value: integer;
begin
  bt0.Process;
  bt1.Process;
  bt2.Process;
  bt3.Process;
  lb1.Process;
  lb2.Process;



  value := GetTagValue( FTagSost );
  if value <> FSost then begin
    case Value of
      0: SostPanel.Caption := M.StateMid + #13'(жду '+M.StateClose+')';
      4: SostPanel.Caption := M.StateMid + #13'(жду '+M.StateOpen+')';
      1: SostPanel.Caption := M.StateClose;
      6: SostPanel.Caption := M.StateOpen;
      5: SostPanel.Caption := M.StateClose + #13'(жду '+M.StateOpen+')';
      2: SostPanel.Caption := M.StateOpen + #13'(жду '+M.StateClose+')';
      3,7: SostPanel.Caption := 'Ошибка';
        8: SostPanel.Caption := 'Адрес';
    end;
    FSost := value;

    if value in [0,4,5,2] then begin
      SostPanel.Top := 6;
      SostPanel.Height := 35;
    end else begin
      SostPanel.Top := 14;
      SostPanel.Height := 16;
    end;
  end;
{
    '0 - среднее (жду закр)'#13+
    '1 - закр              '#13+
    '2 - откр    (жду закр)'#13+
    '3 - ошибка            '#13+
    '4 - среднее (жду откр)'#13+
    '5 - закр    (жду откр)'#13+
    '6 - откр              '#13+
    '7 - ошибка            '#13+
    '8 - неправильный адрес'
}
  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 TZdvaCtrlFrame.NamePanelClick(Sender: TObject);
begin
  ShowTrendWindow(
    M.DeviceName,
    GetTagName(FTagSost),
    '',
    'zdva_',
    '',
    'Состояние: '#13+
    '0 - '+M.StateMid+' (жду '+M.StateClose+')'#13+
    '1 - '+M.StateClose+' '#13+
    '2 - '+M.StateOpen+' (жду '+M.StateClose+')'#13+
    '3 - ошибка '#13+
    '4 - '+M.StateMid+' (жду '+M.StateOpen+')'#13+
    '5 - '+M.StateClose+' (жду '+M.StateOpen+')'#13+
    '6 - '+M.StateOpen+' '#13+
    '7 - ошибка '#13+
    '8 - неправильный адрес'
  );

end;

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

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

  if ((isModeUserEx) and (not isPermitted(ClassName + '~' + NamePanel.Caption + '~' + (Sender as TSpeedButton).Caption + '~' + blokstr))) or
     ((not isModeUserEx) and (not CheckAccess(PREVILEG_BLOK, true))) then
  begin
    BlokButton.Down := not BlokButton.Down;
    exit;
  end;

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

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



procedure TZdvaCtrlFrame.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 TZdvaCtrlFrame.btChnlCloseClick(Sender: TObject);
begin
  ChannelPanel.Visible := false;
end;

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

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

procedure TZdvaCtrlFrame.bt0CanClick(Sender: TObject; var Can: Boolean);
begin
  can := false;
  if not isManualAccessIgnore(M.DeviceName) then begin
//    if isModeUserEx then
//      Can := isPermitted(ClassName + '~' + NamePanel.Caption + '~Режим работы~' + (Sender as TVisButton).CaptionDown);

    if (isModeUserEx) and (not isPermitted(ClassName + '~' + NamePanel.Caption + '~Режим работы~' + (Sender as TVisButton).CaptionDown)) then
      exit;

    if (not isModeUserEx) and (not CheckAccess(PREVILEG_MCHMODE, true)) then
      exit;

  end;
  can := true;

  // ВЫПИЛИТЬ!!!
  // говнокод от Леши
  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);
    end;

end;

procedure TZdvaCtrlFrame.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('out2 - Управление "' + m.StateClose + '";' + tagname + 'Chnl2Out;A;;0');
  dbrdParams.DataPar.Add('out1 - Управление "' + m.StateOpen + '";' + tagname + 'Chnl1Out;A;;0');
  dbrdParams.DataPar.Add('in2 - Датчик "' + m.StateClose + '";' + tagname + 'Chnl2In;A;;0');
  dbrdParams.DataPar.Add('in1 - Датчик "' + m.StateOpen + '";' + tagname + 'Chnl1In;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 (out1-откр out2-закр),4=1 (out1-закр/откр),8=2 (out1 и out2 не используются);0;1');
  dbrdParams.DataPar.Add('Режимы входов датчиков положения;' + tagname + 'Flags;& 48;0=0 (in1-откр in2-закр),16=1 (in1-откр in2-откр),32=2 (in1-закр/откр);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 + 'DlyAlarm;;;0');
  dbrdParams.DataPar.Add('Макс.время сигнала управления, с;' + tagname + 'TimeOut;;;0');
  dbrdParams.DataPar.Add('Выход управления Control;' + tagname + 'Control;;;0');




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


end.
