map/das-dn/hostmodbustcpbf/host_modbus_tcp_bf.cpp

2663 lines
103 KiB
C++
Raw Normal View History

2024-11-20 15:43:54 +08:00
#include "host_modbus_tcp_bf.h"
#include <json.h>
#include <math.h>
#include <map>
#include <unordered_map>
#include <curl/curl.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寄存器长度。
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, 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 },
{ 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 },
{ 2, 362 },
{ 2, 363 },
{ 2, 364 },
{ 2, 365 },
{ 2, 366 },
{ 2, 367 },
{ 2, 368 }
};
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", 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 (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
curl_easy_cleanup(curl);
curl_global_cleanup();
return ret;
}
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] = "Hard Disk2/data/rtdatalog";
char pathName[128] = "./";
//配置远方路径
char* escaped_string = escape_char_in_string(mbt->m_remotePath, ' ');
if (escaped_string == NULL)
{
vLog(LOG_DEBUG, "路径转义错误!\n");
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 < 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.iWindSpeed_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iWindSpeed_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenSpeed_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenSpeed_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenPower_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenPower_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenToruqe_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenToruqe_1sec);
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++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenSpeed_10sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenSpeed_10sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenSpeed_30sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenSpeed_30sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenPower_10sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenPower_10sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenPower_30sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenPower_30sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iWindSpeed_10sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iWindSpeed_10sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iWindSpeed_30sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iWindSpeed_30sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iAvailablePower) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iAvailablePower);
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);
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);
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-数据文件序号
}
}
//根据实际配置表将
WORD ftpget_retry_count = 0;
BOOLEAN bReadCurrentFile = TRUE; //读取当前文件标识
while (TRUE) {
sleep(1); //每秒执行一次
if (!mbt->m_bFtpRun) break;
//ftp获取文件
if (mbt->m_iv == 1) {
//文件目录无效
continue;
}
if (bReadCurrentFile)
{ //读取当前文件
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
{ //读取未读的文件
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
int result = ftpget(remote, name, user, password, 3, &chunk);
if (result == CURLE_OK) {
//成功,处理文件
vLog(LOG_DEBUG, "get %s to local %s, with name: %s, and password: %s okay.\n", remote, name, user, password);
ftpget_retry_count = 0;
struRYDeviceData *data = (struRYDeviceData *)chunk.response;
unionCP56Time st;
int uid = mbt->GetCurUnitID();
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;
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)) {
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);
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, "已读取完成所有未读的文件。\n");
mbt->m_bHaveUnReadFile = FALSE;
}
}
bReadCurrentFile = TRUE;
} else if (result == CURLE_REMOTE_FILE_NOT_FOUND) {
//文件不存在尝试60次1分钟正常情况下PLC10s生成一个文件
ftpget_retry_count++;
if (ftpget_retry_count >= 60) {
//重新通过modbus程序获取文件夹和最新文件信息
mbt->m_iv = 0;
mbt->m_currentDirNo = -1;
mbt->m_currentFileNo = -1;
}
//此处空闲读取未读的文件
if (mbt->m_bHaveUnReadFile) {
bReadCurrentFile = FALSE;
}
}
}
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_pid = 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);
}
}
}
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;
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 (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;
}
}
}
}
}
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 CHostModbusTcpBFProcess::OnPreCreate(int id)
{
if (!CNetProcess::OnPreCreate(id)) return FALSE;
if (!GetOption(&m_nOptions, sizeof(m_nOptions)))
{
vLog(LOG_DEBUG, "润阳modbus读取配置错误。");
return FALSE;
}
m_bHaveFTP = m_nOptions.bHaveFTP;
m_nTimeout = 200;
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);
vLog(LOG_DEBUG, "file size is: %d\n", sizeof(struRYDeviceData) * 250 / 1024);
//读取文件
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_pid <= 0) {
m_bFtpRun = TRUE;
vLog(LOG_DEBUG, "create a ftp thread.\n");
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, MEMERY_1M);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
if (pthread_create(&m_pid, &attr, ryftp_process, this) < 0) {
vLog(LOG_ERROR, "create ryftp_process error(%d,%s).\n", errno, strerror(errno));
return TRUE;
}
char name[17];
snprintf(name, 16, "%s_ftp", GetCurProcessName());
pthread_setname_np(m_pid, name);
pthread_attr_destroy(&attr);
}
}
return TRUE;
}
BOOLEAN 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;
}
pItem = (CHostModbusTcpBFProcessItem *)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 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 dint10
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_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, "不存在未读的文件。\n");
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, "总共有%d个目录的%d个文件未读取。\n", dir_count, file_count);
}
/*文件从保存的最后读取的文件目录的文件一直督导当前开始目录*/
vLog(LOG_DEBUG, "最新文件夹编号: %ld, 最新文件名编号: %ld: 最新文件夹中第一个文件的编号: %ld\n", 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;
}