diff options
author | Xiao Pan <xyz@flylightning.xyz> | 2025-04-29 23:41:06 -0700 |
---|---|---|
committer | Xiao Pan <xyz@flylightning.xyz> | 2025-04-29 23:41:06 -0700 |
commit | 7c86c3921d26788e7a01f4215b098d7e8f31579e (patch) | |
tree | 850fff2f39cd35f0867366d30c76d2c9aa9273aa /remote_plot.c | |
parent | 15854b83aeed2ca9dab055d68b02f487ce39f765 (diff) |
feat: save to local, cli option to read only from local
Diffstat (limited to 'remote_plot.c')
-rw-r--r-- | remote_plot.c | 329 |
1 files changed, 213 insertions, 116 deletions
diff --git a/remote_plot.c b/remote_plot.c index 443747a..bd0c503 100644 --- a/remote_plot.c +++ b/remote_plot.c @@ -195,90 +195,158 @@ typedef struct { uint32_t from_time; uint32_t to_time; bool from_time_entered; + // local file name + char *filename; + // only read from local .csv file or not + bool local; }DATA; -static gboolean sftp_read_sync(gpointer user_data) - //int sftp_read_sync(ssh_session session, sftp_session sftp) +static gboolean read_data(gpointer user_data) +//static gboolean sftp_read_sync(gpointer user_data) +//int sftp_read_sync(ssh_session session, sftp_session sftp) { - //printf("sftp_read_sync begin\n"); + //printf("read_data begin\n"); DATA *data=user_data; + bool new_entry=false; - int access_type; - sftp_file file; - char buffer[MAX_XFER_BUF_SIZE]; - int nbytes, rc; - access_type = O_RDONLY; - - // This is to represent a loop over time - // Let's try a random walk process - - file = sftp_open(data->sftp, sftp_expand_path(data->sftp,"~/.local/share/mycan.csv"), access_type, 0); - if (file == NULL) { - fprintf(stderr, "Can't open file for reading: %s\n", - ssh_get_error(data->session)); - //return SSH_ERROR; - return G_SOURCE_REMOVE; - } + if(data->local) + { + //printf("read_data check local pass\n"); + FILE *fp; + if((fp=fopen(data->filename,"r"))!=NULL) + { + //printf("offset before fseek %d\n",data->offset); + fseek(fp, data->offset, SEEK_SET); + //printf("before read_data local for loop\n"); + for(;;) + { + //printf("start read_data local for loop\n"); + Item temp; + int ct=fscanf(fp,"%u,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf",&(temp.t),&(temp.volt[0]),&(temp.volt[1]),&(temp.volt[2]),&(temp.volt[3]),&(temp.volt[4]),&(temp.volt[5]),&(temp.volt[6]),&(temp.volt[7]),&(temp.volt[8]),&(temp.volt[9]),&(temp.volt[10]),&(temp.volt[11]),&(temp.volt[12]),&(temp.volt[13]),&(temp.volt[14]),&(temp.volt[15]),&(temp.volt[16]),&(temp.volt[17]),&(temp.volt[18]),&(temp.volt[19]),&(temp.volt[20]),&(temp.volt[21]),&(temp.volt[22]),&(temp.volt[23]),&(temp.volt[24]),&(temp.volt[25]),&(temp.volt[26]),&(temp.volt[27]),&(temp.volt[28]),&(temp.volt[29]),&(temp.volt[30]),&(temp.volt[31]),&(temp.volt[32]),&(temp.volt[33]),&(temp.volt[34]),&(temp.volt[35]),&(temp.volt[36]),&(temp.volt[37]),&(temp.volt[38]),&(temp.volt[39]),&(temp.volt[40]),&(temp.volt[41]),&(temp.volt[42]),&(temp.volt[43]),&(temp.volt[44]),&(temp.volt[45]),&(temp.volt[46]),&(temp.volt[47]),&(temp.volt[48]),&(temp.volt[49]),&(temp.volt[50]),&(temp.volt[51]),&(temp.volt[52]),&(temp.volt[53]),&(temp.volt[54]),&(temp.volt[55]),&(temp.volt[56]),&(temp.volt[57]),&(temp.volt[58]),&(temp.volt[59]),&(temp.volt[60]),&(temp.volt[61]),&(temp.volt[62]),&(temp.volt[63]),&(temp.volt[64]),&(temp.volt[65]),&(temp.volt[66]),&(temp.volt[67]),&(temp.volt[68]),&(temp.volt[69]),&(temp.volt[70]),&(temp.volt[71]),&(temp.volt[72]),&(temp.volt[73]),&(temp.volt[74]),&(temp.volt[75]),&(temp.volt[76]),&(temp.volt[77]),&(temp.volt[78]),&(temp.volt[79]),&(temp.volt[80]),&(temp.volt[81]),&(temp.volt[82]),&(temp.volt[83]),&(temp.volt[84]),&(temp.volt[85]),&(temp.volt[86]),&(temp.volt[87]),&(temp.volt[88]),&(temp.volt[89]),&(temp.volt[90]),&(temp.volt[91]),&(temp.volt[92]),&(temp.volt[93]),&(temp.volt[94]),&(temp.volt[95]),&(temp.temp[0]),&(temp.temp[1]),&(temp.temp[2]),&(temp.temp[3]),&(temp.temp[4]),&(temp.temp[5]),&(temp.temp[6]),&(temp.temp[7]),&(temp.temp[8]),&(temp.temp[9]),&(temp.temp[10]),&(temp.temp[11]),&(temp.temp[12]),&(temp.temp[13]),&(temp.temp[14]),&(temp.temp[15]),&(temp.temp[16]),&(temp.temp[17]),&(temp.temp[18]),&(temp.temp[19]),&(temp.temp[20]),&(temp.temp[21]),&(temp.temp[22]),&(temp.temp[23]),&(temp.temp[24]),&(temp.temp[25]),&(temp.temp[26]),&(temp.temp[27]),&(temp.temp[28]),&(temp.temp[29]),&(temp.temp[30]),&(temp.temp[31])); + if(ct == EOF) + break; + else if(ct<(VOLTLEN+TEMPLEN+1)) + { + fprintf(stderr,"Read less items (%d) than expected from local file\n",ct); + //exit(1); + return G_SOURCE_REMOVE; + } + + if(AddItem(temp,&(data->cans))==false) + { + fprintf(stderr,"Problem allocating memory\n"); + //exit(1); + return G_SOURCE_REMOVE; + } - if(data->offset != 0) - sftp_seek(file,data->offset); - for(;;) + if(!new_entry) + new_entry=true; + //printf("end read_data local for loop\n"); + } + //printf("after read_data local for loop\n"); + //printf("offset before ftell %d\n",data->offset); + data->offset=ftell(fp); + //printf("offset after ftell %d\n",data->offset); + fclose(fp); + } + } + else { - nbytes = sftp_read(file, buffer, sizeof(buffer)); - //printf("nbytes: %d\n",nbytes); - //printf("%d\n",MAX_XFER_BUF_SIZE); - if (nbytes == 0) { - break; // EOF - } else if (nbytes < 0) { - fprintf(stderr, "Error while reading file: %s\n", + int access_type; + sftp_file file; + char buffer[MAX_XFER_BUF_SIZE]; + int nbytes, rc; + access_type = O_RDONLY; + + // This is to represent a loop over time + // Let's try a random walk process + + file = sftp_open(data->sftp, sftp_expand_path(data->sftp,"~/.local/share/mycan.csv"), access_type, 0); + if (file == NULL) { + fprintf(stderr, "Can't open file for reading: %s\n", ssh_get_error(data->session)); - sftp_close(file); - //return SSH_ERROR; - return G_SOURCE_REMOVE; - } else if ((nbytes%ENTRY_SIZE) != 0) { - fprintf(stderr, "sftp read nbytes not a multiple of %d\n",ENTRY_SIZE); - sftp_close(file); //return SSH_ERROR; return G_SOURCE_REMOVE; } - // TODO: check strtok return NULL or not - //printf("before strtok\n"); - for(int i=0;i<(nbytes/ENTRY_SIZE);i++) + if(data->offset != 0) + sftp_seek(file,data->offset); + for(;;) { - Item temp; - // TODO: pass endptr and check it and other things to be safe, see https://stackoverflow.com/questions/34206446 - if(i) - temp.t=strtoul(strtok(NULL,","),NULL,10); - else - temp.t=strtoul(strtok(buffer,","),NULL,10); - for(int j=0;j<VOLTLEN;j++) - temp.volt[j]=atof(strtok(NULL,",")); - for(int j=0;j<(TEMPLEN-1);j++) - temp.temp[j]=atof(strtok(NULL,",")); - temp.temp[TEMPLEN-1]=atof(strtok(NULL,"\n")); - //printf("before AddItem\n"); - if(AddItem(temp,&(data->cans))==false) - { - fprintf(stderr,"Problem allocating memory\n"); + nbytes = sftp_read(file, buffer, sizeof(buffer)); + //printf("nbytes: %d\n",nbytes); + //printf("%d\n",MAX_XFER_BUF_SIZE); + if (nbytes == 0) { + break; // EOF + } else if (nbytes < 0) { + fprintf(stderr, "Error while reading file: %s\n", + ssh_get_error(data->session)); + sftp_close(file); + //return SSH_ERROR; + return G_SOURCE_REMOVE; + } else if ((nbytes%ENTRY_SIZE) != 0) { + fprintf(stderr, "sftp read nbytes not a multiple of %d\n",ENTRY_SIZE); + sftp_close(file); + //return SSH_ERROR; return G_SOURCE_REMOVE; } - //printf("after AddItem\n"); + + // TODO: check strtok return NULL or not + //printf("before strtok\n"); + for(int i=0;i<(nbytes/ENTRY_SIZE);i++) + { + Item temp; + FILE *fp; + // TODO: pass endptr and check it and other things to be safe, see https://stackoverflow.com/questions/34206446 + if(i) + temp.t=strtoul(strtok(NULL,","),NULL,10); + else + temp.t=strtoul(strtok(buffer,","),NULL,10); + for(int j=0;j<VOLTLEN;j++) + temp.volt[j]=atof(strtok(NULL,",")); + for(int j=0;j<(TEMPLEN-1);j++) + temp.temp[j]=atof(strtok(NULL,",")); + temp.temp[TEMPLEN-1]=atof(strtok(NULL,"\n")); + //printf("before AddItem\n"); + if(AddItem(temp,&(data->cans))==false) + { + fprintf(stderr,"Problem allocating memory\n"); + return G_SOURCE_REMOVE; + } + if(!new_entry) + new_entry=true; + //printf("after AddItem\n"); + + if((fp=fopen(data->filename,"a"))==NULL) + { + fprintf(stderr,"Can't open file \"%s\".\n",data->filename); + //exit(1); + return G_SOURCE_REMOVE; + } + fprintf(fp,"%u",temp.t); + for(int j=0;j<VOLTLEN;j++) + fprintf(fp,",%5.3f",temp.volt[j]); + for(int j=0;j<TEMPLEN;j++) + fprintf(fp,",%5.1f",temp.temp[j]); + fprintf(fp,"\n"); + fclose(fp); + } + //printf("after strtok\n"); + data->offset+=nbytes; } - //printf("after strtok\n"); - data->offset+=nbytes; - } - rc = sftp_close(file); - if (rc != SSH_OK) { - fprintf(stderr, "Can't close the read file: %s\n", - ssh_get_error(data->session)); - //return rc; - return G_SOURCE_REMOVE; + rc = sftp_close(file); + if (rc != SSH_OK) { + fprintf(stderr, "Can't close the read file: %s\n", + ssh_get_error(data->session)); + //return rc; + return G_SOURCE_REMOVE; + } } - //printf("sftp_read_sync end\n"); + //printf("after read_data check local if else\n"); + if(new_entry) { double sum,avg; // max 28 char + 1 \0: Average temperature: 6553.5 C @@ -296,9 +364,11 @@ static gboolean sftp_read_sync(gpointer user_data) avg=sum/TEMPLEN; sprintf(str,"Average temperature: %.1f C",avg); gtk_label_set_text(GTK_LABEL(data->temp_label),str); + new_entry=false; + gtk_widget_queue_draw(data->area); } - gtk_widget_queue_draw(data->area); + //printf("after check new_entry if\n"); //return SSH_OK; // must return G_SOURCE_CONTINUE to keep polling @@ -622,7 +692,7 @@ static void activate (GtkApplication *app, gpointer user_data) gtk_window_present (GTK_WINDOW (window)); //printf("before g_timeout_add\n"); - g_timeout_add(1000,sftp_read_sync,user_data); + g_timeout_add(1000,read_data,user_data); //printf("after g_timeout_add\n"); } @@ -637,61 +707,66 @@ static int command_line (GApplication *app, GApplicationCommandLine *cmdline, gp // https://docs.gtk.org/glib/gvariant-format-strings.html#pointers // &s copy the pointer g_variant_dict_lookup (options, "destination", "&s", &dest); + g_variant_dict_lookup (options, "local", "b", &(data->local)); - // Open session and set options - data->session = ssh_new(); - if (data->session == NULL) - exit(-1); - ssh_options_set(data->session, SSH_OPTIONS_HOST, dest); - - // Connect to server - rc = ssh_connect(data->session); - if (rc != SSH_OK) + if(!(data->local)) { - fprintf(stderr, "Error connecting to %s: %s\n", - dest, ssh_get_error(data->session)); - ssh_free(data->session); - exit(-1); - } + // Open session and set options + data->session = ssh_new(); + if (data->session == NULL) + exit(-1); + ssh_options_set(data->session, SSH_OPTIONS_HOST, dest); + + // Connect to server + rc = ssh_connect(data->session); + if (rc != SSH_OK) + { + fprintf(stderr, "Error connecting to %s: %s\n", + dest, ssh_get_error(data->session)); + ssh_free(data->session); + exit(-1); + } - // Verify the server's identity - // For the source code of verify_knownhost(), check previous example - if (verify_knownhost(data->session) < 0) - { - ssh_disconnect(data->session); - ssh_free(data->session); - exit(-1); - } + // Verify the server's identity + // For the source code of verify_knownhost(), check previous example + if (verify_knownhost(data->session) < 0) + { + ssh_disconnect(data->session); + ssh_free(data->session); + exit(-1); + } - // Authenticate ourselves - // https://api.libssh.org/stable/libssh_tutor_authentication.html - rc = ssh_userauth_publickey_auto(data->session, NULL, NULL); - if (rc != SSH_AUTH_SUCCESS) - { - fprintf(stderr, "Error authenticating with key: %s\n", - ssh_get_error(data->session)); - ssh_disconnect(data->session); - ssh_free(data->session); - exit(-1); - } + // Authenticate ourselves + // https://api.libssh.org/stable/libssh_tutor_authentication.html + rc = ssh_userauth_publickey_auto(data->session, NULL, NULL); + if (rc != SSH_AUTH_SUCCESS) + { + fprintf(stderr, "Error authenticating with key: %s\n", + ssh_get_error(data->session)); + ssh_disconnect(data->session); + ssh_free(data->session); + exit(-1); + } - data->sftp = sftp_new(data->session); - if (data->sftp == NULL) - { - fprintf(stderr, "Error allocating SFTP session: %s\n", - ssh_get_error(data->session)); - return SSH_ERROR; - } + data->sftp = sftp_new(data->session); + if (data->sftp == NULL) + { + fprintf(stderr, "Error allocating SFTP session: %s\n", + ssh_get_error(data->session)); + return SSH_ERROR; + } - rc = sftp_init(data->sftp); - if (rc != SSH_OK) - { - fprintf(stderr, "Error initializing SFTP session: code %d.\n", - sftp_get_error(data->sftp)); - sftp_free(data->sftp); - return rc; + rc = sftp_init(data->sftp); + if (rc != SSH_OK) + { + fprintf(stderr, "Error initializing SFTP session: code %d.\n", + sftp_get_error(data->sftp)); + sftp_free(data->sftp); + return rc; + } } + // https://discourse.gnome.org/t/gio-application-commandline-does-trigger-activate-signal/2988/22 // > If you pass G_APPLICATION_HANDLES_COMMAND_LINE in the flags, the // > command-line args are passed to the primary instance and ::activate is @@ -711,14 +786,30 @@ int main (int argc, char **argv) GtkApplication *app; int status; + { + // usually ~/.local/share + const char *dir=getenv("XDG_DATA_HOME"); + const char *str; + if(dir != NULL) + str="/mycan.csv"; + else + { + str="/.local/share/mycan.csv"; + dir=getenv("HOME"); + } + data.filename=malloc((strlen(dir)+strlen(str)+1)*sizeof(char)); + sprintf(data.filename,"%s%s",dir,str); + } + InitializeList(&(data.cans)); if(ListIsFull(&(data.cans))) { fprintf(stderr,"No memory available! Bye!\n"); exit(1); } - data.offset=0; data.from_time_entered=false; + data.offset=0; + data.local=false; //printf("after init\n"); @@ -728,6 +819,7 @@ int main (int argc, char **argv) app = gtk_application_new ("org.gtk.example", G_APPLICATION_HANDLES_COMMAND_LINE); g_application_add_main_option(G_APPLICATION(app),"destination",'d',0,G_OPTION_ARG_STRING,"ssh destination","Spartan_Racing_Charger@10.0.0.9"); + g_application_add_main_option(G_APPLICATION(app),"local",'l',0,G_OPTION_ARG_NONE,"Only read from local .csv file",NULL); g_signal_connect (app, "activate", G_CALLBACK (activate), &data); g_signal_connect (app, "command-line", G_CALLBACK (command_line), &data); @@ -737,12 +829,17 @@ int main (int argc, char **argv) //printf("before ssh free\n"); - ssh_disconnect(data.session); - ssh_free(data.session); + if(data.local==false) + { + ssh_disconnect(data.session); + ssh_free(data.session); + } // Segmentation fault (core dumped) error, why? maybe double free? so no free is ok? //sftp_free(sftp); EmptyTheList(&(data.cans)); + free(data.filename); + return status; } |