Ciao a tutti.
Ho due applicazioni, su cui girano due comunicazioni, una su CanBus e una su tcpip.
Devo sviluppare una applicazione( o servizio) in stile tcpGateway, cioè tutto quello che arriva da canbus, devo girarlo su tcpip e tutto quello
che arriva su tcpip devo rigirarlo su canbus.
Sull applicazione client, viene usato il componente Clientsocket che interpreta quello che arriva e lo rimanda al tcpGateway.(oppiure manda direttamente sei messaggi al tcpGateway.
Sul tcpGateway quindi uso il componente serversocket, sull'evento onclientread manda su canbus sottoforma di array il dato che riceve.
il codice è il seguente:
procedure TfrmMain.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
const
cMethodName = 'TfrmMain.ServerSocket1ClientRead';
var
p: PCANAtom;
hdrArray: array [0..7] of byte;
canArray: array [0..15] of byte;
dataArray: array [0..7] of byte;
msgArray: array [0..24] of byte;
msgArrayrec: array [0..24] of byte;
i: Integer;
identifier: cardinal;
pdo, varId: Word;
hdr: String;
hexArray: string;
begin
try
try
// Azzeramento dell'array
FillChar(msgArray, SizeOf(msgArray), 0);
if Socket.ReceiveBuf (msgArray[0], length (msgArray)) = length (msgArray) then
begin
new (p);
p^ := TCANAtom.Create;
for i := 0 to 7 do
begin
hdrArray[i] := msgArray[i];
end;
SetString(hdr, PAnsiChar(@hdrArray[0]), Length(hdrArray));
if (Trim(Uppercase(hdr)) <> Trim(UpperCase(cMsgHeader1))) then
begin
Exit;
end;
for i := 8 to Length(msgArray) - 1 do
begin
canArray[i - 8] := msgArray[i];
end;
for i := 0 to 7 do
begin
dataArray[i] := canArray[8 + i];
end;
// IDE
p^.setIDE(True);
// PDO
pdo := ((canArray[1] shl 8) or canArray[0]) shr 7;
// RTR
if ((canArray[2] and $1) = $1) then
begin
p^.setRTR(True);
end
else
begin
p^.setRTR(False);
end;
// DLC
p^.setDLC(canArray[6]);
// Unit and VarId
varId := (canArray[5] shl 8) or canArray[4];
p^.setBytes(pdo, canArray[7], varId, canArray[6], dataArray);
// Confirmation Request
if ((canArray[3] and $1) = $1) then
begin
p^.setConfirmationRequest(True);
end
else
begin
p^.setConfirmationRequest(False);
end;
// Send Message on CAN
communicationInputList.add(p);
ourCanInterface.addToOutputList(p);
hexArray:='';
for i := 0 to Length(msgArrayrec) - 1 do
begin
hexArray := hexArray + '$' + IntToHex(msgArrayrec[i], 2) + ', ';
end;
// Rimuovi l'ultima virgola e lo spazio
Delete(hexArray, Length(hexArray) - 1, 2);
hexArray:='Ricevuto: '+hexArray;
Memo2.Lines.Add(hexArray);
end
else
begin
ourLogger.DbgLog.LogMsg('Unknown message received', eDebugLvlError, cMethodName);
end;
except
on e: Exception do
begin
ourLogger.DbgLog.LogMsg('Exception processing received message: ' + e.Message,
eDebugLvlError, cMethodName);
end;
end;
finally
p.Free;
end;
end;
mentre per mandare su tcp cio che arriva da canbus :
procedure TfrmMain.SendSocketMsg;
const
cMethodName = 'TfrmMain.SendSocketMsg';
var
p: PCANAtom;
// msgArray: TBytes;
msgArray: array [0..24] of byte;
hdrArray: TArray<Byte>;
wrd: Word;
i, iHdrLen: Integer;
hexArray: string;
begin
if not myIsClientConnected then
begin
Exit;
end;
//
try
try
p := communicationInputList.getFirstOut;
//SetLength(msgArray, 23);
hdrArray := TEncoding.UTF8.GetBytes(cMsgHeader1);
iHdrLen := Length(hdrArray);
for i := 0 to iHdrLen - 1 do
begin
msgArray[i] := hdrArray[i];
end;
// PDO
wrd := p^.getPDO shl 7;
msgArray[iHdrLen] := byte(wrd);
msgArray[iHdrLen + 1] := byte(wrd shr 8);
// RTR
if p^.getRTR then
begin
msgArray[iHdrLen + 2] := 1;
end
else
begin
msgArray[iHdrLen + 2] := 0;
end;
// Reply
if p^.getConfirmationRequest then
begin
msgArray[iHdrLen + 3] := 1;
end
else
begin
msgArray[iHdrLen + 3] := 0;
end;
// VarId
wrd := p^.getVariableCode;
msgArray[iHdrLen + 4] := byte(wrd);
msgArray[iHdrLen + 5] := byte(wrd shr 8);
// DLC
msgArray[iHdrLen + 6] := p^.getDLC;
// Unit
msgArray[iHdrLen + 7] := p^.getUnitNumber;
// Data
p^.dataToByteArray(msgArray, iHdrLen + 8);
//
// ServerSocket1.Socket.Connections[0].SendBuf(msgArray[0], Length(msgArray));
i:=ServerSocket1.Socket.Connections[0].SendBuf(msgArray, Length(msgArray));
for i := 0 to Length(msgArray) - 1 do
begin
hexArray := hexArray + '$' + IntToHex(msgArray[i], 2) + ', ';
end;
// Rimuovi l'ultima virgola e lo spazio
Delete(hexArray, Length(hexArray) - 1, 2);
Memo1.Lines.Add('inviato: (' + hexArray + ')');
//
myAnyMessageReadyToSend := True;
except
on e: Exception do
begin
ourLogger.DbgLog.LogMsg('Exception sending Socket message: ' + e.Message,
eDebugLvlError, cMethodName);
end;
end;
finally
end;
end;
dove la SendSocketMsg dovrebbe scatenarsi ad ogni messaggio che arriva da canbus:
procedure OnCanManagerMsg(var Msg: TMessage); message WM_CAN_MANAGER;
ourCanInterface := TCANCommunicator.Create(Self.Handle, WM_CAN_MANAGER);
procedure TfrmMain.OnCanManagerMsg(var Msg: TMessage);
begin
try
SendSocketMsg;
finally
Msg.Result := 1;
end;
end;
quindi ad ogni messaggio di ourCanInterface in pratica chiama la sendsocketmsg e fin qui credo che funzioni.
Il problema è che credo che l invio sia decisamente lento in quanto sull applicazione client al ricecvimento dei dati da tcpip fa altre cose
ma sembra che i messaggi arrivino davvero in maniera ritardata,
da dire che potrebbero arrivare anche 30 messaggi al secondo, ma spero non sia un grosso problema, o perlomeno lo credevo.
Il problema credo sia lato gateway perche il client ora sta andando se configurato per funziona re con una scheda hardware che in pratica fa esattamente la stessa cosa del gateway, ma in queto caso i messaggi arrivano velocemente, quindi credo e spero che il problema sia lato server(tcpgateway), ma non saprei come risolvere data la ‘semplicità’ dell'oggetto serversocket.