roam-location/main.go

99 lines
2.3 KiB
Go

package main
import (
"context"
"log"
"os"
"strconv"
"sync"
"time"
"github.com/acaloiaro/roam-location/geocode"
"github.com/acaloiaro/roam-location/gpsd"
"github.com/acaloiaro/roam-location/service"
"github.com/acaloiaro/roam-location/weather"
"github.com/acaloiaro/roam-location/webdav"
)
type locationEntry struct {
Lat float64 `json:"lat"`
Lon float64 `json:"lon"`
Name string `json:"name,omitempty"`
}
type snapshot struct {
RecordedAt time.Time `json:"recorded_at"`
Location *locationEntry `json:"location,omitempty"`
Weather *weather.Data `json:"weather,omitempty"`
Conditions *weather.Condition `json:"conditions,omitempty"`
}
type cache struct {
mu sync.RWMutex
lat float64
lon float64
name string
ready bool
}
func (c *cache) set(lat, lon float64, name string) {
c.mu.Lock()
defer c.mu.Unlock()
c.lat, c.lon, c.name, c.ready = lat, lon, name, true
}
func (c *cache) get() (lat, lon float64, name string, ok bool) {
c.mu.RLock()
defer c.mu.RUnlock()
return c.lat, c.lon, c.name, c.ready
}
func pollInterval() time.Duration {
if s := os.Getenv("POLL_INTERVAL_SECONDS"); s != "" {
if n, err := strconv.Atoi(s); err == nil && n > 0 {
return time.Duration(n) * time.Second
}
}
return 30 * time.Second
}
func main() {
loc := &cache{}
wCache := weather.NewCache()
interval := pollInterval()
wdClient := webdav.NewClientFromEnv()
go func() {
for {
lat, lon, err := gpsd.GetLocation(context.Background())
if err != nil {
log.Printf("location poll error: %v", err)
} else {
city, err := geocode.CityCenter(context.Background(), lat, lon)
if err != nil {
log.Printf("geocode error: %v", err)
} else {
loc.set(city.Lat, city.Lon, city.Name)
log.Printf("location updated: %.6f, %.6f (%s)", city.Lat, city.Lon, city.Name)
if wdClient != nil {
snap := snapshot{
RecordedAt: time.Now().UTC(),
Location: &locationEntry{Lat: city.Lat, Lon: city.Lon, Name: city.Name},
}
if data, ok := wCache.Get(); ok {
snap.Weather = &data
snap.Conditions = weather.Infer(data, city.Lat, city.Lon)
}
if err := wdClient.Append(snap); err != nil {
log.Printf("webdav append error: %v", err)
}
}
}
}
time.Sleep(interval)
}
}()
service.Listen(loc.get, wCache)
}