Search code examples
ctimerpthreadsdelaymultitasking

C - Timer logic for error condition


I'm working on a project where I have to deal with several sensors, and print out error values to a textfile. Currently I'm doing random generators, to just generate some dummy values. The thing here is that the same errors are stored into the textfile, since the code is running fast and in loop. So I'm thinking of making a timer to handle the last stored data for the current sensor. I'm not sure if this is a good idea, since it doesn't sound easy, because in the end I will have to handle about 30 different sensors. Any idea how I can implement such a logic into my code?

struct arg_struct{ //store the these data into the textfile
    char *sensorname;
    double sensorvalue;
    int faultcode; 
};

//insert the data into the textfile with the arguments from detect_error
void *write_sens_error(void *arguments){ 
    struct arg_struct *args = arguments;
    struct tm *local;
    time_t t;
    t = time(NULL);
    local = localtime(&t);
    FILE *fp;
    fp = fopen("/home/sal/Desktop/sensors.txt","a");
    fprintf(fp, "%s %s %f %s %d %s %s", args -> sensorname, "\t",args -> sensorvalue, "\t", args -> faultcode,"\t",asctime(local));
    fclose(fp);
    pthread_exit(NULL);
    return NULL;
}

//create a new thread, so the second thread will handle the errorvalue storage
void detect_error(char *sensorname, double sensorvalue, int faultcode){
    pthread_t thread_error1;
    struct arg_struct args;
    args.sensorname = malloc(7);
    strcpy(args.sensorname, sensorname);
    args.sensorvalue = sensorvalue;
    args.faultcode = faultcode;
    pthread_create(&thread_error1, NULL, &write_sens_error, (void *)&args);
    pthread_join(thread_error1, NULL);
    free(args.sensorname);
}
//generate random values and check for error
void rand_temperature_sensor(double EXTS[8], int FTS, int CTS, int OTS){
    int i;
    for (i = 0; i < 8; i++){
        EXTS[i] = rand() % 10 + 820;
        if(EXTS[i]>800){
            char name[6];
            sprintf(name, "EXTS%d", i+1);
            detect_error(name,EXTS[i],((EXTS[i]>850) ? 2 : 1));
        }
    }
    printf("%s,%f,%f,%f,%f,%f,%f,%f,%f\n","Temp",EXTS[0],EXTS[1],EXTS[2],EXTS[3],EXTS[4],EXTS[5],EXTS[6],EXTS[7];
}

And here is a snippet of the log this code is generating. As seen from the log, the same sensors are stored three times in one second. That is what I want to avoid, so the error from sensors are only stored after let's say 5 seconds after the previous error catch.

EXTS0    823.000000      1   Tue Apr 28 23:43:57 2015
EXTS1    820.000000      1   Tue Apr 28 23:43:57 2015
EXTS2    826.000000      1   Tue Apr 28 23:43:57 2015
EXTS3    827.000000      1   Tue Apr 28 23:43:57 2015
EXTS4    829.000000      1   Tue Apr 28 23:43:57 2015
EXTS5    826.000000      1   Tue Apr 28 23:43:57 2015
EXTS6    820.000000      1   Tue Apr 28 23:43:57 2015
EXTS7    823.000000      1   Tue Apr 28 23:43:57 2015
EXTS0    827.000000      1   Tue Apr 28 23:43:57 2015
EXTS1    828.000000      1   Tue Apr 28 23:43:57 2015
EXTS2    822.000000      1   Tue Apr 28 23:43:57 2015
EXTS3    826.000000      1   Tue Apr 28 23:43:57 2015
EXTS4    822.000000      1   Tue Apr 28 23:43:57 2015
EXTS5    822.000000      1   Tue Apr 28 23:43:57 2015
EXTS6    829.000000      1   Tue Apr 28 23:43:57 2015
EXTS7    826.000000      1   Tue Apr 28 23:43:57 2015
EXTS0    821.000000      1   Tue Apr 28 23:43:57 2015
EXTS1    823.000000      1   Tue Apr 28 23:43:57 2015
EXTS2    822.000000      1   Tue Apr 28 23:43:57 2015
EXTS3    824.000000      1   Tue Apr 28 23:43:57 2015
EXTS4    826.000000      1   Tue Apr 28 23:43:57 2015
EXTS5    826.000000      1   Tue Apr 28 23:43:57 2015
EXTS6    821.000000      1   Tue Apr 28 23:43:57 2015
EXTS7    824.000000      1   Tue Apr 28 23:43:57 2015

I really not hope this question was confusing. Please let me know if I have to clear out something. The full code is pasted here.


Solution

  • I suggest you add a "pthread_mutex_t" to handle file writing:
    1. declare mutex_writing as global variable
    2. is_writing[EXTS_LIMIT] as global variable //for each sensor:boolean indicating writing status
    3. writingtime[EXTS_LIMIT]//store the last writing time for a given sensor
    4. index //added to arg_struct in order to identify the sensor and modify is_writing
    5. at writing time lock mutex_writing then unlock

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <pthread.h>
    #include <time.h>
    
    #define EXTS_limit 1000
    #define CPS_limit 200
    #define MAF1_limit 700
    #define MAF2_limit 130
    #define KS_limit 20
    #define FTS_limit 100
    #define CTS_limit 105
    #define OTS_limit 100
    #define OPS_limit 11
    #define FPS_limit 11
    #define MAP_limit 5
    
    
     /****/
     #define    MILLISECONDES  1000
     #define    FIVESECS   5000*MILLISECONDES
     pthread_mutex_t mutex_writing = PTHREAD_MUTEX_INITIALIZER;
     int is_writing[EXTS_limit];
      clock_t writingtime[EXTS_limit];
     /***/
    
    
    struct arg_struct{
            char *sensorname;
            double sensorvalue;
            int faultcode;
        int index;
    };
    
    void *write_sens_error(void *arguments)
    {
         pthread_mutex_lock(&mutex_writing);
        struct arg_struct *args = arguments;
            struct tm *local;
            time_t t;
            t = time(NULL);
            local = localtime(&t);
    
        FILE *fp;
        fp = fopen("/home/sal/Desktop/sensor_data.txt","a"); //PATH TO THE TEXTFILE.
        fprintf(fp, "%s %s %f %s %d %s %s", args -> sensorname, "\t",args -> sensorvalue, "\t", args -> faultcode,"\t",asctime(local));
            fclose(fp);
        is_writing[args->index]=0;
        pthread_mutex_unlock(&mutex_writing);
        pthread_exit(NULL);
        return NULL;
    }
    
    void detect_error(char *sensorname, double sensorvalue, int faultcode, int index){
            pthread_t thread_error1;
            struct arg_struct args;
            args.sensorname = malloc(7);
            strcpy(args.sensorname, sensorname);
            args.sensorvalue = sensorvalue;
            args.faultcode = faultcode;
        args.index=index;
             clock_t t=clock();
        if(is_writing[index]==0 && ((float)t-(float)writingtime[index])>FIVESECS)
        {
        is_writing[index]=1;
                writingtime[index]=clock();
                 pthread_create(&thread_error1, NULL, &write_sens_error, (void *)&args);
                 pthread_join(thread_error1, NULL);
            }
            free(args.sensorname);
    }
    
    void rand_temperature_sensor(double EXTS[8], int FTS, int CTS, int OTS){
            int i;
            for (i = 0; i < 8; i++){
                    EXTS[i] = rand() % 10 + 820;
                    if(EXTS[i]>EXTS_limit){
                            char name[6];
                            sprintf(name, "EXTS%d", i+1);
                            detect_error(name,EXTS[i],((EXTS[i]>1050) ? 2 : 1),i);
                    }
            }
            FTS = rand() % 30 + 91;
                    if(FTS > FTS_limit) detect_error("FTS",FTS,((FTS>120) ? 2 : 1),8);
            CTS = rand() % 3 + 90;
                    if(CTS > CTS_limit) detect_error("CTS",CTS,((CTS>110) ? 2 : 1),9);
            OTS = rand() % 30 + 91;
                    if(OTS > OTS_limit) detect_error("OTS",OTS,((OTS>120) ? 2 : 1),10);
            printf("%s,%f,%f,%f,%f,%f,%f,%f,%f,%d,%d,%d\n","Temp",EXTS[0],EXTS[1],EXTS[2],EXTS[3],EXTS[4],EXTS[5],EXTS[6],EXTS[7],FTS,CTS,OTS);
    }
    
    void rand_CPS_LS_KS_ACC(int CPS[8], int LS[2], int KS[2],int TS[2]){
            int i;
            for (i = 0; i < 8; i++){
                    CPS[i] = rand() % 2 + 20;
            }
            for(i=0; i < 2; i++){
                    LS[i] = rand() % 3 + 30;
                    KS[i] = rand() % 3 + 40;
                    TS[i] = rand() % 40 + 100;
            }
    
            printf("%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n","CPS_LS_KS_TS", CPS[0],CPS[1],CPS[2],CPS[3],CPS[4],CPS[5],CPS[6],CPS[7],LS[0],LS[1],KS[0],KS[1],TS[0],TS[1]);
    }
    
    void rand_CAM_ACC(int CAM[4], int ACC_[2]){
            int i;
            for (i = 0; i < 4; i++){
                    CAM[i] = rand() % 7 + 10;
            }
                    ACC_[1] = rand() % 3 + 20;
                    ACC_[2] = rand() % 1 + 1;
            printf("%s,%d,%d,%d,%d,%d,%d\n","CAM_ACC", CAM[0],CAM[1],CAM[2],CAM[3],ACC_[1],ACC_[2]);
    }
    
    void rand_MAP_MAF_FFS_CRANK(int dash_kmt, int MAP, int MAF, int FFS, int CRANK, int OPS, int FPS){
            dash_kmt = rand() % 6 + 60;
            MAP = rand() % 10 + 30;
            MAF = rand() % 5 + 20;
            FFS = rand() % 2 + 20;
            CRANK = rand() % 3 + 2;
            OPS = rand() % 3 + 2;
            FPS = 25;
            printf("%s,%d,%d,%d,%d,%d,%d,%d\n","dash", dash_kmt,MAP,MAF,FFS,CRANK,OPS,FPS);
    }
    
    int main() {
    
    /*Init global variables*/
    int count=0;
    for(count=0;count<EXTS_limit;count++)
    {
        is_writing[count]=0;
    writingtime[count]=0;
    }
    /****/
    
    
        int i;
        setbuf(stdout, NULL); // Disable output buffering.
        //setbuf(stdin, NULL); //Disable input buffering
    
            srand ( time(NULL) ); //generate different random values
    
            double EXTS[8]; int CPS[8],CAM[4],LS[2],KS[2],TS[2],ACC_[2],FTS, CTS, OTS;
            int dash_kmt,MAP,MAF,FFS,CRANK,OPS,FPS;
            int state = 1;
            while(state == 1){
                    rand_temperature_sensor(EXTS,FTS,CTS,OTS);
                    rand_CPS_LS_KS_ACC(CPS,LS,KS,TS);
                    rand_CAM_ACC(CAM,ACC_);
                    rand_MAP_MAF_FFS_CRANK(dash_kmt,MAP,MAF,FFS,CRANK,OPS,FPS);
                    usleep(600);
            }
    
            //pthread_join(thread_error1, NULL);
    
        return 0;
    }