Hi,
some year ago I developed a program to control my fish tank with a Raspberry Pi...it controls water temperature, pH, lights.
Some days ago I implemented also to receive power consumption data of my house from a 2nd Raspberry that is connected to a SDM120C.
Those data are displayed to the "fish tank" Raspberry through a 7" LCD display.
Data are received through a TCP communication (using lNet components) where the 2nd raspberry is the TCP Server and the "fish tank" raspberry is the TCP client, data are shown on request (by clicking on a button on the main Form) where a TTimer is activated and every 10 seconds request data to the TCP server.
The "polling cycle" is the following:
- TCP Client is created
- it connects to the TCP server
- acquires data
- closes the connection
- the "TLTCP" derived object is freed.
- waits 10 seconds and the cycle start again
Now the problem....if I keep the "power" monitoring active, after a certain time the error in the subject appears then I must close the program and open it again or reboot the "fish tank" raspberry.
Trying to find the problem, I launched the command "ls -l /proc/24130/fd" (where "24130" is the PID of the program) after activating "power" monitoring and I found that there are an increasing number of lines "anon_inode:[eventpoll]" that stops only when I stop the TCP connection (thus the "power" monitoring).
This the code of the TCP Client:
Class definition
Type
TPwrThread= class
private
IP: string;
status: string;
datiStr: string;
porta: integer;
FCon : TLTcp; //client TCP
procedure Scrivi2Log(str: string);
function GetAppDirec(): string;
procedure OnDs(aSocket: TLSocket); //disconnessione dal server
procedure OnRe(aSocket: TLSocket); //ricezione da server
procedure OnEr(const msg: string; aSocket: TLSocket); //errori
procedure ElaboraDati();
procedure SetStatus();
protected
procedure Run;
public
Constructor Create(IPAddr: string; port: integer);
destructor Destroy; override;
end;
constructor TPwrThread.Create(IPAddr: string; port: integer);
begin
//costruttore classe
IP:= IPAddr;
porta:= port;
//TCP client creation
FCon := TLTCP.Create(nil);
FCon.OnError := @OnEr; // assign callbacks
FCon.OnReceive := @OnRe;
FCOn.OnDisconnect := @OnDs;
FCon.Timeout := 100; // responsive enough, but won't hog cpu
//inherited Create(CreateSuspended);
end;
destructor TPwrThread.Destroy;
begin
try
FCon.Free; // free the connection
except
//
end;
inherited Destroy;
end;
procedure TPwrThread.OnDs(aSocket: TLSocket);
begin
//Scrivi2Log('Perso connessione a server');
status:= 'non connesso';
frmMain.lbTCPSrv.Caption:= status;
//Synchronize(@SetStatus);
end;
procedure TPwrThread.OnRe(aSocket: TLSocket);
var
s: string;
begin
//ricezione dati da server
if aSocket.GetMessage(s) > 0 then
begin
datiStr:= s;
//flDati:= true;
end;
end;
procedure TPwrThread.OnEr(const msg: string; aSocket: TLSocket);
begin
//errori vari
Scrivi2Log(msg); // if error occured, write it
frmMain.lbTCPSrv.Caption:= msg;
//Synchronize(@SetStatus);
end;
procedure TPwrThread.Run;
begin
//esecuzione thread
//connetto al TCP server
if FCon.Connect(IP, porta) then
begin
//attende connessione al TCP server
repeat
FCon.CallAction; // wait for "OnConnect"
Sleep(1);
Application.ProcessMessages;
until FCon.Connected;
status:= 'connesso';
frmMain.lbTCPSrv.Caption:='connesso';
//Synchronize(@SetStatus);
//invio richiesta dati al TCP server
datiStr:='';
FCon.SendMessage('*d'); //sends the data request to the server
FCon.CallAction; // eventize lNet loop
//elaboro i dati ricevuti
ElaboraDati;
end;
FCon.Disconnect(true);
FCon.Free;
//Scrivi2Log('Thread TCP Client terminato');
end;
Main program timer to read data
procedure TfrmMain.tmPwrTimer(Sender: TObject);
begin
//power data reading
tmPwr.Enabled:= false;
PWR := TPwrThread.Create('192.168.1.122', 5050);
PWR.Run;
PWR.Free;
tmPwr.Enabled:= true;
end;
Data are reading in the "TPwrThread" class, basically it's a string that contains values as voltage, current, power.
The procedure "ElaboraDati" takes the "data string" received in "OnRe(aSocket: TLSocket)" and assigns each value to some labels to the main Form.
What could be causing that error?
It seems that the socket or the connection is not closed and in some way that allocates "open files" until the limit is reached, then the error.
Thank you
Roberto