1563 lines
56 KiB
C++
1563 lines
56 KiB
C++
#include "host_modbus_tcp.h"
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
//Valid slave device addresses are in the range of 0 锟?C 247 decimal. //
|
||
//The individual slave devices are assigned addresses in the range of 1 锟?C 247. //
|
||
//Address 0 is used for the broadcast address, which all slave devices recognize.//
|
||
///////////////////////////////////////////////////////////////////////////////////
|
||
#define HAVE_FTP_PROCESS
|
||
#ifdef HAVE_FTP_PROCESS
|
||
|
||
#define MODBUSP_READ_ID 100 //读取文件及文件夹ID
|
||
#define MODBUSP_READ_ID_FUNCCODE 0x03 //读取文件及文件夹ID功能码。
|
||
#define MODBUSP_READ_ID_REGISTER_ADDRESS 150 //读取文件及文件夹ID寄存器地址。
|
||
#define MODBUSP_READ_ID_REGISTER_LENGTH 9 //读取文件及文件夹ID寄存器长度。
|
||
|
||
#include <curl/curl.h>
|
||
|
||
struct CustomProgress
|
||
{
|
||
curl_off_t lastruntime;
|
||
CURL *curl;
|
||
};
|
||
|
||
static int progressCallback(void* p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
|
||
{
|
||
struct CustomProgress *progress = (struct CustomProgress *)p;
|
||
CURL *curl = progress->curl;
|
||
curl_off_t curtime = 0;
|
||
|
||
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &curtime);
|
||
if ((curtime - progress->lastruntime) >= 3000000) {
|
||
progress->lastruntime = curtime;
|
||
fprintf(stderr, "Total time: %f\n", curtime);
|
||
}
|
||
fprintf(stderr, "UP: %ld bytes of %ld bytes, DOWN: %ld bytes of %ld bytes.\n", ulnow, ultotal, dlnow, dltotal);
|
||
if (ultotal) fprintf(stderr, "UP progress: %0.2f\n", float(ulnow /ultotal));
|
||
if (dltotal) fprintf(stderr, "DOWN progress: %0.2f\n", float(dlnow /dltotal));
|
||
return 0;
|
||
}
|
||
|
||
static size_t getContentLengthFunc(void *ptr, size_t size, size_t nmemb, void *stream)
|
||
{
|
||
int r;
|
||
long len = 0;
|
||
|
||
r = sscanf((const char*)ptr, "Content-Length: %ld\n", &len);
|
||
if (r) *((long *)stream) = len;
|
||
return size * nmemb;
|
||
}
|
||
|
||
static size_t discardFunc(void *ptr, size_t size, size_t nmemb, void *stream)
|
||
{
|
||
return size * nmemb;
|
||
}
|
||
|
||
static size_t writefunc(void* ptr, size_t size, size_t nmemb, FILE* stream)
|
||
{
|
||
return fwrite(ptr, size, nmemb, stream);
|
||
}
|
||
|
||
static int ftpget(const char* remote, const char* local, const char* user, const char* pwd, const long timeout = 3)
|
||
{
|
||
vLog(LOG_DEBUG, "start to get %s to local %s, with name: %s, and password: %s.\n", remote, local, user, pwd);
|
||
curl_global_init(CURL_GLOBAL_ALL);
|
||
CURL* curl = curl_easy_init();
|
||
|
||
char user_key[1024] = {0};
|
||
snprintf(user_key, sizeof(user_key), "%s:%s", user, pwd);
|
||
|
||
FILE *file;
|
||
curl_off_t local_file_len = -1;
|
||
long filesize = 0;
|
||
CURLcode ret = CURLE_GOT_NOTHING;
|
||
struct stat file_info;
|
||
int use_resume = 0;
|
||
|
||
if (stat(local, &file_info) == 0) {
|
||
local_file_len = file_info.st_size;
|
||
use_resume = 1;
|
||
}
|
||
file = fopen(local, "ab+");
|
||
if (file == NULL) {
|
||
vLog(LOG_ERROR, "open file error(%d,%s)\n", errno, strerror(errno));
|
||
return 0;
|
||
}
|
||
|
||
curl_easy_setopt(curl, CURLOPT_URL, remote);
|
||
curl_easy_setopt(curl, CURLOPT_USERPWD, user_key);
|
||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout);
|
||
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, getContentLengthFunc);
|
||
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &filesize);
|
||
curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, use_resume ? local_file_len : 0);
|
||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
|
||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
|
||
ret = curl_easy_perform(curl);
|
||
fclose(file);
|
||
|
||
vLog(LOG_DEBUG, "curl easy perform return value is: %d, and OK is: %d.\n", ret, CURLE_OK);
|
||
int curl_state = 0;
|
||
if (ret == CURLE_OK) curl_state = 1;
|
||
else {
|
||
vLog(LOG_ERROR, "%d,%s\n", ret, curl_easy_strerror(ret));
|
||
curl_state = 0;
|
||
}
|
||
|
||
curl_easy_cleanup(curl);
|
||
curl_global_cleanup();
|
||
|
||
return curl_state;
|
||
}
|
||
|
||
static void* ryftp_process(void* param)
|
||
{
|
||
if (param == NULL) return ((void*)0);
|
||
|
||
CHostModbusTcpProcess* mbt = (CHostModbusTcpProcess *)param;
|
||
|
||
//获取此协议配置里面的ftp信息
|
||
char remote_filename[64];
|
||
char remote_dirent[64];
|
||
char remote[256];
|
||
char name[128];
|
||
char local_filename[64];
|
||
char local_dirent[128];
|
||
|
||
//默认参数,或是通过协议配置获取
|
||
char user[128] = "administrator";
|
||
char password[128] = "123456";
|
||
char ipaddress[128] = "127.0.0.1";
|
||
|
||
//根据协议创建一个本地协议目录
|
||
int pid = mbt->GetCurID();
|
||
if (pid < 0 || pid >= PROCESSES_NUM) return ((void*)0);
|
||
char pathName[128];
|
||
snprintf(pathName, sizeof(pathName), "%d", pid);
|
||
if (mbt->_mkdir(pathName) < 0) return ((void*)0);
|
||
|
||
//配置的用户名和密码
|
||
#if 0
|
||
snprintf(user, sizeof(user), "%s", mbt->m_user);
|
||
snprintf(password, sizeof(password), "%s", mbt->m_password);
|
||
#endif
|
||
char str[60];
|
||
DWORD target_addr = mbt->target_addr;
|
||
|
||
memset(str, '\0', sizeof(str));
|
||
inet_ntop(AF_INET, &target_addr, str, 16);
|
||
|
||
int i = 1;
|
||
while (TRUE) {
|
||
sleep(1); //每秒执行一次
|
||
//ftp获取文件
|
||
if (mbt->m_iv == 1) {
|
||
//文件目录无效
|
||
continue;
|
||
}
|
||
snprintf(name, sizeof(name), "%s/%d", pathName, mbt->m_currentFileNo);
|
||
snprintf(remote, sizeof(remote), "ftp://%s/data/rtdatalog/%d/%d", str, mbt->m_currentDirNo, mbt->m_currentFileNo);
|
||
|
||
if (ftpget(remote, name, user, password)) {
|
||
//成功,处理文件
|
||
vLog(LOG_DEBUG, "get a file, then send to ws.\n");
|
||
mbt->m_lastFileNo = mbt->m_currentFileNo;
|
||
mbt->m_currentFileNo++;
|
||
if ((mbt->m_currentFileNo - mbt->m_lastStartFileNo) % 1000 == 0) {
|
||
//一个文件夹最多存放1000个文件, mbt->m_currentFileNo = 0;
|
||
mbt->m_currentDirNo++;
|
||
mbt->m_lastStartFileNo = mbt->m_currentFileNo;
|
||
if (mbt->m_currentDirNo >= 56) { //7天数据大约有56个文件夹
|
||
mbt->m_currentDirNo = 0;
|
||
}
|
||
//保存文件信息
|
||
}
|
||
}
|
||
}
|
||
|
||
pthread_exit(0);
|
||
|
||
return ((void*)0);
|
||
}
|
||
|
||
#endif
|
||
|
||
|
||
CHostModbusTcpProcessItem::CHostModbusTcpProcessItem()
|
||
{
|
||
m_nNum = 0;
|
||
m_nFramePoll = 0;
|
||
apdu_t0_begin = 1;
|
||
m_nCurFrame = 0;
|
||
|
||
memset(m_nModbusFrames, 0, sizeof(m_nModbusFrames));
|
||
}
|
||
|
||
CHostModbusTcpProcessItem::~CHostModbusTcpProcessItem()
|
||
{
|
||
m_nNum = 0;
|
||
m_nFramePoll = 0;
|
||
apdu_t0_begin = 1;
|
||
m_nCurFrame = 0;
|
||
|
||
memset(m_nModbusFrames, 0, sizeof(m_nModbusFrames));
|
||
}
|
||
|
||
void CHostModbusTcpProcessItem::AddFrames(struModbusExtFrame* yxs, struModbusExtFrame* ycs, struModbusExtFrame* yms)
|
||
{
|
||
int i = 0, j = 0;
|
||
memset(m_nModbusFrames, 0, sizeof(m_nModbusFrames));
|
||
for (j = 0; j < MODBUS_RTU_AUTOMATIC_FRAME; j++)
|
||
{
|
||
if (yxs[j].FrameType == 0 || yxs[j].FuncCode == 0 || yxs[j].RegCount == 0) continue;
|
||
memcpy(&m_nModbusFrames[i], &yxs[j], sizeof(struModbusExtFrame));
|
||
i++;
|
||
if (i >= MODBUS_RTU_AUTOMATIC_FRAME_MAX) break;
|
||
}
|
||
for (j = 0; j < MODBUS_RTU_AUTOMATIC_FRAME; j++)
|
||
{
|
||
if (ycs[j].FrameType == 0 || ycs[j].FuncCode == 0 || ycs[j].RegCount == 0) continue;
|
||
memcpy(&m_nModbusFrames[i], &ycs[j], sizeof(struModbusExtFrame));
|
||
i++;
|
||
if (i >= MODBUS_RTU_AUTOMATIC_FRAME_MAX) break;
|
||
}
|
||
for (j = 0; j < MODBUS_RTU_AUTOMATIC_FRAME; j++)
|
||
{
|
||
if (yms[j].FrameType == 0 || yms[j].FuncCode == 0 || yms[j].RegCount == 0) continue;
|
||
memcpy(&m_nModbusFrames[i], &yms[j], sizeof(struModbusExtFrame));
|
||
i++;
|
||
if (i >= MODBUS_RTU_AUTOMATIC_FRAME_MAX) break;
|
||
}
|
||
}
|
||
|
||
struModbusExtFrame* CHostModbusTcpProcessItem::GetNextFrame(void)
|
||
{
|
||
int last;
|
||
|
||
if (m_nCurFrame >= MODBUS_RTU_AUTOMATIC_FRAME_MAX) return NULL;
|
||
if (m_nCurFrame < 0) m_nCurFrame = -1;
|
||
|
||
last = m_nCurFrame;
|
||
for (m_nCurFrame++; m_nCurFrame < MODBUS_RTU_AUTOMATIC_FRAME_MAX; m_nCurFrame++)
|
||
{
|
||
if (m_nModbusFrames[m_nCurFrame].FuncCode == 0 || m_nModbusFrames[m_nCurFrame].FrameType == 0) break;
|
||
return &m_nModbusFrames[m_nCurFrame];
|
||
}
|
||
for (m_nCurFrame = 0; m_nCurFrame <= last; m_nCurFrame++)
|
||
{
|
||
if (m_nModbusFrames[m_nCurFrame].FuncCode == 0 || m_nModbusFrames[m_nCurFrame].FrameType == 0) break;
|
||
return &m_nModbusFrames[m_nCurFrame];
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
void CHostModbusTcpProcessItem::Attach(int uid, int sock, DWORD peer_addr, WORD peer_port)
|
||
{
|
||
CNetProcessItem::Attach(uid, sock, peer_addr, peer_port);
|
||
apdu_t0_begin = 1;
|
||
m_nNum = 0;
|
||
m_nFramePoll = 0;
|
||
m_nCurFrame = 0;
|
||
}
|
||
|
||
void CHostModbusTcpProcessItem::Release(void)
|
||
{
|
||
apdu_t0_begin = 1;
|
||
m_nNum = 0;
|
||
m_nFramePoll = 0;
|
||
m_nCurFrame = 0;
|
||
|
||
CNetProcessItem::Release();
|
||
}
|
||
|
||
CHostModbusTcpProcess::CHostModbusTcpProcess(noPollConn *conn)
|
||
{
|
||
m_nCount = 0;
|
||
m_nFrameCount = 0;
|
||
m_nCurFrame = 0;
|
||
m_nSendPoint = 0;
|
||
m_nCurBeginReg = 0;
|
||
m_nNeedSend = FALSE;
|
||
|
||
//websocket接口
|
||
m_conn = NULL;
|
||
if (conn != NULL)
|
||
{
|
||
m_conn = conn;
|
||
}
|
||
|
||
m_pid = 0;
|
||
|
||
//目录无效
|
||
m_iv = 1;
|
||
|
||
m_currentDirNo = -1; //当前目录编号
|
||
m_currentFileNo = -1; //当前文件编号
|
||
m_lastDirNo = -1; //上一目录编号
|
||
m_lastFileNo = -1; //上一文件编号
|
||
}
|
||
|
||
CHostModbusTcpProcess::~CHostModbusTcpProcess()
|
||
{
|
||
}
|
||
|
||
CNetProcessItem *CHostModbusTcpProcess::CreateItem(int ord)
|
||
{
|
||
return dynamic_cast<CNetProcessItem *>(new CHostModbusTcpProcessItem);
|
||
}
|
||
|
||
void CHostModbusTcpProcess::DestroyItem(int ord, BOOLEAN bDeleted /* = FALSE */)
|
||
{
|
||
CHostModbusTcpProcessItem *pItem = (CHostModbusTcpProcessItem *)GetItem(ord);
|
||
if (pItem != NULL && !bDeleted)
|
||
{
|
||
delete pItem;
|
||
return CNetProcess::DestroyItem(ord, TRUE);
|
||
}
|
||
|
||
return CNetProcess::DestroyItem(ord, bDeleted);
|
||
}
|
||
|
||
void CHostModbusTcpProcess::sort1(STRUCT_PARAM *params, int count)
|
||
{
|
||
int i, j, n;
|
||
STRUCT_PARAM temp;
|
||
n = count;
|
||
for (i = 0; i < n - 1; ++i) //比较n-1轮
|
||
{
|
||
for (j = 0; j < n - 1 - i; ++j) //每轮比较n-1-i次,
|
||
{
|
||
if (params[j].param[0] > params[j + 1].param[0])
|
||
{
|
||
memcpy(&temp, ¶ms[j], sizeof(STRUCT_PARAM));
|
||
memcpy(¶ms[j], ¶ms[j + 1], sizeof(STRUCT_PARAM));
|
||
memcpy(¶ms[j + 1], &temp, sizeof(STRUCT_PARAM));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void CHostModbusTcpProcess::sort2(STRUCT_PARAM *params, int count)
|
||
{
|
||
int i, j, n;
|
||
STRUCT_PARAM temp;
|
||
n = count;
|
||
for (i = 0; i < n - 1; ++i) //比较n-1轮
|
||
{
|
||
for (j = 0; j < n - 1 - i; ++j) //每轮比较n-1-i次,
|
||
{
|
||
int addr1 = (int)MAKEWORD(params[j].param[1], params[j].param[2]);
|
||
int addr2 = (int)MAKEWORD(params[j+1].param[1], params[j+1].param[2]);
|
||
if (addr1 > addr2)
|
||
{
|
||
memcpy(&temp, ¶ms[j], sizeof(STRUCT_PARAM));
|
||
memcpy(¶ms[j], ¶ms[j + 1], sizeof(STRUCT_PARAM));
|
||
memcpy(¶ms[j + 1], &temp, sizeof(STRUCT_PARAM));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void CHostModbusTcpProcess::calc2(void)
|
||
{
|
||
int i, j, n, uid;
|
||
BYTE addr;
|
||
CHostModbusTcpProcessItem *pItem;
|
||
|
||
for (i = 0; i < PROCESS_UNIT_NUM; i++)
|
||
{
|
||
pItem = (CHostModbusTcpProcessItem *)GetItem(i);
|
||
if (NULL == pItem) continue;
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) continue;
|
||
|
||
if (GetUnitAddr(uid, &addr, 1))
|
||
{ //获取单元地址成功,则该段原地址采用配置地址,否则该单元为无效地址。
|
||
pItem->m_addr = addr;
|
||
}
|
||
struModbusExtFrame ycframes[MODBUS_RTU_AUTOMATIC_FRAME];
|
||
struModbusExtFrame ymframes[MODBUS_RTU_AUTOMATIC_FRAME];
|
||
struModbusExtFrame yxframes[MODBUS_RTU_AUTOMATIC_FRAME];
|
||
memset(ycframes, 0, sizeof(ycframes));
|
||
memset(ymframes, 0, sizeof(ymframes));
|
||
memset(yxframes, 0, sizeof(yxframes));
|
||
struUnitModbusOption option;
|
||
if (GetUnitOption(uid, &option, sizeof(option)))
|
||
{
|
||
if (option.use_owner_config)
|
||
{ //采用协议配置
|
||
if (option.modbus.yx1Enable)
|
||
{
|
||
yxframes[0].FrameType = MODBUSP_READ_YX1;
|
||
yxframes[0].FuncCode = option.modbus.yx1FuncCode;
|
||
yxframes[0].RegBegin = option.modbus.yx1Begin;
|
||
yxframes[0].RegCount = option.modbus.yx1Count;
|
||
}
|
||
if (option.modbus.yx2Enable)
|
||
{
|
||
yxframes[1].FrameType = MODBUSP_READ_YX1;
|
||
yxframes[1].FuncCode = option.modbus.yx2FuncCode;
|
||
yxframes[1].RegBegin = option.modbus.yx2Begin;
|
||
yxframes[1].RegCount = option.modbus.yx2Count;
|
||
}
|
||
if (option.modbus.yc1Enable)
|
||
{
|
||
ycframes[0].FrameType = MODBUSP_READ_YC1;
|
||
ycframes[0].FuncCode = option.modbus.yc1FuncCode;
|
||
ycframes[0].RegBegin = option.modbus.yc1Begin;
|
||
ycframes[0].RegCount = option.modbus.yc1Count;
|
||
}
|
||
if (option.modbus.yc2Enable)
|
||
{
|
||
ycframes[1].FrameType = MODBUSP_READ_YC1;
|
||
ycframes[1].FuncCode = option.modbus.yc2FuncCode;
|
||
ycframes[1].RegBegin = option.modbus.yc2Begin;
|
||
ycframes[1].RegCount = option.modbus.yc2Count;
|
||
}
|
||
if (option.modbus.yc3Enable)
|
||
{
|
||
ycframes[2].FrameType = MODBUSP_READ_YC1;
|
||
ycframes[2].FuncCode = option.modbus.yc3FuncCode;
|
||
ycframes[2].RegBegin = option.modbus.yc3Begin;
|
||
ycframes[2].RegCount = option.modbus.yc3Count;
|
||
}
|
||
if (option.modbus.yc4Enable)
|
||
{
|
||
ycframes[3].FrameType = MODBUSP_READ_YC1;
|
||
ycframes[3].FuncCode = option.modbus.yc4FuncCode;
|
||
ycframes[3].RegBegin = option.modbus.yc4Begin;
|
||
ycframes[3].RegCount = option.modbus.yc4Count;
|
||
}
|
||
if (option.modbus.ym1Enable)
|
||
{
|
||
ymframes[0].FrameType = MODBUSP_READ_YM1;
|
||
ymframes[0].FuncCode = option.modbus.ym1FuncCode;
|
||
ymframes[0].RegBegin = option.modbus.ym1Begin;
|
||
ymframes[0].RegCount = option.modbus.ym1Count;
|
||
}
|
||
if (option.modbus.ym2Enable)
|
||
{
|
||
ymframes[1].FrameType = MODBUSP_READ_YM1;
|
||
ymframes[1].FuncCode = option.modbus.ym2FuncCode;
|
||
ymframes[1].RegBegin = option.modbus.ym2Begin;
|
||
ymframes[1].RegCount = option.modbus.ym2Count;
|
||
}
|
||
//按寄存器排序
|
||
pItem->AddFrames(yxframes, ycframes, ymframes);
|
||
continue;
|
||
}
|
||
}
|
||
{
|
||
int yccount, ymcount, yxcount;
|
||
yccount = GetUnitYCCount(uid);
|
||
ymcount = GetUnitYMCount(uid);
|
||
yxcount = GetUnitYXCount(uid);
|
||
|
||
STRUCT_PARAM *ycparam = NULL, *ymparam = NULL, *yxparam = NULL;
|
||
if (yccount) ycparam = new STRUCT_PARAM[yccount];
|
||
if (ymcount) ymparam = new STRUCT_PARAM[ymcount];
|
||
if (yxcount) yxparam = new STRUCT_PARAM[yxcount];
|
||
#if 0
|
||
//插入一帧读取信息的报文
|
||
ycframes[0].FrameType = MODBUSP_READ_ID;
|
||
ycframes[0].FuncCode = MODBUSP_READ_ID_FUNCCODE;
|
||
ycframes[0].RegBegin = MODBUSP_READ_ID_REGISTER_ADDRESS;
|
||
ycframes[0].RegCount = MODBUSP_READ_ID_REGISTER_LENGTH;
|
||
|
||
j = 1;
|
||
#else
|
||
j = 0;
|
||
#endif
|
||
if (ycparam)
|
||
{
|
||
memset(ycparam, 0, sizeof(STRUCT_PARAM) * yccount);
|
||
for (n = 0; n < yccount; n++)
|
||
{
|
||
memcpy(ycparam[n].param, GetUnitYCParamByPoint(uid, n), sizeof(STRUCT_PARAM));
|
||
}
|
||
//按功能码排序
|
||
sort1(ycparam, yccount);
|
||
//按寄存器地址排序
|
||
sort2(ycparam, yccount);
|
||
//组帧
|
||
for (n = 0; n < yccount; n++)
|
||
{
|
||
WORD addr = MAKEWORD(ycparam[n].param[1], ycparam[n].param[2]);
|
||
if (addr >= 65535) continue;
|
||
for (; j < MODBUS_RTU_AUTOMATIC_FRAME; j++)
|
||
{
|
||
if (ycframes[j].FuncCode == 0)
|
||
{
|
||
ycframes[j].FrameType = MODBUSP_READ_YC1;
|
||
ycframes[j].FuncCode = ycparam[n].param[0];
|
||
ycframes[j].RegBegin = addr;
|
||
ycframes[j].RegCount = ycparam[n].param[3];
|
||
break;
|
||
}
|
||
if (ycframes[j].FuncCode == ycparam[n].param[0])
|
||
{
|
||
if (addr <= MODBUS_MAX_WORD_REGISTER_NUM + ycframes[j].RegBegin)
|
||
{
|
||
int len = addr - ycframes[j].RegBegin;
|
||
if (len)
|
||
{
|
||
ycframes[j].RegCount = len + ycparam[n].param[3];
|
||
}
|
||
else
|
||
{
|
||
vLog(LOG_DEBUG, "遥测测点配置了相同的功能码和寄存器地址\n");
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (ymparam)
|
||
{
|
||
memset(ymparam, 0, sizeof(STRUCT_PARAM) * ymcount);
|
||
for (n = 0; n < ymcount; n++)
|
||
{
|
||
memcpy(ymparam[n].param, GetUnitYMParamByPoint(uid, n), sizeof(STRUCT_PARAM));
|
||
}
|
||
sort1(ymparam, ymcount);
|
||
sort2(ymparam, ymcount);
|
||
//组帧
|
||
for (n = 0; n < ymcount; n++)
|
||
{
|
||
WORD addr = MAKEWORD(ymparam[n].param[1], ymparam[n].param[2]);
|
||
if (addr >= 65535) continue;
|
||
for (j = 0; j < MODBUS_RTU_AUTOMATIC_FRAME; j++)
|
||
{
|
||
if (ymframes[j].FuncCode == 0)
|
||
{
|
||
ymframes[j].FrameType = MODBUSP_READ_YM1;
|
||
ymframes[j].FuncCode = ymparam[n].param[0];
|
||
ymframes[j].RegBegin = addr;
|
||
ymframes[j].RegCount = ymparam[n].param[3];
|
||
break;
|
||
}
|
||
if (ymframes[j].FuncCode == ymparam[n].param[0])
|
||
{
|
||
if (addr <= MODBUS_MAX_WORD_REGISTER_NUM + ymframes[j].RegBegin)
|
||
{
|
||
int len = addr - ymframes[j].RegBegin;
|
||
if (len)
|
||
{
|
||
ymframes[j].RegCount = len + ymparam[n].param[3];
|
||
}
|
||
else
|
||
{
|
||
vLog(LOG_DEBUG, "遥脉测点配置了相同的功能码和寄存器地址\n");
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (yxparam)
|
||
{
|
||
memset(yxparam, 0, sizeof(STRUCT_PARAM) * yxcount);
|
||
for (n = 0; n < yxcount; n++)
|
||
{
|
||
memcpy(yxparam[n].param, GetUnitYXParamByPoint(uid, n), sizeof(STRUCT_PARAM));
|
||
}
|
||
sort1(yxparam, yxcount);
|
||
sort2(yxparam, yxcount);
|
||
//组帧
|
||
for (n = 0; n < yxcount; n++)
|
||
{
|
||
WORD addr = MAKEWORD(yxparam[n].param[1], yxparam[n].param[2]);
|
||
if (addr >= 65535) continue;
|
||
for (j = 0; j < MODBUS_RTU_AUTOMATIC_FRAME; j++)
|
||
{
|
||
if (yxframes[j].FuncCode == 0)
|
||
{
|
||
yxframes[j].FrameType = MODBUSP_READ_YX1;
|
||
yxframes[j].FuncCode = yxparam[n].param[0];
|
||
yxframes[j].RegBegin = addr;
|
||
yxframes[j].RegCount = 1;
|
||
break;
|
||
}
|
||
if (yxframes[j].FuncCode == yxparam[n].param[0])
|
||
{
|
||
int len = addr - yxframes[j].RegBegin;
|
||
if (len)
|
||
{
|
||
if (yxframes[j].FuncCode == MODBUSC_F01 || yxframes[j].FuncCode == MODBUSC_F02)
|
||
{
|
||
if (addr <= MODBUS_MAX_BITMAP_REGISTER_NUM + yxframes[j].RegBegin)
|
||
{
|
||
yxframes[j].RegCount = len + 1;
|
||
break;
|
||
}
|
||
}
|
||
else if (yxframes[j].FuncCode == MODBUSC_F03 || yxframes[j].FuncCode == MODBUSC_F04)
|
||
{
|
||
if (addr <= MODBUS_MAX_WORD_REGISTER_NUM + yxframes[j].RegBegin)
|
||
{
|
||
yxframes[j].RegCount = len + 1;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (yxframes[j].FuncCode == MODBUSC_F01 || yxframes[j].FuncCode == MODBUSC_F02)
|
||
{
|
||
vLog(LOG_DEBUG, "遥信测点配置了相同的功能码和寄存器地址\n");
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//按寄存器排序
|
||
pItem->AddFrames(yxframes, ycframes, ymframes);
|
||
}
|
||
}
|
||
}
|
||
|
||
BOOLEAN CHostModbusTcpProcess::OnPreCreate(int id)
|
||
{
|
||
if (!CNetProcess::OnPreCreate(id)) return FALSE;
|
||
|
||
m_nTimeout = 200;
|
||
calc2();
|
||
|
||
//启动后,创建ftp线程
|
||
if (m_pid <= 0) {
|
||
vLog(LOG_DEBUG, "create a ftp thread.\n");
|
||
|
||
pthread_attr_t attr;
|
||
pthread_attr_init(&attr);
|
||
pthread_attr_setstacksize(&attr, MEMERY_1M);
|
||
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
|
||
|
||
if (pthread_create(&m_pid, &attr, ryftp_process, this) < 0) {
|
||
vLog(LOG_ERROR, "create ryftp_process error(%d,%s).\n", errno, strerror(errno));
|
||
return TRUE;
|
||
}
|
||
char name[17];
|
||
snprintf(name, 16, "%s_ftp", GetCurProcessName());
|
||
pthread_setname_np(m_pid, name);
|
||
|
||
pthread_attr_destroy(&attr);
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CHostModbusTcpProcess::Run(void)
|
||
{
|
||
int count;
|
||
BYTE buffer[512];
|
||
|
||
if (!CNetProcess::Run()) return FALSE;
|
||
FeedDog();
|
||
|
||
//process polling command
|
||
CHostModbusTcpProcessItem *pItem = (CHostModbusTcpProcessItem *)GetItem(0);
|
||
if (NULL == pItem) return TRUE;
|
||
if (pItem->GetSock() < 0) {
|
||
usleep(20000);
|
||
return TRUE;
|
||
}
|
||
|
||
pItem = (CHostModbusTcpProcessItem *)GetCurItem();
|
||
if (NULL == pItem) return TRUE;
|
||
|
||
buffer[0] = HIBYTE(pItem->m_nNum); buffer[1] = LOBYTE(pItem->m_nNum);
|
||
buffer[2] = 0; buffer[3] = MB_TCP_PROTOCOL_ID;
|
||
if ((m_nCurFrame == 0 && m_nNeedSend))
|
||
{
|
||
count = 0;
|
||
if (GetYKFrame(pItem, &buffer[6], count, m_nCurFrame, m_nCurFuncCode))
|
||
{ //insert yk command
|
||
}
|
||
else if (GetYTFrame(pItem, &buffer[6], count, m_nCurFrame, m_nCurFuncCode))
|
||
{ //insert yt command
|
||
}
|
||
else if (pItem->m_nFramePoll & MODBUSP_SET_TIME_FRAME)
|
||
{
|
||
pItem->m_nFramePoll &= ~MODBUSP_SET_TIME_FRAME;
|
||
if (GetSetTimeFrame(pItem, &buffer[6], count))
|
||
{
|
||
m_nCurFrame = 0;
|
||
}
|
||
}
|
||
else if (pItem->m_nFramePoll & MODBUSP_GET_DATA_FRAME)
|
||
{
|
||
pItem->m_nFramePoll &= ~MODBUSP_GET_DATA_FRAME;
|
||
if (GetReadDataFrame(pItem, &buffer[6], count))
|
||
{
|
||
m_nCurFrame = m_nFrameType;
|
||
}
|
||
}
|
||
if (count >= 2)
|
||
{ //发送前清除接收缓冲区所有数据
|
||
buffer[4] = HIBYTE(count);
|
||
buffer[5] = LOBYTE(count);
|
||
if (WriteData(buffer, count + 6, 0))
|
||
{
|
||
DisplayTxData(buffer, count + 6, TRUE);
|
||
}
|
||
pItem->m_nNum++;
|
||
m_nSendPoint = system32.ticks;//0;
|
||
m_nNeedSend = FALSE;
|
||
|
||
//fprintf(stderr, "tx<%d>: ", count+6); for (int a = 0; a < count+6; a++) fprintf(stderr, "%02X ", buffer[a]); fprintf(stderr, "\n");
|
||
FeedDog();
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CHostModbusTcpProcess::OnTimer(void)
|
||
{
|
||
CHostModbusTcpProcessItem *pItem;
|
||
|
||
if (!CNetProcess::OnTimer()) return FALSE;
|
||
|
||
m_nCount++;
|
||
pItem = (CHostModbusTcpProcessItem *)GetItem(0);
|
||
if (NULL == pItem) return FALSE;
|
||
if (pItem->GetSock() < 0)
|
||
{
|
||
if ((pItem->apdu_t0_begin + 30) < system32.timers)
|
||
{
|
||
pItem->apdu_t0_begin = system32.timers;
|
||
Connect(pItem, 0, TRUE);
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
if (m_nCurFrame != 0)
|
||
{
|
||
if (m_nSendPoint && (m_nSendPoint + m_nTimeout) <= system32.ticks)
|
||
{ //0.5 second command time out
|
||
m_nSendPoint = 0;
|
||
m_nCurFrame = 0;
|
||
}
|
||
}
|
||
|
||
if (m_nCurFrame == 0 && (m_nCount % PollGap()) == 0)
|
||
{
|
||
pItem = (CHostModbusTcpProcessItem *)GetNextItem();
|
||
if (pItem == NULL) return TRUE;
|
||
m_nNeedSend = TRUE;
|
||
|
||
#if 1
|
||
//启动时读取一次,后面自己维护序号
|
||
if ((m_currentDirNo == -1) && (m_currentFileNo == -1))
|
||
{ //当前文件和目录都为-1,程序第一次启动。需要获取ftp目录及文件ID
|
||
m_nFrameType = MODBUSP_READ_ID;
|
||
m_nCurFuncCode = MODBUSP_READ_ID_FUNCCODE;
|
||
m_nCurBeginReg = MODBUSP_READ_ID_REGISTER_ADDRESS;
|
||
m_nCurRegCount = MODBUSP_READ_ID_REGISTER_LENGTH;
|
||
pItem->m_nFramePoll |= MODBUSP_GET_DATA_FRAME;
|
||
return TRUE;
|
||
}
|
||
#endif
|
||
struModbusExtFrame* frame = pItem->GetNextFrame();
|
||
if (frame != NULL)
|
||
{
|
||
m_nFrameType = frame->FrameType;
|
||
m_nCurFuncCode = frame->FuncCode;
|
||
m_nCurBeginReg = frame->RegBegin;
|
||
m_nCurRegCount = frame->RegCount;
|
||
pItem->m_nFramePoll |= MODBUSP_GET_DATA_FRAME;
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CHostModbusTcpProcess::GetYKFrame(CHostModbusTcpProcessItem *pItem, BYTE* pBuf, int& count, DWORD& frame, BYTE& FuncCode)
|
||
{
|
||
int uid;
|
||
BYTE result;
|
||
BYTE* pData;
|
||
|
||
if (NULL == pItem) return FALSE;
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
if (NULL == pBuf) return FALSE;
|
||
|
||
pData = pBuf;
|
||
if (!GetUnitYK(uid, m_nYKOrder, m_bYKValue, m_nYKState, result))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is %s result is %s.\n", uid, m_nYKOrder, (m_bYKValue ? "ClOSE" : "TRIP"), val_to_str(m_nYKState, yk_state, "STATE = %d"), val_to_str(result, yk_result, "RESULT = %d"));
|
||
|
||
BYTE* m_param;
|
||
BYTE nFun; //功能码
|
||
BOOLEAN nNeedSelect; //遥控需要选择
|
||
WORD nReg, nVal;
|
||
WORD nCloseSelReg, nCloseExecReg, nCloseEscReg, nCloseValue; //合闸命令参数
|
||
WORD nOpenSelReg, nOpenExecReg, nOpenEscReg, nOpenValue; //分闸命令参数
|
||
|
||
m_param = GetUnitYKParamByPoint(uid, m_nYKOrder);
|
||
if (NULL == m_param) return FALSE;
|
||
nFun = m_param[0]; //功能码占一个字节
|
||
nNeedSelect = m_param[1]; //遥控是否需要选择
|
||
nCloseSelReg = MAKEWORD(m_param[4], m_param[5]); //选择合寄存器
|
||
nCloseExecReg = MAKEWORD(m_param[6], m_param[7]); //执行合寄存器
|
||
nCloseEscReg = MAKEWORD(m_param[8], m_param[9]); //撤销合寄存器
|
||
nCloseValue = MAKEWORD(m_param[10], m_param[11]); //合
|
||
nOpenSelReg = MAKEWORD(m_param[12], m_param[13]); //选择分寄存器
|
||
nOpenExecReg = MAKEWORD(m_param[14], m_param[15]); //执行分寄存器
|
||
nOpenEscReg = MAKEWORD(m_param[16], m_param[17]); //撤销分寄存器
|
||
nOpenValue = MAKEWORD(m_param[18], m_param[19]); //分
|
||
if (m_nYKState == YKS_SELREQ)
|
||
{ //遥控选择
|
||
if (m_bYKValue)
|
||
{
|
||
nReg = nCloseSelReg;
|
||
nVal = nCloseValue;
|
||
}
|
||
else
|
||
{
|
||
nReg = nOpenSelReg;
|
||
nVal = nOpenValue;
|
||
}
|
||
if (0xffff == nReg || !nNeedSelect)
|
||
{ //寄存器无效,遥控无须选择
|
||
SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_SELED, YKR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_SELED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP"));
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
pData[0] = pItem->m_addr;
|
||
pData[1] = nFun;
|
||
pData[2] = (nReg >> 8) & 0x00ff;
|
||
pData[3] = nReg & 0x00ff;
|
||
pData[4] = (nVal >> 8) & 0x00ff;
|
||
pData[5] = nVal & 0x00ff;
|
||
count = 6;
|
||
FuncCode = nFun;
|
||
frame = MODBUSP_YK_SELECT;
|
||
return TRUE;
|
||
}
|
||
}
|
||
else if (m_nYKState == YKS_EXEREQ)
|
||
{ //遥控执行
|
||
if (m_bYKValue)
|
||
{
|
||
nReg = nCloseExecReg;
|
||
nVal = nCloseValue;
|
||
}
|
||
else
|
||
{
|
||
nReg = nOpenExecReg;
|
||
nVal = nOpenValue;
|
||
}
|
||
if (0xffff == nReg) return FALSE;
|
||
pData[0] = pItem->m_addr;
|
||
pData[1] = nFun;
|
||
pData[2] = (nReg >> 8) & 0x00ff;
|
||
pData[3] = nReg & 0x00ff;
|
||
pData[4] = (nVal >> 8) & 0x00ff;
|
||
pData[5] = nVal & 0x00ff;
|
||
count = 6;
|
||
FuncCode = nFun;
|
||
frame = MODBUSP_YK_EXECUTE;
|
||
return TRUE;
|
||
}
|
||
else if (m_nYKState == YKS_ABRREQ)
|
||
{ //遥控撤销
|
||
if (m_bYKValue)
|
||
{
|
||
nReg = nCloseEscReg;
|
||
nVal = nCloseValue;
|
||
}
|
||
else
|
||
{
|
||
nReg = nOpenEscReg;
|
||
nVal = nOpenValue;
|
||
}
|
||
if (0xffff == nReg || !nNeedSelect)
|
||
{ //寄存器无效
|
||
SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_ABRED, YKR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP"));
|
||
return FALSE;
|
||
}
|
||
pData[0] = pItem->m_addr;
|
||
pData[1] = nFun;
|
||
pData[2] = (nReg >> 8) & 0x00ff;
|
||
pData[3] = nReg & 0x00ff;
|
||
pData[4] = (nVal >> 8) & 0x00ff;
|
||
pData[5] = nVal & 0x00ff;
|
||
count = 6;
|
||
FuncCode = nFun;
|
||
frame = MODBUSP_YK_CANCEL;
|
||
return TRUE;
|
||
}
|
||
else if ((m_nYKState == YKS_SELING || m_nYKState == YKS_SELED) && result == YKR_OVER)
|
||
{ //遥控撤销
|
||
if (m_bYKValue)
|
||
{
|
||
nReg = nCloseEscReg;
|
||
nVal = nCloseValue;
|
||
}
|
||
else
|
||
{
|
||
nReg = nOpenEscReg;
|
||
nVal = nOpenValue;
|
||
}
|
||
if (0xffff == nReg || !nNeedSelect)
|
||
{ //寄存器无效
|
||
SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_ABRED, YKR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP"));
|
||
return FALSE;
|
||
}
|
||
pData[0] = pItem->m_addr;
|
||
pData[1] = nFun;
|
||
pData[2] = (nReg >> 8) & 0x00ff;
|
||
pData[3] = nReg & 0x00ff;
|
||
pData[4] = (nVal >> 8) & 0x00ff;
|
||
pData[5] = nVal & 0x00ff;
|
||
count = 6;
|
||
FuncCode = nFun;
|
||
frame = MODBUSP_YK_CANCEL;
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////
|
||
// yt start //
|
||
//////////////////////////////////////////////////////////////////////////
|
||
BOOLEAN CHostModbusTcpProcess::GetYTFrame(CHostModbusTcpProcessItem *pItem, BYTE* pBuf, int& count, DWORD& frame, BYTE& FuncCode)
|
||
{
|
||
int uid;
|
||
BYTE result;
|
||
BYTE* pData;
|
||
|
||
if (NULL == pItem) return FALSE;
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
|
||
if (NULL == pBuf) return FALSE;
|
||
|
||
pData = pBuf;
|
||
if (!GetUnitYT(uid, m_nYTOrder, m_dwYTValue, m_nYTState, result))
|
||
{
|
||
return FALSE;
|
||
}
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is %s result is %s.\n", uid, m_nYTOrder, m_dwYTValue, val_to_str(m_nYTState, yt_state, "STATE = %d"), val_to_str(result, yt_result, "RESULT = %d"));
|
||
BYTE* m_param;
|
||
BYTE nFun; //功能码
|
||
BYTE nSetType; //设置方式 0单寄存器,1双寄存器
|
||
BOOLEAN nNeedSelect; //遥设需要选择
|
||
WORD nReg = 0xffff;
|
||
WORD nSelReg, nExecReg, nEscReg; //合闸命令参数
|
||
|
||
m_param = GetUnitYTParamByPoint(uid, m_nYTOrder);
|
||
if (NULL == m_param) return FALSE;
|
||
nSetType = m_param[0]; //0 16位整型值;1 32位整型值;2 32位浮点数值;
|
||
nFun = m_param[1]; //功能码占一个字节
|
||
nNeedSelect = m_param[2]; //遥控是否需要选择
|
||
nSelReg = MAKEWORD(m_param[4], m_param[5]); //选择寄存器
|
||
nExecReg = MAKEWORD(m_param[6], m_param[7]); //执行寄存器
|
||
nEscReg = MAKEWORD(m_param[8], m_param[9]); //撤销寄存器
|
||
if (m_nYTState == YTS_SELREQ)
|
||
{ //遥设选择
|
||
nReg = nSelReg;
|
||
if (0xffff == nReg || !nNeedSelect)
|
||
{ //寄存器无效,遥设无须选择
|
||
SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_SELED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_SELED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue);
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
FuncCode = nFun;
|
||
frame = MODBUSP_YT_SELECT;
|
||
}
|
||
}
|
||
else if (m_nYTState == YTS_EXEREQ)
|
||
{ //遥设执行
|
||
nReg = nExecReg;
|
||
if (0xffff == nReg) return FALSE;
|
||
FuncCode = nFun;
|
||
frame = MODBUSP_YT_EXECUTE;
|
||
}
|
||
else if (m_nYTState == YTS_ABRREQ)
|
||
{ //遥设撤销
|
||
nReg = nEscReg;
|
||
if (0xffff == nReg || !nNeedSelect)
|
||
{ //寄存器无效
|
||
SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_ABRED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_ABRED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue);
|
||
return FALSE;
|
||
}
|
||
FuncCode = nFun;
|
||
frame = MODBUSP_YT_CANCEL;
|
||
}
|
||
else if ((m_nYTState == YTS_SELING || m_nYTState == YTS_SELED) && result == YTR_OVER)
|
||
{ //遥设撤销
|
||
nReg = nEscReg;
|
||
if (0xffff == nReg || !nNeedSelect)
|
||
{ //寄存器无效
|
||
SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_ABRED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_ABRED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue);
|
||
return FALSE;
|
||
}
|
||
FuncCode = nFun;
|
||
frame = MODBUSP_YT_CANCEL;
|
||
}
|
||
//modify by assouan for clean;
|
||
pData[0] = pItem->m_addr;
|
||
pData[1] = nFun;
|
||
pData[2] = (nReg >> 8) & 0x00ff;
|
||
pData[3] = nReg & 0x00ff;
|
||
if (nFun == MODBUSC_F06)
|
||
{
|
||
pData[4] = (m_dwYTValue >> 8) & 0x00ff;
|
||
pData[5] = m_dwYTValue & 0x00ff;
|
||
count = 6;
|
||
}
|
||
else if (nFun == MODBUSC_F16)
|
||
{
|
||
if (nSetType == 0)
|
||
{
|
||
pData[4] = 0x00;
|
||
pData[5] = 0x01;
|
||
pData[6] = 0x02;
|
||
pData[7] = (m_dwYTValue >> 8) & 0x00ff;
|
||
pData[8] = m_dwYTValue & 0x00ff;
|
||
count = 9;
|
||
}
|
||
else if (nSetType == 1)
|
||
{
|
||
pData[4] = 0x00;
|
||
pData[5] = 0x02;
|
||
pData[6] = 0x04;
|
||
pData[7] = (m_dwYTValue >> 24) & 0x00ff;
|
||
pData[8] = (m_dwYTValue >> 16) & 0x00ff;
|
||
pData[9] = (m_dwYTValue >> 8) & 0x00ff;
|
||
pData[10] = m_dwYTValue & 0x00ff;
|
||
count = 11;
|
||
}
|
||
else if (nSetType == 2)
|
||
{
|
||
pData[4] = 0x00;
|
||
pData[5] = 0x02;
|
||
pData[6] = 0x04;
|
||
pData[7] = (m_dwYTValue >> 8) & 0x00ff;
|
||
pData[8] = m_dwYTValue & 0x00ff;
|
||
pData[9] = (m_dwYTValue >> 24) & 0x00ff;
|
||
pData[10] = (m_dwYTValue >> 16) & 0x00ff;
|
||
|
||
count = 11;
|
||
}
|
||
}
|
||
else return FALSE;
|
||
return TRUE;
|
||
}
|
||
//////////////////////////////////////////////////////////////////////////
|
||
// yt end //
|
||
//////////////////////////////////////////////////////////////////////////
|
||
|
||
BOOLEAN CHostModbusTcpProcess::GetSetTimeFrame(CHostModbusTcpProcessItem *pItem, BYTE* /*pData*/, int& /*count*/)
|
||
{
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CHostModbusTcpProcess::GetReadDataFrame(CHostModbusTcpProcessItem *pItem, BYTE* pData, int& count)
|
||
{
|
||
if (NULL == pItem) return FALSE;
|
||
|
||
if (m_nFrameType == 0) return FALSE;
|
||
if (m_nCurFuncCode == 0) return FALSE;
|
||
|
||
pData[0] = pItem->m_addr;
|
||
pData[1] = (BYTE)m_nCurFuncCode;
|
||
pData[2] = (m_nCurBeginReg >> 8) & 0x00ff;
|
||
pData[3] = m_nCurBeginReg & 0x00ff;
|
||
pData[4] = (m_nCurRegCount >> 8) & 0x00ff;
|
||
pData[5] = m_nCurRegCount & 0x00ff;
|
||
|
||
count = 6;
|
||
return TRUE;
|
||
}
|
||
|
||
int CHostModbusTcpProcess::OnPackageReceived(BYTE* pBuf, int count, int ord)
|
||
{
|
||
int uid;
|
||
if (count < 6)
|
||
{ //数据长度不足
|
||
return 0;
|
||
}
|
||
CHostModbusTcpProcessItem* pItem;
|
||
pItem = (CHostModbusTcpProcessItem *)GetItem(ord);
|
||
if (NULL == pItem) return -1;
|
||
//头尾判断。
|
||
WORD protocol, len;
|
||
protocol = MAKEWORD(pBuf[3], pBuf[2]);
|
||
len = MAKEWORD(pBuf[5], pBuf[4]);
|
||
if (count < len + 6)
|
||
{ //数据接收未完
|
||
return 0;
|
||
}
|
||
|
||
if (protocol != MB_TCP_PROTOCOL_ID)
|
||
{ //未知协议
|
||
return -1;
|
||
}
|
||
BYTE* buffer = &pBuf[6];
|
||
if (((buffer[1] & 0x7f) != MODBUSC_F01) && ((buffer[1] & 0x7f) != MODBUSC_F02) &&
|
||
((buffer[1] & 0x7f) != MODBUSC_F03) && ((buffer[1] & 0x7f) != MODBUSC_F04) &&
|
||
((buffer[1] & 0x7f) != MODBUSC_F05) && ((buffer[1] & 0x7f) != MODBUSC_F06) &&
|
||
((buffer[1] & 0x7f) != MODBUSC_F07) && ((buffer[1] & 0x7f) != MODBUSC_F08) &&
|
||
((buffer[1] & 0x7f) != MODBUSC_F11) && ((buffer[1] & 0x7f) != MODBUSC_F12) &&
|
||
((buffer[1] & 0x7f) != MODBUSC_F15) && ((buffer[1] & 0x7f) != MODBUSC_F16) &&
|
||
((buffer[1] & 0x7f) != MODBUSC_F17) && ((buffer[1] & 0x7f) != MODBUSC_F20) &&
|
||
((buffer[1] & 0x7f) != MODBUSC_F21) && ((buffer[1] & 0x7f) != MODBUSC_F22) &&
|
||
((buffer[1] & 0x7f) != MODBUSC_F23) && ((buffer[1] & 0x7f) != MODBUSC_F24) &&
|
||
((buffer[1] & 0x7f) != MODBUSC_F43) && ((buffer[1] & 0x7f) != MODBUSC_F26))
|
||
{ //不支持的功能码
|
||
return -1;
|
||
}
|
||
if ((buffer[1] & 0x80) == 0x80)
|
||
{ //错误代码
|
||
m_nCurFrame = 0;
|
||
}
|
||
//根据地址查找单元id
|
||
uid = GetUnitByAddr(buffer, 1);
|
||
if (uid < 0 || uid >= UNIT_NUM) return (len + 6);
|
||
int order = GetOrderByUnitID(uid);
|
||
if (order < 0 || order >= PROCESS_UNIT_NUM) return (len + 6);
|
||
pItem = (CHostModbusTcpProcessItem *)GetItem(order);
|
||
if (NULL == pItem) return (len + 6);
|
||
if (OnReceiveData(pItem, buffer, (len - 3)))
|
||
{
|
||
m_nCurFrame = 0;
|
||
}
|
||
DisplayRxData(pBuf, (len + 6), TRUE, uid);
|
||
UnitFeedDog(uid);
|
||
return (len + 6);
|
||
}
|
||
|
||
BOOLEAN CHostModbusTcpProcess::OnReceiveData(CHostModbusTcpProcessItem *pItem, BYTE* pData, int count)
|
||
{
|
||
int uid;
|
||
if (NULL == pItem) return FALSE;
|
||
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0) return FALSE;
|
||
|
||
UnitFeedDog(uid);
|
||
|
||
if (pData[1] == m_nCurFuncCode)
|
||
{
|
||
if (m_nCurFrame == MODBUSP_READ_YX1)
|
||
{
|
||
return OnReceiveYXData(pItem, &pData[3], count);
|
||
}
|
||
else if (m_nCurFrame == MODBUSP_READ_YC1)
|
||
{
|
||
return OnReceiveYCData(pItem, &pData[3], count);
|
||
}
|
||
else if (m_nCurFrame == MODBUSP_READ_YM1)
|
||
{
|
||
return OnReceiveYMData(pItem, &pData[3], count);
|
||
}
|
||
else if (m_nCurFrame == MODBUSP_READ_ID)
|
||
{
|
||
return OnReceiveIDData(pItem, &pData[3], count);
|
||
}
|
||
else if (m_nCurFrame == MODBUSP_YK_EXECUTE)
|
||
{
|
||
SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_EXEED, YKR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_EXEED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP"));
|
||
return TRUE;
|
||
}
|
||
else if (MODBUSP_YK_SELECT == m_nCurFrame)
|
||
{
|
||
SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_SELED, YKR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_SELED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP"));
|
||
return TRUE;
|
||
}
|
||
else if (MODBUSP_YK_CANCEL == m_nCurFrame)
|
||
{
|
||
SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_ABRED, YKR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP"));
|
||
return TRUE;
|
||
}
|
||
else if (MODBUSP_YT_EXECUTE == m_nCurFrame)
|
||
{
|
||
SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_EXEED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_EXEED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue);
|
||
return TRUE;
|
||
}
|
||
else if (MODBUSP_YT_SELECT == m_nCurFrame)
|
||
{
|
||
SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_SELED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_SELED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue);
|
||
return TRUE;
|
||
}
|
||
else if (MODBUSP_YT_CANCEL == m_nCurFrame)
|
||
{
|
||
SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_ABRED, YTR_SUCC);
|
||
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_ABRED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue);
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN CHostModbusTcpProcess::OnReceiveIDData(CHostModbusTcpProcessItem *pItem, BYTE* pData, int count)
|
||
{
|
||
int i;
|
||
int point;
|
||
int uid;
|
||
BYTE* pBuf;
|
||
|
||
if (pItem == NULL) return FALSE;
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0) return FALSE;
|
||
|
||
pBuf = pData;
|
||
|
||
/*
|
||
1)、路径信息是否有效 byte;
|
||
2)、当前文件夹路径名的后缀 dint,按照顺序增加1(转字符串时在前补0);
|
||
3)、当前文件夹下最后新文件的编号 dint;
|
||
4)、当前文件夹下第一个文件的编号 dint;
|
||
5)、当前文件夹下文件个数 dint;
|
||
*/
|
||
//路径有效性判断
|
||
int iv = ((pBuf[0] << 8) | pBuf[1]); pBuf += 2;
|
||
|
||
m_iv = iv;
|
||
if (iv) {
|
||
vLog(LOG_DEBUG, "路径信息无效\n");
|
||
return FALSE;
|
||
}
|
||
//当前文件夹路径名
|
||
m_currentDirNo = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]); pBuf += 4;
|
||
//当前文件夹下最后新文件
|
||
m_currentFileNo = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]); pBuf += 4;
|
||
//当前文件夹下第一个文件
|
||
m_lastStartFileNo = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]); pBuf += 4;
|
||
|
||
vLog(LOG_DEBUG, "dir: %d, file: %d: start: %d\n", m_currentDirNo, m_currentFileNo, m_lastStartFileNo);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CHostModbusTcpProcess::OnReceiveYXData(CHostModbusTcpProcessItem *pItem, BYTE* pData, int count)
|
||
{
|
||
int uid;
|
||
int i, j;
|
||
int point;
|
||
BYTE param[4];
|
||
WORD reg;
|
||
|
||
BOOLEAN yxVal;
|
||
|
||
if (pItem == NULL) return FALSE;
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0) return FALSE;
|
||
|
||
reg = m_nCurBeginReg;
|
||
param[0] = m_nCurFuncCode;
|
||
if (MODBUSC_F03 == m_nCurFuncCode || MODBUSC_F04 == m_nCurFuncCode)
|
||
{ //03功能码读取Holdings
|
||
WORD nValue;
|
||
WORD nTemp = 0x0001;
|
||
for (i = 0; i < count; i += 2)
|
||
{
|
||
nValue = (pData[i] << 8) | pData[i+1];
|
||
nTemp = 0x0001;
|
||
param[1] = LOBYTE(reg);
|
||
param[2] = HIBYTE(reg);
|
||
reg++;
|
||
for (j = 0; j < 16; j++)
|
||
{
|
||
param[3] = j;
|
||
point = GetUnitYXPointByParam(uid, param, 4);
|
||
if (point >= 0)
|
||
{
|
||
yxVal = SPI_OFF;
|
||
if ((nValue) & nTemp)
|
||
{
|
||
yxVal = SPI_ON;
|
||
}
|
||
SetUnitYX(uid, point, yxVal);
|
||
}
|
||
nTemp <<= 1;
|
||
}
|
||
}
|
||
}
|
||
else if (MODBUSC_F01 == m_nCurFuncCode || MODBUSC_F02 == m_nCurFuncCode)
|
||
{ //01 02功能码读取Coils和Status
|
||
BYTE *nValue = pData;
|
||
BYTE nTemp = 0x01;
|
||
for (i = 0; i < count; i++)
|
||
{
|
||
nTemp = 0x01;
|
||
for (j = 0; j < 8; j++)
|
||
{
|
||
param[1] = LOBYTE(reg);
|
||
param[2] = HIBYTE(reg);
|
||
reg++;
|
||
point = GetUnitYXPointByParam(uid, param, 3);
|
||
if (point >= 0)
|
||
{
|
||
yxVal = SPI_OFF;
|
||
if ((*nValue) & nTemp)
|
||
{
|
||
yxVal = SPI_ON;
|
||
}
|
||
SetUnitYX(uid, point, yxVal);
|
||
}
|
||
nTemp <<= 1;
|
||
}
|
||
nValue++;
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CHostModbusTcpProcess::OnReceiveYCData(CHostModbusTcpProcessItem *pItem, BYTE* pData, int count)
|
||
{
|
||
int uid;
|
||
int i;
|
||
BYTE* pBuf;
|
||
BYTE* pParam;
|
||
BYTE param[8];
|
||
DWORD nValue = 0;
|
||
LONG bin_value;
|
||
float f_val;
|
||
int point;
|
||
WORD reg;
|
||
BYTE reg_count, value_type, sign_mark;
|
||
|
||
if (pItem == NULL) return FALSE;
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0) return FALSE;
|
||
|
||
pBuf = pData;
|
||
reg = m_nCurBeginReg;
|
||
param[0] = m_nCurFuncCode;
|
||
for (i = 0; i < count;)
|
||
{
|
||
param[1] = LOBYTE(reg);
|
||
param[2] = HIBYTE(reg);
|
||
point = GetUnitYCPointByParam(uid, param, 3);
|
||
|
||
if (point >= 0)
|
||
{ //获得合法点号
|
||
pParam = GetUnitYCParamByPoint(uid, point);
|
||
if (pParam != NULL)
|
||
{
|
||
reg_count = pParam[3];
|
||
value_type = pParam[4];
|
||
sign_mark = pParam[5];
|
||
if ((1 == reg_count) && (2 == value_type))
|
||
{ //16位归一化值
|
||
if (2 == value_type)
|
||
{
|
||
if (sign_mark == 0) nValue = (DWORD)(WORD)((pBuf[0] << 8) | pBuf[1]);
|
||
else nValue = (DWORD)(short)((pBuf[0] << 8) | pBuf[1]);
|
||
SetUnitYC(uid, point, (LONG)nValue);
|
||
}
|
||
else if (8 == value_type)
|
||
{
|
||
if (sign_mark == 0) nValue = (DWORD)(WORD)((pBuf[0] << 8) | pBuf[1]);
|
||
else nValue = (DWORD)(short)((pBuf[0] << 8) | pBuf[1]);
|
||
nValue = bcd_to_int((const BYTE*)&nValue, sizeof(WORD));
|
||
SetUnitYC(uid, point, (LONG)nValue);
|
||
}
|
||
pBuf += 2; i += 2; reg++;
|
||
}
|
||
else if (2 == reg_count)
|
||
{ //32位测量值
|
||
if (0 == value_type)
|
||
{ //浮点数,高位在第一个寄存器
|
||
nValue = (DWORD)(pBuf[0] << 24 | pBuf[1] << 16 | pBuf[2] << 8 | pBuf[3]);
|
||
memcpy(&f_val, &nValue, 4);
|
||
SetUnitYC(uid, point, f_val);
|
||
//nValue = (DWORD)(f_val * 1000);
|
||
}
|
||
else if (1 == value_type)
|
||
{
|
||
nValue = (DWORD)(pBuf[2] << 24 | pBuf[3] << 16 | pBuf[0] << 8 | pBuf[1]);
|
||
memcpy(&f_val, &nValue, 4);
|
||
SetUnitYC(uid, point, f_val);
|
||
//nValue = (DWORD)(f_val * 1000);
|
||
}
|
||
else if (3 == value_type)
|
||
{ //归一化值,高位在第一个寄存器
|
||
nValue = (DWORD)(pBuf[0] << 24 | pBuf[1] << 16 | pBuf[2] << 8 | pBuf[3]);
|
||
SetUnitYC(uid, point, (LONG)nValue);
|
||
}
|
||
else if (4 == value_type)
|
||
{ //归一化值,高位在第二个寄存器
|
||
nValue = (DWORD)(pBuf[2] << 24 | pBuf[3] << 16 | pBuf[0] << 8 | pBuf[1]);
|
||
SetUnitYC(uid, point, (LONG)nValue);
|
||
}
|
||
else if (5 == value_type)
|
||
{
|
||
nValue = (DWORD)(pBuf[3] << 24 | pBuf[2] << 16 | pBuf[1] << 8 | pBuf[0]);
|
||
memcpy(&f_val, &nValue, 4);
|
||
SetUnitYC(uid, point, f_val);
|
||
}
|
||
else if (6 == value_type)
|
||
{ //32位bcd数据高位在第一个寄存器
|
||
nValue = (DWORD)((pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | pBuf[3]);
|
||
bin_value = (LONG)bcd_to_int((const BYTE*)&nValue, sizeof(DWORD));
|
||
SetUnitYC(uid, point, bin_value);
|
||
}
|
||
else if (7 == value_type)
|
||
{ //32位bcd数据高位在第二个寄存器
|
||
nValue = (DWORD)(pBuf[2] << 24 | pBuf[3] << 16 | pBuf[0] << 8 | pBuf[1]);
|
||
bin_value = (LONG)bcd_to_int((const BYTE*)&nValue, sizeof(DWORD));
|
||
SetUnitYC(uid, point, bin_value);
|
||
}
|
||
pBuf += 4; i += 4; reg += 2;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
pBuf += 2; i += 2; reg++;
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN CHostModbusTcpProcess::OnReceiveYMData(CHostModbusTcpProcessItem *pItem, BYTE* pData, int count)
|
||
{
|
||
int i;
|
||
int point;
|
||
int uid;
|
||
BYTE* pBuf;
|
||
BYTE* pParam;
|
||
BYTE nParam[4];
|
||
BYTE value_type;
|
||
WORD reg;
|
||
DWORD nValue = 0;
|
||
float f_val;
|
||
DWORD dw[2]; //双精度转换中间变量
|
||
double d_val;
|
||
DWORD bin_value;
|
||
|
||
if (pItem == NULL) return FALSE;
|
||
uid = pItem->GetUnitID();
|
||
if (uid < 0) return FALSE;
|
||
|
||
pBuf = pData;
|
||
reg = m_nCurBeginReg;
|
||
|
||
nParam[0] = m_nCurFuncCode;
|
||
for (i = 0; i < count; )
|
||
{
|
||
nParam[1] = LOBYTE(reg);
|
||
nParam[2] = HIBYTE(reg);
|
||
point = GetUnitYMPointByParam(uid, nParam, 3);
|
||
if (point >= 0)
|
||
{ //获得有效点号
|
||
pParam = GetUnitYMParamByPoint(uid, point);
|
||
if (NULL != pParam)
|
||
{ //获得有效参数
|
||
value_type = pParam[4];
|
||
if (0 == value_type)
|
||
{ //16位无符号整型
|
||
nValue = (pBuf[0] << 8) | pBuf[1];
|
||
SetUnitYM(uid, point, nValue);
|
||
pBuf += 2; i += 2; reg++;
|
||
}
|
||
else if (1 == value_type)
|
||
{ //32位无符号整型高位在第一个寄存器
|
||
nValue = (DWORD)((pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | pBuf[3]);
|
||
SetUnitYM(uid, point, nValue);
|
||
pBuf += 4; reg += 2; i += 4;
|
||
}
|
||
else if (2 == value_type)
|
||
{ //32位整型高位在第一个寄存器
|
||
nValue = (DWORD)((pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | pBuf[3]);
|
||
SetUnitYM(uid, point, nValue);
|
||
pBuf += 4; reg += 2; i += 4;
|
||
}
|
||
else if (3 == value_type)
|
||
{ //32位无符号整型高位在第二个寄存器
|
||
nValue = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]);
|
||
SetUnitYM(uid, point, nValue);
|
||
pBuf += 4; reg += 2; i += 4;
|
||
}
|
||
else if (4 == value_type)
|
||
{ //32位整型高位在第二个寄存器
|
||
nValue = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]);
|
||
SetUnitYM(uid, point, nValue);
|
||
pBuf += 4; reg += 2; i += 4;
|
||
}
|
||
else if (5 == value_type)
|
||
{ //32位浮点数高位在第一个寄存器
|
||
nValue = (DWORD)((pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | pBuf[3]);
|
||
memcpy(&f_val, &nValue, 4);
|
||
SetUnitYM(uid, point, (DWORD)f_val);
|
||
pBuf += 4; reg += 2; i += 4;
|
||
}
|
||
else if (6 == value_type)
|
||
{ //32位浮点数高位在第二个寄存器
|
||
nValue = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]);
|
||
memcpy(&f_val, &nValue, 4);
|
||
SetUnitYM(uid, point, (DWORD)f_val);
|
||
pBuf += 4; reg += 2; i += 4;
|
||
}
|
||
else if (7 == value_type)
|
||
{ //64位浮点数高位在第一个寄存器
|
||
dw[1] = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]);
|
||
dw[0] = (DWORD)((pBuf[6] << 24) | (pBuf[7] << 16) | (pBuf[4] << 8) | pBuf[5]);
|
||
memcpy(&d_val, dw, 8);
|
||
SetUnitYM(uid, point, (DWORD)(d_val));
|
||
pBuf += 8; reg += 4; i += 8;
|
||
}
|
||
else if (8 == value_type)
|
||
{
|
||
dw[0] = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]);
|
||
dw[1] = (DWORD)((pBuf[6] << 24) | (pBuf[7] << 16) | (pBuf[4] << 8) | pBuf[5]);
|
||
memcpy(&d_val, dw, 8);
|
||
SetUnitYM(uid, point, (DWORD)(d_val));
|
||
pBuf += 8; reg += 4; i += 8;
|
||
}
|
||
else if (9 == value_type)
|
||
{
|
||
nValue = (DWORD)((pBuf[3] << 24) | (pBuf[2] << 16) | (pBuf[1] << 8) | pBuf[0]);
|
||
memcpy(&f_val, &nValue, 4);
|
||
SetUnitYM(uid, point, (DWORD)(f_val * 10));
|
||
pBuf += 4; reg += 2; i += 4;
|
||
}
|
||
else if (10 == value_type)
|
||
{ //32位bcd数据
|
||
nValue = (DWORD)((pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | pBuf[3]);
|
||
bin_value = bcd_to_int((const BYTE*)&nValue, sizeof(DWORD));
|
||
SetUnitYM(uid, point, bin_value);
|
||
pBuf += 4; reg += 2; i += 4;
|
||
}
|
||
else
|
||
{ //无配置
|
||
pBuf += 2; reg++; i += 2;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
pBuf += 2; i += 2; reg++;
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|