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;
   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;