⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modlinkdemomain.pas

📁 ModLink VCL component 组件以及代码。版本是shareware edition of ModLink 2.10
💻 PAS
📖 第 1 页 / 共 5 页
字号:
//--------------------------------------------------------------------------------------------------

var
  TransactionLogFileName: TFileName = '';

//--------------------------------------------------------------------------------------------------

function GetTransactionLogFileName: TFileName;
begin
  if TransactionLogFileName = EmptyStr then
    TransactionLogFileName := ExtractFilePath(ParamStr(0)) + 'TransactionLog.txt';
  Result := TransactionLogFileName;
end;

//--------------------------------------------------------------------------------------------------

const
  ServerReplies: array [TServerReply] of string = (
    { srNone            } 'Transaction timed out (no reply)',
    { srInvalidFrame    } 'Transaction timed out (reply frame is corrupted)',
    { srUnexpectedReply } 'Transaction timed out (reply from unexpected server)',
    { srUnmatchedReply  } 'Transaction failed (reply does not match request)',
    { srExceptionReply  } 'Transaction failed (server returned exception reply)',
    { srNormalReply     } 'Transaction succeeded'
  );

//--------------------------------------------------------------------------------------------------

procedure ValidateNumberInEditBox(AEdit: TEdit; MinValue, MaxValue: Int64);

  // begin of local block --------------------------------------------------------------------------

  procedure Error(ResStringRec: PResStringRec; const Args: array of const);
  begin
    {$IFDEF COMPILER_5_UP}
    raise Exception.CreateResFmt(ResStringRec, Args);
    {$ELSE}
    raise Exception.CreateFmt(LoadResString(ResStringRec), Args);
    {$ENDIF COMPILER_5_UP}
  end;

  procedure InvalidInteger;
  begin
    if AEdit.CanFocus then AEdit.SetFocus;
    Error(@SInvalidInteger, [AEdit.Text]);
  end;

  procedure InvalidRange;
  begin
    if AEdit.CanFocus then AEdit.SetFocus;
    Error(@SOutOfRange, [MinValue, MaxValue]);
  end;

  // end of local block ----------------------------------------------------------------------------

var
  I: Int64;
begin
  try
    I := StrToInt64(AEdit.Text);
    if (MinValue <> MaxValue) and ((I < MinValue) or (I > MaxValue)) then
      InvalidRange;
  except
    on E: Exception do
      if E is EConvertError then
      begin
        InvalidInteger;
      end
      else
        raise;
  end;
end;

//--------------------------------------------------------------------------------------------------

{$IFNDEF COMPILER_5_UP}

// FreeAndNil doesn't exist in Delphi 4.
procedure FreeAndNil(var Obj);
var
  TempObj: TObject;
begin
  TempObj := TObject(Obj);
  Pointer(Obj) := nil;
  TempObj.Free;
end;

{$ENDIF COMPILER_5_UP}

//--------------------------------------------------------------------------------------------------
// TModLinkDemoMainForm class
//--------------------------------------------------------------------------------------------------

constructor TModLinkDemoMainForm.Create(AOwner: TComponent);
const
  SIntroductionFileName = 'Introduction.rtf';
begin
  inherited;
  AccessSettings(GetSettingsFileName, LoadSettings);
  ToolsLogTransactionsToFileItem.Checked := fLogTransactionsToFile;

  LogString('');
  if fLogTransactionsToFile then
    LogString('*** Transactions are now being logged to both screen and file.')
  else
    LogString('*** Transactions are now being logged to screen only.');
  LogString('');

  LogString('*** Welcome to demonstration of ModLink VCL component suite!');
  LogString(Format('*** Running on ModLink version %s', [ModLinkVersion]));
  LogString('');
  LogString('*** To specify in which connection mode to operate:');
  LogString('*** [1] Select ''Tools -> Modbus Connection Options...'' from the menu.');
  LogString('*** [2] A dialog will appear.');
  LogString('*** [3] Go to ''Modbus Transaction Management'' page.');
  LogString('*** [4] Locate ''Connection Mode'' group box.');
  LogString('*** [5] Select ''Client'' radio button to operate as local client.');
  LogString('*** [6] Select ''Server'' radio button to operate as local server.');
  LogString('*** [7] Click OK button to close the dialog and apply the changes.');
  LogString('');

  LoadServerItems(GetServerItemsFileName);

  try
    try
      ModbusConnection1.Open;
    except
      on E: Exception do
      begin
        LogString(Format('Failed to open Modbus connection. %s'#13#10, [E.Message]));

        {$IFDEF COMPILER_6_UP}
        if Assigned(ApplicationHandleException) then
          ApplicationHandleException(Self);
        {$ELSE}
        Application.HandleException(Self);
        {$ENDIF}
      end;
    end;
  finally
    ConnectionModeChanged;
    UpdateConnectionStatus;
  end;

  Application.HintHidePause := 20000;

  PageControl1.ActivePage := IntroductionTabSheet;
  RegisterListView.Column[0].Index := 1;
  UpdateDiscreteListView;
  UpdateRegisterListView;

  try
    IntroductionRichEdit.Lines.LoadFromFile(ExtractFilePath(ParamStr(0)) + SIntroductionFileName);
  except
    {$IFDEF COMPILER_6_UP}
    if Assigned(ApplicationHandleException) then
      ApplicationHandleException(Self);
    {$ELSE}
    Application.HandleException(Self);
    {$ENDIF}
  end;
end;

//--------------------------------------------------------------------------------------------------

destructor TModLinkDemoMainForm.Destroy;
begin
  fLogFile.Free;
  inherited;
end;

//--------------------------------------------------------------------------------------------------

procedure TModLinkDemoMainForm.BeginLogTransactions;
var
  OpenMode: Word;
begin
  if not Assigned(fLogFile) then
  begin
    if FileExists(GetTransactionLogFileName) then
      OpenMode := fmOpenReadWrite or fmShareDenyWrite
    else
      OpenMode := fmCreate or fmShareDenyWrite;
    fLogFile := TFileStream.Create(GetTransactionLogFileName, OpenMode);
    fLogFile.Seek(0, soFromEnd);
  end;
  Inc(fLogCounter);
end;

//--------------------------------------------------------------------------------------------------

procedure TModLinkDemoMainForm.ClearTransactionLog;
begin
  LogMemo.Clear;
  if fLogTransactionsToFile then
  begin
    BeginLogTransactions;
    try
      Assert(Assigned(fLogFile));
      fLogFile.Size := 0;
    finally
      EndLogTransactions;
    end;
  end;
end;

//--------------------------------------------------------------------------------------------------

procedure TModLinkDemoMainForm.ConnectionModeChanged;
const
  ConnectionModes: array [TConnectionMode] of string = ('CLIENT', 'SERVER');
begin
  Caption := Format('%s [LOCAL %s MODE]', [Application.Title,
    ConnectionModes[ModbusConnection1.ConnectionMode]]);

  ToolsClientOptionsItem.Visible := ModbusConnection1.ConnectionMode = cmClient;
  ToolsServerOptionsItem.Visible := ModbusConnection1.ConnectionMode = cmServer;
  ToolsDiscardPendingTransactionsItem.Visible := ModbusConnection1.ConnectionMode = cmClient;

  RegisterAccessTabSheet.TabVisible := ModbusConnection1.ConnectionMode = cmClient;
  DiscreteAccessTabSheet.TabVisible := ModbusConnection1.ConnectionMode = cmClient;
  DiagnosticsTabSheet.TabVisible := ModbusConnection1.ConnectionMode = cmClient;
  ServerMapTabSheet.TabVisible := ModbusConnection1.ConnectionMode = cmServer;
end;

//--------------------------------------------------------------------------------------------------

procedure TModLinkDemoMainForm.EditSelectedServerItem;
var
  ListItem: TListItem;
begin
  with ServerItemsListView do
  begin
    ListItem := Selected;
    if Assigned(ListItem) then
    begin
      if EditServerItem(PServerItem(ListItem.Data), False) then
      begin
        SaveServerItems(GetServerItemsFileName);
        UpdateServerItem(ListItem);
      end;
    end
    else
      Beep;
  end;
end;

//--------------------------------------------------------------------------------------------------

procedure TModLinkDemoMainForm.EndLogTransactions;
begin
  if fLogCounter > 0 then
    Dec(fLogCounter);
  if fLogCounter = 0 then
    FreeAndNil(fLogFile);
end;

//--------------------------------------------------------------------------------------------------

function TModLinkDemoMainForm.FindServerItemByAddress(Address: Word; ItemKind: TItemKind): PServerItem;
var
  I: Integer;
  ServerItem: PServerItem;
begin
  Result := nil;
  for I := 0 to ServerItemsListView.Items.Count - 1 do
  begin
    ServerItem := PServerItem(ServerItemsListView.Items[I].Data);
    if (ServerItem^.Addr = Address) and (ServerItem^.Kind = ItemKind) then
    begin
      Result := ServerItem;
      Break;
    end;
  end;
end;

//--------------------------------------------------------------------------------------------------

procedure TModLinkDemoMainForm.LoadServerItems(const aFileName: string);
var
  vStream: TFileStream;
  vCount, I, X: Integer;
  vServerItem: PServerItem;
  vListItem: TListItem;
begin
  ServerItemsListView.Items.Clear;
  if FileExists(aFileName) then
  begin
    vStream := TFileStream.Create(aFileName, fmOpenRead or fmShareDenyWrite);
    try
      ServerItemsListView.Items.BeginUpdate;
      try
        { Obtain the number of server items to be read from the stream }
        vCount := vStream.Size div SizeOf(TServerItem);
        for I := 0 to Pred(vCount) do
        begin
          New(vServerItem);
          try
            LoadServerItem(vServerItem, vStream);
            vListItem := ServerItemsListView.Items.Add;
            try
              for X := 0 to 4 do
                vListItem.SubItems.Add('');
              vListItem.Data := Pointer(vServerItem);
              UpdateServerItem(vListItem);
            except
              ServerItemsListView.Items.Delete(vListItem.Index);
              raise;
            end;
          except
            Dispose(vServerItem);
            raise;
          end;
        end;
      finally
        ServerItemsListView.Items.EndUpdate;
      end;
    finally
      vStream.Free;
    end;
  end;
end;

//--------------------------------------------------------------------------------------------------

procedure TModLinkDemoMainForm.LoadSettings(aIniFile: TCustomIniFile);
const
  cDefaultPort = 'COM1';
begin
  fLogTransactionsToFile := aIniFile.ReadBool(gcGeneral, gcLogTransactionsToFile, False);
  with ModbusConnection1 do
  begin
    BaudRate := TBaudRate(aIniFile.ReadInteger(gcModbusConnection1, gcBaudRate, Ord(br19200)));

    if BaudRate = brCustom then
      CustomBaudRate := Cardinal(aIniFile.ReadInteger(gcModbusConnection1, gcCustomBaudRate, 19200));

    ConnectionMode := TConnectionMode(aIniFile.ReadInteger(gcModbusConnection1, gcConnectionMode, Ord(cmClient)));
    DataBits := TDataBits(aIniFile.ReadInteger(gcModbusConnection1, gcDataBits, Ord(db8)));
    DTREnabled := aIniFile.ReadBool(gcModbusConnection1, gcDTREnabled, True);
    EchoQueryBeforeReply := aIniFile.ReadBool(gcModbusConnection1, gcEchoQryBeforeRpy, False);
    FlowControl := TFlowControl(aIniFile.ReadInteger(gcModbusConnection1, gcFlowControl, Ord(fcNone)));
    MaxRetries := TMaxRetries(aIniFile.ReadInteger(gcModbusConnection1, gcMaxRetries, 1));
    Parity := TParityScheme(aIniFile.ReadInteger(gcModbusConnection1, gcParity, Ord(psEven)));
    Port := aIniFile.ReadString(gcModbusConnection1, gcPort, cDefaultPort);
    ReceiveTimeout := Cardinal(aIniFile.ReadInteger(gcModbusConnection1, gcReceiveTimeout, 1000));
    RefetchDelay := Cardinal(aIniFile.ReadInteger(gcModbusConnection1, gcRefetchDelay, 0));
    RTSEnabled := aIniFile.ReadBool(gcModbusConnection1, gcRTSEnabled, True);
    SendTimeout := Cardinal(aIniFile.ReadInteger(gcModbusConnection1, gcSendTimeout, 1000));
    SilentInterval := Cardinal(aIniFile.ReadInteger(gcModbusConnection1, gcSilentInterval, 4));
    StopBits := TStopBits(aIniFile.ReadInteger(gcModbusConnection1, gcStopBits, Ord(sb1)));
    ThreadPriority := TThreadPriority(aIniFile.ReadInteger(gcModbusConnection1, gcThreadPriority, Ord(tpNormal)));
    TransmissionMode := TTransmissionMode(aIniFile.ReadInteger(gcModbusConnection1, gcTransmissionMode, Ord(tmRTU)));
    TurnaroundDelay := Cardinal(aIniFile.ReadInteger(gcModbusConnection1, gcTurnaroundDelay, 100));
  end;
  ModbusClient1.ServerAddress := aIniFile.ReadInteger(gcModbusClient1, gcServerAddress, 1);
  ModbusServer1.Address := aIniFile.ReadInteger(gcModbusServer1, gcAddress, 1);
end;

//--------------------------------------------------------------------------------------------------

procedure TModLinkDemoMainForm.LogBroadcast;
begin
  LogString('Broadcasting mode: No reply is expected to be returned from a remote server(s).');
end;

//--------------------------------------------------------------------------------------------------

procedure TModLinkDemoMainForm.LogDone(ID: Cardinal; const CmdDesc: string);
begin
  LogString(Format('DONE: %s [ID: %d]', [CmdDesc, ID]));
end;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -