Reputation: 375
We are developing a program in Delphi XE5 to monitor MFPs in a local network. It is important that for each incoming SNMP trap notification we are able to determine the MFP that sent it. It seems that TIdSNMP.ReceiveTrap places each notification that was received since the last call into an element of the TIdSNMP.Trap.Value array property; TIdSNMP.Trap.Host then contains the IP address of the MFP which sent the latest trap notification. Can somebody confirm this? Is there some way to obtain the IP addresses corresponding to the other elements of TIdSNMP.Trap.Value?
For testing purposes we are using the following code to receive and display SNMP trap messages:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages,
System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
IdBaseComponent, IdComponent, IdUDPBase, IdUDPClient, IdSNMP;
type
TForm1 = class(TForm)
Button2: TButton;
IdSNMP1: TIdSNMP;
Memo1: TMemo;
procedure Button2Click(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button2Click(Sender: TObject);
procedure FormatTrap(ASnmpInfo : TSnmpInfo);
var
i : integer;
begin
Memo1.Lines.Add('{');
with ASnmpInfo do begin
Memo1.Lines.Add(Format('Host=%s, ', [Host]));
Memo1.Lines.Add(Format('Port=%d, ', [Port]));
Memo1.Lines.Add(Format('Enterprise=%s, ', [Enterprise]));
Memo1.Lines.Add(Format('GenTrap=%d, ', [GenTrap]));
Memo1.Lines.Add(Format('SpecTrap=%d, ', [SpecTrap]));
Memo1.Lines.Add(Format('Version=%d, ', [Version]));
Memo1.Lines.Add(Format('PDUType=%d, ', [PDUType]));
Memo1.Lines.Add(Format('TimeTicks=%d, ', [TimeTicks]));
Memo1.Lines.Add(Format('ID=%d, ', [ID]));
Memo1.Lines.Add(Format('ErrorStatus=%d, ', [ErrorStatus]));
Memo1.Lines.Add(Format('ErrorIndex=%d, ', [ErrorIndex]));
Memo1.Lines.Add(Format('Community=%s, ', [Community]));
Memo1.Lines.Add(Format('ValueCount=%d, ', [ValueCount]));
for i := 0 to ValueCount-1 do begin
Memo1.Lines.Add( Format('Value[%d]=%s, ', [i,Value[i]]));
Memo1.Lines.Add( Format('ValueOID[%d]=%s, ', [i,ValueOID[i]]));
Memo1.Lines.Add( Format('ValueType[%d]=%d, ', [i,ValueType[i]]));
end;
Memo1.Lines.Add('}');
end;
end;
begin
while not Application.Terminated do begin
if IdSNMP1.ReceiveTrap() then begin
FormatTrap(IdSNMP1.Trap);
end;
Sleep(100);
Application.ProcessMessages();
end;
end;
end.
Two MFPs -- a Konica Minolta bizhub C364e under 192.168.197.159 and a Konica Minolta bizhub C364 under 192.168.197.19 -- have been configured to send SNMP trap notifications to the computer this program is running on. Here are some sample results:
{
Host=192.168.197.159,
Port=32884,
Enterprise=1.3.6.1.4.1.18334,
GenTrap=6,
SpecTrap=10,
Version=0,
PDUType=164,
TimeTicks=7792839,
ID=0,
ErrorStatus=0,
ErrorIndex=0,
Community=public,
ValueCount=5,
Value[0]=No Paper,
ValueOID[0]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2,
ValueType[0]=4,
Value[1]=No Paper,
ValueOID[1]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2,
ValueType[1]=4,
Value[2]=No Paper,
ValueOID[2]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2,
ValueType[2]=4,
Value[3]=No Paper,
ValueOID[3]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2,
ValueType[3]=4,
Value[4]=Job End,
ValueOID[4]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2,
ValueType[4]=4,
}
{
Host=192.168.197.19,
Port=53365,
Enterprise=1.3.6.1.4.1.18334,
GenTrap=6,
SpecTrap=10,
Version=0,
PDUType=164,
TimeTicks=12469234,
ID=0,
ErrorStatus=0,
ErrorIndex=0,
Community=public,
ValueCount=6,
Value[0]=No Paper,
ValueOID[0]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2,
ValueType[0]=4,
Value[1]=No Paper,
ValueOID[1]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2,
ValueType[1]=4,
Value[2]=No Paper,
ValueOID[2]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2,
ValueType[2]=4,
Value[3]=No Paper,
ValueOID[3]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2,
ValueType[3]=4,
Value[4]=Job End,
ValueOID[4]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2,
ValueType[4]=4,
Value[5]=Job End,
ValueOID[5]=1.3.6.1.4.1.18334.1.1.1.2.1.83.3.1,
ValueType[5]=4,
}
1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2 is the SysObjectID for C364e and 1.3.6.1.4.1.18334.1.1.1.2.1.83.3.1 the SysObjectID for C364. So it seems that all but the very last notification comes from the MFP under 192.168.197.159, although for the last 6 notifications TIdSNMP.Trap.Host contains the value 192.168.197.19.
Upvotes: 0
Views: 3797
Reputation: 597550
What you describe looks like a bug in TIdSNMP.ReceiveTrap()
. It is not calling TIdSNMP.Trap.Clear()
each time. It is not supposed to keep a history of received traps over time. I have just checked in a fix into Indy's SVN. If you do not want to, or cannot, upgrade your Indy install, a simple workaround would be to call IdSNMP1.Trap.Clear()
before calling IdSNMP1.ReceiveTrap()
:
while not Application.Terminated do begin
IdSNMP1.Trap.Clear(); // <-- add this
if IdSNMP1.ReceiveTrap() then begin
FormatTrap(IdSNMP1.Trap);
end;
Sleep(100);
Application.ProcessMessages();
end;
With that said, using a busy loop inside a UI click handler is not a good idea. I would suggest you use a TTimer
instead:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages,
System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
Vcl.ExtCtrls, IdBaseComponent, IdComponent, IdUDPBase, IdUDPClient, IdSNMP;
type
TForm1 = class(TForm)
Button2: TButton;
IdSNMP1: TIdSNMP;
Memo1: TMemo;
Timer1: TTimer;
procedure Button2Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button2Click(Sender: TObject);
begin
Timer1.Interval := 100;
Timer1.Enabled := True;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
procedure FormatTrap(ASnmpInfo : TSnmpInfo);
var
i : integer;
begin
Memo1.Lines.BeginUpdate;
try
Memo1.Lines.Add('{');
Memo1.Lines.Add(Format('Host=%s, ', [ASnmpInfo.Host]));
Memo1.Lines.Add(Format('Port=%d, ', [ASnmpInfo.Port]));
Memo1.Lines.Add(Format('Enterprise=%s, ', [ASnmpInfo.Enterprise]));
Memo1.Lines.Add(Format('GenTrap=%d, ', [ASnmpInfo.GenTrap]));
Memo1.Lines.Add(Format('SpecTrap=%d, ', [ASnmpInfo.SpecTrap]));
Memo1.Lines.Add(Format('Version=%d, ', [ASnmpInfo.Version]));
Memo1.Lines.Add(Format('PDUType=%d, ', [ASnmpInfo.PDUType]));
Memo1.Lines.Add(Format('TimeTicks=%d, ', [ASnmpInfo.TimeTicks]));
Memo1.Lines.Add(Format('ID=%d, ', [ASnmpInfo.ID]));
Memo1.Lines.Add(Format('ErrorStatus=%d, ', [ASnmpInfo.ErrorStatus]));
Memo1.Lines.Add(Format('ErrorIndex=%d, ', [ASnmpInfo.ErrorIndex]));
Memo1.Lines.Add(Format('Community=%s, ', [ASnmpInfo.Community]));
Memo1.Lines.Add(Format('ValueCount=%d, ', [ASnmpInfo.ValueCount]));
for i := 0 to ASnmpInfo.ValueCount-1 do begin
Memo1.Lines.Add( Format('Value[%d]=%s, ', [i,ASnmpInfo.Value[i]]));
Memo1.Lines.Add( Format('ValueOID[%d]=%s, ', [i,ASnmpInfo.ValueOID[i]]));
Memo1.Lines.Add( Format('ValueType[%d]=%d, ', [i,ASnmpInfo.ValueType[i]]));
end;
Memo1.Lines.Add('}');
finally
Memo1.Lines.EndUpdate;
end;
end;
begin
IdSNMP1.Trap.Clear();
if IdSNMP1.ReceiveTrap() then begin
FormatTrap(IdSNMP1.Trap);
end;
end;
end.
Upvotes: 2