Electronics > Beginners
help with a little program in linux, need to catch an event
(1/3) > >>
coldfiremc:
Hi
I have to make a C program for Raspbian, which, among other stuff creates a binary file, and fills it with serial port captured stuff everyday. So, no matter the time the machine is turned on, just on midnight, i have to create a new file. I Can't find anything like (I'am a sort of MSDOS guy) INT70h alarm event, that triggers at a specific hour. If the solution is available just with the standard C library, it could be great. Is there anything with that behaviour?

thanks
saike:
Take a look at crontab examples  https://opensource.com/article/17/11/how-use-cron-linux which run tasks at specified times
coldfiremc:
ok, I need to specify more details: I need to catch an asynchronous event, with maximum precision available. alarm() looks great, except by one quirk: i need to specify an "explicit" amount of time. If I Can "subtract" ticks between the current time and midnight on the fly would be great. I was about to use date, but delays can occur, and also, I have to "unnecesarily" parse the output.
hamster_nz:
You could use an alarm to signal to the program to see if it needs to open a new file, or you could use something like this, to read the serial port and open a new file when the first input is seen on a new day.


--- Code: ---#include <stdio.h>
#include <time.h>
#include <sys/time.h>

int main(int argc, char *argv[])
{
  FILE *f = NULL;
  FILE *fin = NULL;
  int year = 0,month = 0,day = 0;
  int c;

  /* Select or open the input file */
  if(argc == 1) {
    fin = stdin;
  } else if(argc == 2) {
    fin = fopen(argv[1],"rb");
    if(fin == NULL) {
      fprintf(stderr,"Unable to open '%s'\n",argv[1]);
    } else {
      fprintf(stderr,"Opened '%s'\n",argv[1]);
    }
  } else {
    fprintf(stderr,"Usage : %s [input file]\n",argv[0]);
  }

  /* Process the characters */
  while(fin != NULL) {
    time_t now_secs;
    struct tm *now;
    /* Get a character */
    c = getc(fin);
    if(c == EOF) break;

    /* Get the time */
    now_secs = time(NULL);
    now = localtime(&now_secs);
    /* Do we need to open a new file */
    if(f == NULL
           || now->tm_mday != day
           || now->tm_mon != month
           || now->tm_year != year) {
      char buffer[16];


      year  = now->tm_year;
      month = now->tm_mon;
      day   = now->tm_mday;
      /* Close any existing file */
      if(f != NULL) {
        fclose(f);
        f = NULL;
      }
      /* Make a file name and open it - check the length of buffer if you change this! */
      sprintf(buffer,"log.%04i-%02i-%02i",year+1900,month,day);
      f = fopen(buffer,"a");
      if(f == NULL) {
        fprintf(stderr,"Unable to open '%s'\b", buffer);
        break;
      }
    }
    /* Output the character to the file, flush if a newline is seen */
    if( f != NULL) {
      putc(c,f);
      if(c == '\n')
        fflush(f);
    }
  }

  /* Cleanup */
  if(argc == 1 && fin != NULL) {
    fclose(fin);
  }
  if(f != NULL)
    fclose(f);
  return 0;
}

--- End code ---

If this meets your requirements or not depends if you need an empty file on a day where you have no input.  You could change the 'getc()'  call to 'select()' with a timeout of a few seconds, which would allow you to avoid the hassles of managing signals. That would involve switching to the unbuffered open()/read()/close() to process the input file, which is just a bit awkward for a quick hack.

You should either 'nohup' it, or set it up as a service (e.g. as script in /etc/init.d or add it to /etc/rc.local or maybe in /etc/inittab) so that it runs on boot, and/or restarts if it gets killed by a user.

If you need to configure the serial port (e.g. set its speed, flow control and so on) either use the 'stty' utility before you open it, or have a read of the man page for 'tcgetattr' and add the required calls to the program.

hamster_nz:

--- Quote from: coldfiremc on May 14, 2018, 04:07:38 am ---Hi
I have to make a C program for Raspbian, which, among other stuff creates a binary file, and fills it with serial port captured stuff everyday. So, no matter the time the machine is turned on, just on midnight, i have to create a new file. I Can't find anything like (I'am a sort of MSDOS guy) INT70h alarm event, that triggers at a specific hour. If the solution is available just with the standard C library, it could be great. Is there anything with that behaviour?

thanks

--- End quote ---

If you really do want to set an alarm, this will help: http://www.gnu.org/software/libc/manual/html_node/Setting-an-Alarm.html

You will need to set up an empty signal handler for SIGALRM, as the default behavior is to terminate the process.

I think you will find that read() or getc() will return -1 with errno set to "EINTR" when the alarm is triggered, avoiding the need to do any real work in your interrupt handler.


--- Code: ---#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>

void handler(int i) {
  /* Do nothing in the signal handler */
}

int main(int argc, char *argv[]) {
   int carry_on = 1;
   struct sigaction sa;


   sa.sa_handler = handler;
   sa.sa_flags = 0;
   sigfillset(&sa.sa_mask);

   if(sigaction(SIGALRM, &sa, NULL) == -1) {
      perror("Error: cannot handle SIGALRM");
   }

   while(carry_on) {
      int c;
      /* Set up an alarm in two seconds */
      alarm(2);

      /* read a character */
      c = getchar();

      if(c == EOF) {
         /* Trap the alarm */
         switch(errno) {
            case EINTR:
               printf("EINTR - alarm called\n");
               break;
            default:
               carry_on = 0;
               break;
         }
      } else {
         /* Output the character */
         putchar(c);
      }
   }

   return 0;
}

--- End code ---
Navigation
Message Index
Next page
There was an error while thanking
Thanking...

Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod