Merge branch 'main' of https://git.jsspisoft.com/ry-das
This commit is contained in:
commit
e13085ae4e
@ -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)
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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_
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)、当前文件夹路径名的后缀 dint,按照顺序增加1(转字符串时在前补0);
|
||||
3)、当前文件夹下最后新文件的编号 dint;
|
||||
4)、当前文件夹下第一个文件的编号 dint;
|
||||
2)、当前文件夹路径名的后缀 dint,按照顺序增加1(转字符串时在前补0);
|
||||
3)、当前文件夹下最后新文件的编号 dint;
|
||||
4)、当前文件夹下第一个文件的编号 dint;
|
||||
5)、当前文件夹下文件个数 dint;
|
||||
*/
|
||||
//路径有效性判断
|
||||
|
@ -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 控制系统 代表目前已经触发的故障代码类似:02(HH)04(HL)005(L)
|
||||
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()
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
//网络配置信息
|
||||
|
95
das-dn/inc/websockets/client.h
Normal file
95
das-dn/inc/websockets/client.h
Normal 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
|
73
das-dn/inc/websockets/easywsclient.hpp
Normal file
73
das-dn/inc/websockets/easywsclient.hpp
Normal 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 */
|
5
das-dn/third_party/nopoll/nopoll_conn.c
vendored
5
das-dn/third_party/nopoll/nopoll_conn.c
vendored
@ -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) {
|
||||
|
527
das-dn/third_party/websockets/easywsclient.cpp
vendored
Normal file
527
das-dn/third_party/websockets/easywsclient.cpp
vendored
Normal 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
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user