Examples - SNMP - Manager

Top  Previous  Next

//-----------------------------------------------------------------------------
// LEDmanager.vpl, created 2020-02-19 15:58
//
// This program demonstrates communication between two RTCU devices, where one
// is the manager (trap listener) and the other a client (publishing agent).
//
// To visualize the communication, the LEDs of both devices are manipulated
// by each other. The manager initiates by setting a pablished integer variable
// on the client, which then updates it's LEDs according to the value written,
// and then sends a trap to the manager, that updates it's LEDs accordingly and
// writes the next value to the other LED on the client, which again responds
// with a trap, which the manager uses to update it's LEDs with and so on.
//-----------------------------------------------------------------------------
INCLUDE rtcu.inc
 
// Use LAN1
#DEFINE SNMP_INTERFACE 2
 
// Exchange this with your real enterprise OID base.
#DEFINE ENTERPRISE_OID "1.3.6.1.4.1.65500."
 
// Put the actual IP address and port of the client here.
#DEFINE SNMP_CLIENT_IP          "192.168.1.20" // example IP
#DEFINE SNMP_CLIENT_PORT        161
 
#DEFINE rwusername               "roed"
#DEFINE sysUpTime                "1.3.6.1.2.1.1.3.0"
#DEFINE usmStatsUnknownEngineIDs "1.3.6.1.6.3.15.1.1.4.0"
 
VAR_OUTPUT
  ledAgreen : BOOL;
  ledAred   : BOOL;
  ledBgreen : BOOL;
  ledBred   : BOOL;
END_VAR;
 
VAR
netInfo    : netGetInformation;
snmpvar    : snmpVariable;
iface      : SINT := SNMP_INTERFACE;
ledA       : INT; // 0=off, 1=green, 2=red, 3=yellow
ledB       : INT; // 0=off, 1=green, 2=red, 3=yellow
END_VAR;
 
FUNCTION printNetInfo
netInfo(iface:=iface);
DebugFmt(message:="Network interface \1:", v1:=iface);
CASE netInfo.status OF
    0 : DebugMsg(message:="Interface is not present.");
    1 : DebugMsg(message:="Interface is not opened.");
    2 : DebugMsg(message:="Interface is not clientconected.");
    3 : DebugMsg(message:="Interface is clientconected.");
    4 : DebugMsg(message:="Interface link is up and waiting for IP configuration.");
ELSE
    DebugFmt(message:="Illegal net status? (\1)", v1:=netInfo.status);
END_CASE;
IF netInfo.status > 1 THEN
  DebugMsg(message:=" Phy addr " + netInfo.phy_addr);
  IF netInfo.dhcp THEN
      DebugMsg(message:=" Dynamic IP address");
  ELSE
      DebugMsg(message:=" Static IP address");
  END_IF;
  DebugMsg(message:=" IP addr " + sockIPToName(ip := netInfo.ip));
  DebugMsg(message:=" Mask    " + sockIPToName(ip := netInfo.subnetMask));
  DebugMsg(message:=" Gateway " + sockIPToName(ip := netInfo.gateway));
  IF netInfo.AutoDNS THEN
      DebugMsg(message:=" Automatic DNS");
  ELSE
      DebugMsg(message:=" Manual DNS");
  END_IF;
  DebugMsg(message:=" DNS1    " + sockIPToName(ip := netInfo.DNS1));
  DebugMsg(message:=" DNS2    " + sockIPToName(ip := netInfo.DNS2));
END_IF;
END_FUNCTION;
 
FUNCTION updateLeds;
VAR_INPUT
  ledA : INT;
  ledB : INT;
END_VAR;
  CASE ledA OF
    0:
    ledAgreen := OFF;
    ledAred := OFF;

    1:
    ledAgreen := ON;
    ledAred := OFF;
    2:
    ledAgreen := OFF;
    ledAred := ON;
    3:
    ledAgreen := ON;
    ledAred := ON;
  ELSE
  END_CASE;
 
  CASE ledB OF
    0:
    ledBgreen := OFF;
    ledBred := OFF;
    1:
    ledBgreen := ON;
    ledBred := OFF;
    2:
    ledBgreen := OFF;
    ledBred := ON;
    3:
    ledBgreen := ON;
    ledBred := ON;
  END_CASE;
  UPDATEIO;
END_FUNCTION;
 
 
PROGRAM LEDmanager;
VAR
  deleteuser : snmpUser;
  rwuser     : snmpUser;
  trapd      : SYSHANDLE;
  clientcon  : SYSHANDLE;
  str        : STRING;
  val        : DINT;
  rc         : INT;
  oid        : STRING;
  vars       : INT;
  ix         : SINT;
  event      : USINT;
  x          : DINT;
END_VAR;
ledA := 0;
ledB := 0;
updateLeds(ledA:=ledA, ledB:=ledB);
 
rc := netOpen(iface:=iface);
DebugFmt(Message:="netOpen (rc=\1)", v1:=rc);
 
WHILE NOT netConnected(iface:=iface) DO
  Sleep(Delay:=2000);
END_WHILE;
 
// Output network information
printNetInfo();
 
// Preemptively delete persistent users.
deleteuser.username := "";
FOR ix:=1 TO 25 DO
  snmpUserSet(index:=ix, user:=deleteuser);
END_FOR;
 
// Configure read-write user
rwuser.username := rwusername;
rwuser.password := "deor1234";
rwuser.cryptkey := "a0b3d543";
rwuser.authentication := _SNMP_USM_MD5;
rwuser.encryption := _SNMP_USM_AES;
rwuser.level := _SNMP_SEC_ENC;
rwuser.engineid := "12345678900001030507";
 
