awn

package module
v0.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 30, 2023 License: MIT Imports: 12 Imported by: 0

README

Ambient Weather Network API Client

Warning

This work is still very much in progress. I would not recommend that you use or fork it... not yet anyway.

Overview

This is a feature-complete Go version of a client that can connect to the Ambient Weather Network API in order to pull information about your weather station and the data that it has collected. It supports the normal API as well as the Websockets-based realtime API.

Installation

go get github.com/d-dot-one/ambient-weather-network-client

... or you can simply import it in your project and use it.

package yourpackagename
import "github.com/d-dot-one/awn"

You'll need to do a go get in the terminal to actually fetch the package.

Environment Variables

In order for all of this to work, you will need the following environment variables:

Variable Required Description
AWN_API_KEY Yes Your Ambient Weather Network API key
AWN_APP_KEY Yes Your Ambient Weather Network application key
AWN_LOG_LEVEL No The log level to use. Defaults to info

Usage

Get Weather Station Data

To fetch the current weather and the weather station device data, you can use the following code:

package main

import (
	"context"
	"fmt"
	"time"

	client "github.com/d-dot-one/awn"
)

func main() {
	// create a context
	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
	defer cancel()

	// fetch required environment variables
	requiredVars := []string{"AWN_API_KEY", "AWN_APP_KEY", "AWN_LOG_LEVEL"}
	environmentVariables := client.GetEnvVars(requiredVars)

	// set the API key
	apiKey := fmt.Sprintf("%v", environmentVariables["AWN_API_KEY"])

	// set the application key
	appKey := fmt.Sprintf("%v", environmentVariables["AWN_APP_KEY"])

	// create an object to hold the API configuration
	ApiConfig := client.CreateApiConfig(apiKey, appKey, ctx)

	// fetch the device data and return it as an AmbientDevice
	data, err := client.GetDevices(ApiConfig)
	client.CheckReturn(err, "failed to get devices", "critical")

	// see the MAC address of the weather station
	fmt.Println(data.MacAddress)
}
Get Historical Weather Station Data
package main

import (
	"context"
	"fmt"
	"time"

	client "github.com/d-dot-one/awn"
)

func main() {
	// create a context
	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
	defer cancel()

	// fetch required environment variables
	requiredVars := []string{"AWN_API_KEY", "AWN_APP_KEY", "AWN_LOG_LEVEL"}
	environmentVariables := client.GetEnvVars(requiredVars)

	// set the API key
	apiKey := fmt.Sprintf("%v", environmentVariables["AWN_API_KEY"])

	// set the application key
	appKey := fmt.Sprintf("%v", environmentVariables["AWN_APP_KEY"])

	// create an object to hold the API configuration
	ApiConfig := client.CreateApiConfig(apiKey, appKey, ctx)

	// fetch the device data and return it as an AmbientDevice
	data, err := client.GetDevices(ApiConfig)
	client.CheckReturn(err, "failed to get devices", "critical")

	// see the MAC address of the weather station
	fmt.Println(data.MacAddress)
}

Dependencies

I purposefully chose to use as few dependencies as possible for this project. I wanted to keep it as simple and close to the standard library. The only exception is the resty library, which is used to make the API calls. It was too helpful with retries to not use it.

Constrictions

The Ambient Weather API has a cap on the number of API calls that one can make in a given second. This is set to 1 call per second. This means that if you have more than one weather station, you will need to make sure that you are not making more than 1 call per second. This is done by using a time.Sleep(1 * time.Second) after each API call. Generally speaking, this is all handled in the background with a retry mechanism, but it is something to be aware of.

Contributing

You are more than welcome to submit a PR if you would like to contribute to this project. I am always open to suggestions and improvements. Reference CONTRIBUTING.md for more information.

License

This package is made available under an MIT license. See LICENSE.md for more information.

Documentation

Overview

