airthings

package module
v0.0.0-...-a2e2dcb Latest Latest
Warning

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

Go to latest
Published: Mar 9, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

README

Airthings API

This project provides HomeKit integration for Airthings air quality monitors, allowing you to view your Airthings sensor data directly via HomeKit using HAP. It supports various air quality measurements including temperature, humidity, CO2, VOC, radon, and atmospheric pressure.

Installation

go get github.com/jeffh/airthings

Usage

Use Authorize to create a client that can access device metrics:

// scopes can be nil for default
client, err := airthings.Authorize(ctx, airthingsClientId, airthingsClientSecret, nil)

Then you can list all available devices to your account:

devices, err := client.ListDevices(airthings.ListDevicesOptions{})

You can then collect devices from each device:

samples, err := client.GetLatestSamples(airthings.GetLatestSamplesOptions{
	SerialNumber: devices[0].SerialNumber,
})
Throttling

The biggest limitation of the airthings API is the aggressive throttling. It's preferrable to poll no greater than every 5 minutes for all API calls.

HAP

The hap subpackage provides accessories for HAP.

import ahap "github.com/jeffh/airthings/hap"

var accessories []*accessory.A
for _, device := range devices {
	group := ahap.New(client)

	accessories = append(accessories, group.A)
	// you have control on how often to update from the API since directly
	// proxying requests to the API would cause you to throttle quickly.
	go func(device airthings.Device){
		for {
			samples, err := client.GetLatestSamples(airthings)
			if err == nil {
				group.Update(samples)
			} else {
				// ...
			}
			select {
			case <-time.After(15 * time.Minute):
				continue
			case <-ctx.Done:
				return
			}
		}
	}(device)
}

store := hap.NewFsStore(".hap")
server := hap.NewServer(store, accessories...)
// ... normal hap setup

Documentation

Index

Constants

View Source
const (
	RadonShortTermAverage               SensorType = "radonShortTermAvg"
	RadonLongTermAverage                           = "radonLongTermAvg"
	Temperature                                    = "temp"
	OutdoorTemperature                             = "outdoorTemp"
	Humidity                                       = "humidity"
	OutdoorHumidity                                = "outdoorHumidity"
	CO2                                            = "co2"
	VOC                                            = "voc"
	Pressure                                       = "pressure"
	OutdoorPressure                                = "outdoorPressure"
	PressureDifference                             = "pressureDifference"
	PressureDifferenceStandardDeviation            = "pressureDiffStdDev"
	PressureDifferenceMin                          = "pressureDiffMin"
	PressureDifferenceMax                          = "pressureDiffMax"
	Light                                          = "light"
	BatteryPercentage                              = "batteryPercentage"
	BatteryVoltage                                 = "batteryVoltage"
	Orientation                                    = "orientation"
	PM1                                            = "pm1"
	OutdoorPM1                                     = "outdoorPm1"
	PM25                                           = "pm25"
	OutdoorPM25                                    = "outdoorPm25"
	PM10                                           = "pm10"
	OutdoorPM10                                    = "outdoorPm10"
	Mold                                           = "mold"
	StaleAir                                       = "staleAir"
	TransmissionEfficiency                         = "transmissionEfficiency"
	VirusSurvivalRate                              = "virusSurvivalRate"
	VirusRisk                                      = "virusRisk"
	WindSpeed                                      = "windSpeed"
	WindDirection                                  = "windDirection"
	WindGust                                       = "windGust"
	DewPoint                                       = "dewPoint"
	CloudCover                                     = "cloudCover"
	Visibility                                     = "visibility"
	PrecipitationProbability                       = "precipitation_probability"
	TotalPrecipitation                             = "total_precipitation"
	OutdoorWeather                                 = "outdoorWeather"
	HourlyRadonStandardDeviation                   = "hourlyRadonStandardDeviation"
	HourlyRadon                                    = "hourlyRadon"
	EnergyWastage                                  = "energyWastage"
	EnergyScenarios                                = "energyScenarios"
	HistoricVentilationConfidence                  = "historicVentilationConfidence"
	DaytimeBaseline                                = "daytimeBaseline"
	DaytimePeak                                    = "daytimePeak"
	NightBaseline                                  = "nightBaseline"
	HistoricVentilation                            = "historicVentilation"
	VentilationRunningConfidence                   = "ventilationRunningConfidence"
	OccupantsUpperBound                            = "occupantsUpper"
	OccupantsLowerBound                            = "occupantsLower"
	Occupants                                      = "occupants"
	RelativeOccupants                              = "relativeOccupants"
	VentilationAmount                              = "ventilationAmount"
	HistoricVentilationRunning                     = "historicVentilationRunning"
	VentilationRunning                             = "ventilationRunning"
	RelativeVentilationRate                        = "relativeVentilationRate"
	Aggregated                                     = "aggregated"
	SLA                                            = "sla"
	PressureAtMinHeight                            = "pressureAtMinHeight"
	PressureAtMaxHeight                            = "pressureAtMaxHeight"
	RegulationPressure                             = "regulationPressure"
	RegulationHeight                               = "regulationHeight"
	ZeroPressureHeight                             = "zeroPressureHeight"
	TotalPowerLost                                 = "totalPowerLost"
	MoistGuard                                     = "moistGuard"
	PotentialPowerSaved                            = "potentialPowerSaved"
	PotentialPowerSavedPercent                     = "potentialPowerSavedPercent"
	ZeroHeightPercent                              = "zeroHeightPercent"
	Zone                                           = "zone"
	ControlSignal                                  = "controlSignal"
	ControlStatus                                  = "controlStatus"
	ReturnState                                    = "returnState"
	AppliedGain                                    = "appliedGain"
	LastBestControlSignal                          = "lastBestControlSignal"
	LastBestSignalError                            = "lastBestSignalError"
	LastBestControlSignalGain                      = "lastBestControlSignalGain"
	LastBestControlSignalRecorded                  = "lastBestControlSignalRecorded"
	Messages                                       = "messages"
	BalanceControl                                 = "balanceControl"
	ControlSignalSlot01                            = "controlSignalSlot01"
	ControlSignalSlot02                            = "controlSignalSlot02"
	ControlSignalSlot03                            = "controlSignalSlot03"
	ControlSignalSlot04                            = "controlSignalSlot04"
	ControlSignalSlot05                            = "controlSignalSlot05"
	ControlSignalSlot06                            = "controlSignalSlot06"
	ControlSignalSlot07                            = "controlSignalSlot07"
	ControlSignalSlot08                            = "controlSignalSlot08"
	InletAirControl                                = "inletAirControl"
	PowerVoltage                                   = "powerVoltage"
	RSRP                                           = "rsrp"
	VentController                                 = "ventController"
	SubsamplesCount                                = "subsamplesCount"
	Subsamples                                     = "subsamples"
	BalanceInfo                                    = "balanceInfo"
	OutdoorNO2                                     = "outdoorNo2"
	OutdoorO3                                      = "outdoorO3"
	OutdoorSo2                                     = "outdoorSo2"
	OutdoorCo                                      = "outdoorCo"
	OutdoorNo                                      = "outdoorNo"
	Airly                                          = "airly"
	AirlyNo2                                       = "airlyNo2"
	AirlyCo                                        = "airlyCo"
	AirlyNo                                        = "airlyNo"
	BacNet                                         = "bacnet"

	Relay = "relayDeviceType" // indicates the device that proxied this information (eg - a hub)
)

Variables

View Source
var ErrNoSerialNumber = errors.New("missing serial number")

Functions

This section is empty.

Types

type Authentication

type Authentication struct {
	GrantType    string `json:"grant_type"`
	ClientId     string `json:"client_id"`
	ClientSecret string `json:"client_secret"`

	Code        string `json:"code"`
	RedirectUri string `json:"redirect_uri"`

	RefreshToken string `json:"refresh_token"`

	Scope []string `json:"scope"`
}

