//----------------------------------------------------------------------------- // LEDclient.vpl, created 2020-02-19 13:24 // // 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 of the manager here. #DEFINE MANAGER_IP "192.168.1.10" // example IP // Configure the LEDs 1-4 in the job configuration manager VAR_OUTPUT ledAgreen : BOOL; // LED 1 ledAred : BOOL; // LED 2 ledBgreen : BOOL; // LED 3 ledBred : BOOL; // LED 4 END_VAR; VAR netInfo : netGetInformation; snmpvar : snmpVariable; trapvar : snmpVariable; iface : SINT := SNMP_INTERFACE; runthread : BOOL := FALSE; ledA : INT; ledB : INT; mancon : SYSHANDLE; rouser : snmpUser; rwuser : snmpUser; END_VAR; FUNCTION authToStr : STRING; VAR_INPUT auth : SINT; END_VAR; CASE auth OF 0 : authToStr := ""; _SNMP_USM_MD5 : authToStr := "MD5"; _SNMP_USM_SHA : authToStr := "SHA"; ELSE authToStr := "Unknown???"; END_CASE; END_FUNCTION FUNCTION encToStr : STRING; VAR_INPUT enc : SINT; END_VAR; CASE enc OF 0 : encToStr := ""; _SNMP_USM_AES : encToStr := "AES"; _SNMP_USM_DES : encToStr := "DES"; ELSE encToStr := "Unknown???"; END_CASE; END_FUNCTION FUNCTION levelToStr : STRING; VAR_INPUT level : SINT; END_VAR; CASE level OF _SNMP_SEC_NONE : levelToStr := "None"; _SNMP_SEC_AUTH : levelToStr := "AuthOnly"; _SNMP_SEC_ENC : levelToStr := "Auth+Enc"; ELSE levelToStr := "Unknown???"; END_CASE; END_FUNCTION FUNCTION printUSMUsersInfo; VAR rc : INT; END_VAR rc := snmpAgentUsersGet(readonly:=rouser, writable:=rwuser); DebugFmt(message:="snmpAgentUsersGet (rc=\1)", v1:=rc); DebugMsg(message:="-----------------------------------------"); DebugMsg(message:="Read-Only user:"); DebugMsg(message:="-----------USM user profile--------------"); DebugMsg(message:="Username is : "+rouser.username); DebugMsg(message:="Auth is : "+authToStr(auth:=rouser.authentication)); DebugMsg(message:="Auth pass is : "+rouser.password); DebugMsg(message:="Enc is : "+encToStr(enc:=rouser.encryption)); DebugMsg(message:="Cryptkey is : "+rouser.cryptkey); DebugMsg(message:="Sec level is : "+levelToStr(level:=rouser.level)); DebugMsg(message:="-----------------------------------------"); DebugMsg(message:=""); DebugMsg(message:="Read-Write capable user:"); DebugMsg(message:="-----------USM user profile--------------"); DebugMsg(message:="Username is : "+rwuser.username); DebugMsg(message:="Auth is : "+authToStr(auth:=rwuser.authentication)); DebugMsg(message:="Auth pass is : "+rwuser.password); DebugMsg(message:="Enc is : "+encToStr(enc:=rwuser.encryption)); DebugMsg(message:="Cryptkey is : "+rwuser.cryptkey); DebugMsg(message:="Sec level is : "+levelToStr(level:=rwuser.level)); DebugMsg(message:="-----------------------------------------"); END_FUNCTION; FUNCTION getledstring : STRING; VAR_INPUT idx : SINT; END_VAR; VAR str: STRING; END_VAR CASE idx OF 1 : IF ledAgreen THEN IF ledAred THEN str := "A is yellow"; ELSE str := "A is green"; END_IF; ELSE IF ledAred THEN str := "A is red"; ELSE str := "A is off"; END_IF; END_IF; 2: IF ledBgreen THEN IF ledBred THEN str := "B is yellow"; ELSE str := "B is green"; END_IF; ELSE IF ledBred THEN str := "B is red"; ELSE str := "B is off"; END_IF; END_IF; END_CASE; getledstring := str; 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; 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 connected."); 3 : DebugMsg(message:="Interface is connected."); 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; PROGRAM LEDclient; VAR deleteuser : snmpUser; traphandle : SYSHANDLE; oid : STRING; vars : INT; eventtype : USINT; rc : INT; str : STRING; ix : SINT; END_VAR; ledAgreen := FALSE; ledAred := FALSE; ledBgreen := FALSE; ledBred := FALSE; ledA := 0; ledB := 0; UPDATEIO; rc := netOpen(iface:=iface); DebugFmt(message:="netOpen (rc=\1)",v1:=rc); // 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 := "roed"; 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 user with index 1 snmpUserSet(index:=1, user:=rwuser); WHILE NOT netConnected(iface:=iface) DO Sleep(delay:=2000); END_WHILE; // Output network information printNetInfo(); // Set USM users for the publishing agent rc := snmpAgentUsersSet(writable:=rwuser, readonly:=rouser); DebugFmt(message:="snmpAgentUsersSet (rc=\1)", v1:=rc); // Output USM users for the publishing agent printUSMUsersInfo(); // Setup connection to the manager rc := snmpConnect( handle:=mancon, host:=MANAGER_IP, port:=162, version:=_SNMP_VER_3, engineid := "12345678900001030507", usmuser:=ADDR(rwuser) ); DebugFmt(message:="snmpConnect (rc=\1)", v1:=rc); // Start the publishing agent rc := snmpStartAgent( engineid := "a9382949f343be38", dtls := 0, // disable dtls as we use USM secure := TRUE // only allow secure connections ); DebugFmt(message:="snmpStartAgent (rc=\1)", v1:=rc); // Publish some variables rc := snmpPublishInteger(v:=ledA, oid:=ENTERPRISE_OID + "1.1", subtype:=1, writable:=TRUE); DebugFmt(message:="snmpPublishInteger (rc=\1)", v1:=rc); rc := snmpPublishInteger(v:=ledB, oid:=ENTERPRISE_OID + "1.2", subtype:=1, writable:=TRUE); DebugFmt(message:="snmpPublishInteger (rc=\1)", v1:=rc); rc := snmpPublishString(v:=getledstring(idx:=1), oid:=ENTERPRISE_OID + "2.1", subtype:=0, writable:=TRUE); DebugFmt(message:="snmpPublishString (rc=\1)", v1:=rc); rc := snmpPublishString(v:=getledstring(idx:=2), oid:=ENTERPRISE_OID + "2.2", subtype:=0, writable:=TRUE); DebugFmt(message:="snmpPublishString (rc=\1)", v1:=rc); rc := snmpPublishTimeTicks(v:=boardTimeSinceReset(), oid:=ENTERPRISE_OID + "3", writable:=TRUE); DebugFmt(message:="snmpPublishTimeTicks (rc=\1)", v1:=rc); rc := snmpPublishOID(v:="1.3.6.4.1.5.333.32.2", oid:=ENTERPRISE_OID + "4", writable:=TRUE); DebugFmt(message:="snmpPublishOID (rc=\1)", v1:=rc); rc := snmpPublishIP(v:="192.168.1.255", oid:=ENTERPRISE_OID + "5", writable:=TRUE); DebugFmt(message:="snmpPublishIP (rc=\1)", v1:=rc); rc := snmpPublishFloat(v:=3.1416, oid:=ENTERPRISE_OID + "6", writable:=TRUE); DebugFmt(message:="snmpPublishFloat (rc=\1)", v1:=rc); rc := snmpPublishDouble(v:=3.14159265359, oid:=ENTERPRISE_OID + "7", writable:=TRUE); DebugFmt(message:="snmpPublishDouble (rc=\1)", v1:=rc); BEGIN // Handle events rc := snmpWaitEvent(timeout:=-1, event:=eventtype, oid:=oid, vars:=vars); CASE eventtype 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:=eventtype); 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: DebugMsg(message:="No more data available."); 1: DebugFmt(message:="Type found is \1", v1:=snmpvar.type); 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; DebugMsg(message:="Variable OID was : " + snmpvar.oid); IF strCompare(str1:=snmpvar.oid, str2:=ENTERPRISE_OID + "1.1") = 0 THEN ledA := INT(snmpvar.int_value); updateLeds(ledA:=ledA, ledB:=ledB); rc := snmpPublishString(v:=getledstring(idx:=1), oid:=ENTERPRISE_OID + "2.1", subtype:=0, writable:=TRUE); IF rc <> 1 THEN DebugFmt(message:="snmpPublishString error, rc=\1", v1:=rc); END_IF; rc := snmpcreateTrap(trap:=traphandle, oid:=ENTERPRISE_OID + "100", uptime:=100); trapvar.type := 2; trapvar.oid:=ENTERPRISE_OID + "100.1"; trapvar.int_value := snmpvar.int_value; rc := snmpAddTrapVariable(trap:=traphandle, data:=trapvar); IF rc <> 1 THEN DebugFmt(message:="snmpAddTrapVariable error, rc=\1", v1:=rc); END_IF; rc := snmpSendTrap(trap:=traphandle, connection:=mancon); IF rc <> 1 THEN DebugFmt(message:="Sending of trap failed (rc=\1)", v1:=rc); ELSE DebugFmt(message:="Successfully sendt trap!", v1:=rc); END_IF; rc := snmpDestroyTrap(trap:=traphandle); IF rc <> 1 THEN DebugFmt(message:="snmpDestroyTrap failed (rc=\1)", v1:=rc); END_IF; END_IF; IF strCompare(str1:=snmpvar.oid, str2:=ENTERPRISE_OID + "1.2") = 0 THEN ledB := INT(snmpvar.int_value); updateLeds(ledA:=ledA, ledB:=ledB); rc := snmpPublishString(v:=getledstring(idx:=2), oid:=ENTERPRISE_OID + "2.2", subtype:=0, writable:=TRUE); IF rc <> 1 THEN DebugFmt(message:="snmpPublishString error, rc=\1", v1:=rc); END_IF; rc := snmpcreateTrap(trap:=traphandle, oid:=ENTERPRISE_OID + "101", uptime:=boardTimeSinceReset()); trapvar.type := 2; trapvar.oid:=ENTERPRISE_OID + "100.2"; trapvar.int_value := snmpvar.int_value; rc := snmpAddTrapVariable(trap:=traphandle, data:=trapvar); IF rc <> 1 THEN DebugFmt(message:="snmpAddTrapVariable error, rc=\1", v1:=rc); END_IF; rc := snmpSendTrap(trap:=traphandle, connection:=mancon); IF rc <> 1 THEN DebugFmt(message:="Sending of trap failed (rc=\1)", v1:=rc); ELSE DebugFmt(message:="Successfully sendt trap!", v1:=rc); END_IF; rc := snmpDestroyTrap(trap:=traphandle); IF rc <> 1 THEN DebugFmt(message:="snmpDestroyTrap failed (rc=\1)", v1:=rc); END_IF; END_IF; ELSE DebugFmt(message:="snmpGetNextVar (rc=\1)", v1:=rc); END_CASE; END_WHILE; END; END_PROGRAM;