Package awn is a client that can access the Ambient Weather network API and return device and weather data.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrContextTimeoutExceeded = ClientError{/* contains filtered or unexported fields */} //nolint:exhaustruct
	ErrMalformedDate          = ClientError{/* contains filtered or unexported fields */} //nolint:exhaustruct
	ErrRegexFailed            = ClientError{/* contains filtered or unexported fields */} //nolint:exhaustruct
	ErrAPIKeyMissing          = ClientError{/* contains filtered or unexported fields */} //nolint:exhaustruct
	ErrAppKeyMissing          = ClientError{/* contains filtered or unexported fields */} //nolint:exhaustruct
	ErrInvalidDateFormat      = ClientError{/* contains filtered or unexported fields */} //nolint:exhaustruct
	ErrMacAddressMissing      = ClientError{/* contains filtered or unexported fields */} //nolint:exhaustruct
)

Functions

func CheckResponse

func CheckResponse(resp map[string]string) (bool, error)

CheckResponse is a public function that will take an API response and evaluate it for any errors that might have occurred. The API specification does not publish all the possible error messages, but these are what I have found so far. It returns a boolean that indicates if the response has an error or not and an error message, if applicable.

This is not currently implemented.

func ConvertTimeToEpoch

func ConvertTimeToEpoch(tte string) (int64, error)

The ConvertTimeToEpoch public helper function that can convert a string, formatted as a time.DateOnly object (i.e. "2023-01-01") to a Unix epoch time in milliseconds. This can be helpful when you want to use the GetHistoricalData function to fetch data for a specific date or range of dates.

Basic Usage:

epochTime, err := ConvertTimeToEpoch("2023-01-01")

func CreateAwnClient

func CreateAwnClient(url string, version string) (*resty.Client, error)

CreateAwnClient is a public function that is used to create a new resty-based API client. It takes the URL that you would like to connect to and the API version as inputs from the caller. This client supports retries and can be placed into debug mode when needed. By default, it will also set the accept content type to JSON. Finally, it returns a pointer to the client and an error.

Basic Usage:

client, err := createAwnClient()

func GetEnvVar

func GetEnvVar(key string) string

GetEnvVar is a public function attempts to fetch an environment variable. If that environment variable is not found, it will return an empty string.

Basic Usage:

environmentVariable := GetEnvVar("ENV_VAR_1", "fallback")

func GetEnvVars

func GetEnvVars(vars []string) map[string]string

GetEnvVars is a public function that will attempt to read the environment variables that are passed in as a list of strings. It will return a map of the environment variables.

Basic Usage:

listOfEnvironmentVariables := GetEnvVars([]string{"ENV_VAR_1", "ENV_VAR_2"})

func GetHistoricalDataAsync

func GetHistoricalDataAsync(
	ctx context.Context,
	funcData FunctionData,
	url string,
	version string,
	w *sync.WaitGroup) (<-chan DeviceDataResponse, error)

GetHistoricalDataAsync is a public function that takes a context object, a FunctionData object, the URL of the Ambient Weather Network API, the version route of the API and a WaitGroup object as inputs. It will return a channel of DeviceDataResponse objects and an error status.

Basic Usage:

ctx := createContext()
outChannel, err := awn.GetHistoricalDataAsync(ctx, functionData, *sync.WaitGroup)

func GetRealtimeData

func GetRealtimeData() (string, error)

GetRealtimeData is a public function that will connect to the Ambient Weather real-time weather API via Websockets and fetch live data.

Types

type AmbientDevice

type AmbientDevice struct {
	Info       info       `json:"info"`
	LastData   DeviceData `json:"DeviceData"`
	MacAddress string     `json:"macAddress"`
}

AmbientDevice is a struct that is used in the marshal/unmarshal JSON. This structure is not fully required, since all we use is the MacAddress field. The rest of the data is thrown away.

func GetLatestData added in v0.0.3

func GetLatestData(ctx context.Context, funcData FunctionData, url string, version string) (*AmbientDevice, error)

GetLatestData is a public function that takes a context object, a FunctionData object, a URL and an API version route as inputs. It then creates an AwnClient and sets the appropriate query parameters for authentication, makes the request to the devicesEndpoint endpoint and marshals the response data into a pointer to an AmbientDevice object, which is returned along with any error message.

