周运行报告

parent 878a91c0
......@@ -13,6 +13,7 @@
"express-async-handler": "^1.1.4",
"express-history-api-fallback": "^2.2.1",
"formidable": "^1.2.1",
"html2pdf.js": "^0.14.0",
"iconv-lite": "^0.7.0",
"log4js": "^6.6.1",
"lru-cache": "^4.1.5",
......
......@@ -946,36 +946,41 @@ export async function controlAcByEnvironment(deviceId: string, data: any) {
}
}
// ===== 新风联动 =====
// ===== 新风联动(后执行,通过送风模式覆盖空调温控) =====
if (co2 != null) {
const fanParams = calcFanParams(co2);
if (fanParams) {
let fanDevices = await selectDataListByParam(TABLENAME.设备表, {
region_key: regionKey,
device_type: "新风"
}, ["id", "device_name", "device_id", "device_ad"]);
device_type: { "%in%": ["新风", "空调"] }
}, ["id", "device_name", "device_id", "device_ad", "device_type"]);
if (fanDevices.data.length > 0) {
// 去重:若本次新风动作与上次相同,跳过调用
// CO2联动:高→送风模式(3)+高风(1),低→不传workMode(不切换模式)+低风(4)
const fanWorkMode: number | undefined = fanParams.action === 'high' ? 3 : undefined;
const fanSpeedVal = fanParams.action === 'high' ? 1 : 4;
// 去重
const fanCacheKey = `fan_${regionKey}`;
const lastFanState = envControlCache.get(fanCacheKey);
if (lastFanState && lastFanState.co2Action === fanParams.action) {
console.log(`新风联动跳过(控制参数未变): CO2 ${co2}ppm, 动作 ${fanParams.action}, 区域 ${regionKey}`);
if (lastFanState && lastFanState.co2Action === fanParams.action && lastFanState.workMode === fanWorkMode && lastFanState.fanSpeed === fanSpeedVal) {
console.log(`新风联动跳过(参数未变): CO2 ${co2}ppm, ${fanParams.action === 'high' ? '送风高风' : '低风待机'}, 区域 ${regionKey}`);
} else {
let fanControlRes = await controlFanRunningApi(fanDevices, fanParams);
let fanControlRes = await controlAcRunningApi(fanDevices, fanWorkMode, undefined, fanSpeedVal, 1);
// 更新缓存
envControlCache.set(fanCacheKey, { co2Action: fanParams.action });
// 更新缓存(含 workMode/fanSpeed 用于去重)
envControlCache.set(fanCacheKey, { co2Action: fanParams.action, workMode: fanWorkMode, fanSpeed: fanSpeedVal });
const fanLogs = fanDevices.data.map((fan: any) => ({
device_id: fan.device_id,
device_type: '新风',
device_type: fan.device_type || '新风',
operation_content: {
option: '自动联动控制',
device_id: deviceId,
time: operationTime,
roomCo2: co2,
action: fanParams.action === 'high' ? '风量调高' : '风量调低待机',
mode: fanParams.action === 'high' ? '送风' : '低风待机',
action: fanParams.action === 'high' ? '送风高风' : '低风不切换模式',
success: fanControlRes.success,
message: fanControlRes.message || (fanControlRes.success ? '控制成功' : '控制失败'),
},
......@@ -986,7 +991,7 @@ export async function controlAcByEnvironment(deviceId: string, data: any) {
await addData(TABLENAME.设备日志表, fanLogs);
if (fanControlRes.success) {
console.log(`新风联动成功: IAQ CO2 ${co2}ppm → ${fanParams.action === 'high' ? '风量调高' : '风量调低待机'}, 设备 ${deviceId}`);
console.log(`新风联动成功: CO2 ${co2}ppm → ${fanParams.action === 'high' ? '送风高风' : '低风待机'}, 设备 ${deviceId}`);
} else {
console.error(`新风联动失败: ${fanControlRes.message}`);
}
......@@ -1009,11 +1014,14 @@ async function controlAcRunningApi(acDevices?: any, workMode?: number, tempSet?:
let params: any = {
"indoorUnitAddressFull": deviceList,
"workMode": workMode,
"onOff": onOff ?? 1, // 联动时按温差动态判断,默认开机兜底
"fanSpeed": fanSpeed ?? 2, // 联动时按温差动态计算,默认中风兜底
"openApiAction": "control",
};
// workMode 为 undefined 时不传,飞奕不切换模式
if (workMode != null) {
params.workMode = workMode;
}
// 如果传入了设定温度,一并下发
if (tempSet != null) {
params.tempSet = tempSet;
......@@ -1039,39 +1047,8 @@ async function controlAcRunningApi(acDevices?: any, workMode?: number, tempSet?:
return controlResults;
}
// 辅助:接入新风控制API,根据CO2浓度控制新风风量
async function controlFanRunningApi(fanDevices?: any, fanParams?: { action: 'high' | 'low' | 'standby' }) {
let deviceList: any = [];
fanDevices.data.forEach((fan: any) => {
deviceList.push(fan.device_id);
});
let controlResults: any = { "success": false, "message": "失败" };
if (deviceList.length === 0) return controlResults;
// fanSpeed: 1高风 2中风 4低风;standby模式关停
const fanSpeed = fanParams?.action === 'high' ? 1 : 4;
const onOff = fanParams?.action === 'standby' ? 0 : 1;
let params: any = {
"indoorUnitAddressFull": deviceList,
"onOff": onOff,
"fanSpeed": fanSpeed,
"openApiAction": "control",
};
let res = await controlIndoorUnit(params);
if (res.success) {
controlResults.success = true;
controlResults.devices = deviceList;
controlResults.message = '控制成功';
} else {
controlResults.success = false;
controlResults.devices = deviceList;
controlResults.message = res.data || '控制新风设备失败';
}
return controlResults;
}
/**
* 数据集成 - 启动定时任务
......
......@@ -95,8 +95,6 @@ async function scheduledTask(): Promise<void> {
// ====== 在此处编写定时任务的具体逻辑 ======
console.log(`[定时任务] 开始执行 - ${new Date().toLocaleString()}`);
// TODO: 替换为实际的业务逻辑
// 例如:数据备份、缓存清理、定时同步等
await region();
await device();
await deviceData();
......
/**
* 周报告 API 路由
*/
import asyncHandler from "express-async-handler";
import * as reportBiz from "../biz/report";
export function setRouter(httpServer) {
/** 获取周报告JSON数据 */
httpServer.get("/api/qdm/report/weekly/data", asyncHandler(getReportData));
}
/**
* GET /api/qdm/report/weekly/data?weekOffset=0
* 返回周报告 JSON 数据供前端页面渲染
*/
async function getReportData(req, res) {
const weekOffset = Number(req.query?.weekOffset) || 0;
const data = await reportBiz.getWeeklyReportData(weekOffset);
res.success(data);
}
......@@ -5,11 +5,13 @@
import * as usersRouter from './users';
import * as deviceRouter from './device';
import * as feiyiClientRouter from './feiyiClient';
import * as reportRouter from './report';
export function setRouter(httpServer) {
usersRouter.setRouter(httpServer);
deviceRouter.setRouter(httpServer);
feiyiClientRouter.setRouter(httpServer);
reportRouter.setRouter(httpServer);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment