diff --git a/SICSmain.c b/SICSmain.c index f6187cf7..0f4e9897 100644 --- a/SICSmain.c +++ b/SICSmain.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "nserver.h" #include "servlog.h" @@ -32,6 +33,12 @@ pServer pServ = NULL; #define DEFAULTINIFILE "servo.tcl" +int usage(const char *name) +{ + fprintf(stderr, "usage: %s [-d] [-nolog] \n", name); + return 1; +} + /*--------------------------------------------------------------------------- The Servers Main program. May take one argument: the name of an initialisation file @@ -40,22 +47,36 @@ pServer pServ = NULL; int main(int argc, char *argv[]) { int iRet; + int daemonize = 0; char *file = NULL; - int i; + int i, firstArg = 1; + + if (argc < 2) + return usage(argv[0]); /* initialise, will die on you if problems */ - for (i = 1; i < argc; i++) { + if (strcasecmp(argv[1], "-d") == 0) { + daemonize = 1; + firstArg = 2; + } + for (i = firstArg; i < argc; i++) { if (strcmp(argv[i], "-nolog") == 0) { SICSLogEnable(0); } else if (file == NULL) { file = argv[i]; } } + + if (file == NULL) + return usage(argv[0]); + iRet = InitServer(file, &pServ); if (!iRet) { printf("Unrecoverable error on server startup, exiting.........\n"); exit(1); } + if (daemonize == 1) + daemon(1, 1); RunServer(pServ); diff --git a/nwatch.c b/nwatch.c index 32f8d674..af95dfeb 100644 --- a/nwatch.c +++ b/nwatch.c @@ -67,10 +67,13 @@ typedef struct __netwatchtimer { struct timeval tv; /* time when event is due */ pNWCallback func; /* function to call */ void *cntx; /* abstract context to pass to callback */ - long int tick; /* millisecond repeat rate */ + int msec; /* millisecond delay time */ + int tick; /* millisecond repeat rate */ long int vrfy; /* integrity check */ } NWTimer; +static pNWTimer activeTimer = NULL; + /* * \brief private function to insert an entry into the sorted timer queue. * @@ -83,6 +86,7 @@ static int NetWatchTimerInsQue(pNetWatch self, pNWTimer handle) if (self->tq_head == NULL) { self->tq_head = self->tq_tail = handle; handle->next = NULL; + handle->vrfy = NWMAGIC; return 1; } /* if new one is not earlier than latest one, insert after latest */ @@ -92,6 +96,7 @@ static int NetWatchTimerInsQue(pNetWatch self, pNWTimer handle) self->tq_tail->next = handle; self->tq_tail = handle; handle->next = NULL; + handle->vrfy = NWMAGIC; return 1; } /* if new one is not later than earliest one, insert before earliest */ @@ -100,6 +105,7 @@ static int NetWatchTimerInsQue(pNetWatch self, pNWTimer handle) handle->tv.tv_usec <= self->tq_head->tv.tv_usec)) { handle->next = self->tq_head; self->tq_head = handle; + handle->vrfy = NWMAGIC; return 1; } else { /* must be in between two so start at the first entry */ @@ -113,8 +119,10 @@ static int NetWatchTimerInsQue(pNetWatch self, pNWTimer handle) /* slip new one in between this one and the next one */ handle->next = pNxt->next; pNxt->next = handle; + handle->vrfy = NWMAGIC; + return 1; } - return 1; + return 0; } /* @@ -125,6 +133,7 @@ static int NetWatchTimerInsQue(pNetWatch self, pNWTimer handle) */ static int NetWatchTimerRemQue(pNetWatch self, pNWTimer handle) { + assert(handle->vrfy == NWMAGIC); /* handle the case of first and possibly only */ if (handle == self->tq_head) { self->tq_head = self->tq_head->next; /* may be NULL */ @@ -145,12 +154,14 @@ static int NetWatchTimerRemQue(pNetWatch self, pNWTimer handle) if (handle == self->tq_tail) self->tq_tail = pNxt; } + handle->vrfy = 0; return 1; } int NetWatchRegisterTimer(pNWTimer * handle, int mSec, pNWCallback callback, void *context) { + assert(callback); pNetWatch self = instance; if (!self || self->lMagic != NWMAGIC) return 0; @@ -165,10 +176,10 @@ int NetWatchRegisterTimer(pNWTimer * handle, int mSec, pNew->tv.tv_sec++; pNew->tv.tv_usec -= 1000000; } + pNew->msec = mSec; pNew->tick = 0; pNew->func = callback; pNew->cntx = context; - pNew->vrfy = NWMAGIC; NetWatchTimerInsQue(self, pNew); *handle = pNew; return 1; @@ -178,6 +189,7 @@ int NetWatchRegisterTimerPeriodic(pNWTimer * handle, int mSecInitial, int mSecPeriod, pNWCallback callback, void *context) { + assert(callback); if (NetWatchRegisterTimer(handle, mSecInitial, callback, context)) { pNWTimer pNew = *handle; if (pNew == NULL) @@ -189,16 +201,36 @@ int NetWatchRegisterTimerPeriodic(pNWTimer * handle, int mSecInitial, return 0; } +pNWTimer NetWatchGetActiveTimer(void) +{ + return activeTimer; +} + +int NetWatchGetTimerInitial(pNWTimer handle) +{ + if (handle == NULL + || (handle->vrfy != NWMAGIC && handle->vrfy != ~NWMAGIC)) + return 0; + return handle->msec; +} + +int NetWatchGetTimerDelay(pNWTimer handle) +{ + return NetWatchGetTimerInitial(handle); +} + int NetWatchGetTimerPeriod(pNWTimer handle) { - if (handle == NULL || handle->vrfy != NWMAGIC) + if (handle == NULL + || (handle->vrfy != NWMAGIC && handle->vrfy != ~NWMAGIC)) return 0; return handle->tick; } int NetWatchSetTimerPeriod(pNWTimer handle, int mSecPeriod) { - if (handle == NULL || handle->vrfy != NWMAGIC) + if (handle == NULL + || (handle->vrfy != NWMAGIC && handle->vrfy != ~NWMAGIC)) return 0; handle->tick = mSecPeriod; return 1; @@ -209,6 +241,8 @@ int NetWatchRemoveTimer(pNWTimer handle) pNetWatch self = instance; if (!self || self->lMagic != NWMAGIC) return 0; + if (handle == NULL || handle->vrfy != NWMAGIC) + return 0; NetWatchTimerRemQue(self, handle); handle->vrfy = 0; free(handle); @@ -239,35 +273,10 @@ static int NetWatchContextInsQue(pNetWatch self, pNWContext handle) self->cq_tail->next = handle; self->cq_tail = handle; } + handle->vrfy = NWMAGIC; return 1; } -/** - * \brief private function to remove entry from unsorted queue - * - * \param self singleton - * \param handle entry to insert - */ -static void NetWatchContextRemQue(pNetWatch self, pNWContext handle) -{ - if (handle == self->cq_head) { /* if first */ - self->cq_head = self->cq_head->next; - if (handle == self->cq_tail) /* if also last */ - self->cq_tail = NULL; - } else { - pNWContext pNxt = self->cq_head; - while (pNxt) { - if (handle == pNxt->next) { - pNxt->next = pNxt->next->next; - break; - } - pNxt = pNxt->next; - } - if (handle == self->cq_tail) /* if last */ - self->cq_tail = pNxt; - } - return; -} /** * \brief private function to purge invalid entries @@ -286,19 +295,19 @@ static void NetWatchContextPrgQue(pNetWatch self) free(tmp); } pNxt = self->cq_head; - while (pNxt) { - if (pNxt->next && pNxt->next->sock < 0) { + while (pNxt && pNxt->next) { + if (pNxt->next->sock < 0) { pNWContext tmp = NULL; tmp = pNxt->next; pNxt->next = pNxt->next->next; tmp->vrfy = 0; free(tmp); + continue; } pNxt = pNxt->next; } - /* if the queue is empty clear the tail */ - if (self->cq_head == NULL) - self->cq_tail = pNxt; + /* if the queue is empty then pNxt is NULL else pNxt points to the tail */ + self->cq_tail = pNxt; self->nInvalid = 0; return; } @@ -306,6 +315,7 @@ static void NetWatchContextPrgQue(pNetWatch self) int NetWatchRegisterCallback(pNWContext * handle, int iSocket, pNWCallback callback, void *context) { + assert(callback); pNWContext pNew = NULL; pNetWatch self = instance; if (!self || self->lMagic != NWMAGIC) @@ -320,7 +330,6 @@ int NetWatchRegisterCallback(pNWContext * handle, int iSocket, pNew->mode = nwatch_read; pNew->func = callback; pNew->cntx = context; - pNew->vrfy = NWMAGIC; *handle = pNew; NetWatchContextInsQue(self, pNew); return 1; @@ -333,8 +342,11 @@ int NetWatchRemoveCallback(pNWContext handle) return 0; if (!self || self->lMagic != NWMAGIC) return 0; + /* mark as invalid */ handle->sock = -1; + /* increment count of invalid */ self->nInvalid++; + /* leave for garbage collection */ return 1; } @@ -375,7 +387,7 @@ int NetWatchTask(void *pData) if (self->nInvalid > 0) NetWatchContextPrgQue(self); - /* build the select mask */ + /* build the select mask */ FD_ZERO(&rMask); FD_ZERO(&wMask); pNWC = self->cq_head; @@ -430,7 +442,11 @@ int NetWatchTask(void *pData) break; } NetWatchTimerRemQue(self, pNew); + activeTimer = pNew; + activeTimer->vrfy = ~NWMAGIC; iStatus = pNew->func(pNew->cntx, 0); + activeTimer->vrfy = 0; + activeTimer = NULL; /* * If this is a recurrent timer and the function * indicates to keep it going, put it back in diff --git a/nwatch.h b/nwatch.h index 03f41fb4..3dae42f8 100644 --- a/nwatch.h +++ b/nwatch.h @@ -53,6 +53,10 @@ int NetWatchRegisterTimerPeriodic(pNWTimer * handle, int mSecInitial, int mSecPeriod, pNWCallback callback, void *context); +pNWTimer NetWatchGetActiveTimer(void); + +int NetWatchGetTimerDelay(pNWTimer handle); +int NetWatchGetTimerInitial(pNWTimer handle); int NetWatchGetTimerPeriod(pNWTimer handle); int NetWatchSetTimerPeriod(pNWTimer handle, int mSecPeriod); /** diff --git a/servlog.c b/servlog.c index 29faad49..5f3ec948 100644 --- a/servlog.c +++ b/servlog.c @@ -47,12 +47,15 @@ - NETWrites log message (if enabled) before attempt to write to file - uses OpenVerifyLogFile helper function (removed duplicate code) -----------------------------------------------------------------------------*/ +#include #include "fortify.h" #include #include #include #include #include +#include +#include #include #include "ifile.h" @@ -126,7 +129,7 @@ int LogCapture(SConnection * pCon, SicsInterp * pSics, void *pData, /* check no af args */ if (argc < 2) { - snprintf(pBueffel,sizeof(pBueffel)-1, "Insufficient number of argumenst to %s", argv[0]); + snprintf(pBueffel,sizeof(pBueffel)-1, "Insufficient number of arguments to %s", argv[0]); SCWrite(pCon, pBueffel, eError); return 0; } @@ -203,8 +206,32 @@ static int HasLineFeed(char *pText) } /*---------------------------------------------------------------------------*/ -#define MAXLOG 10000 -#define MAXFILES 20 +static const char* timestamp(struct timeval *tp) { + static char ts[80]; + int year, month, day; + int hour, min, sec, usec; + struct timeval tv; + struct tm *time; + if (tp) + tv = *tp; + else + gettimeofday(&tv, NULL); + time = localtime(&tv.tv_sec); + year = 1900 + time->tm_year; + month = time->tm_mon + 1; + day = time->tm_mday; + hour = time->tm_hour; + min = time->tm_min; + sec = time->tm_sec; + usec = (int) tv.tv_usec; + snprintf(ts, 80, "%04d-%02d-%02dT%02d:%02d:%02d.%06d", + year, month, day, hour, min, sec, usec); + return ts; +} + +/*---------------------------------------------------------------------------*/ +#define MAXLOG 100000 +#define MAXFILES 100 static FILE *fLogFile = NULL; static int iFile = 0; @@ -217,6 +244,10 @@ int OpenVerifyLogFile() char pFile[256]; char filnam[512]; char *pChar = NULL; + char fPath[1024]; + + /* snprintf(fPath, 1023, "%s/", getenv("SICS_INIT_LOGPATH")); */ + snprintf(fPath, 1023, "%s/", "../log"); pChar = IFindOption(pSICSOptions, "LogFileBaseName"); if (!pChar) { /* Try to write to file "server" in */ @@ -224,7 +255,9 @@ int OpenVerifyLogFile() } else { strlcpy(pFile, pChar, 255); } - snprintf(filnam, 511, "%s%2.2d.log", pFile, iFile); + + snprintf(filnam, 511, "%s%s_%19.19s.%02d.log", fPath, pFile, timestamp(NULL), iFile); + fLogFile = fopen(filnam, "w"); if (!fLogFile) { fprintf(stderr, "ERROR: Cannot open logfile %s for writing\n", pFile); @@ -242,23 +275,23 @@ void SICSLogEnable(int flag) } /*---------------------------------------------------------------------------*/ -void SICSLogWrite(char *pText, OutCode eOut) +static void SICSLogWriteFile(char *pText, OutCode eOut, struct timeval *tp) { - char pFile[256]; - char *pChar = NULL; pCaptureEntry pCurrent; - char pBueffel[256]; + int text_len; #ifdef NOLOG return; #endif + text_len = strlen(pText); /* do all captured */ pCurrent = pCapture; while (pCurrent) { if ((pCurrent->iOut == eOut) || (pCurrent->iAllFlag == 1)) { - ANETwrite(pCurrent->pCon->sockHandle, pText, strlen(pText)); - ANETwrite(pCurrent->pCon->sockHandle, "\n", 1); + ANETwrite(pCurrent->pCon->sockHandle, pText, text_len); + if (pText[text_len - 1] != '\n') + ANETwrite(pCurrent->pCon->sockHandle, "\n", 1); } pCurrent = pCurrent->pNext; } @@ -277,6 +310,7 @@ void SICSLogWrite(char *pText, OutCode eOut) /* switch file if too many lines */ if (iLineCount >= MAXLOG) { + fprintf(fLogFile,"%s: <<>>\n", timestamp(NULL)); fclose(fLogFile); fLogFile = NULL; iFile++; @@ -287,9 +321,225 @@ void SICSLogWrite(char *pText, OutCode eOut) iLogUsable = OpenVerifyLogFile(); } - if (1 == iLogUsable) { - fprintf(fLogFile, "%s\n", pText); + if(1 == iLogUsable) + { + + if (iLineCount == 0) + fprintf(fLogFile,"%s: <<>>\n", timestamp(NULL)); + fprintf(fLogFile,"%s: ", timestamp(tp)); + fprintf(fLogFile,"%s", pText); + if (text_len < 1 || pText[text_len - 1] != '\n') + fprintf(fLogFile,"\n"); fflush(fLogFile); iLineCount++; } } + + void SICSLogWriteTime(char *pText, OutCode eOut, struct timeval *tp) { + char buf[200]; + const char *cp = pText; + int idx = 0; + struct timeval tv; + + if (tp == NULL) { + gettimeofday(&tv, NULL); + tp = &tv; + } + while (*cp) { + if (*cp == '\n') { + buf[idx++] = '\n'; + buf[idx++] = '\0'; + SICSLogWriteFile(buf, eOut, tp); + idx = 0; + } + else if (*cp == '\r') { + buf[idx++] = '\\'; + buf[idx++] = 'r'; + } + else if (*cp == '\t') { + buf[idx++] = '\\'; + buf[idx++] = 't'; + } + else if (*cp < ' ' || *cp > '~') { + const char hex[] = "0123456789ABCDEF"; + buf[idx++] = '<'; + buf[idx++] = hex[(*cp >> 4) & 0xF]; + buf[idx++] = hex[(*cp) & 0xF]; + buf[idx++] = '>'; + } + else { + buf[idx++] = *cp; + } + cp++; + if (idx > 132) { + buf[idx++] = '\n'; + buf[idx++] = '\0'; + SICSLogWriteFile(buf, eOut, tp); + idx = 0; + } + } + if (idx > 0) { + buf[idx++] = '\n'; + buf[idx++] = '\0'; + SICSLogWriteFile(buf, eOut, tp); + } + } + + void SICSLogWrite(char *pText, OutCode eOut) { + struct timeval tv; + gettimeofday(&tv, NULL); + SICSLogWriteTime(pText, eOut, &tv); + } + + void SICSLogWriteHexTime(const char* text, int count, OutCode eOut, struct timeval *tp) { + const char hex[] = "0123456789ABCDEF"; + char addr[20], left[80], right[80]; + char *lp = left; + char *rp = right; + int i; + int duplicates; + /* Limit the output */ + if (count > 1024) + count = 1024; + duplicates = 0; + for (i = 0; i < count; ++i) { + if ((i & 0xF) == 0) { + if (i > 0) { + char line[132]; + snprintf(line, sizeof(line)-1, "%-6s: %-49s | %-17s |", addr, left, right); + SICSLogWriteTime(line, eOut, tp); + } + snprintf(addr, sizeof(addr)-1, "0x%04X", i); + while (i >= 16 && i + 16 < count) { + if (memcmp(&text[i-16], &text[i], 16) != 0) + break; + ++duplicates; + i += 16; + } + if (duplicates > 0) { + if (duplicates > 1) { + char line[132]; + snprintf(line, sizeof(line)-1, "%-6s: ... (%d duplicates)", addr, duplicates); + SICSLogWriteTime(line, eOut, tp); + } + else { + char line[132]; + snprintf(line, sizeof(line)-1, "%-6s: %-49s | %-17s |", addr, left, right); + SICSLogWriteTime(line, eOut, tp); + } + duplicates = 0; + } + snprintf(addr, sizeof(addr)-1, "0x%04X", i); + lp = left; + rp = right; + } + *lp++ = hex[(text[i] >> 4) & 0xF]; + *lp++ = hex[(text[i]) & 0xF]; + *lp++ = ' '; + if (text[i]>= ' ' && text[i] <= '~') + *rp++ = text[i]; + else + *rp++ = '.'; + /* if we just did slot 7, insert an extra space */ + if ((i & 0xF) == 7) { + *lp++ = ' '; + *rp++ = ' '; + } + *lp = *rp = '\0'; + } + if (i > 0) { + char line[132]; + snprintf(line, sizeof(line)-1, "%-6s: %-49s | %-17s |", addr, left, right); + SICSLogWriteTime(line, eOut, tp); + } + } + + void SICSLogWriteHex(const char* text, int count, OutCode eOut) { + struct timeval tv; + gettimeofday(&tv, NULL); + SICSLogWriteHexTime(text, count, eOut, &tv); + } + + void SICSLogTimePrintf(OutCode eOut, struct timeval *tp, const char *fmt, ...) + { + va_list ap; + char buf[256]; + char *dyn; + unsigned int l; + int res; + + va_start(ap, fmt); + l = vsnprintf(buf, sizeof buf, fmt, ap); + va_end(ap); + if (l >= sizeof buf) { + /* we have probably a C99 conforming snprintf and + need a larger buffer + */ + dyn = malloc(l+1); + if (dyn != NULL) { + va_start(ap, fmt); + vsnprintf(dyn, l+1, fmt, ap); + va_end(ap); + SICSLogWriteTime(dyn, eOut, tp); + free(dyn); + return; + } + } + SICSLogWriteTime(buf, eOut, tp); + return; + } + + void SICSLogPrintf(OutCode eOut, const char *fmt, ...) + { + va_list ap; + char buf[256]; + char *dyn; + unsigned int l; + int res; + + va_start(ap, fmt); + l = vsnprintf(buf, sizeof buf, fmt, ap); + va_end(ap); + if (l >= sizeof buf) { + /* we have probably a C99 conforming snprintf and + need a larger buffer + */ + dyn = malloc(l+1); + if (dyn != NULL) { + va_start(ap, fmt); + vsnprintf(dyn, l+1, fmt, ap); + va_end(ap); + SICSLogWrite(dyn, eOut); + free(dyn); + return; + } + } + SICSLogWrite(buf, eOut); + return; + } + +/* Test of the logging facilities */ +int testLogCmd(SConnection *pCon, SicsInterp *pInter, void *pData, int argc, char *argv[]) { + char lbuf[2048]; + char sbuf[1000]; + int i; + SICSLogWrite("Multiline:\nLine 1\r\nLine 2\r\nLine 3\r\n", eStatus); + memset(lbuf, 0, sizeof(lbuf)); + memset(sbuf, ' ', sizeof(sbuf)); + SICSLogPrintf(eStatus, "Hexlog %d all zero bytes", sizeof(lbuf)); + SICSLogWriteHex(lbuf, sizeof(lbuf), eStatus); + for (i = 0; i <= 128; ++i) + sbuf[i] = sbuf[sizeof(sbuf)-1 - i] = i; + sbuf[sizeof(sbuf)/2] = '!'; + SICSLogPrintf(eStatus, "Hexlog %d mid space bytes", sizeof(sbuf)); + SICSLogWriteHex(sbuf, sizeof(sbuf), eStatus); + for (i = 0; i < 1000; ++i) + sbuf[i] = ' ' + (i % 96); + sbuf[sizeof(sbuf)-1] = '\0'; + SICSLogWrite("Very long line 1000 bytes", eStatus); + SICSLogWrite(sbuf, eStatus); + SCSendOK(pCon); + return OKOK; +} + + diff --git a/servlog.h b/servlog.h index c61615f5..f43870ad 100644 --- a/servlog.h +++ b/servlog.h @@ -16,6 +16,11 @@ #define SICSLOG #include "Scommon.h" void SICSLogWrite(char *ptext, OutCode eOut); +void SICSLogWriteTime(char *ptext, OutCode eOut, struct timeval *tp ); +void SICSLogWriteHex(const char* text, int count, OutCode eOut); +void SICSLogWriteHexTime(const char* text, int count, OutCode eOut, struct timeval *tp); +void SICSLogPrintf(OutCode eOut, const char*fmt, ...); +void SICSLogTimePrintf(OutCode eOut, struct timeval *tp, const char *fmt, ...); void SICSLogEnable(int flag); int KillCapture(SConnection * pCon); diff --git a/site_ansto/hardsup/sct_lfprot.c b/site_ansto/hardsup/sct_lfprot.c index 085b9976..ed105d93 100644 --- a/site_ansto/hardsup/sct_lfprot.c +++ b/site_ansto/hardsup/sct_lfprot.c @@ -110,7 +110,8 @@ int LFGenWriteStart(Ascon *a) { pNewBuffer[bufInd] = CRC; bufInd++; //pNewBuffer[bufSize-1] = '\r'; - DynStringReplaceWithLen(a->wrBuffer, pNewBuffer, 0, bufInd); + DynStringClear(a->wrBuffer); + DynStringConcatBytes(a->wrBuffer, pNewBuffer, bufInd); a->wrPos = 0; a->state = AsconWriting; /* if there is only the terminator, do not send it */ diff --git a/site_ansto/hardsup/sct_modbusprot.c b/site_ansto/hardsup/sct_modbusprot.c index 88197c92..dc70c57f 100644 --- a/site_ansto/hardsup/sct_modbusprot.c +++ b/site_ansto/hardsup/sct_modbusprot.c @@ -168,7 +168,8 @@ int ModbusWriteStart(Ascon *a) { if (debug_modbus > 0) { dbgprintx("modbus-xo", (unsigned char*)temp, idx); } - DynStringReplaceWithLen(a->wrBuffer, temp, 0, idx); + DynStringClear(a->wrBuffer); + DynStringConcatBytes(a->wrBuffer, temp, idx); a->state = AsconWriting; a->wrPos = 0; return 1; @@ -230,7 +231,8 @@ int ModbusReading(Ascon *a) { dbgprintx("modbus-xi", cp, blen); } dbgprintf("modbus-rd:%s\n", temp); - DynStringReplaceWithLen(a->rdBuffer, temp, 0, rlen); + DynStringClear(a->rdBuffer); + DynStringConcatBytes(a->rdBuffer, temp, rlen); a->state = AsconReadDone; return 1; } diff --git a/site_ansto/hardsup/sct_orhvpsprot.c b/site_ansto/hardsup/sct_orhvpsprot.c index 519fa875..46f82a7f 100644 --- a/site_ansto/hardsup/sct_orhvpsprot.c +++ b/site_ansto/hardsup/sct_orhvpsprot.c @@ -153,7 +153,8 @@ int OrdHVPSWriteStart(Ascon *a) { pcmdrspfmt++; // skip over the '-' separator into the response format cmd_len=pcmd-cmd; cmd[cmd_len] = '\0'; - DynStringReplaceWithLen(a->wrBuffer,cmd,0,cmd_len); + DynStringClear(a->wrBuffer); + DynStringConcatBytes(a->wrBuffer, cmd, cmd_len); a->state = AsconWriting; a->wrPos = 0; return 1; diff --git a/site_ansto/hardsup/sct_rfamp.c b/site_ansto/hardsup/sct_rfamp.c index c3591530..062cb4e2 100644 --- a/site_ansto/hardsup/sct_rfamp.c +++ b/site_ansto/hardsup/sct_rfamp.c @@ -1,24 +1,24 @@ /** * @brief Protocol handler for Mirrotron RF power supplies - Author: Ferdi Franceschini - - TODO: Provide acknowledgement when setting a parameter - "OK", when successful - "ANSRFAMP: Set failed", on error + Author: Ferdi Franceschini - Current should be ramped up in steps of 0.5A but it doesn't - have to be ramped down. - - Provides two commands (L)ist and (S)et - eg, - The following command lists status info from the RF Amp at address 3. - sct_rfamp send L:3 - The reply string has the following form - address=1|type=L|curr=00|freq=170|voltage=50|K3=1|K2=1|K1=1|O=1|CC=1|CV=0|H=1 + TODO: Provide acknowledgement when setting a parameter + "OK", when successful + "ANSRFAMP: Set failed", on error - The following command sets the current(I), frequency, switches(K1,K2,K3) and output(O). - sct_rfamp send S:3:I=5:F=170:K3=0:K2=1:k1=0:O=1 - NOTE: The current is an integer which equals the desired current x10, ie 71 -> 7.1A + Current should be ramped up in steps of 0.5A but it doesn't + have to be ramped down. + + Provides two commands (L)ist and (S)et + eg, + The following command lists status info from the RF Amp at address 3. + sct_rfamp send L:3 + The reply string has the following form + address=1|type=L|curr=00|freq=170|voltage=50|K3=1|K2=1|K1=1|O=1|CC=1|CV=0|H=1 + + The following command sets the current(I), frequency, switches(K1,K2,K3) and output(O). + sct_rfamp send S:3:I=5:F=170:K3=0:K2=1:k1=0:O=1 + NOTE: The current is an integer which equals the desired current x10, ie 71 -> 7.1A */ #include @@ -83,23 +83,24 @@ int RFAmpWriteStart (Ascon *a) AsconError(a, errMsg, 0); return 1; } - + switch (ctype) { case 'L': sprintf(data->rfCmd,"%c%c%c%c", 2, address, ctype, 3); - DynStringReplaceWithLen(a->wrBuffer, data->rfCmd,0, LCMDLEN); + DynStringClear(a->wrBuffer); + DynStringConcatBytes(a->wrBuffer, data->rfCmd, LCMDLEN); a->state = AsconWriting; a->noResponse = 0; a->wrPos = 0; return 1; - break; + break; case 'S': if (ret < 8) { - snprintf(errMsg, ERRLEN, "ANSRFAMP: Invalid command string %s", dynStrBuffer); - a->state = AsconWriteDone; - a->noResponse = 1; - AsconError(a, errMsg, 0); - return 1; + snprintf(errMsg, ERRLEN, "ANSRFAMP: Invalid command string %s", dynStrBuffer); + a->state = AsconWriteDone; + a->noResponse = 1; + AsconError(a, errMsg, 0); + return 1; } if (address < '1' || address > '9') { snprintf(errMsg, ERRLEN, "ANSRFAMP: Invalid address %c, it should be between 1 and 9", address); @@ -110,7 +111,7 @@ int RFAmpWriteStart (Ascon *a) } if (curr < MINCURRSPEC || curr > MAXCURRSPEC) { snprintf(errMsg, ERRLEN, "ANSRFAMP: Invalid current specifier %d, it should be between %d and %d. NOTE:divide by 10 to convert to Amps", \ - curr, MINCURRSPEC, MAXCURRSPEC); + curr, MINCURRSPEC, MAXCURRSPEC); a->state = AsconWriteDone; a->noResponse = 1; AsconError(a, errMsg, 0); @@ -139,21 +140,22 @@ int RFAmpWriteStart (Ascon *a) return 1; } sprintf(data->statusCmd,"%c%c%c%c", 2, address, 'L', 3); - DynStringReplaceWithLen(a->wrBuffer, data->statusCmd, 0, LCMDLEN); + DynStringClear(a->wrBuffer); + DynStringConcatBytes(a->wrBuffer, data->statusCmd, LCMDLEN); data->transactInProg = txPreSet; data->targetCurrent = curr; a->state = AsconWriting; a->noResponse = 0; a->wrPos = 0; return 1; - break; + break; default: snprintf(errMsg, ERRLEN, "ANSRFAMP: Unknown command type %c, allowed types are 'L' or 'S'", ctype); a->state = AsconWriteDone; a->noResponse = 1; AsconError(a, errMsg, 0); return 1; - break; + break; } } @@ -172,62 +174,64 @@ int RFAmpReading (Ascon *a) if(data->transactInProg == txPostSet){ - data->transactInProg = txCheckReply; + data->transactInProg = txCheckReply; - //Jing: add delay to wait for ramping complete - sleep(data->timeout); + //Jing: add delay to wait for ramping complete + sleep(data->timeout); - DynStringReplaceWithLen(a->wrBuffer, data->statusCmd, 0, LCMDLEN); - a->state = AsconWriting; - a->noResponse = 0; - a->wrPos = 0; - delay = 0; - }else{ - // Start reading when byte = 2 and stop when 3 - while ( ( rdChRet = AsconReadChar(a->fd, &chr) ) > 0) { - a->start = DoubleTime(); - if (a->readState) { - if (a->readState >= LASTBYTENUM) { - a->readState = 0; - if (a->readState > LASTBYTENUM) { - snprintf(errMsg, ERRLEN, "ANSRFAMP: Packet larger than expected, size exceeds %d", LASTBYTENUM); - GetReplyFailed = 1; - break; - } - if (chr != 3) { - snprintf(errMsg, ERRLEN, "ANSRFAMP: Unexpected value %X for packet end signal", chr); - GetReplyFailed = 1; - break; - } - if (0 == DynStringConcatChar(a->rdBuffer, '\0')) { - strcpy(errMsg, "ANSRFAMP: DynStringConcatChar failed:"); - errNum = ENOMEM; - GetReplyFailed = 1; - break; - } - address = GetCharArray(a->rdBuffer)[0]; - ctype = GetCharArray(a->rdBuffer)[1]; + DynStringClear(a->wrBuffer); + DynStringConcatBytes(a->wrBuffer, data->statusCmd, LCMDLEN); + a->state = AsconWriting; + a->noResponse = 0; + a->wrPos = 0; + delay = 0; + } else { + // Start reading when byte = 2 and stop when 3 + while ( ( rdChRet = AsconReadChar(a->fd, &chr) ) > 0) { + a->start = DoubleTime(); + if (a->readState) { + if (a->readState >= LASTBYTENUM) { + a->readState = 0; + if (a->readState > LASTBYTENUM) { + snprintf(errMsg, ERRLEN, "ANSRFAMP: Packet larger than expected, size exceeds %d", LASTBYTENUM); + GetReplyFailed = 1; + break; + } + if (chr != 3) { + snprintf(errMsg, ERRLEN, "ANSRFAMP: Unexpected value %X for packet end signal", chr); + GetReplyFailed = 1; + break; + } + if (0 == DynStringConcatChar(a->rdBuffer, '\0')) { + strcpy(errMsg, "ANSRFAMP: DynStringConcatChar failed:"); + errNum = ENOMEM; + GetReplyFailed = 1; + break; + } + address = GetCharArray(a->rdBuffer)[0]; + ctype = GetCharArray(a->rdBuffer)[1]; memset(curr, 0, sizeof(curr)); memset(freq, 0, sizeof(freq)); memset(voltage, 0, sizeof(voltage)); - strncpy(curr, &GetCharArray(a->rdBuffer)[2], 2); - strncpy(freq, &GetCharArray(a->rdBuffer)[4], 3); - strncpy(voltage, &GetCharArray(a->rdBuffer)[7], 2); - switches = (unsigned char)GetCharArray(a->rdBuffer)[9]; - opstate = GetCharArray(a->rdBuffer)[10]; + strncpy(curr, &GetCharArray(a->rdBuffer)[2], 2); + strncpy(freq, &GetCharArray(a->rdBuffer)[4], 3); + strncpy(voltage, &GetCharArray(a->rdBuffer)[7], 2); + switches = (unsigned char)GetCharArray(a->rdBuffer)[9]; + opstate = GetCharArray(a->rdBuffer)[10]; - if (data->transactInProg == txPreSet) { - data->transactInProg = txPostSet; - if (abs(data->targetCurrent - atoi(curr)) <= (5 + data->currTol)) { - DynStringReplaceWithLen(a->wrBuffer, data->rfCmd,0, SCMDLEN); - delay = round(abs(data->targetCurrent - atoi(curr))/0.5 + 0.5); - a->state = AsconWriting; - a->noResponse = 0; - a->wrPos = 0; - } else { - strcpy(errMsg, "ANSRFAMP: Step size should be <= 5 for current"); - GetReplyFailed = 1; - break; + if (data->transactInProg == txPreSet) { + data->transactInProg = txPostSet; + if (abs(data->targetCurrent - atoi(curr)) <= (5 + data->currTol)) { + DynStringClear(a->wrBuffer); + DynStringConcatBytes(a->wrBuffer, data->rfCmd, SCMDLEN); + delay = round(abs(data->targetCurrent - atoi(curr))/0.5 + 0.5); + a->state = AsconWriting; + a->noResponse = 0; + a->wrPos = 0; + } else { + strcpy(errMsg, "ANSRFAMP: Step size should be <= 5 for current"); + GetReplyFailed = 1; + break; } } else if (data->transactInProg == txCheckReply) { // TODO Compare rdBuffer to rfCmd if they match then set replyStr="OK" else set error message @@ -240,54 +244,55 @@ int RFAmpReading (Ascon *a) strncpy(tmpFreq, &data->rfCmd[5], 3); tmpSwitchs = (unsigned char)data->rfCmd[8]; - // TODO SICS-405 ffr Removed check because the read values don't immediately match the set values + // TODO SICS-405 ffr Removed check because the read values don't immediately match the set values if( (abs(atoi(curr) - atoi(tmpCurr)) > data->currTol) || (atoi(freq) != atoi(tmpFreq)) || ((switches & 0x0F) != (tmpSwitchs & 0x0F)) ) { - strcpy(errMsg, "ANSRFAMP: the (S)ET command failed"); - GetReplyFailed = 1; - break; + strcpy(errMsg, "ANSRFAMP: the (S)ET command failed"); + GetReplyFailed = 1; + break; } else { DynStringReplace(a->rdBuffer, "OK", 0); } - + /* ffr Just report OK until we have a proper fix */ //DynStringReplace(a->rdBuffer, "OK", 0); a->state = AsconReadDone; data->transactInProg = txNormalRead; } else if (data->transactInProg == txNormalRead) { - K3 = (switches & 0x08) >> 3; - K2 = (switches & 0x04) >> 2; - K1 = (switches & 0x02) >> 1; - outOn = switches & 0x01; - CC = (opstate & 0x04) >> 2; - CV = (opstate & 0x02) >> 1; - heat = opstate & 0x01; - snprintf(replyStr, 128, "address=%c|type=%c|curr=%s|freq=%s|voltage=%s|K3=%d|K2=%d|K1=%d|O=%d|CC=%d|CV=%d|H=%d", \ - address, ctype, curr, freq, voltage, K3, K2, K1, outOn, CC, CV, heat); - if (0 == DynStringReplaceWithLen(a->rdBuffer, replyStr, 0, 128)) { - strcpy(errMsg, "ANSRFAMP: DynStringReplace failed:"); - errNum = ENOMEM; - GetReplyFailed = 1; - break; - } - a->state = AsconReadDone; - } - return 1; - } - if (0 == DynStringConcatChar(a->rdBuffer, chr)) { - strcpy(errMsg, "ANSRFAMP: DynStringConcatChar failed:"); - errNum = ENOMEM; - GetReplyFailed = 1; - break; - } - a->readState++; - } else if (chr == 2) { - a->readState = 1; - } - } - } + K3 = (switches & 0x08) >> 3; + K2 = (switches & 0x04) >> 2; + K1 = (switches & 0x02) >> 1; + outOn = switches & 0x01; + CC = (opstate & 0x04) >> 2; + CV = (opstate & 0x02) >> 1; + heat = opstate & 0x01; + snprintf(replyStr, 128, "address=%c|type=%c|curr=%s|freq=%s|voltage=%s|K3=%d|K2=%d|K1=%d|O=%d|CC=%d|CV=%d|H=%d", \ + address, ctype, curr, freq, voltage, K3, K2, K1, outOn, CC, CV, heat); + DynStringClear(a->wrBuffer); + if (0 == DynStringConcatBytes(a->rdBuffer, replyStr, 128)) { + strcpy(errMsg, "ANSRFAMP: DynStringReplace failed:"); + errNum = ENOMEM; + GetReplyFailed = 1; + break; + } + a->state = AsconReadDone; + } + return 1; + } + if (0 == DynStringConcatChar(a->rdBuffer, chr)) { + strcpy(errMsg, "ANSRFAMP: DynStringConcatChar failed:"); + errNum = ENOMEM; + GetReplyFailed = 1; + break; + } + a->readState++; + } else if (chr == 2) { + a->readState = 1; + } + } + } if (rdChRet < 0) { AsconError(a, "ANSRFAMP: AsconReadChar failed:", errno); return 1; @@ -313,16 +318,16 @@ int RFAmpReading (Ascon *a) int RFAmpProtHandler (Ascon *a) { int ret; - + switch (a->state) { case AsconWriteStart: ret = RFAmpWriteStart(a); return ret; - break; + break; case AsconReading: ret = RFAmpReading(a); return ret; - break; + break; default: return AsconStdHandler(a); } @@ -345,11 +350,11 @@ int RFAmpInit(Ascon *a, SConnection *con, int argc, char *argv[]) void AddRFAmpProtocol() { - AsconProtocol *prot = NULL; - - prot = calloc(sizeof(AsconProtocol), 1); - prot->name = strdup("rfamp"); + AsconProtocol *prot = NULL; + + prot = calloc(sizeof(AsconProtocol), 1); + prot->name = strdup("rfamp"); prot->init = RFAmpInit; - prot->handler = RFAmpProtHandler; - AsconInsertProtocol(prot); + prot->handler = RFAmpProtHandler; + AsconInsertProtocol(prot); } diff --git a/site_ansto/hardsup/sct_tcpmodbus.c b/site_ansto/hardsup/sct_tcpmodbus.c index ec3f6d65..ab981991 100644 --- a/site_ansto/hardsup/sct_tcpmodbus.c +++ b/site_ansto/hardsup/sct_tcpmodbus.c @@ -263,7 +263,8 @@ int TCPMBWriteStart(Ascon *a) { PDUlenPlusUID = ADUlen - 6; ADU[4] = (PDUlenPlusUID & 0xFF00) >> 8; ADU[5] = PDUlenPlusUID & 0xFF; - DynStringReplaceWithLen(a->wrBuffer, ADU, 0, ADUlen); + DynStringClear(a->wrBuffer); + DynStringConcatBytes(a->wrBuffer, ADU, ADUlen); a->state = AsconWriting; a->wrPos = 0; return 1; diff --git a/site_ansto/make_gen_variables b/site_ansto/make_gen_variables index 48dbf757..813905df 100644 --- a/site_ansto/make_gen_variables +++ b/site_ansto/make_gen_variables @@ -1,29 +1,29 @@ # vim: ft=make ts=4 sw=4 noet cindent COBJ = Sclient.o network.o ifile.o intcli.o $(FORTIFYOBJ) -SOBJ = access.o alias.o anticollider.o ascon.o asyncprotocol.o asyncqueue.o callback.o \ +SOBJ = alias.o anticollider.o arrayutil.o ascon.o asyncprotocol.o asyncqueue.o asynnet.o background.o callback.o \ cell.o chadapter.o choco.o circular.o commandlog.o cone.o confvirtualmot.o \ - conman.o costa.o danu.o definealias.o devexec.o devser.o diffscan.o d_mod.o \ + conman.o costa.o countersec.o danu.o definealias.o devexec.o devser.o diffscan.o d_mod.o \ drive.o d_sign.o dynstring.o emon.o errormsg.o evcontroller.o evdriver.o \ - event.o exebuf.o exeman.o fitcenter.o fomerge.o $(FORTIFYOBJ) fourlib.o \ - fourtable.o fupa.o gpibcontroller.o help.o hipadaba.o \ - histdriv.o histmem.o histregress.o histsim.o hklmot.o hkl.o \ + event.o exebuf.o exeman.o fitcenter.o fomerge.o $(FORTIFYOBJ) fourlib.o fourmess.o \ + fourtable.o fupa.o genbinprot.o gpibcontroller.o hdbtable.o help.o hipadaba.o \ + histdriv.o histmem.o histmemsec.o histregress.o histsim.o hklmot.o hkl.o \ hmcontrol.o hmdata.o hmslave.o ifile.o initializer.o integrate.o interface.o \ intserv.o lin2ang.o lld_blob.o lld.o logger.o logreader.o logsetup.o lomax.o \ macro.o maximize.o mccontrol.o mcreader.o mcstascounter.o mcstashm.o \ - moregress.o motorlist.o motreglist.o motreg.o multicounter.o mumoconf.o mumo.o \ + moregress.o motorlist.o motorsec.o motreglist.o motreg.o multicounter.o mumoconf.o mumo.o \ napi5.o napi.o network.o $(NIOBJ) nread.o nserver.o nwatch.o nxcopy.o \ nxdataset.o nxdict.o nxinterhelper.o nxinter_wrap.o nxio.o nxscript.o nxstack.o \ nxupdate.o nxutil.o nxxml.o o2t.o obdes.o obpar.o ofac.o optimise.o oscillate.o \ - passwd.o perfmon.o polldriv.o protocol.o proxy.o regresscter.o remob.o \ - rmtrail.o rs232controller.o savehdb.o scaldate.o scan.o scanvar.o SCinter.o \ + passwd.o perfmon.o polldriv.o protocol.o proxy.o reflist.o regresscter.o remob.o \ + rmtrail.o rs232controller.o rwpuffer.o sansbc.o savehdb.o scaldate.o scan.o scanvar.o SCinter.o \ scriptcontext.o script.o sctdriveadapter.o sctdriveobj.o sdynar.o selector.o \ - selvar.o servlog.o sicscron.o sicsdata.o sicsexit.o sicshdbadapter.o \ - sicshdbfactory.o sicshipadaba.o sicslist.o SICSmain.o sicsobj.o sicspoll.o \ - sicvar.o sig_die.o simchop.o simev.o sinfox.o splitter.o s_rnge.o statemon.o \ - statistics.o statusfile.o status.o stdscan.o stptok.o stringdict.o strrepl.o \ - synchronize.o tasdrive.o task.o tasscanub.o tasublib.o tasub.o tcldrivable.o \ - tclev.o tclintimpl.o telnet.o token.o trigd.o trim.o ubcalc.o \ - ubfour.o udpquieck.o userscan.o uubuffer.o varlog.o vector.o wwildcard.o \ + selvar.o servlog.o sgclib.o sghkl.o sgio.o sicscron.o sicsdata.o sicsexit.o sicshdbadapter.o \ + sicshdbfactory.o sicshipadaba.o sicslist.o SICSmain.o sicsobj.o sicspoll.o sicsutil.o \ + sicvar.o sig_die.o simchop.o simev.o simidx.o simindex.o sinfox.o singlebi.o singlediff.o singlenb.o singlebinb.o singletas.o singlex.o splitter.o s_rnge.o statemon.o \ + statistics.o statusfile.o status.o stdscan.o stptok.o stringdict.o strlutil.o strrepl.o \ + syncedprot.o synchronize.o tasdrive.o task.o tasscanub.o tasublib.o tasub.o tcldrivable.o \ + tclev.o tclintimpl.o tclmotdriv.o telnet.o testprot.o token.o trace.o trigd.o trim.o ubcalc.o \ + ubfour.o udpquieck.o uselect.o userscan.o uubuffer.o varlog.o vector.o velosec.o wwildcard.o \ xytable.o # These are intermediate files generated from .tc files, marking