type Client

type Client struct {
	Endpoint string
	// contains filtered or unexported fields
}

func Authorize

func Authorize(ctx context.Context, clientId, clientSecret string, scopes []string) (*Client, error)

func (*Client) GetDevice

func (c *Client) GetDevice(opts GetDeviceOptions) (Device, error)

GetDevice returns information about a particular device

func (*Client) GetLatestSamples

func (c *Client) GetLatestSamples(opts GetLatestSamplesOptions) (map[SensorType]interface{}, error)

func (*Client) ListDevices

func (c *Client) ListDevices(opts ListDevicesOptions) ([]Device, error)

ListDevices get devices belonging to the account

type Device

type Device struct {
	SerialNumber string         `json:"id"` // this is the serial number
	DeviceType   DeviceType     `json:"deviceType"`
	Sensors      []SensorType   `json:"sensors"`
	Segment      DeviceSegment  `json:"segment"`
	Location     DeviceLocation `json:"location"`
}

type DeviceLocation

type DeviceLocation struct {
	Id   string `json:"id"`
	Name string `json:"name"`
}

type DeviceSegment

type DeviceSegment struct {
	Id        string `json:"id"`
	Name      string `json:"name"`
	StartedAt string `json:"started"`
	Active    bool   `json:"active"`
}

type DeviceType

type DeviceType string
const (
	DevWave                 DeviceType = "WAVE"
	DevWaveMist             DeviceType = "WAVE_MIST"
	DevWave2                DeviceType = "WAVE_GEN2"
	DevWaveMini             DeviceType = "WAVE_MINI"
	DevWavePlus             DeviceType = "WAVE_PLUS"
	DevWaveCO2              DeviceType = "WAVE_CO2"
	DevWaveViewPlus         DeviceType = "VIEW_PLUS"
	DevWaveViewPlusBusiness DeviceType = "VIEW_PLUS_BUSINESS"
	DevWaveViewPollution    DeviceType = "VIEW_POLLUTION"
	DevWaveViewRadon        DeviceType = "VIEW_RADON"
	DevWaveViewCO2          DeviceType = "VIEW_CO2"
	DevWaveTernCO2          DeviceType = "TERN_CO2"
	DevWaveHub              DeviceType = "HUB"
	DevWaveHome             DeviceType = "HOME"
	DevWavePro              DeviceType = "PRO"
	DevWaveCloudBerry       DeviceType = "CLOUDBERRY"
	DevWaveAirtight         DeviceType = "AIRTIGHT"
	DevAggregatedGroup      DeviceType = "AGGREGATED_GROUP"
	DevZoneGroup            DeviceType = "ZONE_GROUP"
	DevBalanceControl       DeviceType = "BALANCE_CONTROL"
	DevInletAirControl      DeviceType = "INLET_AIR_CONTROL"
	DevVentController       DeviceType = "VENT_CONTROLLER"
	DevAirly                DeviceType = "AIRLY"
	DevAirlyNO2             DeviceType = "AIRLY_NO2"
	DevAirlyCO              DeviceType = "AIRLY_CO"
	DevAirlyNO              DeviceType = "AIRLY_NO"
	DevBreezometerWeather   DeviceType = "BREEZOMETER_WEATHER"
	DevBacNet               DeviceType = "BACNET"
	DevUnknown              DeviceType = "UNKNOWN"
)

func (DeviceType) String

func (dt DeviceType) String() string

type GetDeviceOptions

type GetDeviceOptions struct {
	SerialNumber   string
	OrganizationId string
	UserGroupId    string
}

type GetLatestSamplesOptions

type GetLatestSamplesOptions struct {
	SerialNumber   string // required
	OrganizationId string
	UserGroupId    string
}

type ListDevicesOptions

type ListDevicesOptions struct {
	ShowInactive   bool
	OrganizationId string
	UserGroupId    string
}

type SensorType

type SensorType string

Directories

Path Synopsis
hap

Jump to

Keyboard shortcuts

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