mirror of
https://github.com/LeRoid-hub/humiditycalc.git
synced 2025-01-31 03:34:56 +00:00
Editited html, pull weather, mode both works, weatherdata cache
This commit is contained in:
parent
80cdd9de4f
commit
c0049aa393
23
README.md
23
README.md
@ -1,7 +1,30 @@
|
||||
# humiditycalc
|
||||
|
||||
BOTH slow- every req talks to api
|
||||
|
||||
## ENV
|
||||
MODES: CALC, WEATHER, BOTH
|
||||
BOTH is standard
|
||||
|
||||
OPENWEATHERMAP_API_KEY is required in WEATHER and BOTH mode
|
||||
|
||||
DEFAULT:
|
||||
MODE=CALC
|
||||
|
||||
Standalone:
|
||||
MODE=BOTH
|
||||
OPENWEATHERMAP_API_KEY=yourkey
|
||||
LATITUDE=
|
||||
LONGITUDE=
|
||||
|
||||
WEATHER:
|
||||
MODE=WEATHER
|
||||
OPENWEATHERMAP_API_KEY=yourkey
|
||||
DB_HOST=
|
||||
DB_PORT=
|
||||
DB_NAME=
|
||||
DB_PASSWORD=
|
||||
DB=
|
||||
|
||||
OPTINAL:
|
||||
PORT=80
|
@ -1 +1,68 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
func Weather(env map[string]string) (humidity float64, temperature float64) {
|
||||
// Get API key from environment variables
|
||||
apiKey := env["OPENWEATHERMAP_API_KEY"]
|
||||
|
||||
// Get latitude and longitude from environment variables
|
||||
latitude := env["LATITUDE"]
|
||||
longitude := env["LONGITUDE"]
|
||||
|
||||
// Check if latitude and longitude are set
|
||||
if latitude == "" || longitude == "" {
|
||||
fmt.Println("Latitude and longitude are not set")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Get data from API
|
||||
data := getData(apiKey, latitude, longitude)
|
||||
|
||||
// Parse data
|
||||
humidity, temperature = parseData(data)
|
||||
|
||||
// Convert to Celsius
|
||||
temperature = temperature - 273.15
|
||||
|
||||
return humidity, temperature
|
||||
|
||||
}
|
||||
|
||||
func getData(apiKey string, latitude string, longitude string) string {
|
||||
// Get data from API
|
||||
url := fmt.Sprintf("https://api.openweathermap.org/data/2.5/weather?lat=%s&lon=%s&appid=%s", latitude, longitude, apiKey)
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
fmt.Println("Error getting data from API")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Read response body
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
fmt.Println("Error reading response body")
|
||||
}
|
||||
|
||||
// Convert body to string
|
||||
return string(body)
|
||||
}
|
||||
|
||||
func parseData(data string) (humidity float64, temperature float64) {
|
||||
// Parse data from API
|
||||
|
||||
m := make(map[string]interface{})
|
||||
err := json.Unmarshal([]byte(data), &m)
|
||||
if err != nil {
|
||||
fmt.Println("Error parsing data")
|
||||
}
|
||||
n := m["main"].(map[string]interface{})
|
||||
|
||||
return n["humidity"].(float64), n["temp"].(float64)
|
||||
}
|
||||
|
8
main.go
8
main.go
@ -14,14 +14,17 @@ func main() {
|
||||
if val, ok := env["MODE"]; ok {
|
||||
if strings.ToLower(val) == "both" {
|
||||
checkEnv(env)
|
||||
server.Run()
|
||||
server.Run(env)
|
||||
} else if strings.ToLower(val) == "weather" {
|
||||
checkEnv(env)
|
||||
// weather.Run()
|
||||
} else if strings.ToLower(val) == "calc" {
|
||||
// calc.Run()
|
||||
server.Run()
|
||||
server.Run(env)
|
||||
}
|
||||
} else {
|
||||
// calc.Run()
|
||||
server.Run(env)
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,7 +45,6 @@ func loadEnv() map[string]string {
|
||||
func checkEnv(env map[string]string) {
|
||||
// Is there an API key for openweathermap?
|
||||
if val, ok := env["OPENWEATHERMAP_API_KEY"]; ok {
|
||||
fmt.Println(val)
|
||||
if val == "" {
|
||||
print("OPENWEATHERMAP_API_KEY is not set")
|
||||
os.Exit(1)
|
||||
|
36
models/cache.go
Normal file
36
models/cache.go
Normal file
@ -0,0 +1,36 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type WeatherCache struct {
|
||||
Humidity float64 // relative humidity in percentage
|
||||
Temperature float64 // temperature in Celsius
|
||||
timestamp time.Time // timestamp of last update
|
||||
duration int16 // duration in seconds
|
||||
}
|
||||
|
||||
func (w *WeatherCache) IsExpired() bool {
|
||||
fmt.Println(time.Since(w.timestamp), time.Duration(w.duration)*time.Second)
|
||||
return time.Since(w.timestamp) > time.Duration(w.duration)*time.Second
|
||||
}
|
||||
|
||||
func (w *WeatherCache) SetData(humidity float64, temperature float64) {
|
||||
w.Humidity = humidity
|
||||
w.Temperature = temperature
|
||||
w.timestamp = time.Now()
|
||||
w.duration = 60
|
||||
}
|
||||
|
||||
func (w *WeatherCache) GetData() (float64, float64) {
|
||||
if w.IsExpired() {
|
||||
return 0, 0
|
||||
}
|
||||
return w.Humidity, w.Temperature
|
||||
}
|
||||
|
||||
func NewWeatherCache() *WeatherCache {
|
||||
return &WeatherCache{}
|
||||
}
|
@ -1,19 +1,33 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/LeRoid-hub/humiditycalc/internal"
|
||||
"github.com/LeRoid-hub/humiditycalc/models"
|
||||
)
|
||||
|
||||
type result struct {
|
||||
AbsoluteHumidity float64
|
||||
AbsoluteHumidity string
|
||||
WeatherData WeatherData
|
||||
}
|
||||
|
||||
type WeatherData struct {
|
||||
Temperature string
|
||||
RelativeHumidity string
|
||||
AbsoluteHumidity string
|
||||
}
|
||||
|
||||
// Run starts the HTTP server.
|
||||
func Run() {
|
||||
func Run(env map[string]string) {
|
||||
// Cache weather data
|
||||
var cacheWeather = models.NewWeatherCache()
|
||||
|
||||
// Load HTML template
|
||||
tmpl := template.Must(template.ParseFiles("./web/templates/index.html"))
|
||||
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
@ -39,10 +53,44 @@ func Run() {
|
||||
// Calculate absolute humidity
|
||||
absoluteHumidity := internal.AbsoluteHumidity(temp, rh)
|
||||
|
||||
var absoluteWeatherHumidity float64
|
||||
var temperature, humidity float64
|
||||
|
||||
// Check if cache is expired or empty
|
||||
if cacheWeather.IsExpired() || cacheWeather.Humidity == 0 || cacheWeather.Temperature == 0 {
|
||||
// Get Weather data
|
||||
humidity, temperature := internal.Weather(env)
|
||||
|
||||
// Calculate absolute weather humidity
|
||||
absoluteWeatherHumidity = internal.AbsoluteHumidity(temperature, humidity)
|
||||
|
||||
// Update cache
|
||||
cacheWeather.SetData(humidity, temperature)
|
||||
} else {
|
||||
// Use cached data
|
||||
humidity, temperature := cacheWeather.GetData()
|
||||
absoluteWeatherHumidity = internal.AbsoluteHumidity(temperature, humidity)
|
||||
}
|
||||
|
||||
// Create response
|
||||
WData := WeatherData{Temperature: FormatFloat(temperature, 2), RelativeHumidity: FormatFloat(humidity, 4), AbsoluteHumidity: FormatFloat(absoluteWeatherHumidity, 4)}
|
||||
|
||||
re := result{AbsoluteHumidity: FormatFloat(absoluteHumidity, 4), WeatherData: WData}
|
||||
|
||||
// Write response
|
||||
tmpl.Execute(w, result{AbsoluteHumidity: absoluteHumidity})
|
||||
tmpl.Execute(w, re)
|
||||
})
|
||||
|
||||
http.ListenAndServe(":8080", nil)
|
||||
|
||||
}
|
||||
|
||||
func FormatFloat(num float64, prc int) string {
|
||||
var (
|
||||
zero, dot = "0", "."
|
||||
|
||||
str = fmt.Sprintf("%."+strconv.Itoa(prc)+"f", num)
|
||||
)
|
||||
|
||||
return strings.TrimRight(strings.TrimRight(str, zero), dot)
|
||||
}
|
||||
|
@ -14,7 +14,15 @@
|
||||
<br>
|
||||
<button type="submit">Calculate</button>
|
||||
</form>
|
||||
|
||||
{{ if .WeatherData }}
|
||||
<h2>Weather Data</h2>
|
||||
<p>Temperature: {{ .WeatherData.Temperature }}°C</p>
|
||||
<p>Relative Humidity: {{ .WeatherData.RelativeHumidity }}%</p>
|
||||
<p>Absolute Humidity: {{ .WeatherData.AbsoluteHumidity }} g/m³</p>
|
||||
{{ end }}
|
||||
{{ if .AbsoluteHumidity }}
|
||||
<h2>Calculated Absolute Humidity</h2>
|
||||
<p>Absolute Humidity: {{ .AbsoluteHumidity }} g/m³</p>
|
||||
{{ end }}
|
||||
</body>
|
||||
|
Loading…
Reference in New Issue
Block a user