source: trunk/src/data_sources/k2ew/k2misc.c @ 3184

Revision 2718, 49.7 KB checked in by paulf, 12 years ago (diff)

made sure time_t are casted to long for heartbeat sprintf()

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 *   THIS FILE IS UNDER RCS - DO NOT MODIFY UNLESS YOU HAVE
3 *   CHECKED IT OUT USING THE COMMAND CHECKOUT.
4 *
5 *    $Id$
6 *
7 *    Revision history:
8 *     $Log$
9 *     Revision 1.30  2007/02/26 17:16:53  paulf
10 *     made sure time_t are casted to long for heartbeat sprintf()
11 *
12 *     Revision 1.29  2005/07/27 19:28:49  friberg
13 *     2.40 changes for ForceBlockMode and comm stats
14 *
15 *     Revision 1.28  2005/03/26 00:17:46  kohler
16 *     Version 2.38.  Added capability to get network code values from the K2
17 *     headers.  The "Network" parameter in the config file is now optional.
18 *     WMK 3/25/05
19 *
20 *     Revision 1.27  2004/06/04 16:36:04  lombard
21 *     Fixed parts of extended status message.
22 *
23 *     Revision 1.26  2003/07/17 19:23:27  friberg
24 *     Fixed a status message to include network and station name for the k2
25 *     from which the error originated.
26 *
27 *     Revision 1.25  2003/06/06 01:24:33  lombard
28 *     Changed to version 2.34: fix for byte alignment problem in extended status
29 *     structure.
30 *
31 *     Revision 1.24  2003/05/29 13:33:40  friberg
32 *     Added in calls to k2info and fixed GPS status message to include
33 *     the station name. Changed all status messages to include
34 *     network code in addition to station name
35 *
36 *     Revision 1.23  2003/05/15 00:41:47  lombard
37 *     *** empty log message ***
38 *
39 *     Revision 1.22  2002/05/06 18:24:58  kohler
40 *     Fixed typo in log statement in function k2mi_init_blkmde().
41 *
42 *     Revision 1.21  2002/04/22 16:35:55  lucky
43 *     k2ew was being restarted by startstop because it would stop beating its
44 *     heart when re-trying to connect. Made it so that we continue to beat our
45 *     heart even when we go through the retry loop several times.
46 *
47 *     Revision 1.20  2002/01/30 14:28:31  friberg
48 *     added robust comm recovery for time out case
49 *
50 *     Revision 1.19  2001/10/19 18:21:28  kohler
51 *     k2mi_log_pktinfo() now sends msg to statmgr if a pcdrv error occurs.
52 *
53 *     Revision 1.18  2001/10/16 22:03:56  friberg
54 *     Upgraded to version 2.25
55 *
56 *     Revision 1.17  2001/08/08 16:11:48  lucky
57 *     version 2.23
58 *
59 *     Revision 1.15  2001/05/23 00:20:00  kohler
60 *     Now, optionally writes entire K2 header to a binary file.
61 *
62 *     Revision 1.14  2001/05/08 00:14:38  kohler
63 *     Minor logging changes.
64 *
65 *     Revision 1.13  2001/04/23 20:24:10  friberg
66 *     Added station name remapping using the StationId config parameter.
67 *
68 *     Revision 1.12  2000/11/28 00:45:46  kohler
69 *     Cosmetic changes to log file output.
70 *
71 *     Revision 1.11  2000/11/07 19:35:01  kohler
72 *     Modified to complain if no GPS lock for xx hours.
73 *
74 *     Revision 1.10  2000/08/30 17:34:00  lombard
75 *     See ChangeLog entry for 30 August 2000
76 *
77 *     Revision 1.9  2000/07/28 22:36:10  lombard
78 *     Moved heartbeats to separate thread; added DontQuick command; removed
79 *     redo_com() since it doesn't do any good; other minor bug fixes
80 *
81 *     Revision 1.8  2000/07/03 18:00:37  lombard
82 *     Added code to limit age of waiting packets; stops circ buffer overflows
83 *     Added and Deleted some config params.
84 *     Added check of K2 station name against restart file station name.
85 *     See ChangeLog for complete list.
86 *
87 *     Revision 1.7  2000/06/18 20:17:46  lombard
88 *     transport calls for status and hearbteats was inproperly commented out.
89 *
90 *     Revision 1.6  2000/06/09 23:14:23  lombard
91 *     Several bug fixes and improvements; See Changelog entry of 2000-06-09.
92 *
93 *     Revision 1.5  2000/05/17 15:12:42  lombard
94 *     bug fix in ping_test
95 *
96 *     Revision 1.4  2000/05/16 23:39:16  lombard
97 *     bug fixes, removed OutputThread Keepalive, added OnBattery alarm
98 *     made alarms report only once per occurence
99 *
100 *     Revision 1.3  2000/05/12 19:02:19  lombard
101 *     fixed g_stnid typo
102 *
103 *     Revision 1.2  2000/05/12 04:04:05  lombard
104 *     Fixed conversion of disk space units
105 *
106 *     Revision 1.1  2000/05/04 23:48:20  lombard
107 *     Initial revision
108 *
109 *
110 *
111 */
112/*  k2misc.c:  Miscellaneous functions for K2:            */
113/*      init_blkmde, ping_test, get_status, get_params    */
114/*                                                        */
115/*    1/1/99 -- [ET]  File started                        */
116/*                                                        */
117
118#include <stdio.h>
119#include <stdlib.h>
120#include <string.h>
121#include <earthworm.h>
122#include <time.h>
123#include "byteswap.h"
124#include "glbvars.h"
125#include "k2pktdef.h"        /* K2 packet definitions and types */
126#include "k2ewerrs.h"        /* K2-to-Earthworm error codes */
127#include "k2comif.h"         /* K2 COM port interface routines */
128#include "k2pktio.h"         /* K2 packet send/receive routines */
129#include "k2pktman.h"        /* K2 packet management functions */
130#include "k2misc.h"          /* header file for this module */
131#include "terminat.h"        /* for status/termination codes */
132#include "k2info.h"          /* for info packet injection codes */
133
134#define K2MI_INIT_TOUTMS  5000     /* packet timeout during init */
135#define K2MI_PING_TOUTMS  1000     /* receive ping timeout in ms */
136#define K2MI_PARM_TOUTMS  1000     /* receive params timeout in ms */
137#define K2MI_TRAN_TOUTMS  500      /* transmission timeout */
138#define K2MI_FLSH_SHORT   100      /* short flush interval in ms */
139#define K2MI_FLSH_LONG    500      /* long flush interval in ms */
140#define K2MI_MONMODE_MAX  6        /* number of times to try mon-mode cmd */
141#define K2MI_BLKMODE_MAX  6        /* number of times to try block-mode cmd */
142#define K2MI_PKT_SRCNUM   44       /* arbitrary packet source # for file */
143
144/* buffer size for 'k2mi_init_blkmde()' fn: */
145#define K2MI_IBFSIZ ((PACKET_MAX_SIZE-11)/5)
146
147#define MAX_MSG_SIZE      256       /* Large enough for all faults in extended
148                                       status message */
149static char msg[MAX_MSG_SIZE];      /* Buffer for text messages */
150
151static struct PACKET_HDR g_k2mi_hdrblk;          /* received header buffer */
152static unsigned char g_k2mi_buff[PACKET_MAX_SIZE-9]; /* received data buffer */
153static int rep_on_batt = 0, rep_low_batt = 0, rep_hwstat = 0;
154static int rep_temp, rep_disk[2] = {0,0};
155
156/**************************************************************************
157 * k2mi_init_blkmde:  verifies communications with K2 unit. If K2 is      *
158 *       already in block mode, then return. Otherwise, try to establish  *
159 *       communications with the K2                                       *
160 *       Sockets are never retried on timeouts                            *
161 *         *pseqnum - address of sequence number for sent command packet  *
162 *                    which will be incremented                           *
163 *      return value:  K2R_POSITIVE if K2 is already sending stream data  *
164 *                     K2R_NO_ERROR K2 has been switched to block mode    *
165 *                     K2R_ERROR if an error occurred                     *
166 *                     K2R_TIMEOUT if a timeout occured while             *
167 *                         communicating with K2                          *
168 **************************************************************************/
169
170int k2mi_init_blkmde(unsigned char *pseqnum)
171{
172  int blkmde_count = K2MI_BLKMODE_MAX;
173  int monmde_count = K2MI_MONMODE_MAX;
174  int idx, dcnt, slen, rc1, rc2;
175  static const char *monmde_str_arr[]={          /* monitor-mode strings */
176                                 "\\\\\\\\\r", "\r","\\\\\\\r","\\","\r\\\\\\\\\r"};
177  static const char blkmde_str[]="BLOCK\r";      /* block-mode command string */
178
179  idx = 0;                  /* initialize monitor-mode string array index */
180
181
182  do     /* loop while attempting to activate and confirm K2 block mode */
183  {
184        /* Tell heartbeat thread we're happy */
185          g_mt_working = 1;
186
187
188    if (gcfg_debug > 3)
189      logit("e", "flushing...");
190    if (k2c_flush_recv(K2MI_FLSH_SHORT) != K2R_NO_ERROR)
191      return K2R_ERROR;
192    if (gcfg_debug > 3)
193      logit("e", "done\n");
194
195    /* check if data is coming in and if it's valid packets */
196    if ( (rc1 = k2c_rcvflg_tout(K2MI_FLSH_LONG)) == K2R_ERROR)
197    {
198      return rc1;
199    }
200    else if (rc1 == K2R_NO_ERROR )
201    {         /* Data ready to be read */
202      if ( (rc2 = k2pm_recv_wstmpkt(&g_k2mi_hdrblk, g_k2mi_buff,
203                                    gcfg_commtimeout_itvl, 0)) == K2R_POSITIVE)
204      {
205        if (gcfg_debug > 3)
206          logit("e", "k2mi_init_blkmde: stream packet ret on try %d\n",
207                blkmde_count - K2MI_BLKMODE_MAX);
208        return K2R_POSITIVE;   /* Found K2 already streaming in block mode */
209
210      }
211      else if (rc2 == K2R_ERROR)
212        return rc2;
213    }
214
215    /* no valid packets coming in */
216    /* check if K2-ping can be sent and received */
217    if ( (rc1 = k2mi_ping_test(1, pseqnum)) == K2R_NO_ERROR)
218      return rc1;                   /* ping returned OK, comms are up */
219    else if (rc1 == K2R_ERROR)
220      return rc1;                   /* comm error; give up */
221
222    monmde_count = K2MI_MONMODE_MAX;
223    do
224    {    /* loop while attempting to activate and confirm K2 monitor mode */
225
226          /* Tell heartbeat thread we're happy */
227          g_mt_working = 1;
228
229      /* send a monitor-mode string */
230      if ( (slen = strlen(monmde_str_arr[idx])) == 1)
231      {
232        /* if '\' (or '\r') then delay a bit before */
233        if ( (rc1 = k2c_flush_recv(K2MI_FLSH_LONG)) == K2R_ERROR)
234          return rc1;
235      }
236
237      if (gcfg_debug > 2)
238        logit("e", "sending MM %d\n", idx);
239
240      if ( (rc1 = k2c_tran_buff((const unsigned char *)(monmde_str_arr[idx]),
241                                slen, gcfg_commtimeout_itvl, 0)) != slen)
242        return rc1;     /* if error transmitting then return */
243
244      /* increment index into monitor-mode string array */
245      if(++idx >= (sizeof(monmde_str_arr)/sizeof(monmde_str_arr[0])))
246        idx = 0;             /* if past end-of-array then wrap around to beg */
247
248      /* wait a bit for (possible) data to appear */
249      /*  (wait a bit longer if '\' (or '\r') command) */
250      if ( (rc1 = k2c_rcvflg_tout( ((slen==1)?K2MI_FLSH_LONG:K2MI_FLSH_SHORT)))
251           == K2R_ERROR)
252        return rc1;
253
254      /* save any data returned from K2 */
255      if ( (dcnt = k2c_recv_buff(g_k2mi_buff, K2MI_IBFSIZ,
256                                 gcfg_commtimeout_itvl, 0)) > 0)
257      {       /* data was received */
258        /* Tell heartbeat thread we're happy */
259        g_mt_working = 1;
260
261        g_k2mi_buff[dcnt] = '\0';           /* NULL terminate buffer */
262        if (gcfg_debug > 2)
263          logit("e", "received:  %s\n", g_k2mi_buff);
264
265        /* check if returned data contains monitor-mode prompt ('*') */
266        if ( strchr((char *)g_k2mi_buff, (int)'*') != NULL)
267          break;             /* if monitor-mode prompt ('*') then exit loop */
268      }
269      else if (dcnt == K2R_ERROR)
270        return dcnt;
271    }
272    while(--monmde_count);         /* loop if count not expired */
273    /* Now we should be in monitor mode, unless monmde_count expired */
274
275    /* send block-mode command string */
276    slen = strlen(blkmde_str);
277    if (gcfg_debug > 2)
278      logit("e", "%s\n",blkmde_str);
279
280    if ( (rc1 = k2c_tran_buff((unsigned char *)blkmde_str, slen,
281                                          gcfg_commtimeout_itvl,0)) != slen)
282    {    /* error transmitting; return code */
283      return (rc1 < 0) ? rc1 : K2R_ERROR;   /* only use code if negative */
284                                            /* 1/29/2002 -- [ET] */
285    }
286    if ( (rc1 = k2c_flush_recv(K2MI_FLSH_SHORT)) == K2R_ERROR)
287      return rc1;
288  }
289  while (--blkmde_count);           /* loop if count not expired */
290  logit("et", "k2mi_init_blkmde: failed to put k2 in block mode\n");
291  return K2R_ERROR;
292}
293
294/**************************************************************************
295 * k2mi_force_blkmde:  forces communications with K2 unit into BLOCK mode.*
296 *       Sockets are never retried on timeouts                            *
297 *      return value:  K2R_POSITIVE has been switched to block mode       *
298 *                     K2R_ERROR if an error occurred                     *
299 *                     K2R_TIMEOUT if a timeout occured while             *
300 *                         communicating with K2                          *
301 **************************************************************************/
302int k2mi_force_blkmde()
303{
304  int blkmde_count = K2MI_BLKMODE_MAX;
305  int monmde_count = K2MI_MONMODE_MAX;
306  int idx, dcnt, slen, rc1, rc2;
307  static const char *monmde_str_arr[]={          /* monitor-mode strings */
308                                 "\\\\\\\\\r", "\r","\\\\\\\r","\\","\r\\\\\\\\\r"};
309  static const char blkmde_str[]="BLOCK\r";      /* block-mode command string */
310
311  idx = 0;                  /* initialize monitor-mode string array index */
312
313
314  do     /* loop while attempting to activate and confirm K2 block mode */
315  {
316        /* Tell heartbeat thread we're happy */
317          g_mt_working = 1;
318
319
320    if (gcfg_debug > 2)
321      logit("e", "flushing...");
322    if (k2c_flush_recv(K2MI_FLSH_SHORT) != K2R_NO_ERROR)
323      return K2R_ERROR;
324    if (gcfg_debug > 2)
325      logit("e", "done\n");
326
327    monmde_count = K2MI_MONMODE_MAX;
328    do
329    {    /* loop while attempting to activate and confirm K2 monitor mode */
330
331          /* Tell heartbeat thread we're happy */
332          g_mt_working = 1;
333
334      /* send a monitor-mode string */
335      if ( (slen = strlen(monmde_str_arr[idx])) == 1)
336      {
337        /* if '\' (or '\r') then delay a bit before */
338        if ( (rc1 = k2c_flush_recv(K2MI_FLSH_LONG)) == K2R_ERROR)
339          return rc1;
340      }
341
342      if (gcfg_debug > 2)
343        logit("e", "sending MM %d\n", idx);
344
345      if ( (rc1 = k2c_tran_buff((const unsigned char *)(monmde_str_arr[idx]),
346                                slen, gcfg_commtimeout_itvl, 0)) != slen)
347        return rc1;     /* if error transmitting then return */
348
349      /* increment index into monitor-mode string array */
350      if(++idx >= (sizeof(monmde_str_arr)/sizeof(monmde_str_arr[0])))
351        idx = 0;             /* if past end-of-array then wrap around to beg */
352
353      /* wait a bit for (possible) data to appear */
354      /*  (wait a bit longer if '\' (or '\r') command) */
355      if ( (rc1 = k2c_rcvflg_tout( ((slen==1)?K2MI_FLSH_LONG:K2MI_FLSH_SHORT)))
356           == K2R_ERROR)
357        return rc1;
358
359      /* save any data returned from K2 */
360      if ( (dcnt = k2c_recv_buff(g_k2mi_buff, K2MI_IBFSIZ,
361                                 gcfg_commtimeout_itvl, 0)) > 0)
362      {       /* data was received */
363        /* Tell heartbeat thread we're happy */
364        g_mt_working = 1;
365
366        g_k2mi_buff[dcnt] = '\0';           /* NULL terminate buffer */
367        if (gcfg_debug > 2)
368          logit("e", "received:  %s\n", g_k2mi_buff);
369
370        /* check if returned data contains monitor-mode prompt ('*') */
371        if ( strchr((char *)g_k2mi_buff, (int)'*') != NULL)
372          break;             /* if monitor-mode prompt ('*') then exit loop */
373      }
374      else if (dcnt == K2R_ERROR)
375        return dcnt;
376    }
377    while(--monmde_count);         /* loop if count not expired */
378    /* Now we should be in monitor mode, unless monmde_count expired */
379
380    /* send block-mode command string */
381    slen = strlen(blkmde_str);
382    if (gcfg_debug > 2)
383      logit("e", "%s\n",blkmde_str);
384
385    if ( (rc1 = k2c_tran_buff((unsigned char *)blkmde_str, slen,
386                                          gcfg_commtimeout_itvl,0)) != slen)
387    {    /* error transmitting; return code */
388      return (rc1 < 0) ? rc1 : K2R_ERROR;   /* only use code if negative */
389                                            /* 1/29/2002 -- [ET] */
390    }
391    if ( (rc1 = k2c_flush_recv(K2MI_FLSH_SHORT)) == K2R_ERROR)
392      return rc1;
393    if (rc1 == 0) return K2R_POSITIVE;
394  }
395  while (--blkmde_count);           /* loop if count not expired */
396  logit("et", "k2mi_init_blkmde: failed to put k2 in block mode\n");
397  return K2R_ERROR;
398}
399
400
401/**************************************************************************
402 * k2mi_ping_test:  executes ping test on K2                              *
403 *        Sockets are never retried on timeout                            *
404 *         count    - number of pings to send and confirm                 *
405 *         *pseqnum - address of sequence number for sent command packet  *
406 *                    which will be incremented                           *
407 *      return value:  returns K2R_NO_ERROR if `count' pings returned;    *
408 *                     returns K2R_ERROR on error or K2R_TIMEOUT          *
409 **************************************************************************/
410
411int k2mi_ping_test(int count, unsigned char *pseqnum)
412{
413  int rc, slen;
414  static const char ping_test_data[]=
415                               "K2 ping test data \\\\\xC0\xC0\\1234567890";
416
417  if (gcfg_debug > 2)
418    logit("e", "ping test\n");
419
420  /* check receive and flush any waiting data */
421  if (gcfg_debug > 3)
422    logit("e", "flushing...");
423  if ( (rc = k2c_flush_recv(0)) != K2R_NO_ERROR)
424    return rc;
425  if (gcfg_debug > 3)
426    logit("e", "done\n");
427
428  while(1)    /* loop for each ping send/receive test */
429  {           /* send ping packet */
430    slen = strlen(ping_test_data);       /* get string length */
431    if (gcfg_debug > 3)
432      logit("e", "sending ping\n");
433    if ( (rc = k2p_send_packet((unsigned char)PKC_PING, *pseqnum,
434                               K2MI_PKT_SRCNUM, slen,
435                               (unsigned char *)ping_test_data, 0))
436         != K2R_NO_ERROR)
437      break;                 /* if error then exit loop */
438
439    /* wait for expected response packet (ignore SDS auto-packets) */
440    if ( (rc = k2pm_recv_waitpkt(PKR_PING, *pseqnum, K2MI_PKT_SRCNUM,
441                                 &g_k2mi_hdrblk, g_k2mi_buff, PKR_STRDATA,
442                                 gcfg_commtimeout_itvl, 0)) != K2R_POSITIVE)
443    {
444      if (rc == K2R_NO_ERROR)  /* something returned, but not a packet */
445        rc = K2R_TIMEOUT;      /* call it a timeout */
446      break;
447    }
448    if (rc == K2R_POSITIVE)  /* packet returned */
449      rc = K2R_NO_ERROR;     /* switch return value to current convention */
450
451    /* check packet data */
452    if(g_k2mi_hdrblk.dataLength != slen ||
453       strncmp((char *)g_k2mi_buff, ping_test_data, (size_t)slen) != 0)
454    {    /* packet data mismatch */
455      rc = K2R_ERROR;            /* setup error code */
456      logit("et", "k2mi_ping_test: ping data mismatch\n");
457      break;                           /* exit loop */
458    }
459    if(--count <= 0)              /* decrement count */
460      break;                      /* if done then exit loop */
461    ++(*pseqnum);                 /* increment sequence number */
462  }
463  ++(*pseqnum);         /* increment sequence number */
464  if (gcfg_debug > 2)
465    logit("e", "k2mi_ping_test returning %d\n", rc);
466
467  return rc;            /* return OK code */
468}
469
470/**************************************************************************
471 * k2mi_get_params:  fetches general K2 parameters (note that none of     *
472 *      the numeric multi-byte entries are byte-swapped by this function) *
473 *      Never does communication retries.                                 *
474 *         pk2hdr  - address of header block to receive parameter data    *
475 *         *pseqnum - address of sequence number for sent command packet  *
476 *                    which will be incremented                           *
477 *      return value:  returns K2R_POSITIVE on return of param packet     *
478 *                     K2R_NO_ERROR if no fatal errors occured but param  *
479 *                       packet didn't come back;                         *
480 *                     K2R_ERROR on fatal errors; K2R_TIMEOUT on timeout  *
481 **************************************************************************/
482
483int k2mi_get_params(K2_HEADER *pk2hdr, unsigned char *pseqnum)
484{
485  int rc;
486  size_t to_copy;
487
488#ifdef DEBUG
489  if(pk2hdr == NULL)              /* if NULL pointer then */
490  {
491    logit("et", "k2mi_get_params: NULL paramter pk2hdr\n");
492    return K2R_ERROR;
493  }
494#endif
495
496  /* check receive and flush any waiting data */
497  if ( (rc = k2c_flush_recv(0)) != K2R_NO_ERROR)
498    return rc;
499
500  /* send get-K2-parameters command packet */
501  if ( (rc = k2p_send_packet((unsigned char)PKC_GETPARMS, *pseqnum,
502                             K2MI_PKT_SRCNUM, (unsigned short)0,
503                             NULL, 0)) == K2R_NO_ERROR)
504  {      /* send OK; wait for expected response packet (ignore message pkts) */
505    if ( (rc = k2pm_recv_waitpkt((unsigned char)PKR_PARMS, *pseqnum,
506                                 K2MI_PKT_SRCNUM, &g_k2mi_hdrblk,
507                                 g_k2mi_buff, (unsigned char)PKC_MSG,
508                                 gcfg_commtimeout_itvl, 0)) == K2R_POSITIVE)
509    {         /* 'parameters' packet received OK */
510      if (g_k2mi_hdrblk.dataLength == (unsigned short)K2_HEAD_SIZE)
511      {       /* packet size OK */
512        memset(pk2hdr, 0, sizeof(*pk2hdr));
513        /* copy data into K2 parameters header block to be returned */
514        /*  (copy smaller of # of bytes received or struct size) */
515        to_copy = (sizeof(*pk2hdr) < K2_HEAD_SIZE) ?
516          sizeof(*pk2hdr) : K2_HEAD_SIZE;
517        memcpy(pk2hdr, g_k2mi_buff, to_copy);
518      }
519      else    /* unexpected packet size */
520      {
521        logit("et", "k2mi_get_params: wrong sized packet returned from K2\n");
522        return K2R_NO_ERROR;
523      }
524    }
525  }
526  ++(*pseqnum);         /* increment sequence number */
527  return rc;            /* return code */
528}
529
530
531/**************************************************************************
532 * k2mi_get_status:  fetches K2 status block (note that none of the       *
533 *      numeric multi-byte entries are byte-swapped by this function)     *
534 *         pk2stat  - address of STATUS_INFO block to receive status data *
535 *         *pseqnum - address of sequence number for sent command packet  *
536 *                    which will be incremented                           *
537 *      return value:  returns K2R_POSITIVE on return of status packet;   *
538 *                     K2R_NO_ERROR if no fatal errors occured but status *
539 *                       packet didn't return;                            *
540 *                     K2R_ERROR on fatal errors; K2R_TIMEOUT on timeout  *
541 **************************************************************************/
542
543int k2mi_get_status(struct STATUS_INFO *pk2stat, unsigned char *pseqnum)
544{
545  int rc;
546  size_t to_copy;
547
548#ifdef DEBUG
549  if (pk2stat == NULL)             /* if NULL pointer then */
550  {
551    logit("et", "k2mi_get_status: NULL paramter pk2stat\n");
552    return K2R_ERROR;
553  }
554#endif
555
556  /* check receive and flush any waiting data */
557  if ( (rc = k2c_flush_recv(0)) != K2R_NO_ERROR)
558    return rc;
559
560  /* send get-K2-status command packet */
561  if ( (rc = k2p_send_packet((unsigned char)PKC_GETSTATUS, *pseqnum,
562                             K2MI_PKT_SRCNUM, (unsigned short)0,
563                             NULL, 0)) == K2R_NO_ERROR)
564  {      /* send OK; wait for expected response packet (ignore none) */
565    if ( (rc = k2pm_recv_waitpkt((unsigned char)PKR_STATUS, *pseqnum,
566                                 K2MI_PKT_SRCNUM, &g_k2mi_hdrblk,
567                                 g_k2mi_buff, (unsigned char)K2PM_IGNR_NONE,
568                                 gcfg_commtimeout_itvl, 0)) == K2R_POSITIVE)
569    {         /* 'parameters' packet received OK */
570      if (g_k2mi_hdrblk.dataLength == (unsigned short)STATUS_SIZE)
571      {       /* packet size OK */
572        memset(pk2stat, 0, sizeof(*pk2stat));
573        /* copy data into K2 parameters status block to be returned */
574        /*  (copy smaller of # of bytes received or struct size) */
575        to_copy = (sizeof(*pk2stat) < STATUS_SIZE) ?
576          sizeof(*pk2stat) : STATUS_SIZE;
577        memcpy(pk2stat, g_k2mi_buff, to_copy);
578      }
579      else    /* unexpected packet size */
580      {
581        logit("et", "k2mi_get_status: wrong sized packet returned from K2\n");
582        return K2R_NO_ERROR;
583      }
584    }
585  }
586  ++(*pseqnum);         /* increment sequence number */
587  return rc;            /* return code */
588}
589
590/**************************************************************************
591 * k2mi_get_extstatus:  fetches K2 extended status block (note that none  *
592 *      of the numeric multi-byte entries are byte-swapped by this        *
593 *      function)                                                         *
594 *         pk2stat  - address of EXT_STATUS_INFO block to receive         *
595 *         *pseqnum - address of sequence number for sent command packet  *
596 *                    which will be incremented                           *
597 *      return value:  returns K2R_POSITIVE on return of status packet;   *
598 *                     K2R_NO_ERROR if no fatal errors occured but status *
599 *                       packet didn't return;                            *
600 *                     K2R_ERROR on fatal errors; K2R_TIMEOUT on timeout  *
601 **************************************************************************/
602
603int k2mi_get_extstatus(struct EXT2_STATUS_INFO *pk2stat, unsigned char *pseqnum,
604                       int *pext_size)
605{
606  int rc;
607  size_t to_copy;
608
609#ifdef DEBUG
610  if (pk2stat == NULL)             /* if NULL pointer then */
611  {
612    logit("et", "k2mi_get_extstatus: NULL paramter pk2stat\n");
613    return K2R_ERROR;
614  }
615#endif
616
617  /* check receive and flush any waiting data */
618  if ( (rc = k2c_flush_recv(0)) != K2R_NO_ERROR)
619    return rc;
620
621  /* send get-K2-status command packet */
622  if ( (rc = k2p_send_packet((unsigned char)PKC_EXTSTATUS, *pseqnum,
623                             K2MI_PKT_SRCNUM, (unsigned short)0,
624                             NULL,0)) == K2R_NO_ERROR)
625  {      /* send OK; wait for expected response packet (ignore none) */
626    if ( (rc = k2pm_recv_waitpkt((unsigned char)PKR_EXTSTATUS, *pseqnum,
627                                 K2MI_PKT_SRCNUM, &g_k2mi_hdrblk,
628                                 g_k2mi_buff, (unsigned char)K2PM_IGNR_NONE,
629                                 gcfg_commtimeout_itvl, 0)) == K2R_POSITIVE)
630    {         /* 'parameters' packet received OK */
631      if (g_k2mi_hdrblk.dataLength == (unsigned short)EXT_SIZE)
632      {       /* packet size OK */
633        memset(pk2stat, 0, sizeof(*pk2stat));
634        /* copy data into K2 parameters status block to be returned */
635        /*  (copy smaller of # of bytes received or struct size) */
636        to_copy = (sizeof(*pk2stat) < EXT_SIZE) ? sizeof(*pk2stat) : EXT_SIZE;
637        memcpy(pk2stat, g_k2mi_buff, to_copy);
638        *pext_size = EXT_SIZE;
639      }
640      else if (g_k2mi_hdrblk.dataLength == (unsigned short)EXT2_SIZE)
641      {
642          memset(pk2stat, 0, sizeof(*pk2stat));
643          /* copy data into K2 parameters status block to be returned */
644          /*  (copy smaller of # of bytes received or struct size) */
645          to_copy = (sizeof(*pk2stat) < EXT2_SIZE) ? sizeof(*pk2stat) : EXT2_SIZE;
646          memcpy(pk2stat, g_k2mi_buff, to_copy);
647          *pext_size = EXT2_SIZE;
648      }
649    else    /* unexpected packet size */
650      {
651        logit("et","k2mi_get_extstatus: wrong sized packet returned from"
652              " K2 (was %d, should be %d or %d)\n",
653              (int)(g_k2mi_hdrblk.dataLength),EXT_SIZE, EXT2_SIZE);
654        *pext_size = 0;
655        return K2R_NO_ERROR;
656      }
657    }
658  }
659  ++(*pseqnum);         /* increment sequence number */
660  return rc;            /* return code */
661}
662
663/**************************************************************************
664 * k2mi_req_status:  requests K2 status block                             *
665 *         *pseqnum - address of sequence number for sent command packet  *
666 *                    which will be incremented                           *
667 *      return value:  returns K2R_NO_ERROR if request is transmitted     *
668 *                     K2R_ERROR on fatal errors; K2R_TIMEOUT on timeout  *
669 **************************************************************************/
670
671int k2mi_req_status(unsigned char *pseqnum)
672{
673  int rc;
674
675  /* send get-K2-status command packet */
676  rc = k2p_send_packet((unsigned char)PKC_GETSTATUS, *pseqnum,
677                       K2MI_PKT_SRCNUM, (unsigned short)0,
678                       NULL,1);
679  ++(*pseqnum);         /* increment sequence number */
680  return rc;            /* return code */
681}
682
683/**************************************************************************
684 * k2mi_req_extstatus:  requests K2 extended status block                 *
685 *         *pseqnum - address of sequence number for sent command packet  *
686 *                    which will be incremented                           *
687 *      return value:  returns K2R_NO_ERROR if request is transmitted     *
688 *                     K2R_ERROR on fatal errors; K2R_TIMEOUT on timeout  *
689 **************************************************************************/
690
691int k2mi_req_extstatus(unsigned char *pseqnum)
692{
693  int rc;
694
695  /* send get-K2-status command packet */
696  rc = k2p_send_packet((unsigned char)PKC_EXTSTATUS, *pseqnum,
697                       K2MI_PKT_SRCNUM, (unsigned short)0,
698                       NULL,1);
699  ++(*pseqnum);         /* increment sequence number */
700  return rc;            /* return code */
701}
702
703
704/**************************************************************************
705 * k2mi_req_params:  requests K2 paramter block                            *
706 *         *pseqnum - address of sequence number for sent command packet  *
707 *                    which will be incremented                           *
708 *      return value:  returns K2R_NO_ERROR if request is transmitted     *
709 *                     K2R_ERROR on fatal errors; K2R_TIMEOUT on timeout  *
710 **************************************************************************/
711
712int k2mi_req_params(unsigned char *pseqnum)
713{
714  int rc;
715
716  /* send get-K2-params command packet */
717  rc = k2p_send_packet((unsigned char)PKC_GETPARMS, *pseqnum,
718                       K2MI_PKT_SRCNUM, (unsigned short)0,
719                       NULL,1);
720  ++(*pseqnum);         /* increment sequence number */
721  return rc;            /* return code */
722}
723
724
725/**************************************************************************
726 * k2mi_log_pktinfo:  logs information about given packet                 *
727 *         phdrblk  - address of header block for packet                  *
728 *         databuff - address of data buffer for packet                   *
729 **************************************************************************/
730
731void k2mi_log_pktinfo(struct PACKET_HDR *phdrblk, unsigned char *databuff)
732{
733  int slen, index;
734  unsigned long alarm, chanmask = 0x00000001;
735
736  switch(phdrblk->typeCode)
737  {      /* process packet based on type-code */
738  case PKC_MSG:            /* system message packet from K2 */
739    /* Ignore these messages */
740    if (strncmp((char *)databuff, "CAUTION: Acquisition is ON", 26) == 0)
741       break;
742
743    /* Log the message string (if not too long) */
744    logit("et","K2 message received: %s\n",
745          (strlen((char *)databuff) < PACKET_MAX_SIZE-11) ?
746          (char *)databuff: "<unterminated-string>");
747
748    /* If flash memory error is detected, send msg to statmgr */
749    /* Added in version 2.26 by W Kohler, added station name to message in 2.35  */
750    if ( strncmp((char *)databuff, "pcdrv_raw_read, error", 21) == 0 ) 
751    {
752       sprintf(msg, "K2 <%s>: pcdrv_raw_read error (bad flash memory)",
753                g_stnid);
754       k2mi_status_hb(g_error_ltype, K2STAT_BAD_DISK, msg);
755    }
756    if ( strncmp((char *)databuff, "pcdrv_raw_write, error", 22) == 0 )
757    {
758       sprintf(msg, "K2 <%s>: pcdrv_raw_write error (bad flash memory)",
759                g_stnid);
760       k2mi_status_hb(g_error_ltype, K2STAT_BAD_DISK, msg);
761    }
762    break;
763  case PKC_SETALARM:       /* alarm message from K2 */
764    /* display alarm as 32-bit int (if length OK) */
765    if(phdrblk->dataLength == (unsigned short)4)
766    {
767      sprintf(msg, "K2 alarm received for channels: ");
768      slen = strlen(msg);
769      alarm = BYTESWAP_UINT32(((struct K2_ALARM*)databuff)->channelBitMap);
770      for (index = 0; index < ABS_MAX_CHANNELS; index++)
771      {
772        if (alarm & chanmask)
773        {
774          sprintf(&msg[slen], "%d ", index + 1);
775          slen = strlen(msg);
776        }
777        chanmask = chanmask << 1L;
778      }
779      logit("et","%s\n", msg);
780    }
781    else
782      logit("et","K2 alarm: <unexpected data-length>\n");
783    break;
784  case PKR_STRDATA:        /* serial data stream auto packet */
785  case PKR_STRRQDATA:      /* serial data stream requested packet */
786    if ( gcfg_debug > 0 )
787       logit("et","Unexpected SDS (%s) packet, "
788             "seq-num=%hu, src-num=%hu, data-len=%hu\n",
789             ((phdrblk->typeCode == (unsigned char)PKR_STRDATA) ?
790             "PKR_STRDATA" : "PKR_STRRQDATA"),
791             (unsigned short)(phdrblk->seqNo), phdrblk->source,
792             phdrblk->dataLength);
793    break;
794  case PKR_STATUS:
795    if (phdrblk->dataLength == (unsigned short) STATUS_SIZE)
796      k2mi_report_status((struct STATUS_INFO *)databuff);
797    else
798      logit("et", "k2ew: abnormal length status packet received\n");
799    break;
800 case PKR_EXTSTATUS:
801    if (phdrblk->dataLength == (unsigned short)EXT_SIZE)
802      k2mi_report_extstatus((struct EXT2_STATUS_INFO *)databuff, EXT_SIZE);
803    else if (phdrblk->dataLength == (unsigned short)EXT2_SIZE)
804      k2mi_report_extstatus((struct EXT2_STATUS_INFO *)databuff, EXT2_SIZE);
805    else
806    {
807      logit("et", "k2ew: abnormal length extended status packet"
808            " received (%d)\n",(int)(phdrblk->dataLength));
809      if (phdrblk->dataLength == (unsigned short)(EXT_SIZE*2))
810      {  /* extended packet is new double-length size */
811        g_extstatus_avail = 0;    /* clear flag to stop future requests */
812        if(gcfg_debug > 0)
813        {     /* debug enabled; log message */
814          logit("et",
815                   "Extended status packets will no longer be requested\n");
816        }
817      }
818    }
819    break;
820  case PKR_PARMS:
821    if (phdrblk->dataLength == (unsigned short)K2_HEAD_SIZE)
822      k2mi_report_params((K2_HEADER *)databuff);
823    else
824      logit("et", "k2ew: abnormal length params packet received\n");
825    break;
826  case PKR_STRNAK:
827    logit("et", "K2 STR_NAK rcvd: %s\n",
828          k2pm_strnak_errcd(phdrblk, databuff, NULL));
829    break;
830  default:       /* unknown packet type-code, display message */
831    logit("et","Unexpected packet received, type-code=%02hXH, "
832          "seq-num=%hu, src-num=%hu, data-len=%hu\n",
833          (unsigned short)(phdrblk->typeCode),
834          (unsigned short)(phdrblk->seqNo),
835          phdrblk->source, phdrblk->dataLength);
836  }
837}
838
839/*****************************************************************
840 * k2mi_report_status: Report information form K2 status packet  *
841 *         pk2stat - pointer to K2 status structure              *
842 *****************************************************************/
843
844void k2mi_report_status( struct STATUS_INFO *pk2stat)
845{
846  time_t timevar;
847  unsigned short wtemp1, wtemp2;
848  char tempchar, disk[2] = {'A', 'B'};
849  int tempbat, index;
850  double batv, diskfree;
851  static char msg2[MAX_MSG_SIZE];      /* another buffer for text messages */
852
853  if (gcfg_inject_info==1)
854        k2info_send(K2INFO_TYPE_STATUS, (char *) pk2stat);
855  /* System time and clock source */
856  timevar = (time_t)(BYTESWAP_UINT32(pk2stat->systemTime) + K2_TIME_CONV);
857  sprintf(msg, "K2 Time = %s", asctime(gmtime(&timevar)));
858  msg[strlen(msg)-1] = '\0';         /* delete the newline left by ctime() */
859
860  switch (pk2stat->clockSource)
861  {
862  case 0:
863    strcat(msg, " set from RTC");
864    break;
865  case 1:
866    strcat(msg, " set from Keyboard");
867    break;
868  case 2:
869    strcat(msg, " set from External Pulse");
870    break;
871  case 3:
872    strcat(msg, " set from Internal GPS");
873    break;
874  default:
875    strcat(msg, " set from (?)");
876  }
877  logit("et","%s\n", msg);
878
879  /* Battery voltage and hardware status */
880  tempbat = (int) pk2stat->batteryStatus;   /* char, no need to swap */
881  batv = tempbat/10.0;
882  if (tempbat < 0)
883  {
884    batv = -batv;
885  }
886  if (tempbat > 0) /* K2 says battery voltage is zero when it is charging */
887  {
888    logit("et", "K2 HW Status = %s Battery Status: %0.1f V\n",
889          (pk2stat->hardwareStatus == (unsigned char)SF_OK)?"OK":"FAULT", batv);
890    if (gcfg_on_batt && rep_on_batt == 0)
891    {
892    sprintf(msg, "K2 <%s>: lost external power; battery voltage: %0.1f V", 
893                g_stnid, batv);
894    k2mi_status_hb(g_error_ltype, K2STAT_ON_BATT, msg);
895    rep_on_batt = 1;
896    }
897  }
898  else
899  {
900    logit("et", "K2 HW Status = %s Battery Status: charging\n",
901          (pk2stat->hardwareStatus == (unsigned char)SF_OK)?"OK":"FAULT");
902    if (rep_on_batt == 1 && gcfg_on_batt)
903    {
904    sprintf(msg, "K2 <%s>: external power restored", g_stnid);
905    k2mi_status_hb(g_error_ltype, K2STAT_OFF_BATT, msg);
906    rep_on_batt = 0;
907    rep_low_batt = 0;
908    }
909  }
910
911  if (gcfg_battery_alarm > 0 && rep_low_batt == 0 && tempbat > 0
912      && batv < 0.1 * gcfg_battery_alarm)
913  {
914    sprintf(msg, "K2 <%s>: low battery voltage: %0.1f V", 
915                g_stnid, batv);
916    k2mi_status_hb(g_error_ltype, K2STAT_LOW_BATT, msg);
917    rep_low_batt = 1;
918  }
919  /* We assume battery voltage goes up only when external power is restored */
920
921  if (gcfg_hwstat_alarm && rep_hwstat == 0
922      && pk2stat->hardwareStatus == (unsigned char) SF_FAULT)
923  {
924    sprintf(msg, "K2 <%s> hardware fault", g_stnid);
925    k2mi_status_hb(g_error_ltype, K2STAT_HW_FAULT, msg);
926    rep_hwstat = 1;
927  }
928  else if (gcfg_hwstat_alarm && rep_hwstat == 1)
929  {
930    sprintf(msg, "K2 <%s> hardware fault cleared", g_stnid);
931    k2mi_status_hb(g_error_ltype, K2STAT_HWFLT_CLR, msg);
932    rep_hwstat = 0;
933  }
934
935  /* Event and recording error counts */
936  logit("et", "Events: %hu Recording Errors: %hu\n",
937        BYTESWAP_UINT16(pk2stat->events),
938        BYTESWAP_UINT16(pk2stat->recordingErrors));
939
940  /* Trigger status */
941  wtemp1 = BYTESWAP_UINT16(pk2stat->triggerStatus);
942  sprintf(msg, "Acquisition: ");
943  if (wtemp1 & 0x0001)
944  {
945    strcat(msg, "on (");
946    if (((wtemp1 & 0x0002) == 0) &&
947        ((wtemp1 & 0x0004) == 0) &&
948        ((wtemp1 & 0x0010) == 0))
949      strcat(msg, "not ");
950    strcat(msg, "triggered);");
951  }
952  else
953    strcat(msg, "off;");
954
955  strcat(msg, "  Alarm: ");
956  if ((wtemp1 & 0x0008) == 0)
957    strcat(msg, "not ");
958  strcat(msg, "triggered.");
959  logit("et", "%s\n", msg);
960
961  /* Disk drive status */
962  strcpy(msg, "Drive:");
963  for (index = 0; index < 2; index++)
964  {
965    sprintf(&msg[strlen(msg)], " %c: ", 'A' + index);
966    wtemp1 = BYTESWAP_UINT16(pk2stat->driveStatus[index]);
967    if (wtemp1 & SF_NOT_READY)
968    {
969      strcat(msg, "not ready");
970      if ( gcfg_disk_alarm[index] > 0.0 && rep_disk[index] == 0)
971      {
972        sprintf(msg2, "K2 <%s>: disk %c failure", 
973                g_stnid, disk[index]);
974        k2mi_status_hb(g_error_ltype, K2STAT_BAD_DISK, msg2);
975        rep_disk[index] = 1;
976      }
977    }
978    else
979    {
980      if ((wtemp1 & SF_GB) == SF_GB)
981      {
982        tempchar = 'G';
983        diskfree = 1073741824.0;   /* `giga' bytes */
984      }
985      else
986      {
987        if ((wtemp1 & SF_MB) == SF_MB)
988        {
989          tempchar = 'M';
990          diskfree = 1048576.0;  /* `mega' bytes */
991        }
992        else
993        {
994          if ((wtemp1 & SF_KB) == SF_KB)
995          {
996            tempchar = 'K';
997            diskfree = 1024.0;  /* `Kilo' bytes */
998          }
999        }
1000      }
1001      wtemp2 = wtemp1 & SF_FREE;
1002      diskfree *= (double)wtemp2;
1003      sprintf(&msg[strlen(msg)], "%d %cB FREE", wtemp2, tempchar);
1004
1005      if (gcfg_disk_alarm[index] > 0.0 && diskfree < gcfg_disk_alarm[index]
1006          && rep_disk[index] == 0)
1007      {
1008        sprintf(msg2, "K2 <%s>: low free space on disk A: %d %cB",
1009                g_stnid, wtemp2, tempchar);
1010        k2mi_status_hb(g_error_ltype, K2STAT_LOW_DISK, msg2);
1011        rep_disk[index] = 1;
1012      }
1013      else if (gcfg_disk_alarm[index] > 0.0 && rep_disk[index] == 1
1014               && diskfree >= gcfg_disk_alarm[index] )
1015      {   /* Disk is no longer full */
1016        sprintf(msg2, "K2 <%s>: disk space OK; A: %d %cB",
1017                g_stnid, wtemp2, tempchar);
1018        k2mi_status_hb(g_error_ltype, K2STAT_OK_DISK, msg2);
1019        rep_disk[index] = 0;
1020      }
1021    }
1022  }
1023  logit("et", "%s\n", msg);
1024}
1025
1026/*****************************************************************
1027 * k2mi_report_extstatus: Report information form K2 extended    *
1028 *             status packet                                     *
1029 *   It seems the K2 doesn't actually support this message, so   *
1030 *   don't expect this function to be used: PNL 8/22/00          *
1031 *   Since the data reported here is not included in the params  *
1032 *   structure, we keep this code around, just in case KMI gets  *
1033 *   ambitious and implements what they advertise; hah!          *
1034 *         pk2stat - pointer to K2 extended status structure     *
1035 *****************************************************************/
1036
1037void k2mi_report_extstatus( struct EXT2_STATUS_INFO *pk2stat, int ext_size)
1038{
1039  unsigned short us_dummy;
1040  unsigned long ul_dummy;
1041  unsigned short fault;
1042  time_t timevar;
1043  char msg[20];
1044 
1045  /* The extended status structure is not byte-aligned for Sparc or Intel *
1046   * hardware. So we have to copy out the bytes into dummy variables      *
1047   * before we can manipluate them. Thanks, kinemetrics!                  */
1048
1049  /* Last restart time */
1050  memcpy(&ul_dummy, ((char *)pk2stat) + 2, sizeof(long));
1051  timevar = (time_t)(BYTESWAP_UINT32(ul_dummy) + K2_TIME_CONV);
1052  switch (pk2stat->clockSource)
1053  {
1054  case 0:
1055    strcpy(msg, "RTC");
1056    break;
1057  case 1:
1058    strcpy(msg, "Keyboard");
1059    break;
1060  case 2:
1061    strcpy(msg, "External Pulse");
1062    break;
1063  case 3:
1064    strcpy(msg, "Internal GPS");
1065    break;
1066  default:
1067    strcpy(msg, "(?)");
1068  }
1069  logit("e", "K2 Extended Status Message: last restart: Time = %s set from %s\n",
1070        asctime(gmtime(&timevar)), msg);
1071
1072  /* Fault status */
1073  memcpy(&us_dummy, ((char *)pk2stat) + 6, sizeof(short));
1074  fault = BYTESWAP_UINT16(us_dummy);
1075  strcpy(msg, "K2 fault status: ");
1076  if (fault != (unsigned short)0)
1077  {
1078    if (fault & FAULT_SYSTEM)
1079      strcat(msg, "bad parameters; ");
1080    if (fault & FAULT_FLASH)
1081      strcat(msg, "flash error; ");
1082    if (fault & FAULT_RAM)
1083      sprintf(&msg[strlen(msg)], "ram error at %lX; ",
1084              BYTESWAP_UINT32(pk2stat->lastRAMError));
1085    if (fault & FAULT_PCMCIA)
1086      strcat(msg, "bad/missing PCMCIA; ");
1087    if (fault & FAULT_DSP)
1088      strcat(msg, "failed to load DSP; ");
1089    if (fault & FAULT_PARMBLK)
1090      strcat(msg, "param block CRC error; ");
1091    if (fault & FAULT_FLASH_MAINTENANCE)
1092      strcat(msg, "flash maintenance required;");
1093
1094    /* I assume that a fault here will also be reported by the HW fault bit
1095       in the status message, so we don't bother sending and earthworm status
1096       message here */
1097  }
1098  else
1099    strcat(msg, "OK");
1100
1101  logit("e", "%s\n", msg);
1102
1103  /* inject it if requested to */
1104  if (gcfg_inject_info==1 && ext_size==EXT_SIZE)
1105        k2info_send(K2INFO_TYPE_ESTATUS, (char *) pk2stat);
1106  else if (gcfg_inject_info==1 && ext_size==EXT2_SIZE)
1107        k2info_send(K2INFO_TYPE_E2STATUS, (char *) pk2stat);
1108
1109  if (ext_size == EXT_SIZE) return;
1110 
1111  /* Report additional information in the "extended" extended status packet */
1112
1113  return;
1114}
1115
1116
1117/*****************************************************************
1118 * k2mi_write_header: Write binary K2 header to disk file        *
1119 *         pk2hdr - pointer to K2 header structure               *
1120 *****************************************************************/
1121
1122static void k2mi_write_header( K2_HEADER *k2hdr )
1123{
1124   FILE *fp = fopen( gcfg_header_filename, "wb" );
1125   if ( fp == NULL )
1126   {
1127      logit( "e", "Can't open new K2 header file: <%s>\n", gcfg_header_filename );
1128      return;
1129   }
1130   if ( fwrite( k2hdr, sizeof(K2_HEADER), 1, fp ) < 1 )
1131   {
1132      logit( "e", "Error writing K2 header file: <%s>\n", gcfg_header_filename );
1133      fclose( fp );
1134      return;
1135   }
1136   fclose( fp );           /* All ok */
1137   if (gcfg_debug > 0)
1138      logit( "et", "K2 header file written: <%s>\n", gcfg_header_filename );
1139   return;
1140}
1141
1142
1143/*****************************************************************
1144 * k2mi_report_params: Report some information from K2 param     *
1145 *             packet: temperature and GPS                       *
1146 *         pk2hdr - pointer to K2 param structure                *
1147 *****************************************************************/
1148
1149void k2mi_report_params( K2_HEADER *pk2hdr)
1150{
1151  short batt_voltx10;
1152  double batv;
1153  short temp;
1154
1155/* Write K2 header to a disk file
1156   ******************************/
1157   if (gcfg_header_filename[0] != '\0')
1158      k2mi_write_header( pk2hdr );
1159
1160   if (gcfg_inject_info == 1)
1161        k2info_send(K2INFO_TYPE_HEADER, (char *) pk2hdr);
1162
1163/* System temperature
1164   ******************/
1165  temp = (short)BYTESWAP_UINT16(pk2hdr->roParms.misc.temperature);
1166  logit("et", "Temperature: %d.%1d deg C\n", temp / 10, temp % 10);
1167
1168  if ((int)temp < gcfg_templo_alarm && rep_temp == 0)
1169  {
1170    sprintf(msg, "K2 <%s>: low temperature: %d.%1d C", 
1171                g_stnid, temp / 10, temp % 10);
1172    k2mi_status_hb(g_error_ltype, K2STAT_LOW_TEMP, msg);
1173    rep_temp = 1;
1174  }
1175  else if ((int)temp > gcfg_temphi_alarm && rep_temp == 0)
1176  {
1177    sprintf(msg, "K2 <%s>: high temperature: %d.%1d C", 
1178                g_stnid, temp / 10, temp % 10);
1179    k2mi_status_hb(g_error_ltype, K2STAT_HIGH_TEMP, msg);
1180    rep_temp = 1;
1181  }
1182  else if (rep_temp == 1)
1183  {
1184    sprintf(msg, "K2 <%s>: temperature OK: %d.%1d C", 
1185                g_stnid, temp / 10, temp % 10);
1186    k2mi_status_hb(g_error_ltype, K2STAT_OK_TEMP, msg);
1187    rep_temp = 0;
1188  }
1189
1190/* Log the last GPS lock time and drift. If the GPS hasn't locked
1191   for gcfg_gpslock_alarm hours, send one message to statmgr.
1192   If and when the GPS locks up again, send another msg to statmgr.
1193   ***************************************************************/
1194   {
1195      const int year2000 = 946080000;   /* Jan 1, 2000 in seconds */
1196
1197      time_t now      = time(0);        /* PC clock time */
1198      time_t timevar1 = (time_t)(BYTESWAP_UINT32(pk2hdr->roParms.timing.gpsLastLockTime[0])
1199                         + K2_TIME_CONV);
1200      char *timestr1  = asctime(gmtime(&timevar1));
1201
1202      timestr1[strlen(timestr1)-1] = '\0';
1203      temp = (short)BYTESWAP_UINT32(pk2hdr->roParms.timing.gpsLastDrift[0]);
1204      logit("et", "Last GPS lock: %s  Drift: %d msec\n", timestr1, temp );
1205
1206      if ( (gcfg_gpslock_alarm >= 0.0) && (now > year2000) && (timevar1 > year2000) )
1207      {
1208         static int prev_gpslock  = 1;            /* Assume GPS was locked at startup */
1209         double timeSinceLastLock = (now - timevar1) / 3600.;
1210
1211         if ( timeSinceLastLock >= gcfg_gpslock_alarm )
1212         {
1213            logit( "et", "WARNING. GPS hasn't locked for %.1lf hours.\n", timeSinceLastLock );
1214            if ( prev_gpslock == 1 )
1215            {
1216               sprintf(msg, "K2 <%s>: No GPS lock for %.1lf hours.", 
1217                        g_stnid, timeSinceLastLock );
1218               k2mi_status_hb(g_error_ltype, K2STAT_GPSLOCK, msg);
1219            }
1220            prev_gpslock = 0;
1221         }
1222         else
1223         {
1224            if ( prev_gpslock == 0 ) 
1225            {
1226               sprintf(msg, "K2 <%s>: GPS lock acquired.", g_stnid);
1227               k2mi_status_hb(g_error_ltype, K2STAT_GPSLOCK, msg);
1228            }
1229            prev_gpslock = 1;
1230         }
1231      }
1232   }
1233
1234  /* Battery voltage is reported as negative when supplied from external *
1235   * source. That's what we need here; internal battery voltage is       *
1236   * reported in status block, above */
1237  batt_voltx10 = (signed short)BYTESWAP_UINT16(pk2hdr->roParms.misc.batteryVoltage);
1238
1239  if (batt_voltx10 < 0)
1240  {
1241    batt_voltx10 = -batt_voltx10;
1242    batv = batt_voltx10 / 10.0;
1243    logit("et", "External battery voltage: %0.1f V\n", batv);
1244  }
1245
1246  /* If k2ew used a restart file to read the station name
1247   * (g_validrestart_flag == 1), we must verify that name against
1248   * the K2's idea of station name. If they don't match, someone
1249   * must have used a non-unique restart-file name in the config file.
1250   * If k2ew continues, then the trace data will be labeled with the
1251   * wrong station name: Bad doodoo! */
1252  if (g_validrestart_flag == 1)
1253  {      /* restart file was used */
1254    if(strncmp(g_k2_stnid,pk2hdr->rwParms.misc.stnID,sizeof(g_k2_stnid)-1) != 0
1255                && strncmp(g_stnid,gcfg_stnid_remap,sizeof(g_stnid)-1) != 0)
1256    {         /* original station name and remapped name do not match */
1257      logit("et","k2ew: MAJOR ERROR: K2 station name <%s> does not match "
1258                 "station name <%s>\n"
1259                 "\tfrom restart file (\"%s\"); Terminating!\n",
1260              pk2hdr->rwParms.misc.stnID,g_k2_stnid, gcfg_restart_filename);
1261      g_terminate_flg = 1;        /* set program terminate flag */
1262
1263    }
1264    else      /* name matches OK */
1265      g_validrestart_flag = 2;    /* so we don't do this test again */
1266  }
1267}
1268
1269
1270/*************************************************************
1271 * k2mi_status_hb: sends heartbeat or status messages to     *
1272 *         earthworm transport ring.                         *
1273 *       type: the message type: heartbeat or status         *
1274 *       code: the error code for status messages            *
1275 *       message: message text, if any                       *
1276 *************************************************************/
1277
1278void k2mi_status_hb(unsigned char type, short code, char* message )
1279{
1280  char          outMsg[MAX_MSG_SIZE];  /* The outgoing message.        */
1281  time_t        msgTime;        /* Time of the message.                 */
1282
1283  /*  Get the time of the message                                       */
1284  time( &msgTime );
1285
1286  /*  Build & process the message based on the type                     */
1287  if ( g_heartbeat_logo.type == type )
1288  {
1289    sprintf( outMsg, "%ld %ld\n\0", (long) msgTime, (long) g_pidval );
1290
1291    /*Write the message to the output region                            */
1292    if ( tport_putmsg( &g_tport_region, &g_heartbeat_logo,
1293                       (long) strlen( outMsg ), outMsg ) != PUT_OK )
1294    {
1295      /*     Log an error message                                       */
1296      logit( "et", "k2ew: Failed to send a heartbeat message (%d).\n",
1297             code );
1298    }
1299  }
1300  else
1301  {
1302    if ( message )
1303    {
1304      sprintf( outMsg, "%ld %hd %s\n\0", (long) msgTime, code, message );
1305      logit("et","Error:%d (%s)\n", code, message );
1306    }
1307    else
1308    {
1309      sprintf( outMsg, "%ld %hd\n\0", (long) msgTime, code );
1310      logit("et","Error:%d (No description)\n", code );
1311    }
1312
1313    /*Write the message to the output region                         */
1314    if ( tport_putmsg( &g_tport_region, &g_error_logo,
1315                       (long) strlen( outMsg ), outMsg ) != PUT_OK )
1316    {
1317      /*     Log an error message                                    */
1318      logit( "et", "k2ew: Failed to send an error message (%d).\n",
1319             code );
1320    }
1321  }
1322}
Note: See TracBrowser for help on using the repository browser.