空调控制逻辑变更-1

parent 3c2bef4f
......@@ -67,18 +67,22 @@ export async function getRunAnalysis(regionGroup: string, regionType: string) {
let deviceEnergyMap = new Map();
for (let rec of records.data) {
let data = rec.data;
let energy = data.energy ?? data.total_energy;
// let energy = data.energy ?? data.total_energy;
let energy = data.current;
if (energy === undefined) continue;
if (!deviceEnergyMap.has(rec.device_id)) {
deviceEnergyMap.set(rec.device_id, { min: energy, max: energy });
// deviceEnergyMap.set(rec.device_id, { min: energy, max: energy });
deviceEnergyMap.set(rec.device_id, energy);
} else {
let cur = deviceEnergyMap.get(rec.device_id);
if (energy < cur.min) cur.min = energy;
if (energy > cur.max) cur.max = energy;
// if (energy < cur.min) cur.min = energy;
// if (energy > cur.max) cur.max = energy;
energy += cur;
deviceEnergyMap.set(rec.device_id, energy);
}
}
for (let { min, max } of deviceEnergyMap.values()) {
total += (max - min);
for (let energy of deviceEnergyMap.values()) {
total += energy;
}
return total;
}
......@@ -764,13 +768,13 @@ export async function controlAcRunning(params: {}) {
"indoorUnitAddressFull": [deviceId],
"workMode": acDeviceKeyMap[mode],
"onOff": acDeviceKeyMap[power],
"tempSet": setTemp,
"tempSet": Number(setTemp),
"fanSpeed": acDeviceKeyMap[fanSpeed],
"onOffLock": acDeviceKeyMap[autoControl],
"workModeLock": acDeviceKeyMap[autoControl],
"tempSetLock": acDeviceKeyMap[autoControl],
"tempSetLo": minTemp,
"tempSetHi": maxTemp,
"tempSetLo": Number(minTemp),
"tempSetHi": Number(maxTemp),
"openApiAction": autoControl === "解除" ? "control" : "lock"
};
return await controlIndoorUnit(acPrarms);
......@@ -788,7 +792,8 @@ async function getEnergyTrend(deviceIds: string[], startTime: Date, endTime: Dat
let intervalMap = new Map(); // key: 时间字符串, value: { deviceMin, deviceMax }
for (let rec of records.data) {
let data = rec.data;
let energy = data.energy ?? data.total_energy;
// let energy = data.energy ?? data.total_energy;
let energy = data.current;
if (energy === undefined) continue;
let intervalKey: string;
let d = new Date(rec.device_time);
......@@ -801,142 +806,215 @@ async function getEnergyTrend(deviceIds: string[], startTime: Date, endTime: Dat
intervalKey = `${d.getFullYear()}-${pad(d.getMonth()+1)}`;
}
if (!intervalMap.has(intervalKey)) {
intervalMap.set(intervalKey, { deviceMin: new Map(), deviceMax: new Map() });
}
let entry = intervalMap.get(intervalKey);
if (!entry.deviceMin.has(rec.device_id)) {
entry.deviceMin.set(rec.device_id, energy);
entry.deviceMax.set(rec.device_id, energy);
intervalMap.set(intervalKey, energy);
} else {
let curMin = entry.deviceMin.get(rec.device_id);
let curMax = entry.deviceMax.get(rec.device_id);
if (energy < curMin) entry.deviceMin.set(rec.device_id, energy);
if (energy > curMax) entry.deviceMax.set(rec.device_id, energy);
energy = intervalMap.get(intervalKey) + energy;
intervalMap.set(intervalKey, energy);
}
}
let result = [];
for (let [key, { deviceMin, deviceMax }] of intervalMap.entries()) {
let total = 0;
for (let [deviceId, minVal] of deviceMin.entries()) {
let maxVal = deviceMax.get(deviceId);
total += (maxVal - minVal);
}
result.push({ key, value: total.toFixed(0) });
for (let [key, energy] of intervalMap.entries()) {
result.push({ key, value: energy.toFixed(0) });
}
result.sort((a, b) => a.key.localeCompare(b.key));
return result;
}
// 基于馆内环境温度、湿度变化等,联动空调启停
// 判断当前季节:5-9月为夏季(制冷),其余为冬季(制热)
function getSeason(): 'summer' | 'winter' {
const month = new Date().getMonth() + 1;
return (month >= 5 && month <= 9) ? 'summer' : 'winter';
}
// 根据IAQ温度计算空调设定温度
function calcAcTempSet(temperature: number, season: 'summer' | 'winter'): number {
if (season === 'summer') {
// 夏季制冷:温度越高,设定越低
if (temperature > 26) return 22;
if (temperature >= 22) return 24;
return 26;
} else {
// 冬季制热:温度越低,设定越高
if (temperature > 21) return 18;
if (temperature >= 18) return 20;
return 21;
}
}
// 根据IAQ CO2浓度计算新风控制参数
function calcFanParams(co2: number): { action: 'high' | 'low' | 'standby' } | null {
if (co2 > 1000) return { action: 'high' }; // 新风开启,风量调高
if (co2 < 800) return { action: 'low' }; // 风量调低,新风待机
return null; // 800-1000 区间不做调整
}
// 基于馆内环境温度、CO2浓度等,联动空调启停及新风控制
export async function controlAcByEnvironment(deviceId: string, data: any) {
// 获取区域内环境监测设备数据
let envDevices = await selectDataListByParam(TABLENAME.设备表, {
device_id: deviceId,
device_type: "环境监测"
}, ["id", "device_name", "region_key"]);
let controlRes:any = {};
// 若是环境设备,则解析环境设备数据,判断是否需要联动空调设备
if (envDevices.data.length) {
// 通过设备所属区域查询当前区域中的空调设备,获取空调设备标准参数中预设的温度、湿度阈值
let regionKey = envDevices.data[0].region_key;
let acDevices = await selectDataListByParam(TABLENAME.设备表, {
region_key: regionKey,
device_type: "空调"
}, ["id", "device_name", "device_id", "device_ad", "control_params"]);
controlRes = await controlAcRunningApi(acDevices, data.temperature, "");
}
// 加入日志
const now = new Date();
const operationTime = now.toISOString().replace('T', ' ').slice(0, 19);
if (controlRes && controlRes.success) {
console.log(`调用空调控制成功: 设备 ${deviceId}`);
if (controlRes.devices) {
const logEntries = controlRes.devices.map((acDeviceId: string) => ({
device_id: acDeviceId,
device_type: '空调',
operation_content: {
option: '自动联动控制',
env_device_id: deviceId,
time: operationTime,
success: true,
message: controlRes.message || '控制成功',
},
status: 1,
created_at: now,
updated_at: now,
}));
await addData(TABLENAME.设备日志表, logEntries);
const season = getSeason();
const temperature = data.temperature;
const co2 = data.co2;
// 若是环境设备,则解析环境设备数据,判断是否需要联动
if (envDevices.data.length) {
let regionKey = envDevices.data[0].region_key;
// ===== 空调联动 =====
if (temperature != null) {
let acDevices = await selectDataListByParam(TABLENAME.设备表, {
region_key: regionKey,
device_type: "空调"
}, ["id", "device_name", "device_id", "device_ad", "control_params"]);
if (acDevices.data.length > 0) {
const tempSet = calcAcTempSet(temperature, season);
const workMode = season === 'summer' ? 1 : 2; // 1制冷 2制热
const modeName = season === 'summer' ? '制冷' : '制热';
let controlRes = await controlAcRunningApi(acDevices, workMode, tempSet);
// 空调日志
const acLogs = acDevices.data.map((ac: any) => ({
device_id: ac.device_id,
device_type: '空调',
operation_content: {
option: '自动联动控制',
device_id: deviceId,
time: operationTime,
season,
mode: modeName,
roomTemp: temperature,
setTemp: tempSet,
success: controlRes.success,
message: controlRes.message || (controlRes.success ? '控制成功' : '控制失败'),
},
status: controlRes.success ? 1 : 0,
created_at: now,
updated_at: now,
}));
await addData(TABLENAME.设备日志表, acLogs);
if (controlRes.success) {
console.log(`空调联动(${modeName})成功: IAQ温度${temperature}℃ → 设定${tempSet}℃, 设备 ${deviceId}`);
} else {
console.error(`空调联动(${modeName})失败: ${controlRes.message}`);
}
}
}
} else if (controlRes && !controlRes.success) {
console.log(`调用空调控制失败: 设备 ${deviceId} 模式 ${controlRes.message}`);
if (controlRes.devices) {
const logEntries = controlRes.devices.map((acDeviceId: string) => ({
device_id: acDeviceId,
device_type: '空调',
operation_content: {
option: '自动联动控制',
env_device_id: deviceId,
time: operationTime,
success: false,
message: controlRes.message || '控制失败',
},
status: 0,
created_at: now,
updated_at: now,
}));
await addData(TABLENAME.设备日志表, logEntries);
// ===== 新风联动 =====
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"]);
if (fanDevices.data.length > 0) {
let fanControlRes = await controlFanRunningApi(fanDevices, fanParams);
const fanLogs = fanDevices.data.map((fan: any) => ({
device_id: fan.device_id,
device_type: '新风',
operation_content: {
option: '自动联动控制',
device_id: deviceId,
time: operationTime,
roomCo2: co2,
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(`新风联动成功: IAQ CO2 ${co2}ppm → ${fanParams.action === 'high' ? '风量调高' : '风量调低待机'}, 设备 ${deviceId}`);
} else {
console.error(`新风联动失败: ${fanControlRes.message}`);
}
}
}
}
} else {
console.log(`未调用空调控制: 设备 ${deviceId}`);
}
}
// 辅助:接入空调控制API,根据温度阈值启停空调设备
async function controlAcRunningApi(acDevices?: any, temperature?: number, workerMode?: string) {
let workModeMap = {};
let deviceMaxList: any = [];
let deviceMinList: any = [];
let openApiAction = "control"; // control: 控制空调模式,lock: 锁定空调模式
// 辅助:接入空调控制API,根据温度设定值启停空调设备
async function controlAcRunningApi(acDevices?: any, workMode?: number, tempSet?: number) {
let deviceList: any = [];
acDevices.data.forEach((ac: any) => {
let controlParams = ac.control_params;
let maxTemp = controlParams.maxTemp;
let minTemp = controlParams.minTemp;
if (temperature && temperature > maxTemp) {
// 调用空调控制接口启停空调设备
console.log(`联动空调 ${ac.device_name}${ac.id})启停,当前温度:${temperature},阈值范围:${minTemp}-${maxTemp}`);
// 单个接入空调控制API,传入设备ID和控制指令(如开/关、温度设定等)
deviceMaxList.push(ac.device_id);
workModeMap[1] = deviceMaxList;
openApiAction = "control";
} else if (temperature && temperature < minTemp) {
console.log(`联动空调 ${ac.device_name}${ac.id})启停,当前温度:${temperature},阈值范围:${minTemp}-${maxTemp}`);
deviceMinList.push(ac.device_id);
workModeMap[2] = deviceMinList;
openApiAction = "control";
}
deviceList.push(ac.device_id);
});
// 多个设备: 接入空调控制API,传入设备ID和控制指令(如开/关、温度设定等)
let controlResults:any = { "success": false, "message": "失败" };
if (workModeMap[1]) {
// 处理制冷模式
let coldRes = await controlIndoorUnit({ "indoorUnitAddressFull": workModeMap[1], "workMode": 1, "openApiAction": openApiAction })
if (!coldRes.success) {
console.error("控制空调设备制冷失败", coldRes);
controlResults.success = false;
controlResults.devices = workModeMap[1];
controlResults.message = coldRes.data || "控制空调设备制冷失败";
}
let controlResults: any = { "success": false, "message": "失败" };
if (deviceList.length === 0) return controlResults;
let params: any = {
"indoorUnitAddressFull": deviceList,
"workMode": workMode,
"onOff": 1, // 联动时自动开机
"fanSpeed": 2, // 默认中风
"openApiAction": "control",
};
// 如果传入了设定温度,一并下发
if (tempSet != null) {
params.tempSet = tempSet;
}
if (workModeMap[2]) {
// 处理制热模式
let hotRes = await controlIndoorUnit({ "indoorUnitAddressFull": workModeMap[2], "workMode": 2, "openApiAction": openApiAction })
if (!hotRes.success) {
console.error("控制空调设备制热失败", hotRes);
controlResults.success = false;
controlResults.devices = workModeMap[2];
controlResults.message = hotRes.data || "控制空调设备制热失败";
}
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;
}
// 辅助:接入新风控制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;
}
......
......@@ -136,8 +136,8 @@ async function getRegionList(req, res) {
* 控制空调开关
*/
async function controlAcRunning(req, res) {
let reqConf = {deviceId:'String', mode:'String', power:'String', setTemp:'Number', maxTemp:'Number', minTemp:'Number', autoControl:'String', fanSpeed:'String'};
const NotMustHaveKeys = [];
let reqConf = {deviceId:'String', mode:'String', power:'String', setTemp:'String', maxTemp:'String', minTemp:'String', autoControl:'String', fanSpeed:'String'};
const NotMustHaveKeys = [ 'maxTemp', 'minTemp', 'autoControl', 'fanSpeed' ];
let { deviceId, mode, power, setTemp, maxTemp, minTemp, autoControl, fanSpeed } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
let params = { deviceId, mode, power, setTemp, maxTemp, minTemp, autoControl, fanSpeed };
const result = await runningBiz.controlAcRunning(params);
......
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