This commit is contained in:
高云鹏 2024-11-27 13:27:31 +08:00
commit e13085ae4e
14 changed files with 1275 additions and 237 deletions

View File

@ -61,7 +61,9 @@ include_directories (
inc/uuid
inc/sqlite
inc/nopoll
inc/websockets
inc/crypto
cmg/
inc/mqtt)
set (APP_SRCS
@ -136,24 +138,31 @@ set (APP_SRCS ${APP_SRCS}
if (USE_WEBSOCKET)
set (APP_SRCS ${APP_SRCS}
third_party/nopoll/nopoll.c
third_party/nopoll/nopoll_conn.c
third_party/nopoll/nopoll_conn_opts.c
third_party/nopoll/nopoll_listener.c
third_party/nopoll/nopoll_ctx.c
third_party/nopoll/nopoll_decl.c
third_party/nopoll/nopoll_io.c
third_party/nopoll/nopoll_log.c
third_party/nopoll/nopoll_msg.c)
third_party/websockets/easywsclient.cpp
)
# find_package(websockets)
# set (APP_LIBS ${APP_LIBS} websockets)
# set (APP_SRCS ${APP_SRCS}
# third_party/nopoll/nopoll.c
# third_party/nopoll/nopoll_conn.c
# third_party/nopoll/nopoll_conn_opts.c
# third_party/nopoll/nopoll_listener.c
# third_party/nopoll/nopoll_ctx.c
# third_party/nopoll/nopoll_decl.c
# third_party/nopoll/nopoll_io.c
# third_party/nopoll/nopoll_log.c
# third_party/nopoll/nopoll_msg.c)
set (APP_LIBS ${APP_LIBS} ssl crypto)
add_definitions(-DUSE_WEBSOCKET)
add_definitions(-DNOPOLL_OS_UNIX=1)
add_definitions(-DSHOW_DEBUG_LOG)
add_definitions(-DNOPOLL_HAVE_VASPRINTF=1)
add_definitions(-DNOPOLL_HAVE_TLSv10_ENABLED=1)
add_definitions(-DNOPOLL_HAVE_TLSv11_ENABLED=1)
add_definitions(-DNOPOLL_HAVE_TLSv12_ENABLED=1)
add_definitions(-DNOPOLL_HAVE_TLS_FLEXIBLE_ENABLED=1)
# add_definitions(-DUSE_WEBSOCKET)
# add_definitions(-DNOPOLL_OS_UNIX=1)
# add_definitions(-DSHOW_DEBUG_LOG)
# add_definitions(-DNOPOLL_HAVE_VASPRINTF=1)
# add_definitions(-DNOPOLL_HAVE_TLSv10_ENABLED=1)
# add_definitions(-DNOPOLL_HAVE_TLSv11_ENABLED=1)
# add_definitions(-DNOPOLL_HAVE_TLSv12_ENABLED=1)
# add_definitions(-DNOPOLL_HAVE_TLS_FLEXIBLE_ENABLED=1)
endif ()
if (USE_MQTT)

View File

@ -186,6 +186,7 @@ int main(int argc, char** argv)
signal(SIGFPE, stop);
CRYDevice ryDevice;
g_conn = &ryDevice;
do {
vLog(LOG_DEBUG, "system initialize...\n");

View File

@ -1,17 +1,25 @@
#include "ry.h"
#include <math.h>
CRYDevice::CRYDevice()
{
#if 1
#else
ctx = NULL;
conn = NULL;
msg_count = 0;
#endif
pthread_mutex_init(&m_SendQueueMutex, NULL);
pthread_mutex_init(&m_RecvQueueMutex, NULL);
}
CRYDevice::~CRYDevice()
{
// client.setEnd(true);
pthread_mutex_destroy(&m_SendQueueMutex);
pthread_mutex_destroy(&m_RecvQueueMutex);
}
bool CRYDevice::configInitializeMemory(void)
@ -249,7 +257,8 @@ bool CRYDevice::configWriteDatabaseCFG(void)
}
return false;
}
#if 1
#else
BOOLEAN CRYDevice::websocket_msg_join(noPollMsg **msg, int msg_count, BYTE* &buffer, int &buffer_size)
{
if (msg_count <= 0 || msg_count >= MAX_MSG_COUNT) return FALSE;
@ -280,7 +289,7 @@ int CRYDevice::websocket_write(const char * buffer, int buffer_len)
result = nopoll_conn_flush_writes(conn, 2000000, result);
return (result == buffer_len) ? 0 : -1;
}
#endif
bool CRYDevice::publish_sensor_data(const std::string traceId, const char* command, const Json::Value payload)
{
Json::StreamWriterBuilder builder;
@ -305,6 +314,7 @@ bool CRYDevice::publish_sensor_data(const std::string traceId, const char* comma
jsonRoot["data"] = payload;
std::string outputConfig = Json::writeString(builder, jsonRoot);
if (traceId != "")
{
vLog(LOG_DEBUG, "send cmd: %s, payload: %d\n", command, outputConfig.length());
@ -314,13 +324,18 @@ bool CRYDevice::publish_sensor_data(const std::string traceId, const char* comma
vLog(LOG_DEBUG, "send cmd: %s, payload: %d\n", command, outputConfig.length());
}
}
#if 1
//vLog(LOG_DEBUG, "push a frame <%s>\n", command);
sendMsg(outputConfig);
//g_conn->send(outputConfig);
#else
int rc = websocket_write(outputConfig.c_str(), outputConfig.length());
if (rc != 0) {
vLog(LOG_DEBUG, "websocket write is error<%d>,insert into database.\n", rc);
//插入数据库
return false;
}
#endif
return true;
}
@ -3102,10 +3117,6 @@ BOOLEAN CRYDevice::ry_init(const char *host, const int port, const char *nodeId,
snprintf(m_version, sizeof(m_version), "%s", version);
m_port = port;
ctx = nopoll_ctx_new();
nopoll_log_enable(ctx, nopoll_false);
nopoll_log_color_enable(ctx, nopoll_false);
status = 2; //0 - 离线, 1 - 在线, 2 - 未配置
m_dataAcquisitionReload = false;
@ -3148,7 +3159,26 @@ BOOLEAN CRYDevice::ry_init(const char *host, const int port, const char *nodeId,
}
}
status = 1;
#if 1
#if 0
char url[512];
snprintf(url, sizeof(url), "ws://%s:%d/node/%s/%s", m_host, m_port, m_nodeId, m_version);
client.init(url);
client.set_ssl(NULL, NULL, NULL, 0);
client.create();
client.connect(0);
client.run(200);
g_conn = &client;
#else
char url[520];
snprintf(url, sizeof(url), "ws://%s:%d/node/%s/%s", m_host, m_port, m_nodeId, m_version);
m_ws = WebSocket::from_url(url);
last_connect_sec = system32.timers;
#endif
#else
ctx = nopoll_ctx_new();
nopoll_log_enable(ctx, nopoll_false);
nopoll_log_color_enable(ctx, nopoll_false);
if (ctx != NULL) {
nopoll_conn_connect_timeout(ctx, 50000);
char url[512];
@ -3160,12 +3190,103 @@ BOOLEAN CRYDevice::ry_init(const char *host, const int port, const char *nodeId,
conn = nopoll_conn_new(ctx, m_host, cPort, NULL, url, NULL, NULL);
g_conn = conn;
}
#endif
return TRUE;
}
int CRYDevice::sendMsg(std::string sMessage)
{
if (NULL != m_ws && m_ws->getReadyState() == easywsclient::WebSocket::OPEN)
{
pthread_mutex_lock(&m_SendQueueMutex);
m_SendQueue.push(sMessage);
pthread_mutex_unlock(&m_SendQueueMutex);
return (int)sMessage.length();
}
return 0;
}
int CRYDevice::recvMsg(std::string sMessage)
{
pthread_mutex_lock(&m_RecvQueueMutex);
m_recvMsgQueue.push(sMessage);
pthread_mutex_unlock(&m_RecvQueueMutex);
return (int)sMessage.length();
}
bool CRYDevice::ry_run(void)
{
#if 1
#if 0
std::string msg;
do {
msg = client.getRecvMsg();
if (msg != "")
{
on_message((const char *)msg.c_str(), msg.length());
}
client.popRecvMsg();
} while (msg != "");
#else
if (m_ws != NULL)
{
if (m_ws->getReadyState() != WebSocket::CLOSED)
{
CRYDevice *rydevice = this;
std::string data;
m_ws->poll();
m_ws->dispatch([rydevice](const std::string & message) {
//printf(">>> %s\n", message.c_str());
rydevice->on_message((const char *)message.c_str(), message.length());
});
//如果有数据待发
if (!m_SendQueue.empty())
{
std::string sMessage;
while (1)
{
pthread_mutex_lock(&m_SendQueueMutex);
if (!m_SendQueue.empty())
{
sMessage = m_SendQueue.front();
m_SendQueue.pop();
}
else
{
pthread_mutex_unlock(&m_SendQueueMutex);
break;
}
pthread_mutex_unlock(&m_SendQueueMutex);
m_ws->send(sMessage);
}
}
}
else if (m_ws->getReadyState() == WebSocket::CLOSED)
{
delete m_ws;
m_ws = NULL;
char url[520];
snprintf(url, sizeof(url), "ws://%s:%d/node/%s/%s", m_host, m_port, m_nodeId, m_version);
m_ws = WebSocket::from_url(url);
last_connect_sec = system32.timers;
vLog(LOG_DEBUG, "here reconnect.\n");
}
}
else
{
if (last_connect_sec > 0 && system32.timers > (last_connect_sec + 8)) {
char url[520];
snprintf(url, sizeof(url), "ws://%s:%d/node/%s/%s", m_host, m_port, m_nodeId, m_version);
m_ws = WebSocket::from_url(url);
last_connect_sec = system32.timers;
vLog(LOG_DEBUG, "here reconnect.\n");
}
}
#endif
#else
nopoll_bool isOk = nopoll_conn_is_ready(conn);
if (isOk) {
last_connect_sec = system32.timers;
@ -3211,6 +3332,7 @@ bool CRYDevice::ry_run(void)
last_connect_sec = system32.timers;
}
}
#endif
BOOLEAN sec_changed = FALSE;
if (last_sec != (time_t)system32.timers) {
last_sec = system32.timers;
@ -3239,6 +3361,10 @@ bool CRYDevice::ry_run(void)
void CRYDevice::ry_destroy(void)
{
#if 1
// client.destroy();
#else
nopoll_conn_close(conn);
nopoll_ctx_unref(ctx);
#endif
}

View File

@ -11,8 +11,13 @@
#include <fnmatch.h>
#include <signal.h>
#include <nopoll.h>
#include <nopoll_decl.h>
#if 1
#include <easywsclient.hpp>
using easywsclient::WebSocket;
#else
#include <nopoll.h>
#include <nopoll_decl.h>
#endif
#include <json.h>
#include <md5.h>
@ -27,6 +32,7 @@
#include "ytlog.h"
#include "public.h"
#define MAX_MSG_COUNT 4096
typedef std::unordered_map<std::string, short> uid2pidmap;
@ -66,6 +72,10 @@ typedef struct {
typedef std::unordered_map<int, attrvectorGroup> pid2attrvectormap;
#include <queue>
#include <string>
#include <stack>
class CRYDevice
{
public:
@ -75,6 +85,10 @@ public:
BOOLEAN ry_init(const char*, const int, const char*, const char*);
void ry_destroy(void);
bool ry_run(void);
int sendMsg(std::string);
int recvMsg(std::string);
void handle_message(const std::string & message);
private:
uid2pidmap uid2pid_map;
unitname2servicemap unitname2service_map;
@ -92,15 +106,24 @@ private:
struUnitStatic config_static_units[UNIT_NUM];
private:
#if 1
std::queue<std::string> m_SendQueue;
std::queue<std::string> m_recvMsgQueue;
pthread_mutex_t m_SendQueueMutex;
pthread_mutex_t m_RecvQueueMutex;
WebSocket::pointer m_ws;
#else
noPollCtx *ctx;
noPollConn *conn;
DWORD last_connect_sec = 0;
int status;
int msg_count = 0;
noPollMsg *msg[2048];
int msg_count = 0;
#endif
bool m_dataAcquisitionReload = false;
DWORD last_connect_sec = 0;
int status;
bool m_dataAcquisitionReload = false;
char m_host[256] = {"127.0.0.1"};
int m_port = 7790;
@ -162,9 +185,11 @@ private:
bool publishdeviceEventData(void);
BOOLEAN publishYXBWData(int uid);
BOOLEAN publishYCBWData(int uid);
#if 1
#else
BOOLEAN websocket_msg_join(noPollMsg **msg, int msg_count, BYTE* &buffer, int &buffer_size);
int websocket_write(const char * buffer, int buffer_len);
#endif
bool publish_sensor_data(const std::string traceId, const char* command, const Json::Value payload);
};
#endif //_RY_H_

View File

@ -23,6 +23,8 @@
#include "json.h"
#include "ry.h"
#define PARAMTER_TYPE_MODBUS 1
#define PARAMTER_TYPE_104 2
#define PARAMTER_TYPE_9712 3
@ -52,8 +54,12 @@ char configpath[MAX_PATH] = "./conf"; //配置文件
char configfile[MAX_PATH] = "./conf/config.db"; //配置文件
QWORD system_timems;
#if 1
//WebSocket::pointer g_conn;
CRYDevice* g_conn;
#else
noPollConn *g_conn;
#endif
Snowflake g_sf = {1, 1, 0, 0};
static eLogLevel eLevelMax = LOG_DEBUG; //LOG_DEBUG;

View File

@ -312,6 +312,7 @@ void CHostModbusRtuProcess::calc1(void)
}
}
}
delete [] ycparam;
}
if (ymparam)
{
@ -355,6 +356,7 @@ void CHostModbusRtuProcess::calc1(void)
}
}
}
delete [] ymparam;
}
if (yxparam)
{
@ -413,6 +415,7 @@ void CHostModbusRtuProcess::calc1(void)
}
}
}
delete [] yxparam;
}
//按寄存器排序
pItem->AddFrames(ycframes, ymframes, yxframes);
@ -643,7 +646,7 @@ BOOLEAN CHostModbusRtuProcess::Run(void)
GetData(tmpbuf, tmplen);
DropData(tmplen);
DisplayRxData(tmpbuf, tmplen, FALSE);
delete tmpbuf;
delete [] tmpbuf;
tmpbuf = NULL;
}
if (WriteData(buffer, count + 2))
@ -683,7 +686,7 @@ BOOLEAN CHostModbusRtuProcess::OnTimer(void)
GetData(tmpbuf, tmplen);
DropData(tmplen);
DisplayRxData(tmpbuf, tmplen, FALSE);
delete tmpbuf;
delete [] tmpbuf;
tmpbuf = NULL;
}
m_nNeedCount = 2;

View File

@ -4,6 +4,7 @@
#include <map>
#include <unordered_map>
#include <curl/curl.h>
#include <ry.h>
#define MODBUSP_READ_ID 100 //读取文件及文件夹ID
#define MODBUSP_READ_ID_FUNCCODE 0x03 //读取文件及文件夹ID功能码。
@ -22,8 +23,8 @@ typedef std::unordered_map<short, short> datatypemap;
typedef struct
{
int start;
int length;
int start;
int length;
} FIELDDES;
struct {
@ -132,9 +133,8 @@ struct {
{ 2, 307 },
{ 4, 308 },
{ 4, 310 },
{ 2, 312 },
{ 4, 313 },
{ 2, 315 },
{ 4, 312 },
{ 4, 314 },
{ 4, 316 },
{ 4, 318 },
{ 2, 320 },
@ -185,9 +185,34 @@ struct {
{ 2, 365 },
{ 2, 366 },
{ 2, 367 },
{ 2, 368 }
{ 2, 368 },
{ 2, 369 },
{ 2, 370 },
{ 2, 371 },
{ 2, 372 },
{ 2, 373 },
{ 2, 374 },
{ 2, 375 },
{ 2, 376 },
{ 2, 377 },
{ 4, 378 },
{ 4, 380 },
{ 4, 382 },
{ 2, 384 },
{ 2, 385 },
{ 2, 386 },
{ 2, 387 },
{ 2, 388 },
{ 2, 389 },
{ 2, 390 },
{ 2, 391 },
{ 2, 392 },
{ 2, 393 },
{ 2, 394 }
};
#if 1
#else
static int websocket_write(const noPollConn* conn, const char * buffer, int buffer_len)
{
int result;
@ -196,8 +221,12 @@ static int websocket_write(const noPollConn* conn, const char * buffer, int buff
result = nopoll_conn_flush_writes((noPollConn *)conn, 2000000, result);
return (result == buffer_len) ? 0 : -1;
}
#endif
#if 1
static bool publish_sensor_data(const char* command, const Json::Value payload)
#else
static bool publish_sensor_data(const noPollConn* conn, const char* command, const Json::Value payload)
#endif
{
Json::StreamWriterBuilder builder;
builder["indentation"] = "";
@ -216,7 +245,12 @@ static bool publish_sensor_data(const noPollConn* conn, const char* command, con
jsonRoot["time"] = mtime;
jsonRoot["data"] = payload;
//vLog(LOG_DEBUG, "here start to send.\n");
std::string outputConfig = Json::writeString(builder, jsonRoot);
#if 1
g_conn->sendMsg(outputConfig);
//vLog(LOG_DEBUG, "outputConfig length is: %d\n", outputConfig.length());
#else
int rc = websocket_write(conn, outputConfig.c_str(), outputConfig.length());
//vLog(LOG_DEBUG, "send cmd: %s, payload: %d\n", command, outputConfig.length()/*, outputConfig.c_str()*/);
if (rc != 0) {
@ -224,7 +258,7 @@ static bool publish_sensor_data(const noPollConn* conn, const char* command, con
//插入数据库
return false;
}
#endif
return true;
}
@ -334,10 +368,10 @@ static BYTE GetUnitYXDataPos(int uid, int point)
struUnit* pUnit;
struUnitYX* pYX;
if (uid < 0 || uid >= UNIT_NUM) return (WORD)65535;
if (uid < 0 || uid >= UNIT_NUM) return (BYTE)0;
pUnit = &config.units[uid];
if (pUnit->yxcount <= 0) return (WORD)65535;
if (point < 0 || point >= pUnit->yxcount) return (WORD)65535;
if (pUnit->yxcount <= 0) return (BYTE)0;
if (point < 0 || point >= pUnit->yxcount) return (BYTE)0;
pYX = &pUnit->yxs[point];
return (pYX->m_param[3]);
}
@ -347,7 +381,7 @@ static BOOLEAN GetYCValue(const int order, const FIELDDES* fields, const char* p
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;
int start = fields[order].start;
if (fields[order].length == sizeof(DWORD))
{ //4字节
value = *(DWORD *)(pData + start);
@ -369,7 +403,7 @@ static BOOLEAN GetYXValue(const int order, const FIELDDES* fields, const char* p
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;
int start = fields[order].start;
if (fields[order].length == sizeof(WORD))
{
WORD tmp = *(WORD *)(pData + start);
@ -383,7 +417,11 @@ static BOOLEAN GetYXValue(const int order, const FIELDDES* fields, const char* p
return FALSE;
}
#if 1
static bool publishhistoryHighSpeedData(const int uid, const QWORD dt, const Json::Value values)
#else
static bool publishhistoryHighSpeedData(const noPollConn* conn, const int uid, const QWORD dt, const Json::Value values)
#endif
{
if (uid < 0 || uid >= UNIT_NUM) return false;
Json::Value root;
@ -391,12 +429,20 @@ static bool publishhistoryHighSpeedData(const noPollConn* conn, const int uid, c
root["dataTime"] = (Json::Int64)dt;
root["deviceId"] = static_units[uid].deviceId;
root["values"] = values;
#if 1
return publish_sensor_data("historyHighSpeedData", root);
#else
return publish_sensor_data(conn, "historyHighSpeedData", root);
#endif
}
return false;
}
#if 1
static bool publishhistoryLowSpeedData(const int uid, const QWORD dt, const Json::Value values)
#else
static bool publishhistoryLowSpeedData(const noPollConn* conn, const int uid, const QWORD dt, const Json::Value values)
#endif
{
if (uid < 0 || uid >= UNIT_NUM) return false;
Json::Value root;
@ -405,7 +451,11 @@ static bool publishhistoryLowSpeedData(const noPollConn* conn, const int uid, co
root["dataTime"] = (Json::Int64)(dt / 1000 * 1000); //取整
root["deviceId"] = static_units[uid].deviceId;
root["values"] = values;
#if 1
return publish_sensor_data("historyLowSpeedData", root);
#else
return publish_sensor_data(conn, "historyLowSpeedData", root);
#endif
}
return false;
}
@ -450,11 +500,11 @@ static int progressCallback(void* p, curl_off_t dltotal, curl_off_t dlnow, curl_
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &curtime);
if ((curtime - progress->lastruntime) >= 3000000) {
progress->lastruntime = curtime;
fprintf(stderr, "Total time: %f\n", curtime);
vLog(LOG_DEBUG, "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));
vLog(LOG_DEBUG, "UP: %ld bytes of %ld bytes, DOWN: %ld bytes of %ld bytes.\n", ulnow, ultotal, dlnow, dltotal);
if (ultotal) vLog(LOG_DEBUG, "UP progress: %0.2f\n", float(ulnow /ultotal));
if (dltotal) vLog(LOG_DEBUG, "DOWN progress: %0.2f\n", float(dlnow /dltotal));
return 0;
}
@ -591,7 +641,6 @@ static void* ryftp_process(void* param)
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++;
@ -619,8 +668,8 @@ static void* ryftp_process(void* param)
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);
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenToruqe) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenToruqe);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iRotorSpeed) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iRotorSpeed);
@ -634,8 +683,8 @@ static void* ryftp_process(void* param)
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);
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iReactivePowerSetPointValue) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iReactivePowerSetPointValue);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iSetValueGenSpeed) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iSetValueGenSpeed);
@ -904,9 +953,6 @@ static void* ryftp_process(void* param)
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++;
@ -1033,6 +1079,30 @@ static void* ryftp_process(void* param)
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.SCW043) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW043);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW044) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW044);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW045) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW045);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW046) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW046);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW047) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW047);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW048) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW048);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW049) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW049);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.SCW050) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.SCW050);
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++;
@ -1051,10 +1121,54 @@ static void* ryftp_process(void* param)
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.iWindSpeed_10min) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iWindSpeed_10min);
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++;
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.FaultInformation) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.FaultInformation);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.WecRunCondition) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.WecRunCondition);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iWindSpeedIEC) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iWindSpeedIEC);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iWindSpeedIEC_30sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iWindSpeedIEC_30sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iWindSpeedIEC_10min) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iWindSpeedIEC_10min);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iYawPress) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iYawPress);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iStandardAirDensity) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iStandardAirDensity);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iAirDensity) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iAirDensity);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iVibrationYFiltered) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iVibrationYFiltered);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iVibrationZFiltered) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iVibrationZFiltered);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempGearWaterCool_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempGearWaterCool_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.PowerLimitSource) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.PowerLimitSource);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iTempOutdoor_10min) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iTempOutdoor_10min);
len++;
//判断是否链接单元
int uid = mbt->GetUnitID(0); //默认只接一个设备
@ -1107,22 +1221,27 @@ static void* ryftp_process(void* param)
if (bReadCurrentFile)
{ //读取当前文件
//vLog(LOG_DEBUG, "读取当前文件.\n");
snprintf(name, sizeof(name), "%s/%d", pathName, mbt->m_currentFileNo);
snprintf(remote, sizeof(remote), "ftp://%s/%s/%d/%d", ipaddress, remotePath, mbt->m_currentDirNo, mbt->m_currentFileNo);
}
else
{ //读取未读的文件
//vLog(LOG_DEBUG, "读取未读的文件.\n");
snprintf(name, sizeof(name), "%s/%d", pathName, mbt->m_lastReadFileNo);
snprintf(remote, sizeof(remote), "ftp://%s/%s/%d/%d", ipaddress, remotePath, mbt->m_lastReadDirNo, mbt->m_lastReadFileNo);
}
struct memory chunk = {0}; // For storing the downloaded data
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);
vLog(LOG_DEBUG, "get %s to local %s, with name: %s, and password: %s okay, and file length is: %d.\n", remote, name, user, password, chunk.size);
ftpget_retry_count = 0;
if (chunk.size <= 0) {
vLog(LOG_DEBUG, "PLC文件生成未完成\n");
continue;
}
struRYDeviceData *data = (struRYDeviceData *)chunk.response;
unionCP56Time st;
@ -1153,7 +1272,11 @@ static void* ryftp_process(void* param)
highspeedvalues[(const char *)config.units[uid].ycs[order].name] = 0.0f;
}
}
#if 1
publishhistoryHighSpeedData(uid, unix_time, highspeedvalues);
#else
publishhistoryHighSpeedData(g_conn, uid, unix_time, highspeedvalues);
#endif
if (i % 25 == 0) { //40ms一个值每25次位1s
Json::Value lowspeedvalues;
@ -1184,7 +1307,11 @@ static void* ryftp_process(void* param)
lowspeedvalues[(const char *)config.units[uid].yxs[order].name] = 0;
}
}
#if 1
publishhistoryLowSpeedData(uid, unix_time, lowspeedvalues);
#else
publishhistoryLowSpeedData(g_conn, uid, unix_time, lowspeedvalues);
#endif
}
}
@ -1212,6 +1339,7 @@ static void* ryftp_process(void* param)
bReadCurrentFile = TRUE;
} else if (result == CURLE_REMOTE_FILE_NOT_FOUND) {
//文件不存在尝试60次1分钟正常情况下PLC10s生成一个文件
//vLog(LOG_DEBUG, "文件不存在, ftpget_retry_count is: %d\n", ftpget_retry_count);
ftpget_retry_count++;
if (ftpget_retry_count >= 60) {
//重新通过modbus程序获取文件夹和最新文件信息
@ -1223,6 +1351,10 @@ static void* ryftp_process(void* param)
if (mbt->m_bHaveUnReadFile) {
bReadCurrentFile = FALSE;
}
} else if (result == CURLE_REMOTE_ACCESS_DENIED) {
vLog(LOG_DEBUG, "已读取完成所有未读的文件。\n");
mbt->m_bHaveUnReadFile = FALSE;
bReadCurrentFile = TRUE;
}
}
@ -1531,8 +1663,8 @@ void CHostModbusTcpBFProcess::calc2(void)
//组帧
for (n = 0; n < yccount; n++)
{
WORD addr = MAKEWORD(ycparam[n].param[1], ycparam[n].param[2]);
if (addr >= 65535) continue;
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)
@ -1561,6 +1693,8 @@ void CHostModbusTcpBFProcess::calc2(void)
}
}
}
delete [] ycparam;
}
if (ymparam)
{
@ -1574,8 +1708,8 @@ void CHostModbusTcpBFProcess::calc2(void)
//组帧
for (n = 0; n < ymcount; n++)
{
WORD addr = MAKEWORD(ymparam[n].param[1], ymparam[n].param[2]);
if (addr >= 65535) continue;
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)
@ -1604,6 +1738,8 @@ void CHostModbusTcpBFProcess::calc2(void)
}
}
}
delete [] ymparam;
}
if (yxparam)
{
@ -1617,8 +1753,8 @@ void CHostModbusTcpBFProcess::calc2(void)
//组帧
for (n = 0; n < yxcount; n++)
{
WORD addr = MAKEWORD(yxparam[n].param[1], yxparam[n].param[2]);
if (addr >= 65535) continue;
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)
@ -1662,6 +1798,7 @@ void CHostModbusTcpBFProcess::calc2(void)
}
}
}
delete [] yxparam;
}
//按寄存器排序
pItem->AddFrames(yxframes, ycframes, ymframes);
@ -2308,9 +2445,9 @@ BOOLEAN CHostModbusTcpBFProcess::OnReceiveIDData(CHostModbusTcpBFProcessItem *pI
/*
1 byte
2 dint10
3 dint
4 dint;
2 dint10
3 dint
4 dint;
5 dint
*/
//路径有效性判断

View File

@ -5,168 +5,194 @@
#include "modbus_def.h"
#include <dirent.h>
#if 1
//#include "client.h"
#else
#include <nopoll.h>
#include <nopoll_decl.h>
#endif
#pragma pack(1)
typedef struct {
QLONG localtime;// PLC本地时间 8 none 0.0001 毫秒 little endian 系统
WORD iGenSpeed;// 发电机转速 2 200 0.1 转/分 40ms 控制系统
WORD iGenPower;// 机组有功功率 2 201 0.1 千瓦 40ms 控制系统
WORD iWindSpeed;// 风速 2 202 0.01 米/秒 40ms 气象
WORD iVibrationY;// 机舱振动前后方向 2 203 0.001 米/秒^2 40ms 机舱
WORD iVibrationZ;// 机舱振动左右方向 2 204 0.001 米/秒^2 40ms 机舱
WORD iTurbineOperationMode;// 运行模式 2 205 1 需要解析 1s 控制系统
WORD iBPLevel;// 刹车等级 2 206 1 需要解析 1s 控制系统
WORD iYPLevel;// 偏航运行模式 2 207 1 需要解析 1s 控制系统
WORD iWindSpeed_1sec;// 风速1秒均值 2 208 0.01 米/秒 1s 控制系统
WORD iGenSpeed_1sec;// 发电机转速1秒均值 2 209 0.1 转/分 1s 控制系统
WORD iGenPower_1sec;// 机组有功1秒均值 2 210 0.1 千瓦 1s 控制系统
WORD iGenToruqe_1sec;// 发电机扭矩1秒均值 2 211 0.1 牛米 1s 控制系统
WORD iRotorSpeed;// 风轮转速 2 212 0.1 转/分 1s 控制系统
WORD iTheoreticalPower;// 理论有功功率 2 213 0.1 千瓦 1s 控制系统
WORD iReactivePower;// 无功功率 2 214 0.1 千乏 1s 控制系统
WORD iActivePowerSetPointValue;// 有功设定值 2 215 0.1 千瓦 1s 控制系统
WORD iCosPhiSetValue;// 功率因数设定值 2 216 0.001 . 1s 控制系统
WORD iSetValueGenSpeed;// 发电机转速设定值 2 217 0.1 转/分 1s 控制系统
WORD iSetValuePitchAngle;// 桨叶角度设定值 2 218 0.01 度 1s 控制系统
WORD iPitchAngle1RefValue;// 桨叶1角度给定 2 219 0.01 度 1s 控制系统
WORD iPitchAngle2RefValue;// 桨叶2角度给定 2 220 0.01 度 1s 控制系统
WORD iPitchAngle3RefValue;// 桨叶3角度给定 2 221 0.01 度 1s 控制系统
WORD iPitchAngle1;// 桨叶1角度 2 222 0.01 度 1s 变桨系统
WORD iPitchAngle2;// 桨叶2角度 2 223 0.01 度 1s 变桨系统
WORD iPitchAngle3;// 桨叶3角度 2 224 0.01 度 1s 变桨系统
WORD iVaneDirection;// 机舱方向 2 225 0.1 度 1s 气象
WORD iWindDirection;// 风向(与机舱夹角) 2 226 0.1 度 1s 气象
WORD StateWord01;// 状态字01 2 227 1 需要解析 1s 控制系统 详细解析见 状态字解析
WORD StateWord02;// 状态字02 2 228 1 需要解析 1s 控制系统
WORD StateWord03;// 状态字03 2 229 1 需要解析 1s 控制系统
WORD StateWord04;// 状态字04 2 230 1 需要解析 1s 控制系统
WORD StateWord05;// 状态字05 2 231 1 需要解析 1s 控制系统
WORD StateWord06;// 状态字06 2 232 1 需要解析 1s 控制系统
WORD StateWord07;// 状态字07 2 233 1 需要解析 1s 控制系统
WORD StateWord08;// 状态字08 2 234 1 需要解析 1s 控制系统
DWORD ActiveStatusCode01;// 故障代码01 4 235 1 需要解析 1s 控制系统 代表目前已经触发的故障代码类似02HH04HL005L
DWORD ActiveStatusCode02;// 故障代码02 4 237 1 需要解析 1s 控制系统 详细解析见故障代码字解析
DWORD ActiveStatusCode03;// 故障代码03 4 239 1 需要解析 1s 控制系统
DWORD ActiveStatusCode04;// 故障代码04 4 241 1 需要解析 1s 控制系统
DWORD ActiveStatusCode05;// 故障代码05 4 243 1 需要解析 1s 控制系统
DWORD ActiveStatusCode06;// 故障代码06 4 245 1 需要解析 1s 控制系统
DWORD ActiveStatusCode07;// 故障代码07 4 247 1 需要解析 1s 控制系统
DWORD ActiveStatusCode08;// 故障代码08 4 249 1 需要解析 1s 控制系统
WORD iFrequency;// 电网频率 2 251 0.01 赫兹 1s 电网
WORD iUL1_690V;// 电网L1相电压 2 252 0.1 伏 1s 电网
WORD iUL2_690V;// 电网L2相电压 2 253 0.1 伏 1s 电网
WORD iUL3_690V;// 电网L3相电压 2 254 0.1 伏 1s 电网
WORD iIL1_690V;// 电网L1相电流 2 255 0.1 安 1s 电网
WORD iIL2_690V;// 电网L2相电流 2 256 0.1 安 1s 电网
WORD iIL3_690V;// 电网L3相电流 2 257 0.1 安 1s 电网
WORD iBlade1MotorCurrent;// 变桨电机1电流 2 258 0.1 安 1s 变桨系统
WORD iBlade2MotorCurrent;// 变桨电机2电流 2 259 0.1 安 1s 变桨系统
WORD iBlade3MotorCurrent;// 变桨电机3电流 2 260 0.1 安 1s 变桨系统
WORD iPitchAngleBk1;// 备用桨叶角度1 2 261 0.01 度 1s 变桨系统
WORD iPitchAngleBk2;// 备用桨叶角度2 2 262 0.01 度 1s 变桨系统
WORD iPitchAngleBk3;// 备用桨叶角度3 2 263 0.01 度 1s 变桨系统
WORD iCosPhi;// 并网点功率因数 2 264 0.001 . 1s 电网
WORD iGearPressA;// 齿轮箱油压A 2 265 0.1 巴 1s 齿轮箱
WORD iGearPressB;// 齿轮箱油压B 2 266 0.1 巴 1s 齿轮箱
WORD iHydrPress;// 液压系统压力 2 267 0.1 巴 1s 液压系统
WORD iNacellePositionLtd;// 机舱绝对方向 2 268 0.1 度 1s 机舱
WORD iCableTwistTotal;// 总扭缆角度 2 269 0.1 度 1s 机舱
WORD iNacellePositionTotal;// 机舱方向 2 270 0.1 度 1s 机舱
WORD iTempOutdoor_1sec;// 环境温度 2 271 0.1 摄氏度 1s 环境
WORD iTempHub_1sec;// 轮毂内温度 2 272 0.1 摄氏度 1s 轮毂
WORD iTempNacelle_1sec;// 机舱内温度 2 273 0.1 摄氏度 1s 机舱
WORD iTempTowerBase_1sec;// 塔基内温度 2 274 0.1 摄氏度 1s 塔基
WORD iTempCabinetNacelle_1sec;// 机舱柜内温度 2 275 0.1 摄氏度 1s 机舱
WORD iTempCabinetTowerBase_1sec;// 塔基柜内温度 2 276 0.1 摄氏度 1s 塔基
WORD iTempTransformer690_400V_1sec;// 400伏变压器温度 2 277 0.1 摄氏度 1s 塔基
WORD iTempMV_1sec;// 箱变温度 2 278 0.1 摄氏度 1s 箱变
WORD iBlade1TempMotor_1sec;// 变桨电机1温度 2 279 0.1 摄氏度 1s 变桨系统
WORD iBlade2TempMotor_1sec;// 变桨电机2温度 2 280 0.1 摄氏度 1s 变桨系统
WORD iBlade3TempMotor_1sec;// 变桨电机3温度 2 281 0.1 摄氏度 1s 变桨系统
WORD iBlade1TempBattBox_1sec;// 变桨电池柜1温度 2 282 0.1 摄氏度 1s 变桨系统
WORD iBlade2TempBattBox_1sec;// 变桨电池柜2温度 2 283 0.1 摄氏度 1s 变桨系统
WORD iBlade3TempBattBox_1sec;// 变桨电池柜3温度 2 284 0.1 摄氏度 1s 变桨系统
WORD iTempCntr_1sec;// 变桨中控箱温度 2 285 0.1 摄氏度 1s 变桨系统
WORD iBlade1TempInvBox_1sec;// 变桨逆变器1温度 2 286 0.1 摄氏度 1s 变桨系统
WORD iBlade2TempInvBox_1sec;// 变桨逆变器2温度 2 287 0.1 摄氏度 1s 变桨系统
WORD iBlade3TempInvBox_1sec;// 变桨逆变器3温度 2 288 0.1 摄氏度 1s 变桨系统
WORD iBlade1TempPMMHeatsink_1sec;// 变桨PMM1散热器温度 2 289 0.1 摄氏度 1s 变桨系统
WORD iBlade2TempPMMHeatsink_1sec;// 变桨PMM2散热器温度 2 290 0.1 摄氏度 1s 变桨系统
WORD iBlade3TempPMMHeatsink_1sec;// 变桨PMM3散热器温度 2 291 0.1 摄氏度 1s 变桨系统
WORD iBlade1TempPMCHeatsink_1sec;// 变桨PMC1散热器温度 2 292 0.1 摄氏度 1s 变桨系统
WORD iBlade2TempPMCHeatsink_1sec;// 变桨PMC2散热器温度 2 293 0.1 摄氏度 1s 变桨系统
WORD iBlade3TempPMCHeatsink_1sec;// 变桨PMC3散热器温度 2 294 0.1 摄氏度 1s 变桨系统
WORD iTempRotorBearA_1sec;// 主轴承A温度 2 295 0.1 摄氏度 1s 传动链
WORD iTempRotorBearB_1sec;// 主轴承B温度 2 296 0.1 摄氏度 1s 传动链
WORD iTemp1GearOil_1sec;// 齿轮箱油温 2 297 0.1 摄氏度 1s 齿轮箱
WORD iTempGearBearDE_1sec;// 齿轮箱驱动齿轴承温度 2 298 0.1 摄氏度 1s 齿轮箱
WORD iTempGearBearNDE_1sec;// 齿轮箱非驱动侧轴承温度 2 299 0.1 摄氏度 1s 发电机
WORD iTempGenBearDE_1sec;// 发电机驱动侧轴承温度 2 300 0.1 摄氏度 1s 发电机
WORD iTempGenBearNDE_1sec;// 发电机非驱动侧轴承温度 2 301 0.1 摄氏度 1s 发电机
WORD iTempGenStatorU_1sec;// 发电机绕组U温度 2 302 0.1 摄氏度 1s 发电机
WORD iTempGenStatorV_1sec;// 发电机绕组V温度 2 303 0.1 摄氏度 1s 发电机
WORD iTempGenStatorW_1sec;// 发电机绕组W温度 2 304 0.1 摄氏度 1s 发电机
WORD iTempGenCoolingAir_1sec;// 发电机冷却风温度 2 305 0.1 摄氏度 1s 发电机
WORD iAvailabillityToday;// 当天可利用率 2 306 0.001 . 1s 控制系统
WORD iAvailabillityTotal;// 总可利用率 2 307 0.001 . 1s 控制系统
DWORD iKWhThisDay;// 当天发电量 2 308 千瓦时 1s 控制系统
DWORD iKWhOverall;// 总发电量 2 310 千瓦时 1s 控制系统
WORD iOperationHoursDay;// 当天发电小时数 2 312 小时 1s 控制系统
DWORD iOperationHoursOverall;// 总发电小时数 2 313 小时 1s 控制系统
WORD iLostKWhThisDay;// 当天损失发电量 2 315 千瓦时 1s 控制系统
DWORD iLostKWhOverall;// 总损失发电量 2 316 千瓦时 1s 控制系统
DWORD FirstTriggeredCode;// 首触故障代码高 4 318 1 1s 控制系统 详细解析见故障代码字解析
WORD SCW001;// 故障代码字01 2 320 1 1s 控制系统
WORD SCW002;// 故障代码字02 2 321 1 1s 控制系统
WORD SCW003;// 故障代码字03 2 322 1 1s 控制系统
WORD SCW004;// 故障代码字04 2 323 1 1s 控制系统
WORD SCW005;// 故障代码字05 2 324 1 1s 控制系统
WORD SCW006;// 故障代码字06 2 325 1 1s 控制系统
WORD SCW007;// 故障代码字07 2 326 1 1s 控制系统
WORD SCW008;// 故障代码字08 2 327 1 1s 控制系统
WORD SCW009;// 故障代码字09 2 328 1 1s 控制系统
WORD SCW010;// 故障代码字10 2 329 1 1s 控制系统
WORD SCW011;// 故障代码字11 2 330 1 1s 控制系统
WORD SCW012;// 故障代码字12 2 331 1 1s 控制系统
WORD SCW013;// 故障代码字13 2 332 1 1s 控制系统
WORD SCW014;// 故障代码字14 2 333 1 1s 控制系统
WORD SCW015;// 故障代码字15 2 334 1 1s 控制系统
WORD SCW016;// 故障代码字16 2 335 1 1s 控制系统
WORD SCW017;// 故障代码字17 2 336 1 1s 控制系统
WORD SCW018;// 故障代码字18 2 337 1 1s 控制系统
WORD SCW019;// 故障代码字19 2 338 1 1s 控制系统
WORD SCW020;// 故障代码字20 2 339 1 1s 控制系统
WORD SCW021;// 故障代码字21 2 340 1 1s 控制系统
WORD SCW022;// 故障代码字22 2 341 1 1s 控制系统
WORD SCW023;// 故障代码字23 2 342 1 1s 控制系统
WORD SCW024;// 故障代码字24 2 343 1 1s 控制系统
WORD SCW025;// 故障代码字25 2 344 1 1s 控制系统
WORD SCW026;// 故障代码字26 2 345 1 1s 控制系统
WORD SCW027;// 故障代码字27 2 346 1 1s 控制系统
WORD SCW028;// 故障代码字28 2 347 1 1s 控制系统
WORD SCW029;// 故障代码字29 2 348 1 1s 控制系统
WORD SCW030;// 故障代码字30 2 349 1 1s 控制系统
WORD SCW031;// 故障代码字31 2 350 1 1s 控制系统
WORD SCW032;// 故障代码字32 2 351 1 1s 控制系统
WORD SCW033;// 故障代码字33 2 352 1 1s 控制系统
WORD SCW034;// 故障代码字34 2 353 1 1s 控制系统
WORD SCW035;// 故障代码字35 2 354 1 1s 控制系统
WORD SCW036;// 故障代码字36 2 355 1 1s 控制系统
WORD SCW037;// 故障代码字37 2 356 1 1s 控制系统
WORD SCW038;// 故障代码字38 2 357 1 1s 控制系统
WORD SCW039;// 故障代码字39 2 358 1 1s 控制系统
WORD SCW040;// 故障代码字40 2 359 1 1s 控制系统
WORD SCW041;// 故障代码字41 2 360 1 1s 控制系统
WORD SCW042;// 故障代码字42 2 361 1 1s 控制系统
WORD iGenSpeed_10sec;// 发电机转速10秒均值 2 362
WORD iGenSpeed_30sec;// 发电机转速30秒均值 2 363
WORD iGenPower_10sec;// 机组有功10秒均值 2 364
WORD iGenPower_30sec;// 机组有功30秒均值 2 365
WORD iWindSpeed_10sec;// 风速10秒均值 2 366
WORD iWindSpeed_30sec;// 风速30秒均值 2 367
WORD iAvailablePower;// 可用有功功率 2 368
QLONG localtime;// PLC本地时间 8 none 0.0001 毫秒 little endian 系统
WORD iGenSpeed;//发电机转速 2 200 0.1 转/分 40ms 控制系统
WORD iGenPower;//机组有功功率 2 201 0.1 千瓦 40ms 控制系统
WORD iWindSpeed;//风速 2 202 0.01 米/秒 40ms 气象
WORD iVibrationY;//机舱振动前后方向 2 203 0.001 米/秒^2 40ms 机舱
WORD iVibrationZ;//机舱振动左右方向 2 204 0.001 米/秒^2 40ms 机舱
WORD iTurbineOperationMode;//运行模式 2 205 1 需要解析 1s 控制系统
WORD iBPLevel;//刹车等级 2 206 1 需要解析 1s 控制系统
WORD iYPLevel;//偏航运行模式 2 207 1 需要解析 1s 控制系统
WORD iWindSpeed_1sec;//风速1秒均值 2 208 0.01 米/秒 1s 气象
WORD iGenSpeed_1sec;//发电机转速1秒均值 2 209 0.1 转/分 1s 控制系统
WORD iGenPower_1sec;//机组有功1秒均值 2 210 0.1 千瓦 1s 控制系统
WORD iGenToruqe;//发电机扭矩1秒均值 2 211 0.1 牛米 1s 控制系统
WORD iRotorSpeed;//风轮转速 2 212 0.1 转/分 1s 控制系统
WORD iTheoreticalPower;//理论有功功率 2 213 0.1 千瓦 1s 控制系统
WORD iReactivePower;//无功功率 2 214 0.1 千乏 1s 控制系统
WORD iActivePowerSetPointValue;//有功设定值 2 215 0.1 千瓦 1s 控制系统
WORD iReactivePowerSetPointValue;//无功设定值 2 216 0.1 千乏 1s 控制系统
WORD iSetValueGenSpeed;//发电机转速设定值 2 217 0.1 转/分 1s 控制系统
WORD iSetValuePitchAngle;//桨叶角度设定值 2 218 0.01 度 1s 控制系统
WORD iPitchAngle1RefValue;//桨叶1角度给定 2 219 0.01 度 1s 控制系统
WORD iPitchAngle2RefValue;//桨叶2角度给定 2 220 0.01 度 1s 控制系统
WORD iPitchAngle3RefValue;//桨叶3角度给定 2 221 0.01 度 1s 控制系统
WORD iPitchAngle1;//桨叶1角度 2 222 0.01 度 1s 变桨系统
WORD iPitchAngle2;//桨叶2角度 2 223 0.01 度 1s 变桨系统
WORD iPitchAngle3;//桨叶3角度 2 224 0.01 度 1s 变桨系统
WORD iVaneDirection;//机舱方向 2 225 0.1 度 1s 气象
WORD iWindDirection;//风向(与机舱夹角) 2 226 0.1 度 1s 气象
WORD StateWord01;//状态字01 2 227 1 需要解析 1s 控制系统
WORD StateWord02;//状态字02 2 228 1 需要解析 1s 控制系统
WORD StateWord03;//状态字03 2 229 1 需要解析 1s 控制系统
WORD StateWord04;//状态字04 2 230 1 需要解析 1s 控制系统
WORD StateWord05;//状态字05 2 231 1 需要解析 1s 控制系统
WORD StateWord06;//状态字06 2 232 1 需要解析 1s 控制系统
WORD StateWord07;//状态字07 2 233 1 需要解析 1s 控制系统
WORD StateWord08;//状态字08 2 234 1 需要解析 1s 控制系统
DWORD ActiveStatusCode01;//故障代码01 4 235 1 需要解析 1s 控制系统
DWORD ActiveStatusCode02;//故障代码02 4 237 1 需要解析 1s 控制系统
DWORD ActiveStatusCode03;//故障代码03 4 239 1 需要解析 1s 控制系统
DWORD ActiveStatusCode04;//故障代码04 4 241 1 需要解析 1s 控制系统
DWORD ActiveStatusCode05;//故障代码05 4 243 1 需要解析 1s 控制系统
DWORD ActiveStatusCode06;//故障代码06 4 245 1 需要解析 1s 控制系统
DWORD ActiveStatusCode07;//故障代码07 4 247 1 需要解析 1s 控制系统
DWORD ActiveStatusCode08;//故障代码08 4 249 1 需要解析 1s 控制系统
WORD iFrequency;//电网频率 2 251 0.01 赫兹 1s 电网
WORD iUL1_690V;//电网L1相电压 2 252 0.1 伏 1s 电网
WORD iUL2_690V;//电网L2相电压 2 253 0.1 伏 1s 电网
WORD iUL3_690V;//电网L3相电压 2 254 0.1 伏 1s 电网
WORD iIL1_690V;//电网L1相电流 2 255 0.1 安 1s 电网
WORD iIL2_690V;//电网L2相电流 2 256 0.1 安 1s 电网
WORD iIL3_690V;//电网L3相电流 2 257 0.1 安 1s 电网
WORD iBlade1MotorCurrent;//变桨电机1电流 2 258 0.1 安 1s 变桨系统
WORD iBlade2MotorCurrent;//变桨电机2电流 2 259 0.1 安 1s 变桨系统
WORD iBlade3MotorCurrent;//变桨电机3电流 2 260 0.1 安 1s 变桨系统
WORD iPitchAngleBk1;//备用桨叶角度1 2 261 0.01 度 1s 变桨系统
WORD iPitchAngleBk2;//备用桨叶角度2 2 262 0.01 度 1s 变桨系统
WORD iPitchAngleBk3;//备用桨叶角度3 2 263 0.01 度 1s 变桨系统
WORD iCosPhi;//并网点功率因数 2 264 0.001 . 1s 电网
WORD iGearPressA;//齿轮箱油压A 2 265 0.1 巴 1s 齿轮箱
WORD iGearPressB;//齿轮箱油压B 2 266 0.1 巴 1s 齿轮箱
WORD iHydrPress;//液压系统压力 2 267 0.1 巴 1s 液压系统
WORD iNacellePositionLtd;//机舱绝对方向 2 268 0.1 度 1s 机舱
WORD iCableTwistTotal;//总扭缆角度 2 269 0.1 度 1s 机舱
WORD iNacellePositionTotal;//机舱方向 2 270 0.1 度 1s 机舱
WORD iTempOutdoor_1sec;//环境温度 2 271 0.1 摄氏度 1s 环境
WORD iTempHub_1sec;//轮毂内温度 2 272 0.1 摄氏度 1s 轮毂
WORD iTempNacelle_1sec;//机舱内温度 2 273 0.1 摄氏度 1s 机舱
WORD iTempTowerBase_1sec;//塔基内温度 2 274 0.1 摄氏度 1s 塔基
WORD iTempCabinetNacelle_1sec;//机舱柜内温度 2 275 0.1 摄氏度 1s 机舱
WORD iTempCabinetTowerBase_1sec;//塔基柜内温度 2 276 0.1 摄氏度 1s 塔基
WORD iTempTransformer690_400V_1sec;//400伏变压器温度 2 277 0.1 摄氏度 1s 塔基
WORD iTempMV_1sec;//箱变温度 2 278 0.1 摄氏度 1s 箱变
WORD iBlade1TempMotor_1sec;//变桨电机1温度 2 279 0.1 摄氏度 1s 变桨系统
WORD iBlade2TempMotor_1sec;//变桨电机2温度 2 280 0.1 摄氏度 1s 变桨系统
WORD iBlade3TempMotor_1sec;//变桨电机3温度 2 281 0.1 摄氏度 1s 变桨系统
WORD iBlade1TempBattBox_1sec;//变桨电池柜1温度 2 282 0.1 摄氏度 1s 变桨系统
WORD iBlade2TempBattBox_1sec;//变桨电池柜2温度 2 283 0.1 摄氏度 1s 变桨系统
WORD iBlade3TempBattBox_1sec;//变桨电池柜3温度 2 284 0.1 摄氏度 1s 变桨系统
WORD iTempCntr_1sec;//变桨中控箱温度 2 285 0.1 摄氏度 1s 变桨系统
WORD iBlade1TempInvBox_1sec;//变桨逆变器1温度 2 286 0.1 摄氏度 1s 变桨系统
WORD iBlade2TempInvBox_1sec;//变桨逆变器2温度 2 287 0.1 摄氏度 1s 变桨系统
WORD iBlade3TempInvBox_1sec;//变桨逆变器3温度 2 288 0.1 摄氏度 1s 变桨系统
WORD iBlade1TempPMMHeatsink_1sec;//变桨PMM1散热器温度 2 289 0.1 摄氏度 1s 变桨系统
WORD iBlade2TempPMMHeatsink_1sec;//变桨PMM2散热器温度 2 290 0.1 摄氏度 1s 变桨系统
WORD iBlade3TempPMMHeatsink_1sec;//变桨PMM3散热器温度 2 291 0.1 摄氏度 1s 变桨系统
WORD iBlade1TempPMCHeatsink_1sec;//变桨PMC1散热器温度 2 292 0.1 摄氏度 1s 变桨系统
WORD iBlade2TempPMCHeatsink_1sec;//变桨PMC2散热器温度 2 293 0.1 摄氏度 1s 变桨系统
WORD iBlade3TempPMCHeatsink_1sec;//变桨PMC3散热器温度 2 294 0.1 摄氏度 1s 变桨系统
WORD iTempRotorBearA_1sec;//主轴承A温度 2 295 0.1 摄氏度 1s 传动链
WORD iTempRotorBearB_1sec;//主轴承B温度 2 296 0.1 摄氏度 1s 传动链
WORD iTemp1GearOil_1sec;//齿轮箱油温 2 297 0.1 摄氏度 1s 齿轮箱
WORD iTempGearBearDE_1sec;//齿轮箱驱动齿轴承温度 2 298 0.1 摄氏度 1s 齿轮箱
WORD iTempGearBearNDE_1sec;//齿轮箱非驱动侧轴承温度 2 299 0.1 摄氏度 1s 发电机
WORD iTempGenBearDE_1sec;//发电机驱动侧轴承温度 2 300 0.1 摄氏度 1s 发电机
WORD iTempGenBearNDE_1sec;//发电机非驱动侧轴承温度 2 301 0.1 摄氏度 1s 发电机
WORD iTempGenStatorU_1sec;//发电机绕组U温度 2 302 0.1 摄氏度 1s 发电机
WORD iTempGenStatorV_1sec;//发电机绕组V温度 2 303 0.1 摄氏度 1s 发电机
WORD iTempGenStatorW_1sec;//发电机绕组W温度 2 304 0.1 摄氏度 1s 发电机
WORD iTempGenCoolingAir_1sec;//发电机冷却风温度 2 305 0.1 摄氏度 1s 发电机
WORD iAvailabillityToday;//当天可利用率 2 306 0.001 . 1s 控制系统
WORD iAvailabillityTotal;//总可利用率 2 307 0.001 . 1s 控制系统
DWORD iKWhThisDay;//当天发电量 4 308 千瓦时 1s 控制系统
DWORD iKWhOverall;//总发电量 4 310 千瓦时 1s 控制系统
DWORD iOperationHoursDay;//当天发电小时数 4 312 小时 1s 控制系统
DWORD iOperationHoursOverall;//总发电小时数 4 314 小时 1s 控制系统
DWORD iLostKWhThisDay;//当天损失发电量 4 316 千瓦时 1s 控制系统
DWORD iLostKWhOverall;//总损失发电量 4 318 千瓦时 1s 控制系统
WORD SCW001;//故障代码字01 2 320 1 1s 控制系统
WORD SCW002;//故障代码字02 2 321 1 1s 控制系统
WORD SCW003;//故障代码字03 2 322 1 1s 控制系统
WORD SCW004;//故障代码字04 2 323 1 1s 控制系统
WORD SCW005;//故障代码字05 2 324 1 1s 控制系统
WORD SCW006;//故障代码字06 2 325 1 1s 控制系统
WORD SCW007;//故障代码字07 2 326 1 1s 控制系统
WORD SCW008;//故障代码字08 2 327 1 1s 控制系统
WORD SCW009;//故障代码字09 2 328 1 1s 控制系统
WORD SCW010;//故障代码字10 2 329 1 1s 控制系统
WORD SCW011;//故障代码字11 2 330 1 1s 控制系统
WORD SCW012;//故障代码字12 2 331 1 1s 控制系统
WORD SCW013;//故障代码字13 2 332 1 1s 控制系统
WORD SCW014;//故障代码字14 2 333 1 1s 控制系统
WORD SCW015;//故障代码字15 2 334 1 1s 控制系统
WORD SCW016;//故障代码字16 2 335 1 1s 控制系统
WORD SCW017;//故障代码字17 2 336 1 1s 控制系统
WORD SCW018;//故障代码字18 2 337 1 1s 控制系统
WORD SCW019;//故障代码字19 2 338 1 1s 控制系统
WORD SCW020;//故障代码字20 2 339 1 1s 控制系统
WORD SCW021;//故障代码字21 2 340 1 1s 控制系统
WORD SCW022;//故障代码字22 2 341 1 1s 控制系统
WORD SCW023;//故障代码字23 2 342 1 1s 控制系统
WORD SCW024;//故障代码字24 2 343 1 1s 控制系统
WORD SCW025;//故障代码字25 2 344 1 1s 控制系统
WORD SCW026;//故障代码字26 2 345 1 1s 控制系统
WORD SCW027;//故障代码字27 2 346 1 1s 控制系统
WORD SCW028;//故障代码字28 2 347 1 1s 控制系统
WORD SCW029;//故障代码字29 2 348 1 1s 控制系统
WORD SCW030;//故障代码字30 2 349 1 1s 控制系统
WORD SCW031;//故障代码字31 2 350 1 1s 控制系统
WORD SCW032;//故障代码字32 2 351 1 1s 控制系统
WORD SCW033;//故障代码字33 2 352 1 1s 控制系统
WORD SCW034;//故障代码字34 2 353 1 1s 控制系统
WORD SCW035;//故障代码字35 2 354 1 1s 控制系统
WORD SCW036;//故障代码字36 2 355 1 1s 控制系统
WORD SCW037;//故障代码字37 2 356 1 1s 控制系统
WORD SCW038;//故障代码字38 2 357 1 1s 控制系统
WORD SCW039;//故障代码字39 2 358 1 1s 控制系统
WORD SCW040;//故障代码字40 2 359 1 1s 控制系统
WORD SCW041;//故障代码字41 2 360 1 1s 控制系统
WORD SCW042;//故障代码字42 2 361 1 1s 控制系统
WORD SCW043;//故障代码字43 2 362 1 1s 控制系统
WORD SCW044;//故障代码字44 2 363 1 1s 控制系统
WORD SCW045;//故障代码字45 2 364 1 1s 控制系统
WORD SCW046;//故障代码字46 2 365 1 1s 控制系统
WORD SCW047;//故障代码字47 2 366 1 1s 控制系统
WORD SCW048;//故障代码字48 2 367 1 1s 控制系统
WORD SCW049;//故障代码字49 2 368 1 1s 控制系统
WORD SCW050;//故障代码字50 2 369 1 1s 控制系统
WORD iGenSpeed_10sec;//发电机转速10秒均值 2 370 0.1 转/分 1s 控制系统
WORD iGenSpeed_30sec;//发电机转速30秒均值 2 371 0.1 转/分 1s 控制系统
WORD iGenPower_10sec;//机组有功10秒均值 2 372 0.1 千瓦 1s 控制系统
WORD iGenPower_30sec;//机组有功30秒均值 2 373 0.1 千瓦 1s 控制系统
WORD iWindSpeed_10sec;//风速10秒均值 2 374 0.01 米/秒 1s 气象
WORD iWindSpeed_30sec;//风速30秒均值 2 375 0.01 米/秒 1s 气象
WORD iWindSpeed_10min;//风速10分钟均值 2 376 0.01 米/秒 1s 气象
WORD iAvailablePower;//可用有功功率 2 377 0.1 千瓦 1s 控制系统
DWORD FirstTriggeredCode;//首触故障代码 4 378 1 1s 控制系统
DWORD FaultInformation;//故障信息 4 380 1 1s 控制系统
DWORD WecRunCondition;//机组运行状态机状态 4 382 1 1s 控制系统
WORD iWindSpeedIEC;//标准化风速 2 384 0.01 米/秒 1s 控制系统
WORD iWindSpeedIEC_30sec;//标准化风速30秒均值 2 385 0.01 米/秒 1s 控制系统
WORD iWindSpeedIEC_10min;//标准化风速10分钟均值 2 386 0.01 米/秒 1s 控制系统
WORD iYawPress;//偏航系统压力 2 387 0.1 巴 1s 液压系统
WORD iStandardAirDensity;//标准空气密度 2 388 0.001 千克/米^3 1s 气象
WORD iAirDensity;//实时空气密度 2 389 0.001 1s 气象
WORD iVibrationYFiltered;//机舱振动前后方向滤波值 2 390 0.001 米/秒^2 1s 机舱
WORD iVibrationZFiltered;//机舱振动左右方向滤波值 2 391 0.001 米/秒^2 1s 机舱
WORD iTempGearWaterCool_1sec;//齿轮箱水冷温度 2 392 0.1 摄氏度 1s 齿轮箱
WORD PowerLimitSource;//限功率原因 2 393 1 1s 控制系统
WORD iTempOutdoor_10min;//环境温度十分钟均值 2 394 0.1 摄氏度 1s 环境
} struRYDeviceData;
#pragma pack()

View File

@ -40,8 +40,13 @@ typedef int SOCKET;
#include <vector>
#include <sys/stat.h>
#include "zlog/zlog.h"
#if 1
//#include "easywsclient.hpp"
//using easywsclient::WebSocket;
#else
#include <nopoll.h>
#include <nopoll_decl.h>
#endif
#define MEMERY_1M 65536 //设置位64K
#define DELAY_RUN 5000
@ -1342,7 +1347,13 @@ extern struNodeOption nodes;
extern char configpath[MAX_PATH]; //配置文件所在目录
extern char configfile[MAX_PATH]; //配置文件
#if 1
//extern WebSocket::pointer g_conn;
class CRYDevice;
extern CRYDevice* g_conn;
#else
extern noPollConn *g_conn;
#endif
typedef struct
{
//网络配置信息

View File

@ -0,0 +1,95 @@
#ifndef _CLIENT_
#define _CLIENT_
#include <iostream>
#include <fstream>
#include <stack>
#include <queue>
#include <signal.h>
//#include <pthread.h>
#include <string>
#include <libwebsockets.h>
#include "zjdtypes.h"
using namespace std;
#define MAX_PAYLOAD_SIZE 20 * 1024
typedef enum
{
CLIENT_IDLE,
CLIENT_CONNECTING,
CLIENT_CONNECTED,
CLIENT_AWAITING_SEND,
ClIENT_COMPLETE_RECV,
CLIENT_CLOSED
} TSTAT;
typedef struct session_data {
int msg_count;
unsigned char buf[LWS_PRE + MAX_PAYLOAD_SIZE];
int len;
} session_data, *SESSIONDATA;
class CWSClient
{
public:
CWSClient(string url);
CWSClient(void);
~CWSClient();
void init();
void init(std::string url);
int set_ssl(const char* ca_filepath, const char* server_cert_filepath, const char*server_private_key_filepath, int ssl_conn);
bool create();
bool connect(int ssl_conn);
bool reconnect(void);
bool run(int wait_time);
int send(string data);
int recv(std::string data);
int recvMsg(void);
int recvFrame(std::string);
int getRecvSize();
string getRecvMsg();
void popRecvMsg();
#if 0
void setLogLevel(int level);
#endif
TSTAT getConnStat();
void destroy();
void setEnd(bool flag);
DWORD getConnectTime(void) { return m_reconnect_attempts; }
void setConnectTime(DWORD tm) { m_reconnect_attempts = tm; }
friend void* WSpthreadFunc(void* arg);
friend int callback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len);
private:
string m_cacheFile;
bool m_end;
int m_waittime;
pthread_t m_threadID;
queue<string> m_sendMsgQueue;
queue<string> m_recvMsgQueue;
queue<string> m_recvFrameQueue;
SESSIONDATA m_session_data;
string m_url;
const char* m_prot;
const char* m_ads;
const char* m_path;
int m_port;
TSTAT m_stat;
int m_logLevel;
DWORD m_reconnect_attempts;
struct lws_protocols * m_protocols;
struct lws_context_creation_info m_ctx_info; /* 用于创建vhost或者context的参数 */
struct lws_context * m_context;
struct lws_client_connect_info m_conn_info;
struct lws * m_wsi;
pthread_mutex_t m_rmutex;
pthread_mutex_t m_smutex;
};
#endif

View File

@ -0,0 +1,73 @@
#ifndef EASYWSCLIENT_HPP_20170819_MIOFVASDTNUASZDQPLFD
#define EASYWSCLIENT_HPP_20170819_MIOFVASDTNUASZDQPLFD
// This code comes from:
// https://github.com/dhbaird/easywsclient
//
// To get the latest version:
// wget https://raw.github.com/dhbaird/easywsclient/master/easywsclient.hpp
// wget https://raw.github.com/dhbaird/easywsclient/master/easywsclient.cpp
#include <string>
#include <vector>
#include <cstdint>
namespace easywsclient {
struct Callback_Imp { virtual void operator()(const std::string& message) = 0; };
struct BytesCallback_Imp { virtual void operator()(const std::vector<uint8_t>& message) = 0; };
class WebSocket {
public:
typedef WebSocket * pointer;
typedef enum readyStateValues { CLOSING, CLOSED, CONNECTING, OPEN } readyStateValues;
// Factories:
static pointer create_dummy();
static pointer from_url(const std::string& url, const std::string& origin = std::string());
static pointer from_url_no_mask(const std::string& url, const std::string& origin = std::string());
// Interfaces:
virtual ~WebSocket() { }
virtual void poll(int timeout = 0) = 0; // timeout in milliseconds
virtual void send(const std::string& message) = 0;
virtual void sendBinary(const std::string& message) = 0;
virtual void sendBinary(const std::vector<uint8_t>& message) = 0;
virtual void sendPing() = 0;
virtual void close() = 0;
virtual readyStateValues getReadyState() const = 0;
template<class Callable>
void dispatch(Callable callable)
// For callbacks that accept a string argument.
{ // N.B. this is compatible with both C++11 lambdas, functors and C function pointers
struct _Callback : public Callback_Imp {
Callable& callable;
_Callback(Callable& callable) : callable(callable) { }
void operator()(const std::string& message) { callable(message); }
};
_Callback callback(callable);
_dispatch(callback);
}
template<class Callable>
void dispatchBinary(Callable callable)
// For callbacks that accept a std::vector<uint8_t> argument.
{ // N.B. this is compatible with both C++11 lambdas, functors and C function pointers
struct _Callback : public BytesCallback_Imp {
Callable& callable;
_Callback(Callable& callable) : callable(callable) { }
void operator()(const std::vector<uint8_t>& message) { callable(message); }
};
_Callback callback(callable);
_dispatchBinary(callback);
}
protected:
virtual void _dispatch(Callback_Imp& callable) = 0;
virtual void _dispatchBinary(BytesCallback_Imp& callable) = 0;
};
} // namespace easywsclient
#endif /* EASYWSCLIENT_HPP_20120819_MIOFVASDTNUASZDQPLFD */

View File

@ -3383,7 +3383,7 @@ noPollMsg * nopoll_conn_get_msg (noPollConn * conn)
msg->payload_size = nopoll_get_16bit (buffer + 2);
nopoll_log (conn->ctx, NOPOLL_LEVEL_DEBUG, "Received (%d) bytes in header (size %d) for payload size indication, which finally is: %d", bytes, header_size,(int) msg->payload_size);
fprintf(stderr, "Received (%d) bytes in header (size %d) for payload size indication, which finally is: %d\n", bytes, header_size,(int) msg->payload_size);
//fprintf(stderr, "Received (%d) bytes in header (size %d) for payload size indication, which finally is: %d\n", bytes, header_size,(int) msg->payload_size);
} else if (msg->payload_size == 127) {
/* read more content (next 8 bytes) */
@ -3479,8 +3479,7 @@ noPollMsg * nopoll_conn_get_msg (noPollConn * conn)
nopoll_log (conn->ctx, NOPOLL_LEVEL_DEBUG, "Detected incoming websocket frame: fin(%d), op_code(%d), is_masked(%d), payload size(%ld), mask=%d",
msg->has_fin, msg->op_code, msg->is_masked, msg->payload_size, nopoll_get_32bit (msg->mask));
fprintf(stderr, "Detected incoming websocket frame: fin(%d), op_code(%d), is_masked(%d), payload size(%ld), mask=%d\n",
msg->has_fin, msg->op_code, msg->is_masked, msg->payload_size, nopoll_get_32bit (msg->mask));
//fprintf(stderr, "Detected incoming websocket frame: fin(%d), op_code(%d), is_masked(%d), payload size(%ld), mask=%d\n", msg->has_fin, msg->op_code, msg->is_masked, msg->payload_size, nopoll_get_32bit (msg->mask));
/* check payload size */
if (msg->payload_size == 0) {

View File

@ -0,0 +1,527 @@
#ifdef _WIN32
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS // _CRT_SECURE_NO_WARNINGS for sscanf errors in MSVC2013 Express
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <fcntl.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#pragma comment( lib, "ws2_32" )
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <io.h>
#ifndef _SSIZE_T_DEFINED
typedef int ssize_t;
#define _SSIZE_T_DEFINED
#endif
#ifndef _SOCKET_T_DEFINED
typedef SOCKET socket_t;
#define _SOCKET_T_DEFINED
#endif
#ifndef snprintf
#define snprintf _snprintf_s
#endif
#if _MSC_VER >=1600
// vs2010 or later
#include <stdint.h>
#else
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#endif
#define socketerrno WSAGetLastError()
#define SOCKET_EAGAIN_EINPROGRESS WSAEINPROGRESS
#define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
#else
#include <fcntl.h>
#include <netdb.h>
#include <netinet/tcp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdint.h>
#ifndef _SOCKET_T_DEFINED
typedef int socket_t;
#define _SOCKET_T_DEFINED
#endif
#ifndef INVALID_SOCKET
#define INVALID_SOCKET (-1)
#endif
#ifndef SOCKET_ERROR
#define SOCKET_ERROR (-1)
#endif
#define closesocket(s) ::close(s)
#include <errno.h>
#define socketerrno errno
#define SOCKET_EAGAIN_EINPROGRESS EAGAIN
#define SOCKET_EWOULDBLOCK EWOULDBLOCK
#endif
#include <vector>
#include <string>
#include "easywsclient.hpp"
#include "public.h"
using easywsclient::Callback_Imp;
using easywsclient::BytesCallback_Imp;
namespace { // private module-only namespace
socket_t hostname_connect(const std::string& hostname, int port) {
struct addrinfo hints;
struct addrinfo *result;
struct addrinfo *p;
int ret;
socket_t sockfd = INVALID_SOCKET;
char sport[16];
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
snprintf(sport, 16, "%d", port);
if ((ret = getaddrinfo(hostname.c_str(), sport, &hints, &result)) != 0)
{
vLog(LOG_ERROR, "getaddrinfo: %s\n", gai_strerror(ret));
return 1;
}
for(p = result; p != NULL; p = p->ai_next)
{
sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sockfd == INVALID_SOCKET) { continue; }
if (connect(sockfd, p->ai_addr, p->ai_addrlen) != SOCKET_ERROR) {
break;
}
closesocket(sockfd);
sockfd = INVALID_SOCKET;
}
freeaddrinfo(result);
return sockfd;
}
class _DummyWebSocket : public easywsclient::WebSocket
{
public:
void poll(int timeout) { }
void send(const std::string& message) { }
void sendBinary(const std::string& message) { }
void sendBinary(const std::vector<uint8_t>& message) { }
void sendPing() { }
void close() { }
readyStateValues getReadyState() const { return CLOSED; }
void _dispatch(Callback_Imp & callable) { }
void _dispatchBinary(BytesCallback_Imp& callable) { }
};
class _RealWebSocket : public easywsclient::WebSocket
{
public:
// http://tools.ietf.org/html/rfc6455#section-5.2 Base Framing Protocol
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-------+-+-------------+-------------------------------+
// |F|R|R|R| opcode|M| Payload len | Extended payload length |
// |I|S|S|S| (4) |A| (7) | (16/64) |
// |N|V|V|V| |S| | (if payload len==126/127) |
// | |1|2|3| |K| | |
// +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
// | Extended payload length continued, if payload len == 127 |
// + - - - - - - - - - - - - - - - +-------------------------------+
// | |Masking-key, if MASK set to 1 |
// +-------------------------------+-------------------------------+
// | Masking-key (continued) | Payload Data |
// +-------------------------------- - - - - - - - - - - - - - - - +
// : Payload Data continued ... :
// + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
// | Payload Data continued ... |
// +---------------------------------------------------------------+
struct wsheader_type {
unsigned header_size;
bool fin;
bool mask;
enum opcode_type {
CONTINUATION = 0x0,
TEXT_FRAME = 0x1,
BINARY_FRAME = 0x2,
CLOSE = 8,
PING = 9,
PONG = 0xa,
} opcode;
int N0;
uint64_t N;
uint8_t masking_key[4];
};
std::vector<uint8_t> rxbuf;
std::vector<uint8_t> txbuf;
std::vector<uint8_t> receivedData;
socket_t sockfd;
readyStateValues readyState;
bool useMask;
_RealWebSocket(socket_t sockfd, bool useMask) : sockfd(sockfd), readyState(OPEN), useMask(useMask) {
}
readyStateValues getReadyState() const {
return readyState;
}
void poll(int timeout) { // timeout in milliseconds
if (readyState == CLOSED) {
if (timeout > 0) {
timeval tv = { timeout/1000, (timeout%1000) * 1000 };
select(0, NULL, NULL, NULL, &tv);
}
return;
}
if (timeout != 0) {
fd_set rfds;
fd_set wfds;
timeval tv = { timeout/1000, (timeout%1000) * 1000 };
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_SET(sockfd, &rfds);
if (txbuf.size()) { FD_SET(sockfd, &wfds); }
select(sockfd + 1, &rfds, &wfds, 0, timeout > 0 ? &tv : 0);
}
while (true) {
// FD_ISSET(0, &rfds) will be true
int N = rxbuf.size();
ssize_t ret;
rxbuf.resize(N + 1500);
ret = recv(sockfd, (char*)&rxbuf[0] + N, 1500, 0);
if (false) { }
else if (ret < 0 && (socketerrno == SOCKET_EWOULDBLOCK || socketerrno == SOCKET_EAGAIN_EINPROGRESS)) {
rxbuf.resize(N);
break;
}
else if (ret <= 0) {
rxbuf.resize(N);
closesocket(sockfd);
readyState = CLOSED;
fputs(ret < 0 ? "Connection error!\n" : "Connection closed!\n", stderr);
break;
}
else {
rxbuf.resize(N + ret);
}
}
while (txbuf.size()) {
int ret = ::send(sockfd, (char*)&txbuf[0], txbuf.size(), 0);
if (false) { } // ??
else if (ret < 0 && (socketerrno == SOCKET_EWOULDBLOCK || socketerrno == SOCKET_EAGAIN_EINPROGRESS)) {
break;
}
else if (ret <= 0) {
closesocket(sockfd);
readyState = CLOSED;
fputs(ret < 0 ? "Connection error!\n" : "Connection closed!\n", stderr);
break;
}
else {
txbuf.erase(txbuf.begin(), txbuf.begin() + ret);
}
}
if (!txbuf.size() && readyState == CLOSING) {
closesocket(sockfd);
readyState = CLOSED;
}
}
// Callable must have signature: void(const std::string & message).
// Should work with C functions, C++ functors, and C++11 std::function and
// lambda:
//template<class Callable>
//void dispatch(Callable callable)
virtual void _dispatch(Callback_Imp & callable) {
struct CallbackAdapter : public BytesCallback_Imp
// Adapt void(const std::string<uint8_t>&) to void(const std::string&)
{
Callback_Imp& callable;
CallbackAdapter(Callback_Imp& callable) : callable(callable) { }
void operator()(const std::vector<uint8_t>& message) {
std::string stringMessage(message.begin(), message.end());
callable(stringMessage);
}
};
CallbackAdapter bytesCallback(callable);
_dispatchBinary(bytesCallback);
}
virtual void _dispatchBinary(BytesCallback_Imp & callable) {
// TODO: consider acquiring a lock on rxbuf...
while (true) {
wsheader_type ws;
if (rxbuf.size() < 2) { return; /* Need at least 2 */ }
const uint8_t * data = (uint8_t *) &rxbuf[0]; // peek, but don't consume
ws.fin = (data[0] & 0x80) == 0x80;
ws.opcode = (wsheader_type::opcode_type) (data[0] & 0x0f);
ws.mask = (data[1] & 0x80) == 0x80;
ws.N0 = (data[1] & 0x7f);
ws.header_size = 2 + (ws.N0 == 126? 2 : 0) + (ws.N0 == 127? 8 : 0) + (ws.mask? 4 : 0);
if (rxbuf.size() < ws.header_size) { return; /* Need: ws.header_size - rxbuf.size() */ }
int i = 0;
if (ws.N0 < 126) {
ws.N = ws.N0;
i = 2;
}
else if (ws.N0 == 126) {
ws.N = 0;
ws.N |= ((uint64_t) data[2]) << 8;
ws.N |= ((uint64_t) data[3]) << 0;
i = 4;
}
else if (ws.N0 == 127) {
ws.N = 0;
ws.N |= ((uint64_t) data[2]) << 56;
ws.N |= ((uint64_t) data[3]) << 48;
ws.N |= ((uint64_t) data[4]) << 40;
ws.N |= ((uint64_t) data[5]) << 32;
ws.N |= ((uint64_t) data[6]) << 24;
ws.N |= ((uint64_t) data[7]) << 16;
ws.N |= ((uint64_t) data[8]) << 8;
ws.N |= ((uint64_t) data[9]) << 0;
i = 10;
}
if (ws.mask) {
ws.masking_key[0] = ((uint8_t) data[i+0]) << 0;
ws.masking_key[1] = ((uint8_t) data[i+1]) << 0;
ws.masking_key[2] = ((uint8_t) data[i+2]) << 0;
ws.masking_key[3] = ((uint8_t) data[i+3]) << 0;
}
else {
ws.masking_key[0] = 0;
ws.masking_key[1] = 0;
ws.masking_key[2] = 0;
ws.masking_key[3] = 0;
}
if (rxbuf.size() < ws.header_size+ws.N) { return; /* Need: ws.header_size+ws.N - rxbuf.size() */ }
// We got a whole message, now do something with it:
if (false) { }
else if (
ws.opcode == wsheader_type::TEXT_FRAME
|| ws.opcode == wsheader_type::BINARY_FRAME
|| ws.opcode == wsheader_type::CONTINUATION
) {
if (ws.mask) { for (size_t i = 0; i != ws.N; ++i) { rxbuf[i+ws.header_size] ^= ws.masking_key[i&0x3]; } }
receivedData.insert(receivedData.end(), rxbuf.begin()+ws.header_size, rxbuf.begin()+ws.header_size+(size_t)ws.N);// just feed
if (ws.fin) {
callable((const std::vector<uint8_t>) receivedData);
receivedData.erase(receivedData.begin(), receivedData.end());
std::vector<uint8_t> ().swap(receivedData);// free memory
}
}
else if (ws.opcode == wsheader_type::PING) {
if (ws.mask) { for (size_t i = 0; i != ws.N; ++i) { rxbuf[i+ws.header_size] ^= ws.masking_key[i&0x3]; } }
std::string data(rxbuf.begin()+ws.header_size, rxbuf.begin()+ws.header_size+(size_t)ws.N);
sendData(wsheader_type::PONG, data.size(), data.begin(), data.end());
}
else if (ws.opcode == wsheader_type::PONG) { }
else if (ws.opcode == wsheader_type::CLOSE) { close(); }
else { vLog(LOG_ERROR, "ERROR: Got unexpected WebSocket message.\n"); close(); }
rxbuf.erase(rxbuf.begin(), rxbuf.begin() + ws.header_size+(size_t)ws.N);
}
}
void sendPing() {
std::string empty;
sendData(wsheader_type::PING, empty.size(), empty.begin(), empty.end());
}
void send(const std::string& message) {
sendData(wsheader_type::TEXT_FRAME, message.size(), message.begin(), message.end());
}
void sendBinary(const std::string& message) {
sendData(wsheader_type::BINARY_FRAME, message.size(), message.begin(), message.end());
}
void sendBinary(const std::vector<uint8_t>& message) {
sendData(wsheader_type::BINARY_FRAME, message.size(), message.begin(), message.end());
}
template<class Iterator>
void sendData(wsheader_type::opcode_type type, uint64_t message_size, Iterator message_begin, Iterator message_end) {
// TODO:
// Masking key should (must) be derived from a high quality random
// number generator, to mitigate attacks on non-WebSocket friendly
// middleware:
const uint8_t masking_key[4] = { 0x12, 0x34, 0x56, 0x78 };
// TODO: consider acquiring a lock on txbuf...
if (readyState == CLOSING || readyState == CLOSED) { return; }
std::vector<uint8_t> header;
header.assign(2 + (message_size >= 126 ? 2 : 0) + (message_size >= 65536 ? 6 : 0) + (useMask ? 4 : 0), 0);
header[0] = 0x80 | type;
if (false) { }
else if (message_size < 126) {
header[1] = (message_size & 0xff) | (useMask ? 0x80 : 0);
if (useMask) {
header[2] = masking_key[0];
header[3] = masking_key[1];
header[4] = masking_key[2];
header[5] = masking_key[3];
}
}
else if (message_size < 65536) {
header[1] = 126 | (useMask ? 0x80 : 0);
header[2] = (message_size >> 8) & 0xff;
header[3] = (message_size >> 0) & 0xff;
if (useMask) {
header[4] = masking_key[0];
header[5] = masking_key[1];
header[6] = masking_key[2];
header[7] = masking_key[3];
}
}
else { // TODO: run coverage testing here
header[1] = 127 | (useMask ? 0x80 : 0);
header[2] = (message_size >> 56) & 0xff;
header[3] = (message_size >> 48) & 0xff;
header[4] = (message_size >> 40) & 0xff;
header[5] = (message_size >> 32) & 0xff;
header[6] = (message_size >> 24) & 0xff;
header[7] = (message_size >> 16) & 0xff;
header[8] = (message_size >> 8) & 0xff;
header[9] = (message_size >> 0) & 0xff;
if (useMask) {
header[10] = masking_key[0];
header[11] = masking_key[1];
header[12] = masking_key[2];
header[13] = masking_key[3];
}
}
// N.B. - txbuf will keep growing until it can be transmitted over the socket:
txbuf.insert(txbuf.end(), header.begin(), header.end());
txbuf.insert(txbuf.end(), message_begin, message_end);
if (useMask) {
for (size_t i = 0; i != message_size; ++i) { *(txbuf.end() - message_size + i) ^= masking_key[i&0x3]; }
}
}
void close() {
if(readyState == CLOSING || readyState == CLOSED) { return; }
readyState = CLOSING;
uint8_t closeFrame[6] = {0x88, 0x80, 0x00, 0x00, 0x00, 0x00}; // last 4 bytes are a masking key
std::vector<uint8_t> header(closeFrame, closeFrame+6);
txbuf.insert(txbuf.end(), header.begin(), header.end());
}
};
easywsclient::WebSocket::pointer from_url(const std::string& url, bool useMask, const std::string& origin) {
char host[128];
int port;
char path[128];
if (url.size() >= 128) {
vLog(LOG_ERROR, "ERROR: url size limit exceeded: %s\n", url.c_str());
return NULL;
}
if (origin.size() >= 200) {
vLog(LOG_ERROR, "ERROR: origin size limit exceeded: %s\n", origin.c_str());
return NULL;
}
if (false) { }
else if (sscanf(url.c_str(), "ws://%[^:/]:%d/%s", host, &port, path) == 3) {
}
else if (sscanf(url.c_str(), "ws://%[^:/]/%s", host, path) == 2) {
port = 80;
}
else if (sscanf(url.c_str(), "ws://%[^:/]:%d", host, &port) == 2) {
path[0] = '\0';
}
else if (sscanf(url.c_str(), "ws://%[^:/]", host) == 1) {
port = 80;
path[0] = '\0';
}
else {
vLog(LOG_ERROR, "ERROR: Could not parse WebSocket url: %s\n", url.c_str());
return NULL;
}
vLog(LOG_DEBUG, "easywsclient: connecting: host=%s port=%d path=/%s\n", host, port, path);
socket_t sockfd = hostname_connect(host, port);
if (sockfd == INVALID_SOCKET) {
vLog(LOG_ERROR, "Unable to connect to %s:%d\n", host, port);
return NULL;
}
{
// XXX: this should be done non-blocking,
char line[256];
int status;
int i;
snprintf(line, 256, "GET /%s HTTP/1.1\r\n", path); ::send(sockfd, line, strlen(line), 0);
if (port == 80) {
snprintf(line, 256, "Host: %s\r\n", host); ::send(sockfd, line, strlen(line), 0);
}
else {
snprintf(line, 256, "Host: %s:%d\r\n", host, port); ::send(sockfd, line, strlen(line), 0);
}
snprintf(line, 256, "Upgrade: websocket\r\n"); ::send(sockfd, line, strlen(line), 0);
snprintf(line, 256, "Connection: Upgrade\r\n"); ::send(sockfd, line, strlen(line), 0);
if (!origin.empty()) {
snprintf(line, 256, "Origin: %s\r\n", origin.c_str()); ::send(sockfd, line, strlen(line), 0);
}
snprintf(line, 256, "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n"); ::send(sockfd, line, strlen(line), 0);
snprintf(line, 256, "Sec-WebSocket-Version: 13\r\n"); ::send(sockfd, line, strlen(line), 0);
snprintf(line, 256, "\r\n"); ::send(sockfd, line, strlen(line), 0);
for (i = 0; i < 2 || (i < 255 && line[i-2] != '\r' && line[i-1] != '\n'); ++i) { if (recv(sockfd, line+i, 1, 0) == 0) { return NULL; } }
line[i] = 0;
if (i == 255) { vLog(LOG_ERROR, "ERROR: Got invalid status line connecting to: %s\n", url.c_str()); return NULL; }
if (sscanf(line, "HTTP/1.1 %d", &status) != 1 || status != 101) { vLog(LOG_ERROR, "ERROR: Got bad status connecting to %s: %s", url.c_str(), line); return NULL; }
// TODO: verify response headers,
while (true) {
for (i = 0; i < 2 || (i < 255 && line[i-2] != '\r' && line[i-1] != '\n'); ++i) { if (recv(sockfd, line+i, 1, 0) == 0) { return NULL; } }
if (line[0] == '\r' && line[1] == '\n') { break; }
}
}
int flag = 1;
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char*) &flag, sizeof(flag)); // Disable Nagle's algorithm
#ifdef _WIN32
u_long on = 1;
ioctlsocket(sockfd, FIONBIO, &on);
#else
fcntl(sockfd, F_SETFL, O_NONBLOCK);
#endif
vLog(LOG_DEBUG, "Connected to: %s\n", url.c_str());
return easywsclient::WebSocket::pointer(new _RealWebSocket(sockfd, useMask));
}
} // end of module-only namespace
namespace easywsclient {
WebSocket::pointer WebSocket::create_dummy() {
static pointer dummy = pointer(new _DummyWebSocket);
return dummy;
}
WebSocket::pointer WebSocket::from_url(const std::string& url, const std::string& origin) {
return ::from_url(url, true, origin);
}
WebSocket::pointer WebSocket::from_url_no_mask(const std::string& url, const std::string& origin) {
return ::from_url(url, false, origin);
}
} // namespace easywsclient

View File

@ -90,7 +90,7 @@ const props = defineProps({
const getAnimationStyle = (item) => {
const irotorspeed = item.attributeMap?.irotorspeed ?? 0
let animationDuration;
if(irotorspeed>15){
if(irotorspeed>10){
animationDuration= 60 / irotorspeed
}else{
animationDuration = 60 / irotorspeed / 5