// ... decrement all timers; return shortest delta on list static ULONG updateTimers (ULONG delta) { register TIMER_ID timer; ULONG retVal = 0xFFFFFFFF; for (timer = (TIMER_ID) radListGetFirst (&timerList->pendingList); timer != NULL; timer = (TIMER_ID) radListGetNext (&timerList->pendingList, (NODE_PTR)timer)) { if (timer->deltaTime <= delta) { timer->deltaTime = 0; } else { timer->deltaTime -= delta; } if (timer->deltaTime < retVal) { retVal = timer->deltaTime; } } return retVal; }
static void pushLoopToClients(LOOP_PKT* loopData) { WVIEW_ALARM_CLIENT *client, *oldClient; LOOP_PKT networkLoop; datafeedConvertLOOP_HTON(&networkLoop, loopData); // Push to each socket client: for (client = (WVIEW_ALARM_CLIENT *) radListGetFirst (&alarmsWork.clientList); client != NULL; client = (WVIEW_ALARM_CLIENT *) radListGetNext (&alarmsWork.clientList, (NODE_PTR)client)) { // write the frame start so clients may sync to the beginning of each // data update if (radSocketWriteExact (client->client, (void *)DF_LOOP_START_FRAME, DF_START_FRAME_LENGTH) != DF_START_FRAME_LENGTH) { // write error, bail on this guy radMsgLog (PRI_HIGH, "LOOP: write error to client %s:%d - closing socket...", radSocketGetHost (client->client), radSocketGetPort (client->client)); statusDecrementStat(ALARM_STATS_CLIENTS); radProcessIODeRegisterDescriptorByFd(radSocketGetDescriptor(client->client)); radSocketDestroy (client->client); oldClient = client; client = (WVIEW_ALARM_CLIENT *) radListGetPrevious (&alarmsWork.clientList, (NODE_PTR)client); radListRemove (&alarmsWork.clientList, (NODE_PTR)oldClient); free (oldClient); continue; } // write out the loop data in network byte order: if (radSocketWriteExact(client->client, &networkLoop, sizeof(networkLoop)) != sizeof(networkLoop)) { // write error, bail on this guy radMsgLog (PRI_HIGH, "LOOP: write error to client %s:%d - closing socket...", radSocketGetHost (client->client), radSocketGetPort (client->client)); statusDecrementStat(ALARM_STATS_CLIENTS); radProcessIODeRegisterDescriptorByFd(radSocketGetDescriptor(client->client)); radSocketDestroy (client->client); oldClient = client; client = (WVIEW_ALARM_CLIENT *) radListGetPrevious (&alarmsWork.clientList, (NODE_PTR)client); radListRemove (&alarmsWork.clientList, (NODE_PTR)oldClient); free (oldClient); continue; } statusIncrementStat(ALARM_STATS_PKTS_SENT); } return; }
void raddatabaseRowDescriptionDelete ( ROW_ID row ) { FIELD_ID field; for (field = (FIELD_ID) radListGetFirst (&row->fields); field != NULL; field = (FIELD_ID) radListGetFirst (&row->fields)) { if ((field->type & FIELD_STRING) || (field->type & FIELD_DATETIME)) { free (field->cvalue); } radListRemove (&row->fields, (NODE_PTR)field); free (field); } free (row); }
float sensorAccumGetTotal (WV_ACCUM_ID id) { WV_ACCUM_SAMPLE* nodePtr; float sum = 0; // Do we need to age off any nodes? AgeAccumulator (id); for (nodePtr = (WV_ACCUM_SAMPLE*)radListGetFirst (&id->samples); nodePtr != NULL; nodePtr = (WV_ACCUM_SAMPLE*)radListGetNext (&id->samples, (NODE_PTR)nodePtr)) { sum += nodePtr->value; } return sum; }
static WVIEW_ALARM_CLIENT* FindClient(RADSOCK_ID clientSock) { WVIEW_ALARM_CLIENT* node; for (node = (WVIEW_ALARM_CLIENT*)radListGetFirst(&alarmsWork.clientList); node != NULL; node = (WVIEW_ALARM_CLIENT*)radListGetNext(&alarmsWork.clientList, (NODE_PTR)node)) { if (node->client == clientSock) { // found him! return node; } } return NULL; }
int radTimerListDebug (void) { register TIMER_ID next; radMsgLog(PRI_HIGH, "################## radTimerListDebug START ##################"); for (next = (TIMER_ID) radListGetFirst (&timerList->pendingList); next != NULL; next = (TIMER_ID) radListGetNext (&timerList->pendingList, (NODE_PTR)next)) { if (next->routine) { radMsgLog(PRI_HIGH, "Timer-%8.8X: delta: %u, pending: %d, routine: %8.8X", (ULONG)next, next->deltaTime, next->pending, (ULONG)next->routine); } } radMsgLog(PRI_HIGH, "################## radTimerListDebug END ##################"); }
/* ... get the field of interest; returns FIELD_ID or NULL */ FIELD_ID raddatabaseFieldGet ( ROW_ID id, const char *fieldName ) { FIELD_ID field; for (field = (FIELD_ID) radListGetFirst (&id->fields); field != NULL; field = (FIELD_ID) radListGetNext (&id->fields, (NODE_PTR)field)) { if (!strcasecmp (field->name, fieldName)) { return field; } } return NULL; }
static void RemoveClient(RADSOCK_ID clientSock) { WVIEW_ALARM_CLIENT* node; for (node = (WVIEW_ALARM_CLIENT*)radListGetFirst(&alarmsWork.clientList); node != NULL; node = (WVIEW_ALARM_CLIENT*)radListGetNext(&alarmsWork.clientList, (NODE_PTR)node)) { if (node->client == clientSock) { // found him! statusDecrementStat(ALARM_STATS_CLIENTS); radListRemove(&alarmsWork.clientList, (NODE_PTR)node); radProcessIODeRegisterDescriptorByFd(radSocketGetDescriptor(node->client)); radSocketDestroy(node->client); free(node); return; } } }
static void pushArchiveToClients(ARCHIVE_PKT* archive) { WVIEW_ALARM_CLIENT *client, *oldClient; ARCHIVE_PKT networkArchive; datafeedConvertArchive_HTON(&networkArchive, archive); // Push to each socket client: for (client = (WVIEW_ALARM_CLIENT *) radListGetFirst (&alarmsWork.clientList); client != NULL; client = (WVIEW_ALARM_CLIENT *) radListGetNext (&alarmsWork.clientList, (NODE_PTR)client)) { // Check for archive sync in progress: if (client->syncInProgress) { continue; } // Write start frame and archive packet on the socket: if (WriteArchiveToClient(client->client, &networkArchive) == ERROR) { // write error, bail on this guy radMsgLog (PRI_HIGH, "ARCHIVE: write error to client %s:%d - closing socket...", radSocketGetHost (client->client), radSocketGetPort (client->client)); statusDecrementStat(ALARM_STATS_CLIENTS); radProcessIODeRegisterDescriptorByFd(radSocketGetDescriptor(client->client)); radSocketDestroy (client->client); oldClient = client; client = (WVIEW_ALARM_CLIENT *) radListGetPrevious (&alarmsWork.clientList, (NODE_PTR)client); radListRemove (&alarmsWork.clientList, (NODE_PTR)oldClient); free (oldClient); continue; } } return; }
// ... process expired timers static void processExpiredTimers (void) { register TIMER_ID timer, prevTimer; SYS_CALLBACK_MSG cbMsg; int retVal; for (timer = (TIMER_ID) radListGetFirst (&timerList->pendingList); timer != NULL; timer = (TIMER_ID) radListGetNext (&timerList->pendingList, (NODE_PTR)timer)) { if (timer->deltaTime == 0) { // remove from pending list prevTimer = (TIMER_ID) radListGetPrevious (&timerList->pendingList, (NODE_PTR)timer); radListRemove (&timerList->pendingList, (NODE_PTR)timer); timer->pending = FALSE; // send expiry notification if (timer->routine != NULL) { cbMsg.length = sizeof (cbMsg) - sizeof (cbMsg.length); cbMsg.msgType = 0; cbMsg.callback = timer->routine; cbMsg.parm = timer->parm; retVal = write (timerList->notifyFD, &cbMsg, sizeof (cbMsg)); if (retVal != sizeof (cbMsg)) { radMsgLog(PRI_HIGH, "processExpiredTimers: write to notify fd failed: %s", strerror (errno)); } } timer = prevTimer; } } return; }
/* ... traverse the result set row by row */ ROW_ID raddatabaseResultsGetFirst (RESULT_SET_ID id) { id->current = (ROW_ID)radListGetFirst (&id->rows); return id->current; }
int htmlmgrGenerate ( HTML_MGR_ID id ) { register HTML_IMG *img; int retVal, imgs = 0, htmls = 0; char temp[256]; struct stat fileData; GenerateTime = radTimeGetMSSinceEpoch (); #if __DEBUG_BUFFERS radMsgLog (PRI_STATUS, "DBG BFRS: HTML BEGIN: %u of %u available", buffersGetAvailable (), buffersGetTotal ()); #endif // ... compute the Barometric Pressure trend computeBPTrend (id); #if DEBUG_GENERATION radMsgLog (PRI_MEDIUM, "GENERATE: images"); #endif // ... generate the weather images for (img = (HTML_IMG *)radListGetFirst (&id->imgList); img != NULL; img = (HTML_IMG *)radListGetNext (&id->imgList, (NODE_PTR)img)) { retVal = (*img->generator) (img); if (retVal == OK) { imgs ++; } else if (retVal != ERROR_ABORT) { sprintf (temp, "%s/%s", id->imagePath, img->fname); radMsgLog (PRI_HIGH, "%s generation failed - must be local to the wview server!", temp); radMsgLog (PRI_HIGH, "Otherwise you may be including data in " "images.conf for which you do not have sensors?!?"); } } // ... clear the archiveAvailable flag (must be after generator loop) id->newArchiveMask = 0; #if DEBUG_GENERATION radMsgLog (PRI_MEDIUM, "GENERATE: pre-generate script"); #endif // If the wview pre-generation script exists, run it now sprintf (temp, "%s/%s", WVIEW_CONFIG_DIR, HTML_PRE_GEN_SCRIPT); if (stat (temp, &fileData) == 0) { // File exists, run it radStartProcess (newProcessEntryPoint, temp); } #if DEBUG_GENERATION radMsgLog (PRI_MEDIUM, "GENERATE: templates"); #endif // ... now generate the HTML if ((htmls = htmlgenOutputFiles(id, GenerateTime)) == ERROR) { return ERROR; } wvutilsLogEvent(PRI_STATUS, "Generated: %u ms: %d images, %d template files", (uint32_t)(radTimeGetMSSinceEpoch() - GenerateTime), imgs, htmls); id->imagesGenerated += imgs; id->templatesGenerated += htmls; statusUpdateStat(HTML_STATS_IMAGES_GENERATED, id->imagesGenerated); statusUpdateStat(HTML_STATS_TEMPLATES_GENERATED, id->templatesGenerated); #if __DEBUG_BUFFERS radMsgLog (PRI_STATUS, "DBG BFRS: HTML END: %u of %u available", buffersGetAvailable (), buffersGetTotal ()); #endif #if DEBUG_GENERATION radMsgLog (PRI_MEDIUM, "GENERATE: post-generate script"); #endif // Finally, if the wview post-generation script exists, run it now sprintf (temp, "%s/%s", WVIEW_CONFIG_DIR, HTML_POST_GEN_SCRIPT); if (stat (temp, &fileData) == 0) { // File exists, run it radStartProcess (newProcessEntryPoint, temp); } #if DEBUG_GENERATION radMsgLog (PRI_MEDIUM, "GENERATE: DONE"); #endif return OK; }
static void processAlarms (LOOP_PKT *loopData) { WVIEW_ALARM *alarm; float tempFloat; // process the local alarms: for (alarm = (WVIEW_ALARM *) radListGetFirst (&alarmsWork.alarmList); alarm != NULL; alarm = (WVIEW_ALARM *) radListGetNext (&alarmsWork.alarmList, (NODE_PTR)alarm)) { // first check to see if we are in abatement if (alarm->triggered) { if ((radTimeGetSECSinceEpoch () - alarm->abateStart) < alarm->abateSecs) { // abatement - go to the next alarm continue; } else { // clear trigger for future alarms alarm->triggered = FALSE; } } // switch on alarm type switch (alarm->type) { case Barometer: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertINHGToHPA(loopData->barometer); } else { tempFloat = loopData->barometer; } break; case InsideTemp: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertFToC(loopData->inTemp); } else { tempFloat = loopData->inTemp; } break; case InsideHumidity: tempFloat = (float)loopData->inHumidity; break; case OutsideTemp: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertFToC(loopData->outTemp); } else { tempFloat = loopData->outTemp; } break; case WindSpeed: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertMPHToKPH((float)loopData->windSpeed); } else { tempFloat = (float)loopData->windSpeed; } break; case TenMinuteAvgWindSpeed: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertMPHToKPH((float)loopData->tenMinuteAvgWindSpeed); } else { tempFloat = (float)loopData->tenMinuteAvgWindSpeed; } break; case WindDirection: tempFloat = (float)loopData->windDir; break; case OutsideHumidity: tempFloat = (float)loopData->outHumidity; break; case RainRate: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertRainINToMetric(loopData->rainRate); } else { tempFloat = loopData->rainRate; } break; case StormRain: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertRainINToMetric(loopData->stormRain); } else { tempFloat = loopData->stormRain; } break; case DayRain: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertRainINToMetric(loopData->dayRain); } else { tempFloat = loopData->dayRain; } break; case MonthRain: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertRainINToMetric(loopData->monthRain); } else { tempFloat = loopData->monthRain; } break; case YearRain: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertRainINToMetric(loopData->yearRain); } else { tempFloat = loopData->yearRain; } break; case TxBatteryStatus: tempFloat = (float)loopData->txBatteryStatus; break; case ConsoleBatteryVoltage: tempFloat = (((float)loopData->consBatteryVoltage * 300)/512)/100; break; case DewPoint: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertFToC(loopData->dewpoint); } else { tempFloat = loopData->dewpoint; } break; case WindChill: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertFToC(loopData->windchill); } else { tempFloat = loopData->windchill; } break; case HeatIndex: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertFToC(loopData->heatindex); } else { tempFloat = loopData->heatindex; } break; case Radiation: tempFloat = (float)loopData->radiation; break; case UV: tempFloat = (float)loopData->UV; break; case ET: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertRainINToMetric(loopData->dayET); } else { tempFloat = loopData->dayET; } break; case ExtraTemp1: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertFToC(loopData->extraTemp1); } else { tempFloat = loopData->extraTemp1; } break; case ExtraTemp2: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertFToC(loopData->extraTemp2); } else { tempFloat = loopData->extraTemp2; } break; case ExtraTemp3: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertFToC(loopData->extraTemp3); } else { tempFloat = loopData->extraTemp3; } break; case SoilTemp1: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertFToC(loopData->soilTemp1); } else { tempFloat = loopData->soilTemp1; } break; case SoilTemp2: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertFToC(loopData->soilTemp2); } else { tempFloat = loopData->soilTemp2; } break; case SoilTemp3: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertFToC(loopData->soilTemp3); } else { tempFloat = loopData->soilTemp3; } break; case SoilTemp4: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertFToC(loopData->soilTemp4); } else { tempFloat = loopData->soilTemp4; } break; case LeafTemp1: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertFToC(loopData->leafTemp1); } else { tempFloat = loopData->leafTemp1; } break; case LeafTemp2: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertFToC(loopData->leafTemp2); } else { tempFloat = loopData->leafTemp2; } break; case ExtraHumid1: tempFloat = (float)loopData->extraHumid1; break; case ExtraHumid2: tempFloat = (float)loopData->extraHumid2; break; case Wxt510Hail: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertRainINToMetric(loopData->wxt510Hail); } else { tempFloat = loopData->wxt510Hail; } break; case Wxt510Hailrate: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertRainINToMetric(loopData->wxt510Hailrate); } else { tempFloat = loopData->wxt510Hailrate; } break; case Wxt510HeatingTemp: if (alarmsWork.isMetric) { tempFloat = wvutilsConvertFToC(loopData->wxt510HeatingTemp); } else { tempFloat = loopData->wxt510HeatingTemp; } break; case Wxt510HeatingVoltage: tempFloat = loopData->wxt510HeatingVoltage; break; case Wxt510SupplyVoltage: tempFloat = loopData->wxt510SupplyVoltage; break; case Wxt510ReferenceVoltage: tempFloat = loopData->wxt510ReferenceVoltage; break; default: // no match, blow it off continue; } // see if we tripped the breaker here if (alarm->isMax) { if (tempFloat >= alarm->bound) { // we did! alarm->triggered = TRUE; alarm->triggerValue = tempFloat; alarm->abateStart = radTimeGetSECSinceEpoch (); // run user script here statusIncrementStat(ALARM_STATS_SCRIPTS_RUN); if (executeScript (alarm) != 0) { radMsgLog (PRI_MEDIUM, "processAlarms: script %s failed", alarm->scriptToRun); } } } else { if (tempFloat <= alarm->bound) { // we did! alarm->triggered = TRUE; alarm->triggerValue = tempFloat; alarm->abateStart = radTimeGetSECSinceEpoch (); // run user script here statusIncrementStat(ALARM_STATS_SCRIPTS_RUN); if (executeScript (alarm) != 0) { radMsgLog (PRI_MEDIUM, "processAlarms: script %s failed", alarm->scriptToRun); } } } } return; }
/* ... the main entry point for the alarm process */ int main (int argc, char *argv[]) { void (*alarmHandler)(int); int retVal; FILE *pidfile; WVIEW_ALARM *alarm; int runAsDaemon = TRUE; if (argc > 1) { if (!strcmp(argv[1], "-f")) { runAsDaemon = FALSE; } } memset (&alarmsWork, 0, sizeof (alarmsWork)); radListReset (&alarmsWork.alarmList); radListReset (&alarmsWork.clientList); /* ... initialize some system stuff first */ retVal = alarmsSysInit (&alarmsWork); if (retVal == ERROR) { radMsgLogInit (PROC_NAME_ALARMS, FALSE, TRUE); radMsgLog (PRI_CATASTROPHIC, "wvalarmd sysinit failed!"); radMsgLogExit (); exit (1); } else if (retVal == ERROR_ABORT) { exit (2); } /* ... call the global radlib system init function */ if (radSystemInit (WVIEW_SYSTEM_ID) == ERROR) { radMsgLogInit (PROC_NAME_ALARMS, TRUE, TRUE); radMsgLog (PRI_CATASTROPHIC, "radSystemInit failed!"); radMsgLogExit (); exit (1); } /* ... call the radlib process init function */ if (radProcessInit (PROC_NAME_ALARMS, alarmsWork.fifoFile, PROC_NUM_TIMERS_ALARMS, runAsDaemon, // TRUE for daemon msgHandler, evtHandler, NULL) == ERROR) { printf ("\nradProcessInit failed: %s\n\n", PROC_NAME_ALARMS); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } alarmsWork.myPid = getpid (); pidfile = fopen (alarmsWork.pidFile, "w"); if (pidfile == NULL) { radMsgLog (PRI_CATASTROPHIC, "lock file create failed!"); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } fprintf (pidfile, "%d", getpid ()); fclose (pidfile); alarmHandler = radProcessSignalGetHandler (SIGALRM); radProcessSignalCatchAll (defaultSigHandler); radProcessSignalCatch (SIGALRM, alarmHandler); radProcessSignalRelease(SIGABRT); // grab all of our alarm definitions from the config database retVal = readAlarmsConfig (); if (retVal == ERROR_ABORT) { radMsgLog (PRI_HIGH, "ALARM daemon not enabled - exiting..."); alarmsSysExit (&alarmsWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (0); } else if (retVal < 0) { radMsgLog (PRI_HIGH, "readAlarmsConfig failed - " "is there a problem with the wview config database?"); alarmsSysExit (&alarmsWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } else { radMsgLog (PRI_STATUS, "alarms: added %d alarm definitions", retVal); } if (statusInit(alarmsWork.statusFile, alarmsStatusLabels) == ERROR) { radMsgLog (PRI_HIGH, "ALARM status init failed - exiting..."); alarmsSysExit (&alarmsWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } statusUpdate(STATUS_BOOTING); statusUpdateStat(ALARM_STATS_ALARMS, retVal); // wait a bit here before continuing radUtilsSleep (500); // register with the radlib message router if (radMsgRouterInit (WVIEW_RUN_DIR) == ERROR) { statusUpdateMessage("radMsgRouterInit failed!"); radMsgLog (PRI_HIGH, "radMsgRouterInit failed!"); statusUpdate(STATUS_ERROR); alarmsSysExit (&alarmsWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // enable message reception from the radlib router for SHUTDOWN msgs radMsgRouterMessageRegister (WVIEW_MSG_TYPE_SHUTDOWN); // wait for the wview daemon to be ready if (waitForWviewDaemon () == ERROR) { radMsgLog (PRI_HIGH, "waitForWviewDaemon failed"); statusUpdate(STATUS_ERROR); radMsgRouterExit (); alarmsSysExit (&alarmsWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // finally, initialize our data feed socket alarmsWork.dataFeedServer = radSocketServerCreate(WV_DATAFEED_PORT); if (alarmsWork.dataFeedServer == NULL) { statusUpdateMessage("radSocketServerCreate failed"); radMsgLog (PRI_HIGH, "radSocketServerCreate failed..."); statusUpdate(STATUS_ERROR); radMsgRouterExit (); alarmsSysExit (&alarmsWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // add it to our descriptors of interest if (radProcessIORegisterDescriptor(radSocketGetDescriptor(alarmsWork.dataFeedServer), dataFeedAccept, NULL) == ERROR) { statusUpdateMessage("radProcessIORegisterDescriptor server failed"); radMsgLog (PRI_HIGH, "radProcessIORegisterDescriptor failed..."); statusUpdate(STATUS_ERROR); radSocketDestroy (alarmsWork.dataFeedServer); radMsgRouterExit (); alarmsSysExit (&alarmsWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // enable message reception from the radlib router for loop data radMsgRouterMessageRegister (WVIEW_MSG_TYPE_LOOP_DATA_SVC); // enable message reception from the radlib router for archive data radMsgRouterMessageRegister (WVIEW_MSG_TYPE_ARCHIVE_DATA); // enable message reception from the radlib router for POLL msgs radMsgRouterMessageRegister (WVIEW_MSG_TYPE_POLL); // enter normal processing alarmsWork.inMainLoop = TRUE; statusUpdate(STATUS_RUNNING); statusUpdateMessage("Normal operation"); radMsgLog (PRI_STATUS, "running..."); // Do we need to trigger a test alarm? if (alarmsWork.doTest) { if (1 <= alarmsWork.doTestNumber && alarmsWork.doTestNumber <= ALARMS_MAX) { // Generate the bad boy: retVal = 1; for (alarm = (WVIEW_ALARM *) radListGetFirst (&alarmsWork.alarmList); retVal <= ALARMS_MAX && alarm != NULL; alarm = (WVIEW_ALARM *) radListGetNext (&alarmsWork.alarmList, (NODE_PTR)alarm)) { if (retVal == alarmsWork.doTestNumber) { // This is the one to test: alarm->triggerValue = -1; // run user script here if (executeScript(alarm) != 0) { radMsgLog (PRI_MEDIUM, "Test Alarm %d: script %s failed", retVal, alarm->scriptToRun); } else { radMsgLog (PRI_MEDIUM, "Test Alarm %d: script %s executed", retVal, alarm->scriptToRun); } retVal = ALARMS_MAX; } retVal ++; } } else { radMsgLog (PRI_MEDIUM, "Test Alarm: bad alarm index %d given!", alarmsWork.doTestNumber); } } while (!alarmsWork.exiting) { // wait on something interesting if (radProcessWait (0) == ERROR) { alarmsWork.exiting = TRUE; } } statusUpdateMessage("exiting normally"); radMsgLog (PRI_STATUS, "exiting normally..."); statusUpdate(STATUS_SHUTDOWN); radSocketDestroy (alarmsWork.dataFeedServer); radMsgRouterExit (); alarmsSysExit (&alarmsWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (0); }