The following example tinyslave.cpp shows how to implement a small Modbus RTU slave:
#include "hmplatf.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MbusRtuSlaveProtocol.hpp"
#if defined(__WIN32__)
const TCHAR *portName = TEXT("COM1");
#elif defined(__LINUX__)
const char *portName = "/dev/ttyS0";
#elif defined(__MACOSX__)
const char *portName = "/dev/ttys0";
#elif defined(__FREEBSD__) || defined(__NETBSD__) || defined(__OPENBSD__)
const char *portName = "/dev/ttyd0";
#elif defined(__QNX__)
const char *portName = "/dev/ser1";
#elif defined(__VXWORKS__)
const char *portName = "/tyCo/0";
#elif defined(__SOLARIS__)
const char *portName = "/dev/ttya";
#elif defined(__IRIX__)
const char *portName = "/dev/ttyf1";
#elif defined(__OSF__)
const char *portName = "/dev/tty00";
#else
const char *portName = "/dev/tty";
#endif
typedef struct
{
short actTemp;
short minTemp;
long scanCounter;
float setPoint;
short statusReg;
short configType;
} MyDeviceData;
MyDeviceData deviceData;
{
public:
{
startRef--;
if (startRef + refCnt > int(sizeof(deviceData) / sizeof(short)))
return 0;
memcpy(regArr, &((short *) &deviceData)[startRef],
refCnt * sizeof(short));
return 1;
}
const short regArr[],
int refCnt)
{
startRef--;
if (startRef + refCnt > int(sizeof(deviceData) / sizeof(short)))
return 0;
memcpy(&((short *) &deviceData)[startRef],
regArr, refCnt * sizeof(short));
return 1;
}
} dataProvider;
void startupServer()
{
int result;
19200L,
8,
1,
2);
{
fprintf(stderr, "Error starting server: %s!\n",
exit(EXIT_FAILURE);
}
}
void shutdownServer()
{
}
void runServer()
{
{
}
}
#if defined(_WIN32_WCE)
int wmain()
#else
int main()
#endif
{
atexit(shutdownServer);
startupServer();
runServer();
return EXIT_FAILURE;
}
The following example tcpslave.cpp shows how to implement a small Modbus/TCP slave:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MbusTcpSlaveProtocol.hpp"
typedef struct
{
short actTemp;
short minTemp;
long scanCounter;
float setPoint;
short statusReg;
short configType;
} MyDeviceData;
MyDeviceData deviceData;
const char* VENDOR_NAME = "proconX Pty Ltd";
const char* PRODUCT_CODE = "FT-MBSV";
const char* VENDOR_URL = "http://www.modbusdriver.com";
const char* PRODUCT_NAME = "FieldTalk";
const char* MODEL_NAME = "Modbus Slave C++ Library";
const char* USER_APPLICATION_NAME = "diagslave";
{
public:
void printHello()
{
printf("Hello!\n");
}
{
startRef--;
if (startRef + refCnt > int(sizeof(deviceData) / sizeof(short)))
return 0;
memcpy(regArr, &((short *) &deviceData)[startRef],
refCnt * sizeof(short));
return 1;
}
const short regArr[],
int refCnt)
{
startRef--;
if (startRef + refCnt > int(sizeof(deviceData) / sizeof(short)))
return 0;
memcpy(&((short *) &deviceData)[startRef],
regArr, refCnt * sizeof(short));
return 1;
}
{
switch (objId)
{
case 0:
if (bufferArr)
{
#ifdef HAS_STRNCPY
strncpy(bufferArr, VENDOR_NAME, maxBufSize);
#else
strcpy(bufferArr, VENDOR_NAME);
#endif
}
return strlen(VENDOR_NAME);
case 1:
if (bufferArr)
{
#ifdef HAS_STRNCPY
strncpy(bufferArr, PRODUCT_CODE, maxBufSize);
#else
strcpy(bufferArr, PRODUCT_CODE);
#endif
}
return strlen(PRODUCT_CODE);
case 2:
if (bufferArr)
{
#ifdef HAS_STRNCPY
#else
#endif
}
}
return 0;
}
} dataProvider;
int masterPollEvent(const char* masterIpAddrSz)
{
printf("masterPollEvent for %s!\n", masterIpAddrSz);
return 1;
}
void masterDisconnectEventOld(const char* masterIpAddrSz)
{
printf("masterDisconnectEvent for %s!\n", masterIpAddrSz);
}
void masterDisconnectEventNew(const char* masterIpAddrSz, void* userData)
{
printf("masterDisconnectEvent for %s!\n", masterIpAddrSz);
((MyDataProvider*)userData)->printHello();
}
void startupServer()
{
int result;
mbusServer.installMasterPollNotifyCallBack(masterPollEvent);
mbusServer.installMasterDisconnectCallBack(masterDisconnectEventOld);
{
fprintf(stderr, "Error starting server: %s!\n",
exit(EXIT_FAILURE);
}
}
void shutdownServer()
{
}
void runServer()
{
{
}
}
#if defined(_WIN32_WCE)
int wmain()
#else
int main()
#endif
{
atexit(shutdownServer);
startupServer();
runServer();
return EXIT_FAILURE;
}
The following example shows how to implement a Data Provider which serves it's data from shared memory:
{
public:
ShmemMbusDataTable(int table0Size, int table1Size, int table3Size, int table4Size)
{
int i;
int fd;
for (i = 0; i < 5; i++)
{
switch (i)
{
case 0:
if (table0Size <= 0)
break;
dataTableArr[i].size = table0Size * sizeof(char);
break;
case 1:
if (table1Size <= 0)
break;
dataTableArr[i].size = table1Size * sizeof(char);
break;
case 2:
dataTableArr[i].size = sizeof(SlaveStatusInfo);
break;
case 3:
if (table3Size <= 0)
break;
dataTableArr[i].size = table3Size * sizeof(short);
break;
case 4:
if (table4Size <= 0)
break;
dataTableArr[i].size = table4Size * sizeof(short);
break;
}
shm_unlink(dataTableArr[i].name);
if (dataTableArr[i].size == 0)
continue;
fd = shm_open(dataTableArr[i].name, O_CREAT | O_RDWR | O_EXCL, S_IRWXU);
if (fd < 0)
{
perror("Shared memory open failed");
abort();
}
if (ftruncate(fd, dataTableArr[i].size) < 0)
{
perror("Shared memory ftruncate failed");
abort();
}
dataTableArr[i].ptr = (short *) mmap(0, dataTableArr[i].size,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0L);
if (dataTableArr[i].ptr == NULL)
{
perror("Shared memory mmap failed");
abort();
}
close (fd);
memset(dataTableArr[i].ptr, 0, dataTableArr[i].size);
}
if (table3Size == -1)
{
dataTableArr[3].size = dataTableArr[4].size;
dataTableArr[3].ptr = dataTableArr[4].ptr;
}
if (table1Size == -1)
{
dataTableArr[1].size = dataTableArr[0].size;
dataTableArr[1].ptr = dataTableArr[0].ptr;
}
slaveStatusInfoPtr = (SlaveStatusInfo *) dataTableArr[2].ptr;
}
~ShmemMbusDataTable()
{
int i;
for (i = 0; i < 5; i++)
{
if (dataTableArr[i].ptr != NULL)
{
munmap(dataTableArr[i].ptr, dataTableArr[i].size);
shm_unlink(dataTableArr[i].name);
}
}
}
void timeOutHandler()
{
slaveStatusInfoPtr->timeoutCnt++;
}
int readInputDiscretesTable(int startRef,
char bitArr[],
int refCnt)
{
printf("\nreadInputDiscretesTable: %d, %d\n", startRef, refCnt);
startRef--;
if (startRef + refCnt > (int) (dataTableArr[1].size / sizeof(char)))
return 0;
memcpy(bitArr, &((char *) dataTableArr[1].ptr)[startRef], refCnt * sizeof(char));
slaveStatusInfoPtr->readDiscretesCnt++;
return 1;
}
int readCoilsTable(int startRef,
char bitArr[],
int refCnt)
{
printf("\nreadCoilsTable: %d, %d\n", startRef, refCnt);
startRef--;
if (startRef + refCnt > (int) (dataTableArr[0].size / sizeof(char)))
return 0;
memcpy(bitArr, &((char *) dataTableArr[0].ptr)[startRef], refCnt * sizeof(char));
slaveStatusInfoPtr->readDiscretesCnt++;
return 1;
}
int writeCoilsTable(int startRef,
const char bitArr[],
int refCnt)
{
printf("\nriteCoilsTable: %d, %d\n", startRef, refCnt);
startRef--;
if (startRef + refCnt > (int) (dataTableArr[0].size / sizeof(char)))
return 0;
memcpy(&((char *) dataTableArr[0].ptr)[startRef], bitArr, refCnt * sizeof(char));
slaveStatusInfoPtr->writeDiscretesCnt++;
return 1;
}
int readInputRegistersTable(int startRef,
short regArr[],
int refCnt)
{
printf("\nreadInputRegistersTable: %d, %d\n", startRef, refCnt);
startRef--;
if (startRef + refCnt > (int) (dataTableArr[3].size / sizeof(short)))
return 0;
memcpy(regArr, &((short *) dataTableArr[3].ptr)[startRef], refCnt * sizeof(short));
slaveStatusInfoPtr->readRegistersCnt++;
return 1;
}
int readHoldingRegistersTable(int startRef,
short regArr[],
int refCnt)
{
printf("\nreadHoldingRegistersTable: %d, %d\n", startRef, refCnt);
startRef--;
if (startRef + refCnt > (int) (dataTableArr[4].size / sizeof(short)))
return 0;
memcpy(regArr, &((short *) dataTableArr[4].ptr)[startRef], refCnt * sizeof(short));
slaveStatusInfoPtr->readRegistersCnt++;
return 1;
}
int writeHoldingRegistersTable(int startRef,
const short regArr[],
int refCnt)
{
printf("\nwriteHoldingRegistersTable: %d, %d\n", startRef, refCnt);
startRef--;
if (startRef + refCnt > (int) (dataTableArr[4].size / sizeof(short)))
return 0;
memcpy(&((short *) dataTableArr[4].ptr)[startRef], regArr, refCnt * sizeof(short));
slaveStatusInfoPtr->writeRegistersCnt++;
return 1;
}
private:
SlaveStatusInfo *slaveStatusInfoPtr;
};