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