运行分析修改

parent 2eb4581a
......@@ -94,10 +94,11 @@ export async function handleDevicePush(deviceId: string, data: any, deviceTime?:
["name"]
);
// 调用空调控制(非文创区域才允许自动控温)
if (regionRow?.data && !regionRow.data.name?.includes("文创")) {
// 根据设备上报的数据,联动控制空调设备
await controlAcByEnvironment(deviceId, data);
}
// if (regionRow?.data && !regionRow.data.name?.includes("文创")) {
// 根据设备上报的数据,联动控制空调设备
let regionName = regionRow?.data && !regionRow.data.name ? regionRow.data.name : "";
await controlAcByEnvironment(deviceId, data, regionName);
// }
return { success: true };
}
......
......@@ -107,7 +107,8 @@ export async function processDeviceData(message) {
// && !regionRow.data.name?.includes("社会责任厅")
// && !regionRow.data.name?.includes("新包装")
// ) {
await controlAcByEnvironment(devEUI, data);
let regionName = regionRow?.data && !regionRow.data.name? regionRow.data.name : "";
await controlAcByEnvironment(devEUI, data, regionName);
// }
}
......
......@@ -11,7 +11,7 @@ import { selectDataListByParam } from "../data/findData";
const HALL_NAMES = ["A馆", "B馆", "C馆"];
const HALL_KEYS = ["total_a", "total_b", "total_c"];
const TABLE_TITLE_LIST = ["时间", "运行时长", "温度℃", "客流量", "能耗kWh"];
const TABLE_TITLE_LIST = ["时间", "运行时长", "温度℃", "客流量", "总耗电量"];
// ======================= 工具函数 =======================
......@@ -67,10 +67,10 @@ function fmtNum(val: number | null): string {
return String(Math.round(val * 10) / 10);
}
/** 格式化能耗,为 0 时返回 "——" */
/** 格式化能耗,保留两位小数,为 0 时返回 "——" */
function fmtEnergy(val: number): string {
if (val <= 0) return "——";
return Math.round(val).toLocaleString() + "kwh";
return String(Math.round(val * 100) / 100) + "kwh";
}
/** 按周七天生成日期数组 */
......@@ -318,19 +318,19 @@ export async function getWeeklyReportData(weekOffset: number = 0): Promise<any>
dayRunHours > 0 ? fmtNum(dayRunHours) + "h" : "——",
dayTempCount > 0 ? fmtNum(dayTempSum / dayTempCount) : "——",
dayVisitor > 0 ? String(dayVisitor) : "——",
dayEnergy > 0 ? String(Math.round(dayEnergy / 24 * 100) / 100) : "——",
dayEnergy > 0 ? String(Math.round(dayEnergy * 100) / 100) : "——",
]);
}
// ===== 第四步:汇总各馆 =====
const hallAvgTemp = hallTempCount > 0 ? hallTempSum / hallTempCount : null;
const hallTempStr = hallAvgTemp != null ? fmtNum(hallAvgTemp) + "°C" : "——";
const hallEnergyStr = fmtEnergy(hallTotalEnergy / 7);
const kllStr = hallTotalVisitor > 0 ? String(Math.round(hallTotalVisitor / 7)) : "——";
const hallEnergyStr = fmtEnergy(hallTotalEnergy);
const kllStr = hallTotalVisitor > 0 ? String(Math.round(hallTotalVisitor)) : "——";
dataTotal[hallKey] = { nh: hallEnergyStr, kll: kllStr, jw: hallTempStr };
runDatas[hallName] = {
rjnh: hallTotalEnergy > 0 ? fmtNum(hallTotalEnergy / 7) + " kWh" : "——",
rjnh: hallTotalEnergy > 0 ? String(Math.round(hallTotalEnergy * 100) / 100) + " kWh" : "——",
tableData: [{ titleList: TABLE_TITLE_LIST, tableList }],
totalData: [
"周累计",
......@@ -355,8 +355,8 @@ export async function getWeeklyReportData(weekOffset: number = 0): Promise<any>
// ===== 第五步:整体汇总 + 评价 =====
dataTotal.ztyx = {
nh: fmtEnergy(overallEnergy / 7),
kll: overallVisitor > 0 ? String(Math.round(overallVisitor / 7)) : "——",
nh: fmtEnergy(overallEnergy),
kll: overallVisitor > 0 ? String(Math.round(overallVisitor)) : "——",
jw: overallTempCount > 0
? fmtNum(overallTempSum / overallTempCount) + "°C"
: "——",
......
......@@ -233,11 +233,12 @@ export async function getRunAnalysis(regionGroup: string, regionType: string) {
currentPressure = airData.pressure??0;
currentTvoc = airData.tvoc??0;
}
// 过去24小时趋势
let last24h = new Date(nowTime.getTime() - 24*3600000);
// 今天 00:00 ~ 当前时刻
let todayStart = new Date(nowTime);
todayStart.setHours(0, 0, 0, 0);
let airHistory = await selectDataListByParam(TABLENAME.设备数据表, {
device_id: { "%in%": airDeviceIds },
device_time: { "%gte%": formatLocalTime(last24h) }
device_time: { "%gte%": formatLocalTime(todayStart), "%lte%": formatLocalTime(nowTime) }
}, ["data", "device_time"]);
let hourlyData = new Map();
for (let rec of airHistory.data) {
......@@ -249,21 +250,38 @@ export async function getRunAnalysis(regionGroup: string, regionType: string) {
, hcho: data.hcho, lightLevel: data.light_level, pm10: data.pm10, pressure: data.pressure, tvoc: data.tvoc });
}
}
const currentHour = nowTime.getHours();
for (let i = 0; i < 24; i++) {
let key = `${i}`;
let val = hourlyData.get(key);
temperatureTrend.push({ time: `${i}:00`, value: val?.temp?.toString() ?? '0' });
humidityTrend.push({ time: `${i}:00`, value: val?.hum?.toString() ?? '0' });
pm25Trend.push({ time: `${i}:00`, value: val?.pm?.toString() ?? '0' });
let co2Val = val?.co2 ?? 0;
co2TrendDetail.push({ time: `${i}:00`, value: (co2Val / 100).toFixed(1) });
co2Trend.push({ time: `${i}时`, value: co2Val.toString() });
hchoTrend.push({ time: `${i}:00`, value: val?.hcho?.toString() ?? '0' });
lightLevelTrend.push({ time: `${i}:00`, value: val?.lightLevel?.toString() ?? '0' });
pm10Trend.push({ time: `${i}:00`, value: val?.pm10?.toString() ?? '0' });
pressureTrend.push({ time: `${i}:00`, value: val?.pressure?.toString() ?? '0' });
tvocTrend.push({ time: `${i}:00`, value: val?.tvoc?.toString() ?? '0' });
if (i <= currentHour) {
// 已过去的小时:有数据则用,无数据填 '0'
temperatureTrend.push({ time: `${i}:00`, value: val?.temp?.toString() ?? '0' });
humidityTrend.push({ time: `${i}:00`, value: val?.hum?.toString() ?? '0' });
pm25Trend.push({ time: `${i}:00`, value: val?.pm?.toString() ?? '0' });
let co2Val = val?.co2 ?? 0;
co2TrendDetail.push({ time: `${i}:00`, value: (co2Val / 100).toFixed(1) });
co2Trend.push({ time: `${i}时`, value: co2Val.toString() });
hchoTrend.push({ time: `${i}:00`, value: val?.hcho?.toString() ?? '0' });
lightLevelTrend.push({ time: `${i}:00`, value: val?.lightLevel?.toString() ?? '0' });
pm10Trend.push({ time: `${i}:00`, value: val?.pm10?.toString() ?? '0' });
pressureTrend.push({ time: `${i}:00`, value: val?.pressure?.toString() ?? '0' });
tvocTrend.push({ time: `${i}:00`, value: val?.tvoc?.toString() ?? '0' });
} else {
// 未来的小时:填充 null,图表不画折线
temperatureTrend.push({ time: `${i}:00`, value: null });
humidityTrend.push({ time: `${i}:00`, value: null });
pm25Trend.push({ time: `${i}:00`, value: null });
co2TrendDetail.push({ time: `${i}:00`, value: null });
co2Trend.push({ time: `${i}时`, value: null });
hchoTrend.push({ time: `${i}:00`, value: null });
lightLevelTrend.push({ time: `${i}:00`, value: null });
pm10Trend.push({ time: `${i}:00`, value: null });
pressureTrend.push({ time: `${i}:00`, value: null });
tvocTrend.push({ time: `${i}:00`, value: null });
}
}
}
......@@ -906,13 +924,13 @@ function getSeason(): 'summer' | 'winter' {
function calcAcTempSet(temperature: number, season: 'summer' | 'winter'): { tempSet: number; fanSpeed: number; onOff: number } {
if (season === 'summer') {
// 夏季制冷:温度越高,设定越低
if (temperature > 23) return { tempSet: 19, fanSpeed: 1, onOff: 1 }; // 未达需求:高风制冷
if (temperature >= 19) return { tempSet: 21, fanSpeed: 4, onOff: Math.round(temperature) === 21 ? 0 : 1 }; // 舒适区:四舍五入21℃待机
return { tempSet: 23, fanSpeed: 4, onOff: 1 }; // 已达需求:低风维持
if (temperature > 21) return { tempSet: 16, fanSpeed: 1, onOff: 1 }; // 未达需求:高风制冷
if (temperature >= 16) return { tempSet: 16, fanSpeed: 4, onOff: 1}; // 舒适区:四舍五入21℃待机 Math.round(temperature) === 21 ? 0 : 1
return { tempSet: 18, fanSpeed: 4, onOff: 1 }; // 已达需求:低风维持
} else {
// 冬季制热:温度越低,设定越高
if (temperature < 18) return { tempSet: 21, fanSpeed: 1, onOff: 1 }; // 未达需求:高风制热
if (temperature <= 21) return { tempSet: 20, fanSpeed: 4, onOff: Math.round(temperature) === 20 ? 0 : 1 }; // 舒适区:四舍五入20℃待机
if (temperature <= 21) return { tempSet: 20, fanSpeed: 4, onOff: 1}; // 舒适区:四舍五入20℃待机 Math.round(temperature) === 20 ? 0 : 1
return { tempSet: 18, fanSpeed: 4, onOff: 1 }; // 已达需求:低风维持
}
}
......@@ -925,7 +943,7 @@ function calcFanParams(co2: number): { action: 'high' | 'low' | 'standby' } | nu
}
// 基于馆内环境温度、CO2浓度等,联动空调启停及新风控制
export async function controlAcByEnvironment(deviceId: string, data: any) {
export async function controlAcByEnvironment(deviceId: string, data: any, regionName:string) {
// 获取区域内环境监测设备数据
let envDevices = await selectDataListByParam(TABLENAME.设备表, {
device_id: deviceId,
......@@ -942,6 +960,63 @@ export async function controlAcByEnvironment(deviceId: string, data: any) {
if (envDevices.data.length) {
let regionKey = envDevices.data[0].region_key;
// ===== 新风联动(后执行,通过送风模式覆盖空调温控) =====
if (co2 != null && !regionName?.includes("原料厅") && !regionName?.includes("社会责任厅")) {
const fanParams = calcFanParams(co2);
if (fanParams) {
let fanDevices = await selectDataListByParam(TABLENAME.设备表, {
region_key: regionKey,
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 && lastFanState.workMode === fanWorkMode && lastFanState.fanSpeed === fanSpeedVal) {
console.log(`新风联动跳过(参数未变): CO2 ${co2}ppm, ${fanParams.action === 'high' ? '送风高风' : '低风待机'}, 区域 ${regionKey}`);
} else {
let fanControlRes = await controlAcRunningApi(fanDevices, fanWorkMode, undefined, fanSpeedVal, 1);
// 更新缓存(含 workMode/fanSpeed 用于去重)
envControlCache.set(fanCacheKey, { co2Action: fanParams.action, workMode: fanWorkMode, fanSpeed: fanSpeedVal });
let temp = calcAcTempSet(temperature, season);
const fanLogs = fanDevices.data.map((fan: any) => ({
device_id: fan.device_id,
device_type: fan.device_type || '新风',
operation_content: {
option: '自动联动控制',
device_id: deviceId,
time: operationTime,
roomCo2: co2,
mode: fanParams.action === 'high' ? '送风' : '低风待机',
action: fanParams.action === 'high' ? '送风高风' : '低风不切换模式',
success: fanControlRes.success,
message: fanControlRes.message || (fanControlRes.success ? '控制成功' : '控制失败'),
setTemp: temp?.tempSet,
},
status: fanControlRes.success ? 1 : 0,
created_at: now,
updated_at: now,
}));
await addData(TABLENAME.设备日志表, fanLogs);
if (fanControlRes.success) {
console.log(`新风联动成功: CO2 ${co2}ppm → ${fanParams.action === 'high' ? '送风高风' : '低风待机'}, 设备 ${deviceId}`);
} else {
console.error(`新风联动失败: ${fanControlRes.message}`);
}
}
}
}
}
// ===== 空调联动 =====
if (temperature != null) {
let acDevices = await selectDataListByParam(TABLENAME.设备表, {
......@@ -1011,60 +1086,6 @@ 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: { "%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 && lastFanState.workMode === fanWorkMode && lastFanState.fanSpeed === fanSpeedVal) {
console.log(`新风联动跳过(参数未变): CO2 ${co2}ppm, ${fanParams.action === 'high' ? '送风高风' : '低风待机'}, 区域 ${regionKey}`);
} else {
let fanControlRes = await controlAcRunningApi(fanDevices, fanWorkMode, undefined, fanSpeedVal, 1);
// 更新缓存(含 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: fan.device_type || '新风',
operation_content: {
option: '自动联动控制',
device_id: deviceId,
time: operationTime,
roomCo2: co2,
mode: fanParams.action === 'high' ? '送风' : '低风待机',
action: fanParams.action === 'high' ? '送风高风' : '低风不切换模式',
success: fanControlRes.success,
message: fanControlRes.message || (fanControlRes.success ? '控制成功' : '控制失败'),
},
status: fanControlRes.success ? 1 : 0,
created_at: now,
updated_at: now,
}));
await addData(TABLENAME.设备日志表, fanLogs);
if (fanControlRes.success) {
console.log(`新风联动成功: CO2 ${co2}ppm → ${fanParams.action === 'high' ? '送风高风' : '低风待机'}, 设备 ${deviceId}`);
} else {
console.error(`新风联动失败: ${fanControlRes.message}`);
}
}
}
}
}
}
}
......
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