| ioPAC RTU Controllers C/C++ Sample Code Programming Guide

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

Macros | Functions
ioPAC8500_modbus_tcp_master_and_slave.c File Reference

ioPAC8500 Modbus TCP Master and Slave More...

`#include "libmoxa_rtu.h"`

## Macros
#define | BUFFER_SIZE 128
#define | SERVICE_MODBUSMASTER_STATUS_TAG "Service_ModbusMaster_Status"
#define | SERVICE_MODBUSSLAVE_STATUS_TAG "Service_ModbusSlave_Status"

## Functions
int | main (int argc, char *argv[])

## Detailed Description

ioPAC8500 Modbus TCP Master and Slave

Copyright
  Moxa Inc.

Date
  03-04-2014

Author
  Eddy Kao

Version
  V1.0
  ioPAC8500 Modbus TCP Master and Slave

    Introduction:
    Modbus TCP Master accesses DI and DO from Modbus TCP Slave of localhost.
    Example:
     ./ioPAC8500_modbus_tcp_master_and_slave
    Help:

    root@Moxa:/tmp#./ioPAC8500_modbus_tcp_master_and_slave -h
    ioPAC8500 Modbus TCP Master and Slave program.

    Usage: ./ioPAC8500_modbus_tcp_master_and_slave [OPTIONS]

    Options:
        No options.

Library:
TAG APIs
RTUxpress Project file:
ioPAC8500_modbus_tcp_master_and_slave.rtu
(Please right click on the link and ‘Save Target As…’ to save RTUxpress project file and open it with RTUxpress utility)

## Macro Definition Documentation

#define BUFFER_SIZE 128

#define SERVICE_MODBUSMASTER_STATUS_TAG "Service_ModbusMaster_Status"

#define SERVICE_MODBUSSLAVE_STATUS_TAG "Service_ModbusSlave_Status"

## Function Documentation

int main | ( | int | argc,
|  | char * | argv[]
| ) |  |

