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

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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

Copyright
  Moxa Inc.

Date
  04-10-2013

Author
  Eddy Kao

Version
  V1.0
  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_USER_WRITE;
}
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 0;
}
}
if(ipFlag == 0)
{
printf("No IP\r\n");
exit(1);
}
rc = MX_RTU_AOPC_Init();
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);
MX_RTU_AOPC_Uninit();
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);
MX_RTU_AOPC_Disconnect(sHandle);
MX_RTU_AOPC_Uninit();
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);
MX_RTU_AOPC_Disconnect(sHandle);
MX_RTU_AOPC_Uninit();
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);
MX_RTU_AOPC_Disconnect(sHandle);
MX_RTU_AOPC_Uninit();
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.tagQuality = TAG_QUALITY_GOOD;
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);
MX_RTU_AOPC_Disconnect(sHandle);
MX_RTU_AOPC_Uninit();
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);
MX_RTU_AOPC_Disconnect(sHandle);
MX_RTU_AOPC_Uninit();
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);
MX_RTU_AOPC_Disconnect(sHandle);
MX_RTU_AOPC_Uninit();
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);
MX_RTU_AOPC_Disconnect(sHandle);
MX_RTU_AOPC_Uninit();
exit(1);
}
if(retry == 0)
{
printf("Retry fail!\r\n");
MX_RTU_AOPC_Disconnect(sHandle);
MX_RTU_AOPC_Uninit();
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);
MX_RTU_AOPC_Disconnect(sHandle);
MX_RTU_AOPC_Uninit();
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);
MX_RTU_AOPC_Disconnect(sHandle);
MX_RTU_AOPC_Uninit();
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);
MX_RTU_AOPC_Disconnect(sHandle);
MX_RTU_AOPC_Uninit();
exit(1);
}
MX_RTU_AOPC_Disconnect(sHandle);
MX_RTU_AOPC_Uninit();
return 0;
}

## Variable Documentation

UINT8 DOChannelValue = 0

UINT32 DOOutputValue = 0