This commit is contained in:
高云鹏 2024-10-29 16:20:19 +08:00
commit a2ffa5068c
25 changed files with 1771 additions and 360 deletions

View File

@ -1,4 +1,5 @@
#include "ry.h"
#include <math.h>
CRYDevice::CRYDevice()
{
@ -275,10 +276,12 @@ BOOLEAN CRYDevice::websocket_msg_join(noPollMsg **msg, int msg_count, BYTE* &buf
len += nopoll_msg_get_payload_size(msg[i]);
}
buffer[buffer_size] = 0;
vLog(LOG_DEBUG, "buffer size is: %ld.\n", buffer_size);
return TRUE;
}
int CRYDevice::websocket_write(noPollConn* conn, const char * buffer, int buffer_len)
int CRYDevice::websocket_write(const char * buffer, int buffer_len)
{
int result;
result = nopoll_conn_send_text(conn, (const char *)buffer, buffer_len);
@ -287,7 +290,7 @@ int CRYDevice::websocket_write(noPollConn* conn, const char * buffer, int buffer
return (result == buffer_len) ? 0 : -1;
}
bool CRYDevice::publish_sensor_data(noPollConn* conn, const std::string traceId, const char* command, const Json::Value payload)
bool CRYDevice::publish_sensor_data(const std::string traceId, const char* command, const Json::Value payload)
{
Json::StreamWriterBuilder builder;
builder["indentation"] = "";
@ -311,8 +314,11 @@ bool CRYDevice::publish_sensor_data(noPollConn* conn, const std::string traceId,
jsonRoot["data"] = payload;
std::string outputConfig = Json::writeString(builder, jsonRoot);
vLog(LOG_DEBUG, "send cmd: %s, payload: %d\n", command, outputConfig.length());
int rc = websocket_write(conn, outputConfig.c_str(), outputConfig.length());
if (traceId != "")
{
vLog(LOG_DEBUG, "send cmd: %s, payload: %d, %128s\n", command, outputConfig.length(), outputConfig.c_str());
}
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);
//插入数据库
@ -340,7 +346,39 @@ int CRYDevice::GetUnitYMCount(int uid)
return config.units[uid].ymcount;
}
float CRYDevice::GetUnitYCReal(int uid, int order)
LONG CRYDevice::GetUnitYC(int uid, int order) const
{
int udb;
LONG value;
struUnit* pUnit;
struUnitYC* pYC;
if (uid < 0 || uid >= UNIT_NUM) return 0;
pUnit = &config.units[uid];
if ((pUnit->state & 0x01) != TRUE) return 0;
if (order < 0 || order >= pUnit->yccount) return 0;
pYC = &pUnit->ycs[order];
udb = pYC->order;
if (udb < 0 || udb >= DATABASE_YC_NUM)
{
value = pYC->value;
}
else
{
value = database.ycs[udb].value;
pYC->value = value;
pYC->update_time = database.ycs[udb].update_time;
pYC->qds = database.ycs[udb].qds;
}
if (pYC->factor > 1 && (pUnit->type & 0x0f) == 0x00)
{ //系数有效,且为转发单元
value /= pYC->factor;
}
return value;
}
float CRYDevice::GetUnitYCReal(int uid, int order) const
{
int udb;
long value;
@ -369,7 +407,7 @@ float CRYDevice::GetUnitYCReal(int uid, int order)
return (float)((float)value * coef + base);
}
float CRYDevice::GetUnitYCRealFromValue(int uid, int order, long value)
float CRYDevice::GetUnitYCRealFromValue(int uid, int order, long value) const
{
int udb;
float coef;
@ -393,6 +431,64 @@ float CRYDevice::GetUnitYCRealFromValue(int uid, int order, long value)
return (float)(value * coef + base);
}
BOOLEAN CRYDevice::GetUnitYCIsFloat(int uid, int order) const
{
int udb;
float coef = 1.0f;
struUnit* pUnit;
struUnitYC* pYC;
if (uid < 0 || uid >= UNIT_NUM) return 0;
pUnit = &config.units[uid];
if ((pUnit->state & 0x01) != TRUE) return 0;
if (order < 0 || order >= pUnit->yccount) return 0;
pYC = &pUnit->ycs[order];
udb = pYC->order;
if (udb < 0 || udb >= DATABASE_YC_NUM)
{
coef = 1.0f;
}
else
{
coef = pYC->coef;
}
if (fabsf(coef) <= 1E-8) coef = 1.0f;
if (fabsf(coef - 1.0f) <= 1E-8) return FALSE;
return TRUE;
}
float CRYDevice::GetUnitYCLimitReal(int uid, int order, int type) const
{
float limitValue;
struUnit* pUnit;
struUnitYC* pYC;
if (uid < 0 || uid >= UNIT_NUM) return 0;
pUnit = &config.units[uid];
if ((pUnit->state & 0x01) != TRUE) return 0;
if (order < 0 || order >= pUnit->yccount) return 0;
pYC = &pUnit->ycs[order];
//1-越上限 2-越下限)
if (type == 1)
{
limitValue = pYC->limit1High;
}
else if (type == 2)
{
limitValue = pYC->limit1Low;
}
else if (type == 3)
{
limitValue = pYC->limit2High;
}
else if (type == 4)
{
limitValue = pYC->limit2Low;
}
return limitValue;
}
float CRYDevice::GetUnitYMReal(int uid, int order)
{
int udb;
@ -444,10 +540,13 @@ BYTE CRYDevice::GetUnitYX(int uid, int point)
return value;
}
int CRYDevice::GetUnitYXBW(int& uid, BOOLEAN& value, BYTE& qds, int& type, unionCP56Time& st)
int CRYDevice::GetUnitYXBW(int& uid, BOOLEAN& value, unionCP56Time& st)
{
int order;
int point;
int type;
BYTE qds;
while (yxbw.GetYXBW(m_yxbwload, st, order, value, qds, uid, point, type))
{
@ -470,10 +569,11 @@ int CRYDevice::GetUnitSOE(int& uid, BOOLEAN& value, BYTE& qds, unionCP56Time& st
return -1;
}
int CRYDevice::GetUnitYCBW(int& uid, LONG& value, BYTE& qds, int& type, unionCP56Time& st)
int CRYDevice::GetUnitYCBW(int& uid, LONG& value, int& type, unionCP56Time& st)
{
int order;
int point;
BYTE qds;
while (ycbw.GetYCBW(m_ycbwload, st, order, value, qds, uid, point, type)) {
m_ycbwload++;
@ -751,7 +851,7 @@ void CRYDevice::SetUnitYT(int uid, int order, DWORD value, BYTE act, BYTE result
}
}
int CRYDevice::MakeYKFrame(noPollConn* conn, int uid)
int CRYDevice::MakeYKFrame(int uid)
{
int order;
BYTE value, action, result;
@ -790,13 +890,13 @@ int CRYDevice::MakeYKFrame(noPollConn* conn, int uid)
jsonRoot["result"] = true;
}
publish_sensor_data(conn, m_traceId, "deviceControlResp", jsonRoot);
publish_sensor_data(m_traceId, "deviceControlResp", jsonRoot);
return 1;
}
return 0;
}
int CRYDevice::MakeYTFrame(noPollConn* conn, int uid)
int CRYDevice::MakeYTFrame(int uid)
{
int order;
BYTE action, result;
@ -834,7 +934,7 @@ int CRYDevice::MakeYTFrame(noPollConn* conn, int uid)
jsonRoot["result"] = true;
}
publish_sensor_data(conn, m_traceId, "deviceControlResp", jsonRoot);
publish_sensor_data(m_traceId, "deviceControlResp", jsonRoot);
return 1;
}
@ -1081,13 +1181,13 @@ BOOLEAN CRYDevice::processModbusPointParam(const Json::Value jsonRoot, int uid,
} else {
config_config.units[uid].ycs[point].m_param[0] = 0;
}
if (jsonRoot["col3"].isString()) {
BYTE dataType = (BYTE)atoi(jsonRoot["col3"].asCString());
if (jsonRoot["col2"].isString()) {
BYTE dataType = (BYTE)atoi(jsonRoot["col2"].asCString());
config_config.units[uid].ycs[point].m_param[4] = dataType;
if (dataType == 2 || dataType == 8) config_config.units[uid].ycs[point].m_param[3] = 1;
else config_config.units[uid].ycs[point].m_param[3] = 2;
} else if (jsonRoot["col3"].isInt()) {
BYTE dataType = jsonRoot["col3"].asInt();
} else if (jsonRoot["col2"].isInt()) {
BYTE dataType = jsonRoot["col2"].asInt();
config_config.units[uid].ycs[point].m_param[4] = dataType;
if (dataType == 2 || dataType == 8) config_config.units[uid].ycs[point].m_param[3] = 1;
else config_config.units[uid].ycs[point].m_param[3] = 2;
@ -1095,11 +1195,11 @@ BOOLEAN CRYDevice::processModbusPointParam(const Json::Value jsonRoot, int uid,
config_config.units[uid].ycs[point].m_param[4] = 0;
config_config.units[uid].ycs[point].m_param[3] = 1;
}
if (jsonRoot["col2"].isString()) {
BYTE signMark = (BYTE)atoi(jsonRoot["col2"].asCString());
if (jsonRoot["col3"].isString()) {
BYTE signMark = (BYTE)atoi(jsonRoot["col3"].asCString());
config_config.units[uid].ycs[point].m_param[5] = signMark;
} else if (jsonRoot["col2"].isInt()) {
BYTE signMark = jsonRoot["col2"].asInt();
} else if (jsonRoot["col3"].isInt()) {
BYTE signMark = jsonRoot["col3"].asInt();
config_config.units[uid].ycs[point].m_param[5] = signMark;
} else {
config_config.units[uid].ycs[point].m_param[5] = 0;
@ -1693,7 +1793,7 @@ bool CRYDevice::dealConfigFile(const Json::Value jsonRoot)
return true;
}
bool CRYDevice::OnReceivedSystemAction(noPollConn* conn, const std::string cmdId, const std::string cmd, const Json::Value data)
bool CRYDevice::OnReceivedSystemAction(const std::string cmdId, const std::string cmd, const Json::Value data)
{
do {
if (cmd == "configUpdate") { //配置更新
@ -1710,7 +1810,7 @@ bool CRYDevice::OnReceivedSystemAction(noPollConn* conn, const std::string cmdId
return true;
}
void CRYDevice::on_message(noPollConn* conn, const char *msg, const int size)
void CRYDevice::on_message(const char *msg, const int size)
{
if (msg == NULL) return;
if (size <= 0) return;
@ -1742,11 +1842,11 @@ void CRYDevice::on_message(noPollConn* conn, const char *msg, const int size)
Json::Int64 mtime = jsonRoot["time"].asInt64();
#endif
Json::Value datas = jsonRoot["data"];
OnReceivedSystemAction(conn, cmdId, cmd, datas);
OnReceivedSystemAction(cmdId, cmd, datas);
} while (0);
}
void CRYDevice::heart_beat(noPollConn* conn, int status)
void CRYDevice::heart_beat(int status)
{
//发送心跳报文
Json::Value payload;
@ -1756,7 +1856,6 @@ void CRYDevice::heart_beat(noPollConn* conn, int status)
if (status == 1) {
Json::Value jsonItem;
Json::Value jsonValue;
//for (int i = 0; i < static_cast<int>(m_gLinkIDs.size()); i++) {
for (int i = 0; i < PROCESSES_NUM - 1; i++) {
if (config.processes[i].state == TRUE) {
char linkId[32];
@ -1771,11 +1870,11 @@ void CRYDevice::heart_beat(noPollConn* conn, int status)
}
}
publish_sensor_data(conn, "", "heartbeat", payload);
publish_sensor_data("", "heartbeat", payload);
}
bool CRYDevice::publishinitDeviceData(noPollConn* conn, int uid)
bool CRYDevice::publishinitDeviceData(int uid)
{
if (uid < 0 || uid >= UNIT_NUM) return false;
@ -1813,12 +1912,12 @@ bool CRYDevice::publishinitDeviceData(noPollConn* conn, int uid)
root["values"] = values;
config.units[uid].state |= 0x40;
return publish_sensor_data(conn, "", "initDeviceData", root);
return publish_sensor_data("", "initDeviceData", root);
}
return false;
}
bool CRYDevice::publishAnalogData(noPollConn* conn, int uid)
bool CRYDevice::publishAnalogData(int uid)
{
if (uid < 0 || uid >= UNIT_NUM) return false;
Json::Value root;
@ -1826,7 +1925,11 @@ bool CRYDevice::publishAnalogData(noPollConn* conn, int uid)
int count = GetUnitYCCount(uid);
if (count) {
for (int i = 0; i < count; i++) {
values[(const char *)config.units[uid].ycs[i].name] = GetUnitYCReal(uid, i);
if (GetUnitYCIsFloat(uid, i)) {
values[(const char *)config.units[uid].ycs[i].name] = GetUnitYCReal(uid, i);
} else {
values[(const char *)config.units[uid].ycs[i].name] = GetUnitYC(uid, i);
}
}
}
if (values.size()) {
@ -1835,12 +1938,12 @@ bool CRYDevice::publishAnalogData(noPollConn* conn, int uid)
root["dataTime"] = datatime;
root["deviceId"] = static_units[uid].deviceId;
root["values"] = values;
return publish_sensor_data(conn, "", "analogData", root);
return publish_sensor_data("", "analogData", root);
}
return false;
}
bool CRYDevice::publishStateData(noPollConn* conn, int uid)
bool CRYDevice::publishStateData(int uid)
{
if (uid < 0 || uid >= UNIT_NUM) return false;
Json::Value root;
@ -1857,35 +1960,65 @@ bool CRYDevice::publishStateData(noPollConn* conn, int uid)
root["dataTime"] = datatime;
root["deviceId"] = static_units[uid].deviceId;
root["values"] = values;
return publish_sensor_data(conn, "", "stateData", root);
return publish_sensor_data("", "stateData", root);
}
return false;
}
bool CRYDevice::publishHistoryAnalogData(noPollConn* conn, int uid)
bool CRYDevice::publishdeviceEventData(void)
{
if (uid < 0 || uid >= UNIT_NUM) return false;
Json::Value root;
Json::Value values;
if (values.size()) {
root["deviceId"] = static_units[uid].deviceId;
root["values"] = values;
return publish_sensor_data(conn, "", "historyAnalogData", root);
}
return false;
}
int i;
int uid;
int yxbw_point;
BOOLEAN yxbw_value;
unionCP56Time yxbw_time;
bool CRYDevice::publishHistoryStateData(noPollConn* conn, int uid)
{
if (uid < 0 || uid >= UNIT_NUM) return false;
Json::Value root;
Json::Value values;
if (values.size()) {
root["deviceId"] = static_units[uid].deviceId;
root["values"] = values;
return publish_sensor_data(conn, "", "historyStateData", root);
Json::Value value;
for (i = 0; i < DATABASE_YXBW_NUM; i++)
{
yxbw_point = GetUnitYXBW(uid, yxbw_value, yxbw_time);
if (yxbw_point < 0) break;
value["deviceId"] = static_units[uid].deviceId;
value["attrCode"] = (const char *)config.units[uid].yxs[yxbw_point].name;
value["attrValue"] = yxbw_value;
value["eventType"] = 0;
Json::Int64 datatime = (Json::Int64)time(NULL);
datatime *= 1000;
value["dataTime"] = datatime;
value["limitValue"] = Json::Value::null;
root.append(value);
}
int ycbw_point;
int ycbw_type;
LONG ycbw_value;
unionCP56Time ycbw_time;
for (i = 0; i < DATABASE_YCBW_NUM; i++)
{
ycbw_point = GetUnitYCBW(uid, ycbw_value, ycbw_type, ycbw_time);
if (ycbw_point < 0) break;
value["deviceId"] = static_units[uid].deviceId;
value["attrCode"] = (const char *)config.units[uid].ycs[ycbw_point].name;
value["attrValue"] = ycbw_value;
value["eventType"] = ycbw_type;
Json::Int64 datatime = (Json::Int64)time(NULL);
datatime *= 1000;
value["dataTime"] = datatime;
value["limitValue"] = GetUnitYCLimitReal(uid, ycbw_point, ycbw_type);
root.append(value);
}
if (root.size()) {
//return publish_sensor_data("", "deviceEvent", root);
vLog(LOG_DEBUG, "%s", root.toStyledString().c_str());
}
return false;
return FALSE;
}
void CRYDevice::releaseAllUnits(void)
@ -1969,31 +2102,38 @@ bool CRYDevice::ry_run(void)
nopoll_bool isOk = nopoll_conn_is_ready(conn);
if (isOk) {
last_connect_sec = system32.timers;
int msg_count = 0;
noPollMsg *msg[2048];
while ((msg[msg_count] = nopoll_conn_get_msg(conn)) != NULL) {
vLog(LOG_DEBUG, "recv length = %d, %d\n", nopoll_msg_get_payload_size(msg[msg_count]), nopoll_msg_is_final(msg[msg_count]));
vLog(LOG_DEBUG, "recv %d length = %d, %d\n", msg_count, nopoll_msg_get_payload_size(msg[msg_count]), nopoll_msg_is_final(msg[msg_count]));
char pathN[256];
snprintf(pathN, sizeof(pathN), "0/_%d.txt", msg_count);
FILE* pf = fopen(pathN, "w+");
if (pf) {
fwrite(nopoll_msg_get_payload(msg[msg_count]), nopoll_msg_get_payload_size(msg[msg_count]), 1, pf);
fclose(pf);
}
if (nopoll_msg_is_final(msg[msg_count])) {
msg_count++;
if (msg_count > 0) {
int buffer_len;
BYTE *buffer = NULL;
if (websocket_msg_join(msg, msg_count, buffer, buffer_len)) {
if (buffer) {
on_message((const char *)buffer, buffer_len);
delete [] buffer;
buffer = NULL;
}
for (int i = 0; i < msg_count; i++) {
nopoll_msg_unref(msg[i]);
msg_count = 0;
}
}
}
break;
} else {
msg_count++;
}
}
if (msg_count > 0) {
int buffer_len;
BYTE *buffer = NULL;
if (websocket_msg_join(msg, msg_count, buffer, buffer_len)) {
if (buffer) {
on_message(conn, (const char *)buffer, buffer_len);
delete [] buffer;
buffer = NULL;
}
}
}
for (int i = 0; i < msg_count; i++) {
nopoll_msg_unref(msg[i]);
}
} else {
if (last_connect_sec > 0 && system32.timers > (last_connect_sec + 30)) {
nopoll_conn_connect_timeout(ctx, 50000);
@ -2015,19 +2155,20 @@ bool CRYDevice::ry_run(void)
}
if (sec_changed) {
if ((last_sec % 20) == 0) {
heart_beat(conn, status);
heart_beat(status);
}
}
publishdeviceEventData();
for (int i = 0; i < UNIT_NUM; i++) {
if ((config.units[i].state & 0x01) != TRUE) continue;
MakeYKFrame(conn, i);
MakeYTFrame(conn, i);
MakeYKFrame(i);
MakeYTFrame(i);
if (sec_changed) {
//publishinitDeviceData(conn, i);
if ((last_sec % 60) == 0) { //更新数据
publishAnalogData(conn, i);
publishStateData(conn, i);
}
//publishinitDeviceData(i);
// if ((last_sec % 10) == 0) { //更新数据
publishAnalogData(i);
publishStateData(i);
// }
}
}
return m_dataAcquisitionReload;

View File

@ -80,6 +80,9 @@ private:
DWORD last_connect_sec = 0;
int status;
int msg_count = 0;
noPollMsg *msg[2048];
bool m_dataAcquisitionReload = false;
char m_host[256] = {"127.0.0.1"};
@ -105,37 +108,43 @@ private:
int GetUnitYXCount(int uid);
int GetUnitYCCount(int uid);
int GetUnitYMCount(int uid);
float GetUnitYCReal(int uid, int order);
float GetUnitYCRealFromValue(int uid, int order, long value);
LONG GetUnitYC(int uid, int order) const;
float GetUnitYCReal(int uid, int order) const;
float GetUnitYCRealFromValue(int uid, int order, long value) const;
BOOLEAN GetUnitYCIsFloat(int uid, int order) const;
float GetUnitYCLimitReal(int uid, int order, int type = 1) const;
float GetUnitYMReal(int uid, int order);
BYTE GetUnitYX(int uid, int point);
int GetUnitYXBW(int& uid, BOOLEAN& value, BYTE& qds, int& type, unionCP56Time& st);
int GetUnitYXBW(int& uid, BOOLEAN& value, unionCP56Time& st);
int GetUnitSOE(int& uid, BOOLEAN& value, BYTE& qds, unionCP56Time& st);
int GetUnitYCBW(int& uid, LONG& value, BYTE& qds, int& type, unionCP56Time& st);
int GetUnitYCBW(int& uid, LONG& value, int& type, unionCP56Time& st);
BOOLEAN GetUnitYK(int uid, int& order, BYTE& value, BYTE& act, BYTE& result);
void SetUnitYK(int uid, int order, BYTE value, BYTE act, BYTE result);
BOOLEAN GetUnitYT(int uid, int& order, DWORD& value, BYTE& act, BYTE& result);
void SetUnitYT(int uid, int order, DWORD value, BYTE act, BYTE result);
int MakeYKFrame(noPollConn* conn, int uid);
int MakeYTFrame(noPollConn* conn, int uid);
int MakeYKFrame(int uid);
int MakeYTFrame(int uid);
bool OnReceivedDeviceCommand(const Json::Value jsonRoot);
BOOLEAN processUartParam(const Json::Value jsonRoot, int ord);
BOOLEAN processNetworkParam(const Json::Value jsonRoot, int pid);
BOOLEAN processHostIEC104ProcessParam(const Json::Value jsonRoot, int pid);
BOOLEAN processModbusPointParam(const Json::Value jsonRoot, int uid, int point, int type);
bool dealConfigFile(const Json::Value jsonRoot);
bool OnReceivedSystemAction(noPollConn* conn, const std::string cmdId, const std::string cmd, const Json::Value data);
void on_message(noPollConn* conn, const char *msg, const int size);
bool OnReceivedSystemAction(const std::string cmdId, const std::string cmd, const Json::Value data);
void on_message(const char *msg, const int size);
void heart_beat(noPollConn* conn, int status);
bool publishinitDeviceData(noPollConn* conn, int uid);
bool publishAnalogData(noPollConn* conn, int uid);
bool publishStateData(noPollConn* conn, int uid);
bool publishHistoryAnalogData(noPollConn* conn, int uid);
bool publishHistoryStateData(noPollConn* conn, int uid);
void heart_beat(int status);
bool publishinitDeviceData(int uid);
bool publishAnalogData(int uid);
bool publishStateData(int uid);
bool publishHistoryAnalogData(int uid);
bool publishHistoryStateData(int uid);
bool publishdeviceEventData(void);
BOOLEAN publishYXBWData(int uid);
BOOLEAN publishYCBWData(int uid);
BOOLEAN websocket_msg_join(noPollMsg **msg, int msg_count, BYTE* &buffer, int &buffer_size);
int websocket_write(noPollConn* conn, const char * buffer, int buffer_len);
bool publish_sensor_data(noPollConn* conn, const std::string traceId, const char* command, const Json::Value payload);
int websocket_write(const char * buffer, int buffer_len);
bool publish_sensor_data(const std::string traceId, const char* command, const Json::Value payload);
};
#endif //_RY_H_

View File

@ -879,8 +879,6 @@ float CProcess::GetUnitYCRealFromValue(int uid, int order, long value) const
base = 0.0f;
}
else {
// coef = database.ycs[udb].coef;
// base = database.ycs[udb].base;
coef = pYC->coef;
base = pYC->base;
}
@ -906,7 +904,6 @@ float CProcess::GetUnitYCCoef(int uid, int order) const
}
else
{
// coef = database.ycs[udb].coef;
coef = pYC->coef;
}
@ -933,7 +930,6 @@ float CProcess::GetUnitYCBase(int uid, int order) const
}
else
{
// base = database.ycs[udb].base;
base = pYC->base;
}
@ -1022,7 +1018,6 @@ float CProcess::GetUnitYMCoef(int uid, int order) const
}
else
{
// coef = database.yms[udb].coef;
coef = pYM->coef;
}
@ -1049,7 +1044,6 @@ float CProcess::GetUnitYMBase(int uid, int order) const
}
else
{
// base = database.yms[udb].base;
base = pYM->base;
}

View File

@ -3,11 +3,7 @@
#include <math.h>
#include <map>
#include <unordered_map>
///////////////////////////////////////////////////////////////////////////////////
//Valid slave device addresses are in the range of 0 锟?C 247 decimal. //
//The individual slave devices are assigned addresses in the range of 1 锟?C 247. //
//Address 0 is used for the broadcast address, which all slave devices recognize.//
///////////////////////////////////////////////////////////////////////////////////
#ifdef HAVE_FTP_PROCESS
#define MODBUSP_READ_ID 100 //读取文件及文件夹ID
@ -43,9 +39,9 @@ struct {
{ 2, 205 },
{ 2, 206 },
{ 2, 207 },
{ 2, 208 },
{ 2, 209 },
{ 2, 210 },
{ 2, 208 },
{ 2, 211 },
{ 2, 212 },
{ 2, 213 },
@ -183,7 +179,14 @@ struct {
{ 2, 358 },
{ 2, 359 },
{ 2, 360 },
{ 2, 361 }
{ 2, 361 },
{ 2, 362 },
{ 2, 363 },
{ 2, 364 },
{ 2, 365 },
{ 2, 366 },
{ 2, 367 },
{ 2, 368 }
};
#include <curl/curl.h>
@ -218,7 +221,7 @@ static bool publish_sensor_data(const noPollConn* conn, const char* command, con
std::string outputConfig = Json::writeString(builder, jsonRoot);
int rc = websocket_write(conn, outputConfig.c_str(), outputConfig.length());
vLog(LOG_DEBUG, "send cmd: %s, payload: %d\n%s\n", command, outputConfig.length(), outputConfig.c_str());
//vLog(LOG_DEBUG, "send cmd: %s, payload: %d\n", command, outputConfig.length()/*, outputConfig.c_str()*/);
if (rc != 0) {
vLog(LOG_DEBUG, "websocket write is error<%d>,insert into database.\n", rc);
//插入数据库
@ -490,7 +493,7 @@ static size_t writefunc(void* ptr, size_t size, size_t nmemb, FILE* stream)
static int ftpget(const char* remote, const char* local, const char* user, const char* pwd, const long timeout = 3, struct memory* chunk = NULL)
{
vLog(LOG_DEBUG, "start to get %s to local %s, with name: %s, and password: %s.\n", remote, local, user, pwd);
//vLog(LOG_DEBUG, "start to get %s to local %s, with name: %s, and password: %s.\n", remote, local, user, pwd);
curl_global_init(CURL_GLOBAL_ALL);
CURL* curl = curl_easy_init();
@ -536,17 +539,18 @@ static int ftpget(const char* remote, const char* local, const char* user, const
ret = curl_easy_perform(curl);
#endif
//vLog(LOG_DEBUG, "curl easy perform return value is: %d, and OK is: %d.\n", ret, CURLE_OK);
#if 0
int curl_state = 0;
if (ret == CURLE_OK) curl_state = 1;
else {
vLog(LOG_ERROR, "%d,%s\n", ret, curl_easy_strerror(ret));
//vLog(LOG_ERROR, "%d,%s\n", ret, curl_easy_strerror(ret));
curl_state = 0;
}
#endif
curl_easy_cleanup(curl);
curl_global_cleanup();
return curl_state;
return ret;
}
static void* ryftp_process(void* param)
@ -583,9 +587,10 @@ static void* ryftp_process(void* param)
DWORD target_addr = mbt->target_addr;
memset(ipaddress, '\0', sizeof(ipaddress));
inet_ntop(AF_INET, &target_addr, ipaddress, 16);
#if 0
struct timespec start, end;
double elapsed_time = 0;
#endif
for (int i = 0; i < sizeof(m_datalen_mbaddr) / sizeof(m_datalen_mbaddr[0]); i++) {
m_datalen2mbaddr_map.insert(datalen2mbaddrmap::value_type(m_datalen_mbaddr[i].address, i + 1));
@ -621,17 +626,17 @@ static void* ryftp_process(void* param)
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iYPLevel) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iYPLevel);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenSpeed1s) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenSpeed1s);
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iWindSpeed_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iWindSpeed_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenPower1s) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenPower1s);
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenSpeed_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenSpeed_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iWindSpeed1s) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iWindSpeed1s);
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.iGenToruqe1s) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenToruqe1s);
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenToruqe_1sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenToruqe_1sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iRotorSpeed) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iRotorSpeed);
@ -1044,6 +1049,27 @@ 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.iGenSpeed_10sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenSpeed_10sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenSpeed_30sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenSpeed_30sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenPower_10sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenPower_10sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iGenPower_30sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iGenPower_30sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iWindSpeed_10sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iWindSpeed_10sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iWindSpeed_30sec) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iWindSpeed_30sec);
len++;
fields[len].start = reinterpret_cast<uintptr_t>(&t_data.iAvailablePower) - reinterpret_cast<uintptr_t>(&t_data);
fields[len].length = sizeof(t_data.iAvailablePower);
len++;
//判断是否链接单元
@ -1085,7 +1111,7 @@ static void* ryftp_process(void* param)
}
//根据实际配置表将
WORD ftpget_retry_count = 0;
while (TRUE) {
sleep(1); //每秒执行一次
//ftp获取文件
@ -1096,11 +1122,15 @@ static void* ryftp_process(void* param)
snprintf(name, sizeof(name), "%s/%d", pathName, mbt->m_currentFileNo);
snprintf(remote, sizeof(remote), "ftp://%s/Hard%20Disk2/data/rtdatalog/%d/%d", ipaddress, mbt->m_currentDirNo, mbt->m_currentFileNo);
#if 0
clock_gettime(CLOCK_MONOTONIC, &start);
#endif
struct memory chunk = {0}; // For storing the downloaded data
if (ftpget(remote, name, user, password, 3, &chunk)) {
int result = ftpget(remote, name, user, password, 3, &chunk);
if (result == CURLE_OK) {
//成功,处理文件
vLog(LOG_DEBUG, "get %s to local %s, with name: %s, and password: %s okay.\n", remote, name, user, password);
ftpget_retry_count = 0;
struRYDeviceData *data = (struRYDeviceData *)chunk.response;
unionCP56Time st;
int uid = mbt->GetCurUnitID();
@ -1173,11 +1203,11 @@ static void* ryftp_process(void* param)
}
}
if (chunk.response) free(chunk.response);
//vLog(LOG_DEBUG, "get a file, then send to ws.\n");
#if 0
clock_gettime(CLOCK_MONOTONIC, &end);
elapsed_time = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;
vLog(LOG_DEBUG, "Elapsed time: %.6f seconds\n", elapsed_time);
#endif
mbt->m_lastFileNo = mbt->m_currentFileNo;
mbt->m_currentFileNo++;
if ((mbt->m_currentFileNo - mbt->m_lastStartFileNo) % 1000 == 0) {
@ -1191,6 +1221,15 @@ static void* ryftp_process(void* param)
#endif
//保存文件信息
}
} else if (result == CURLE_REMOTE_FILE_NOT_FOUND) {
//文件不存在尝试60次1分钟正常情况下PLC10s生成一个文件
ftpget_retry_count++;
if (ftpget_retry_count >= 60) {
//重新通过modbus程序获取文件夹和最新文件信息
mbt->m_iv = 0;
mbt->m_currentDirNo = -1;
mbt->m_currentFileNo = -1;
}
}
}
@ -1642,9 +1681,8 @@ BOOLEAN CHostModbusTcpProcess::OnPreCreate(int id)
m_nTimeout = 200;
calc2();
vLog(LOG_DEBUG, "file size is: %d\n", sizeof(struRYDeviceData) * 250 / 1024);
#ifdef HAVE_FTP_PROCESS
vLog(LOG_DEBUG, "file size is: %d\n", sizeof(struRYDeviceData) * 250 / 1024);
//启动后创建ftp线程
if (m_pid <= 0) {
vLog(LOG_DEBUG, "create a ftp thread.\n");
@ -2271,12 +2309,7 @@ BOOLEAN CHostModbusTcpProcess::OnReceiveIDData(CHostModbusTcpProcessItem *pItem,
//当前文件夹下第一个文件
m_lastStartFileNo = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]); pBuf += 4;
#if 0
m_currentDirNo = 37;
m_currentFileNo = 26901;
m_lastStartFileNo = 26901;
#endif
vLog(LOG_DEBUG, "dir: %ld, file: %ld: start: %ld\n", m_currentDirNo, m_currentFileNo, m_lastStartFileNo);
vLog(LOG_DEBUG, "最新文件夹编号: %ld, 最新文件名编号: %ld: 最新文件夹中第一个文件的编号: %ld\n", m_currentDirNo, m_currentFileNo, m_lastStartFileNo);
return TRUE;
}
@ -2392,6 +2425,7 @@ BOOLEAN CHostModbusTcpProcess::OnReceiveYCData(CHostModbusTcpProcessItem *pItem,
reg_count = pParam[3];
value_type = pParam[4];
sign_mark = pParam[5];
//vLog(LOG_DEBUG, "here count is: %d, value type is: %d, and ", reg_count, value_type);
if ((1 == reg_count) && (2 == value_type))
{ //16位归一化值
if (2 == value_type)
@ -2399,6 +2433,7 @@ BOOLEAN CHostModbusTcpProcess::OnReceiveYCData(CHostModbusTcpProcessItem *pItem,
if (sign_mark == 0) nValue = (DWORD)(WORD)((pBuf[0] << 8) | pBuf[1]);
else nValue = (DWORD)(short)((pBuf[0] << 8) | pBuf[1]);
SetUnitYC(uid, point, (LONG)nValue);
//vLog(LOG_DEBUG, "value is: %ld.\n", nValue);
}
else if (8 == value_type)
{
@ -2429,6 +2464,7 @@ BOOLEAN CHostModbusTcpProcess::OnReceiveYCData(CHostModbusTcpProcessItem *pItem,
{ //归一化值,高位在第一个寄存器
nValue = (DWORD)(pBuf[0] << 24 | pBuf[1] << 16 | pBuf[2] << 8 | pBuf[3]);
SetUnitYC(uid, point, (LONG)nValue);
//vLog(LOG_DEBUG, "value is: %ld.\n", nValue);
}
else if (4 == value_type)
{ //归一化值,高位在第二个寄存器

View File

@ -4,7 +4,7 @@
#include "netproc.h"
#include "modbus_def.h"
#define HAVE_FTP_PROCESS
//#define HAVE_FTP_PROCESS
#ifdef HAVE_FTP_PROCESS
#include <dirent.h>
#include <nopoll.h>
@ -21,10 +21,10 @@ typedef struct {
WORD iTurbineOperationMode;// 运行模式 2 205 1 需要解析 1s 控制系统
WORD iBPLevel;// 刹车等级 2 206 1 需要解析 1s 控制系统
WORD iYPLevel;// 偏航运行模式 2 207 1 需要解析 1s 控制系统
WORD iGenSpeed1s;// 发电机转速1秒均值 2 209 0.1 转/分 1s 控制系统
WORD iGenPower1s;// 机组有功1秒均值 2 210 0.1 千瓦 1s 控制系统
WORD iWindSpeed1s;// 风速1秒均值 2 208 0.01 米/秒 1s 控制系统
WORD iGenToruqe1s;// 发电机扭矩1秒均值 2 211 0.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 控制系统
@ -161,7 +161,14 @@ typedef struct {
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 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
} struRYDeviceData;
#pragma pack()

View File

@ -402,20 +402,52 @@ public:
}
} else if (database.ycs[udb].value != value) { //update value
//此处增加越线判断
float coef = pUnit->ycs[point].coef;
float base = pUnit->ycs[point].base;
float fValue = (float)((float)value * coef + base);
if (pUnit->ycs[point].limit1Enable) {
}
if (pUnit->ycs[point].limit2Enable) {
if (fValue > pUnit->ycs[point].limit1High) { //越上限
if (!pUnit->ycs[point].ycbw) {
pUnit->ycs[point].ycbw = TRUE;
ycbw.PushYCBW(system32.now, udb, value, qds, uid, point, 1);
}
} else if (fValue < pUnit->ycs[point].limit1Low) { //越下限
if (!pUnit->ycs[point].ycbw) {
pUnit->ycs[point].ycbw = TRUE;
ycbw.PushYCBW(system32.now, udb, value, qds, uid, point, 2);
}
} else { //不越限
if (pUnit->ycs[point].ycbw) {
pUnit->ycs[point].ycbw = FALSE;
ycbw.PushYCBW(system32.now, udb, value, qds, uid, point, 5);
}
}
//默认二级越限必须大于一级越限
if (pUnit->ycs[point].limit2Enable) {
if (fValue > pUnit->ycs[point].limit2High) { //越上限
if (!pUnit->ycs[point].ycbw) {
pUnit->ycs[point].ycbw = TRUE;
ycbw.PushYCBW(system32.now, udb, value, qds, uid, point, 3);
}
} else if (fValue < pUnit->ycs[point].limit2Low) { //越下限
if (!pUnit->ycs[point].ycbw) {
pUnit->ycs[point].ycbw = TRUE;
ycbw.PushYCBW(system32.now, udb, value, qds, uid, point, 4);
}
}
}
}
pUnit->ycs[point].value = value;
pUnit->ycs[point].update_time = system32.timers;
#if 0
if (pUnit->ycs[point].change_pos >= 0 && bAddYCBW) {
if (abs(pUnit->ycs[point].value - database.ycs[udb].value) >= pUnit->ycs[point].change_pos) { //40码值变化量认为是遥测变位
pUnit->ycs[point].ycbw = TRUE;
ycbw.PushYCBW(system32.now, udb, value, qds, uid, point, YCBWT_AUTO);
}
}
#endif
database.ycs[udb].value = value;
database.ycs[udb].op_unit = uid;
database.ycs[udb].update_time = system32.timers; //设置刷新时间
@ -458,12 +490,14 @@ public:
}
pUnit->ycs[point].value = nvalue;
pUnit->ycs[point].update_time = system32.timers;
#if 0
if (pUnit->ycs[point].change_pos >= 0 && bAddYCBW) {
if (abs(pUnit->ycs[point].value - database.ycs[udb].value) >= pUnit->ycs[point].change_pos) { //40码值变化量认为是遥测变位
pUnit->ycs[point].ycbw = TRUE;
ycbw.PushYCBW(system32.now, udb, nvalue, qds, uid, point, YCBWT_AUTO);
}
}
#endif
database.ycs[udb].value = nvalue;
database.ycs[udb].op_unit = uid;
database.ycs[udb].update_time = system32.timers; //设置刷新时间

View File

@ -75,7 +75,7 @@ typedef int SOCKET;
#define MAX_DISPLAY_BUFFER_SIZE 0x8000
#define HARDWARE_PORTS_NUM 20
#define PROCESSES_NUM 64
#define PROCESSES_NUM 256
#define PROCESS_UNIT_NUM 256
#define UNIT_NUM 256
#define UNIT_YX_MAX 0x1500

View File

@ -38,4 +38,8 @@ public interface SysEquipmentMapper extends BaseMapperPlus<SysEquipment, SysEqui
List<String> queryBelongLines(@Param("objectType") Long objectType);
List<SysEquipmentVo> querySysEquipmentList(@Param("info") SysEquipmentDto sysEquipmentDto);
SysEquipmentVo queryWindFarm(@Param("info") SysEquipmentDto sysEquipmentDto);
}

View File

@ -1,7 +1,7 @@
package com.das.modules.equipment.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@ -78,9 +78,10 @@ public class SysIotModelServiceImpl implements SysIotModelService {
sysIotModel.setRevision(1);
sysIotModelMapper.insert(sysIotModel);
addModelCache(sysIotModel);
SysIotModelVo sysIotModelVo = new SysIotModelVo();
BeanCopyUtils.copy(sysIotModel, sysIotModelVo);
sysIotModelVo.setIotModelCode(sysIotModelDto.getIotModelCode().toLowerCase());
sysIotModelVo.setIotModelCode(sysIotModelDto.getIotModelCode());
return sysIotModelVo;
}
@ -101,7 +102,7 @@ public class SysIotModelServiceImpl implements SysIotModelService {
}
sysIotModel.setUpdatedTime(new Date());
sysIotModel.setUpdatedBy(sysUserVo.getAccount());
sysIotModel.setIotModelCode(sysIotModelDto.getIotModelCode().toLowerCase());
sysIotModel.setIotModelCode(sysIotModelDto.getIotModelCode());
sysIotModelMapper.updateById(sysIotModel);
SysIotModelVo sysIotModelVo = new SysIotModelVo();
BeanCopyUtils.copy(sysIotModel, sysIotModelVo);
@ -115,6 +116,7 @@ public class SysIotModelServiceImpl implements SysIotModelService {
throw new RuntimeException("该物模型下面有类型,不能删除");
}
sysIotModelMapper.deleteById(sysIotModelDto.getId());
deleteModelCache(sysIotModelDto.getId());
}
@ -181,7 +183,7 @@ public class SysIotModelServiceImpl implements SysIotModelService {
addModelFieldCache(sysIotModelField);
SysIotModelFieldVo sysIotModelFieldVo = new SysIotModelFieldVo();
BeanCopyUtils.copy(sysIotModelField, sysIotModelFieldVo);
sysIotModelFieldVo.setAttributeCode(sysIotModelFieldDto.getAttributeCode().toLowerCase());
sysIotModelFieldVo.setAttributeCode(sysIotModelFieldDto.getAttributeCode());
return sysIotModelFieldVo;
}
@ -192,7 +194,7 @@ public class SysIotModelServiceImpl implements SysIotModelService {
SysUserVo sysUserVo = (SysUserVo) StpUtil.getTokenSession().get(SessionUtil.SESSION_USER_KEY);
sysIotModelField.setUpdatedTime(new Date());
sysIotModelField.setUpdatedBy(sysUserVo.getAccount());
sysIotModelField.setAttributeCode(sysIotModelFieldDto.getAttributeCode().toLowerCase());
sysIotModelField.setAttributeCode(sysIotModelFieldDto.getAttributeCode());
if (sysIotModelFieldDto.getAttributeType() == 140) {
sysIotModelField.setDataType("tinyint");
}
@ -255,7 +257,7 @@ public class SysIotModelServiceImpl implements SysIotModelService {
sysIotModelServiceMapper.insert(sysIotModelServices);
SysIotModelServiceVo sysIotModelServiceVo = new SysIotModelServiceVo();
BeanCopyUtils.copy(sysIotModelServices, sysIotModelServiceVo);
sysIotModelServiceVo.setServiceCode(sysIotModelServiceDto.getServiceCode().toLowerCase());
sysIotModelServiceVo.setServiceCode(sysIotModelServiceDto.getServiceCode());
return sysIotModelServiceVo;
}
@ -266,7 +268,7 @@ public class SysIotModelServiceImpl implements SysIotModelService {
SysUserVo sysUserVo = (SysUserVo) StpUtil.getTokenSession().get(SessionUtil.SESSION_USER_KEY);
sysIotModelServices.setUpdatedTime(new Date());
sysIotModelServices.setUpdatedBy(sysUserVo.getAccount());
sysIotModelServices.setServiceCode(sysIotModelServiceDto.getServiceCode().toLowerCase());
sysIotModelServices.setServiceCode(sysIotModelServiceDto.getServiceCode());
SysIotModelServiceVo sysIotModelServiceQuery = sysIotModelServiceMapper.selectByServiceCode(sysIotModelServiceDto.getIotModelId(), sysIotModelServiceDto.getServiceCode());
if (!(sysIotModelServiceQuery == null)) {
@ -360,7 +362,7 @@ public class SysIotModelServiceImpl implements SysIotModelService {
for (List<Object> row : list) {
// 遍历sheet页中记录构造需要导入的对象
SysIotModelServices services = new SysIotModelServices();
services.setServiceCode(row.get(3).toString().toLowerCase());
services.setServiceCode(row.get(3).toString());
services.setServiceName(row.get(4).toString());
services.setServiceType(Integer.valueOf(row.get(5).toString()));
services.setPorder(Integer.valueOf(row.get(6).toString()));
@ -497,17 +499,20 @@ public class SysIotModelServiceImpl implements SysIotModelService {
}
private static void buildFieldInfo(String iotModelId, List<Object> row, SysIotModelField field) {
if (row.get(3).equals("") || row.get(4).equals("") || row.get(5).equals("") || row.get(7).equals("") || row.get(9).equals("") || row.get(11).equals("")) {
//参数校验
boolean allNotEmpty = ObjectUtil.isAllNotEmpty(row.get(3), row.get(4), row.get(5), row.get(7), row.get(9), row.get(11));
if (!allNotEmpty) {
throw new ServiceException("字段不可为空请检查excel文件{}" + row);
}
field.setAttributeCode(row.get(3).toString().toLowerCase());
field.setAttributeCode(row.get(3).toString());
field.setAttributeName(row.get(4).toString());
field.setAttributeType(Integer.valueOf(row.get(5).toString()));
field.setUnit(row.get(6).equals("") ? null : row.get(6).toString());
//row6,8,10 转换前校验
field.setUnit(ObjectUtil.isEmpty(row.get(6)) ? null : row.get(6).toString());
field.setPorder(Integer.valueOf(row.get(7).toString()));
field.setSubSystem(row.get(8).equals("") ? null : row.get(8).toString());
field.setSubSystem(ObjectUtil.isEmpty(row.get(8)) ? null : row.get(8).toString());
field.setDataType(row.get(9).toString());
field.setVisible(row.get(10).equals("") ? null : Integer.valueOf(row.get(10).toString()));
field.setVisible(ObjectUtil.isEmpty(row.get(10)) ? null : Integer.valueOf(row.get(10).toString()));
field.setHighSpeed(Integer.valueOf(row.get(11).toString()));
field.setIotModelId(Long.valueOf(iotModelId));
}
@ -591,11 +596,24 @@ public class SysIotModelServiceImpl implements SysIotModelService {
String modelCode = dataService.iotModelMap.get(sysIotModelField.getIotModelId().toString());
if (sysIotModelField.getHighSpeed() == 0) {
Map<String, Object> map = dataService.lowIotFieldMap.get(modelCode);
map.put(sysIotModelField.getAttributeCode(), sysIotModelField.getDataType());
if (map == null){
Map<String, Object> cacheFieldMap = new HashMap<>();
cacheFieldMap.put(sysIotModelField.getAttributeCode(), sysIotModelField.getDataType());
dataService.lowIotFieldMap.put(modelCode,cacheFieldMap);
}
else {
map.put(sysIotModelField.getAttributeCode(), sysIotModelField.getDataType());
}
}
if (sysIotModelField.getHighSpeed() == 1) {
Map<String, Object> map = dataService.highIotFieldMap.get(modelCode);
map.put(sysIotModelField.getAttributeCode(), sysIotModelField.getDataType());
if (map == null){
Map<String, Object> cacheFieldMap = new HashMap<>();
cacheFieldMap.put(sysIotModelField.getAttributeCode(), sysIotModelField.getDataType());
dataService.highIotFieldMap.put(modelCode,cacheFieldMap);
}else {
map.put(sysIotModelField.getAttributeCode(), sysIotModelField.getDataType());
}
}
}
@ -621,4 +639,11 @@ public class SysIotModelServiceImpl implements SysIotModelService {
}
}
private void addModelCache(SysIotModel sysIotModel){
dataService.iotModelMap.put(sysIotModel.getId().toString(), sysIotModel.getIotModelCode());
}
private void deleteModelCache(Long irn){
dataService.iotModelMap.remove(irn.toString());
}
}

View File

@ -85,8 +85,8 @@ public class SysNodeController {
/** 配置下发 */
@PostMapping("/configUpdate")
public R<?> configUpdate() {
dataService.sendTerminalConfig(Long.valueOf(1));
public R<?> configUpdate(@RequestBody SysNodeDto sysNodeDto) {
dataService.sendTerminalConfig(sysNodeDto.getId());
return R.success();
}

View File

@ -462,7 +462,7 @@ public class TDEngineService {
List<Long> timeList = new ArrayList<>();
timeList.add(rs.getTimestamp(1).getTime());
List<Object> valueList = new ArrayList<>();
valueList.add(rs.getObject(fieldList.get(i)));
valueList.add(rs.getObject(fieldList.get(i).toLowerCase()));
map.put("times",timeList);
map.put("values",valueList);
valueMap.put(fieldList.get(i),map);
@ -471,7 +471,7 @@ public class TDEngineService {
List<Long> times = (List<Long>) map.get("times");
List<Object> values = (List<Object>) map.get("values");
times.add(rs.getTimestamp(1).getTime());
values.add(rs.getObject(fieldList.get(i)));
values.add(rs.getObject(fieldList.get(i).toLowerCase()));
}
}
}

View File

@ -0,0 +1,49 @@
package com.das.modules.page.controller;
import com.das.common.result.R;
import com.das.modules.page.domian.HomeWindFarmRealDataVo;
import com.das.modules.page.domian.HomeWindTurbineMatrixDataVoVo;
import com.das.modules.page.domian.dto.WindFarmRealDataDto;
import com.das.modules.page.service.HomeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 首页相关Controller
*/
@Slf4j
@RequestMapping("/api/home")
@RestController
public class HomeController {
@Autowired
private HomeService homeService;
/**
* 首页风机矩阵数据
* @return 风机矩阵数据
*/
@PostMapping("/getWindTurbineMatrixData")
public R<List<HomeWindTurbineMatrixDataVoVo>> getWindTurbineMatrixData() {
return R.success(homeService.getWindTurbineMatrixData());
}
/**
* 获取风电场的实时数据
* @param windFarmRealDataDto
* @return
*/
@PostMapping("/getWindFarmRealData")
public R<HomeWindFarmRealDataVo> getWindFarmRealData(@RequestBody WindFarmRealDataDto windFarmRealDataDto) {
return R.success(homeService.getWindFarmRealData(windFarmRealDataDto));
}
}

View File

@ -0,0 +1,18 @@
package com.das.modules.page.domian;
import lombok.Data;
import java.util.Map;
@Data
public class HomeWindFarmRealDataVo {
/**
* 风电场id
*/
private Long windFarmId;
private Map<String,Object> attributeMap;
}

View File

@ -0,0 +1,38 @@
package com.das.modules.page.domian;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import java.util.Map;
/**
* 首页风机矩阵
*/
@Data
public class HomeWindTurbineMatrixDataVoVo {
@JsonSerialize(using = ToStringSerializer.class)
private Long irn;
private String name;
@JsonSerialize(using = ToStringSerializer.class)
private Long modelId;
private String model;
private String belongLine;
/**
* 是否为标杆机组
*/
private Integer standard;
/**
* 额定容量
*/
private Double nominalCapacity;
private Map<String,Object> attributeMap;
}

View File

@ -0,0 +1,24 @@
package com.das.modules.page.domian.dto;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import java.io.Serializable;
@Data
public class WindFarmRealDataDto implements Serializable {
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
/**
* 风场id
*/
private Long windFarmId;
/**
* 风场名称
*/
private String WindFarmName;
}

View File

@ -0,0 +1,27 @@
package com.das.modules.page.service;
import com.das.modules.page.domian.HomeWindFarmRealDataVo;
import com.das.modules.page.domian.HomeWindTurbineMatrixDataVoVo;
import com.das.modules.page.domian.dto.WindFarmRealDataDto;
import java.util.List;
public interface HomeService {
/**
* 接口1 首页风机矩阵数据
* @return 风机矩阵数据
*/
List<HomeWindTurbineMatrixDataVoVo> getWindTurbineMatrixData();
/**
* 接口2 获取风电场的实时数据
* @param windFarmRealDataDto
* @return 页面左上角风场概况,页面右上角发电量概况
*/
HomeWindFarmRealDataVo getWindFarmRealData(WindFarmRealDataDto windFarmRealDataDto);
}

View File

@ -0,0 +1,139 @@
package com.das.modules.page.service.impl;
import com.das.common.constant.EquipmentTypeIds;
import com.das.modules.data.domain.SnapshotValueQueryParam;
import com.das.modules.data.service.DataService;
import com.das.modules.equipment.domain.dto.SysEquipmentDto;
import com.das.modules.equipment.domain.vo.SysEquipmentVo;
import com.das.modules.equipment.mapper.SysEquipmentMapper;
import com.das.modules.page.domian.HomeWindFarmRealDataVo;
import com.das.modules.page.domian.HomeWindTurbineMatrixDataVoVo;
import com.das.modules.page.domian.dto.WindFarmRealDataDto;
import com.das.modules.page.service.HomeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
public class HomeServiceImpl implements HomeService {
@Autowired
SysEquipmentMapper sysEquipmentMapper;
@Autowired
private DataService dataService;
/**
* 接口1 首页风机矩阵数据
*
* @return 风机矩阵数据
*/
@Override
public List<HomeWindTurbineMatrixDataVoVo> getWindTurbineMatrixData() {
SysEquipmentDto sysEquipmentDto = new SysEquipmentDto();
sysEquipmentDto.setObjectType(EquipmentTypeIds.EQUIPMENT_TYPE_STATION_WTG);
//获取所有风机设备
List<SysEquipmentVo> sysEquipmentVos = sysEquipmentMapper.querySysEquipmentList(sysEquipmentDto);
//风机返回数据列表
List<HomeWindTurbineMatrixDataVoVo> homeWindRealTimeVoList = new ArrayList<>();
List<SnapshotValueQueryParam> paramList = new ArrayList<>();
//构建需要查询的物模型属
List<String> attributesList = new ArrayList<>();
//风速
attributesList.add("iwindspeed");
//风机状态判断条件所需的字段iturbineoperationmodeiYPLevelGridLostDetected可能会调整
//风机状态
attributesList.add("iturbineoperationmode");
//偏航运行模式
attributesList.add("iYPLevel");
//风机电网掉电
attributesList.add("GridLostDetected");
//有功功率(MW)
attributesList.add("igenpower");
//当天可利用率
//attributesList.add("iavailabillitytoday");
//日发电量(kwh)
attributesList.add("ikwhthisday");
//总发电量(万kwh)
//attributesList.add("ikwhoverall");
for (SysEquipmentVo item : sysEquipmentVos) {
//构建查询属性参数
SnapshotValueQueryParam snapshotValueQueryParam = new SnapshotValueQueryParam();
snapshotValueQueryParam.setAttributes(attributesList);
snapshotValueQueryParam.setDeviceId(item.getId().toString());
paramList.add(snapshotValueQueryParam);
//构建风机数据返回
HomeWindTurbineMatrixDataVoVo homeWindRealTimeVoResult = new HomeWindTurbineMatrixDataVoVo();
homeWindRealTimeVoResult.setIrn(item.getId());
homeWindRealTimeVoResult.setName(item.getName());
homeWindRealTimeVoResult.setModel(item.getModel());
homeWindRealTimeVoResult.setModelId(item.getIotModelId());
homeWindRealTimeVoResult.setBelongLine(item.getBelongLine());
homeWindRealTimeVoResult.setStandard(item.getStandard());
homeWindRealTimeVoResult.setNominalCapacity(item.getNominalCapacity());
homeWindRealTimeVoList.add(homeWindRealTimeVoResult);
}
//获取设备测点数据
Map<String, Map<String, Object>> map = dataService.querySnapshotValues(paramList);
for (HomeWindTurbineMatrixDataVoVo item : homeWindRealTimeVoList) {
item.setAttributeMap(map.get(item.getIrn().toString()));
}
return homeWindRealTimeVoList;
}
/**
* 接口2 获取风电场的实时数据
* @param windFarmRealDataDto
* @return 页面左上角风场概况,页面右上角发电量概况
*/
@Override
public HomeWindFarmRealDataVo getWindFarmRealData(WindFarmRealDataDto windFarmRealDataDto) {
Long windFarmId = windFarmRealDataDto.getWindFarmId();
//查询数据库中风电场设备取第一个风电场
if (windFarmId == null) {
SysEquipmentDto sysEquipmentDto = new SysEquipmentDto();
sysEquipmentDto.setObjectType(EquipmentTypeIds.EQUIPMENT_TYPE_WIND_FARM);
SysEquipmentVo sysEquipmentVo1 = sysEquipmentMapper.queryWindFarm(sysEquipmentDto);
windFarmId = sysEquipmentVo1.getId();
}
List<SnapshotValueQueryParam> paramList = new ArrayList<>();
//构建需要查询的物模型属
List<String> attributesList = new ArrayList<>();
//功率
attributesList.add("windfarmactivepower");
//平均风速
attributesList.add("windfarmavgwindspeed");
//日利用小时
attributesList.add("windfarmdayoperationhours");
//月利用小时
attributesList.add("windfarmmonthoperationhours");
//日发电量
attributesList.add("windfarmdayprodenergy");
//月发电量
attributesList.add("windfarmmonthprodenergy");
//年发电量
attributesList.add("windfarmyearprodenergy");
//总发电量
attributesList.add("windfarmtotalprodenergy");
//构建查询属性参数
SnapshotValueQueryParam snapshotValueQueryParam = new SnapshotValueQueryParam();
snapshotValueQueryParam.setAttributes(attributesList);
snapshotValueQueryParam.setDeviceId(windFarmId.toString());
paramList.add(snapshotValueQueryParam);
//获取设备测点数据
Map<String, Map<String, Object>> map = dataService.querySnapshotValues(paramList);
HomeWindFarmRealDataVo homeWindFarmRealDataVo = new HomeWindFarmRealDataVo();
homeWindFarmRealDataVo.setWindFarmId(windFarmId);
if (map !=null){
homeWindFarmRealDataVo.setAttributeMap(map.get(windFarmId.toString()));
}
return homeWindFarmRealDataVo;
}
}

View File

@ -141,5 +141,33 @@
select se.id as irn,se.name,se.model,se.belong_line as belongLine, se.iot_model_id as modelId from sys_equipment se where se.object_type = #{objectType} order by se.name
</select>
<select id="queryWindFarm" resultMap="SysEquipmentMap">
select t.* from sys_equipment t
<where>
<if test="info.iotModelId != null and info.iotModelId != ''">
and t.iot_model_id = #{info.iotModelId}
</if>
<if test="info.orgId != null and info.orgId != ''">
and t.org_id = #{info.orgId}
</if>
<if test="info.parentEquipmentId != null and info.parentEquipmentId != ''">
and t.parent_equipment_id = #{info.parentEquipmentId}
</if>
<if test="info.name != null and info.name != ''">
and t.name like concat('%',#{info.name},'%')
</if>
<if test="info.code != null and info.code != ''">
and t.code like concat('%',#{info.code},'%')
</if>
<if test="info.objectType != null and info.objectType != ''">
and t.object_type = #{info.objectType}
</if>
<if test="info.id != null and info.id != ''">
and t.id = #{info.id}
</if>
</where>
order by t.name
limit 1
</select>
</mapper>

View File

@ -25,13 +25,12 @@
<if test="info.attributeCode != null and info.attributeCode != ''">
and t.attribute_code like concat('%',#{info.attributeCode},'%')
</if>
<if test="info.orderColumn != null and info.orderType != ''">
order by ${info.orderColumn} ${info.orderType}
</if>
<if test="info.attributeType != null and info.attributeType != ''">
and t.attribute_type = #{info.attributeType}
</if>
<if test="info.orderColumn != null and info.orderType != ''">
order by ${info.orderColumn} ${info.orderType}
</if>
<if test="info.orderColumn == null or info.orderColumn == '' or info.orderType == null or info.orderType == ''">
order by t.porder asc
</if>

View File

@ -0,0 +1,37 @@
import createAxios from '/@/utils/axios'
export const queryWindTurbinesPages = () => {
return createAxios({
url: '/api/page/turbines/queryWindTurbinesPages',
method: 'get',
})
}
export const historyReq = (data: {
devices: {
deviceId: string
attributes: string
}
startTime: string
endTime: string
}) => {
return createAxios({
url: '/api/data/history',
method: 'post',
data: data,
})
}
export const runAirBlowerReq = (
data: {
deviceId: string
serviceName: string
opValue: 1 | 0
}[]
) => {
return createAxios({
url: '/api/page/turbines/windTurbinesControl',
method: 'post',
data: data,
})
}

View File

@ -0,0 +1,15 @@
export default {
PowerCurveAnalysis: '功率曲线分析',
trendAnalysis: '趋势分析',
trendComparison: '趋势对比',
deviceId: '风机',
attributes: '测点名称',
interval: '间隔',
search: '查询',
import: '下载',
export: '导出',
time: '时间',
max: '最大值',
min: '最小值',
average: '平均值',
}

View File

@ -70,18 +70,30 @@ import { ElMessage, TableInstance, TreeInstance } from 'element-plus'
import { Search } from '@element-plus/icons-vue'
import { AlarmsFieldsEnums, AlarmsTableType, GetAlarmsTableParam } from './type'
import { getAlarmListReq } from '/@/api/backend/alarms/request'
import { equipList } from '/@/api/backend/realData/request.ts'
import { debounce, cloneDeep } from 'lodash'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
import { useAdminInfo } from '/@/stores/adminInfo'
const adminInfo = useAdminInfo()
//
const timeRange = ref([])
const shortcuts = [
{
text: '今天',
value: () => {
const end = new Date()
const start = new Date()
return [start, end]
},
},
{
text: '昨天',
value: () => {
const end = new Date()
end.setDate(end.getDate() - 1)
const start = new Date()
start.setDate(start.getDate() - 1)
return [start, end]
@ -92,36 +104,27 @@ const shortcuts = [
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 3)
start.setDate(start.getDate() - 2)
return [start, end]
},
},
{
text: '周',
text: '周',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 7)
return [start, end]
return getDateRange('week')
},
},
{
text: '上个月',
text: '月',
value: () => {
const end = new Date()
const start = new Date()
start.setMonth(start.getMonth() - 1)
return [start, end]
return getDateRange('month')
},
},
]
//
const airBlowerNumberValue = ref('')
const airBlowerList = ref([
{ label: 'sc-001', value: '001' },
{ label: 'sc-001', value: '002' },
])
const airBlowerList = ref([{ label: '', value: '' }])
//
const alarmTypeValue = ref('')
const alarmTypes = ref([
@ -147,9 +150,9 @@ const alarmsTableData = ref<AlarmsTableType[]>([])
//
const paginationOptions = reactive({
current: 1,
pageSize: 10,
pageSize: 20,
total: 0,
pageSizes: [10, 20, 30],
pageSizes: [20, 50, 100],
})
const getcurrentPage = () => {
getalarmsList()
@ -201,27 +204,41 @@ const okSubmit = (val) => {
console.log(val)
getalarmsList()
}
const getTodayAndYesterday = () => {
const getDateRange = (type: 'week' | 'month') => {
const today = new Date()
const yesterday = new Date()
yesterday.setDate(today.getDate() - 1)
const formatDate = (date) => {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
if (type === 'week') {
const dayOfWeek = today.getDay()
const startOfWeek = new Date(today)
startOfWeek.setDate(today.getDate() - dayOfWeek + (dayOfWeek === 0 ? -6 : 1))
startOfWeek.setHours(0, 0, 0, 0)
const endOfWeek = new Date(startOfWeek)
endOfWeek.setDate(startOfWeek.getDate() + 6)
endOfWeek.setHours(23, 59, 59, 999)
return [startOfWeek, endOfWeek]
}
return {
today: formatDate(today),
yesterday: formatDate(yesterday),
if (type === 'month') {
const startOfMonth = new Date(today.getFullYear(), today.getMonth(), 1)
startOfMonth.setHours(0, 0, 0, 0)
const endOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0)
endOfMonth.setHours(23, 59, 59, 999)
return [startOfMonth, endOfMonth]
}
}
onMounted(() => {
console.log(getTodayAndYesterday(), 999)
// timeRange[0] = getTodayAndYesterday().yesterday
// timeRange[1] = getTodayAndYesterday().today
onMounted(() => {
equipList({
// orgId: adminInfo.orgid,
objectType: 10002,
}).then((res) => {
if (res.code == 200) {
airBlowerList.value = res.data.map((item) => {
return {
label: item.code,
value: item.id,
}
})
}
})
getalarmsList()
})
</script>

View File

@ -7,7 +7,7 @@
<div class="transferLeft">
<div class="transferHeader">
<span class="transferTitle">可添加的测点</span>
<el-radio-group v-model="radioActiveName" @change="handleradioClose">
<el-radio-group v-model="radioActiveName" @change="handleradioChange">
<el-radio value="138">模拟量</el-radio>
<el-radio value="140">状态量</el-radio>
</el-radio-group>
@ -16,21 +16,24 @@
<el-table class="tablePart"
ref="tableRef"
:data="modalTbleData"
@selectionChange="selectTable">
<el-table-column type="selection" width="55" />
<el-table-column prop="attributeCode" label="名称" />
<el-table-column prop="attributeName" label="描述" />
@selectionChange="selectTable"
:row-key="getRowKey">
<el-table-column type="selection" width="55" :reserve-selection="true"/>
<el-table-column prop="porder" label="序号" width="60" />
<el-table-column prop="attributeCode" sortable label="名称" />
<el-table-column prop="attributeName" sortable label="描述" />
</el-table>
<div class="mainFooter" style="display: flex; justify-content: left">
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="currentPageSize"
:total="pageTotal"
:page-sizes="pagePagination"
background
:pager-count="6"
:pager-count="5"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
layout="prev, pager, next"
layout="prev, pager, next,sizes"
></el-pagination>
</div>
</el-main>
@ -83,7 +86,7 @@
<div class="realConter">
<div class="header">
<el-button type="primary" :icon="Crop" class="defaultBtn" @click="openMeasure">测点选择</el-button>
<el-button style="color: rgb(0, 100, 170);;" :icon="Download" class="defaultBtn" @click="downFun(tableColumn,tableDatadown)">数据导出</el-button>
<el-button style="color: rgb(0, 100, 170);;" :icon="Download" class="defaultBtn" @click="downFun(tableColumn,tableData)">数据导出</el-button>
<div class="selectPart">
<span>自动更新</span>
<el-switch
@ -109,21 +112,80 @@ import {Crop,Download,Top,Bottom} from '@element-plus/icons-vue'
import {onMounted, onUnmounted, reactive, ref, watch,computed} from 'vue'
import {ElMessage} from 'element-plus'
import {equipList,getModelAttributeList,getsnapshotData} from "/@/api/backend/realData/request.ts";
import * as console from "console";
const tableData = ref()
const tableItem0: any = {
label: '风机列表',
prop: 'code',
align: 'center',
}
const tableColumn=ref([
{ ...tableItem0 }
])
const tableDownData=ref()
const tableItem0: any = [
{
label: '风机列表',
prop: 'code',
align: 'center',
},
{
label: '风速 (m/s)',
prop: 'iwindspeed',
align: 'center',
custom: 'header',
},
{
label: '有功功率 (MW)',
prop: 'igenpower',
align: 'center',
custom: 'header',
},
{
label: '日发电量 (kWh)',
prop: 'ikwhthisday',
align: 'center',
custom: 'header',
},
{
label: '总发电量 (万kWh)',
prop: 'ikwhoverall',
align: 'center',
custom: 'header',
},
{
label: '机舱角度',
prop: 'ivanedirection',
align: 'center',
},
{
label: '叶轮转速 (rmp)',
prop: 'irotorspeed',
align: 'center',
custom: 'header',
},
{
label: '发电机转速 (rmp)',
prop: 'igenspeed',
align: 'center',
custom: 'header',
},
{
label: '机舱温度 (℃)',
prop: 'itempnacelle_1sec',
align: 'center',
custom: 'header',
},
{
label: '主油路压力 (kpa)',
prop: 'ihydrpress',
align: 'center',
custom: 'header',
},
{
label: '变桨角度',
prop: 'ipitchangle',
align: 'center',
}
]
const tableColumn=ref(
tableItem0
)
const deviceList = ref()
const tableList=ref()
var modalTbleData=ref()
const modalTbleData=ref<any[]>([])
const devicelistData = reactive({
objectType: 10002,
})
@ -136,15 +198,45 @@ const deviceQuery = (data: any) => {
deviceList.value = res.data
tableData.value = res.data
iotModelId.value=res.data[0].iotModelId
tableList.value = res.data
const deviceId=deviceList.value.map((item) => item.id);
deviceId.forEach((item,index) => {
objparms.deviceId=item
objparms.attributes=tableColumn.value.map((item1)=>item1.prop)
snapshotParms.push({...objparms})
})
getsnapshotData(snapshotParms).then((res) => {
if (res.code == 200) {
const tsnapshotVoObject: any = res.data;
const tsnapshotVoMap = new Map(Object.entries(tsnapshotVoObject));
const updatedTableData = tableColumn.value.reduce((acc, item1) => {
acc.forEach((item, i) => {
const itemKey = item.id;
if (tsnapshotVoMap.has(itemKey)) {
const tsnapshotVoItem = tsnapshotVoMap.get(itemKey);
//const attributeCodeLower = item1.attributeCode?.toLowerCase();
const attributeCodeLower = item1.prop;
if(attributeCodeLower!='code'){
if (attributeCodeLower) {
const value = tsnapshotVoItem[attributeCodeLower];
const formattedValue = value !== undefined ? (value % 1 === 0 ? value : value.toFixed(3)) : '-';
acc[i] = { ...item, [attributeCodeLower]: formattedValue };
}
}
}
});
return acc;
}, [...tableData.value]);
tableData.value = updatedTableData;
} else {
ElMessage.error({
message: res.msg,
type: 'error',
})
}
})
})
}
/*const filteredItems = computed(() => {
return tableList.value.map(item => ({
code: item.code
}));
});*/
const queryListData = reactive({
pageSize: 20,
@ -166,7 +258,7 @@ const modelAttributeList=(data: any) =>{
})
}
const Statistic=ref(0)
interface TableType {
attributeCode:string
@ -183,12 +275,26 @@ interface TableType {
visible:number | null
}
const tableRef=ref()
const multipleSelection = ref<TableType[]>([])
const selectTable = (selected: TableType[]) => {
Statistic.value=selected.length
multipleSelection.value =selected
selectpageTotal.value=selected.length
const Statistic = computed(() => multipleSelection.value.length)
const selectTable = (selected: TableType[] | null) => {
if (!selected) {
console.error('Selected is null or undefined')
return
}
multipleSelection.value = selected
}
const getRowKey = (row) => row.id;
const visible = ref(false)
const openMeasure=() =>{
visible.value=true
queryListData.iotModelId=iotModelId.value
queryListData.attributeType=radioActiveName.value
modelAttributeList(queryListData)
}
const moveUp = (index:number) => {
if (index > 0) {
const temp = multipleSelection.value[index];
@ -209,12 +315,13 @@ const moveDown = (index:number) => {
const clearList=() => {
Statistic.value=0
multipleSelection.value = [];
tableRef.value.clearSelection()
queryListData.iotModelId=iotModelId.value
queryListData.attributeType=radioActiveName.value
modelAttributeList(queryListData)
}
const handleradioClose=() => {
multipleSelection.value = [];
const handleradioChange=() => {
//multipleSelection.value = [];
queryListData.iotModelId=iotModelId.value
queryListData.attributeType=radioActiveName.value
modelAttributeList(queryListData)
@ -226,6 +333,7 @@ watch(autoUpdate, (newVal: boolean) => {
if (autoUpdateInterval.value) return
ElMessage.success('开启自动刷新')
autoUpdateInterval.value = setInterval(() => {
deviceQuery(devicelistData)
getTableData()
}, 2000)
} else {
@ -238,6 +346,7 @@ watch(autoUpdate, (newVal: boolean) => {
const currentPage = ref(1)
const currentPageSize = ref(20)
const pageTotal = ref(0)
const pagePagination = ref([20, 50, 100])
const handleSizeChange = (val: number) => {
queryListData.pageSize = val
queryListData.iotModelId=iotModelId.value
@ -265,13 +374,7 @@ const selecthandleCurrentChange = (val: number) => {
modelAttributeList(queryListData)*/
}
const visible = ref(false)
const openMeasure=() =>{
visible.value=true
queryListData.iotModelId=iotModelId.value
queryListData.attributeType=radioActiveName.value
modelAttributeList(queryListData)
}
const handleClose = (done: () => void) => {
visible.value = false
@ -284,18 +387,41 @@ const objparms = reactive({
})
const tableDatadown=ref()
const getTableData = () => {
const deviceId=deviceList.value.map((item) => item.id);
let tableColumnEnds: any = [];
multipleSelection.value.map((item) => {
tableColumnEnds.push({
label: item.attributeName,
prop: item.attributeCode.toLowerCase(),
align: 'center',
})
})
tableColumn.value = [ { ...tableItem0}, ...tableColumnEnds ];
const tableColumnEnds = ref([]);
const tableColumnup = ref([]);
const tableColumnMap = new Map();
tableColumn.value.forEach(item1 => {
if (item1.prop) {
tableColumnMap.set(item1.prop, item1);
tableColumnup.value.push({
label: item1.label,
prop: item1.prop,
align: 'center',
});
}
});
if(multipleSelection.value.length === 0){
tableColumn.value = [...tableItem0, ...tableColumnEnds.value];
}else{
multipleSelection.value.forEach(item => {
if (item.attributeCode) {
const attributeCodeLower = item.attributeCode.toLowerCase();
if (!tableColumnMap.has(attributeCodeLower)) {
tableColumnEnds.value.push({
label: item.attributeName+'\n'+item.unit,
prop: attributeCodeLower,
align: 'center',
});
}
}
});
tableColumn.value = [...tableColumnup.value, ...tableColumnEnds.value];
}
//tableColumn.value = [...tableItem0, ...tableColumnEnds.value];
deviceId.forEach((item,index) => {
objparms.deviceId=item
objparms.attributes=multipleSelection.value.map((item) => item.attributeCode)
@ -306,25 +432,12 @@ const getTableData = () => {
const tsnapshotVoObject: any = res.data;
multipleSelection.value.map((item1: any) => {
tableData.value.forEach((item: any, i: number, arr: any) => {
debugger
for (const itemKey in tsnapshotVoObject) {
if (item.id === itemKey) {
const attributeCodeLower = item1.attributeCode?.toLowerCase();
const value = tsnapshotVoObject[itemKey]?.[attributeCodeLower];
const formattedValue =value ? (value % 1 === 0 ? value : value.toFixed(3)) : '-';
const { code } = item;
arr[i] = { ...item, [attributeCodeLower]: formattedValue };
/*tableList.value.map(item => ({
code: item.code,
[attributeCodeLower]:formattedValue
}));*/
// tableList.value.forEach((item2: any, j: number, arr2: any) => {
// return{
// code: item2.code,
// [attributeCodeLower]:formattedValue
// }
// })
//tableDatadown.value=tableList.value
}
}
});
@ -342,125 +455,45 @@ const sureBtn = (done: () => void) => {
getTableData()
visible.value = false
}
const transferred = (data:any) => {
return data.replace(/<br>/g, "\r\n").replace(/&gt;/g, ">");
}
/*const downFun=(tableColumn,tableData)=>{
debugger
const downFun=(tableColumn,tableData)=>{
const itemsWithoutAge = tableData.map(item => {
const { id, belongLine, iotModelId, location,madeinFactory,model,name,nominalCapacity,objectType,parentEquipmentId,remarks,standard,...rest } = item;
return rest;
});
let addobj = {}
// 2.1 rowData
try {
tableColumn.map((v, i) => {
//addobj['rowData' + i] = v.prop
addobj['rowData' + i] = v.label
})
} catch (error) {
ElMessage.error('请填写tableLable表头属性')
return
}
/!*if(tableData.length == 0) {
ElMessage.error('请填写tableData表格数据属性')
return
}*!/
// 2.2JSON
let tableDatadown = JSON.parse(JSON.stringify(tableData))
// 2.3
tableColumn.map((v, i) => {
addobj['rowData' + i] = v.label
})
let tableDatadown = JSON.parse(JSON.stringify(itemsWithoutAge))
tableDatadown.unshift(addobj)
/!*if (tableDatadown.length === 0) {
return '';
}
let lines = [];*!/
// 2.4
let str = ``;
/!* for (let i = 0; i < tableDatadown.length; i++) {
let row = [];
for (let item in tableDatadown[i]) {
let value = tableDatadown[i][item];
if (typeof value === 'string') {
value = value.replace(/\n/g, ' ').replace(/,/g, '');
} else {
value = String(value).replace(/\n/g, ' ').replace(/,/g, '');
}
row.push(value);
}
lines.push(row.join('\t'));
}
let str = lines.join('\n');*!/
// 2.5\t
for(let i = 0; i < tableDatadown.length; i++) {
for(let item in tableDatadown[i]) {
// 2.5.1
//tableDatadown[i][item] = tableDatadown[i][item].replace(/\n/g, ' ')
//tableDatadown[i][item] = tableDatadown[i][item].replace(/,/g, '') //
if (typeof tableDatadown[i][item] === 'string') {
tableDatadown[i][item] = tableDatadown[i][item].replace(/[\n,]/g, match => match === '\n' ? ' ' : '');
} else {
console.warn(`tableDatadown[${i}][${item}] is not a string`);
}
str += `${tableDatadown[i][item] + '\t'},`;
}
str += '\n';
}
// 2.6encodeURIComponent
let uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(str);
// 2.7a
let link = document.createElement('a');
link.href = uri;
// 2.8
link.download = Date.now() + ".csv";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
/!*let fileName = Date.now() + ".csv";//使用当前时间戳作为文件名
var columnDelimiter = ","; //
var lineDelimiter = "\r\n"; //
var table__header = document.getElementsByClassName(
"el-table__header"
)[0];//
var table__body = document.getElementsByClassName("el-table__body")[0];//tbody
var head = table__header.tHead;
let result = "";//
var ths = head.getElementsByTagName("span");
for (let i = 0, l = ths.length; i < l; i++) {
result +=
transferred('"' + ths[i].innerHTML + '"') + columnDelimiter;//
}
result += lineDelimiter;// 使"\r\n"
var trs = table__body.getElementsByTagName("tr");
for (let i = 0, l = trs.length; i < l; i++) {
let spandata = trs[i].getElementsByTagName("span");
for (let i = 0, l = spandata.length; i < l; i++) {
result +=
transferred('"' + spandata[i].innerHTML + '"') +
columnDelimiter;
}
result += lineDelimiter;
}
var blob = new Blob(["\uFEFF" + result], { type: "text/csv;" });//
var downloadLink = document.createElement("a");
if ("download" in downloadLink) {
var url = URL.createObjectURL(blob);
downloadLink.href = url;
downloadLink.download = fileName;
downloadLink.hidden = true;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
}*!/
/!*else {
if (navigator.msSaveBlob) {
//IE10+
navigator.msSaveBlob(blob, fileName);
}
}*!/
}*/
}
onUnmounted(() => {
autoUpdateInterval.value && clearInterval(autoUpdateInterval.value)
autoUpdateInterval.value = null
})
onMounted(() => {
//deviceQuery(objectType)
deviceQuery(devicelistData)
modelAttributeList(queryListData)
})
</script>

View File

@ -0,0 +1,224 @@
<template>
<div class="measurement">
<el-table :columns="tableColumn" :data="tableData" @sort-change="sortChange" max-height="495">
<el-table-column
v-for="item in tableColumn"
:key="item.prop"
:label="item.label"
:prop="item.prop"
:width="item.width ?? ''"
:align="item.align"
:sortable="item.sortable"
>
<template #default="scope">
<el-radio
v-if="item.prop === 'index'"
:label="scope.$index"
v-model="selectedIndex"
@change="handleRadioChange(scope.$index, scope.row)"
>&nbsp;</el-radio
>
</template>
</el-table-column>
</el-table>
<div>
<el-pagination
v-model:current-page="pageSetting.current"
v-model:page-size="pageSetting.pageSize"
:total="pageSetting.total"
:page-sizes="pageSetting.pageSizes"
background
:pager-count="7"
layout="prev, pager, next, jumper,sizes,total"
@change="getcurrentPage"
></el-pagination>
</div>
</div>
</template>
<script setup lang="ts">
import { reactive, ref, watch, defineEmits } from 'vue'
import { ElMessage } from 'element-plus'
import type { ModelAttributeFieldsEnums, GetModelAttributeType } from '/@/views/backend/auth/model/type'
import { getModelAttributeListReq, getRealValueListReq } from '/@/api/backend/deviceModel/request'
const props = defineProps({
iotModelId: {
type: String,
default: '',
},
deviceId: {
type: String,
default: '',
},
show: {
type: Boolean,
default: false,
},
})
const selectedIndex = ref(null)
const tableColumn = [
{
type: 'selection',
prop: 'index',
width: 55,
},
{
label: '序号',
prop: 'porder',
width: 76,
align: 'center',
sortable: 'custom',
},
{
label: '属性名称',
prop: 'attributeName',
align: 'left',
sortable: 'custom',
},
{
label: '属性编码',
prop: 'attributeCode',
align: 'left',
width: 200,
sortable: 'custom',
},
{
label: '子系统',
prop: 'subSystem',
align: 'left',
width: 110,
sortable: false,
},
]
const tableData = ref<any[]>([])
const emit = defineEmits(['handleRadioChange'])
const handleRadioChange = (index, row) => {
emit('handleRadioChange', row)
console.log(row)
}
const getAttributeList = () => {
console.log(props)
const requestData: GetModelAttributeType = {
iotModelId: props.iotModelId,
pageNum: pageSetting.current,
pageSize: pageSetting.pageSize,
attributeType: '138',
orderColumn: sortData.orderColumn,
orderType: sortData.orderType,
}
console.log('🚀 ~ getAttributeList ~ requestData:', requestData)
console.log(requestData)
return new Promise((resolve) => {
getModelAttributeListReq(requestData)
.then((res) => {
if (res.rows && res.rows.length > 0) {
const codeList: any = []
const data = res.rows!.map((item) => {
codeList.push(item.attributeCode)
return {
...item,
attributeTypeName:
item.attributeType === 138
? '模拟量'
: item.attributeType === 139
? '累积量'
: item.attributeType === 140
? '离散量'
: item.attributeType!,
}
})
pageSetting.total = res.total
resolve({ data, codeList })
} else {
if (res.rows && res.rows.length === 0) {
tableData.value = []
} else {
ElMessage.error(res.msg)
}
}
})
.catch((err) => {
ElMessage.error(err?.response?.data?.msg ?? '查询失败')
})
})
}
const getRealValueList = (data: { deviceId: string; attributes: string[] }, list?: any) => {
return new Promise((resolve) => {
getRealValueListReq([data]).then((res) => {
if (res.success && res.data) {
resolve({ realVal: res.data, list })
}
})
})
}
const getCompleteData = () => {
getAttributeList()
.then(({ data, codeList }: any) => {
return getRealValueList({ deviceId: props.deviceId, attributes: codeList }, data)
})
.then((realData: any) => {
console.log(realData)
const data = realData.list.map((item: any) => {
const realValItem = realData.realVal[props.deviceId]?.[item.attributeCode?.toLowerCase()]
return {
...item,
realTimeValue: realValItem ? (realValItem % 1 === 0 ? realValItem : realValItem.toFixed(3)) : '-',
}
})
tableData.value = data
})
}
const sortData = reactive<{ orderColumn?: keyof typeof ModelAttributeFieldsEnums; orderType?: 'asc' | 'desc' }>({
orderColumn: 'porder',
orderType: 'asc',
})
const sortChange = ({ prop, order }: { prop: keyof typeof ModelAttributeFieldsEnums; order: 'ascending' | 'descending' | null }) => {
const propEnums = {
attributeCode: 'attribute_code',
attributeName: 'attribute_name',
attributeTypeName: 'attribute_type',
porder: 'porder',
serviceCode: 'service_code',
serviceName: 'service_name',
serviceTypeName: 'service_type',
}
const orderType = order === 'ascending' ? 'asc' : order === 'descending' ? 'desc' : undefined
const filed = propEnums[prop as keyof typeof propEnums] as keyof typeof ModelAttributeFieldsEnums
sortData.orderColumn = orderType ? filed : undefined
sortData.orderType = orderType
getCompleteData()
}
const pageSetting = reactive({
current: 1,
pageSize: 20,
total: 0,
pageSizes: [10, 20, 30],
})
const getcurrentPage = () => {
getCompleteData()
}
watch(
() => props.show,
(newVal) => {
if (newVal) {
getCompleteData()
}
},
{
immediate: true,
}
)
</script>
<style scoped></style>

View File

@ -0,0 +1,513 @@
<template>
<div class="statAnalysis">
<el-menu :default-active="activeIndex" class="headerList" mode="horizontal" @select="handleSelect">
<el-menu-item v-for="(item, index) in headerList" :index="index" :key="index"> {{ item }} </el-menu-item>
</el-menu>
<div class="contain">
<el-header class="headerPart">
<div class="topLeft">
<div class="selectPart">
<span>{{ t('statAnalysis.deviceId') }}</span>
<el-select
v-model="statAnalysisSelect.deviceId"
@change="selectstatAnalysis('deviceId')"
:placeholder="'请选择' + t('statAnalysis.deviceId')"
class="statAnalysisSelect"
>
<el-option v-for="v in statAnalysisSelectOptions.deviceId" :key="v.value" :label="v.label" :value="v.value"></el-option>
</el-select>
</div>
<div class="selectPart">
<span>{{ t('statAnalysis.attributes') }}</span>
<el-input
class="statAnalysisSelect"
v-model="statAnalysisSelect.attributes"
@click="showMeasure = true"
:placeholder="'请选择' + t('statAnalysis.attributes')"
></el-input>
</div>
<div class="selectPart">
<span>{{ t('statAnalysis.interval') }}</span>
<el-select
v-model="statAnalysisSelect.interval"
@change="selectstatAnalysis('interval')"
:placeholder="'请选择' + t('statAnalysis.interval')"
class="statAnalysisSelect"
>
<el-option v-for="v in statAnalysisSelectOptions.interval" :key="v.value" :label="v.label" :value="v.value"></el-option>
</el-select>
</div>
</div>
<div class="topRight">
<el-button type="primary" @click="statAnalysisOperate()">{{ t('statAnalysis.search') }}</el-button>
<el-button style="color: #0064aa" @click="statAnalysiImport()">{{ t('statAnalysis.import') }}</el-button>
<el-button style="color: #0064aa" @click="statAnalysisExport()">{{ t('statAnalysis.export') }}</el-button>
</div>
</el-header>
<div class="timeColumns" :class="{ expand: isExpand }">
<div class="headerPart" v-for="(time, index) in times" :key="index">
<div class="topLeft">
<div class="selectPart">
<span>{{ customName }}</span>
<span>{{ t('statAnalysis.time') }}</span>
<el-date-picker
class="datetime-picker"
v-model="times[index]"
:type="statAnalysisSelect.interval == '1d' ? 'daterange' : 'datetimerange'"
:value-format="statAnalysisSelect.interval == '1d' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss'"
:teleported="false"
:shortcuts="shortcuts"
@change="timechange(index)"
/>
</div>
<div class="topLeft">
<div class="selectPart" v-if="index === times.length - 1">
<el-button type="primary" size="small" :icon="Plus" circle @click="addTime(index)"> </el-button>
</div>
<div class="selectPart" v-if="index !== 0">
<el-button type="danger" size="small" :icon="Delete" @click="switchTime(index)" circle />
</div>
<div class="selectPart">
<span>{{ t('statAnalysis.max') }}</span>
<span class="max">11</span>
</div>
<div class="selectPart">
<span>{{ t('statAnalysis.min') }}</span>
<span class="min">22</span>
</div>
<div class="selectPart">
<span>{{ t('statAnalysis.average') }}</span>
<span class="average">33</span>
</div>
</div>
</div>
</div>
</div>
<div v-if="times.length > 2" class="ralIcon" @click="handleClick">
<el-icon :size="20" color="#0064AA"><DArrowRight /></el-icon>
</div>
<div ref="chartContainer" style="width: 100%; height: 400px"></div>
<el-dialog v-model="showMeasure" title="测点名称" :width="800">
<template #header>
<div class="measureSlotHeader">
<span style="font-size: 20px">测点名称</span>
</div>
</template>
<div class="measureSlot">
<MeasurementPage :show="showMeasure" :iotModelId="iotModelId" @handleRadioChange="handleRadioChange"></MeasurementPage>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="showMeasure = false">取消</el-button>
<el-button type="primary" @click="selectstatAnalysisAttributes"> 确认 </el-button>
</span>
</template>
</el-dialog>
</div>
</div>
</template>
<script setup lang="ts">
import { SelectTypeObjType, SelectTypeKeyUnionType, TableDataObjType, TableColumnType } from './type'
import { onUnmounted, reactive, ref, watch, nextTick, onMounted, computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { queryWindTurbinesPages, historyReq } from '/@/api/backend/statAnalysis/request'
import { ElMessage, TableInstance, ElMenu } from 'element-plus'
import { useRouter, useRoute } from 'vue-router'
import { useConfig } from '/@/stores/config'
import { DArrowRight, Plus, Delete } from '@element-plus/icons-vue'
import MeasurementPage from './analysisAttributes.vue'
import * as echarts from 'echarts'
const config = useConfig()
const router = useRouter()
const route = useRoute()
const activeIndex = ref(0)
const { t } = useI18n()
const headerList = [t('statAnalysis.PowerCurveAnalysis'), t('statAnalysis.trendAnalysis'), t('statAnalysis.trendComparison')]
const statAnalysisSelect = reactive({
deviceId: '',
attributes: '',
attributeCode: '',
interval: '',
time: '',
})
const times = reactive([{ time: '' }])
const addTime = (index) => {
console.log(index)
console.log(times)
times.push({ time: '' })
}
const switchTime = (index) => {
times.splice(index, 1)
}
const timechange = (value) => {
const count = getTimeIntervals(times[0][0], times[0][1])
const count1 = getTimeIntervals(times[value][0], times[value][1])
if (count !== count1) {
times[value] = { time: '' }
value = ElMessage.warning('查询时间点错误,请重新舒服')
}
console.log('🚀 ~ timechange ~ count:', count)
}
const isExpand = ref(false)
const handleClick = () => {
isExpand.value = !isExpand.value
console.log(isExpand)
}
const iotModelId = ref('')
watch(
() => statAnalysisSelect.deviceId,
(newVal) => {
if (newVal) {
const row = statAnalysisSelectOptions.deviceId.filter((item) => {
console.log(item.value == newVal)
return item.value == newVal
})
console.log()
iotModelId.value = row[0].iotModelId
console.log('🚀 ~ iotModelId:', iotModelId)
}
},
{
immediate: true,
}
)
const showMeasure = ref(false)
const selectedAttrRow = ref({
attributeCode: '',
attributeName: '',
})
const handleRadioChange = (value) => {
const { attributeCode, attributeName } = { ...value }
selectedAttrRow.attributeCode = attributeCode
selectedAttrRow.attributeName = attributeName
}
const selectstatAnalysisAttributes = () => {
statAnalysisSelect.attributes = selectedAttrRow.attributeName
console.log('🚀 ~ selectstatAnalysisAttributes ~ selectedAttrRow:', selectedAttrRow)
statAnalysisSelect.attributeCode = selectedAttrRow.attributeCode
showMeasure.value = false
}
const chartContainer = ref<HTMLElement | null>(null)
const option = {
// dataZoom: [
// {
// type: 'inside',
// start: 0,
// end: 100,
// },
// {
// start: 0,
// },
// ],
tooltip: {
trigger: 'axis',
// axisPointer: {
// type: 'cross',
// label: {
// backgroundColor: '#6a7985',
// },
// },
},
legend: {
right: 10,
top: 0,
icon: 'rect',
itemGap: 20,
itemWidth: 8,
itemHeight: 8,
data: [],
selected: {},
},
xAxis: {
type: 'category',
data: [],
},
yAxis: {
type: 'value',
},
series: [],
grid: {
left: '3%',
right: '3%',
},
}
const statAnalysisSelectOptions = reactive({
interval: [
{ label: '五分钟', value: '5m' },
{ label: '十五分钟', value: '15m' },
{ label: '一小时', value: '1h' },
{ label: '一天', value: '1d' },
{ label: '原始', value: 'NONE' },
],
deviceId: [],
})
const customName = ref('第一条数据')
const chart = ref(null)
onMounted(() => {
if (chartContainer.value) {
chart.value = echarts.init(chartContainer.value)
chart.value.setOption(option)
}
queryWindTurbines()
})
const queryWindTurbines = () => {
queryWindTurbinesPages().then((res) => {
if (res.code == 200) {
statAnalysisSelectOptions.deviceId = res.data.map((item) => {
return {
value: item.irn,
label: item.name ?? '-',
iotModelId: item.modelId,
}
})
}
})
}
window.onresize = () => {
chart.resize()
}
const handleSelect = () => {}
const selectstatAnalysis = () => {}
const shortcuts = [
{
text: '昨日',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24)
return [start, end]
},
},
{
text: '前三天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 3)
return [start, end]
},
},
{
text: '前七天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
return [start, end]
},
},
{
text: '上个月',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
return [start, end]
},
},
]
const getTimeIntervals = (startTimestamp, endTimestamp) => {
const startDate = new Date(startTimestamp)
const endDate = new Date(endTimestamp)
let count = 0
switch (statAnalysisSelect.interval) {
case 'NONE':
count = Math.floor((endDate - startDate) / 1000)
break
case '5m':
count = Math.floor((endDate - startDate) / (5 * 60 * 1000))
break
case '15m':
count = Math.floor((endDate - startDate) / (15 * 60 * 1000))
break
case '1h':
count = Math.floor((endDate - startDate) / (1 * 60 * 60 * 1000))
break
case '1d':
count = Math.floor((endDate - startDate) / (1 * 24 * 60 * 60 * 1000))
break
// default:
// throw new Error('Invalid interval')
}
return count
}
const statAnalysisOperate = () => {
console.log(statAnalysisSelect)
console.log(times)
times.forEach((time) => {
if (time[0] && time[1]) {
const requestData = {
devices: [
{
deviceId: statAnalysisSelect.deviceId,
attributes: [statAnalysisSelect.attributeCode],
},
],
interval: statAnalysisSelect.interval,
startTime: new Date(time[0]).getTime(),
endTime: new Date(time[1]).getTime(),
}
historyDataReq(requestData)
console.log(requestData)
}
})
}
const historyDataReq = (data) => {
// historyReq(data).then((res) => {
// console.log(res)
const res = {
//ID
'129476828342323': {
//
power: {
//
times: [123452435924242, 123452435924342, 123452435924442, 123452435924542],
//
values: [123.23, 35.21, 34.56, 67],
},
},
}
const deviceId = statAnalysisSelect.deviceId
const attributeCode = statAnalysisSelect.attributeCode
const resData = res['129476828342323']['power']
const xData = resData['times']
const yData = resData['values']
option.tooltip = {
trigger: 'axis',
show: true,
formatter: function (params) {
console.log('🚀 ~ //historyReq ~ params:', params)
return params
.map((item) => {
return `${item.seriesName} (${xData[item.dataIndex]}): ${item.data}`
})
.join('<br/>')
},
}
option.xAxis.data = Array.from({ length: xData.length }, (_, index) => index)
option.series = [
{
name: '',
type: 'line',
data: yData,
},
]
console.log('🚀 ~ //historyReq ~ option:', option)
chart.value.setOption(option)
// })
}
const statAnalysisExport = () => {}
const statAnalysiImport = () => {}
</script>
<style scoped lang="scss">
.statAnalysis {
height: 100%;
.headerList {
border: none;
--el-menu-bg-color: v-bind('config.getColorVal("menuBackground")');
--el-menu-text-color: v-bind('config.getColorVal("menuColor")');
--el-menu-active-color: v-bind('config.getColorVal("menuActiveColor")');
}
.headerPart {
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
.topLeft {
display: flex;
.selectPart {
display: flex;
justify-content: space-between;
align-items: center;
height: 40px;
margin-right: 20px;
span {
margin-right: 10px;
}
.statAnalysisSelect {
width: 200px;
:deep(.el-select__wrapper) {
height: 40px;
}
:deep(.el-input__inner) {
height: 38px;
}
}
.max,
.min,
.average {
border-radius: 6px;
height: 40px;
width: 72px;
text-align: center;
line-height: 40px;
}
.max {
background: rgba(254, 55, 49, 0.2);
border: 1px solid #fe3731;
color: #fe3731;
}
.min {
background: rgba(0, 160, 150, 0.2);
border: 1px solid #00a096;
color: #00a096;
}
.average {
background: rgba(0, 100, 170, 0.2);
border: 1px solid #0064aa;
color: #0064aa;
}
}
.dialog-footer button:first-child {
margin-right: 10px;
}
}
.topRight {
// width: 436px;
display: flex;
justify-content: space-between;
.el-button {
width: 100px;
height: 40px;
}
}
}
.timeColumns {
max-height: 120px;
overflow: hidden;
.headerPart {
padding: 10px;
}
&.expand {
max-height: max-content;
height: auto;
overflow: inherit;
}
}
.timeColumns.expand + div.ralIcon {
transform: rotate(-90deg);
}
.ralIcon {
width: 100%;
text-align: center;
transform: rotate(90deg);
}
#myEChart {
width: 100%;
height: 300px;
}
}
</style>