/*******************************************************************************
* Copyright Moxa Inc.
*
* TAG Service for Modbus TCP Master and Slave
*
* Date Author Comment
* 03-04-2014 Eddy Kao Created.
******************************************************************************/
/*******************************************************************************
*
* Sample code for Modbus TCP Master and Slave Services
*
*******************************************************************************/
#include "libmoxa_rtu.h"
#define BUFFER_SIZE 128
#define SERVICE_MODBUSMASTER_STATUS_TAG "Service_ModbusMaster_Status"
#define SERVICE_MODBUSSLAVE_STATUS_TAG "Service_ModbusSlave_Status"
int main(int argc, char * argv[])
{
int i = 0;
int retval = 0;
UINT8 timeOut = 60; //60s
UINT8 cmd = 0;
TAG_ERR_CODE rc = TAG_ERR_OK;
TAG_INFO modbusMasterStatusTagInfo;
TAG_INFO modbusSlaveStatusTagInfo;
TAG_INFO *modbusTagsTagInfo = NULL;
UINT32 readBytes = 0;
UINT16 nModbusTags = 0;
struct Timestamp timestamp;
int tagValue = 0;
unsigned int unsignedTagValue = 0;
float floatTagValue = 0.0;
UINT8 tagName[TAG_MAX_NAME_SIZE];
UINT8 tagBuf[BUFFER_SIZE];
//Modbus TCP Master accesses Modbus tags by internal registers, like variables.
char modbusTags[][TAG_MAX_NAME_SIZE] = {{"IR_S1_DI0_DIValue"},
{"IR_S2_DO0_DOValue"},
{"IR_S0_SR_DeviceName"},
{"IR_Service_ModbusSlave_Status"},
};
char cmdBuf[][BUFFER_SIZE] = {{"0: read Modbus Master Service status"},
{"1: read Modbus Slave Service status"},
{"2: read Modbus Tags by Master"},
{"3: write DO Tags to be \"On\" by Master"},
{"4: write DO Tags to be \"Off\" by Master"},
{"5: exit program"},
};
while((retval = getopt(argc, argv, "h")) != -1)
{
switch(retval)
{
case '?':
case 'h':
default:
printf("%s.\n\n", "ioPAC8500 Modbus TCP Master and Slave program");
printf("Usage: ./ioPAC8500_modbus_tcp_master_and_slave [OPTIONS]\n\n");
printf("Options:\n");
printf("\tNo options.\n");
printf("\n");
return 0;
}
}
printf("\r\nTag Init\r\n");
retval = MX_RTU_Tag_Init();
if(retval != TAG_ERR_OK)
{
printf("MX_RTU_Tag_Init error = %d\r\n", retval);
return -1;
}
else printf("Tag Init ok!\r\n\r\n");
printf("Get Tag Info\r\n");
memset(&modbusMasterStatusTagInfo, 0, sizeof(modbusMasterStatusTagInfo));
rc = MX_RTU_Tag_Get_Info(SERVICE_MODBUSMASTER_STATUS_TAG, &modbusMasterStatusTagInfo);
if(rc != TAG_ERR_OK)
{
printf("tagName = %s, MX_RTU_Tag_Get_Info error = %d\r\n", SERVICE_MODBUSMASTER_STATUS_TAG, rc);
goto exit;
}
memset(&modbusSlaveStatusTagInfo, 0, sizeof(modbusSlaveStatusTagInfo));
rc = MX_RTU_Tag_Get_Info(SERVICE_MODBUSSLAVE_STATUS_TAG, &modbusSlaveStatusTagInfo);
if(rc != TAG_ERR_OK)
{
printf("tagName = %s, MX_RTU_Tag_Get_Info error = %d\r\n", SERVICE_MODBUSSLAVE_STATUS_TAG, rc);
goto exit;
}
nModbusTags = (sizeof(modbusTags) / TAG_MAX_NAME_SIZE);
modbusTagsTagInfo = malloc(nModbusTags * sizeof(TAG_INFO));
memset(modbusTagsTagInfo, 0, sizeof(nModbusTags * sizeof(TAG_INFO)));
for(i = 0; i < nModbusTags; i++)
{
memset(&modbusTagsTagInfo[i], 0, sizeof(TAG_INFO));
rc = MX_RTU_Tag_Get_Info(modbusTags[i], &modbusTagsTagInfo[i]);
if(rc != TAG_ERR_OK)
{
printf("tagName = %s, MX_RTU_Tag_Get_Info error = %d\r\n", modbusTags[i], rc);
free(modbusTagsTagInfo);
goto exit;
}
}
printf("Get Tag Info ok\r\n\r\n");
printf("Get Modbus TCP Master and Slave Service status\r\n\r\n");
while(timeOut)
{
memset(tagBuf, 0, sizeof(tagBuf));
rc = MX_RTU_Tag_Read(SERVICE_MODBUSMASTER_STATUS_TAG, (void *)tagBuf, sizeof(tagBuf), &readBytes, NULL);
if(rc != TAG_ERR_OK || readBytes != modbusMasterStatusTagInfo.tagSize)
{
printf("tagName = %s, MX_RTU_Tag_Read error = %d, readBytes = %d, tagSize = %d\r\n", SERVICE_MODBUSMASTER_STATUS_TAG, rc, readBytes, modbusMasterStatusTagInfo.tagSize);
free(modbusTagsTagInfo);
goto exit;
}
else
{
tagValue = 0;
memcpy(&tagValue, tagBuf, modbusMasterStatusTagInfo.tagSize);
printf("tagName = %s, value = %d\r\n", SERVICE_MODBUSMASTER_STATUS_TAG, tagValue);
}
if(tagValue == STATUS_INIT)
{
printf("Modbus TCP Master Service initing, please wait...\r\n");
}
else if(tagValue == STATUS_READY)
{
printf("Modbus TCP Master Service is ready!\r\n");
break;
}
else if(tagValue == STATUS_FAIL)
{
printf("Modbus TCP Master Service init fail...exit program!\r\n");
free(modbusTagsTagInfo);
goto exit;
}
else
{
printf("Invalid status...exit program!\r\n");
free(modbusTagsTagInfo);
goto exit;
}
timeOut--;
sleep(1);
}
if(timeOut == 0)
{
printf("Timeout!!! Modbus TCP Master Service is not ready...exit program!\r\n");
free(modbusTagsTagInfo);
goto exit;
}
timeOut = 60;
printf("\r\n");
while(timeOut)
{
memset(tagBuf, 0, sizeof(tagBuf));
rc = MX_RTU_Tag_Read(SERVICE_MODBUSSLAVE_STATUS_TAG, (void *)tagBuf, sizeof(tagBuf), &readBytes, NULL);
if(rc != TAG_ERR_OK || readBytes != modbusSlaveStatusTagInfo.tagSize)
{
printf("tagName = %s, MX_RTU_Tag_Read error = %d, readBytes = %d, tagSize = %d\r\n", SERVICE_MODBUSSLAVE_STATUS_TAG, rc, readBytes, modbusSlaveStatusTagInfo.tagSize);
free(modbusTagsTagInfo);
goto exit;
}
else
{
tagValue = 0;
memcpy(&tagValue, tagBuf, modbusSlaveStatusTagInfo.tagSize);
printf("tagName = %s, value = %d\r\n", SERVICE_MODBUSSLAVE_STATUS_TAG, tagValue);
}
if(tagValue == STATUS_INIT)
{
printf("Modbus TCP Slave Service initing, please wait...\r\n");
}
else if(tagValue == STATUS_READY || tagValue == STATUS_RUNNING)
{
printf("Modbus TCP Slave Service is ready!\r\n");
break;
}
else if(tagValue == STATUS_FAIL)
{
printf("Modbus TCP Slave Service init fail...exit program!\r\n");
free(modbusTagsTagInfo);
goto exit;
}
else
{
printf("Invalid status...exit program!\r\n");
free(modbusTagsTagInfo);
goto exit;
}
timeOut--;
sleep(1);
}
if(timeOut == 0)
{
printf("Timeout!!! Modbus TCP Slave Service is not ready...exit program!\r\n");
free(modbusTagsTagInfo);
goto exit;
}
while(1)
{
printf("\r\n");
for(i = 0; i < (sizeof(cmdBuf) / BUFFER_SIZE); i++)
{
printf("%s\r\n", cmdBuf[i]);
}
printf("Enter:");
cmd = getchar();
cmd -= 0x30; //ASCII 0 = 0x30
printf("\r\ncommand = %d\r\n", cmd);
getchar(); //filter Enter
switch(cmd)
{
case 0:
memset(tagBuf, 0, sizeof(tagBuf));
rc = MX_RTU_Tag_Read(SERVICE_MODBUSMASTER_STATUS_TAG, (void *)tagBuf, sizeof(tagBuf), &readBytes, NULL);
if(rc != TAG_ERR_OK || readBytes != modbusMasterStatusTagInfo.tagSize)
{
printf("tagName = %s, MX_RTU_Tag_Read error = %d, readBytes = %d, tagSize = %d\r\n", SERVICE_MODBUSMASTER_STATUS_TAG, rc, readBytes, modbusMasterStatusTagInfo.tagSize);
}
else
{
tagValue = 0;
memcpy(&tagValue, tagBuf, modbusMasterStatusTagInfo.tagSize);
printf("tagName = %s, value = %d\r\n", SERVICE_MODBUSMASTER_STATUS_TAG, tagValue);
}
break;
case 1:
memset(tagBuf, 0, sizeof(tagBuf));
rc = MX_RTU_Tag_Read(SERVICE_MODBUSSLAVE_STATUS_TAG, (void *)tagBuf, sizeof(tagBuf), &readBytes, NULL);
if(rc != TAG_ERR_OK || readBytes != modbusSlaveStatusTagInfo.tagSize)
{
printf("tagName = %s, MX_RTU_Tag_Read error = %d, readBytes = %d, tagSize = %d\r\n", SERVICE_MODBUSSLAVE_STATUS_TAG, rc, readBytes, modbusSlaveStatusTagInfo.tagSize);
}
else
{
tagValue = 0;
memcpy(&tagValue, tagBuf, modbusSlaveStatusTagInfo.tagSize);
printf("tagName = %s, value = %d\r\n", SERVICE_MODBUSSLAVE_STATUS_TAG, tagValue);
}
break;
case 2:
for(i = 0; i < nModbusTags; i++)
{
memset(tagBuf, 0, sizeof(tagBuf));
memset(&timestamp, 0, sizeof(timestamp));
rc = MX_RTU_Tag_Read(modbusTags[i], (void *)tagBuf, sizeof(tagBuf), &readBytes, &timestamp);
if(rc != TAG_ERR_OK || readBytes != modbusTagsTagInfo[i].tagSize)
{
printf("tagName = %s, MX_RTU_Tag_Read error = %d, readBytes = %d, tagSize = %d\r\n", modbusTags[i], rc, readBytes, modbusTagsTagInfo[i].tagSize);
continue;
}
else
{
if(modbusTagsTagInfo[i].dataType == TAG_DATA_TYPE_COIL || modbusTagsTagInfo[i].dataType == TAG_DATA_TYPE_INT8 || modbusTagsTagInfo[i].dataType == TAG_DATA_TYPE_INT16 || modbusTagsTagInfo[i].dataType == TAG_DATA_TYPE_INT32)
{
tagValue = 0;
memcpy(&tagValue, tagBuf, modbusTagsTagInfo[i].tagSize);
printf("tagName = %s, dataType = %d, value = %d, timestamp = %d:%d:%d.%d(hour:min:sec.msec)\r\n", modbusTags[i], modbusTagsTagInfo[i].dataType, tagValue, timestamp.hour, timestamp.min, timestamp.sec, timestamp.msec);
}
else if(modbusTagsTagInfo[i].dataType == TAG_DATA_TYPE_UINT8 || modbusTagsTagInfo[i].dataType == TAG_DATA_TYPE_UINT16 || modbusTagsTagInfo[i].dataType == TAG_DATA_TYPE_UINT32)
{
unsignedTagValue = 0;
memcpy(&unsignedTagValue, tagBuf, modbusTagsTagInfo[i].tagSize);
printf("tagName = %s, dataType = %d, value = %u, timestamp = %d:%d:%d.%d(hour:min:sec.msec)\r\n", modbusTags[i], modbusTagsTagInfo[i].dataType, tagValue, timestamp.hour, timestamp.min, timestamp.sec, timestamp.msec);
}
else if(modbusTagsTagInfo[i].dataType == TAG_DATA_TYPE_FLOAT)
{
printf("tagName = %s, dataType = %d, value = %f, timestamp = %d:%d:%d.%d(hour:min:sec.msec)\r\n", modbusTags[i], modbusTagsTagInfo[i].dataType, floatTagValue, timestamp.hour, timestamp.min, timestamp.sec, timestamp.msec);
}
else if(modbusTagsTagInfo[i].dataType == TAG_DATA_TYPE_STR)
{
printf("tagName = %s, dataType = %d, value = %s, timestamp = %d:%d:%d.%d(hour:min:sec.msec)\r\n", modbusTags[i], modbusTagsTagInfo[i].dataType, tagBuf, timestamp.hour, timestamp.min, timestamp.sec, timestamp.msec);
}
}
}
break;
case 3:
for(i = 0; i < nModbusTags; i++)
{
if(strstr(modbusTags[i], "DOValue"))
{
tagValue = 1;
rc = MX_RTU_Tag_Write(modbusTags[i], (void *)&tagValue, modbusTagsTagInfo[i].tagSize);
printf("tagName = %s, MX_RTU_Tag_Write = %d\r\n", modbusTags[i], rc);
}
}
break;
case 4:
for(i = 0; i < nModbusTags; i++)
{
if(strstr(modbusTags[i], "DOValue"))
{
tagValue = 0;
rc = MX_RTU_Tag_Write(modbusTags[i], (void *)&tagValue, modbusTagsTagInfo[i].tagSize);
printf("tagName = %s, MX_RTU_Tag_Write = %d\r\n", modbusTags[i], rc);
}
}
break;
case 5:
free(modbusTagsTagInfo);
goto exit;
default:
printf("Invalid command...exit program!\r\n");
free(modbusTagsTagInfo);
goto exit;
}
}
exit:
printf("\r\nTag Uninit\r\n");
retval = MX_RTU_Tag_Uninit();
if(retval != TAG_ERR_OK)
{
printf("MX_RTU_Tag_Uninit error = %d\r\n", retval);
}
else printf("Tag Uninit ok\r\n");
return 0;
}