map/das-dn/hostmodbustcpbf/host_modbus_tcp_bf.cpp
2024-12-30 17:20:28 +08:00

2119 lines
75 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "host_modbus_tcp_bf.h"
#include <json.h>
#include <math.h>
#include <curl/curl.h>
#include <ry.h>
#include "ryFileDef.h"
#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寄存器长度。
static datalen2mbaddrmap m_datalen2mbaddr_map;
static struDataLengthMBAddr m_datalen_mbaddr[] = {
{ 2, 200 },
{ 2, 201 },
{ 2, 202 },
{ 2, 203 },
{ 2, 204 },
{ 2, 205 },
{ 2, 206 },
{ 2, 207 },
{ 2, 208 },
{ 2, 209 },
{ 2, 210 },
{ 2, 211 },
{ 2, 212 },
{ 2, 213 },
{ 2, 214 },
{ 2, 215 },
{ 2, 216 },
{ 2, 217 },
{ 2, 218 },
{ 2, 219 },
{ 2, 220 },
{ 2, 221 },
{ 2, 222 },
{ 2, 223 },
{ 2, 224 },
{ 2, 225 },
{ 2, 226 },
{ 2, 227 },
{ 2, 228 },
{ 2, 229 },
{ 2, 230 },
{ 2, 231 },
{ 2, 232 },
{ 2, 233 },
{ 2, 234 },
{ 4, 235 },
{ 4, 237 },
{ 4, 239 },
{ 4, 241 },
{ 4, 243 },
{ 4, 245 },
{ 4, 247 },
{ 4, 249 },
{ 2, 251 },
{ 2, 252 },
{ 2, 253 },
{ 2, 254 },
{ 2, 255 },
{ 2, 256 },
{ 2, 257 },
{ 2, 258 },
{ 2, 259 },
{ 2, 260 },
{ 2, 261 },
{ 2, 262 },
{ 2, 263 },
{ 2, 264 },
{ 2, 265 },
{ 2, 266 },
{ 2, 267 },
{ 2, 268 },
{ 2, 269 },
{ 2, 270 },
{ 2, 271 },
{ 2, 272 },
{ 2, 273 },
{ 2, 274 },
{ 2, 275 },
{ 2, 276 },
{ 2, 277 },
{ 2, 278 },
{ 2, 279 },
{ 2, 280 },
{ 2, 281 },
{ 2, 282 },
{ 2, 283 },
{ 2, 284 },
{ 2, 285 },
{ 2, 286 },
{ 2, 287 },
{ 2, 288 },
{ 2, 289 },
{ 2, 290 },
{ 2, 291 },
{ 2, 292 },
{ 2, 293 },
{ 2, 294 },
{ 2, 295 },
{ 2, 296 },
{ 2, 297 },
{ 2, 298 },
{ 2, 299 },
{ 2, 300 },
{ 2, 301 },
{ 2, 302 },
{ 2, 303 },
{ 2, 304 },
{ 2, 305 },
{ 2, 306 },
{ 2, 307 },
{ 4, 308 },
{ 4, 310 },
{ 4, 312 },
{ 4, 314 },
{ 4, 316 },
{ 4, 318 },
{ 2, 320 },
{ 2, 321 },
{ 2, 322 },
{ 2, 323 },
{ 2, 324 },
{ 2, 325 },
{ 2, 326 },
{ 2, 327 },
{ 2, 328 },
{ 2, 329 },
{ 2, 330 },
{ 2, 331 },
{ 2, 332 },
{ 2, 333 },
{ 2, 334 },
{ 2, 335 },
{ 2, 336 },
{ 2, 337 },
{ 2, 338 },
{ 2, 339 },
{ 2, 340 },
{ 2, 341 },
{ 2, 342 },
{ 2, 343 },
{ 2, 344 },
{ 2, 345 },
{ 2, 346 },
{ 2, 347 },
{ 2, 348 },
{ 2, 349 },
{ 2, 350 },
{ 2, 351 },
{ 2, 352 },
{ 2, 353 },
{ 2, 354 },
{ 2, 355 },
{ 2, 356 },
{ 2, 357 },
{ 2, 358 },
{ 2, 359 },
{ 2, 360 },
{ 2, 361 },
{ 2, 362 },
{ 2, 363 },
{ 2, 364 },
{ 2, 365 },
{ 2, 366 },
{ 2, 367 },
{ 2, 368 },
{ 2, 369 },
{ 2, 370 },
{ 2, 371 },
{ 2, 372 },
{ 2, 373 },
{ 2, 374 },
{ 2, 375 },
{ 2, 376 },
{ 2, 377 },
{ 4, 378 },
{ 4, 380 },
{ 4, 382 },
{ 2, 384 },
{ 2, 385 },
{ 2, 386 },
{ 2, 387 },
{ 2, 388 },
{ 2, 389 },
{ 2, 390 },
{ 2, 391 },
{ 2, 392 },
{ 2, 393 },
{ 2, 394 }
};
#ifdef USE_NOPOLL_WEBSOCKET
static int websocket_write(const noPollConn* conn, const char * buffer, int buffer_len)
{
int result;
result = nopoll_conn_send_text((noPollConn *)conn, (const char *)buffer, buffer_len);
/* ensure we have written all bytes but limit operation to 2 seconds */
result = nopoll_conn_flush_writes((noPollConn *)conn, 2000000, result);
return (result == buffer_len) ? 0 : -1;
}
#endif
#ifndef USE_NOPOLL_WEBSOCKET
static bool publish_sensor_data(const char* command, const Json::Value payload)
#else
static bool publish_sensor_data(const noPollConn* conn, const char* command, const Json::Value payload)
#endif
{
Json::StreamWriterBuilder builder;
builder["indentation"] = "";
builder["emitUTF8"] = true;
Json::Value jsonRoot;
jsonRoot["cmd"] = command;
char str[128];
#ifdef NOPOLL_64BIT_PLATFORM
snprintf(str, sizeof(str), "%ld", snowflake_next_id());
#else
snprintf(str, sizeof(str), "%lld", snowflake_next_id());
#endif
jsonRoot["cmdId"] = str;
Json::Int64 mtime = (Json::Int64)time(NULL);
mtime *= 1000;
jsonRoot["time"] = mtime;
jsonRoot["data"] = payload;
//vLog(LOG_DEBUG, "here start to send.\n");
std::string outputConfig = Json::writeString(builder, jsonRoot);
#ifndef USE_NOPOLL_WEBSOCKET
g_conn->sendMsg(outputConfig);
//vLog(LOG_DEBUG, "outputConfig length is: %d\n", outputConfig.length());
#else
int rc = websocket_write(conn, outputConfig.c_str(), outputConfig.length());
//vLog(LOG_DEBUG, "send cmd: %s, payload: %d\n", command, outputConfig.length()/*, outputConfig.c_str()*/);
if (rc != 0) {
vLog(LOG_DEBUG, "websocket write is error<%d>,insert into database.\n", rc);
//插入数据库
return false;
}
#endif
return true;
}
static WORD GetUnitYCRegisterAddr(int uid, int point)
{
struUnit* pUnit;
struUnitYC* pYC;
if (uid < 0 || uid >= UNIT_NUM) return (WORD)65535;
pUnit = &config.units[uid];
if (pUnit->yccount <= 0) return (WORD)65535;
if (point < 0 || point >= pUnit->yccount) return (WORD)65535;
pYC = &pUnit->ycs[point];
return (MAKEWORD(pYC->m_param[1], pYC->m_param[2]));
}
static WORD GetUnitYXRegisterAddr(int uid, int point)
{
struUnit* pUnit;
struUnitYX* pYX;
if (uid < 0 || uid >= UNIT_NUM) return (WORD)65535;
pUnit = &config.units[uid];
if (pUnit->yxcount <= 0) return (WORD)65535;
if (point < 0 || point >= pUnit->yxcount) return (WORD)65535;
pYX = &pUnit->yxs[point];
return (MAKEWORD(pYX->m_param[1], pYX->m_param[2]));
}
static BYTE GetUnitYXDataPos(int uid, int point)
{
struUnit* pUnit;
struUnitYX* pYX;
if (uid < 0 || uid >= UNIT_NUM) return (BYTE)0;
pUnit = &config.units[uid];
if (pUnit->yxcount <= 0) return (BYTE)0;
if (point < 0 || point >= pUnit->yxcount) return (BYTE)0;
pYX = &pUnit->yxs[point];
return (pYX->m_param[3]);
}
static BOOLEAN GetYCValue(const int order, const FIELDDES* fields, const char* pData, LONG& value)
{
if (pData == NULL) return FALSE;
if (fields == NULL) return FALSE;
if (order < 1 || order > (int)(sizeof(m_datalen_mbaddr) / sizeof(m_datalen_mbaddr[0]))) return FALSE;
int start = fields[order].start;
if (fields[order].length == sizeof(DWORD))
{ //4字节
value = *(LONG *)(pData + start);
return TRUE;
}
else if (fields[order].length == sizeof(WORD))
{
short tmp = *(short *)(pData + start);
value = (LONG)tmp;
return TRUE;
}
return FALSE;
}
static BOOLEAN GetYXValue(const int order, const FIELDDES* fields, const char* pData, const int pos, BOOLEAN& value)
{
if (pData == NULL) return FALSE;
if (fields == NULL) return FALSE;
if (pos < 0 || pos >= 16) return FALSE;
if (order < 1 || order > (int)(sizeof(m_datalen_mbaddr) / sizeof(m_datalen_mbaddr[0]))) return FALSE;
int start = fields[order].start;
if (fields[order].length == sizeof(WORD))
{
WORD tmp = *(WORD *)(pData + start);
WORD nTemp = 0x0001;
nTemp <<= pos;
if (tmp & nTemp) value = TRUE;
else value = FALSE;
return TRUE;
}
return FALSE;
}
#ifndef USE_NOPOLL_WEBSOCKET
static bool publishhistoryHighSpeedData(const int uid, const QWORD dt, const Json::Value values)
#else
static bool publishhistoryHighSpeedData(const noPollConn* conn, const int uid, const QWORD dt, const Json::Value values)
#endif
{
if (uid < 0 || uid >= UNIT_NUM) return false;
Json::Value root;
if (values.size()) {
root["dataTime"] = (Json::Int64)dt;
root["deviceId"] = static_units[uid].deviceId;
root["values"] = values;
#ifndef USE_NOPOLL_WEBSOCKET
return publish_sensor_data("historyHighSpeedData", root);
#else
return publish_sensor_data(conn, "historyHighSpeedData", root);
#endif
}
return false;
}
#ifndef USE_NOPOLL_WEBSOCKET
static bool publishhistoryLowSpeedData(const int uid, const QWORD dt, const Json::Value values)
#else
static bool publishhistoryLowSpeedData(const noPollConn* conn, const int uid, const QWORD dt, const Json::Value values)
#endif
{
if (uid < 0 || uid >= UNIT_NUM) return false;
Json::Value root;
if (values.size()) {
root["dataTime"] = (Json::Int64)(dt / 1000 * 1000); //取整
root["deviceId"] = static_units[uid].deviceId;
root["values"] = values;
#ifndef USE_NOPOLL_WEBSOCKET
return publish_sensor_data("historyLowSpeedData", root);
#else
return publish_sensor_data(conn, "historyLowSpeedData", root);
#endif
}
return false;
}
#if 0
static int ftpget(const char* remote, const char* local, const char* user, const char* pwd, const long timeout = 3, struct memory* chunk = NULL)
{
//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);
CURLcode ret = CURLE_GOT_NOTHING;
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_WRITEFUNCTION, write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)chunk);
curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 0L); // Optional: depending on your FTP server
ret = curl_easy_perform(curl);
curl_easy_cleanup(curl);
curl_global_cleanup();
return ret;
}
#endif
static void* ryftp_process(void* param)
{
if (param == NULL) return ((void*)0);
CHostModbusTcpBFProcess* mbt = (CHostModbusTcpBFProcess *)param;
//获取此协议配置里面的ftp信息
char remote[512];
//char name[512];
//默认参数,或是通过协议配置获取
char user[128] = "administrator";
char password[128] = "123456";
char ipaddress[128] = "127.0.0.1";
char remotePath[128] = "/data/rtdatalog";
//char pathName[128] = "./";
char processName[128];
snprintf(processName, sizeof(processName), "%s", mbt->m_pidName.c_str());
//配置远方路径
char* escaped_string = escape_char_in_string(mbt->m_remotePath, ' ');
if (escaped_string == NULL)
{
vLog(LOG_DEBUG, "%s 路径转义错误!\n", processName);
return ((void*)0);
}
snprintf(remotePath, sizeof(remotePath), "%s", escaped_string);
free(escaped_string);
#if 0
//根据协议创s建一个本地协议目录
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);
#endif
//配置的用户名和密码
snprintf(user, sizeof(user), "%s", mbt->m_user);
snprintf(password, sizeof(password), "%s", mbt->m_password);
//配置ip地址
DWORD target_addr = mbt->target_addr;
memset(ipaddress, '\0', sizeof(ipaddress));
inet_ntop(AF_INET, &target_addr, ipaddress, 16);
for (int i = 0; i < (int)(sizeof(m_datalen_mbaddr) / sizeof(m_datalen_mbaddr[0])); i++) {
m_datalen2mbaddr_map.insert(datalen2mbaddrmap::value_type(m_datalen_mbaddr[i].address, i + 1));
}
//struRYDeviceData t_data;
FIELDDES fields[1024];
calcFields(fields);
//判断是否链接单元
int uid = mbt->GetUnitID(0); //默认只接一个设备
if (uid < 0 || uid >= UNIT_NUM) return ((void*)0);
datatypemap highspeedmap;
datatypemap lowspeedmap;
datatypeposmap yxdatamap;
int yccount = GetUnitYCCount(uid);
for (int i = 0; i < yccount; i++) {
//根据遥测参数配置寄存器,获取高频数据寄存器
WORD register_addr = GetUnitYCRegisterAddr(uid, i);
if (GetUnitYCType(uid, i)) {
if (m_datalen2mbaddr_map.find(register_addr) != m_datalen2mbaddr_map.end()) {
highspeedmap.insert(datatypemap::value_type(i, m_datalen2mbaddr_map[register_addr])); //point-配置的序号order-数据文件序号
//vLog(LOG_DEBUG, "register_addr is: %d, point is: %d, and order is: %d\n", register_addr, i, m_datalen2mbaddr_map[register_addr]);
}
} else {
if (m_datalen2mbaddr_map.find(register_addr) != m_datalen2mbaddr_map.end()) {
lowspeedmap.insert(datatypemap::value_type(i, m_datalen2mbaddr_map[register_addr])); //point-配置的序号order-数据文件序号
//vLog(LOG_DEBUG, "register_addr is: %d, point is: %d, and order is: %d\n", register_addr, i, m_datalen2mbaddr_map[register_addr]);
}
}
}
int yxcount = GetUnitYXCount(uid);
for (int i = 0; i < yxcount; i++) {
//根据遥测参数配置寄存器,获取高频数据寄存器
WORD register_addr = GetUnitYXRegisterAddr(uid, i);
BYTE data_pos = GetUnitYXDataPos(uid, i);
//fprintf(stderr, "register_addr is: %d, pos is: %d.\n", register_addr, data_pos);
struDataPos pos;
if (m_datalen2mbaddr_map.find(register_addr) != m_datalen2mbaddr_map.end()) {
pos.point = m_datalen2mbaddr_map[register_addr];
pos.pos = data_pos;
yxdatamap.insert(datatypeposmap::value_type(i, pos)); //point-配置的序号order-数据文件序号
//vLog(LOG_DEBUG, "aaaa register_addr is: %d, point is: %d, and order is: %d\n", register_addr, i, m_datalen2mbaddr_map[register_addr]);
}
}
//根据实际配置表将
WORD ftpget_retry_count = 0;
BOOLEAN bReadCurrentFile = TRUE; //读取当前文件标识
while (TRUE) {
sleep(1); //每秒执行一次
if (!mbt->m_bFtpRun) break;
mbt->FeedFTPDog();
//ftp获取文件
if (mbt->m_iv == 1) {
//文件目录无效
continue;
}
if (bReadCurrentFile)
{ //读取当前文件
//vLog(LOG_DEBUG, "读取当前文件.\n");
//snprintf(name, sizeof(name), "%s/%d", pathName, mbt->m_currentFileNo);
snprintf(remote, sizeof(remote), "ftp://%s/%s/%d/%d", ipaddress, remotePath, mbt->m_currentDirNo, mbt->m_currentFileNo);
}
else
{ //读取未读的文件
//vLog(LOG_DEBUG, "读取未读的文件.\n");
//snprintf(name, sizeof(name), "%s/%d", pathName, mbt->m_lastReadFileNo);
snprintf(remote, sizeof(remote), "ftp://%s/%s/%d/%d", ipaddress, remotePath, mbt->m_lastReadDirNo, mbt->m_lastReadFileNo);
}
struct memory chunk = {0}; // For storing the downloaded data
//vLog(LOG_DEBUG, "start to read %s\n", remote);
CURLcode result = ftpget(remote, user, password, 3, &chunk);
//vLog(LOG_DEBUG, "%s ftpget result is: %d,%s\n", processName, result, curl_easy_strerror(result));
if (result == CURLE_OK) {
//成功,处理文件
vLog(LOG_DEBUG, "%s get %s to local memory, with name: %s, and password: %s okay, and file length is: %d.\n", processName, remote, user, password, chunk.size);
config.units[uid].value &= ~0x02;
ftpget_retry_count = 0;
if (chunk.size <= (int)(sizeof(struRYDeviceData) << 5)) {
vLog(LOG_DEBUG, "%s PLC文件生成未完成\n", processName);
continue;
}
struRYDeviceData *data = (struRYDeviceData *)chunk.response;
int uid = mbt->GetCurUnitID();
mbt->UnitFeedFTPDog(uid);
for (int i = 0; i < 250; i++, data++) { //每个文件有250个数据块
QLONG unix_time = filetime_to_unix(data->localtime);
DWORD localtime = ((unix_time / 1000) - 28800L);
DWORD millisec = unix_time % 1000;
unix_time = localtime; unix_time *= 1000;
unix_time += millisec;
#if 0
unionCP56Time st;
st = Time_ttounionCP56Time(localtime);
vLog(LOG_DEBUG, "data<%d> time is: %04d/%02d/%02d %02d:%02d:%02d.%03d\n", \
i, \
st.year + 2000, st.month, st.dayofmonth, \
st.hour, st.minute, st.millisecond/1000, st.millisecond%1000);
#endif
//如何将结构化数据传入,且快速获取
Json::Value highspeedvalues;
for (datatypemap::iterator it = highspeedmap.begin(); it != highspeedmap.end(); it++) {
//获取数据
LONG dvalue;
int order = it->first;
int point = it->second;
if (GetYCValue(point, fields, (const char *)data, dvalue)) {
if (GetUnitYCIsFloat(uid, order)) {
highspeedvalues[(const char *)config.units[uid].ycs[order].name] = GetUnitYCRealFromValue(uid, order, dvalue);
} else {
highspeedvalues[(const char *)config.units[uid].ycs[order].name] = dvalue;
}
} else {
highspeedvalues[(const char *)config.units[uid].ycs[order].name] = 0.0f;
}
}
#ifndef USE_NOPOLL_WEBSOCKET
publishhistoryHighSpeedData(uid, unix_time, highspeedvalues);
#else
publishhistoryHighSpeedData(g_conn, uid, unix_time, highspeedvalues);
#endif
if (i % 25 == 0) { //40ms一个值每25次位1s
Json::Value lowspeedvalues;
for (datatypemap::iterator it = lowspeedmap.begin(); it != lowspeedmap.end(); it++) {
//获取数据
LONG dvalue;
int order = it->first;
int point = it->second;
if (GetYCValue(point, fields, (const char *)data, dvalue)) {
//fprintf(stderr, "get<%d> value is: %d.\n", point, dvalue);
if (GetUnitYCIsFloat(uid, order)) {
lowspeedvalues[(const char *)config.units[uid].ycs[order].name] = GetUnitYCRealFromValue(uid, order, dvalue);
} else {
lowspeedvalues[(const char *)config.units[uid].ycs[order].name] = dvalue;
}
} else {
lowspeedvalues[(const char *)config.units[uid].ycs[order].name] = 0.0f;
}
}
for (datatypeposmap::iterator it = yxdatamap.begin(); it != yxdatamap.end(); it++) {
BOOLEAN bvalue;
int order = it->first;
int point = it->second.point;
int pos = it->second.pos;
//vLog(LOG_DEBUG, "start to get point is: %d, pos is: %d\n", point, pos);
if (GetYXValue(point, fields, (const char *)data, pos, bvalue)) {
lowspeedvalues[(const char *)config.units[uid].yxs[order].name] = (int)bvalue;
} else {
lowspeedvalues[(const char *)config.units[uid].yxs[order].name] = 0;
}
}
#ifndef USE_NOPOLL_WEBSOCKET
publishhistoryLowSpeedData(uid, unix_time, lowspeedvalues);
#else
publishhistoryLowSpeedData(g_conn, uid, unix_time, lowspeedvalues);
#endif
}
}
if (chunk.response) free(chunk.response);
if (bReadCurrentFile) { //读取的是当前文件
mbt->m_lastFileNo = mbt->m_currentFileNo;
mbt->m_currentFileNo++;
if ((mbt->m_currentFileNo - mbt->m_currentDirStartFileNo) % 1000 == 0) {
//一个文件夹最多存放1000个文件, mbt->m_currentFileNo = 0;
mbt->m_currentDirNo++;
mbt->m_currentDirStartFileNo = mbt->m_currentFileNo;
}
} else { //读取的是未读历史文件
mbt->m_lastReadFileNo++;
if ((mbt->m_lastReadFileNo - mbt->m_lastReadDirStartFileNo) % 1000 == 0) {
//一个文件夹最多存放1000个文件, mbt->m_currentFileNo = 0;
mbt->m_lastReadDirNo++;
}
if (mbt->m_curStartDirNo <= mbt->m_lastReadDirNo && mbt->m_curStartFileNo <= mbt->m_lastReadFileNo) {
vLog(LOG_DEBUG, "%s a已读取完成所有未读的文件。\n", processName);
mbt->m_bHaveUnReadFile = FALSE;
}
}
bReadCurrentFile = TRUE;
} else if (result == CURLE_REMOTE_FILE_NOT_FOUND) {
//文件不存在尝试60次1分钟正常情况下PLC10s生成一个文件
//vLog(LOG_DEBUG, "文件不存在, ftpget_retry_count is: %d\n", ftpget_retry_count);
ftpget_retry_count++;
if (ftpget_retry_count >= 60) {
//重新通过modbus程序获取文件夹和最新文件信息
mbt->m_iv = 0;
mbt->m_currentDirNo = -1;
mbt->m_currentFileNo = -1;
config.units[uid].value |= 0x02; //
}
//此处空闲读取未读的文件
if (mbt->m_bHaveUnReadFile) {
bReadCurrentFile = FALSE;
}
} else if (result == CURLE_REMOTE_ACCESS_DENIED) {
vLog(LOG_DEBUG, "%s b已读取完成所有未读的文件。\n", processName);
mbt->m_bHaveUnReadFile = FALSE;
bReadCurrentFile = TRUE;
}
}
pthread_exit(0);
return ((void*)0);
}
CHostModbusTcpBFProcessItem::CHostModbusTcpBFProcessItem()
{
m_nNum = 0;
m_nFramePoll = 0;
apdu_t0_begin = 1;
m_nCurFrame = 0;
memset(m_nModbusFrames, 0, sizeof(m_nModbusFrames));
}
CHostModbusTcpBFProcessItem::~CHostModbusTcpBFProcessItem()
{
m_nNum = 0;
m_nFramePoll = 0;
apdu_t0_begin = 1;
m_nCurFrame = 0;
memset(m_nModbusFrames, 0, sizeof(m_nModbusFrames));
}
void CHostModbusTcpBFProcessItem::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* CHostModbusTcpBFProcessItem::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 CHostModbusTcpBFProcessItem::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 CHostModbusTcpBFProcessItem::Release(void)
{
apdu_t0_begin = 1;
m_nNum = 0;
m_nFramePoll = 0;
m_nCurFrame = 0;
CNetProcessItem::Release();
}
CHostModbusTcpBFProcess::CHostModbusTcpBFProcess()
{
m_nCount = 0;
m_nFrameCount = 0;
m_nCurFrame = 0;
m_nSendPoint = 0;
m_nCurBeginReg = 0;
m_nNeedSend = FALSE;
//websocket接口
m_cpid = 0;
//目录无效
m_iv = 1;
m_currentDirNo = -1; //当前目录编号
m_currentFileNo = -1; //当前文件编号
m_lastDirNo = -1; //上一目录编号
m_lastFileNo = -1; //上一文件编号
m_bFtpRun = FALSE;
}
CHostModbusTcpBFProcess::~CHostModbusTcpBFProcess()
{
if (m_bHaveFTP)
{
m_bFtpRun = FALSE;
vLog(LOG_DEBUG, "保存本协议读取到的那个目录和文件\n");
char fileName[260];
snprintf(fileName, sizeof(fileName), "hostmodbustcp_%d.mem", GetCurID());
FILE *pf = fopen(fileName, "w+");
if (pf)
{
fwrite(&m_currentDirNo, sizeof(LONG), 1, pf);
fwrite(&m_currentFileNo, sizeof(LONG), 1, pf);
fwrite(&m_currentDirStartFileNo, sizeof(LONG), 1, pf);
fclose(pf);
}
char name[16];
memset(name, '\0', sizeof(name));
if (pthread_getname_np(m_cpid, name, sizeof(name)) != 0)
{
memset(name, '\0', sizeof(name));
}
vLog(LOG_DEBUG, "waiting for child thread [%s] destroy.\n", (name[0] != '\0') ? name : "unknow");
pthread_join(m_cpid, NULL);
vLog(LOG_DEBUG, "child protocol thread [%s] is destroyed.\n", (name[0] != '\0') ? name : "unknow");
}
}
CNetProcessItem *CHostModbusTcpBFProcess::CreateItem(int ord)
{
return dynamic_cast<CNetProcessItem *>(new CHostModbusTcpBFProcessItem);
}
void CHostModbusTcpBFProcess::DestroyItem(int ord, BOOLEAN bDeleted /* = FALSE */)
{
CHostModbusTcpBFProcessItem *pItem = (CHostModbusTcpBFProcessItem *)GetItem(ord);
if (pItem != NULL && !bDeleted)
{
delete pItem;
return CNetProcess::DestroyItem(ord, TRUE);
}
return CNetProcess::DestroyItem(ord, bDeleted);
}
void CHostModbusTcpBFProcess::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, &params[j], sizeof(STRUCT_PARAM));
memcpy(&params[j], &params[j + 1], sizeof(STRUCT_PARAM));
memcpy(&params[j + 1], &temp, sizeof(STRUCT_PARAM));
}
}
}
}
void CHostModbusTcpBFProcess::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, &params[j], sizeof(STRUCT_PARAM));
memcpy(&params[j], &params[j + 1], sizeof(STRUCT_PARAM));
memcpy(&params[j + 1], &temp, sizeof(STRUCT_PARAM));
}
}
}
}
void CHostModbusTcpBFProcess::calc2(void)
{
int i, j, n, uid;
BYTE addr;
CHostModbusTcpBFProcessItem *pItem;
for (i = 0; i < PROCESS_UNIT_NUM; i++)
{
pItem = (CHostModbusTcpBFProcessItem *)GetItem(i);
if (NULL == pItem) continue;
uid = pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) continue;
//需要给单元添加一个是否有ftp数据的标识
if (m_bHaveFTP) config.units[uid].state |= 0x20; //存在ftp标识
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);
//vLog(LOG_DEBUG, "unit %d, yc count is: %d, and yx count is: %d\n", uid, yccount, yxcount);
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 (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 = 0; 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;
}
}
}
}
delete [] ycparam;
}
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;
}
}
}
}
delete [] ymparam;
}
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;
}
}
}
}
delete [] yxparam;
}
//按寄存器排序
pItem->AddFrames(yxframes, ycframes, ymframes);
}
}
}
BOOLEAN CHostModbusTcpBFProcess::OnPreCreate(int id)
{
if (!CNetProcess::OnPreCreate(id)) return FALSE;
if (!GetOption(&m_nOptions, sizeof(m_nOptions)))
{
vLog(LOG_DEBUG, "润阳modbus读取配置错误。");
return FALSE;
}
m_pidName = std::string(GetCurProcessName());
m_bHaveFTP = m_nOptions.bHaveFTP;
m_nTimeout = 200;
//需要给单元添加一个是否有ftp数据的标识
if (m_bHaveFTP)
{
config.processes[id].state |= 0x20;
}
calc2();
if (m_bHaveFTP)
{
snprintf(m_user, sizeof(m_user), "%s", m_nOptions.ftp.user);
snprintf(m_password, sizeof(m_password), "%s", m_nOptions.ftp.password);
snprintf(m_remotePath, sizeof(m_remotePath), "%s", m_nOptions.ftp.remotePath);
snprintf(m_localPath, sizeof(m_localPath), "%s", m_nOptions.ftp.localPath);
//读取文件
m_lastReadDirNo = 1;
m_lastReadFileNo = 1;
m_lastReadDirStartFileNo = 1;
m_bHaveUnReadFile = TRUE;
char fileName[260];
snprintf(fileName, sizeof(fileName), "hostmodbustcp_%d.mem", GetCurID());
FILE *pf = fopen(fileName, "rb");
if (pf)
{
fread(&m_lastReadDirNo, sizeof(LONG), 1, pf);
fread(&m_lastReadFileNo, sizeof(LONG), 1, pf);
fread(&m_lastReadDirStartFileNo, sizeof(LONG), 1, pf);
fclose(pf);
}
//启动后创建ftp线程
if (m_cpid <= 0) {
m_bFtpRun = TRUE;
vLog(LOG_DEBUG, "rymodbus 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_cpid, &attr, ryftp_process, this) < 0) {
vLog(LOG_ERROR, "rymodbus create ryftp_process error(%d,%s).\n", errno, strerror(errno));
return TRUE;
}
char name[17];
snprintf(name, 16, "%s_ftp", m_pidName.c_str());
pthread_setname_np(m_cpid, name);
pthread_attr_destroy(&attr);
}
}
return TRUE;
}
BOOLEAN CHostModbusTcpBFProcess::Run(void)
{
int count;
BYTE buffer[512];
if (!CNetProcess::Run()) return FALSE;
FeedDog();
//process polling command
CHostModbusTcpBFProcessItem *pItem = (CHostModbusTcpBFProcessItem *)GetItem(0);
if (NULL == pItem) return TRUE;
if (pItem->GetSock() < 0) {
usleep(20000);
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 CHostModbusTcpBFProcess::OnTimer(void)
{
CHostModbusTcpBFProcessItem *pItem;
if (!CNetProcess::OnTimer()) return FALSE;
m_nCount++;
pItem = (CHostModbusTcpBFProcessItem *)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 = (CHostModbusTcpBFProcessItem *)GetNextItem();
if (pItem == NULL) return TRUE;
m_nNeedSend = TRUE;
if (m_bHaveFTP)
{ //启动时读取一次,后面自己维护序号
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;
}
}
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 CHostModbusTcpBFProcess::GetYKFrame(CHostModbusTcpBFProcessItem *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 CHostModbusTcpBFProcess::GetYTFrame(CHostModbusTcpBFProcessItem *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 CHostModbusTcpBFProcess::GetSetTimeFrame(CHostModbusTcpBFProcessItem *pItem, BYTE* /*pData*/, int& /*count*/)
{
return TRUE;
}
BOOLEAN CHostModbusTcpBFProcess::GetReadDataFrame(CHostModbusTcpBFProcessItem *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 CHostModbusTcpBFProcess::OnPackageReceived(BYTE* pBuf, int count, int ord)
{
int uid;
if (count < 6)
{ //数据长度不足
return 0;
}
CHostModbusTcpBFProcessItem* pItem;
pItem = (CHostModbusTcpBFProcessItem *)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 = (CHostModbusTcpBFProcessItem *)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 CHostModbusTcpBFProcess::OnReceiveData(CHostModbusTcpBFProcessItem *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 CHostModbusTcpBFProcess::OnReceiveIDData(CHostModbusTcpBFProcessItem *pItem, BYTE* pData, int count)
{
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, "%s 路径信息无效\n", m_pidName.c_str());
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_currentDirStartFileNo = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]); pBuf += 4;
m_curStartDirNo = m_currentDirNo; //当前开始目录
m_curStartFileNo = m_currentFileNo; //当前开始文件
//判断是否有要读取的文件
if (m_curStartDirNo <= m_lastReadDirNo && m_curStartFileNo <= m_lastReadFileNo)
{
vLog(LOG_DEBUG, "%s 不存在未读的文件。\n", m_pidName.c_str());
m_bHaveUnReadFile = FALSE;
}
else
{
m_bHaveUnReadFile = TRUE;
int dir_count = m_curStartDirNo - m_lastReadDirNo + 1;
int file_count = m_curStartFileNo - m_lastReadFileNo;
vLog(LOG_DEBUG, "%s 总共有%d个目录的%d个文件未读取。\n", m_pidName.c_str(), dir_count, file_count);
}
/*文件从保存的最后读取的文件目录的文件一直督导当前开始目录*/
vLog(LOG_DEBUG, "%s 最新文件夹编号: %ld, 最新文件名编号: %ld: 最新文件夹中第一个文件的编号: %ld\n", m_pidName.c_str(), m_currentDirNo, m_currentFileNo, m_currentDirStartFileNo);
return TRUE;
}
BOOLEAN CHostModbusTcpBFProcess::OnReceiveYXData(CHostModbusTcpBFProcessItem *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 CHostModbusTcpBFProcess::OnReceiveYCData(CHostModbusTcpBFProcessItem *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];
//vLog(LOG_DEBUG, "here count is: %d, value type is: %d, and ", reg_count, value_type);
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);
//vLog(LOG_DEBUG, "value is: %ld.\n", 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);
//vLog(LOG_DEBUG, "value is: %ld.\n", 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 CHostModbusTcpBFProcess::OnReceiveYMData(CHostModbusTcpBFProcessItem *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;
}