diff --git a/application/controllers/Dashboard.php b/application/controllers/Dashboard.php index 87c989ab8..a64e7ebc2 100644 --- a/application/controllers/Dashboard.php +++ b/application/controllers/Dashboard.php @@ -79,6 +79,14 @@ class Dashboard extends CI_Controller { $data['dashboard_banner'] = 'N'; } + // Check user preferrence to show Solar Data on Dashboard + // Default to not show + if (($this->session->userdata('user_dashboard_solar') ?? '') != '') { + $data['dashboard_solar'] = $this->session->userdata('user_dashboard_solar') ?? 'Y'; + } else { + $data['dashboard_solar'] = 'N'; + } + $data['user_map_custom'] = $this->optionslib->get_map_custom(); $this->load->model('cat'); @@ -179,6 +187,23 @@ class Dashboard extends CI_Controller { $data['total_countries_needed'] = count($dxcc->result()) - $current; + // Check user preferrence to show Solar Data on Dashboard and load data if yes + // Default to not show + if($data['dashboard_solar'] == 'true') { + $this->load->model('Hamqsl_model'); // Load HAMQSL model + + if (!$this->Hamqsl_model->set_solardata()) { + // Problem getting data, set to null + $data['solar_bandconditions'] = null; + $data['solar_solardata'] = null; + } else { + // Load data into arrays + $data['solar_bandconditions'] = $this->Hamqsl_model->get_bandconditions_array(); + $data['solar_solardata'] = $this->Hamqsl_model->get_solarinformation_array(); + } + } + + // Load the views $this->load->view('interface_assets/header', $data); $this->load->view('dashboard/index'); $this->load->view('interface_assets/footer', $footerData); diff --git a/application/controllers/User.php b/application/controllers/User.php index 736b149b9..4d79426ba 100644 --- a/application/controllers/User.php +++ b/application/controllers/User.php @@ -206,6 +206,7 @@ class User extends CI_Controller { $data['user_measurement_base'] = $this->input->post('user_measurement_base') ?? 'K'; $data['user_dashboard_map'] = $this->input->post('user_dashboard_map') ?? 'Y'; $data['user_dashboard_banner'] = $this->input->post('user_dashboard_banner') ?? 'Y'; + $data['user_dashboard_solar'] = $this->input->post('user_dashboard_solar') ?? 'Y'; $data['user_stylesheet'] = $this->input->post('user_stylesheet'); $data['user_qth_lookup'] = $this->input->post('user_qth_lookup'); $data['user_sota_lookup'] = $this->input->post('user_sota_lookup'); @@ -299,6 +300,7 @@ class User extends CI_Controller { $this->input->post('on_air_widget_show_only_most_recent_radio'), $this->input->post('qso_widget_display_qso_time'), $this->input->post('user_dashboard_banner') ?? 'Y', + $this->input->post('user_dashboard_solar') ?? 'Y', $this->input->post('clubstation') == '1' ? true : false, $this->input->post('global_oqrs_text') ?? '', $this->input->post('oqrs_grouped_search') ?? 'off', @@ -336,6 +338,7 @@ class User extends CI_Controller { $data['user_measurement_base'] = $this->input->post('user_measurement_base'); $data['user_dashboard_map'] = $this->input->post('user_dashboard_map') ?? 'Y'; $data['user_dashboard_banner'] = $this->input->post('user_dashboard_banner') ?? 'Y'; + $data['user_dashboard_solar'] = $this->input->post('user_dashboard_solar') ?? 'Y'; $data['user_stylesheet'] = $this->input->post('user_stylesheet'); $data['user_qth_lookup'] = $this->input->post('user_qth_lookup'); $data['user_sota_lookup'] = $this->input->post('user_sota_lookup'); @@ -717,6 +720,16 @@ class User extends CI_Controller { } } + // Dashboard solar data information widget + if($this->input->post('user_dashboard_solar')) { + $data['user_dashboard_solar'] = $this->input->post('user_dashboard_solar', false); + } else { + $dkey_opt=$this->user_options_model->get_options('dashboard',array('option_name'=>'show_dashboard_solar','option_key'=>'boolean'), $this->uri->segment(3))->result(); + if (count($dkey_opt)>0) { + $data['user_dashboard_solar'] = $dkey_opt[0]->option_value; + } + } + if($this->input->post('user_hamsat_workable_only')) { $data['user_hamsat_workable_only'] = $this->input->post('user_hamsat_workable_only', false); } else { diff --git a/application/models/Hamqsl_model.php b/application/models/Hamqsl_model.php new file mode 100644 index 000000000..d29600716 --- /dev/null +++ b/application/models/Hamqsl_model.php @@ -0,0 +1,125 @@ +solarData + // Returns true if data was read, false if not + // The XML file shall be updated every 60 minutes by a cron job + $xmlData = null; + + if (file_exists("./updates/solarxml.xml")) { + + $xmlstr = file_get_contents("./updates/solarxml.xml"); + + if ($xmlstr !== false) { + try { + $xmlData = new SimpleXMLElement($xmlstr); + } catch (Exception $e) { + // Do nothing + } + } + } + + if($xmlData) { + $this->solarData = $xmlData; + return true; + } else { + $this->solarData = null; + return false; + } + } + + function get_bandconditions(string $name, string $time) { + // Returns the band condition for a given band name and time of day from the provided XML root + // If the data is not available, returns null + // Example: get_band_condition('80m-40m', 'day') + // Returns: 'Good', 'Fair', 'Poor', or null if not found + + if (!$this->solarData) { + if (!$this->set_solardata()) { + return null; // Unable to load data + } + } + + // Properly escape values for XPath + $escapeForXPath = function($value) { + if (strpos($value, "'") === false) { + return "'$value'"; + } elseif (strpos($value, '"') === false) { + return "\"$value\""; + } else { + return "concat('" . str_replace("'", "',\"'\",'", $value) . "')"; + } + }; + $nameEscaped = $escapeForXPath($name); + $timeEscaped = $escapeForXPath($time); + $xpathQuery = "/solardata/calculatedconditions/band[@name=$nameEscaped and @time=$timeEscaped]"; + $result = $this->solarData->xpath($xpathQuery); + + if ($result && count($result) > 0) { + return trim((string)$result[0]); + } else { + return null; // Not found + } + } + + function get_bandconditions_array() { + // Returns an associative array of all band conditions from the XML data + // The array structure is: [band_name][time_of_day] = condition + // Example: $conditions['80m-40m']['day'] = 'Good' + // Returns null if data is not available + + if (!$this->solarData) { + if (!$this->set_solardata()) { + return null; // Unable to load data + } + } + + $conditions = []; + if (isset($this->solarData->solardata->calculatedconditions->band)) { + foreach ($this->solarData->solardata->calculatedconditions->band as $band) { + $name = (string)$band['name']; + $time = (string)$band['time']; + $condition = trim((string)$band); + if (!isset($conditions[$name])) { + $conditions[$name] = []; + } + $conditions[$name][$time] = $condition; + } + } + return $conditions; // Return the associative array + } + + function get_solarinformation_array() { + // Returns an associative array of all information from the XML data, + // including band conditions, without filtering anything out. + // The 'updated' field is converted to "d M H:i \G\M\T" format. + // Returns null if data is not available. + + if (!$this->solarData) { + if (!$this->set_solardata()) { + return null; // Unable to load data + } + } + + // Find the node (handle both root and nested) + $solardata = isset($this->solarData->solardata) ? $this->solarData->solardata : $this->solarData; + + // Convert the entire node to an associative array + $solarinformation = json_decode(json_encode($solardata), true); + + // Format the 'updated' field if it exists + if (isset($solarinformation['updated'])) { + $timestamp = strtotime($solarinformation['updated']); + if ($timestamp !== false) { + $solarinformation['updated'] = gmdate('d M H:i \G\M\T', $timestamp); + } + } + + return $solarinformation; // Return the associative array + } +} + +?> diff --git a/application/models/User_model.php b/application/models/User_model.php index 4bad6c5cb..99ea168e2 100644 --- a/application/models/User_model.php +++ b/application/models/User_model.php @@ -224,7 +224,7 @@ class User_Model extends CI_Model { $user_wwff_to_qso_tab, $user_pota_to_qso_tab, $user_sig_to_qso_tab, $user_dok_to_qso_tab, $user_lotw_name, $user_lotw_password, $user_eqsl_name, $user_eqsl_password, $user_clublog_name, $user_clublog_password, $user_winkey, $on_air_widget_enabled, $on_air_widget_display_last_seen, $on_air_widget_show_only_most_recent_radio, - $qso_widget_display_qso_time, $dashboard_banner, $clubstation = 0) { + $qso_widget_display_qso_time, $dashboard_banner,$dashboard_solar, $clubstation = 0) { // Check that the user isn't already used if(!$this->exists($username)) { $data = array( @@ -308,6 +308,7 @@ class User_Model extends CI_Model { $this->db->query("insert into user_options (user_id, option_type, option_name, option_key, option_value) values (" . $insert_id . ", 'qso_tab','dok','show',".(xss_clean($user_dok_to_qso_tab ?? 'off') == "on" ? 1 : 0).");"); $this->db->query("insert into user_options (user_id, option_type, option_name, option_key, option_value) values (" . $insert_id . ", 'dashboard','show_map','boolean','".xss_clean($dashboard_map ?? 'Y')."');"); $this->db->query("insert into user_options (user_id, option_type, option_name, option_key, option_value) values (" . $insert_id . ", 'dashboard','show_dashboard_banner','boolean','".xss_clean($dashboard_banner ?? 'Y')."');"); + $this->db->query("insert into user_options (user_id, option_type, option_name, option_key, option_value) values (" . $insert_id . ", 'dashboard','show_dashboard_solar','boolean','".xss_clean($dashboard_solar ?? 'Y')."');"); $this->db->query("insert into user_options (user_id, option_type, option_name, option_key, option_value) values (" . $insert_id . ", 'widget','on_air','enabled','".(xss_clean($on_air_widget_enabled ?? 'false'))."');"); $this->db->query("insert into user_options (user_id, option_type, option_name, option_key, option_value) values (" . $insert_id . ", 'widget','on_air','display_last_seen','".(xss_clean($on_air_widget_display_last_seen ?? 'false'))."');"); $this->db->query("insert into user_options (user_id, option_type, option_name, option_key, option_value) values (" . $insert_id . ", 'widget','on_air','display_only_most_recent_radio','".(xss_clean($on_air_widget_show_only_most_recent_radio ?? 'true'))."');"); @@ -385,10 +386,12 @@ class User_Model extends CI_Model { $this->db->query("replace into user_options (user_id, option_type, option_name, option_key, option_value) values (" . $fields['id'] . ", 'qso_tab','last_qso_count','count','".$qso_page_last_qso_count."');"); $this->db->query("replace into user_options (user_id, option_type, option_name, option_key, option_value) values (" . $fields['id'] . ", 'dashboard','show_map','boolean','".xss_clean($fields['user_dashboard_map'] ?? 'Y')."');"); $this->db->query("replace into user_options (user_id, option_type, option_name, option_key, option_value) values (" . $fields['id'] . ", 'dashboard','show_dashboard_banner','boolean','".xss_clean($fields['user_dashboard_banner'] ?? 'Y')."');"); + $this->db->query("replace into user_options (user_id, option_type, option_name, option_key, option_value) values (" . $fields['id'] . ", 'dashboard','show_dashboard_solar','boolean','".xss_clean($fields['user_dashboard_solar'] ?? 'Y')."');"); $this->session->set_userdata('dashboard_last_qso_count', $dashboard_last_qso_count); $this->session->set_userdata('qso_page_last_qso_count', $qso_page_last_qso_count); $this->session->set_userdata('user_dashboard_map',xss_clean($fields['user_dashboard_map'] ?? 'Y')); $this->session->set_userdata('user_dashboard_banner',xss_clean($fields['user_dashboard_banner'] ?? 'Y')); + $this->session->set_userdata('user_dashboard_solar',xss_clean($fields['user_dashboard_solar'] ?? 'Y')); // Check to see if the user is allowed to change user levels if($this->session->userdata('user_type') == 99) { @@ -547,6 +550,7 @@ class User_Model extends CI_Model { 'user_measurement_base' => $u->row()->user_measurement_base, 'user_dashboard_map' => ((($this->session->userdata('user_dashboard_map') ?? 'Y') == 'Y') ? $this->user_options_model->get_options('dashboard', array('option_name' => 'show_map', 'option_key' => 'boolean'))->row()->option_value ?? 'Y' : $this->session->userdata('user_dashboard_map')), 'user_dashboard_banner' => ((($this->session->userdata('user_dashboard_banner') ?? 'Y') == 'Y') ? $this->user_options_model->get_options('dashboard', array('option_name' => 'show_dashboard_banner', 'option_key' => 'boolean'))->row()->option_value ?? 'Y' : $this->session->userdata('user_dashboard_banner')), + 'user_dashboard_solar' => ((($this->session->userdata('user_dashboard_solar') ?? 'Y') == 'Y') ? $this->user_options_model->get_options('dashboard', array('option_name' => 'show_dashboard_solar', 'option_key' => 'boolean'))->row()->option_value ?? 'Y' : $this->session->userdata('user_dashboard_solar')), 'user_date_format' => $u->row()->user_date_format, 'user_stylesheet' => $u->row()->user_stylesheet, 'user_qth_lookup' => isset($u->row()->user_qth_lookup) ? $u->row()->user_qth_lookup : 0, diff --git a/application/views/dashboard/index.php b/application/views/dashboard/index.php index 1f8a4c721..cfa59477c 100644 --- a/application/views/dashboard/index.php +++ b/application/views/dashboard/index.php @@ -456,6 +456,76 @@ function getDistance($distance) { + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
 80m-40m30m-20m17m-15m12m-10m
Day
Night
+
+ + + + + + + + + + + + + + + + + + + + + +
KpASFISWSSXNoiseAurora
+
+ '.'HAMqsl'.''); ?> + +
+ + + diff --git a/application/views/user/edit.php b/application/views/user/edit.php index d74395d11..60b7439d4 100644 --- a/application/views/user/edit.php +++ b/application/views/user/edit.php @@ -636,6 +636,16 @@ + +
+ + + + +