From 8e87815d76462566b4214029b1e6ae7fcff14882 Mon Sep 17 00:00:00 2001 From: zolliker Date: Fri, 23 Feb 2007 12:34:30 +0000 Subject: [PATCH] - added new driver for new haake thermostat --- haakedriv.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++++++++ psi.c | 1 + 2 files changed, 311 insertions(+) create mode 100644 haakedriv.c diff --git a/haakedriv.c b/haakedriv.c new file mode 100644 index 0000000..0fbe1ee --- /dev/null +++ b/haakedriv.c @@ -0,0 +1,310 @@ +/*--------------------------------------------------------------------------- +haakedriv.c + +Driver for the Phoenix P1 HAAKE thermostat + +Markus Zolliker, Nov 2006 +----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fsm.h" +#include "ease.h" +#include "initializer.h" + +#define HAAKE_ON 1 +#define HAAKE_EXT 2 +#define HAAKE_RESET 3 + +typedef struct { + EaseDriv d; + float t; + float t2; + float set; + int errcnt; + int status; + int running; + int extcontrol; + int relais; + int overtemp; + int lowlevel; + int pumpalarm; + int externalarm; + int coolalarm; + int sensor1alarm; + int sensor2alarm; + int with2sensors; +} Haake; + + +static ParClass haakeClass = { "HAAKE", sizeof(Haake) }; + +/*----------------------------------------------------------------------------*/ +int HaakeHandler(void *object) { + int iret, l; + Haake *drv = ParCast(&haakeClass, object); + EaseBase *eab = EaseBaseCast(object); + char *corr; + + assert(drv); + if (eab->state < EASE_idle) goto quit; + if (availableNetRS232(eab->ser) || availableRS232(eab->ser)) { + eab->msg[0] = '\0'; + l = sizeof(eab->ans); + iret = readRS232TillTerm(eab->ser, eab->ans, &l); + if (eab->state != EASE_expect && eab->state != EASE_lost) { + if (iret == 1) { + ParPrintf(eab, eError, "unexpected answer: %s", eab->ans); + } + goto quit; + } + l = strlen(eab->ans) - 1; + if (l >= 0 && eab->ans[l] != '$') { /* end char is not $ -> send again */ + ParPrintf(eab, -2, "ans: %s", eab->ans); + if (drv->errcnt < 10) { + eab->state = EASE_read; + EaseWrite(eab, NULL); /* send the same command again */ + drv->errcnt++; + return 0; + } + eab->errCode = EASE_ILL_ANS; + eab->state = EASE_idle; + goto error; + } else { + drv->errcnt=0; + } + if (iret == 1) { + ParPrintf(eab, -2, "ans: %s", eab->ans); + if (eab->state == EASE_lost) { + goto quit; + } else if (eab->cmd[0] == 'V') { + if (strcmp(eab->ans, eab->version) == 0) { + /* we are still connected with the same device */ + } else if (*eab->version == '\0') { + strncat(eab->version, eab->ans, sizeof(eab->version)-1); + } else { /* version (and therefore device) changed */ + eab->errCode = EASE_DEV_CHANGED; + eab->state = EASE_idle; + goto error; + } + eab->state = EASE_idle; + goto quit; + } else { + eab->tmo = 120; + } + } + if (iret != 1) { + eab->errCode = iret; + eab->state = EASE_idle; + goto error; + } + eab->state = EASE_read; + } else if (eab->state == EASE_expect) { + if (time(NULL) > eab->cmdtime + eab->tmo) { + eab->state = EASE_lost; + } + } else if (eab->state == EASE_lost) { +/* + if (time(NULL) > eab->cmdtime) { + EaseWrite(eab, "check"); + eab->state = EASE_lost; + } +*/ + } + goto quit; +error: + /* EaseWriteError(eab); */ +quit: + return EaseHandler(eab); +} +/*----------------------------------------------------------------------------*/ +static void HaakeParDef(void *object) { + Haake *drv = ParCast(&haakeClass, object); + EaseBase *eab = object; + int reset = 0; + + ParName(""); ParFmt("%.2f"); ParTail("C"); + ParFloat(&drv->t, PAR_NAN); + + ParName("t2"); + if (drv->with2sensors) { ParFmt("%.2f"); ParTail("C"); } + ParFloat(&drv->t2, PAR_NAN); + + ParName("set"); ParFmt("%.2f"); ParTail("C"); + ParFloat(&drv->set, PAR_NAN); + + ParName("running"); EaseUpdate(HAAKE_ON); + ParInt(&drv->running, 0); + + ParName("extcontrol"); EaseUpdate(HAAKE_EXT); + ParInt(&drv->extcontrol, 0); + + ParName("relais"); ParInt(&drv->relais, 0); + ParName("overtemp"); ParInt(&drv->overtemp, 0); + ParName("lowlevel"); ParInt(&drv->lowlevel, 0); + ParName("pumpalarm"); ParInt(&drv->pumpalarm, 0); + ParName("externalarm"); ParInt(&drv->externalarm, 0); + ParName("coolalarm"); ParInt(&drv->coolalarm, 0); + ParName("sensor1alarm"); ParInt(&drv->sensor1alarm, 0); + ParName("sensor2alarm"); ParInt(&drv->sensor2alarm, 0); + + ParName("reset"); ParAccess(usUser); ParSave(0); + ParInt(&reset, 0); + if (ParActionIs(PAR_SET) > 0) { + EaseSetUpdate(drv, HAAKE_RESET, 1); + } + ParName("with2sensors"); ParAccess(usUser); ParInt(&drv->with2sensors, 0); + + EaseBasePar(drv); + EaseSendPar(drv); + EaseDrivPar(drv, "%.2f", "C"); + ParStdDef(); + EaseMsgPar(drv); +} +/*----------------------------------------------------------------------------*/ +static long HaakeRead(long pc, void *object) { + Haake *drv = ParCast(&haakeClass, object); + EaseBase *eab = object; + char alarms[128]; + int status; + + switch (pc) { default: /* FSM BEGIN *******************************/ + EaseWrite(eab, "B"); + return __LINE__; case __LINE__: /**********************************/ + if (!EaseGetUpdate(drv, HAAKE_ON)) { + drv->running = (eab->ans[0]!='0'); + } + if (!EaseGetUpdate(drv, HAAKE_EXT)) { + drv->extcontrol = (eab->ans[1]!='0'); + } + drv->relais = (eab->ans[2]!='0'); + drv->overtemp = (eab->ans[3]!='0'); + drv->lowlevel = (eab->ans[4]!='0'); + drv->pumpalarm = (eab->ans[5]!='0'); + drv->externalarm = (eab->ans[6]!='0'); + drv->coolalarm = (eab->ans[7]!='0'); + drv->sensor1alarm = (eab->ans[10]!='0'); + drv->sensor2alarm = (eab->ans[11]!='0'); + + EaseWrite(eab, "F1"); + return __LINE__; case __LINE__: /**********************************/ + drv->t = atof(eab->ans); + if (!drv->with2sensors) goto nof2; + EaseWrite(eab, "F2"); + return __LINE__; case __LINE__: /**********************************/ + drv->t2 = atof(eab->ans); + if (drv->t2 < -222) { + drv->t2 = PAR_NAN; + } + nof2: + EaseWrite(eab, "S"); + return __LINE__; case __LINE__: /**********************************/ + drv->set = atof(eab->ans); + + skipGetSet: + ParLog(drv); + fsm_quit: return 0; } /* FSM END *********************************/ +} +/*----------------------------------------------------------------------------*/ +static long HaakeStart(long pc, void *object) { + Haake *drv = ParCast(&haakeClass, object); + EaseBase *eab = object; + + switch (pc) { default: /* FSM BEGIN *******************************/ + EaseWrite(eab, "V"); + return __LINE__; case __LINE__: /**********************************/ + if (0 != strncmp(eab->version, "1P/H", 4)) { + snprintf(eab->msg, sizeof eab->msg, "unknown temperature controller version: %s", + eab->version); + ParPrintf(drv, eError, "ERROR: %s", eab->msg); + EaseStop(eab); + goto quit; + } + ParPrintf(drv, eStatus, "connected to haake thermostat %s", eab->version); + FsmCall(HaakeRead); + return __LINE__; case __LINE__: /**********************************/ + + quit: + return 0; } /* FSM END ********************************************/ +} +/*----------------------------------------------------------------------------*/ +static long HaakeSet(long pc, void *object) { + Haake *drv = ParCast(&haakeClass, object); + EaseBase *eab = object; + char cmd[32]; + int upd; + + switch (pc) { default: /* FSM BEGIN *******************************/ + upd = EaseNextUpdate(drv); + switch (upd) { + case EASE_RUN: + snprintf(cmd, sizeof cmd, "w sw %.5g", drv->d.targetValue); + break; + case HAAKE_ON: + snprintf(cmd, sizeof cmd, "w ts%d", drv->running); + break; + case HAAKE_EXT: + if (drv->extcontrol) { + snprintf(cmd, sizeof cmd, "w ex"); + } else { + snprintf(cmd, sizeof cmd, "w in"); + } + break; + case HAAKE_RESET: + snprintf(cmd, sizeof cmd, "er"); + break; + default: + goto quit; + } + if (!drv->running) { + ParPrintf(eab, eWarning, "WARNING: Haake is not running"); + } + if (drv->relais || drv->overtemp || drv->lowlevel + || drv->pumpalarm || drv->externalarm || drv->coolalarm + || drv->sensor1alarm || drv->sensor2alarm) { + ParPrintf(eab, eWarning, "WARNING: Haake alarm"); + } + EaseWrite(eab, cmd); + quit: + return 0; } /* FSM END ********************************************/ +} +/*----------------------------------------------------------------------------*/ +static int HaakeInit(SConnection *con, int argc, char *argv[], int dynamic) { + /* args: + MakeObject objectname haake + MakeObject objectname haake + */ + Haake *drv; + + drv = EaseMakeDriv(con, &haakeClass, argc, argv, dynamic, 7, + HaakeParDef, HaakeHandler, HaakeStart, NULL, HaakeRead, + HaakeSet); + if (drv == NULL) return 0; + setRS232ReplyTerminator(drv->d.b.ser,"\r"); + setRS232SendTerminator(drv->d.b.ser,"\r"); + drv->d.b.tmo=5; + return 1; +} +/*----------------------------------------------------------------------------*/ +void HaakeStartup(void) { + ParMakeClass(&haakeClass, EaseDrivClass()); + MakeDriver("HAAKE", HaakeInit, 0, "HAAKE Phoenix P1 thermostat"); +} diff --git a/psi.c b/psi.c index d48fd79..a046c40 100644 --- a/psi.c +++ b/psi.c @@ -86,6 +86,7 @@ void SiteInit(void) { INIT(ArrayObjStartup); INIT(Lsc370Startup); INIT(LinaStartup); + INIT(HaakeStartup); }