This function can be used to get the latest data from the Ambient Weather Network API. But, it is generally used to get the MAC address of the weather station that you would like to get historical data from.

Basic Usage:

ctx := createContext()
apiConfig := awn.CreateApiConfig(apiKey, appKey)
data, err := awn.GetLatestData(ctx, ApiConfig, baseURL, apiVersion)

func (AmbientDevice) String

func (a AmbientDevice) String() string

String is a helper function to print the AmbientDevice struct as a string.

type ClientError added in v0.0.3

type ClientError struct {
	// contains filtered or unexported fields
}

ClientError is a public custom error type that is used to return errors from the client.

func (ClientError) Error added in v0.0.3

func (c ClientError) Error() string

Error is a public function that returns the error message.

func (ClientError) Is added in v0.0.3

func (c ClientError) Is(err error) bool

Is is a public function that reports whether any error in the error's chain matches target.

func (ClientError) Unwrap added in v0.0.3

func (c ClientError) Unwrap() error

Unwrap is a public function that returns the underlying error by unwrapping it.

func (ClientError) Wrap added in v0.0.3

func (c ClientError) Wrap() error

Wrap is a public function that allows for errors to be propagated up correctly.

type DeviceData

type DeviceData struct {
	Baromabsin        float64   `json:"baromabsin"`
	Baromrelin        float64   `json:"baromrelin"`
	BattLightning     int       `json:"batt_lightning"`
	Dailyrainin       int       `json:"dailyrainin"`
	Date              time.Time `json:"date"`
	Dateutc           int64     `json:"dateutc"`
	DewPoint          float64   `json:"dewPoint"`
	DewPointin        float64   `json:"dewPointin"`
	Eventrainin       int       `json:"eventrainin"`
	FeelsLike         float64   `json:"feelsLike"`
	FeelsLikein       float64   `json:"feelsLikein"`
	Hourlyrainin      int       `json:"hourlyrainin"`
	Humidity          int       `json:"humidity"`
	Humidityin        int       `json:"humidityin"`
	LastRain          time.Time `json:"lastRain"`
	LightningDay      int       `json:"lightning_day"`
	LightningDistance float64   `json:"lightning_distance"`
	LightningHour     int       `json:"lightning_hour"`
	LightningTime     int64     `json:"lightning_time"`
	Maxdailygust      float64   `json:"maxdailygust"`
	Monthlyrainin     float64   `json:"monthlyrainin"`
	Solarradiation    float64   `json:"solarradiation"`
	Tempf             float64   `json:"tempf"`
	Tempinf           float64   `json:"tempinf"`
	Tz                string    `json:"tz"`
	Uv                int       `json:"uv"`
	Weeklyrainin      float64   `json:"weeklyrainin"`
	Winddir           int       `json:"winddir"`
	WinddirAvg10M     int       `json:"winddir_avg10m"`
	Windgustmph       float64   `json:"windgustmph"`
	WindspdmphAvg10M  float64   `json:"windspdmph_avg10m"`
	Windspeedmph      float64   `json:"windspeedmph"`
	Yearlyrainin      float64   `json:"yearlyrainin"`
}

DeviceData is used to marshal/unmarshal the response from the 'devices' API endpoint. This should be removed, since this data is not captured. It's only possible use is for a quasi-real-time data pull.

type DeviceDataResponse

