From b5ef7ff221c083d2624cc1f8f657f2a0ac34a5ce Mon Sep 17 00:00:00 2001 From: "anklimov@gmail.com" Date: Sun, 5 Apr 2026 20:57:16 +0300 Subject: [PATCH] Multi AC pre-release 2 --- lighthub/modules/out_multivent.cpp | 269 +++++++++++++++++++---------- lighthub/modules/out_multivent.h | 13 +- 2 files changed, 189 insertions(+), 93 deletions(-) diff --git a/lighthub/modules/out_multivent.cpp b/lighthub/modules/out_multivent.cpp index 28366b4..93f2572 100644 --- a/lighthub/modules/out_multivent.cpp +++ b/lighthub/modules/out_multivent.cpp @@ -52,7 +52,7 @@ if (gatesObj) { aJsonObject * setObj = getCreateObject(i,"set",(float) 20.0); convert2float(setObj); - aJsonObject * valObj = getCreateObject(i,"val",(float) 20.0); + aJsonObject * valObj = getCreateObject(i,"val",(float) NAN); convert2float(valObj); aJsonObject * poObj = getCreateObject(i,"po", (float) -2.0); convert2float(poObj); @@ -169,7 +169,7 @@ int out_Multivent::Poll(short cause) int actualCmd = getIntFromJson (acObj,"mode"); // global params - int boostTreshold = getIntFromJson (acObj,"boost"); + int boostTreshold = getIntFromJson (acObj,"boost",AC_BOOST_TRESHOLD); int actualMode = CMD_FAN; if (acTemp>30.0) actualMode = CMD_HEAT; else if (acTemp<15.0) actualMode = CMD_COOL; @@ -185,9 +185,9 @@ int out_Multivent::Poll(short cause) { if (i->name && *i->name) { - int cmd = getIntFromJson(i,"cmd"); - int set = getIntFromJson(i,"set"); - int val = getIntFromJson(i,"val"); + int cmd = getIntFromJson(i,"cmd"); + float set = getFloatFromJson(i,"set"); + float val = getFloatFromJson(i,"val"); int execCmd = 0; bool weakMode=false; // kind of modes when we activating PID only if AC in active mode @@ -219,30 +219,34 @@ int out_Multivent::Poll(short cause) bool passiveMode = getIntFromJson(i,"@pasv",0); aJsonObject * pidObj = aJson.getObjectItem(i, "pid"); - aJsonObject * poObj = aJson.getObjectItem(i,"po"); + aJsonObject * poObj = aJson.getObjectItem(i, "po"); if (pidObj && pidObj->valueint && poObj && poObj->type == aJson_Float) { - PID * p = (PID *) pidObj->valueint; - if ((execCmd == CMD_HEAT || execCmd == CMD_COOL) && p->GetMode() == AUTOMATIC) pidActive = true; - switch (actualMode) - { //if air hot or cold - uses temp PID and block control by /fan - case CMD_HEAT: - if (weakMode || passiveMode) p->SetMode(AUTOMATIC); - p->SetControllerDirection(DIRECT); - break; - case CMD_COOL: - if (weakMode || passiveMode) p->SetMode(AUTOMATIC); - p->SetControllerDirection(REVERSE); - break; - default: - if ((passiveMode || weakMode || execCmd ==CMD_OFF) && p->GetMode() == AUTOMATIC) - { - p->SetMode(MANUAL); - debugSerial<name<name,true,true); - } - } + int pidAlarmTime = getIntFromJson(i,"pidAlarmTime",120000L); + if (isTimeOver(getIntFromJson(i,"valTS"),millisNZ(),pidAlarmTime)) //if value is fresh - use it, otherwise set val to NAN + setValToJson(i,"val",NAN); + PID * p = (PID *) pidObj->valueint; + + if ((execCmd == CMD_HEAT || execCmd == CMD_COOL) && p->GetMode() == AUTOMATIC) pidActive = true; + switch (actualMode) + { //if air hot or cold - uses temp PID and block control by /fan + case CMD_HEAT: + if (weakMode || passiveMode) p->SetMode(AUTOMATIC); + p->SetControllerDirection(DIRECT); + break; + case CMD_COOL: + if (weakMode || passiveMode) p->SetMode(AUTOMATIC); + p->SetControllerDirection(REVERSE); + break; + default: + if ((passiveMode || weakMode || execCmd ==CMD_OFF) && p->GetMode() == AUTOMATIC) + { + p->SetMode(MANUAL); + debugSerial<name<name,true,true); + } + } if (p->Compute()) { { @@ -252,7 +256,13 @@ int out_Multivent::Poll(short cause) <<" P:"<GetKp()<<" I:"<GetKi()<<" D:"<GetKd()<<((p->GetDirection())?" Rev ":" Dir ")<<((p->GetMode())?"A":"M"); debugSerial<valuefloat)) + { + poObj->valuefloat = getFloatFromJson(i,"pidAlarmValue",NAN); + debugSerial<valuefloat<valuefloat)) switch (execCmd) { case CMD_HEAT: @@ -297,7 +307,7 @@ int out_Multivent::Poll(short cause) } else //PID not computed - maybe not in time, but we can use PID output as indicator of balance and boost if needed { - if (p->GetMode() == AUTOMATIC) + if (p->GetMode() == AUTOMATIC && !isnan(poObj->valuefloat)) { if (execCmd == CMD_HEAT) balance+=poObj->valuefloat; else if (execCmd == CMD_COOL) balance-=poObj->valuefloat; @@ -312,11 +322,11 @@ int out_Multivent::Poll(short cause) { debugSerial<boostTreshold) setBoost(itemCmd().Cmd(CMD_HEAT).Int(30).setSuffix(S_SET)); - else if (-balance>boostTreshold) setBoost(itemCmd().Cmd(CMD_COOL).Int(18).setSuffix(S_SET)); + if (balance>boostTreshold) setBoost(itemCmd().Cmd(CMD_HEAT).Int(AC_BOOST_HIGH_TEMP).setSuffix(S_SET)); + else if (-balance>boostTreshold) setBoost(itemCmd().Cmd(CMD_COOL).Int(AC_BOOST_LOW_TEMP).setSuffix(S_SET)); else { - pidActive = false; + if (abs(balance)child; // Pass 1 - calculate summ air value, max value etc int activeV = 0; @@ -552,13 +565,7 @@ while (i) { debugSerial<valueint = cmd.getInt(); - //sendFlags |= FLAG_PARAMETERS; } else { @@ -576,12 +581,7 @@ while (i) { cmd.Cmd(CMD_OFF); debugSerial<<"VENT: Turning OFF by fan"<valueint); - //cmdObj->valueint = CMD_OFF; - //sendFlags |= FLAG_COMMAND; } - //fanObj->valueint = 0; - //sendFlags |= FLAG_PARAMETERS; } fanObj->valueint = cmd.getInt(); // if (!passiveMode) sendFlags |= FLAG_PARAMETERS; // @@ -713,6 +713,7 @@ while (i) { debugSerial<valueint) && (((PID *) pidObj->valueint)->GetMode() ==AUTOMATIC)); } + + void out_Multivent::checkACcmd (int acCmd) +{ + if (!acObj) return; + int lastCmd = getIntFromJson(acObj,"@lastCmd"); + int prevACcmd = getIntFromJson(acObj,"mode"); + + if (!prevACcmd) { + debugSerial<<"VENT: AC MODE received initially "<getCmd()<0); switch (cmd.getSuffix()) { case S_FAN: - setValToJson(acObj,"@lastFan",cmd.getCmd()); + if (!(supress & AC_SUPPRESS_FAN) || lastFan != cmd.getInt()) { + executeCommand(acObj,-1,cmd.Cmd(0)); + } + setValToJson(acObj,"@lastFan",cmd.getInt()); + if (cmd.getInt() == 0 && isActiveNow) + { + setValToJson(acObj,"@lastCmd",CMD_OFF); + setValToJson(acObj,"@preCmd",prevACcmd); + } + else if (cmd.getInt() > 0 && !isActiveNow) + { + int preCmd = getIntFromJson(acObj,"@preCmd",CMD_FAN); + setValToJson(acObj,"@lastCmd",preCmd); + } break; case S_SET: - setValToJson(acObj,"@lastSet",cmd.getCmd()); + if (!(supress & AC_SUPPRESS_SET) || lastSet != cmd.getFloat()) { + executeCommand(acObj,-1,cmd.Cmd(0)); } + setValToJson(acObj,"@lastSet",cmd.getFloat()); + break; + default: + executeCommand(acObj,-1,cmd.Cmd(0)); + break; + } + } return 1; } @@ -875,22 +960,22 @@ void out_Multivent::setBoost(itemCmd cmd) { if (!acObj || getFlag(acObj,FLAG_ACTION_NEEDED)) return; debugSerial<<"VENT: boost on"<=AC_BOOST_HIGH_TEMP) preTemp = AC_PRESET_TEMP; sendACcmd(itemCmd().Cmd(0).Int(preTemp).setSuffix(S_SET)); - //executeCommand(acObj,-1,itemCmd().Cmd(0).Int(preTemp).setSuffix(S_SET)); clearFlag(acObj,FLAG_ACTION_NEEDED); } diff --git a/lighthub/modules/out_multivent.h b/lighthub/modules/out_multivent.h index 9913d17..63c013d 100644 --- a/lighthub/modules/out_multivent.h +++ b/lighthub/modules/out_multivent.h @@ -6,8 +6,16 @@ #include "itemCmd.h" #include +#define AC_BOOST_HIGH_TEMP 30 +#define AC_PRESET_TEMP 21 +#define AC_BOOST_LOW_TEMP 17 +#define AC_BOOST_TRESHOLD 230 +#define AC_BOOST_DEADBAND 10 + +#define AC_SUPPRESS_FAN 1 +#define AC_SUPPRESS_SET 2 +#define AC_SUPPRESS_CMD 4 -//static int8_t motorQuote = 0; class out_Multivent : public abstractOut { public: @@ -26,6 +34,9 @@ public: protected: void getConfig(); int sendACcmd (itemCmd cmd); + void checkACcmd (int acCmd); + void checkACfan (int acFan); + void checkACset (int acSet); void setPassiveMode(aJsonObject* zone, bool mode); uint32_t getFlag (aJsonObject* zone, uint32_t flag); void setFlag (aJsonObject* zone, uint32_t flag);