Writing data to the Cascade DataHub

Cogent API and Utilities: Version 4.1
Prev | Appendix A. Cascade DataHub Code Examples | Next

# A.2. Writing data to the Cascade DataHub

    /*
     * Cascade DataHub point writer:  writept
     *
     * (C) Copyright Cogent Real-Time Systems Inc., 1997.  All rights reserved.
     *
     * This program writes a point to the Cascade DataHub.
     *
     * This program is supplied with the Cascade DataHub programming API.  It
     * may be copied or modified, in whole or in part, for the sole purpose of
     * creating applications to be used with the Cascade DataHub.
     */

    #include    <stdio.h>
    #include    <stdlib.h>
    #include    <string.h>
    #include    <time.h>

    #include    <cogent/cogdb.h>

    #ifdef __USAGE
    Copyright (C) Cogent Real-Time Systems Inc., 1996

    %C [-d domain] [-r|-f|-i|-l|-s] [-S security] pointname pointvalue
        -d domain - set the domain for the operation
        -r|-f     - write as a floating point number
        -i        - write as a short integer
        -l        - write as a long integer
        -s        - write as a character string
        -S        - set security level for write

    Write a point to the Cascade DataHub in the given
    domain.  Strings containing spaces and special characters
    must be escaped from the shell appropriately.

    To write a negative number, use --value.
    #endif

    void Usage (char** argv)
    {
        print_usage (argv);
        exit (1);
    }

    int main (int argc, char** argv)
    {
        IP_hMSG            hmsg;
        ST_STATUS        status;
        PT_stCPOINT        point;
        char            *ptname = NULL, *ptvalue = NULL, *domain=NULL;
        short            type = PT_TYPE_INT32;
        int                i, security=0;
        IP_hTASK        htask;
        struct timespec    tp;

        /*
         * Parse the command line
         */
        for (i=1; i<argc; i++)
        {
            if (argv[i][0] == '-')
            {
                switch (argv[i][1])
                {
                  case 'd':
                    domain = (argv[i][2] ? &argv[i][2] : argv[++i]);
                    if (strlen(domain) > 15)
                        domain[15] = '\0';
                    break;
                  case 'r':
                  case 'f':
                    type = PT_TYPE_REAL;
                    break;
                  case 'i':
                  case 'l':
                    type = PT_TYPE_INT32;
                    break;
                  case 's':
                    type = PT_TYPE_STRING;
                    break;
                  case 'S':
                    security = atoi (argv[i][2] ? &argv[i][2] : argv[++i]);
                    break;
                  case '-':
                    ptvalue = &argv[i][1];
                    break;
                  default:
                    Usage (argv);
                    break;
                }
            }
            else
            {
                if (!ptname)
                    ptname = argv[i];
                else
                    ptvalue = argv[i];
            }
        }

        if (!ptname || !ptvalue)
        {
            printf ("Need a point and value\n");
            exit (1);
        }

        /*
         * Initialize communication with the Cascade NameServer.  We do
         * not want other tasks to be notified of the start and stop of this
         * task, so we make it NS_INVISIBLE.  The name server will know about
         * this task, it just will not tell anybody.  Also, since we do not
         * want to be receiving queue messages, do not name the queue.
         */
        if (!(htask = NS_Init (argv[0], NULL, domain, NS_INVISIBLE)))
        {
            fprintf (stderr, "Could not initialize Cascade DataHub IPC subsystem\n");
            exit (1);
        }

        /*
         * Set this task's security level.  This level must be greater than or
         * equal to the security level of the point in the datahub in order
         * for the write to succeed.  The datahub does not know whether this
         * task has the right to claim this security level.  That enforcement
         * is up to the programmer of the user task.
         */
        IP_TaskSetSecurity (htask, security);

        /*
         * Create a pre-allocated message structure for use with all
         * IPC calls.  This includes the DH_* functions.  The API could have
         * created its own internal message structure, but this would have
         * left us with no way to control its size or be efficient about
         * allocation.  This way we do a little more work, but have more
         * control of what is being allocated.
         */
        hmsg = IP_CreateMsg (0, 0, NULL, IP_MAX_MESSAGE, NULL);

        /*
         * Zero the point structure.  If we do not do this, the address
         * field could be non-zero, and then the API will take that to be a
         * cached datahub address.  That might cause a crash.
         */
        memset (&point, 0, sizeof(point));

        /*
         * Provide a point name buffer separately from the rest of the point
         * structure.  There is no way for the API to know what the allocation
         * status of a point name is, so it will never attempt to free this
         * buffer, nor write into it.
         */
        point.name = ptname;
        point.type = type;
        point.conf = 100;

        /*
         * Set the time on the point.  If this is not set, then the datahub
         * will show a zero time.
         */
        clock_gettime (CLOCK_REALTIME, &tp);
        point.seconds = tp.tv_sec;
        point.nanoseconds = tp.tv_nsec;

        /*
         * Set the value of the point based on the type.
         */
        switch (point.type)
        {
          case PT_TYPE_INT32:
            point.value.i = atoi (ptvalue);
            break;
          case PT_TYPE_REAL:
            point.value.r = strtod (ptvalue, NULL);
            break;
          case PT_TYPE_STRING:
            point.value.s = ptvalue;
            break;
        }

        /*
         * Write the point.  We need a IP_hMSG structure and a IP_hTASK in
         * to provide buffer space and sender identification respectively.
         */
        if ((status = DH_WritePoint (htask, &point, hmsg, NULL)) != ST_OK)
            printf ("Write point failed: %s\n", ST_StatusName (status));

        return (0);
    }

Prev | Home | Next
Cascade DataHub Code Examples | Up | Registering for exceptions from the Cascade DataHub

Copyright 1995-2002 by Cogent Real-Time Systems, Inc.