ioPAC RTU Controllers
C/C++ Sample Code Programming Guide
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Functions | Variables
aopc_io_update.c File Reference

AOPC I/O Update More...

#include <libmoxa_rtu.h>

Functions

int ipCheck (char *ip)
 
UINT8 doWriteCallback (UINT8 *tagName, UINT16 tagValueType, UINT8 *tagValue)
 
int main (int argc, char *argv[])
 

Variables

UINT8 DOChannelValue = 0
 
UINT32 DOOutputValue = 0
 

Detailed Description

AOPC I/O Update

Date
04-10-2013
Author
Eddy Kao
Version
V1.0
aopc_io_update.jpg
AOPC I/O Update
Introduction:
The controller sends DO status and AI value updates to Moxa Active OPC Server (AOPC Server).
At the same time, the OPC Client can get the AI value and set the DO status through AOPC Server.
Example:
1. Using default: ./aopc_io_update -i192.168.0.1
2. Setting IP, DO, and AI: ./aopc_io_update -i192.168.0.1 -s2 -c1 -S1 -C1
Default:
IP = None
Port = 9900
Heartbeat = 30s
DO Slot = 1
DO Channel = 0
AI Slot = 2
AI Channel = 0
Help:
root@Moxa:/tmp#./aopc_io_update -h
AOPC I/O Update.

Usage: ./aopc_io_update [OPTIONS]

Options:
        -i       IP
        -p       Port [0-65535]. Default port = 9900
        -b       HeartBeat [0-4294967295]. Default heartbeat = 30 seconds
        -s       DO slot [0-9]. Default DO slot = 1
                 (slot 0: Built-in IO, slot 1 ~ 9: IO Module)
        -c       DO channel [0-24]. Default DO channel = 0
        -S       AI slot [0-9]. Default AI slot = 2
                 (slot 0: Built-in IO, slot 1 ~ 9: IO Module)
        -C       AI channel [0-24]. Default AI channel = 0

Library:
AOPC APIs

Function Documentation

