Realising & testing LAN communication quickly

ProgrammierenThere is probably nothing more annoying than a printer that doesn’t work when you need it the most. We all know this problem that can have numerous reasons like for example lack of paper or an empty toner cartridge. The good news is: It’s a problem we can solve. This example – for which we used the rapidM2M PoC LAN Shield – shows you how:

rapidM2M enables you to communicate with all devices of a network. Here are three things you have to bear in mind:

1. W5200 chip: Usually TCP is used to transmit and receive data via LAN. The W5200 chip provides a TCP socket. To use the chip the include file w5200.inc is required which provides you with interface functions that enable the communication with the IP.

2. DHCP (Dynamic Host Configuration Protocol): The include file dhcp.inc implements functions that use the standardised DHCP to receive information like the IP adress or other relevant network parameters. As soon as an IP address is assigned, communication with other devices within the network is enabled.

3. SNMP: The Simple Network Management Protocol is used to exchange management information between the “manager” and the “agent” within a network. In this example the rapidM2M module is the manager. It sends a request to the agent (device with the stated IP address). The request comprises the target IP address and the requested entity’s Object Identifier.

In this example the OID of the entity “Device Description” is used which is basically the same for all kind of printers. The application sets up a connection and requests the device designation of all printers within the network.

First the W5200 chip that “paves the way” to the network has to be initialised. Using the DHCP a connection to the network is set up and the module gets an IP address that enables it to communicate with other devices in the network. Then the SNMP request follows. If you use the IP address aIPAddress{4} = {255, 255, 255, 255} all devices within the network are addressed. The printers can assign the Object Identifier to the entity “Device Description” and answer. There may be other devices in the network that are not able to use the OID. These devices will answer with NULL.

With this simple example all devices within a network can be monitored – provided their IP addresses and OIDs are known. Different device features can be requested, like for example the current device status. This way for example an alarm can be triggered in case a device has a bug status, lacks paper or needs a new toner cartridge.

The following example sends a request with the OID “Printer Device Description” to the whole network and displays all answers on the Toolset’s console:

#pragma amxcompress 3

/* generic socket handler callbacks (have to be defined before w5200 include) */
#define W5200_SOCKET_0_EVENT(%1,%2) DHCP_SocketEvent(%1,%2)
#define W5200_SOCKET_1_EVENT(%1,%2) SNMP_SocketEvent(%1,%2)

#include <string>
#include w5200
#include dhcp
#include snmp

forward public Main_Timer();
forward public Timer60s();

#define DHCP_SOCKET (0)
#define SNMP_SOCKET (1)

static sW5200_Setup[TW5200_Setup] =
[
{0, 0, 0, 0},                         /* default local IP Address */
{0, 0, 0, 0},                         /* default SubnetMask Address */
{0, 0, 0, 0},                         /* default Gateway Address */
{0x00, 0x08, 0xDC, 0x01, 0x02, 0x03}, /* dummy WizNet MAC Address */
{2,2,2,2,2,2,2,2},                    /* Rx mem config */
{2,2,2,2,2,2,2,2}                     /* Tx mem config */
];

new caIPAddress{4} =  {255,255,255,255};  /* to all devices in network */

static iMain_TriggerDHCP;
static iMain_TriggerSNMP;

static sSNMP_Resp[TSNMP_Response];
static aSNMP_Objects[10][TSNMP_Obj];

/* application entry point */
main()
{
/* init W5200 with used hardware interface and DHCP with MAC address */
W5200_Init(0, 3, 5, 4);
DHCP_Init(sW5200_Setup.aMAC);

/* start 1s Timer */
rM2M_TimerAdd(funcidx("Main_Timer"));

/* set communication mode to wakeup */
rM2M_TxSetMode(RM2M_TXMODE_WAKEUP);
}

/* 1s Timer, used for connecting/requesting */
public Main_Timer()
{
static bool:bLinkUp = false;

/* get state of W5200 */
if(W5200_GetState() == W5200_STATE_ERROR)
{
/* W5200 in error state -> reset */
W5200_Reset();
return;
}

/* wait until Link is up */
if(!W5200_GetLinkStatus())
{
/* Link got lost */
if(bLinkUp)
{
printf("Link down\r\n");
bLinkUp = false;
}
return;
}

/* DHCP trigger */
if(iMain_TriggerDHCP)
{
iMain_TriggerDHCP--;
if(!iMain_TriggerDHCP)
{
/* get new IP -> start DHCP */
DHCP_Start();
}
}

/* SNMP trigger, sends a request if set */
if(iMain_TriggerSNMP)
{
iMain_TriggerSNMP--;
if(!iMain_TriggerSNMP)
{
new sReq[TSNMP_Request] = ["public", 5961, 0];

/* device description OID */
new aObjList[][TSNMP_ObjName] =
[
[[1,3,6,1,2,1,25,3,2,1,3,1], 12]
];

/* send SNMP GetRequest */
sReq.iNumObj = 1;
SNMP_GetRequest(caIPAddress, sReq, aObjList);
}
}

if(!bLinkUp)
{
printf("Link up\r\n");
bLinkUp = true;
/* trigger DHCP */
iMain_TriggerDHCP = 2;
/* setup W5200 */
W5200_Setup(sW5200_Setup);
}

/* call generic socket handler */
W5200_SocketHandler();
}

