mirror of
https://github.com/wavelog/wavelog.git
synced 2026-03-22 02:14:13 +00:00
New model: HAMqsl data with solar activity and propagation. User can display brief information of the solar activity at the Dashboard. Model can be re-used in various other places.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
125
application/models/Hamqsl_model.php
Normal file
125
application/models/Hamqsl_model.php
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
class Hamqsl_model extends CI_Model {
|
||||
public $solarData = null;
|
||||
|
||||
function set_solardata() {
|
||||
// Reads solar data from local XML file and sets $this->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 <solardata> node (handle both root and nested)
|
||||
$solardata = isset($this->solarData->solardata) ? $this->solarData->solardata : $this->solarData;
|
||||
|
||||
// Convert the entire <solardata> 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
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -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,
|
||||
|
||||
@@ -456,6 +456,76 @@ function getDistance($distance) {
|
||||
|
||||
</table>
|
||||
<?php } ?>
|
||||
|
||||
<?php if($solar_bandconditions && $solar_solardata){ ?>
|
||||
<!-- Solar Data -->
|
||||
<table class="table table-striped border-top">
|
||||
<tr class="titles">
|
||||
<td colspan="10"><i class="fas fa-sun"></i> <?= __("Solar Data & Propagation"); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="10">
|
||||
<table class="table table-sm small text-center table-striped">
|
||||
<tr>
|
||||
<th width="20%"> </th>
|
||||
<th width="20%">80m-40m</th>
|
||||
<th width="20%">30m-20m</th>
|
||||
<th width="20%">17m-15m</th>
|
||||
<th width="20%">12m-10m</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Day</td>
|
||||
<td><?= $solar_bandconditions['80m-40m']['day'] ?></td>
|
||||
<td><?= $solar_bandconditions['30m-20m']['day'] ?></td>
|
||||
<td><?= $solar_bandconditions['17m-15m']['day'] ?></td>
|
||||
<td><?= $solar_bandconditions['12m-10m']['day'] ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Night</td>
|
||||
<td><?= $solar_bandconditions['80m-40m']['night'] ?></td>
|
||||
<td><?= $solar_bandconditions['30m-20m']['night'] ?></td>
|
||||
<td><?= $solar_bandconditions['17m-15m']['night'] ?></td>
|
||||
<td><?= $solar_bandconditions['12m-10m']['night'] ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="10">
|
||||
<table class="table table-sm small text-center table-striped">
|
||||
<tr>
|
||||
<th width="5%">Kp</th>
|
||||
<th width="5%">A</th>
|
||||
<th width="15%">SFI</th>
|
||||
<th width="15%">SW</th>
|
||||
<th width="15%">SS</th>
|
||||
<th width="15%">X</th>
|
||||
<th width="20%">Noise</th>
|
||||
<th width="20%">Aurora</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><?= $solar_solardata['kindex'] ?></td>
|
||||
<td><?= $solar_solardata['aindex'] ?></td>
|
||||
<td><?= $solar_solardata['solarflux'] ?></td>
|
||||
<td><?= $solar_solardata['solarwind'] ?></td>
|
||||
<td><?= $solar_solardata['signalnoise'] ?></td>
|
||||
<td><?= $solar_solardata['xray'] ?></td>
|
||||
<td><?= $solar_solardata['sunspots'] ?></td>
|
||||
<td><?= $solar_solardata['aurora'] ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="10" class="small">
|
||||
<?= sprintf(__("Data provided by %s."), '<a target="_blank" class="text-primary fw-bold text-decoration-underline" href="https://www.hamqsl.com/">'.'HAMqsl'.'</a>'); ?>
|
||||
<?= sprintf(__("Last update at %s."), $solar_solardata['updated']); ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -636,6 +636,16 @@
|
||||
</select>
|
||||
<small id="user_dashboard_banner_Help" class="form-text text-muted"><?= __("This allows to disable the global notification banner on the dashboard."); ?></small>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="user_dashboard_solar"><?= __("Dashboard solar and propagation data"); ?></label>
|
||||
<?php if(!isset($user_dashboard_solar)) { $user_dashboard_solar='Y'; }?>
|
||||
<select class="form-select" id="user_dashboard_solar" name="user_dashboard_solar" aria-describedby="user_dashboard_solar_Help" required>
|
||||
<option value='true' <?php if($user_dashboard_solar == "true") { echo "selected=\"selected\""; } ?>><?= __("Enabled"); ?></option>
|
||||
<option value='false' <?php if($user_dashboard_solar == "false") { echo "selected=\"selected\""; } ?>><?= __("Disabled"); ?></option>
|
||||
</select>
|
||||
<small id="user_dashboard_solar_Help" class="form-text text-muted"><?= __("This switches the display of the solar and propagation data on the dashboard."); ?></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user