// references: // https://api.libssh.org/stable/libssh_tutorial.html // https://api.libssh.org/stable/libssh_tutor_guided_tour.html // plplot example 17 // plplot example ext-cairo-test.c // https://docs.gtk.org/gtk4/class.DrawingArea.html // https://www.gtk.org/docs/getting-started/hello-world/ #include #include #include #include // verify_knownhost() #include #include #include // open() // plplot #include #include #include //#include #include #include #include // very small also works, just transfter delays, I test accelerometer data is // like 15782 which is 7 bytes consider newline and \0? #define MAX_XFER_BUF_SIZE 7 #define LEN 10 // Variables for holding error return info from PLplot static PLINT pl_errcode; static char errmsg[160]; typedef struct { ssh_session session; sftp_session sftp; PLINT id1; PLFLT t[LEN]; PLFLT buffer[LEN]; GtkWidget *area; }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"); DATA *data=user_data; 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, "/sys/bus/iio/devices/iio:device2/in_accel_z_raw", 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; } for(int i=0;i<(LEN-1);i++) data->buffer[i]=data->buffer[i+1]; for (;;) { nbytes = sftp_read(file, buffer, sizeof(buffer)); 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; } //printf("buffer %s",buffer); //printf("buffer int %d\n",atoi(buffer)); //printf("id1 %d\n",data->id1); //printf("t %f\n",data->t[9]); //printf("before sftp_read_sync plstripa\n"); data->buffer[LEN-1]=atof(buffer); //printf("after sftp_read_sync plstripa\n"); } 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; } for(int i=0;it[i]++; //printf("sftp_read_sync end\n"); gtk_widget_queue_draw(data->area); //return SSH_OK; // must return G_SOURCE_CONTINUE to keep polling // return G_SOURCE_REMOVE to stop return G_SOURCE_CONTINUE; } // https://api.libssh.org/stable/libssh_tutor_guided_tour.html int verify_knownhost(ssh_session session) { enum ssh_known_hosts_e state; unsigned char *hash = NULL; ssh_key srv_pubkey = NULL; size_t hlen; char buf[10]; char *hexa; char *p; int cmp; int rc; rc = ssh_get_server_publickey(session, &srv_pubkey); if (rc < 0) { return -1; } rc = ssh_get_publickey_hash(srv_pubkey, SSH_PUBLICKEY_HASH_SHA1, &hash, &hlen); ssh_key_free(srv_pubkey); if (rc < 0) { return -1; } state = ssh_session_is_known_server(session); switch (state) { case SSH_KNOWN_HOSTS_OK: /* OK */ break; case SSH_KNOWN_HOSTS_CHANGED: fprintf(stderr, "Host key for server changed: it is now:\n"); ssh_print_hexa("Public key hash", hash, hlen); fprintf(stderr, "For security reasons, connection will be stopped\n"); ssh_clean_pubkey_hash(&hash); return -1; case SSH_KNOWN_HOSTS_OTHER: fprintf(stderr, "The host key for this server was not found but an other" "type of key exists.\n"); fprintf(stderr, "An attacker might change the default server key to" "confuse your client into thinking the key does not exist\n"); ssh_clean_pubkey_hash(&hash); return -1; case SSH_KNOWN_HOSTS_NOT_FOUND: fprintf(stderr, "Could not find known host file.\n"); fprintf(stderr, "If you accept the host key here, the file will be" "automatically created.\n"); /* FALL THROUGH to SSH_SERVER_NOT_KNOWN behavior */ case SSH_KNOWN_HOSTS_UNKNOWN: hexa = ssh_get_hexa(hash, hlen); fprintf(stderr,"The server is unknown. Do you trust the host key?\n"); fprintf(stderr, "Public key hash: %s\n", hexa); ssh_string_free_char(hexa); ssh_clean_pubkey_hash(&hash); p = fgets(buf, sizeof(buf), stdin); if (p == NULL) { return -1; } cmp = strncasecmp(buf, "yes", 3); if (cmp != 0) { return -1; } rc = ssh_session_update_known_hosts(session); if (rc < 0) { fprintf(stderr, "Error %s\n", strerror(errno)); return -1; } break; case SSH_KNOWN_HOSTS_ERROR: fprintf(stderr, "Error %s", ssh_get_error(session)); ssh_clean_pubkey_hash(&hash); return -1; } ssh_clean_pubkey_hash(&hash); return 0; } static void draw_function (GtkDrawingArea *area, cairo_t *cr, int width, int height, gpointer user_data) { //printf("draw begin\n"); DATA *data=user_data; PLINT autoy, acc; PLFLT ymin, ymax, xlab, ylab; PLFLT tmin, tmax, tjump; PLINT colbox, collab, colline[4], styline[4]; PLCHAR_VECTOR legline[4]; // If db is used the plot is much more smooth. However, because of the // async X behaviour, one does not have a real-time scripcharter. // This is now disabled since it does not significantly improve the // performance on new machines and makes it difficult to use this // example non-interactively since it requires an extra pleop call after // each call to plstripa. // //plsetopt("db", ""); //plsetopt("np", ""); // User sets up plot completely except for window and data // Eventually settings in place when strip chart is created will be // remembered so that multiple strip charts can be used simultaneously. // // Specify some reasonable defaults for ymin and ymax // The plot will grow automatically if needed (but not shrink) ymin = -0.1; ymax = 0.1; // Specify initial tmin and tmax -- this determines length of window. // Also specify maximum jump in t // This can accomodate adaptive timesteps tmin = 0.; tmax = 10.; tjump = 0.3; // percentage of plot to jump // Axes options same as plbox. // Only automatic tick generation and label placement allowed // Eventually I'll make this fancier colbox = 1; collab = 3; styline[0] = colline[0] = 2; // pens color and line style styline[1] = colline[1] = 3; styline[2] = colline[2] = 4; styline[3] = colline[3] = 5; legline[0] = "in_accel_z_raw"; // pens legend legline[1] = "not_used"; legline[2] = "not_used"; legline[3] = "not_used"; xlab = 0.; ylab = 0.25; // legend position autoy = 1; // autoscale y acc = 1; // don't scrip, accumulate // Initialize plplot plsdev( "extcairo" ); plinit(); pl_cmd( PLESC_DEVINIT, cr ); pladv( 0 ); plvsta(); // Register our error variables with PLplot // From here on, we're handling all errors here plsError( &pl_errcode, errmsg ); plstripc( &(data->id1), "bcnst", "bcnstv", tmin, tmax, tjump, ymin, ymax, xlab, ylab, autoy, acc, colbox, collab, colline, styline, legline, "t", "", "Strip chart demo" ); if ( pl_errcode ) { fprintf( stderr, "%s\n", errmsg ); exit( 1 ); } // Let plplot handle errors from here on plsError( NULL, NULL ); autoy = 0; // autoscale y acc = 1; // accumulate for(int i=0;it[i]); //printf("buffer%d %f\n",i,data->buffer[i]); plstripa( data->id1, 0, data->t[i], data->buffer[i]); } //printf("before pl free\n"); plstripd( data->id1 ); plend(); //printf("draw done\n"); } static void print_data (GtkWidget *widget, gpointer user_data) { DATA *data=user_data; printf("t:"); for(int i=0;it[i]); putchar('\n'); printf("buffer:"); for(int i=0;ibuffer[i]); putchar('\n'); } static void activate (GtkApplication *app, gpointer user_data) { DATA *data=user_data; GtkWidget *window; data->area = gtk_drawing_area_new (); GtkWidget *button; GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL,1); window = gtk_application_window_new (app); gtk_window_set_title (GTK_WINDOW (window), "remote_plot"); gtk_window_set_default_size (GTK_WINDOW (window), 1000, 1000); gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (data->area), 600); gtk_drawing_area_set_content_height (GTK_DRAWING_AREA (data->area), 600); gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (data->area), draw_function, user_data, NULL); button = gtk_button_new_with_label ("Print data"); g_signal_connect (button, "clicked", G_CALLBACK (print_data), user_data); gtk_box_append(GTK_BOX(box), button); gtk_box_append(GTK_BOX(box), data->area); gtk_window_set_child (GTK_WINDOW (window), box); gtk_window_present (GTK_WINDOW (window)); g_timeout_add(50,sftp_read_sync,user_data); //printf("after g_timeout_add\n"); } int main (int argc, char **argv) { DATA data; //ssh_session session; //sftp_session sftp; int rc; GtkApplication *app; int status; for(int i=0;i