/* socket event handler for DHCP, automatically called on DHCP message reception */
DHCP_SocketEvent(s, iEvent)
{
if(iEvent == W5200_SOCK_RECV)
{
new aMsg{DHCP_MSG_MAX_LEN};
new iLen;
new aIP{4};
new iPort;

/* get received data */
iLen = W5200_RecvFrom(s, aMsg, DHCP_MSG_MAX_LEN, aIP, iPort);
if(iLen > 0)
{
/* DHCP receive */
DHCP_RecvFrom(aMsg, iLen, aIP, iPort);
}
}
}

/* DHCP event callback function, automatically called on connection start or reconnection */
DHCP_Event(iEvent)
{
if(iEvent == DHCP_EVENT_ABORT)
{
printf("DHCP_Event: abort\r\n");
W5200_Close(DHCP_SOCKET);
}
else if(iEvent == DHCP_EVENT_UPDATE)
{
/* read new config, get IP Address */
DHCP_GetConfig(sW5200_Setup.aIP, sW5200_Setup.aSub, sW5200_Setup.aGW);

printf("DHCP_Event: new IP = %d.%d.%d.%d\r\n",
sW5200_Setup.aIP{0},
sW5200_Setup.aIP{1},
sW5200_Setup.aIP{2},
sW5200_Setup.aIP{3});
printf("DHCP_Event: subnet mask = %d.%d.%d.%d\r\n",
sW5200_Setup.aSub{0},
sW5200_Setup.aSub{1},
sW5200_Setup.aSub{2},
sW5200_Setup.aSub{3});
printf("DHCP_Event: gateway = %d.%d.%d.%d\r\n",
sW5200_Setup.aGW{0},
sW5200_Setup.aGW{1},
sW5200_Setup.aGW{2},
sW5200_Setup.aGW{3});

/* reinit W5200 */
W5200_Setup(sW5200_Setup);
}
else if(iEvent == DHCP_EVENT_FINISH)
{
printf("DHCP_Event: finish\r\n");
/* socket is not used any more */
W5200_Close(DHCP_SOCKET);

/* connection established, start request */
iMain_TriggerSNMP = 1;
}
}

/* DHCP send callback function, triggered when DHCP_Start() is executed */
DHCP_SendTo(aBuf{}, iLen, aIP{4}, iPort)
{
/* check availability of socket */
if(W5200_GetSocketStatus(DHCP_SOCKET) != W5200_SOCK_UDP)
{
/* close socket */
W5200_Close(DHCP_SOCKET);

/* open socket for dhcp */
W5200_Socket(DHCP_SOCKET, W5200_Sn_MR_UDP, DHCP_CLIENT_PORT, 0);
}
/* test connection */
if(W5200_SendTo(DHCP_SOCKET, aBuf, iLen, aIP, iPort) < OK)
{
printf("DHCP_SendTo: send error\r\n");
return(ERROR);
}
return(OK);
}

/* socket event handler for SNMP, automatically called on SNMP message reception */
SNMP_SocketEvent(s, iEvent)
{
if(iEvent == W5200_SOCK_RECV)
{
new aMsg{SNMP_MSG_MAX_LEN};
new iLen;
new aIP{4};
new iPort;

/* get received data */
iLen = W5200_RecvFrom(s, aMsg, SNMP_MSG_MAX_LEN, aIP, iPort);
if(iLen > 0)
{
/* SNMP receive */
sSNMP_Resp.iNumObj = sizeof(aSNMP_Objects);

if(SNMP_RecvFrom(aMsg, iLen, aIP, iPort, sSNMP_Resp, aSNMP_Objects) < OK)
{
/* decode failed */
printf("no valid SNMP message!\r\n");
}
else
{ /* print received data */
for(new i=0; i<sSNMP_Resp.iNumObj; i++)
{
SNMP_PrintObject(aSNMP_Objects[i]);
printf("\r\n");
}
}
}
}
}

/* SNMP send callback function, automatically called when a SNMP request was sent */
SNMP_SendTo(aBuf{}, iLen, aIP{4}, iPort)
{
/* check availability of socket */
if(W5200_GetSocketStatus(SNMP_SOCKET) != W5200_SOCK_UDP)
{
/* close socket */
W5200_Close(SNMP_SOCKET);

/* open socket for SNMP */
W5200_Socket(SNMP_SOCKET, W5200_Sn_MR_UDP, 0, 0);
}

if(W5200_SendTo(SNMP_SOCKET, aBuf, iLen, aIP, iPort) < OK)
{
printf("SNMP_SendTo: send error\r\n");
return(ERROR);
}
return(OK);
}

Testing this example won’t take you longer than 15 minutes. You just have to connect your rapidM2M PoC LAN Shield to the network and to your PC with a USB micro cable. Now you can unpack all the required files (download files here). Start the toolset and open the example example.p. Now you just have to click “Compile and send to device”. Within a couple of seconds the answers of all devices will be listed in the console tab.

If you would like to communicate with single devices, use the other example called example_extended.p.  It regularly sends a request to the network, saves the first five answers in the module’s Config 0 and sends them to the server. Additionally you can use Config 1 to enter an IP address that will automatically serve as target address for future requests. Just copy the content of the file connector.txt and add it to your site at Control -> Data structure.

You can order the rapidM2M LAN PoC Shield used in this example in the Microtronics Shop. If you have any questions, please do not hesitate to contact the Microtronics Support team.

Contact Microtronics Support team
Monday to Friday 8 am - 12 pm and 13 pm - 5 pm (except for Austrian national holidays)
Phone: +43 2756 77180-23
E-mail: support@microtronics.com