map/das-dn/hostmodbustcp/host_modbus_tcp.cpp
2024-10-21 10:53:15 +08:00

2591 lines
99 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.h"
#include <json.h>
#include <math.h>
#include <map>
#include <unordered_map>
///////////////////////////////////////////////////////////////////////////////////
//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.//
///////////////////////////////////////////////////////////////////////////////////
#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寄存器长度。
typedef std::unordered_map<short, short> datalen2mbaddrmap;
datalen2mbaddrmap m_datalen2mbaddr_map;
typedef struct {
short point;
short pos;
} struDataPos;
typedef std::unordered_map<short, struDataPos> datatypeposmap;
typedef std::unordered_map<short, short> datatypemap;
typedef struct
{
int start;
int length;
} FIELDDES;
struct {
int length;
int address;
} m_datalen_mbaddr[] = {
{ 2, 200 },
{ 2, 201 },
{ 2, 202 },
{ 2, 203 },
{ 2, 204 },
{ 2, 205 },
{ 2, 206 },
{ 2, 207 },
{ 2, 209 },
{ 2, 210 },
{ 2, 208 },
{ 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 },
{ 2, 312 },
{ 4, 313 },
{ 2, 315 },
{ 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 }
};
#include <curl/curl.h>
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;
}
static bool publish_sensor_data(const noPollConn* conn, const char* command, const Json::Value payload)
{
Json::StreamWriterBuilder builder;
builder["indentation"] = "";
builder["emitUTF8"] = true;
Json::Value jsonRoot;
jsonRoot["cmd"] = command;
char str[128];
snprintf(str, sizeof(str), "%lld", snowflake_next_id());
jsonRoot["cmdId"] = str;
Json::Int64 mtime = (Json::Int64)time(NULL);
mtime *= 1000;
jsonRoot["time"] = mtime;
jsonRoot["data"] = payload;
std::string outputConfig = Json::writeString(builder, jsonRoot);
int rc = websocket_write(conn, outputConfig.c_str(), outputConfig.length());
vLog(LOG_DEBUG, "send cmd: %s, payload: %d\n%s\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;
}
return true;
}
static float GetUnitYCRealFromValue(int uid, int order, DWORD value)
{
int udb;
float coef;
float base;
struUnit* pUnit;
struUnitYC* pYC;
if (uid < 0 || uid >= UNIT_NUM) return 0;
pUnit = &config.units[uid];
if ((pUnit->state & 0x01) != TRUE) return 0;
if (order < 0 || order >= pUnit->yccount) return 0;
pYC = &pUnit->ycs[order];
udb = pYC->order;
if (udb < 0 || udb >= DATABASE_YC_NUM) {
coef = 1.0f;
base = 0.0f;
} else {
coef = pYC->coef;
base = pYC->base;
}
return (float)(value * coef + base);
}
BOOLEAN GetUnitYCIsFloat(int uid, int order)
{
int udb;
float coef = 1.0f;
struUnit* pUnit;
struUnitYC* pYC;
if (uid < 0 || uid >= UNIT_NUM) return 0;
pUnit = &config.units[uid];
if ((pUnit->state & 0x01) != TRUE) return 0;
if (order < 0 || order >= pUnit->yccount) return 0;
pYC = &pUnit->ycs[order];
udb = pYC->order;
if (udb < 0 || udb >= DATABASE_YC_NUM)
{
coef = 1.0f;
}
else
{
coef = pYC->coef;
}
if (fabsf(coef) <= 1E-8) coef = 1.0f;
if (fabsf(coef - 1.0f) <= 1E-8) return FALSE;
return TRUE;
}
static int GetUnitYXCount(int uid)
{
if (uid < 0 || uid >= UNIT_NUM) return 0;
return config.units[uid].yxcount;
}
static int GetUnitYCCount(int uid)
{
if (uid < 0 || uid >= UNIT_NUM) return 0;
return config.units[uid].yccount;
}
static BOOLEAN GetUnitYCType(int uid, int order)
{
struUnit* pUnit;
struUnitYC* pYC;
if (uid < 0 || uid >= UNIT_NUM) return 0;
pUnit = &config.units[uid];
if ((pUnit->state & 0x01) != TRUE) return 0;
if (order < 0 || order >= pUnit->yccount) return 0;
pYC = &pUnit->ycs[order];
return pYC->highSpeed;
}
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 (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 (pYX->m_param[3]);
}
static BOOLEAN GetYCValue(const int order, const FIELDDES* fields, const char* pData, DWORD& value)
{
if (pData == NULL) return FALSE;
if (fields == NULL) return FALSE;
if (order < 0 || order >= sizeof(m_datalen_mbaddr) / sizeof(m_datalen_mbaddr[0])) return FALSE;
int start = fields[order].start;
if (fields[order].length == sizeof(DWORD))
{ //4字节
value = *(DWORD *)(pData + start);
return TRUE;
}
else if (fields[order].length == sizeof(WORD))
{
WORD tmp = *(WORD *)(pData + start);
value = 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 < 0 || order >= 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;
value = FALSE;
return TRUE;
}
return FALSE;
}
static bool publishhistoryHighSpeedData(const noPollConn* conn, const int uid, const QWORD dt, const Json::Value values)
{
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;
return publish_sensor_data(conn, "historyHighSpeedData", root);
}
return false;
}
static bool publishhistoryLowSpeedData(const noPollConn* conn, const int uid, const QWORD dt, const Json::Value values)
{
if (uid < 0 || uid >= UNIT_NUM) return false;
Json::Value root;
#if 0
Json::Value values;
int count = GetUnitYCCount(uid);
if (count) {
for (int i = 0; i < count; i++) {
values[(const char *)config.units[uid].ycs[i].name] = GetUnitYCRealFromValue(uid, i, data[i]);
}
}
#endif
if (values.size()) {
root["dataTime"] = (Json::Int64)(dt / 1000 * 1000); //取整
root["deviceId"] = static_units[uid].deviceId;
root["values"] = values;
return publish_sensor_data(conn, "historyLowSpeedData", root);
}
return false;
}
#define USE_MEMORY
#ifdef USE_MEMORY
struct memory {
char *response;
size_t size;
};
static size_t write_callback(void *ptr, size_t size, size_t nmemb, struct memory *mem) {
size_t new_size = mem->size + size * nmemb;
//fprintf(stderr, "mem is: %u", mem->response);
mem->response = (char *)realloc(mem->response, new_size + 1);
if (mem->response == NULL) {
fprintf(stderr, "Failed to allocate memory.\n");
return 0; // Out of memory
}
memcpy(&(mem->response[mem->size]), ptr, size * nmemb);
mem->size = new_size;
mem->response[new_size] = '\0';
return size * nmemb;
}
#else
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);
}
#endif
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;
#ifndef USE_MEMORY
FILE *file;
curl_off_t local_file_len = -1;
long filesize = 0;
struct stat file_info;
int use_resume = 0;
if (stat(local, &file_info) == 0) {
local_file_len = file_info.st_size;
use_resume = 1;
}
#if 0
file = fopen(local, "ab+");
if (file == NULL) {
vLog(LOG_ERROR, "open file error(%d,%s)\n", errno, strerror(errno));
return 0;
}
#endif
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);
#else
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);
#endif
//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[256];
// char local_filename[64];
// char local_dirent[128];
//默认参数,或是通过协议配置获取
char user[128] = "administrator";
char password[128] = "123456";
char ipaddress[128] = "127.0.0.1";
//根据协议创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);
//配置的用户名和密码
#if 0
snprintf(user, sizeof(user), "%s", mbt->m_user);
snprintf(password, sizeof(password), "%s", mbt->m_password);
#endif
DWORD target_addr = mbt->target_addr;
memset(ipaddress, '\0', sizeof(ipaddress));
inet_ntop(AF_INET, &target_addr, ipaddress, 16);
struct timespec start, end;
double elapsed_time = 0;
for (int i = 0; i < sizeof(m_datalen_mbaddr) / sizeof(m_datalen_mbaddr[0]); i++) {
m_datalen2mbaddr_map.insert(datalen2mbaddrmap::value_type(m_datalen_mbaddr[i].address, i + 1));
}
int len = 0;
struRYDeviceData t_data;
FIELDDES fields[1024];
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.localtime) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.localtime);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenSpeed) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenSpeed);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenPower) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenPower);
len++;
//
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iWindSpeed) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iWindSpeed);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iVibrationY) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iVibrationY);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iVibrationZ) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iVibrationZ);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTurbineOperationMode) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTurbineOperationMode);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBPLevel) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBPLevel);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iYPLevel) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iYPLevel);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenSpeed1s) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenSpeed1s);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenPower1s) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenPower1s);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iWindSpeed1s) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iWindSpeed1s);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenToruqe1s) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenToruqe1s);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iRotorSpeed) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iRotorSpeed);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTheoreticalPower) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTheoreticalPower);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iReactivePower) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iReactivePower);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iActivePowerSetPointValue) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iActivePowerSetPointValue);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iCosPhiSetValue) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iCosPhiSetValue);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iSetValueGenSpeed) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iSetValueGenSpeed);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iSetValuePitchAngle) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iSetValuePitchAngle);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iPitchAngle1RefValue) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iPitchAngle1RefValue);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iPitchAngle2RefValue) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iPitchAngle2RefValue);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iPitchAngle3RefValue) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iPitchAngle3RefValue);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iPitchAngle1) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iPitchAngle1);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iPitchAngle2) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iPitchAngle2);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iPitchAngle3) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iPitchAngle3);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iVaneDirection) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iVaneDirection);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iWindDirection) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iWindDirection);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.StateWord01) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.StateWord01);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.StateWord02) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.StateWord02);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.StateWord03) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.StateWord03);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.StateWord04) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.StateWord04);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.StateWord05) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.StateWord05);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.StateWord06) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.StateWord06);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.StateWord07) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.StateWord07);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.StateWord08) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.StateWord08);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.ActiveStatusCode01) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.ActiveStatusCode01);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.ActiveStatusCode02) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.ActiveStatusCode02);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.ActiveStatusCode03) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.ActiveStatusCode03);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.ActiveStatusCode04) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.ActiveStatusCode04);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.ActiveStatusCode05) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.ActiveStatusCode05);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.ActiveStatusCode06) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.ActiveStatusCode06);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.ActiveStatusCode07) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.ActiveStatusCode07);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.ActiveStatusCode08) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.ActiveStatusCode08);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iFrequency) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iFrequency);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iUL1_690V) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iUL1_690V);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iUL2_690V) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iUL2_690V);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iUL3_690V) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iUL3_690V);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iIL1_690V) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iIL1_690V);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iIL2_690V) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iIL2_690V);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iIL3_690V) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iIL3_690V);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade1MotorCurrent) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade1MotorCurrent);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade2MotorCurrent) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade2MotorCurrent);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade3MotorCurrent) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade3MotorCurrent);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iPitchAngleBk1) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iPitchAngleBk1);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iPitchAngleBk2) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iPitchAngleBk2);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iPitchAngleBk3) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iPitchAngleBk3);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iCosPhi) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iCosPhi);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGearPressA) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGearPressA);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGearPressB) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGearPressB);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iHydrPress) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iHydrPress);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iNacellePositionLtd) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iNacellePositionLtd);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iCableTwistTotal) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iCableTwistTotal);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iNacellePositionTotal) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iNacellePositionTotal);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempOutdoor_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempOutdoor_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempHub_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempHub_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempNacelle_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempNacelle_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempTowerBase_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempTowerBase_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempCabinetNacelle_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempCabinetNacelle_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempCabinetTowerBase_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempCabinetTowerBase_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempTransformer690_400V_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempTransformer690_400V_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempMV_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempMV_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade1TempMotor_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade1TempMotor_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade2TempMotor_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade2TempMotor_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade3TempMotor_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade3TempMotor_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade1TempBattBox_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade1TempBattBox_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade2TempBattBox_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade2TempBattBox_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade3TempBattBox_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade3TempBattBox_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempCntr_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempCntr_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade1TempInvBox_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade1TempInvBox_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade2TempInvBox_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade2TempInvBox_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade3TempInvBox_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade3TempInvBox_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade1TempPMMHeatsink_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade1TempPMMHeatsink_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade2TempPMMHeatsink_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade2TempPMMHeatsink_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade3TempPMMHeatsink_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade3TempPMMHeatsink_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade1TempPMCHeatsink_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade1TempPMCHeatsink_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade2TempPMCHeatsink_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade2TempPMCHeatsink_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iBlade3TempPMCHeatsink_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iBlade3TempPMCHeatsink_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempRotorBearA_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempRotorBearA_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempRotorBearB_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempRotorBearB_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTemp1GearOil_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTemp1GearOil_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempGearBearDE_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempGearBearDE_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempGearBearNDE_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempGearBearNDE_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempGenBearDE_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempGenBearDE_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempGenBearNDE_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempGenBearNDE_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempGenStatorU_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempGenStatorU_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempGenStatorV_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempGenStatorV_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempGenStatorW_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempGenStatorW_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempGenCoolingAir_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempGenCoolingAir_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iAvailabillityToday) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iAvailabillityToday);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iAvailabillityTotal) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iAvailabillityTotal);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iKWhThisDay) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iKWhThisDay);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iKWhOverall) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iKWhOverall);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iOperationHoursDay) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iOperationHoursDay);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iOperationHoursOverall) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iOperationHoursOverall);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iLostKWhThisDay) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iLostKWhThisDay);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iLostKWhOverall) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iLostKWhOverall);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.FirstTriggeredCode) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.FirstTriggeredCode);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW001) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW001);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW002) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW002);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW003) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW003);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW004) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW004);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW005) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW005);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW006) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW006);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW007) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW007);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW008) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW008);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW009) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW009);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW010) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW010);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW011) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW011);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW012) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW012);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW013) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW013);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW014) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW014);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW015) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW015);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW016) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW016);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW017) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW017);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW018) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW018);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW019) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW019);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW020) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW020);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW021) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW021);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW022) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW022);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW023) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW023);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW024) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW024);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW025) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW025);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW026) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW026);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW027) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW027);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW028) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW028);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW029) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW029);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW030) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW030);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW031) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW031);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW032) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW032);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW033) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW033);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW034) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW034);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW035) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW035);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW036) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW036);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW037) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW037);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW038) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW038);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW039) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW039);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW040) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW040);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW041) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW041);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW042) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW042);
len++;
//判断是否链接单元
int uid = mbt->GetUnitID(0); //默认只接一个设备
if (uid < 0 || uid >= UNIT_NUM) return ((void*)0);
datatypemap highspeedmap;
datatypemap lowspeedmap;
datatypeposmap yxdatamap;
int yccount = GetUnitYCCount(uid);
vLog(LOG_DEBUG, "yccount is: %d.\n", yccount);
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-数据文件序号
}
} 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-数据文件序号
}
}
}
int yxcount = GetUnitYXCount(uid);
vLog(LOG_DEBUG, "yxcount is: %d.\n", yxcount);
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-数据文件序号
}
}
//根据实际配置表将
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/Hard%20Disk2/data/rtdatalog/%d/%d", ipaddress, mbt->m_currentDirNo, mbt->m_currentFileNo);
clock_gettime(CLOCK_MONOTONIC, &start);
struct memory chunk = {0}; // For storing the downloaded data
if (ftpget(remote, name, user, password, 3, &chunk)) {
//成功,处理文件
struRYDeviceData *data = (struRYDeviceData *)chunk.response;
unionCP56Time st;
int uid = mbt->GetCurUnitID();
for (int i = 0; i < 250; i++, data++) {
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;
st = Time_ttounionCP56Time(localtime);
//如何将结构化数据传入,且快速获取
Json::Value highspeedvalues;
for (datatypemap::iterator it = highspeedmap.begin(); it != highspeedmap.end(); it++) {
//获取数据
DWORD 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 0
vLog(LOG_DEBUG, "datatime is: %04d-%02d-%02d %02d:%02d:%02d.%03d, value1 is: %d, value2 is: %d.\n",
st.year + 2000, st.month, st.dayofmonth, st.hour, st.minute, st.millisecond / 1000,
unix_time % 1000,
data->iGenSpeed,
data->iGenPower);
#endif
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;
}
}
publishhistoryHighSpeedData(g_conn, uid, unix_time, highspeedvalues);
if (i % 25 == 0) { //40ms一个值每25次位1s
Json::Value lowspeedvalues;
for (datatypemap::iterator it = lowspeedmap.begin(); it != lowspeedmap.end(); it++) {
//获取数据
DWORD 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;
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;
}
}
publishhistoryLowSpeedData(g_conn, uid, unix_time, lowspeedvalues);
}
}
if (chunk.response) free(chunk.response);
//vLog(LOG_DEBUG, "get a file, then send to ws.\n");
clock_gettime(CLOCK_MONOTONIC, &end);
elapsed_time = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;
vLog(LOG_DEBUG, "Elapsed time: %.6f seconds\n", elapsed_time);
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 0
if (mbt->m_currentDirNo >= 56) { //7天数据大约有56个文件夹
mbt->m_currentDirNo = 0;
}
#endif
//保存文件信息
}
}
}
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()
{
m_nCount = 0;
m_nFrameCount = 0;
m_nCurFrame = 0;
m_nSendPoint = 0;
m_nCurBeginReg = 0;
m_nNeedSend = FALSE;
#ifdef HAVE_FTP_PROCESS
//websocket接口
m_pid = 0;
//目录无效
m_iv = 1;
m_currentDirNo = -1; //当前目录编号
m_currentFileNo = -1; //当前文件编号
m_lastDirNo = -1; //上一目录编号
m_lastFileNo = -1; //上一文件编号
#endif
}
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, &params[j], sizeof(STRUCT_PARAM));
memcpy(&params[j], &params[j + 1], sizeof(STRUCT_PARAM));
memcpy(&params[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, &params[j], sizeof(STRUCT_PARAM));
memcpy(&params[j], &params[j + 1], sizeof(STRUCT_PARAM));
memcpy(&params[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();
vLog(LOG_DEBUG, "file size is: %d\n", sizeof(struRYDeviceData) * 250 / 1024);
#ifdef HAVE_FTP_PROCESS
//启动后创建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);
}
#endif
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;
#ifdef HAVE_FTP_PROCESS
//启动时读取一次,后面自己维护序号
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);
}
#ifdef HAVE_FTP_PROCESS
else if (m_nCurFrame == MODBUSP_READ_ID)
{
return OnReceiveIDData(pItem, &pData[3], count);
}
#endif
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;
}
#ifdef HAVE_FTP_PROCESS
BOOLEAN CHostModbusTcpProcess::OnReceiveIDData(CHostModbusTcpProcessItem *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, "路径信息无效\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;
#if 0
m_currentDirNo = 37;
m_currentFileNo = 26901;
m_lastStartFileNo = 26901;
#endif
vLog(LOG_DEBUG, "dir: %ld, file: %ld: start: %ld\n", m_currentDirNo, m_currentFileNo, m_lastStartFileNo);
return TRUE;
}
#endif
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;
}