// Set USM users
rc := snmpUserSet(index:=1, user:=rwuser);
IF rc <> 1 THEN
  DebugFmt(message:="Failed to set snmp user (rc=\1)", v1:=rc);
END_IF;
 
// Start the trap listener
rc := snmpStartListen(
                    handle := trapd,
                    version:= _SNMP_VER_3
                    );
DebugFmt(message:="snmpStartListen (rc=\1)", v1:=rc);
 
// Register traps to listen for
rc := snmpRegisterTrap(oid:=ENTERPRISE_OID + "100");
DebugFmt(message:="snmpRegisterTrap (rc=\1)", v1:=rc);
rc := snmpRegisterTrap(oid:=ENTERPRISE_OID + "101");
DebugFmt(message:="snmpRegisterTrap (rc=\1)", v1:=rc);
 
// Setup connection to the client
rc := snmpConnect(
                host    := SNMP_CLIENT_IP,
                port    := SNMP_CLIENT_PORT,
                version := _SNMP_VER_3,
                usmuser := ADDR(rwuser),
                handle  := clientcon
                );
DebugFmt(message:="snmpConnect (rc=\1)", v1:=rc);
 
// Start the test by setting a variable on the client
snmpSetInteger(handle:=clientcon, OID:=ENTERPRISE_OID + "1.1.0", v:=1);
IF rc <> 1 THEN
  DebugFmt(message:="Failed to set variable! snmpSetInteger (rc=\1)", v1:=rc);
END_IF;
 
BEGIN
// Handle events
  rc := snmpWaitEvent(timeout:=-1, event:=event, oid:=oid, vars:=vars);
  CASE event OF
    _SNMP_EVENT_NOEVENT :
        CASE rc OF
            0: DebugMsg(message:="ERROR: The function is not supported!");
          -2: DebugMsg(message:="ERROR: Invalid input");
          -5: DebugMsg(message:="WARNING: Event buffer overflow.");
        ELSE
          DebugFmt(message:="ERROR: unknown return code from snmpReadEvent (rc=\1)", v1:=rc);
        END_CASE;
    _SNMP_EVENT_TIMEOUT :
        DebugMsg(message:="snmpWaitEvent: Timeout!");
    _SNMP_EVENT_TRAP :
        DebugMsg(message:="Trap received!");
        DebugMsg(message:="Trap oid is: " + oid);
        DebugFmt(message:="Vars to read : \1", v1:=vars);
    _SNMP_EVENT_SET :
        DebugMsg(message:="Set request received on OID " + oid);
  ELSE
    DebugFmt(message:="ERROR: snmpWaitEvent - unknown event type \1!", v1:=event);
  END_CASE;
  rc := 0;
  WHILE NOT(rc = -11) DO
    rc := snmpGetNextVar(data:=snmpvar);
    CASE rc OF
      0: DebugMsg(message:="snmpGetNextVar: Function not implemented!");
    -2: DebugMsg(message:="Invalid parameter.");
    -9: DebugFmt(message:="Invalid variable type \1", v1:=snmpvar.type);
    -11:
    1:
        CASE snmpvar.type OF
          1: DebugFmt(message:="TimeTicks received = \4", v4:=snmpvar.time_value);
          2: DebugFmt(message:="INTEGER received = \4", v4:=snmpvar.int_value);
          3: DebugFmt(message:="UNSIGNED INTEGER received = \4", v4:=snmpvar.uint_value);
          4: DebugFmt(message:="STRING received = " + snmpvar.str_value);
          5: DebugFmt(message:="Hex STRING received = " + snmpvar.hex_value);
          6: DebugFmt(message:="OID received = " + snmpvar.oid_value);
          7: DebugFmt(message:="IP Address received = " + snmpvar.ip_value);
          8: DebugFmt(message:="FLOAT received = " + floatToStr(v:=snmpvar.float_value) );
          9: DebugFmt(message:="DOUBLE received = " + doubleToStr(v:=snmpvar.double_value) );
        ELSE
          DebugFmt(message:="Unknown var type received : \1", v1:=snmpvar.type);
        END_CASE;
        IF strCompare(str1:=snmpvar.oid, str2:="." + ENTERPRISE_OID + "100.1") = 0 THEN
          ledA := INT(snmpvar.int_value);
          updateleds(ledA:=ledA, ledB:=ledB);
          snmpGetString(handle:=clientcon, OID:=ENTERPRISE_OID + "2.1.0", v:=str);
          DebugMsg(message:="Client LED " + str);
          x := (snmpvar.int_value + 1) MOD 4;
          snmpSetInteger(handle:=clientcon, OID:=ENTERPRISE_OID + "1.2.0", v:=x);
        END_IF;
        IF strCompare(str1:=snmpvar.oid, str2:="." + ENTERPRISE_OID + "100.2") = 0 THEN
          ledB := INT(snmpvar.int_value);
          updateleds(ledA:=ledA, ledB:=ledB);
          snmpGetString(handle:=clientcon, OID:=ENTERPRISE_OID + "2.2.0", v:=str);
          DebugMsg(message:="Client LED "+str);
          x := (snmpvar.int_value + 1) MOD 4;
          snmpSetInteger(handle:=clientcon, OID:=ENTERPRISE_OID + "1.1.0", v:=x);
        END_IF;
        DebugMsg(message:="Variable OID was : " + snmpvar.oid);
    ELSE
        DebugFmt(Message:="snmpGetNextVar (rc=\1)", v1:=rc);
    END_CASE;
  END_WHILE;
END;
END_PROGRAM;