rot finished
This commit is contained in:
96
internal/services/solar/solar.go
Normal file
96
internal/services/solar/solar.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package solar
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// SolarData contains current solar and geomagnetic conditions
|
||||
type SolarData struct {
|
||||
SolarFluxIndex int `json:"sfi"` // Solar Flux Index
|
||||
Sunspots int `json:"sunspots"` // Number of sunspots
|
||||
AIndex int `json:"a_index"` // A-index (geomagnetic activity)
|
||||
KIndex int `json:"k_index"` // K-index (geomagnetic activity)
|
||||
GeomagField string `json:"geomag"` // Geomagnetic field status
|
||||
UpdatedAt string `json:"updated"` // Last update time
|
||||
}
|
||||
|
||||
// HamQSLResponse matches the XML structure from hamqsl.com
|
||||
type HamQSLResponse struct {
|
||||
XMLName xml.Name `xml:"solar"`
|
||||
SolarData SolarDataXML `xml:"solardata"`
|
||||
}
|
||||
|
||||
type SolarDataXML struct {
|
||||
Updated string `xml:"updated"`
|
||||
SolarFlux string `xml:"solarflux"`
|
||||
AIndex string `xml:"aindex"`
|
||||
KIndex string `xml:"kindex"`
|
||||
Sunspots string `xml:"sunspots"`
|
||||
GeomagField string `xml:"geomagfield"`
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
httpClient *http.Client
|
||||
lastUpdate time.Time
|
||||
cachedData *SolarData
|
||||
}
|
||||
|
||||
func New() *Client {
|
||||
return &Client{
|
||||
httpClient: &http.Client{
|
||||
Timeout: 10 * time.Second,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// GetSolarData fetches current solar data from HamQSL
|
||||
// Data is cached for 15 minutes to avoid excessive requests
|
||||
func (c *Client) GetSolarData() (*SolarData, error) {
|
||||
// Return cached data if less than 15 minutes old
|
||||
if c.cachedData != nil && time.Since(c.lastUpdate) < 15*time.Minute {
|
||||
return c.cachedData, nil
|
||||
}
|
||||
|
||||
resp, err := c.httpClient.Get("http://www.hamqsl.com/solarxml.php")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch solar data: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read response: %w", err)
|
||||
}
|
||||
|
||||
var hamqslData HamQSLResponse
|
||||
if err := xml.Unmarshal(body, &hamqslData); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse XML: %w", err)
|
||||
}
|
||||
|
||||
// Parse the data
|
||||
solarData := &SolarData{
|
||||
GeomagField: hamqslData.SolarData.GeomagField,
|
||||
UpdatedAt: hamqslData.SolarData.Updated,
|
||||
}
|
||||
|
||||
// Parse numeric values (trim spaces)
|
||||
fmt.Sscanf(strings.TrimSpace(hamqslData.SolarData.SolarFlux), "%d", &solarData.SolarFluxIndex)
|
||||
fmt.Sscanf(strings.TrimSpace(hamqslData.SolarData.AIndex), "%d", &solarData.AIndex)
|
||||
fmt.Sscanf(strings.TrimSpace(hamqslData.SolarData.KIndex), "%d", &solarData.KIndex)
|
||||
fmt.Sscanf(strings.TrimSpace(hamqslData.SolarData.Sunspots), "%d", &solarData.Sunspots)
|
||||
|
||||
// Cache the data
|
||||
c.cachedData = solarData
|
||||
c.lastUpdate = time.Now()
|
||||
|
||||
return solarData, nil
|
||||
}
|
||||
Reference in New Issue
Block a user