static int RestoreConnection(WVIEWD_WORK *work) { if (ethernetMediumInit (&work->medium, work->stationHost, work->stationPort) == ERROR) { radMsgLog (PRI_HIGH, "RestoreConnection: ethernet MediumInit failed"); return ERROR_ABORT; } // initialize the interface using the media specific routine if ((*(work->medium.init))(&work->medium, work->stationDevice) == ERROR) { radMsgLog (PRI_HIGH, "RestoreConnection: medium setup failed"); return ERROR; } // Make the socket blocking: radSocketSetBlocking ((*(work->medium.getsocket))(&work->medium), TRUE); return OK; }
// station-supplied init function // -- Can Be Asynchronous - event indication required -- // // MUST: // - set the 'stationGeneratesArchives' flag in WVIEWD_WORK: // if the station generates archive records (TRUE) or they should be // generated automatically by the daemon from the sensor readings (FALSE) // - Initialize the 'stationData' store for station work area // - Initialize the interface medium // - do initial LOOP acquisition // - do any catch-up on archive records if there is a data logger // - 'work->runningFlag' can be used for start up synchronization but should // not be modified by the station interface code // - indicate init is done by sending the STATION_INIT_COMPLETE_EVENT event to // this process (radProcessEventsSend (NULL, STATION_INIT_COMPLETE_EVENT, 0)) // // OPTIONAL: // - Initialize a state machine or any other construct required for the // station interface - these should be stored in the 'stationData' store // // 'archiveIndication' - indication callback used to pass back an archive record // generated as a result of 'stationGetArchive' being called; should receive a // NULL pointer for 'newRecord' if no record available; only used if // 'stationGeneratesArchives' flag is set to TRUE by the station interface // // Returns: OK or ERROR // int stationInit ( WVIEWD_WORK *work, void (*archiveIndication)(ARCHIVE_PKT* newRecord) ) { int i; STIM stim; memset (&ws2300WorkData, 0, sizeof(ws2300WorkData)); // save the archive indication callback (we should never need it) ArchiveIndicator = archiveIndication; // set our work data pointer work->stationData = &ws2300WorkData; // set the Archive Generation flag to indicate the WS-2300 DOES NOT // generate them work->stationGeneratesArchives = FALSE; // initialize the medium abstraction based on user configuration if (!strcmp (work->stationInterface, "serial")) { if (serialMediumInit (&work->medium, serialPortConfig, O_RDWR | O_NOCTTY | O_NDELAY) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: serial MediumInit failed"); return ERROR; } } else if (!strcmp (work->stationInterface, "ethernet")) { if (ethernetMediumInit (&work->medium, work->stationHost, work->stationPort) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: ethernet MediumInit failed"); return ERROR; } } else { radMsgLog (PRI_HIGH, "stationInit: medium %s not supported", work->stationInterface); return ERROR; } // initialize the interface using the media specific routine if ((*(work->medium.init)) (&work->medium, work->stationDevice) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: medium setup failed"); return ERROR; } if (!strcmp (work->stationInterface, "serial")) { radMsgLog (PRI_STATUS, "WS-2300 on %s opened ...", work->stationDevice); } else if (!strcmp (work->stationInterface, "ethernet")) { radMsgLog (PRI_STATUS, "WS-2300 on %s:%d opened ...", work->stationHost, work->stationPort); } // grab the station configuration now if (stationGetConfigValueInt (work, STATION_PARM_ELEVATION, &ws2300WorkData.elevation) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: stationGetConfigValueInt ELEV failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } if (stationGetConfigValueFloat (work, STATION_PARM_LATITUDE, &ws2300WorkData.latitude) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: stationGetConfigValueInt LAT failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } if (stationGetConfigValueFloat (work, STATION_PARM_LONGITUDE, &ws2300WorkData.longitude) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: stationGetConfigValueInt LONG failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } if (stationGetConfigValueInt (work, STATION_PARM_ARC_INTERVAL, &ws2300WorkData.archiveInterval) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: stationGetConfigValueInt ARCINT failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } // now initialize the state machine ws2300WorkData.stateMachine = radStatesInit (work); if (ws2300WorkData.stateMachine == NULL) { radMsgLog (PRI_HIGH, "stationInit: radStatesInit failed"); (*(work->medium.exit)) (&work->medium); return ERROR; } if (radStatesAddHandler (ws2300WorkData.stateMachine, WS_STATE_STARTPROC, wsStartProcState) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: radStatesAddHandler failed"); radStatesExit (ws2300WorkData.stateMachine); (*(work->medium.exit)) (&work->medium); return ERROR; } if (radStatesAddHandler (ws2300WorkData.stateMachine, WS_STATE_RUN, wsRunState) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: radStatesAddHandler failed"); radStatesExit (ws2300WorkData.stateMachine); (*(work->medium.exit)) (&work->medium); return ERROR; } if (radStatesAddHandler (ws2300WorkData.stateMachine, WS_STATE_ADRS0_ACK, wsAdrs0State) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: radStatesAddHandler failed"); radStatesExit (ws2300WorkData.stateMachine); (*(work->medium.exit)) (&work->medium); return ERROR; } if (radStatesAddHandler (ws2300WorkData.stateMachine, WS_STATE_ADRS1_ACK, wsAdrs1State) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: radStatesAddHandler failed"); radStatesExit (ws2300WorkData.stateMachine); (*(work->medium.exit)) (&work->medium); return ERROR; } if (radStatesAddHandler (ws2300WorkData.stateMachine, WS_STATE_ADRS2_ACK, wsAdrs2State) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: radStatesAddHandler failed"); radStatesExit (ws2300WorkData.stateMachine); (*(work->medium.exit)) (&work->medium); return ERROR; } if (radStatesAddHandler (ws2300WorkData.stateMachine, WS_STATE_ADRS3_ACK, wsAdrs3State) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: radStatesAddHandler failed"); radStatesExit (ws2300WorkData.stateMachine); (*(work->medium.exit)) (&work->medium); return ERROR; } if (radStatesAddHandler (ws2300WorkData.stateMachine, WS_STATE_NUMBYTES_ACK, wsNumBytesState) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: radStatesAddHandler failed"); radStatesExit (ws2300WorkData.stateMachine); (*(work->medium.exit)) (&work->medium); return ERROR; } if (radStatesAddHandler (ws2300WorkData.stateMachine, WS_STATE_ERROR, wsErrorState) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: radStatesAddHandler failed"); radStatesExit (ws2300WorkData.stateMachine); (*(work->medium.exit)) (&work->medium); return ERROR; } radStatesSetState (ws2300WorkData.stateMachine, WS_STATE_STARTPROC); radMsgLog (PRI_STATUS, "Starting station interface: WS2300"); // dummy up a stimulus to get the state machine running stim.type = STIM_DUMMY; radStatesProcess (ws2300WorkData.stateMachine, &stim); return OK; }
// station-supplied init function // -- Can Be Asynchronous - event indication required -- // // MUST: // - set the 'stationGeneratesArchives' flag in WVIEWD_WORK: // if the station generates archive records (TRUE) or they should be // generated automatically by the daemon from the sensor readings (FALSE) // - Initialize the 'stationData' store for station work area // - Initialize the interface medium // - do initial LOOP acquisition // - do any catch-up on archive records if there is a data logger // - 'work->runningFlag' can be used for start up synchronization but should // not be modified by the station interface code // - indicate init is done by sending the STATION_INIT_COMPLETE_EVENT event to // this process (radProcessEventsSend (NULL, STATION_INIT_COMPLETE_EVENT, 0)) // // OPTIONAL: // - Initialize a state machine or any other construct required for the // station interface - these should be stored in the 'stationData' store // // 'archiveIndication' - indication callback used to pass back an archive record // generated as a result of 'stationGetArchive' being called; should receive a // NULL pointer for 'newRecord' if no record available; only used if // 'stationGeneratesArchives' flag is set to TRUE by the station interface // // Returns: OK or ERROR // int stationInit ( WVIEWD_WORK *work, void (*archiveIndication)(ARCHIVE_PKT* newRecord) ) { int i; time_t nowTime = time(NULL) - (WV_SECONDS_IN_HOUR * 12); ARCHIVE_PKT recordStore; ARCHIVE_PKT newestRecord; char tempStr[WVIEW_MAX_PATH]; memset (&virtualWorkData, 0, sizeof(virtualWorkData)); // save the archive indication callback (we should never need it) ArchiveIndicator = archiveIndication; // set our work data pointer work->stationData = &virtualWorkData; // set the Archive Generation flag to indicate the VIRTUAL DOES NOT // generate them work->stationGeneratesArchives = TRUE; // initialize the medium abstraction based on user configuration if (!strcmp (work->stationInterface, "serial")) { radMsgLog (PRI_HIGH, "stationInit: serial medium not supported for virtual station!"); return ERROR; } else if (!strcmp (work->stationInterface, "ethernet")) { if (ethernetMediumInit (&work->medium, work->stationHost, work->stationPort) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: ethernet MediumInit failed"); return ERROR; } } else { radMsgLog (PRI_HIGH, "stationInit: medium %s not supported", work->stationInterface); return ERROR; } // initialize the interface using the media specific routine if ((*(work->medium.init))(&work->medium, work->stationDevice) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: medium setup failed"); return ERROR; } // Make the socket blocking: radSocketSetBlocking ((*(work->medium.getsocket))(&work->medium), TRUE); // Reset the stationType to include the host:port: sprintf(tempStr, "%s:%s:%d", work->stationType, work->stationHost, work->stationPort); wvstrncpy(work->stationType, tempStr, sizeof(work->stationType)); if (!strcmp (work->stationInterface, "ethernet")) { radMsgLog (PRI_STATUS, "VIRTUAL on %s:%d opened ...", work->stationHost, work->stationPort); } // grab the station configuration now if (stationGetConfigValueInt (work, STATION_PARM_ELEVATION, &virtualWorkData.elevation) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: stationGetConfigValueInt ELEV failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } if (stationGetConfigValueFloat (work, STATION_PARM_LATITUDE, &virtualWorkData.latitude) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: stationGetConfigValueInt LAT failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } if (stationGetConfigValueFloat (work, STATION_PARM_LONGITUDE, &virtualWorkData.longitude) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: stationGetConfigValueInt LONG failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } if (stationGetConfigValueInt (work, STATION_PARM_ARC_INTERVAL, &virtualWorkData.archiveInterval) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: stationGetConfigValueInt ARCINT failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } // set the work archive interval now work->archiveInterval = virtualWorkData.archiveInterval; // sanity check the archive interval against the most recent record if (stationVerifyArchiveInterval (work) == ERROR) { // bad magic! radMsgLog (PRI_HIGH, "stationInit: stationVerifyArchiveInterval failed!"); radMsgLog (PRI_HIGH, "You must either move old archive data out of the way -or-"); radMsgLog (PRI_HIGH, "fix the interval setting..."); (*(work->medium.exit)) (&work->medium); return ERROR; } else { radMsgLog (PRI_STATUS, "station archive interval: %d minutes", work->archiveInterval); } radMsgLog (PRI_STATUS, "Starting station interface: VIRTUAL"); // This must be done here: work->archiveDateTime = dbsqliteArchiveGetNewestTime(&newestRecord); if ((int)work->archiveDateTime == ERROR) { work->archiveDateTime = 0; radMsgLog (PRI_STATUS, "stationInit: no archive records found in database!"); } // initialize the station interface if (virtualProtocolInit(work) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: virtualProtocolInit failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } // do the initial GetReadings now if (virtualProtocolGetReadings(work, &virtualWorkData.virtualReadings) != OK) { radMsgLog (PRI_HIGH, "stationInit: initial virtualProtocolGetReadings failed!"); virtualProtocolExit (work); (*(work->medium.exit)) (&work->medium); return ERROR; } // populate the LOOP structure storeLoopPkt (&work->loopPkt, &virtualWorkData); // we must indicate successful completion here - // even though we are synchronous, the daemon wants to see this event radProcessEventsSend(NULL, STATION_INIT_COMPLETE_EVENT, 0); return OK; }
// station-supplied init function // -- Can Be Asynchronous - event indication required -- // // MUST: // - set the 'stationGeneratesArchives' flag in WVIEWD_WORK: // if the station generates archive records (TRUE) or they should be // generated automatically by the daemon from the sensor readings (FALSE) // - Initialize the 'stationData' store for station work area // - Initialize the interface medium // - do initial LOOP acquisition // - do any catch-up on archive records if there is a data logger // - 'work->runningFlag' can be used for start up synchronization but should // not be modified by the station interface code // - indicate init is done by sending the STATION_INIT_COMPLETE_EVENT event to // this process (radProcessEventsSend (NULL, STATION_INIT_COMPLETE_EVENT, 0)) // // OPTIONAL: // - Initialize a state machine or any other construct required for the // station interface - these should be stored in the 'stationData' store // // 'archiveIndication' - indication callback used to pass back an archive record // generated as a result of 'stationGetArchive' being called; should receive a // NULL pointer for 'newRecord' if no record available; only used if // 'stationGeneratesArchives' flag is set to TRUE by the station interface // // Returns: OK or ERROR // int stationInit ( WVIEWD_WORK *work, void (*archiveIndication)(ARCHIVE_PKT* newRecord) ) { int i; ARCHIVE_PKT recordStore; time_t nowTime; memset (&twiWorkData, 0, sizeof(twiWorkData)); pwviewWork = work; twiWorkData.baudrate = B19200; // save the archive indication callback (we should never need it) ArchiveIndicator = archiveIndication; // set our work data pointer work->stationData = &twiWorkData; // set the Archive Generation flag to indicate the TWI DOES NOT // generate them work->stationGeneratesArchives = FALSE; // initialize the medium abstraction based on user configuration if (!strcmp (work->stationInterface, "serial")) { if (serialMediumInit (&work->medium, serialPortConfig, O_RDWR | O_NOCTTY | O_NDELAY) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: serial MediumInit failed"); return ERROR; } } else if (!strcmp (work->stationInterface, "ethernet")) { if (ethernetMediumInit (&work->medium, work->stationHost, work->stationPort) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: ethernet MediumInit failed"); return ERROR; } } else { radMsgLog (PRI_HIGH, "stationInit: medium %s not supported", work->stationInterface); return ERROR; } // initialize the interface using the media specific routine if ((*(work->medium.init)) (&work->medium, work->stationDevice) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: medium setup failed"); return ERROR; } // Autobaud the station now: twiWorkData.baudrate = twiConfig(work); if (twiWorkData.baudrate <= 0) { radMsgLog (PRI_HIGH, "TWI: twiProtocolInit: autobaud failed!"); return ERROR; } radMsgLog (PRI_STATUS, "TWI: autobaud = %d", twiWorkData.baudrate); // Reconfigure the serial port here to ensure consistency: serialPortConfig(work->medium.fd); tcflush (work->medium.fd, TCIFLUSH); tcflush (work->medium.fd, TCOFLUSH); if (!strcmp (work->stationInterface, "serial")) { radMsgLog (PRI_STATUS, "TWI on %s opened ...", work->stationDevice); } else if (!strcmp (work->stationInterface, "ethernet")) { radMsgLog (PRI_STATUS, "TWI on %s:%d opened ...", work->stationHost, work->stationPort); } // grab the station configuration now if (stationGetConfigValueInt (work, STATION_PARM_ELEVATION, &twiWorkData.elevation) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: stationGetConfigValueInt ELEV failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } if (stationGetConfigValueFloat (work, STATION_PARM_LATITUDE, &twiWorkData.latitude) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: stationGetConfigValueInt LAT failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } if (stationGetConfigValueFloat (work, STATION_PARM_LONGITUDE, &twiWorkData.longitude) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: stationGetConfigValueInt LONG failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } if (stationGetConfigValueInt (work, STATION_PARM_ARC_INTERVAL, &twiWorkData.archiveInterval) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: stationGetConfigValueInt ARCINT failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } // set the work archive interval now work->archiveInterval = twiWorkData.archiveInterval; // sanity check the archive interval against the most recent record if (stationVerifyArchiveInterval (work) == ERROR) { // bad magic! radMsgLog (PRI_HIGH, "stationInit: stationVerifyArchiveInterval failed!"); radMsgLog (PRI_HIGH, "You must either move old archive data out of the way -or-"); radMsgLog (PRI_HIGH, "fix the interval setting..."); (*(work->medium.exit)) (&work->medium); return ERROR; } else { radMsgLog (PRI_STATUS, "station archive interval: %d minutes", work->archiveInterval); } twiWorkData.totalRain = 0; // Create the rain accumulator (TWI_RAIN_RATE_PERIOD minute age) // so we can compute rain rate: twiWorkData.rainRateAccumulator = sensorAccumInit(TWI_RAIN_RATE_PERIOD); // Populate the accumulator with the last TWI_RAIN_RATE_PERIOD minutes: nowTime = time(NULL) - (WV_SECONDS_IN_HOUR/(60/TWI_RAIN_RATE_PERIOD)); while ((nowTime = dbsqliteArchiveGetNextRecord(nowTime, &recordStore)) != ERROR) { sensorAccumAddSample(twiWorkData.rainRateAccumulator, recordStore.dateTime, recordStore.value[DATA_INDEX_rain]); } radMsgLog (PRI_STATUS, "Starting station interface: TWI"); // initialize the station interface if (twiProtocolInit(work) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: twiProtocolInit failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } // do the initial GetReadings now if (twiProtocolGetReadings(work, &twiWorkData.twiReadings) != OK) { radMsgLog (PRI_HIGH, "stationInit: initial twiProtocolGetReadings failed!"); twiProtocolExit (work); (*(work->medium.exit)) (&work->medium); return ERROR; } // Initialize the 12-hour temp accumulator: twi12HourTempAvg = sensorAccumInit(60 * 12); // Load data for the last 12 hours: nowTime = time(NULL) - (WV_SECONDS_IN_HOUR * 12); while ((nowTime = dbsqliteArchiveGetNextRecord(nowTime, &recordStore)) != ERROR) { sensorAccumAddSample(twi12HourTempAvg, recordStore.dateTime, recordStore.value[DATA_INDEX_outTemp]); } // populate the LOOP structure storeLoopPkt (work, &work->loopPkt, &twiWorkData.twiReadings); // we must indicate successful completion here - // even though we are synchronous, the daemon wants to see this event radProcessEventsSend(NULL, STATION_INIT_COMPLETE_EVENT, 0); return OK; }