Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you fetch weather data from the Google Maps Platform?

Tags:

I have a list of locations and I want to know if it's possible to get weather data from the Google Maps API.

like image 231
Kelsey Hightower Avatar asked Jul 26 '18 06:07

Kelsey Hightower


People also ask

How do I get weather on Google Maps?

To add the weather layer, hover over the widget in the upper right corner of Google Maps and select the weather layer from the list of options. When zoomed out, you'll see a map with current weather conditions from weather.com for various locations, with icons to denote sun, clouds, rain and so on.

Is Google Maps API free?

The API is available for developers that have a free Google Maps API key. Usage of the API is not strictly free, but they do offer $200 of free monthly usage for most users. The pricing scales to fit your particular needs and you are only charged for your API usage.

Does Google Maps have an API?

The Google Maps Platform is a set of APIs and SDKs that allows developers to embed Google Maps into mobile apps and web pages, or to retrieve data from Google Maps.


1 Answers

When I've had to do this in Go, I've done something like this:

package main

import (
    "bufio"
    "context"
    "database/sql"
    "encoding/json"
    "flag"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "os"
    "strings"
    "sync"
    "time"

    "googlemaps.github.io/maps"

    _ "github.com/lib/pq"
)

var db *sql.DB

var (
    apiKey        string
    dsn           string
    locationsFile string
)

type HourlyForecast struct {
    Type       string
    Properties Properties
}

type Properties struct {
    Periods []Period
}

type Period struct {
    Temperature int
}

func main() {
    flag.StringVar(&apiKey, "api-key", "", "Google Maps API key")
    flag.StringVar(&dsn, "dsn", "", "The database connection string")
    flag.StringVar(&locationsFile, "locations", "locations.txt", "The locations file")
    flag.Parse()

    if apiKey == "" {
        apiKey = os.Getenv("GOOGLE_MAPS_API_KEY")
    }

    if apiKey == "" {
        log.Fatal("The --api-key flag or GOOGLE_MAPS_API_KEY env var must be set and non-empty")
    }

    apiKey = strings.TrimSpace(apiKey)

    if dsn == "" {
        dsn = os.Getenv("DSN")
    }

    var err error
    db, err = sql.Open("postgres", dsn)
    if err != nil {
        log.Fatal(err)
    }

    for {
        err := db.Ping()
        if err != nil {
            log.Println(err.Error())
            time.Sleep(3 * time.Second)
            continue
        }
        break
    }

    data, err := os.Open(locationsFile)
    if err != nil {
        log.Fatal(err)
    }

    var locations []string

    scanner := bufio.NewScanner(data)
    for scanner.Scan() {
        locations = append(locations, scanner.Text())

    }

    var wg sync.WaitGroup

    for _, location := range locations {
        wg.Add(1)
        location := location

        go func() {
            defer wg.Done()

            mc, err := maps.NewClient(maps.WithAPIKey(apiKey))
            if err != nil {
                log.Fatal(err)
            }

            r := maps.FindPlaceFromTextRequest{
                Input:     location,
                InputType: maps.FindPlaceFromTextInputTypeTextQuery,
            }

            response, err := mc.FindPlaceFromText(context.Background(), &r)
            if err != nil {
                log.Fatal(err)
            }

            pdr := maps.PlaceDetailsRequest{
                PlaceID: response.Candidates[0].PlaceID,
            }
            log.Printf("retrieving geo coordinates for %s", location)
            pdResponse, err := mc.PlaceDetails(context.Background(), &pdr)
            if err != nil {
                log.Fatal(err)
            }

            lat := pdResponse.Geometry.Location.Lat
            lng := pdResponse.Geometry.Location.Lng
            u := fmt.Sprintf("https://api.weather.gov/points/%.4f,%.4f/forecast/hourly", lat, lng)
            log.Printf("retrieving weather data for %s (%.4f,%.4f)", location, lat, lng)

            request, err := http.NewRequest("GET", u, nil)
            if err != nil {
                log.Fatal(err)
            }
            request.Header.Add("User-Agent", "Hightower Weather 1.0")
            request.Header.Add("Accept", "application/geo+json")

            weatherResponse, err := http.DefaultClient.Do(request)
            if err != nil {
                log.Fatal(err)
            }

            data, err := ioutil.ReadAll(weatherResponse.Body)
            if err != nil {
                log.Fatal(err)
            }

            weatherResponse.Body.Close()

            var forecast HourlyForecast
            if err := json.Unmarshal(data, &forecast); err != nil {
                log.Fatal(err)
            }

            log.Printf("setting temperature for %s to %d", location, forecast.Properties.Periods[0].Temperature)
            _, err = db.Exec(query, location, forecast.Properties.Periods[0].Temperature)
            if err != nil {
                log.Fatal(err)
            }
        }()
    }

    wg.Wait()
}

var query = `INSERT INTO weather (location, temperature)
VALUES ($1, $2)
ON CONFLICT (location)
DO UPDATE SET temperature = EXCLUDED.temperature;`
like image 86
Terry Ryan Avatar answered Sep 23 '22 00:09

Terry Ryan