/** Save a row from the QTH list (called by the save function) */ static gboolean save_qth(GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter, gpointer data) { qth_t qth; gboolean def = FALSE; gchar *filename, *confdir; gchar *buff; (void)path; (void)data; gtk_tree_model_get(model, iter, QTH_LIST_COL_DEF, &def, QTH_LIST_COL_NAME, &qth.name, QTH_LIST_COL_LOC, &qth.loc, QTH_LIST_COL_DESC, &qth.desc, QTH_LIST_COL_LAT, &qth.lat, QTH_LIST_COL_LON, &qth.lon, QTH_LIST_COL_ALT, &qth.alt, QTH_LIST_COL_WX, &qth.wx, QTH_LIST_COL_TYPE, &qth.type, QTH_LIST_COL_GPSD_SERVER, &qth.gpsd_server, QTH_LIST_COL_GPSD_PORT, &qth.gpsd_port, -1); confdir = get_user_conf_dir(); filename = g_strconcat(confdir, G_DIR_SEPARATOR_S, qth.name, ".qth", NULL); g_free(confdir); /* check wehter we are using imperial or metric system; in case of imperial we have to convert altitude from feet to meters before saving. */ if (sat_cfg_get_bool(SAT_CFG_BOOL_USE_IMPERIAL)) { qth.alt = (guint) FT_TO_M(qth.alt); } if (qth_data_save(filename, &qth)) { /* saved ok, go on check whether qth is default */ if (def) { sat_log_log(SAT_LOG_LEVEL_INFO, _("%s:%d: %s appears to be default QTH"), __FILE__, __LINE__, qth.name); buff = g_path_get_basename(filename); sat_cfg_set_str(SAT_CFG_STR_DEF_QTH, buff); g_free(buff); } } g_free(filename); g_free(qth.name); g_free(qth.loc); g_free(qth.desc); g_free(qth.wx); return FALSE; }
/** * Remove .qth files. * * This function is used to remove any existing .qth file * before storing the data from the QTH list. */ static void delete_location_files() { GDir *dir = NULL; /* directory handle */ GError *error = NULL; /* error flag and info */ gchar *dirname; /* directory name */ const gchar *filename; /* file name */ gchar *buff; /* scan for .qth files in the user config directory and add the contents of each .qth file to the list store */ dirname = get_user_conf_dir(); dir = g_dir_open(dirname, 0, &error); if (dir) { while ((filename = g_dir_read_name(dir))) { if (g_str_has_suffix(filename, ".qth")) { buff = g_strconcat(dirname, G_DIR_SEPARATOR_S, filename, NULL); /* remove file */ if (g_remove(buff)) { sat_log_log(SAT_LOG_LEVEL_ERROR, _("%s:%d: Failed to remove %s"), __FILE__, __LINE__, filename); } else { sat_log_log(SAT_LOG_LEVEL_DEBUG, _("%s:%d: Removed %s"), __FILE__, __LINE__, filename); } g_free(buff); } } } else { sat_log_log(SAT_LOG_LEVEL_ERROR, _("%s:%d: Failed to open user cfg dir (%s)"), __FILE__, __LINE__, error->message); g_clear_error(&error); } g_free(dirname); g_dir_close(dir); }
/** * Save configuration data. * @return 0 on success, 1 if an error occured. * * This function saves the configuration data currently stored in * memory to the gpredict.cfg file. */ guint sat_cfg_save() { gchar *keyfile; gchar *confdir; guint err = 0; confdir = get_user_conf_dir (); keyfile = g_strconcat (confdir, G_DIR_SEPARATOR_S, "gpredict.cfg", NULL); err = gpredict_save_key_file( config , keyfile); g_free (confdir); return err; }
/** \brief Load configuration data. * \return 0 if everything OK, 1 otherwise. * * This function reads the configuration data from gpredict.cfg into * memory. This function must be called very early at program start. * * The the configuration data in memory is already "loaded" the data will * be ereased first. */ guint sat_cfg_load () { gchar *keyfile,*confdir; GError *error = NULL; if (config != NULL) sat_cfg_close (); /* load the configuration file */ config = g_key_file_new (); confdir = get_user_conf_dir (); keyfile = g_strconcat (confdir, G_DIR_SEPARATOR_S, "gpredict.cfg", NULL); g_free (confdir); g_key_file_load_from_file (config, keyfile, G_KEY_FILE_KEEP_COMMENTS, &error); g_free (keyfile); if (error != NULL) { sat_log_log (SAT_LOG_LEVEL_WARN, _("%s: Error reading config file (%s)"), __FUNCTION__, error->message); sat_log_log (SAT_LOG_LEVEL_WARN, _("%s: Using built-in defaults"), __FUNCTION__); g_clear_error (&error); return 1; } else { sat_log_log (SAT_LOG_LEVEL_DEBUG, _("%s: Everything OK."), __FUNCTION__); } /* if config version is < 1.1; reset SAT_CFG_STR_TLE_FILES */ guint ver; ver = 10*sat_cfg_get_int (SAT_CFG_INT_VERSION_MAJOR) + sat_cfg_get_int (SAT_CFG_INT_VERSION_MINOR); if (ver < 11) { sat_cfg_reset_str (SAT_CFG_STR_TLE_FILES); sat_cfg_set_int (SAT_CFG_INT_VERSION_MAJOR, 1); sat_cfg_set_int (SAT_CFG_INT_VERSION_MINOR, 1); } return 0; }
/** \brief Save configuration data. * \return 0 on success, 1 if an error occured. * * This function saves the configuration data currently stored in * memory to the gpredict.cfg file. */ guint sat_cfg_save () { gsize length; gsize written; GError *error = NULL; gchar *cfgstr; gchar *keyfile; gchar *confdir; GIOChannel *cfgfile; guint err = 0; /* convert configuration data struct to charachter string */ cfgstr = g_key_file_to_data (config, &length, &error); if (error != NULL) { sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s: Could not create config data (%s)."), __FUNCTION__, error->message); g_clear_error (&error); err = 1; } else { /* create and open a file for writing */ confdir = get_user_conf_dir (); keyfile = g_strconcat (confdir, G_DIR_SEPARATOR_S, "gpredict.cfg", NULL); g_free (confdir); cfgfile = g_io_channel_new_file (keyfile, "w", &error); g_free (keyfile); if (error != NULL) { sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s: Could not create config file (%s)."), __FUNCTION__, error->message); g_clear_error (&error); err = 1; } else { g_io_channel_write_chars (cfgfile, cfgstr, length, &written, &error); g_io_channel_shutdown (cfgfile, TRUE, NULL); g_io_channel_unref (cfgfile); if (error != NULL) { sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s: Error writing config data (%s)."), __FUNCTION__, error->message); g_clear_error (&error); err = 1; } else if (length != written) { sat_log_log (SAT_LOG_LEVEL_WARN, _("%s: Wrote only %d out of %d chars."), __FUNCTION__, written, length); err = 1; } else { sat_log_log (SAT_LOG_LEVEL_MSG, _("%s: Configuration saved."), __FUNCTION__); err = 0; } } g_free (cfgstr); } return err; }
/** * Create data storage for QTH list. * * This function creates the data storage necessary for the * list view. The newly created tree model is populated with * data from the .qth files in the users config diretory. * The individual .qth files are read by the read_qth_file * function. */ static GtkTreeModel *create_and_fill_model() { GtkListStore *liststore; /* the list store data structure */ GDir *dir = NULL; /* directory handle */ GError *error = NULL; /* error flag and info */ gchar *dirname; /* directory name */ const gchar *filename; /* file name */ gchar *buff; /* create a new list store */ liststore = gtk_list_store_new(QTH_LIST_COL_NUM, G_TYPE_STRING, // QTH name G_TYPE_STRING, // Location G_TYPE_STRING, // Description G_TYPE_DOUBLE, // Latitude G_TYPE_DOUBLE, // Longitude G_TYPE_INT, // Altitude G_TYPE_STRING, // QRA locator G_TYPE_STRING, // Weather station G_TYPE_BOOLEAN, // Default G_TYPE_INT, //type G_TYPE_STRING, //server G_TYPE_INT //port ); gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(liststore), QTH_LIST_COL_NAME, GTK_SORT_ASCENDING); /* scan for .qth files in the user config directory and add the contents of each .qth file to the list store */ dirname = get_user_conf_dir(); dir = g_dir_open(dirname, 0, &error); if (dir) { while ((filename = g_dir_read_name(dir))) { if (g_str_has_suffix(filename, ".qth")) { buff = g_strconcat(dirname, G_DIR_SEPARATOR_S, filename, NULL); /* read qth file */ if (read_qth_file(liststore, buff)) { /* send debug message */ sat_log_log(SAT_LOG_LEVEL_DEBUG, _("%s:%d: Read QTH data from %s."), __FILE__, __LINE__, filename); } else { /* error reading the file */ sat_log_log(SAT_LOG_LEVEL_ERROR, _("%s:%d: Error reading %s (see prev msg)"), __FILE__, __LINE__, filename); } g_free(buff); } } } else { sat_log_log(SAT_LOG_LEVEL_ERROR, _("%s:%d: Failed to open user cfg dir (%s)"), __FILE__, __LINE__, error->message); g_clear_error(&error); } g_free(dirname); g_dir_close(dir); return GTK_TREE_MODEL(liststore); }
/** \brief Update TLE files from local files. * \param dir Directory where files are located. * \param filter File filter, e.g. *.txt (not used at the moment!) * \param silent TRUE if function should execute without graphical status indicator. * \param label1 Activity label (can be NULL) * \param label2 Statistics label (can be NULL) * \param progress Pointer to progress indicator. * \param init_prgs Initial value of progress indicator, e.g 0.5 if we are updating * from network. * * This function is used to update the TLE data from local files. * * Functional description: TBD * */ void tle_update_from_files (const gchar *dir, const gchar *filter, gboolean silent, GtkWidget *progress, GtkWidget *label1, GtkWidget *label2) { static GMutex tle_file_in_progress; GHashTable *data; /* hash table with fresh TLE data */ GDir *cache_dir; /* directory to scan fresh TLE */ GDir *loc_dir; /* directory for gpredict TLE files */ GError *err = NULL; gchar *text; gchar *ldname; gchar *userconfdir; const gchar *fnam; guint num = 0; guint updated,updated_tmp; guint skipped,skipped_tmp; guint nodata,nodata_tmp; guint newsats = 0; guint total,total_tmp; gdouble fraction = 0.0; gdouble start = 0.0; (void) filter; /* avoid unused parameter compiler warning */ if (g_mutex_trylock(&tle_file_in_progress) == FALSE) { sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s: A TLE update process is already running. Aborting."), __FUNCTION__); return; } /* create hash table */ data = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, free_new_tle); /* open directory and read files one by one */ cache_dir = g_dir_open (dir, 0, &err); if (err != NULL) { /* send an error message */ sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s: Error opening directory %s (%s)"), __FUNCTION__, dir, err->message); /* insert error message into the status string, too */ if (!silent && (label1 != NULL)) { text = g_strdup_printf (_("<b>ERROR</b> opening directory %s\n%s"), dir, err->message); gtk_label_set_markup (GTK_LABEL (label1), text); g_free (text); } g_clear_error (&err); err = NULL; } else { /* scan directory for tle files */ while ((fnam = g_dir_read_name (cache_dir)) != NULL) { /* check that we got a TLE file */ if (is_tle_file(dir, fnam)) { /* status message */ if (!silent && (label1 != NULL)) { text = g_strdup_printf (_("Reading data from %s"), fnam); gtk_label_set_text (GTK_LABEL (label1), text); g_free (text); /* Force the drawing queue to be processed otherwise there will not be any visual feedback, ie. frozen GUI - see Gtk+ FAQ http://www.gtk.org/faq/#AEN602 */ while (g_main_context_iteration (NULL, FALSE)); /* give user a chance to follow progress */ g_usleep (G_USEC_PER_SEC / 100); } /* now, do read the fresh data */ num = read_fresh_tle (dir, fnam, data); } else { num = 0; } if (num < 1) { sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s: No valid TLE data found in %s"), __FUNCTION__, fnam); } else { sat_log_log (SAT_LOG_LEVEL_INFO, _("%s: Read %d sats from %s into memory"), __FUNCTION__, num, fnam); } } /* close directory since we don't need it anymore */ g_dir_close (cache_dir); /* now we load each .sat file and update if we have new data */ userconfdir = get_user_conf_dir (); ldname = g_strconcat (userconfdir, G_DIR_SEPARATOR_S, "satdata", NULL); g_free (userconfdir); /* open directory and read files one by one */ loc_dir = g_dir_open (ldname, 0, &err); if (err != NULL) { /* send an error message */ sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s: Error opening directory %s (%s)"), __FUNCTION__, dir, err->message); /* insert error message into the status string, too */ if (!silent && (label1 != NULL)) { text = g_strdup_printf (_("<b>ERROR</b> opening directory %s\n%s"), dir, err->message); gtk_label_set_markup (GTK_LABEL (label1), text); g_free (text); } g_clear_error (&err); err = NULL; } else { /* clear statistics */ updated = 0; skipped = 0; nodata = 0; total = 0; /* get initial value of progress indicator */ if (progress != NULL) start = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (progress)); /* This is insane but I don't know how else to count the number of sats */ num = 0; while ((fnam = g_dir_read_name (loc_dir)) != NULL) { /* only consider .sat files */ if (g_str_has_suffix (fnam, ".sat")) { num++; } } g_dir_rewind (loc_dir); /* update TLE files one by one */ while ((fnam = g_dir_read_name (loc_dir)) != NULL) { /* only consider .sat files */ if (g_str_has_suffix (fnam, ".sat")) { /* clear stat bufs */ updated_tmp = 0; skipped_tmp = 0; nodata_tmp = 0; total_tmp = 0; /* update TLE data in this file */ update_tle_in_file (ldname, fnam, data, &updated_tmp, &skipped_tmp, &nodata_tmp, &total_tmp); /* update statistics */ updated += updated_tmp; skipped += skipped_tmp; nodata += nodata_tmp; total = updated+skipped+nodata; if (!silent) { if (label1 != NULL) { gtk_label_set_text (GTK_LABEL (label1), _("Updating data...")); } if (label2 != NULL) { text = g_strdup_printf (_("Satellites updated:\t %d\n"\ "Satellites skipped:\t %d\n"\ "Missing Satellites:\t %d\n"), updated, skipped, nodata); gtk_label_set_text (GTK_LABEL (label2), text); g_free (text); } if (progress != NULL) { /* two different calculations for completeness depending on whether we are adding new satellites or not. */ if (sat_cfg_get_bool (SAT_CFG_BOOL_TLE_ADD_NEW)) { /* In this case we are possibly processing more than num satellites How many more? We do not know yet. Worst case is g_hash_table_size more. As we update skipped and updated we can reduce the denominator count as those are in both pools (files and hash table). When we have processed all the files, updated and skipped are completely correct and the progress is correct. It may be correct sooner if the missed satellites are the last files to process. Until then, if we eliminate the ones that are updated and skipped from being double counted, our progress will shown will always be less or equal to our true progress since the denominator will be larger than is correct. Advantages to this are that the progress bar does not stall close to finished when there are a large number of new satellites. */ fraction = start + (1.0-start) * ((gdouble) total) / ((gdouble) num + g_hash_table_size(data) - updated - skipped); } else { /* here we only process satellites we have have files for so divide by num */ fraction = start + (1.0-start) * ((gdouble) total) / ((gdouble) num); } gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progress), fraction); } /* update the gui only every so often to speed up the process */ /* 47 was selected empirically to balance the update looking smooth but not take too much time. */ /* it also tumbles all digits in the numbers so that there is no obvious pattern. */ /* on a developer machine this improved an update from 5 minutes to under 20 seconds. */ if (total%47 == 0) { /* Force the drawing queue to be processed otherwise there will not be any visual feedback, ie. frozen GUI - see Gtk+ FAQ http://www.gtk.org/faq/#AEN602 */ while (g_main_context_iteration (NULL, FALSE)); /* give user a chance to follow progress */ g_usleep (G_USEC_PER_SEC / 1000); } } } } /* force gui update */ while (g_main_context_iteration (NULL, FALSE)); /* close directory handle */ g_dir_close (loc_dir); /* see if we have any new sats that need to be added */ if (sat_cfg_get_bool (SAT_CFG_BOOL_TLE_ADD_NEW)) { newsats = add_new_sats (data); if (!silent && (label2 != NULL)) { text = g_strdup_printf (_("Satellites updated:\t %d\n"\ "Satellites skipped:\t %d\n"\ "Missing Satellites:\t %d\n"\ "New Satellites:\t\t %d"), updated, skipped, nodata, newsats); gtk_label_set_text (GTK_LABEL (label2), text); g_free (text); } sat_log_log (SAT_LOG_LEVEL_INFO, _("%s: Added %d new satellites to local database"), __FUNCTION__, newsats); } /* store time of update if we have updated something */ if ((updated > 0) || (newsats > 0)) { GTimeVal tval; g_get_current_time (&tval); sat_cfg_set_int (SAT_CFG_INT_TLE_LAST_UPDATE, tval.tv_sec); } } g_free (ldname); sat_log_log (SAT_LOG_LEVEL_INFO, _("%s: TLE elements updated."), __FUNCTION__); } /* destroy hash tables */ g_hash_table_destroy (data); g_mutex_unlock(&tle_file_in_progress); }
/** \brief Update TLE files from network. * \param silent TRUE if function should execute without graphical status indicator. * \param progress Pointer to a GtkProgressBar progress indicator (can be NULL) * \param label1 GtkLabel for activity string. * \param label2 GtkLabel for statistics string. */ void tle_update_from_network (gboolean silent, GtkWidget *progress, GtkWidget *label1, GtkWidget *label2) { static GMutex tle_in_progress; gchar *server; gchar *proxy = NULL; gchar *files_tmp; gchar **files; guint numfiles,i; gchar *curfile; gchar *locfile; gchar *userconfdir; CURL *curl; CURLcode res; gdouble fraction,start=0; FILE *outfile; GDir *dir; gchar *cache; const gchar *fname; gchar *text; GError *err = NULL; guint success = 0; /* no. of successfull downloads */ /* bail out if we are already in an update process */ if (g_mutex_trylock(&tle_in_progress) == FALSE) { sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s: A TLE update process is already running. Aborting."), __FUNCTION__); return; } /* get server, proxy, and list of files */ server = sat_cfg_get_str (SAT_CFG_STR_TLE_SERVER); proxy = sat_cfg_get_str (SAT_CFG_STR_TLE_PROXY); files_tmp = sat_cfg_get_str (SAT_CFG_STR_TLE_FILES); files = g_strsplit (files_tmp, ";", 0); numfiles = g_strv_length (files); if (numfiles < 1) { sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s: No files to fetch from network."), __FUNCTION__); /* set activity string, so user knows why nothing happens */ if (!silent && (label1 != NULL)) { gtk_label_set_text (GTK_LABEL (label1), _("No files to fetch from network")); } } else { /* initialise progress bar */ if (!silent && (progress != NULL)) start = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (progress)); /* initialise curl */ curl = curl_easy_init(); if (proxy != NULL) curl_easy_setopt (curl, CURLOPT_PROXY, proxy); curl_easy_setopt (curl, CURLOPT_USERAGENT, "gpredict/curl"); curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, 10); /* get files */ for (i = 0; i < numfiles; i++) { /* set URL */ curfile = g_strconcat (server, files[i], NULL); curl_easy_setopt (curl, CURLOPT_URL, curfile); /* set activity message */ if (!silent && (label1 != NULL)) { text = g_strdup_printf (_("Fetching %s"), files[i]); gtk_label_set_text (GTK_LABEL (label1), text); g_free (text); /* Force the drawing queue to be processed otherwise there will not be any visual feedback, ie. frozen GUI - see Gtk+ FAQ http://www.gtk.org/faq/#AEN602 */ while (g_main_context_iteration (NULL, FALSE)); } /* create local cache file */ userconfdir = get_user_conf_dir (); locfile = g_strconcat (userconfdir, G_DIR_SEPARATOR_S, "satdata", G_DIR_SEPARATOR_S, "cache", G_DIR_SEPARATOR_S, files[i], NULL); outfile = g_fopen (locfile, "wb"); if (outfile != NULL) { curl_easy_setopt (curl, CURLOPT_WRITEDATA, outfile); curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, my_write_func); /* get file */ res = curl_easy_perform (curl); if (res != CURLE_OK) { sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s: Error fetching %s (%s)"), __FUNCTION__, curfile, curl_easy_strerror (res)); } else { sat_log_log (SAT_LOG_LEVEL_INFO, _("%s: Successfully fetched %s"), __FUNCTION__, curfile); success++; } fclose (outfile); } else { sat_log_log (SAT_LOG_LEVEL_INFO, _("%s: Failed to open %s preventing update"), __FUNCTION__, locfile); } /* update progress indicator */ if (!silent && (progress != NULL)) { /* complete download corresponds to 50% */ fraction = start + (0.5-start) * i / (1.0 * numfiles); gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progress), fraction); /* Force the drawing queue to be processed otherwise there will not be any visual feedback, ie. frozen GUI - see Gtk+ FAQ http://www.gtk.org/faq/#AEN602 */ while (g_main_context_iteration (NULL, FALSE)); } g_free (userconfdir); g_free (curfile); g_free (locfile); } curl_easy_cleanup (curl); /* continue update if we have fetched at least one file */ if (success > 0) { sat_log_log (SAT_LOG_LEVEL_INFO, _("%s: Fetched %d files from network; updating..."), __FUNCTION__, success); /* call update_from_files */ cache = sat_file_name ("cache"); tle_update_from_files (cache, NULL, silent, progress, label1, label2); g_free (cache); } else { sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s: Could not fetch any new TLE files from network; aborting..."), __FUNCTION__); } } /* clear cache and memory */ g_free (server); g_strfreev (files); g_free (files_tmp); if (proxy != NULL) g_free (proxy); /* open cache */ cache = sat_file_name ("cache"); dir = g_dir_open (cache, 0, &err); if (err != NULL) { /* send an error message */ sat_log_log (SAT_LOG_LEVEL_ERROR, _("%s: Error opening %s (%s)"), __FUNCTION__, dir, err->message); g_clear_error (&err); } else { /* delete files in cache one by one */ while ((fname = g_dir_read_name (dir)) != NULL) { locfile = g_strconcat (cache, G_DIR_SEPARATOR_S, fname, NULL); g_remove (locfile); g_free (locfile); } /* close cache */ g_dir_close (dir); } g_free (cache); g_mutex_unlock(&tle_in_progress); }
/** * Update TRSP files from network. * * @param silent TRUE if function should execute without graphical status indicator. * @param progress Pointer to a GtkProgressBar progress indicator (can be NULL) * @param label1 GtkLabel for activity string. * @param label2 GtkLabel for statistics string. */ void trsp_update_from_network(gboolean silent, GtkWidget * progress, GtkWidget * label1, GtkWidget * label2) { static GMutex trsp_in_progress; gchar *server; gchar *proxy = NULL; gchar *freq_file; gchar *file_url; gchar *locfile_trsp; gchar *userconfdir; CURL *curl; CURLcode res; gdouble fraction; FILE *outfile; gchar *cache; gchar *text; guint success = 0; /* no. of successfull downloads */ /* bail out if we are already in an update process */ if (g_mutex_trylock(&trsp_in_progress) == FALSE) { sat_log_log(SAT_LOG_LEVEL_ERROR, _("%s: A frequency update process is already running"), __func__); return; } /* get list with modes */ modes_update_from_network(); /* get server, proxy, and list of files */ //server = sprintf("%stransmitters/?format=json", sat_cfg_get_str(SAT_CFG_STR_TRSP_SERVER)); server = sat_cfg_get_str(SAT_CFG_STR_TRSP_SERVER); proxy = sat_cfg_get_str(SAT_CFG_STR_TRSP_PROXY); freq_file = sat_cfg_get_str(SAT_CFG_STR_TRSP_FREQ_FILE); /* initialise curl */ curl = curl_easy_init(); if (proxy != NULL) curl_easy_setopt(curl, CURLOPT_PROXY, proxy); curl_easy_setopt(curl, CURLOPT_USERAGENT, "gpredict/curl"); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10); /* get files */ /* set URL */ file_url = g_strconcat(server, freq_file, NULL); curl_easy_setopt(curl, CURLOPT_URL, file_url); sat_log_log(SAT_LOG_LEVEL_INFO, _("%s: Ready to fetch transponder list from %s"), __func__, file_url); /* set activity message */ if (!silent && (label1 != NULL)) { text = g_strdup_printf(_("Fetching %s"), "transmitters.json"); gtk_label_set_text(GTK_LABEL(label1), text); g_free(text); /* Force the drawing queue to be processed otherwise there will not be any visual feedback, ie. frozen GUI - see Gtk+ FAQ http://www.gtk.org/faq/#AEN602 */ while (g_main_context_iteration(NULL, FALSE)); } /* create local cache file */ userconfdir = get_user_conf_dir(); locfile_trsp = g_strconcat(userconfdir, G_DIR_SEPARATOR_S, "trsp", G_DIR_SEPARATOR_S, "transmitters.json", NULL); sat_log_log(SAT_LOG_LEVEL_INFO, _("%s: File to open %s "), __func__, locfile_trsp); outfile = g_fopen(locfile_trsp, "wb"); if (outfile != NULL) { curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_func); /* get file */ res = curl_easy_perform(curl); if (res != CURLE_OK) { sat_log_log(SAT_LOG_LEVEL_ERROR, _("%s: Error fetching %s (%s)"), __func__, file_url, curl_easy_strerror(res)); } else { sat_log_log(SAT_LOG_LEVEL_INFO, _("%s: Successfully fetched %s"), __func__, file_url); success++; } fclose(outfile); } else { sat_log_log(SAT_LOG_LEVEL_INFO, _("%s: Failed to open %s preventing update"), __func__, locfile_trsp); } /* update progress indicator */ if (!silent && (progress != NULL)) { /* complete download corresponds to 50% */ fraction = 1; gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), fraction); /* Force the drawing queue to be processed otherwise there will not be any visual feedback, ie. frozen GUI - see Gtk+ FAQ http://www.gtk.org/faq/#AEN602 */ while (g_main_context_iteration(NULL, FALSE)); } g_free(userconfdir); g_free(file_url); g_free(server); g_free(freq_file); g_free(proxy); curl_easy_cleanup(curl); /* continue update if we have fetched at least one file */ if (success > 0) { sat_log_log(SAT_LOG_LEVEL_INFO, _("%s: Fetched %d files from network; updating..."), __func__, success); /* call update_from_files */ cache = sat_file_name("cache"); trsp_update_files(locfile_trsp); g_free(cache); } else { sat_log_log(SAT_LOG_LEVEL_ERROR, _("%s: Could not fetch frequency files from network"), __func__); } g_mutex_unlock(&trsp_in_progress); }
/** Update MODES files from network. */ void modes_update_from_network() { gchar *server; gchar *proxy = NULL; gchar *modes_file; gchar *file_url; gchar *locfile; gchar *userconfdir; CURL *curl; CURLcode res; FILE *outfile; guint success = 0; /* no. of successfull downloads */ server = sat_cfg_get_str(SAT_CFG_STR_TRSP_SERVER); proxy = sat_cfg_get_str(SAT_CFG_STR_TRSP_PROXY); modes_file = sat_cfg_get_str(SAT_CFG_STR_TRSP_MODE_FILE); /* initialise curl */ curl = curl_easy_init(); if (proxy != NULL) curl_easy_setopt(curl, CURLOPT_PROXY, proxy); curl_easy_setopt(curl, CURLOPT_USERAGENT, "gpredict/curl"); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10); /* get files */ /* set URL */ file_url = g_strconcat(server, modes_file, NULL); curl_easy_setopt(curl, CURLOPT_URL, file_url); sat_log_log(SAT_LOG_LEVEL_INFO, _("%s: Ready to fetch modes list from %s"), __func__, file_url); /* create local cache file */ userconfdir = get_user_conf_dir(); locfile = g_strconcat(userconfdir, G_DIR_SEPARATOR_S, "trsp", G_DIR_SEPARATOR_S, "modes.json", NULL); sat_log_log(SAT_LOG_LEVEL_INFO, _("%s: File to open %s "), __func__, locfile); outfile = g_fopen(locfile, "wb"); if (outfile != NULL) { curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_func); /* get file */ res = curl_easy_perform(curl); if (res != CURLE_OK) { sat_log_log(SAT_LOG_LEVEL_ERROR, _("%s: Error fetching %s (%s)"), __func__, file_url, curl_easy_strerror(res)); } else { sat_log_log(SAT_LOG_LEVEL_INFO, _("%s: Successfully fetched %s"), __func__, file_url); success++; } fclose(outfile); } else { sat_log_log(SAT_LOG_LEVEL_INFO, _("%s: Failed to open %s preventing update"), __func__, locfile); } g_free(userconfdir); g_free(file_url); g_free(server); g_free(proxy); g_free(modes_file); curl_easy_cleanup(curl); /* continue update if we have fetched at least one file */ if (success > 0) { sat_log_log(SAT_LOG_LEVEL_INFO, _("%s: Fetched %d files from network; updating..."), __func__, success); //here we can get the modes json file into memory as hashmap.. //g_free(cache); } else { sat_log_log(SAT_LOG_LEVEL_ERROR, _("%s: Could not fetch frequency files from network"), __func__); } }
void trsp_update_files(gchar * input_file) { FILE *mfp; /* transmitter information json file */ unsigned int mfplen; /* size of transmitter information json file */ int result; FILE *ffile; /* transponder output file in gpredict format */ char *jsn_object; /* json array will be in this buffer before parsing */ unsigned int idx; /* object index in JSON-Array */ new_mode_t *nmode; new_trsp_t *ntrsp; GHashTable *modes_hash; /* hash table to store modes */ GHashTable *trsp_hash; /* hash table to store satellite list to generate trsp files */ guint *key = NULL; gchar *userconfdir; gchar *trspfile; gchar *modesfile; gchar *trspfolder; /* force decimal mark to dot when parsing JSON file */ setlocale(LC_NUMERIC, "C"); modes_hash = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, free_new_mode); trsp_hash = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, free_new_trsp); userconfdir = get_user_conf_dir(); trspfolder = g_strconcat(userconfdir, G_DIR_SEPARATOR_S, "trsp", NULL); modesfile = g_strconcat(trspfolder, "/modes.json", NULL); mfp = fopen(modesfile, "r"); if (mfp != NULL) { mfplen = 0; fseek(mfp, 0, SEEK_END); mfplen = ftell(mfp); rewind(mfp); jsn_object = g_malloc(mfplen); result = fread(jsn_object, mfplen, 1, mfp); if (result == 1) { const nx_json *json = nx_json_parse(jsn_object, 0); if (json) { idx = 0; while (1) { const nx_json *json_obj = nx_json_item(json, idx++); struct modes m_modes; if (json_obj->type == NX_JSON_NULL) break; m_modes.id = nx_json_get(json_obj, "id")->int_value; strncpy(m_modes.name, nx_json_get(json_obj, "name")->text_value, 79); m_modes.name[79] = 0; /* add data to hash table */ key = g_try_new0(guint, 1); *key = m_modes.id; nmode = g_hash_table_lookup(modes_hash, key); if (nmode == NULL) { /* create new_mode structure */ nmode = g_try_new(new_mode_t, 1); nmode->modnum = m_modes.id; nmode->modname = g_strdup(m_modes.name); g_hash_table_insert(modes_hash, key, nmode); } sat_log_log(SAT_LOG_LEVEL_INFO, _("MODE %d %s"), m_modes.id, m_modes.name); } // while(1) nx_json_free(json); } // if(json) } // if(result == 1) g_free(jsn_object); fclose(mfp); } // if(mfp) // guint num = 0; // printf("---------- PRINTING MODES LIST ------- \n"); // g_hash_table_foreach (modes_hash, check_and_print_mode, &num); mfp = fopen(input_file, "r"); if (mfp != NULL) { mfplen = 0; fseek(mfp, 0, SEEK_END); mfplen = ftell(mfp); rewind(mfp); jsn_object = g_malloc(mfplen); result = fread(jsn_object, mfplen, 1, mfp); if (result == 1) { const nx_json *json = nx_json_parse(jsn_object, 0); if (json) { idx = 0; while (1) { const nx_json *json_obj = nx_json_item(json, idx++); struct transponder m_trsp; if (json_obj->type == NX_JSON_NULL) break; strncpy(m_trsp.description, nx_json_get(json_obj, "description")->text_value, 79); m_trsp.description[79] = 0; m_trsp.catnum = nx_json_get(json_obj, "norad_cat_id")->int_value; m_trsp.uplink_low = nx_json_get(json_obj, "uplink_low")->int_value; m_trsp.uplink_high = nx_json_get(json_obj, "uplink_high")->int_value; m_trsp.downlink_low = nx_json_get(json_obj, "downlink_low")->int_value; m_trsp.downlink_high = nx_json_get(json_obj, "downlink_high")->int_value; key = g_try_new0(guint, 1); *key = nx_json_get(json_obj, "mode_id")->int_value; nmode = g_hash_table_lookup(modes_hash, key); if (nmode != NULL) sprintf(m_trsp.mode, "%s", nmode->modname); else sprintf(m_trsp.mode, "%lli", nx_json_get(json_obj, "mode_id")->int_value); m_trsp.invert = nx_json_get(json_obj, "invert")->int_value; m_trsp.baud = nx_json_get(json_obj, "baud")->dbl_value; m_trsp.alive = nx_json_get(json_obj, "alive")->int_value; //strcpy(m_trsp.uuid,nx_json_get(json_obj, "uuid")->text_value); //sat_log_log(SAT_LOG_LEVEL_DEBUG, _(">>> Preparing information for transponders of cat_id %d <<<"), m_trsp.catnum, __func__); ////sat_log_log (SAT_LOG_LEVEL_INFO, _(" uuid : %s"), m_trsp.uuid, __func__); //sat_log_log(SAT_LOG_LEVEL_DEBUG, _(" description : %s"), m_trsp.description, __func__); //sat_log_log(SAT_LOG_LEVEL_DEBUG, _(" alive : %s"), m_trsp.alive ? "true" : "false", __func__); //sat_log_log(SAT_LOG_LEVEL_DEBUG, _(" uplink_low : %Ld"),m_trsp.uplink_low, __func__); //sat_log_log(SAT_LOG_LEVEL_DEBUG, _(" uplink_high : %Ld"),m_trsp.uplink_high, __func__); //sat_log_log(SAT_LOG_LEVEL_DEBUG, _(" downink_low : %Ld"),m_trsp.downlink_low, __func__); //sat_log_log(SAT_LOG_LEVEL_DEBUG, _("downlink_high : %Ld"),m_trsp.downlink_high, __func__); //sat_log_log(SAT_LOG_LEVEL_DEBUG, _(" Mode : %s"), m_trsp.mode, __func__); //sat_log_log(SAT_LOG_LEVEL_DEBUG, _(" Invert : %s"), m_trsp.invert ? "true" : "false", __func__); // sat_log_log(SAT_LOG_LEVEL_DEBUG, _(" Baud : %lf"),m_trsp.baud, __func__); //sat_log_log(SAT_LOG_LEVEL_DEBUG, _(" norad_cat_id : %Ld"),m_trsp.catnum, __func__); char m_catnum[20]; sprintf(m_catnum, "%d", m_trsp.catnum); trspfile = g_strconcat(trspfolder, G_DIR_SEPARATOR_S, m_catnum, ".trsp", NULL); //sat_log_log(SAT_LOG_LEVEL_DEBUG, _("%s: Writing to file : %s "), __func__, trspfile); //first lets delete the file we already have, to make space for the new version /* check existence and add data to hash table for future check */ key = g_try_new0(guint, 1); *key = m_trsp.catnum; ntrsp = g_hash_table_lookup(trsp_hash, key); if (ntrsp == NULL) { /* create new_trsp structure */ ntrsp = g_try_new(new_trsp_t, 1); ntrsp->catnum = m_trsp.catnum; ntrsp->numtrsp = 1; //our first insertion of transponder to this file g_hash_table_insert(trsp_hash, key, ntrsp); g_remove(trspfile); } else { //TODO: increase number of transponders here //ntrsp->numtrsp += 1; //number of transponder info in this file //g_hash_table_replace(trsp_hash, key, ntrsp); } //now lets write the new version ffile = g_fopen(trspfile, "a"); if (ffile != NULL) { fprintf(ffile, "\n[%s]\n", m_trsp.description); if (m_trsp.uplink_low > 0) fprintf(ffile, "UP_LOW=%lld\n", m_trsp.uplink_low); if (m_trsp.uplink_high > 0) fprintf(ffile, "UP_HIGH=%lld\n", m_trsp.uplink_high); if (m_trsp.downlink_low > 0) fprintf(ffile, "DOWN_LOW=%lld\n", m_trsp.downlink_low); if (m_trsp.downlink_high > 0) fprintf(ffile, "DOWN_HIGH=%lld\n", m_trsp.downlink_high); fprintf(ffile, "MODE=%s\n", m_trsp.mode); if (m_trsp.baud > 0.0) fprintf(ffile, "BAUD=%.0f\n", m_trsp.baud); if (m_trsp.invert) fprintf(ffile, "INVERT=%s\n", "true"); fclose(ffile); } else { sat_log_log(SAT_LOG_LEVEL_ERROR, _ ("%s: Could not open trsp file for write"), __func__); } } // while(1) nx_json_free(json); } // if(json) } // if(result == 1) g_free(jsn_object); fclose(mfp); } // if(mfp) g_hash_table_destroy(modes_hash); }
GtkWidget *sat_pref_debug_create() { GtkWidget *vbox; /* vbox containing the list part and the details part */ GtkWidget *hbox; GtkWidget *rbut; GtkWidget *label; GtkWidget *butbox; gchar *msg; gchar *confdir; vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); gtk_box_set_homogeneous(GTK_BOX(vbox), FALSE); gtk_container_set_border_width(GTK_CONTAINER(vbox), 20); gtk_box_set_spacing(GTK_BOX(vbox), 10); /* debug level */ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10); gtk_box_set_homogeneous(GTK_BOX(hbox), FALSE); label = gtk_label_new(_("Debug level:")); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); level = gtk_combo_box_text_new(); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(level), _("Level 0: None")); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(level), _("Level 1: Error")); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(level), _("Level 2: Warning")); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(level), _("Level 3: Info")); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(level), _("Level 4: Debug")); gtk_combo_box_set_active(GTK_COMBO_BOX(level), sat_cfg_get_int(SAT_CFG_INT_LOG_LEVEL)); g_signal_connect(G_OBJECT(level), "realize", G_CALLBACK(gpredict_set_combo_tooltips), _("Select the debug level. The higher the level, " "the more messages will be logged.")); g_signal_connect(G_OBJECT(level), "changed", G_CALLBACK(state_change_cb), NULL); gtk_box_pack_start(GTK_BOX(hbox), level, FALSE, FALSE, 10); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); /* clean frequency */ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10); gtk_box_set_homogeneous(GTK_BOX(hbox), FALSE); label = gtk_label_new(_("Delete log files older than:")); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); age = gtk_combo_box_text_new(); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(age), _("Always delete")); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(age), _("1 day")); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(age), _("1 week")); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(age), _("1 month")); select_age(); g_signal_connect(G_OBJECT(age), "realize", G_CALLBACK(gpredict_set_combo_tooltips), _("Select how often gpredict should delete " "old log files.")); g_signal_connect(G_OBJECT(age), "changed", G_CALLBACK(state_change_cb), NULL); gtk_box_pack_start(GTK_BOX(hbox), age, FALSE, FALSE, 10); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); /* separator */ gtk_box_pack_start(GTK_BOX(vbox), gtk_separator_new(GTK_ORIENTATION_HORIZONTAL), FALSE, FALSE, 0); /* info label */ confdir = get_user_conf_dir(); msg = g_strdup_printf(_ ("Gpredict stores all run-time messages in the %s%slogs%s\n" "directory. The current log file is called gpredict.log and the file is\n" "always kept until the next execution, so that you can examine it in case\n" "of a failure. If old log files are kept, they are called gpredict-XYZ.log\n" "where XYZ is a unique timestamp."), confdir, G_DIR_SEPARATOR_S, G_DIR_SEPARATOR_S); label = gtk_label_new(msg); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); g_free(msg); /* reset button */ rbut = gtk_button_new_with_label(_("Reset")); gtk_widget_set_tooltip_text(rbut, _("Reset settings to the default values.")); g_signal_connect(G_OBJECT(rbut), "clicked", G_CALLBACK(reset_cb), NULL); butbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL); gtk_button_box_set_layout(GTK_BUTTON_BOX(butbox), GTK_BUTTONBOX_END); gtk_box_pack_end(GTK_BOX(butbox), rbut, FALSE, TRUE, 10); gtk_box_pack_end(GTK_BOX(vbox), butbox, FALSE, TRUE, 0); return vbox; }