Example #1
0
static int serialReadExact (WVIEW_MEDIUM *med, void *bfr, int len, int msTimeout)
{
    int         rval, cumTime = 0, index = 0;
    uint64_t    readTime;
    uint8_t     *ptr = (uint8_t *)bfr;

    while (index < len && cumTime < msTimeout)
    {
        readTime = radTimeGetMSSinceEpoch ();
        rval = read (med->fd, &ptr[index], len - index);
        if (rval < 0)
        {
            if (errno != EINTR && errno != EAGAIN)
            {
                return ERROR;
            }
        }
        else
        {
            index += rval;
        }

        readTime = radTimeGetMSSinceEpoch () - readTime;
        cumTime += (int)readTime;
        if (index < len && cumTime < msTimeout)
        {
            readTime = radTimeGetMSSinceEpoch ();
            radUtilsSleep (9);
            readTime = radTimeGetMSSinceEpoch () - readTime;
            cumTime += (int)readTime;
        }
    }

    return ((index == len) ? len : ERROR);
}
Example #2
0
static void portDTRToggle (int fd, int msec)
{
    struct termios  tty, old;

    tcgetattr (fd, &tty);
    tcgetattr (fd, &old);
    cfsetospeed (&tty, B0);
    cfsetispeed (&tty, B0);
    tcsetattr (fd, TCSANOW, &tty);
    if (msec > 0)
    {
        radUtilsSleep (msec);
    }

    tcsetattr (fd, TCSANOW, &old);
}
Example #3
0
File: alarms.c Project: breu/wview
static int executeScript (WVIEW_ALARM *alarm)
{
    int             retVal;
    char            *args[5];
    char            path[_MAX_PATH];
    char            type[64];
    char            thresh[64];
    char            trigVal[64];

    wvstrncpy (path, alarm->scriptToRun, _MAX_PATH);
    args[0] = path;

    sprintf (type, "%d", alarm->type);
    args[1] = type;

    sprintf (thresh, "%.3f", alarm->bound);
    args[2] = thresh;

    sprintf (trigVal, "%.3f", alarm->triggerValue);
    args[3] = trigVal;

    args[4] = 0;

    retVal = fork ();
    if (retVal == -1)
    {
        return -1;
    }
    else if (retVal == 0)
    {
        // we are the child!
        if (execv (path, args) == -1)
        {
            radMsgLog(PRI_HIGH, "executeScript: execv(%s) failed: %s", path, strerror(errno));
            exit(-1);
        }
        exit(0);
    }
    else
    {
        // we are the parent, pause a bit to let the script run 
        // and avoid a process "storm"
        radUtilsSleep (50);                 // 50 ms
    }

    return 0;
}
Example #4
0
static int serialInit (WVIEW_MEDIUM *med, char *deviceName)
{
    MEDIUM_SERIAL   *serialWork = (MEDIUM_SERIAL *)med->workData;

    //  ... open our serial channel
    med->fd = open (deviceName, serialWork->openFlags);
    if (med->fd == -1)
    {
        radMsgLog (PRI_CATASTROPHIC, "Serial device %s failed to open: %s",
                   deviceName, strerror(errno));
        return ERROR;
    }

#ifdef HAVE_FLOCK
    if (flock (med->fd, LOCK_EX) < 0)
#else
    struct flock lock = {0};
    lock.l_type = F_WRLCK;
    if (fcntl(med->fd, F_SETLKW, &lock) < 0)
#endif
    {
        if (errno == EOPNOTSUPP)
        {
            radMsgLog(PRI_MEDIUM, "serial device locking not supported by OS for %s",
                      deviceName);
        }
        else
        {
            radMsgLog (PRI_CATASTROPHIC, "Serial device %s locked by other program!",
                       deviceName);
            return ERROR;
        }
    }

    // configure it
    serialWork->portInit (med->fd);

    tcflush (med->fd, TCIFLUSH);
    tcflush (med->fd, TCOFLUSH);

    // Save the device name:
    strncpy(serialWork->device, deviceName, WVIEW_STRING2_SIZE);

    radUtilsSleep (1);
    return OK;
}
Example #5
0
static int serialRestart (WVIEW_MEDIUM *med)
{
    MEDIUM_SERIAL   *work = (MEDIUM_SERIAL*)med->workData;

    serialExit(med);
    radMsgLog (PRI_HIGH, "serialRestart: attempting restart");
    while ((!wviewdIsExiting()) && (serialInit(med, work->device) == ERROR))
    {
        radMsgLog (PRI_HIGH, "serialRestart: restart failed");
        radUtilsSleep(5000);
        radMsgLog (PRI_HIGH, "serialRestart: retrying restart");
    }
    if (!wviewdIsExiting())
    {
        radMsgLog (PRI_HIGH, "serialRestart: recovered");
    }
    return OK;

}
Example #6
0
// Autobaud the TWI station:
// Returns the baudrate or ERROR:
int twiConfig(WVIEWD_WORK *pWork)
{
    int             baudIndex;

    radMsgLog (PRI_STATUS, "==> Detecting TWI communication settings:");

    // now autobaud the station:
    for (baudIndex = 0; baudIndex < TWI_NUMBER_BAUDS; baudIndex ++)
    {
        radMsgLog (PRI_STATUS, "==> Trying %s-8-N-1...", BaudNames[baudIndex]);
        // setup the port
        serialPortConfig(pWork->medium.fd, BaudRates[baudIndex]);

        tcflush (pWork->medium.fd, TCIFLUSH);
        tcflush (pWork->medium.fd, TCOFLUSH);

        // bump the DTR line so the station will not hang in certain scenarios
        if (pWork->stationToggleDTR)
        {
            portDTRToggle (pWork->medium.fd, 100);
        }

        // try to communicate:
        twiProtocolWriteLineToStation(pWork, "R", FALSE);

        radUtilsSleep (100);

        if (twiProtocolReadLine(pWork) == OK)
        {
            radMsgLog (PRI_STATUS, "==> Yes!");
            radMsgLog (PRI_STATUS, "==> Found TWI at %s-8-N-1", BaudNames[baudIndex]);
            return (int)BaudRates[baudIndex];
        }
        else
        {
            radMsgLog (PRI_STATUS, "==> No");
        }
    }

    radMsgLog (PRI_HIGH, "==> TWI autodetect failed!!");
    return ERROR;
}
Example #7
0
// station-supplied function to indicate data is available on the station
// interface medium (serial or ethernet) -
// It is the responsibility of the station interface to read the data from the
// medium and process appropriately. The data does not have to be read within
// the context of this function, but may be used to stimulate a state machine.
// -- Synchronous --
//
// Returns: N/A
//
void stationDataIndicate (WVIEWD_WORK *work)
{
    int         retVal, done = FALSE;

    if (virtualProtocolDataIndicate(work) == ERROR_ABORT)
    {
        // We need to try to reconnect:
        radMsgLog (PRI_HIGH, "VIRTUAL: remote station lost - retrying...");
        virtualProtocolExit(work);
        (*(work->medium.exit))(&work->medium);

        while (! done && ! work->exiting)
        {
            retVal = RestoreConnection(work);
            if (retVal == ERROR_ABORT)
            {
                radMsgLog (PRI_HIGH, "VIRTUAL: restore connection failed - exiting");
                radProcessSetExitFlag();
                done = TRUE;
            }
            else if (retVal == OK)
            {
                radMsgLog (PRI_HIGH, "VIRTUAL: restore connection success");
                virtualProtocolInit(work);
                done = TRUE;
            }
            else
            {
                radMsgLog (PRI_HIGH, "VIRTUAL: try again in 15 seconds to restore connection.");
                radUtilsSleep(15000);
            }
        }
    }

    return;
}
Example #8
0
File: cwop.c Project: breu/wview
static void processCWOP ()
{
    RADSOCK_ID                          socket;
    time_t                              ntime;
    struct tm                           *gmTime;
    char                                cwopBuffer[256], login[64];
    int                                 length = 0;
    char                                *serv;
    int                                 port;
    volatile WVIEW_MSG_ARCHIVE_NOTIFY   Notify;

    memcpy ((void*)&Notify, (void*)&cwopWork.ArchiveMsg, sizeof(WVIEW_MSG_ARCHIVE_NOTIFY));

    // format the CWOP data
    ntime = time (NULL);
    gmTime = gmtime (&ntime);
    length = sprintf (cwopBuffer, "%s>APRS,TCPXX*,qAX,%s:@", 
                      cwopWork.callSign, cwopWork.callSign);
    length += sprintf (&cwopBuffer[length], "%2.2d%2.2d%2.2dz",
                       gmTime->tm_mday, gmTime->tm_hour, gmTime->tm_min);
    length += sprintf (&cwopBuffer[length], "%s/%s",
                       cwopWork.latitude, cwopWork.longitude);

    // check for any wind registered
    if (Notify.wspeed < 0)
    {
        length += sprintf (&cwopBuffer[length], "_...");
    }
    else
    {
        length += sprintf (&cwopBuffer[length], "_%3.3d", Notify.winddir);
    }
    
    length += sprintf (&cwopBuffer[length], "/%3.3d", Notify.wspeed);
    length += sprintf (&cwopBuffer[length], "g%3.3d", Notify.hiwspeed);

    if (Notify.temp < 0)
    {
        if (((Notify.temp * (-1)) % 10) >= 5)
        {
            Notify.temp -= 10;
        }

        length += sprintf (&cwopBuffer[length], "t-%2.2d", 
                           (Notify.temp * (-1))/10);
    }
    else
    {
        if ((Notify.temp % 10) >= 5)
        {
            Notify.temp += 10;
        }

        length += sprintf (&cwopBuffer[length], "t%3.3d", Notify.temp/10);
    }
    
    length += sprintf (&cwopBuffer[length], "P%3.3d", Notify.rainDay);
    
    if (Notify.humidity >= 0 && Notify.humidity <= 100)
    {
        length += sprintf (&cwopBuffer[length], "h%2.2d", Notify.humidity % 100);
    }
    
    length += sprintf (&cwopBuffer[length], "b%5.5d", 
                       (int)(10 * wvutilsConvertINHGToHPA((float)Notify.altimeter/1000.0)));
    sprintf (&cwopBuffer[length], ".%s", wvutilsCreateCWOPVersion(globalWviewVersionStr));


    // connect to the CWOP server - try the primary then secondary then tertiary
    socket = radSocketClientCreate (cwopWork.server1, cwopWork.portNo1);
    if (socket == NULL)
    {
        statusUpdateMessage("CWOP-connect: failed to connect to server");
        statusIncrementStat(CWOP_STATS_CONNECT_ERRORS);
        wvutilsLogEvent (PRI_MEDIUM, "CWOP-connect: failed to connect to %s:%d",
                         cwopWork.server1, cwopWork.portNo1);
        
        // try the secondary server
        socket = radSocketClientCreate (cwopWork.server2, cwopWork.portNo2);
        if (socket == NULL)
        {
            statusUpdateMessage("CWOP-connect: failed to connect to server");
            statusIncrementStat(CWOP_STATS_CONNECT_ERRORS);
            wvutilsLogEvent (PRI_MEDIUM, "CWOP-connect: failed to connect to %s:%d",
                             cwopWork.server2, cwopWork.portNo2);
        
            // try the tertiary server
            socket = radSocketClientCreate (cwopWork.server3, cwopWork.portNo3);
            if (socket == NULL)
            {
                // we are all out of luck this time!
                statusUpdateMessage("CWOP-connect: failed to connect to server");
                statusIncrementStat(CWOP_STATS_CONNECT_ERRORS);
                wvutilsLogEvent (PRI_MEDIUM, "CWOP-connect: failed to connect to %s:%d",
                                 cwopWork.server3, cwopWork.portNo3);
                radMsgLog (PRI_HIGH, 
                           "CWOP-connect: failed to connect to all 3 APRS servers!");
                return;
            }
            else
            {
                serv = cwopWork.server3;
                port = cwopWork.portNo3;
            }
        }
        else
        {
            serv = cwopWork.server2;
            port = cwopWork.portNo2;
        }
    }
    else
    {
        serv = cwopWork.server1;
        port = cwopWork.portNo1;
    }
    
    // wait 1 second ...
    radUtilsSleep (1000);
    
    // transmit the data 
    sprintf (login, "user %6s pass %d vers %s", 
             cwopWork.callSign, 
             (int)getPasscode(cwopWork.callSign), 
             globalWviewVersionStr);
    length = strlen (login);
    login[length] = 0x0D;           // tack on the CR and LF
    login[length+1] = 0x0A;
    login[length+2] = 0;
    
    if (radSocketWriteExact (socket, login, length + 2) != (length + 2))
    {
        statusUpdateMessage("CWOP-error: failed to login to server");
        radMsgLog (PRI_HIGH, "CWOP-error: %d: failed to login to %s:%d!",
                   errno, serv, port);
        radSocketDestroy (socket);
        return;
    }
    
    // wait 3 seconds ...
    radUtilsSleep (3000);
    
    // write the data record
    wvutilsLogEvent (PRI_STATUS, "CWOP-send: %s", cwopBuffer);

    length = strlen (cwopBuffer);
    cwopBuffer[length] = 0x0D;       // tack on the CR and LF
    cwopBuffer[length+1] = 0x0A;
    cwopBuffer[length+2] = 0;
    if (radSocketWriteExact (socket, cwopBuffer, length + 2) != (length + 2))
    {
        statusUpdateMessage("CWOP-error: failed to write to server");
        radMsgLog (PRI_HIGH, "CWOP-error: %d: failed to write to %s:%d!",
                   errno, serv, port);
        radSocketDestroy (socket);
        return;
    }

    statusIncrementStat(CWOP_STATS_PKTS_SENT);

    // wait 3 more seconds ...
    radUtilsSleep (3000);

    // close connection and cleanup
    radSocketDestroy (socket);

    return;
}
Example #9
0
File: cwop.c Project: breu/wview
/*  ... the main entry point for the wvcwopd process
*/
int main (int argc, char *argv[])
{
    void            (*alarmHandler)(int);
    int             retVal;
    FILE            *pidfile;
    int             iValue;
    double          dValue;
    const char*     sValue;
    int             runAsDaemon = TRUE;

    if (argc > 1)
    {
        if (!strcmp(argv[1], "-f"))
        {
            runAsDaemon = FALSE;
        }
    }

    memset (&cwopWork, 0, sizeof (cwopWork));

    /*  ... initialize some system stuff first
    */
    retVal = cwopSysInit (&cwopWork);
    if (retVal == ERROR)
    {
        radMsgLogInit (PROC_NAME_CWOP, FALSE, TRUE);
        radMsgLog (PRI_CATASTROPHIC, "wvcwopd init 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_CWOP, TRUE, TRUE);
        radMsgLog (PRI_CATASTROPHIC, "radSystemInit failed!");
        radMsgLogExit ();
        exit (1);
    }


    /*  ... call the radlib process init function
    */
    if (radProcessInit (PROC_NAME_CWOP,
                        cwopWork.fifoFile,
                        PROC_NUM_TIMERS_CWOP,
                        runAsDaemon,                // TRUE for daemon
                        msgHandler,
                        evtHandler,
                        NULL)
        == ERROR)
    {
        printf ("\nradProcessInit failed: %s\n\n", PROC_NAME_CWOP);
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }

    cwopWork.myPid = getpid ();
    pidfile = fopen (cwopWork.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);


    //  get our configuration values
    if (wvconfigInit(FALSE) == ERROR)
    {
        radMsgLog (PRI_CATASTROPHIC, "wvconfigInit failed!");
        cwopSysExit (&cwopWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }

    // Is the CWOP daemon enabled?
    iValue = wvconfigGetBooleanValue(configItem_ENABLE_CWOP);
    if (iValue == ERROR || iValue == 0)
    {
        wvconfigExit ();
        radMsgLog (PRI_CATASTROPHIC, "CWOP daemon is NOT enabled - exiting...");
        cwopSysExit (&cwopWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }

    // get the wview verbosity setting
    if (wvutilsSetVerbosity (WV_VERBOSE_WVCWOPD) == ERROR)
    {
        wvconfigExit ();
        radMsgLog (PRI_CATASTROPHIC, "wvutilsSetVerbosity failed!");
        cwopSysExit (&cwopWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }

    // get the APRS call sign
    sValue = wvconfigGetStringValue(configItemCWOP_APRS_CALL_SIGN);
    if (sValue == NULL)
    {
        // we can't do without this!
        wvconfigExit ();
        radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_APRS_CALL_SIGN);
        cwopSysExit (&cwopWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }
    else
    {
        wvstrncpy (cwopWork.callSign, sValue, sizeof(cwopWork.callSign));
        if (sValue[strlen(sValue)-1] >= '0' && sValue[strlen(sValue)-1] <= '9')
        {
            cwopWork.callSignOffset = atoi(&sValue[strlen(sValue)-1]);
        }
        else
        {
            cwopWork.callSignOffset = (sValue[strlen(sValue)-1] % 10);
        }
        cwopWork.callSignOffset %= 10;
    }

    // get the primary APRS server
    sValue = wvconfigGetStringValue(configItemCWOP_APRS_SERVER1);
    if (sValue == NULL)
    {
        // we can't do without this!
        wvconfigExit ();
        radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_APRS_SERVER1);
        cwopSysExit (&cwopWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }
    else
    {
        wvstrncpy (cwopWork.server1, sValue, sizeof(cwopWork.server1));
    }

    // get the primary APRS port number
    iValue = wvconfigGetINTValue(configItemCWOP_APRS_PORTNO1);
    if (iValue < 0)
    {
        // we can't do without this!
        wvconfigExit ();
        radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_APRS_PORTNO1);
        cwopSysExit (&cwopWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }
    else
    {
        cwopWork.portNo1 = iValue;
    }

    // get the secondary APRS server
    sValue = wvconfigGetStringValue(configItemCWOP_APRS_SERVER2);
    if (sValue == NULL)
    {
        // we can't do without this!
        wvconfigExit ();
        radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_APRS_SERVER2);
        cwopSysExit (&cwopWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }
    else
    {
        wvstrncpy (cwopWork.server2, sValue, sizeof(cwopWork.server2));
    }

    // get the primary APRS port number
    iValue = wvconfigGetINTValue(configItemCWOP_APRS_PORTNO2);
    if (iValue < 0)
    {
        // we can't do without this!
        wvconfigExit ();
        radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_APRS_PORTNO2);
        cwopSysExit (&cwopWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }
    else
    {
        cwopWork.portNo2 = iValue;
    }

    // get the tertiary APRS server
    sValue = wvconfigGetStringValue(configItemCWOP_APRS_SERVER3);
    if (sValue == NULL)
    {
        // we can't do without this!
        wvconfigExit ();
        radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_APRS_SERVER3);
        cwopSysExit (&cwopWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }
    else
    {
        wvstrncpy (cwopWork.server3, sValue, sizeof(cwopWork.server3));
    }

    // get the primary APRS port number
    iValue = wvconfigGetINTValue(configItemCWOP_APRS_PORTNO3);
    if (iValue < 0)
    {
        // we can't do without this!
        wvconfigExit ();
        radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_APRS_PORTNO3);
        cwopSysExit (&cwopWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }
    else
    {
        cwopWork.portNo3 = iValue;
    }

    // get the fine pitch latitude that APRS requires
    sValue = wvconfigGetStringValue(configItemCWOP_LATITUDE);
    if (sValue == NULL)
    {
        // we can't do without this!
        wvconfigExit ();
        radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_LATITUDE);
        cwopSysExit (&cwopWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }
    else
    {
        wvstrncpy (cwopWork.latitude, sValue, sizeof(cwopWork.latitude));
    }

    // get the fine pitch longitude that APRS requires
    sValue = wvconfigGetStringValue(configItemCWOP_LONGITUDE);
    if (sValue == NULL)
    {
        // we can't do without this!
        wvconfigExit ();
        radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_LONGITUDE);
        cwopSysExit (&cwopWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }
    else
    {
        wvstrncpy (cwopWork.longitude, sValue, sizeof(cwopWork.longitude));
    }

    // get the WX packet logging preference
    iValue = wvconfigGetBooleanValue(configItemCWOP_LOG_WX_PACKET);
    if (iValue <= 0)
    {
        // just disable it
        cwopWork.logWXPackets = 0;
    }
    else
    {
        cwopWork.logWXPackets = iValue;
    }

    wvconfigExit ();


    if (statusInit(cwopWork.statusFile, cwopStatusLabels) == ERROR)
    {
        radMsgLog (PRI_HIGH, "statusInit failed - exiting...");
        cwopSysExit (&cwopWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }
    statusUpdate(STATUS_BOOTING);


    // wait a bit here before continuing
    radUtilsSleep (500);


    cwopWork.timer = radTimerCreate (NULL, timerHandler, NULL);
    if (cwopWork.timer == NULL)
    {
        statusUpdateMessage("radTimerCreate failed");
        radMsgLog (PRI_HIGH, "radTimerCreate failed");
        statusUpdate(STATUS_ERROR);
        cwopSysExit (&cwopWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }
    radProcessTimerStart (cwopWork.timer, CWOP_MINUTE_INTERVAL);


    //  register with the radlib message router
    if (radMsgRouterInit (WVIEW_RUN_DIR) == ERROR)
    {
        statusUpdateMessage("radMsgRouterInit failed");
        radMsgLog (PRI_HIGH, "radMsgRouterInit failed!");
        statusUpdate(STATUS_ERROR);
        cwopSysExit (&cwopWork);
        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 ();
        cwopSysExit (&cwopWork);
        radProcessExit ();
        radSystemExit (WVIEW_SYSTEM_ID);
        exit (1);
    }

    // enable message reception from the radlib router for archive notifications
    radMsgRouterMessageRegister (WVIEW_MSG_TYPE_ARCHIVE_NOTIFY);

    // enable message reception from the radlib router for POLL msgs
    radMsgRouterMessageRegister (WVIEW_MSG_TYPE_POLL);


    radMsgLog (PRI_STATUS, "CWOP: configured to submit station %s data to:",
               cwopWork.callSign);
    radMsgLog (PRI_STATUS, "CWOP: Primary:   %s:%d", cwopWork.server1, cwopWork.portNo1);
    radMsgLog (PRI_STATUS, "CWOP: Secondary: %s:%d", cwopWork.server2, cwopWork.portNo2);
    radMsgLog (PRI_STATUS, "CWOP: Tertiary:  %s:%d", cwopWork.server3, cwopWork.portNo3);
    radMsgLog (PRI_STATUS, "CWOP: Submitting every %d minutes at offset minute: %d",
               cwopWork.reportInterval, cwopWork.callSignOffset);


    // enter normal processing
    cwopWork.inMainLoop = TRUE;
    statusUpdate(STATUS_RUNNING);
    statusUpdateMessage("Normal operation");
    radMsgLog (PRI_STATUS, "running...");


    while (!cwopWork.exiting)
    {
        // wait on something interesting
        if (radProcessWait (0) == ERROR)
        {
            cwopWork.exiting = TRUE;
        }
    }


    statusUpdateMessage("exiting normally");
    radMsgLog (PRI_STATUS, "exiting normally...");
    statusUpdate(STATUS_SHUTDOWN);

    radMsgRouterExit ();
    radTimerDelete (cwopWork.timer);
    cwopSysExit (&cwopWork);
    radProcessExit ();
    radSystemExit (WVIEW_SYSTEM_ID);
    exit (0);
}
Example #10
0
File: cwop.c Project: breu/wview
static int waitForWviewDaemon (void)
{
    WVIEW_MSG_REQUEST       msg;
    char                    srcQName[QUEUE_NAME_LENGTH+1];
    UINT                    msgType;
    UINT                    length;
    void                    *recvBfr;
    int                     retVal, done = FALSE;

    // enable message reception from the radlib router for the archive path
    radMsgRouterMessageRegister (WVIEW_MSG_TYPE_STATION_INFO);

    msg.requestType = WVIEW_RQST_TYPE_STATION_INFO;

    if (radMsgRouterMessageSend (WVIEW_MSG_TYPE_REQUEST, &msg, sizeof(msg)) == ERROR)
    {
        statusUpdateMessage("waitForWviewDaemon: radMsgRouterMessageSend failed!");
        radMsgLog (PRI_HIGH, "waitForWviewDaemon: radMsgRouterMessageSend failed!");
        radMsgRouterMessageDeregister (WVIEW_MSG_TYPE_STATION_INFO);
        return ERROR;
    }

    statusUpdate(STATUS_WAITING_FOR_WVIEW);

    // now wait for the response here
    while (!done)
    {
        radUtilsSleep (50);
        
        
        if ((retVal = radQueueRecv (radProcessQueueGetID (),
                                    srcQName,
                                    &msgType,
                                    &recvBfr,
                                    &length))
            == FALSE)
        {
            continue;
        }
        else if (retVal == ERROR)
        {
            statusUpdateMessage("waitForWviewDaemon: queue is closed!");
            radMsgLog (PRI_STATUS, "waitForWviewDaemon: queue is closed!");
            radMsgRouterMessageDeregister (WVIEW_MSG_TYPE_STATION_INFO);
            return ERROR;
        }
    
        // is this what we want?
        if (msgType == WVIEW_MSG_TYPE_STATION_INFO)
        {
            // yes!
            done = TRUE;
            cwopWork.reportInterval = ((WVIEW_MSG_STATION_INFO*)recvBfr)->archiveInterval;
            if (cwopWork.reportInterval < 10)
            {
                cwopWork.reportInterval = 10;
            }
        }
        else if (msgType == WVIEW_MSG_TYPE_SHUTDOWN)
        {
            statusUpdateMessage("waitForWviewDaemon: received shutdown from wviewd");
            radMsgLog (PRI_HIGH, "waitForWviewDaemon: received shutdown from wviewd"); 
            radMsgRouterMessageDeregister (WVIEW_MSG_TYPE_STATION_INFO);
            return ERROR;
        }
    
        // release the received buffer
        radBufferRls (recvBfr);
    }
    
    // disable message reception from the radlib router for the archive path
    radMsgRouterMessageDeregister (WVIEW_MSG_TYPE_STATION_INFO);

    return OK;
}
Example #11
0
static void dumpConfig (void)
{
    int         numTries = 0;
    int         channel;
    
    // initial wakeup of the VP console
    while ((vpifWakeupConsole (&wvWork) == ERROR) && 
           (numTries < VPC_INITIAL_WAKEUP_TRIES))
    {
        printf ("VP console WAKEUP failed - retry\n");
        radUtilsSleep (1000);
        numTries ++;
    }
    if (numTries == VPC_INITIAL_WAKEUP_TRIES)
    {
        printf ("VP console WAKEUP failed - aborting\n");
        return;
    }

    // get the archive interval
    if (vpconfigGetArchiveInterval (&wvWork) == ERROR)
    {
        printf ("vpconfigGetArchiveInterval failed - aborting\n");
        return;
    }
    
    // get the RXCheck string
    if (vpifGetRXCheck (&wvWork) == ERROR)
    {
        printf ("vpifGetRXCheck failed - aborting\n");
        return;
    }
    
    // get the version string
    if (vpconfigGetFWVersion (&wvWork) == ERROR)
    {
        printf ("vpconfigGetFWVersion failed - aborting\n");
        return;
    }
    
    // get the Lat and Long
    if (vpifGetLatandLong (&wvWork) == ERROR)
    {
        printf ("vpifGetLatandLong failed - aborting\n");
        return;
    }
    
    // get the Rain Season Start
    if (vpconfigGetRainSeasonStart (&wvWork) == ERROR)
    {
        printf ("vpconfigGetRainSeasonStart failed - aborting\n");
        return;
    }
    
    // get the station wind direction calibration
    if (vpconfigGetWindDirectionCal (&wvWork) == ERROR)
    {
        printf ("vpconfigGetWindDirectionCal failed - aborting\n");
        return;
    }
    
    // get the transmitter type and retransmitter settings
    if (vpconfigGetTransmitters (&wvWork) == ERROR)
    {
        printf ("vpconfigGetTransmitters failed - aborting\n");
        return;
    }
    
    // get the rain collector size
    if (vpconfigGetRainCollectorSize (&wvWork) == ERROR)
    {
        printf ("vpconfigRainCollectorSize failed - aborting\n");
        return;
    }
    
    // get the wind cup size
    if (vpconfigGetWindCupSize (&wvWork) == ERROR)
    {
        printf ("vpconfigGetWindCupSize failed - aborting\n");
        return;
    }
    
    printf ("\n");
    printf ("Firmware Version:        %s\n",
            ((VP_IF_DATA *)wvWork.stationData)->fwVersion);

    printf ("Station Location:        ");
    if (wvWork.latitude < 0)
        printf ("%.1f S, ", (float)(-wvWork.latitude)/10.0);
    else
        printf ("%.1f N, ", (float)wvWork.latitude/10.0);
    if (wvWork.longitude < 0)
        printf ("%.1f W, ", (float)(-wvWork.longitude)/10.0);
    else
        printf ("%.1f E, ", (float)wvWork.longitude/10.0);
    printf ("%d feet\n", (int)wvWork.elevation);
        
    printf ("Archive Interval:        %d minutes\n", 
            wvWork.archiveInterval);

    printf ("Rain Season Start Month: %d\n", 
            ((VP_IF_DATA *)wvWork.stationData)->rainSeasonStart);
    
    printf ("Wind direction calibration: %d degrees\n", 
            ((VP_IF_DATA *)wvWork.stationData)->windDirectionCal);
    
    for (channel = 0; channel < 8; channel++)
    {
        if (((VP_IF_DATA *)wvWork.stationData)->listenChannels & ((uint8_t) 1 << channel))
        {
            uint8_t sensorType = ((VP_IF_DATA *)wvWork.stationData)->transmitterType[channel*2] & 0xF;
            uint8_t humidityIndex = (((VP_IF_DATA *)wvWork.stationData)->transmitterType[channel*2 + 1] & (uint8_t) 0xF0) >> 4;
            uint8_t temperatureIndex = ((VP_IF_DATA *)wvWork.stationData)->transmitterType[channel*2 + 1] & 0xF;
            printf ("Listening on channel:    %d for ", channel + 1);
            switch ((VPRO_SENSOR_TYPES) sensorType)
            {
                case VPRO_SENSOR_ISS:
                    printf("ISS\n"); break;
                case VPRO_SENSOR_TEMP:
                    printf("temperature (ID %d)\n", temperatureIndex + 1); break;
                case VPRO_SENSOR_HUM:
                    printf("humidity (ID %d)\n", humidityIndex); break;
                case VPRO_SENSOR_TEMP_HUM:
                    printf("temperature (ID %d) and humidity (ID %d)\n", temperatureIndex + 1, humidityIndex); break;
                case VPRO_SENSOR_WIND:
                    printf("wireless anemometer\n"); break;
                case VPRO_SENSOR_RAIN:
                    printf("rain\n"); break;
                case VPRO_SENSOR_LEAF:
                    printf("leaf wetness\n"); break;
                case VPRO_SENSOR_SOIL:
                    printf("soil moisture\n"); break;
                case VPRO_SENSOR_LEAF_SOIL:
                    printf("leaf wetness and soil moisture\n"); break;
                case VPRO_SENSOR_SENSORLINK:
                    printf("SensorLink\n"); break;
                case VPRO_SENSOR_NONE:
                    // Should not happen; tx bit in listenChannels should be off.
                    printf("no sensor\n"); break;
                default:
                    printf("unknown sensor type 0x%02x\n", sensorType); break;
            }
        }
    }
Example #12
0
File: alarms.c Project: breu/wview
/*  ... 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);
}
Example #13
0
int wh1080Init (WVIEWD_WORK *work)
{
    WH1080_IF_DATA*     ifWorkData = (WH1080_IF_DATA*)work->stationData;
    fd_set              rfds;
    struct timeval      tv;
    int                 ret;
    time_t              nowTime = time(NULL) - (WV_SECONDS_IN_HOUR/(60/WH1080_RAIN_RATE_PERIOD));
    ARCHIVE_PKT         recordStore;
    unsigned char       controlBlock[WH1080_BUFFER_CHUNK];

    memset (&wh1080Work, 0, sizeof(wh1080Work));

    // Create the rain accumulator (WH1080_RAIN_RATE_PERIOD minute age)
    // so we can compute rain rate:
    ifWorkData->rainRateAccumulator = sensorAccumInit(WH1080_RAIN_RATE_PERIOD);

    // Populate the accumulator with the last WH1080_RAIN_RATE_PERIOD minutes:
    while ((nowTime = dbsqliteArchiveGetNextRecord(nowTime, &recordStore)) != ERROR)
    {
        sensorAccumAddSample(ifWorkData->rainRateAccumulator,
                             recordStore.dateTime,
                             recordStore.value[DATA_INDEX_rain]);
    }

    if ((*(work->medium.usbhidInit))(&work->medium) != OK)
    {
        return ERROR;
    }

    // Set the station to log data once per minute:
    while ((!work->exiting) && (readFixedBlock(work, controlBlock) != OK))
    {
        radMsgLog (PRI_HIGH, "WH1080: Initial fixed block read failed");
        (*(work->medium.usbhidExit))(&work->medium);
        radUtilsSleep(5000);
        (*(work->medium.usbhidInit))(&work->medium);
        radMsgLog (PRI_HIGH, "WH1080: Retrying initial fixed block read");
    }

    // For some reason the WH1080 wants the IF closed between a read and a write:
    (*(work->medium.usbhidExit))(&work->medium);
    if (work->exiting)
    {
        return ERROR;
    }

    controlBlock[WH1080_SAMPLING_INTERVAL] = 1;
    (*(work->medium.usbhidInit))(&work->medium);

    if (writeFixedBlock(work, controlBlock) == ERROR)
    {
        (*(work->medium.usbhidExit))(&work->medium);
        return ERROR;
    }

    radUtilsSleep(2000);

    (*(work->medium.usbhidExit))(&work->medium);

    radUtilsSleep(1000);

    wh1080Work.lastRecord = -1;

    // populate the LOOP structure:
    radMsgLog (PRI_HIGH, "Waiting for the next weather record to be ready "
                         "in the console to populate initial wview sensor readings "
                         "(this could take some time);");
    radMsgLog (PRI_HIGH, "While waiting be sure you are receiving all sensors on the console;");
    radMsgLog (PRI_HIGH, "if not, you may need to relocate the sensors or the console.");
    while ((!work->exiting) && (readStationData(work) != OK))
    {
        radUtilsSleep(1000);
    }
    if (work->exiting)
    {
        return ERROR;
    }

    ifWorkData->wh1080Readings = wh1080Work.sensorData;
    storeLoopPkt (work, &work->loopPkt, &ifWorkData->wh1080Readings);

    // 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;
}