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