int ipCheck ( char *  ip)
UINT8 doWriteCallback ( UINT8 tagName,
UINT16  tagValueType,
UINT8 tagValue 
)
int main ( int  argc,
char *  argv[] 
)
/*******************************************************************************
* Copyright Moxa Inc.
*
* AOPC I/O Update
*
* Date Author Comment
* 04-10-2013 Eddy Kao Created.
******************************************************************************/
#include <libmoxa_rtu.h>
UINT8 DOChannelValue = 0;
UINT32 DOOutputValue = 0;
int ipCheck(char *ip)
{
int count = 3;
char *pch;
pch = ip;
while(count)
{
pch = strstr(pch, ".");
if(pch == NULL) return -1;
pch++;
count--;
}
return 0;
}
UINT8 doWriteCallback(UINT8 *tagName, UINT16 tagValueType, UINT8 *tagValue)
{
UINT32 rc = 0;
char *pch;
char num[2];
UINT8 doSlot = 0;
UINT8 doChannel = 0;
memset(num, 0, sizeof(num));
pch = strstr(tagName, "-");
num[0] = *(pch + 1);
doSlot = atoi(num);
memset(num, 0, sizeof(num));
pch = strstr(pch + 1, "-");
strncpy(num, pch + 1, strlen(pch + 1));
doChannel = atoi(num);
if(*tagValue)
{
DOChannelValue = 1;
DOOutputValue |= (1 << doChannel);
}
else
{
DOChannelValue = 0;
DOOutputValue &= ~(1 << doChannel);
}
rc = MX_RTU_Module_DO_Value_Set(doSlot, DOOutputValue);
if(rc != MODULE_RW_ERR_OK)
{
printf("MX_RTU_Module_DO_Value_Set(%d, %x), return code = %d\r\n", doSlot, DOOutputValue, rc);
}
return AOPC_ERR_OK;
}
int main(int argc, char *argv[])
{
char ch = 0;
char chIgnore = 0;
char retry = 3;
int retval = 0;
UINT32 rc = 0;
UINT8 deviceName[AOPC_MAX_DEV_NAME + 1];
UINT8 ip[17];
char ipFlag = 0;
unsigned short port = AOPC_DEFAULT_PORT; //Default port
UINT32 heartBeatS = 30; //send hearbeat signal every 30 seconds
UINT32 timeoutMs = 5 * 1000; //5 seconds
UINT32 sHandle = 0;
TAG boolTagInfo;
TAG floatTagInfo;
UINT8 doSlot = 1;
UINT8 doChannel = 0;
UINT8 aiSlot = 2;
UINT8 aiChannel = 0;
float aiValue = 0.0;
struct Timestamp time;
while((retval = getopt(argc, argv, "hi:p:b:s:c:S:C:")) != -1)
{
switch(retval)
{
case 'i':
if(ipCheck(optarg))
{
printf("Invalid IP\r\n");
exit(1);
}
strcpy(ip, optarg);
ipFlag = 1;
break;
case 'p':
port = atoi(optarg);
break;
case 'b':
heartBeatS = atoi(optarg);
break;
case 's':
doSlot = atoi(optarg);
if(doSlot > MAX_SLOT)
{
printf("Error DO slot = %d\r\n", doSlot);
exit(1);
}
break;
case 'c':
doChannel = atoi(optarg);
if(doChannel > MAX_CHANNEL)
{
printf("Error DO channel = %d\r\n", doChannel);
exit(1);
}
break;
case 'S':
aiSlot = atoi(optarg);
if(aiSlot > MAX_SLOT)
{
printf("Error AI slot = %d\r\n", aiSlot);
exit(1);
}
break;
case 'C':
aiChannel = atoi(optarg);
if(aiChannel > MAX_CHANNEL)
{
printf("Error AI channel = %d\r\n", aiChannel);
exit(1);
}
break;
case '?':
case 'h':
default:
printf("AOPC I/O Update.\n\n");
printf("Usage: ./aopc_io_update [OPTIONS]\n\n");
printf("Options:\n");
printf("\t%-8s IP\n", "-i");
printf("\t%-8s Port [%d-%d]. Default port = %d\n", "-p", 0, 65535, port);
printf("\t%-8s HeartBeat [%d-%u]. Default heartbeat = %d seconds\n", "-b", 0, 0xFFFFFFFF, heartBeatS);
printf("\t%-8s DO slot [%d-%d]. Default DO slot = %d\n", "-s", 0, MAX_SLOT, doSlot);
printf("\t%-8s (slot 0: Built-in IO, slot 1 ~ 9: IO Module)\n", "");
printf("\t%-8s DO channel [%d-%d]. Default DO channel = %d\n", "-c", 0, MAX_CHANNEL, doChannel);
printf("\t%-8s AI slot [%d-%d]. Default AI slot = %d\n", "-S", 0, MAX_SLOT, aiSlot);
printf("\t%-8s (slot 0: Built-in IO, slot 1 ~ 9: IO Module)\n", "");
printf("\t%-8s AI channel [%d-%d]. Default AI channel = %d\n", "-C", 0, MAX_CHANNEL, aiChannel);
printf("\n");
return;
}
}
if(ipFlag == 0)
{
printf("No IP\r\n");
exit(1);
}
if(rc != AOPC_ERR_OK)
{
printf("MX_RTU_AOPC_Init(), return code = %d\r\n", rc);
exit(1);
}
memset(deviceName, 0, sizeof(deviceName));
strcpy(deviceName, "Moxa RTU");
rc = MX_RTU_AOPC_Connect(deviceName, heartBeatS, ip, port, timeoutMs, &sHandle);
if(rc != AOPC_ERR_OK)
{
printf("MX_RTU_AOPC_Connect(%s, %d, %s, %d, %d, &sHandle), return code = %d\r\n", deviceName, heartBeatS, ip, port, timeoutMs, rc);
exit(1);
}
rc = MX_RTU_AOPC_DelAllTag(sHandle, timeoutMs);
if(rc != AOPC_ERR_OK)
{
printf("MX_RTU_AOPC_DelAllTag(%d, %d), return code = %d\r\n", sHandle, timeoutMs, rc);
exit(1);
}
rc = MX_RTU_Module_DO_Value_Get(doSlot, &DOOutputValue);
if(rc != MODULE_RW_ERR_OK)
{
printf("MX_RTU_Module_DO_Value_Get(%d, &DOOutputValue), return code = %d\r\n", doSlot, rc);
exit(1);
}
else
{
if(DOOutputValue & (1 << doChannel)) DOChannelValue = 1;
else DOChannelValue = 0;
}
rc = MX_RTU_Module_AI_Eng_Value_Get(aiSlot, aiChannel, 1, &aiValue, &time);
if(rc != MODULE_RW_ERR_OK)
{
printf("MX_RTU_Module_AI_Eng_Value_Get(%d, %d, %d, &aiValue, &time), return code = %d\r\n", aiSlot, aiChannel, 1, rc);
exit(1);
}
//bool tag
memset(&boolTagInfo, 0, sizeof(boolTagInfo));
sprintf((char*)boolTagInfo.strTagName, "do-%d-%d", doSlot, doChannel);
sprintf((char*)boolTagInfo.strTagDescription, "bool tag des");
sprintf((char*)boolTagInfo.strTagUnit, "bool");
boolTagInfo.tagValueType = TAG_TYPE_BOOL;//tag type
boolTagInfo.tagAccessRight = TAG_ACC_READ_WRITE; //read/writable
boolTagInfo.tagCallBack = doWriteCallback;//write callback
boolTagInfo.tagValue = (void *)&DOChannelValue;
//float tag
memset(&floatTagInfo, 0, sizeof(floatTagInfo));
sprintf((char*)floatTagInfo.strTagName, "ai-%d-%d", aiSlot, aiChannel);
sprintf((char*)floatTagInfo.strTagDescription, "float tag des");
sprintf((char*)floatTagInfo.strTagUnit, "float");
floatTagInfo.tagValueType = TAG_TYPE_FLOAT;//tag type
floatTagInfo.tagAccessRight = TAG_ACC_READ; //read only
floatTagInfo.tagCallBack = NULL;//write callback
floatTagInfo.tagQuality = TAG_QUALITY_GOOD;
floatTagInfo.tagValue = (void *)&aiValue;
rc = MX_RTU_AOPC_AddTag(sHandle, &boolTagInfo, NULL, timeoutMs);
if(rc != MODULE_RW_ERR_OK)
{
printf("MX_RTU_AOPC_AddTag(%d, &boolTagInfo, %d), return code = %d\r\n", sHandle, timeoutMs, rc);
exit(1);
}
rc = MX_RTU_AOPC_AddTag(sHandle, &floatTagInfo, NULL, timeoutMs);
if(rc != MODULE_RW_ERR_OK)
{
printf("MX_RTU_AOPC_AddTag(%d, &floatTagInfo, %d), return code = %d\r\n", sHandle, timeoutMs, rc);
exit(1);
}
printf("Please keyin 'u' to update AI.\r\n");
ch = getchar();
while(1)
{
chIgnore = getchar();
if(chIgnore == 0xa) break;
}
if(ch == 'u')
{
rc = MX_RTU_Module_AI_Eng_Value_Get(aiSlot, aiChannel, 1, &aiValue, &time);
if(rc != MODULE_RW_ERR_OK)
{
printf("MX_RTU_Module_AI_Eng_Value_Get(%d, %d, %d, &aiValue, &time), return code = %d\r\n", aiSlot, aiChannel, 1, rc);
exit(1);
}
while(retry--)
{
rc = MX_RTU_AOPC_UpdateValue(sHandle, floatTagInfo.strTagName, (void *)&aiValue, &time, timeoutMs);
if(rc == AOPC_ERR_SOCKET)
{
rc = MX_RTU_AOPC_Reconnect(sHandle, timeoutMs);
if(rc != MODULE_RW_ERR_OK)
{
printf("MX_RTU_AOPC_Reconnect(%d, %d), return code = %d\r\n", sHandle, timeoutMs, rc);
exit(1);
}
if(retry == 0)
{
printf("Retry fail!\r\n");
exit(1);
}
continue;
}
else if(rc != MODULE_RW_ERR_OK)
{
printf("MX_RTU_AOPC_UpdateValue(%d, %s, %f, %d), return code = %d\r\n", sHandle, floatTagInfo.strTagName, aiValue, timeoutMs, rc);
exit(1);
}
else
{
printf("Please check AI value of AOPC Server, and press 'Enter' to exit.\r\n");
ch = getchar();
break;
}
}
}
rc = MX_RTU_AOPC_DelTag(sHandle, boolTagInfo.strTagName, timeoutMs);
if(rc != MODULE_RW_ERR_OK)
{
printf("MX_RTU_AOPC_DelTag(%d, %s, %d), return code = %d\r\n", sHandle, boolTagInfo.strTagName, timeoutMs, rc);
exit(1);
}
rc = MX_RTU_AOPC_DelTag(sHandle, floatTagInfo.strTagName, timeoutMs);
if(rc != MODULE_RW_ERR_OK)
{
printf("MX_RTU_AOPC_DelTag(%d, %s, %d), return code = %d\r\n", sHandle, floatTagInfo.strTagName, timeoutMs, rc);
exit(1);
}
return 0;
}

Variable Documentation

UINT8 DOChannelValue = 0
UINT32 DOOutputValue = 0