type DeviceDataResponse struct {
	Baromabsin        float64   `json:"baromabsin"`
	Baromrelin        float64   `json:"baromrelin"`
	BattLightning     int       `json:"batt_lightning"`
	Dailyrainin       float64   `json:"dailyrainin"`
	Date              time.Time `json:"date"`
	Dateutc           int64     `json:"dateutc"`
	DewPoint          float64   `json:"dewPoint"`
	DewPointin        float64   `json:"dewPointin"`
	Eventrainin       float64   `json:"eventrainin"`
	FeelsLike         float64   `json:"feelsLike"`
	FeelsLikein       float64   `json:"feelsLikein"`
	Hourlyrainin      float64   `json:"hourlyrainin"`
	Humidity          int       `json:"humidity"`
	Humidityin        int       `json:"humidityin"`
	LastRain          time.Time `json:"lastRain"`
	LightningDay      int       `json:"lightning_day"`
	LightningDistance float64   `json:"lightning_distance"`
	LightningHour     int       `json:"lightning_hour"`
	LightningTime     int64     `json:"lightning_time"`
	Maxdailygust      float64   `json:"maxdailygust"`
	Monthlyrainin     float64   `json:"monthlyrainin"`
	Solarradiation    float64   `json:"solarradiation"`
	Tempf             float64   `json:"tempf"`
	Tempinf           float64   `json:"tempinf"`
	Tz                string    `json:"tz"`
	Uv                int       `json:"uv"`
	Weeklyrainin      float64   `json:"weeklyrainin"`
	Winddir           int       `json:"winddir"`
	WinddirAvg10M     int       `json:"winddir_avg10m"`
	Windgustmph       float64   `json:"windgustmph"`
	WindspdmphAvg10M  float64   `json:"windspdmph_avg10m"`
	Windspeedmph      float64   `json:"windspeedmph"`
	Yearlyrainin      float64   `json:"yearlyrainin"`
}

DeviceDataResponse is used to marshal/unmarshal the response from the devices/macAddress endpoint.

func GetHistoricalData

func GetHistoricalData(
	ctx context.Context,
	funcData FunctionData,
	url string,
	version string) ([]DeviceDataResponse, error)

GetHistoricalData is a public function that takes a context object, a FunctionData object, the URL of the Ambient Weather Network API and the API version route as inputs and returns a list of DeviceDataResponse objects and an error.

This function is useful if you would like to retrieve data from some point in the past until the present.

Basic Usage:

ctx := createContext()
apiConfig := awn.CreateApiConfig(apiKey, appKey)
resp, err := GetHistoricalData(ctx, apiConfig)

func (DeviceDataResponse) String

func (d DeviceDataResponse) String() string

String is a helper function to print the DeviceDataResponse struct as a string.

type FunctionData

type FunctionData struct {
	API   string `json:"api"`
	App   string `json:"app"`
	Epoch int64  `json:"epoch"`
	Limit int    `json:"limit"`
	Mac   string `json:"mac"`
}

FunctionData is a struct that is used to pass data basic API call parameters more easily. It contains API (API key), App (Application key), Epoch (Unix epoch time in milliseconds), Limit (maximum number of records to return in a single API call), and Mac (MAC address of the weather station).

func CreateAPIConfig

func CreateAPIConfig(api string, app string) *FunctionData

CreateAPIConfig is a public helper function that is used to create the FunctionData struct, which is passed to the data gathering functions. It takes as parameters the API key as "api" and the Application key as "app" and returns a pointer to a FunctionData object.

Basic Usage:

apiConfig := awn.CreateApiConfig("apiTokenHere", "appTokenHere")

func NewFunctionData

func NewFunctionData() *FunctionData

NewFunctionData creates a new FunctionData object with bare default values and return it to the caller as a pointer.

func (FunctionData) String

func (f FunctionData) String() string

String is a helper function to print the FunctionData struct as a string.

func (FunctionData) ToMap

func (f FunctionData) ToMap() map[string]interface{}

ToMap is a helper function to convert the FunctionData struct to a map.

type LogLevelForError

type LogLevelForError string

LogLevelForError is a type that describes the log level for an error message.

type LogMessage added in v0.0.2

type LogMessage string

LogMessage is the message that you would like to see in the log.

type YearMonthDay added in v0.0.2

type YearMonthDay string

YearMonthDay is a type that describes a date in the format YYYY-MM-DD.

func (YearMonthDay) String added in v0.0.2

func (y YearMonthDay) String() string

String is a public helper function that will return the YearMonthDay object as a string.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL