Client code examples
Simplex OPC UA Client
Simplex OPC UA Client as an example of using the Simplex OPC UA SDK (time-limited evaluation version).
Comes with the source code (Delphi XE 10.2, VCL and FireMonkey).
Supported OPC UA Services:
- CreateSession, ActivateSession, CloseSession
- Browse
- Read, HistoryRead
- Write
- Call
- CreateSubscription, DeleteSubscription
- CreateMonitoredItems, DeleteMonitoredItems
- Publish
Simple client code example
..
uses SysUtils, Simplex.Client, Simplex.Types;
..
var OpcUaClient: TOpcUaClient;
ClientConfig: SpxClientConfig;
begin
try
ClientConfig .EndpointUrl := 'opc.tcp://localhost:4848'
;
ClientConfig .SessionTimeout := 300;
ClientConfig .TraceLevel := tlNone;
ClientConfig .Callback := nil;
OpcUaClient
:=
TOpcUaClient .Create(
ClientConfig
);
if (not
OpcUaClient
.Connect()) then
begin
OpcUaClient
.Free();
Writeln(Format('Error connect to OPC UA server , EndpointUrl=%s ',
[
ClientConfig
.EndpointUrl ]));
Exit;
end;
Writeln(Format('Connect to OPC UA server - OK, EndpointUrl=%s',
[
ClientConfig
.EndpointUrl ]));
OpcUaClient
.Free();
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
|
Advanced client code example
..
uses SysUtils, Simplex.Client, Simplex.Types;
..
var Client: TSimplexClientTest;
// see details below
EndpointUrl: string;
begin
try
EndpointUrl := 'opc.tcp://localhost:4848';
Client := TSimplexClientTest.Create(EndpointUrl);
if (Client.Connect() = False) then
begin
Client.Free();
Writeln(Format('Error connect to OPC UA server, EndpointUrl=%s',
[EndpointUrl]));
Exit;
end;
Writeln(Format('Connect to OPC UA server - OK, EndpointUrl=%s',
[EndpointUrl]));
if (Client.ReadData() = False) then
begin
Client.Free();
Writeln('Error read data from OPC UA server');
Exit;
end;
Writeln('Read data from OPC UA server - OK');
Client.Free();
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
|
SimplexClientTest.pas
unit SimplexClientTest;
{$DEFINE SIMPLEX_SECURITY}
{$DEFINE SIMPLEX_AUTHENTICATION}
interface
uses SysUtils, DateUtils, Simplex.Client, Simplex.Types;
type
TWriteln = procedure(AInfo: string) of object;
TProcessMessages = procedure() of object;
TSimplexClientTest = class(SpxClientCallback)
private
FWriteln: TWriteln;
FProcessMessages: TProcessMessages;
FClient: TOpcUaClient;
FClientConfig: SpxClientConfig;
function ExistServer(AServers: SpxApplicationDescriptionArray): boolean;
function ExistSecurityNone(AEndpoints: SpxEndpointDescriptionArray): boolean;
function GetNodeId(ANamespaceIndex: Word; AIdent: Cardinal): SpxNodeId; overload;
function GetNodeId(ANamespaceIndex: Word; AIdent: string): SpxNodeId; overload;
function GetReadValueId(ANodeId: SpxNodeId): SpxReadValueId;
function GetWriteValue(ANodeId: SpxNodeId; AValue: string): SpxWriteValue;
function GetValue(AValue: string): SpxVariant;
function GetMonitoredItem(ANodeId: SpxNodeId; AClientHandle: Cardinal;
ASamplingInterval: double): SpxMonitoredItem;
function GetModifyItem(AMonitoredItemId: Cardinal; AClientHandle: Cardinal;
ASamplingInterval: double): SpxModifyMonitoredItem;
procedure ConsoleWriteln(AInfo: string);
procedure ConsoleProcessMessages();
private // callbacks
procedure OnChannelEvent(AEvent: SpxChannelEvent; AStatus: SpxStatusCode); override;
procedure OnMonitoredItemChange(ASubscriptionId: SpxUInt32;
AValues : SpxMonitoredItemNotifyArray); override;
procedure OnLog(AMessage: string); override;
procedure OnLogWarning(AMessage: string); override;
procedure OnLogError(AMessage: string); override;
procedure OnLogException(AMessage: string; AException: Exception); override;
public
constructor Create(AEndpointUrl: string); overload;
constructor Create(AEndpointUrl: string; AWriteln: TWriteln;
AProcessMessages: TProcessMessages); overload;
destructor Destroy; override;
function Connect(): boolean;
procedure Disconnect();
function ReadData(): boolean;
end;
implementation
const
FormatDT = 'yy.mm.dd hh:nn:ss.zzz';
Localhost = 'localhost';
VariableClientHandle = 1;
/// <summary>
/// Constructor
/// </summary>
constructor TSimplexClientTest.Create(AEndpointUrl: string);
begin
Create(AEndpointUrl, ConsoleWriteln, ConsoleProcessMessages);
end;
/// <summary>
/// Constructor
/// </summary>
constructor TSimplexClientTest.Create(AEndpointUrl: string; AWriteln: TWriteln;
AProcessMessages: TProcessMessages);
begin
inherited Create();
FWriteln := AWriteln;
FProcessMessages := AProcessMessages;
FClientConfig.EndpointUrl := AEndpointUrl;
FClientConfig.ApplicationInfo.ApplicationName := 'Simplex OPC UA Cllient SDK';
// application uri from ClientCertificate.der
FClientConfig.ApplicationInfo.ApplicationUri := 'urn:localhost:Simplex OPC UA:Client SDK';
FClientConfig.ApplicationInfo.ProductUri := 'urn:Simplex OPC UA:Client SDK';
FClientConfig.ApplicationInfo.ManufacturerName := 'Simplex OPC UA';
FClientConfig.ApplicationInfo.SoftwareVersion := '1.0';
FClientConfig.ApplicationInfo.BuildNumber := '123';
FClientConfig.ApplicationInfo.BuildDate := Now;
FClientConfig.CertificateFileName := '';
FClientConfig.PrivateKeyFileName := '';
FClientConfig.TrustedCertificatesFolder := '';
FClientConfig.ServerCertificateFileName := '';
FClientConfig.Authentication.AuthenticationType := SpxAuthenticationType_Anonymous;
FClientConfig.Authentication.UserName := '';
FClientConfig.Authentication.Password := '';
{$IFDEF SIMPLEX_SECURITY}
FClientConfig.CertificateFileName := 'ClientCertificate.der';
FClientConfig.PrivateKeyFileName := 'ClientPrivateKey.pem';
FClientConfig.TrustedCertificatesFolder := 'TrustedCertificates';
FClientConfig.ServerCertificateFileName := 'TrustedCertificates\ServerCertificate.der';
{$IFDEF SIMPLEX_AUTHENTICATION}
FClientConfig.Authentication.AuthenticationType := SpxAuthenticationType_UserName;
FClientConfig.Authentication.UserName := 'root';
FClientConfig.Authentication.Password := 'secret';
{$ENDIF}
{$ENDIF} FClientConfig.ConnectTimeout := 30; FClientConfig.SessionTimeout := 300;
FClientConfig.TraceLevel := tlDebug;
FClientConfig.Callback := Self;
FClient := TOpcUaClient.Create(FClientConfig);
end;
/// <summary>
/// Destructor
/// </summary>
destructor TSimplexClientTest.Destroy();
begin
FClient.Free();
inherited;
end;
/// <summary>
/// Connect to OPC UA server with security mode - none
/// </summary>
function TSimplexClientTest.Connect(): boolean;
var Servers: SpxApplicationDescriptionArray;
Endpoints: SpxEndpointDescriptionArray;
begin
Result := False;
// connect
{$IFDEF SIMPLEX_SECURITY}
if (not FClient.Connect(SpxMessageSecurityMode_SignAndEncrypt,
SpxSecurityPolicy_Basic128Rsa15)) then Exit;
{$ELSE}
if (not FClient.Connect()) then Exit;
{$ENDIF}
// exist OPC UA server
if (not FClient.FindServers(Servers)) then Exit;
if (not ExistServer(Servers)) then Exit;
// exist endpoint with security mode - none
if (not FClient.GetEndpoints(Endpoints)) then Exit;
if (not ExistSecurityNone(Endpoints)) then Exit;
// init session
if (not FClient.InitSession()) then Exit;
Result := True;
end;
/// <summary>
/// Disconnect from OPC UA server
/// </summary>
procedure TSimplexClientTest.Disconnect();
begin
FClient.Disconnect();
end;
/// <summary>
/// Read data
/// </summary>
function TSimplexClientTest.ReadData(): boolean;
var NodeId: SpxNodeId;
ReadValues: SpxReadValueIdArray;
Values: SpxDataValueArray;
NodesToRead: SpxHistoryReadValueIdArray;
HistoryValues: SpxHistoryReadResultArray;
WriteValues: SpxWriteValueArray;
StatusCodes: SpxStatusCodeArray;
MethodsToCall: SpxCallMethodRequestArray;
MethodResults: SpxCallMethodResultArray;
BrowseDescriptions: SpxBrowseDescriptionArray;
BrowseResults: SpxBrowseResultArray;
Subscription: SpxSubscription;
SubscriptionResult: SpxSubscriptionResult;
SubcriptionId, MonitoredItemId: SpxUInt32;
SubcriptionIds, MonitoredItemIds: SpxUInt32Array;
MonitoredItems: SpxMonitoredItemArray;
MonitoredItemResult: SpxMonitoredItemResultArray;
ModifyItems: SpxModifyMonitoredItemArray;
ModifyItemResult: SpxModifyMonitoredItemResultArray;
ContinuationPoints: SpxByteArrayArray;
i: integer;
EndTime: TDateTime;
begin
Result := False;
// Read current time
NodeId := GetNodeId(0, SpxNodeId_Server_ServerStatus_CurrentTime);
SetLength(ReadValues, 1);
ReadValues[0] := GetReadValueId(NodeId);
if (not FClient.ReadValue(0, SpxTimestampsToReturn_Both, ReadValues, Values)) then Exit;
if (Length(Values) = 0) then Exit;
FWriteln(Format('ReadValue - OK, StatusCode = %u',
[Ord(Values[0].StatusCode)]));
FWriteln(Format('CurrentUtcTime = %s',
[FormatDateTime(FormatDT, Values[0].Value.AsDateTime)]));
// Read history value from Simplex OPC UA Server SDK - see "Advanced server code example"
NodeId := GetNodeId(1, 'MyFolder.MyVarStr');
SetLength(NodesToRead, 1);
NodesToRead[0].NodeId := NodeId;
NodesToRead[0].IndexRange := '';
NodesToRead[0].DataEncoding.NamespaceIndex := 0;
NodesToRead[0].DataEncoding.Name := '';
NodesToRead[0].ContinuationPoint := nil;
if (not FClient.ReadHistory(False, IncHour(Now, -3), Now, 1000, True,
SpxTimestampsToReturn_Both, False, NodesToRead, HistoryValues)) then Exit;
if (Length(HistoryValues) = 0) then Exit;
FWriteln(Format('ReadHistory - OK, StatusCode = %u',
[Ord(HistoryValues[0].StatusCode)]));
for i := Low(HistoryValues[0].HistoryData) to High(HistoryValues[0].HistoryData) do
FWriteln(Format('HistoryValue[%d] = %s',
[i, HistoryValues[0].HistoryData[i].Value.AsString]));
// Write value to Simplex OPC UA Server SDK - see "Advanced server code example"
NodeId := GetNodeId(1, 'MyFolder.MyVarStr');
SetLength(WriteValues, 1);
WriteValues[0] := GetWriteValue(NodeId, 'value123');
if (not FClient.WriteValue(WriteValues, StatusCodes)) then Exit;
if (Length(StatusCodes) = 0) then Exit;
FWriteln(Format('WriteValue - OK, StatusCode = %u',
[Ord(StatusCodes[0])]));
// Call method from Simplex OPC UA Server SDK - see "Advanced server code example"
NodeId := GetNodeId(1, 'MyFolder.MyMethod');
SetLength(MethodsToCall, 1);
MethodsToCall[0].MethodId := NodeId;
MethodsToCall[0].ObjectId := GetNodeId(1, 0);
SetLength(MethodsToCall[0].InputArguments, 2);
MethodsToCall[0].InputArguments[0] := GetValue('One');
MethodsToCall[0].InputArguments[1] := GetValue('Two');
if (not FClient.CallMethod(MethodsToCall, MethodResults)) then Exit;
if (Length(MethodResults) = 0) then Exit;
FWriteln(Format('CallMethod - OK, StatusCode = %u',
[Ord(MethodResults[0].StatusCode)]));
for i := Low(MethodResults[0].OutputArguments) to High(MethodResults[0].OutputArguments) do
FWriteln(Format('MethodOutputArgument[%d] = %s',
[i, MethodResults[0].OutputArguments[i].AsString]));
// Browse from Root
ContinuationPoints := nil;
SetLength(BrowseDescriptions, 1);
BrowseDescriptions[0].NodeId := GetNodeId(0, SpxNodeId_RootFolder);
BrowseDescriptions[0].BrowseDirection := SpxBrowseDirection_Forward;
BrowseDescriptions[0].ReferenceTypeId := GetNodeId(0, SpxNodeId_HierarchicalReferences);
BrowseDescriptions[0].IncludeSubtypes := True;
BrowseDescriptions[0].NodeClassMask := SpxUInt32(SpxNodeClass_Unspecified);
BrowseDescriptions[0].ResultMask := SpxUInt32(SpxBrowseResultMask_All);
while True do
begin
if (Length(ContinuationPoints) = 0) then
begin
if (not FClient.Browse(1000, BrowseDescriptions, BrowseResults)) then Exit;
end
else begin
if (not FClient.BrowseNext(False, ContinuationPoints, BrowseResults)) then Exit;
end;
if (Length(BrowseResults) = 0) then Exit;
FWriteln(Format('Browse - OK, StatusCode = %u',
[Ord(BrowseResults[0].StatusCode)]));
for i := Low(BrowseResults[0].References) to High(BrowseResults[0].References) do
FWriteln(Format('BrowseDisplayName[%d] = %s',
[i, BrowseResults[0].References[i].DisplayName.Text]));
// continue browse (if more than 1000 references)
if (Length(BrowseResults[0].ContinuationPoint) > 0) then
begin
SetLength(ContinuationPoints, 1);
ContinuationPoints[0] := BrowseResults[0].ContinuationPoint;
end
else Break;
end;
// Create subscription
Subscription.RequestedPublishingInterval := 2000;
Subscription.RequestedLifetimeCount := 200;
Subscription.RequestedMaxKeepAliveCount := 20;
Subscription.MaxNotificationsPerPublish := 20000;
Subscription.Priority := 0;
if (not FClient.CreateSubscription(True, Subscription, SubcriptionId,
SubscriptionResult)) then Exit;
FWriteln(Format('CreateSubscription - OK, SubscriptionId = %d, '+
'RevisedPublishingInterval=%f, RevisedLifetimeCount=%d, RevisedMaxKeepAliveCount=%d',
[SubcriptionId, SubscriptionResult.RevisedPublishingInterval,
SubscriptionResult.RevisedLifetimeCount, SubscriptionResult.RevisedMaxKeepAliveCount]));
// Modify subscription
Subscription.RequestedPublishingInterval := 3000;
Subscription.RequestedLifetimeCount := 300;
Subscription.RequestedMaxKeepAliveCount := 30;
Subscription.MaxNotificationsPerPublish := 30000;
Subscription.Priority := 1;
if (not FClient.ModifySubscriptiont(SubcriptionId, Subscription,
SubscriptionResult)) then Exit;
FWriteln(Format('ModifySubscriptiont - OK, RevisedPublishingInterval=%f, '+
'RevisedLifetimeCount=%d, RevisedMaxKeepAliveCount=%d',
[SubscriptionResult.RevisedPublishingInterval, SubscriptionResult.RevisedLifetimeCount,
SubscriptionResult.RevisedMaxKeepAliveCount]));
// Create monitored item
NodeId := GetNodeId(0, SpxNodeId_Server_ServerStatus_CurrentTime);
SetLength(MonitoredItems, 1);
MonitoredItems[0] := GetMonitoredItem(NodeId, VariableClientHandle, 500);
if (not FClient.CreateMonitoredItems(SubcriptionId, SpxTimestampsToReturn_Both,
MonitoredItems, MonitoredItemResult)) then Exit;
if (Length(MonitoredItemResult) = 0) then Exit;
FWriteln(Format('CreateMonitoredItems - OK, StatusCode=%u, MonitoredItemId=%d, '+
'SamplingInterval=%f, QueueSize=%d',
[MonitoredItemResult[0].StatusCode, MonitoredItemResult[0].MonitoredItemId,
MonitoredItemResult[0].SamplingInterval, MonitoredItemResult[0].QueueSize]));
MonitoredItemId := MonitoredItemResult[0].MonitoredItemId;
// Modify monitored item
SetLength(ModifyItems, 1);
ModifyItems[0] := GetModifyItem(MonitoredItemId, VariableClientHandle, 600);
if (not FClient.ModifyMonitoredItems(SubcriptionId, SpxTimestampsToReturn_Both,
ModifyItems, ModifyItemResult)) then Exit;
if (Length(ModifyItemResult) = 0) then Exit;
FWriteln(Format('ModifyMonitoredItems - OK, StatusCode=%u, SamplingInterval=%f, '+
'QueueSize=%d',
[ModifyItemResult[0].StatusCode, ModifyItemResult[0].SamplingInterval,
ModifyItemResult[0].QueueSize]));
// Set monitoring mode
SetLength(MonitoredItemIds, 1);
MonitoredItemIds[0] := MonitoredItemId;
if (not FClient.SetMonitoringMode(SubcriptionId, SpxMonitoringMode_Reporting,
MonitoredItemIds, StatusCodes)) then Exit;
if (Length(StatusCodes) = 0) then Exit;
FWriteln(Format('SetMonitoringMode - OK, StatusCode=%u',
[StatusCodes[0]]));
// Wait for receive data
EndTime := IncSecond(Now, 30);
while (Now < EndTime) do
FProcessMessages();
// Delete monitored item
if (not FClient.DeleteMonitoredItems(SubcriptionId, MonitoredItemIds,
StatusCodes)) then Exit;
if (Length(StatusCodes) = 0) then Exit;
FWriteln(Format('DeleteMonitoredItems - OK, StatusCode=%u',
[StatusCodes[0]]));
// Delete subscription
SetLength(SubcriptionIds, 1);
SubcriptionIds[0] := SubcriptionId;
if (not FClient.DeleteSubscriptions(SubcriptionIds, StatusCodes)) then Exit;
if (Length(StatusCodes) = 0) then Exit;
FWriteln(Format('DeleteSubscriptions- OK, StatusCode = %u',
[Ord(StatusCodes[0])]));
Result := True;
end;
/// <summary>
/// Callback - change channel state
/// </summary>
procedure TSimplexClientTest.OnChannelEvent(AEvent: SpxChannelEvent; AStatus: SpxStatusCode);
begin
if (AEvent = SpxChannelEvent_Disconnected) then
FWriteln('OnChannelEvent: Disconnected');
end;
/// <summary>
/// Callback - change monitored item
/// </summary>
procedure TSimplexClientTest.OnMonitoredItemChange(ASubscriptionId: SpxUInt32;
AValues : SpxMonitoredItemNotifyArray);
var i: integer;
begin
FWriteln(Format('OnMonitoredItemChange: Values.Count=%d',
[Length(AValues)]));
for i := Low(AValues) to High(AValues) do
if (AValues[i].ClientHandle = VariableClientHandle) then
FWriteln(Format('CurrentUtcTime = %s',
[FormatDateTime(FormatDT, AValues[i].Value.Value.AsDateTime)]));
end;
/// <summary>
/// Callback - output trace message
/// </summary>
procedure TSimplexClientTest.OnLog(AMessage: SpxString);
begin
FWriteln(AMessage);
end;
/// <summary>
/// Callback - output warning message
/// </summary>
procedure TSimplexClientTest.OnLogWarning(AMessage: SpxString);
begin
FWriteln(Format('[WARNING] %s',
[AMessage]));
end;
/// <summary>
/// Callback - output error message
/// </summary>
procedure TSimplexClientTest.OnLogError(AMessage: SpxString);
begin
FWriteln(Format('[ERROR] %s',
[AMessage]));
end;
/// <summary>
/// Callback - output exception
/// </summary>
procedure TSimplexClientTest.OnLogException(AMessage: SpxString; AException: Exception);
begin
FWriteln(Format('[EXCEPTION] %s, E.Message=%s',
[AMessage, AException.Message]));
end;
/// <summary>
/// Exist OPC UA server
/// </summary>
function TSimplexClientTest.ExistServer(AServers: SpxApplicationDescriptionArray): boolean;
var i: integer;
begin
Result := False;
for i := Low(AServers) to High(AServers) do
if (AServers[i].ApplicationType = SpxApplicationType_Server) or
(AServers[i].ApplicationType = SpxApplicationType_ClientAndServer) then
begin
Result := True;
Exit;
end;
end;
/// <summary>
/// Exist endpoint with security mode - none
/// </summary>
function TSimplexClientTest.ExistSecurityNone(AEndpoints: SpxEndpointDescriptionArray): boolean;
var i: integer;
begin
Result := False;
for i := Low(AEndpoints) to High(AEndpoints) do
if (AEndpoints[i].SecurityMode = SpxMessageSecurityMode_None) then
begin
Result := True;
Exit;
end;
end;
/// <summary>
/// Get numeric SpxNodeId
/// </summary>
function TSimplexClientTest.GetNodeId(ANamespaceIndex: Word; AIdent: Cardinal): SpxNodeId;
begin
Result.NamespaceIndex := ANamespaceIndex;
Result.IdentifierType := SpxIdentifierType_Numeric;
Result.IdentifierNumeric := AIdent;
end;
/// <summary>
/// Get string SpxNodeId
/// </summary>
function TSimplexClientTest.GetNodeId(ANamespaceIndex: Word; AIdent: string): SpxNodeId;
begin
Result.NamespaceIndex := ANamespaceIndex;
Result.IdentifierType := SpxIdentifierType_String;
Result.IdentifierString := AIdent;
end;
/// <summary>
/// Get parameters for read value
/// </summary>
function TSimplexClientTest.GetReadValueId(ANodeId: SpxNodeId): SpxReadValueId;
begin
Result.NodeId := ANodeId;
Result.AttributeId := SpxAttributes_Value;
Result.IndexRange := '';
Result.DataEncoding.NamespaceIndex := 0;
Result.DataEncoding.Name := '';
end;
/// <summary>
/// Get parameters for write value
/// </summary>
function TSimplexClientTest.GetWriteValue(ANodeId: SpxNodeId; AValue: string): SpxWriteValue;
begin
Result.NodeId := ANodeId;
Result.AttributeId := SpxAttributes_Value;
Result.IndexRange := '';
Result.Value.Value := GetValue(AValue);
Result.Value.StatusCode := SpxStatusCode_Good;
Result.Value.SourceTimestamp := 0;
Result.Value.SourcePicoseconds := 0;
Result.Value.ServerTimestamp := 0;
Result.Value.ServerPicoseconds := 0;
end;
/// <summary>
/// Get value
/// </summary>
function TSimplexClientTest.GetValue(AValue: string): SpxVariant;
begin
Result.ValueRank := SpxValueRanks_Scalar;
Result.BuiltInType := SpxType_String;
Result.AsString := AValue;
end;
/// <summary>
/// Get monitored item
/// </summary>
function TSimplexClientTest.GetMonitoredItem(ANodeId: SpxNodeId;
AClientHandle: Cardinal; ASamplingInterval: double): SpxMonitoredItem;
begin
Result.NodeId := ANodeId;
Result.AttributeId := SpxAttributes_Value;
Result.IndexRange := '';
Result.DataEncoding.NamespaceIndex := 0;
Result.DataEncoding.Name := '';
Result.MonitoringMode := SpxMonitoringMode_Reporting;
Result.ClientHandle := AClientHandle;
Result.SamplingInterval := ASamplingInterval;
Result.QueueSize := 1000;
Result.DiscardOldest := True;
end;
/// <summary>
/// Get modify monitored item
/// </summary>
function TSimplexClientTest.GetModifyItem(AMonitoredItemId: Cardinal;
AClientHandle: Cardinal; ASamplingInterval: double): SpxModifyMonitoredItem;
begin
Result.MonitoredItemId := AMonitoredItemId;
Result.ClientHandle := AClientHandle;
Result.SamplingInterval := ASamplingInterval;
Result.DiscardOldest := True;
end;
/// <summary>
/// Console output
/// </summary>
procedure TSimplexClientTest.ConsoleWriteln(AInfo: string);
begin
Writeln(AInfo);
end;
/// <summary>
/// Console process messages
/// </summary>
procedure TSimplexClientTest.ConsoleProcessMessages();
begin
Sleep(100);
end;
end.
|
Add license code example
1) Copy the license file (license.lic) to the Delphi project directory.
2) Create an text file SimplexLecense.RC, then add line like:
SimplexLicense RCDATA license.lic
3) Add file SimplexLecense.RC to you Delphi project.
4) Use the following code to add licenses:
...
uses Classes, Windows, Simplex.License;
...
function AddLicense(): boolean;
var Stream: TResourceStream;
License: TBytes;
begin
Result := False;
try
Stream := TResourceStream.Create(hInstance, 'SimplexLicense', RT_RCDATA);
SetLength(License, Stream.Size);
Stream.Read(License[0], Stream.Size);
Stream.Free();
if (AddLicence(License) = False) then Exit;
Result := True;
except
end;
end;
|
|
|