Add Toshiba Tec LIUST-A00 utilities
All checks were successful
Alpine 3.22 Success
OpenBSD 7.8 Success

This commit is contained in:
2025-10-05 17:02:02 +02:00
parent f26cfd3bb5
commit de4379ca2c
11 changed files with 1280 additions and 0 deletions

View File

@@ -0,0 +1,132 @@
package main
import (
"encoding/xml"
"fmt"
"io"
"log"
"net/http"
"strconv"
"time"
)
const (
baseURL = "https://api.met.no/weatherapi"
userAgent = "liustatus/1.0"
// Prague coordinates.
lat = 50.08804
lon = 14.42076
altitude = 202
)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
type Weatherdata struct {
XMLName xml.Name `xml:"weatherdata"`
Product Product `xml:"product"`
}
type Product struct {
Times []Time `xml:"time"`
}
type Time struct {
From string `xml:"from,attr"`
To string `xml:"to,attr"`
Location Location `xml:"location"`
}
type Location struct {
Temperature *Temperature `xml:"temperature"`
}
type Temperature struct {
Unit string `xml:"unit,attr"`
Value string `xml:"value,attr"`
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// WeatherFetcher handles weather data retrieval.
type WeatherFetcher struct {
client *http.Client
}
// NewWeatherFetcher creates a new weather fetcher instance.
func NewWeatherFetcher() *WeatherFetcher {
return &WeatherFetcher{
client: &http.Client{Timeout: 30 * time.Second},
}
}
// fetchWeather retrieves the current temperature from the API.
func (w *WeatherFetcher) fetchWeather() (string, error) {
url := fmt.Sprintf(
"%s/locationforecast/2.0/classic?lat=%.5f&lon=%.5f&altitude=%d",
baseURL, lat, lon, altitude)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return "", err
}
req.Header.Set("User-Agent", userAgent)
resp, err := w.client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("API returned status %d", resp.StatusCode)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
var weatherData Weatherdata
if err := xml.Unmarshal(body, &weatherData); err != nil {
return "", err
}
now := time.Now().UTC()
for _, t := range weatherData.Product.Times {
toTime, err := time.Parse("2006-01-02T15:04:05Z", t.To)
if err != nil || toTime.Before(now) {
continue
}
if t.Location.Temperature != nil {
temp, err := strconv.ParseFloat(t.Location.Temperature.Value, 64)
if err != nil {
continue
}
return fmt.Sprintf("%d゚", int(temp)), nil
}
}
return "", fmt.Errorf("no usable temperature data found")
}
// update fetches new weather data and returns it.
func (w *WeatherFetcher) update() string {
temp, err := w.fetchWeather()
if err != nil {
log.Printf("Error fetching weather: %v", err)
}
return temp
}
// Run runs as a goroutine to periodically fetch weather data.
func (w *WeatherFetcher) Run(interval time.Duration, output chan<- string) {
ticker := time.NewTicker(interval)
defer ticker.Stop()
output <- w.update()
for range ticker.C {
output <- w.update()
}
}