farm-messages/messages.go

1016 lines
38 KiB
Go

// **********************************************************************
// Copyright (c) 2018-2019 Henry Seurer
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// **********************************************************************
package messages
import (
"encoding/json"
"log"
"math"
"math/rand"
"os"
"strings"
"sync/atomic"
"time"
)
type BuildVersion struct {
Version string `json:"version,omitempty"`
BuildTime string `json:"build_time,omitempty"`
Image string `json:"image,omitempty"`
ImageID string `json:"image_id,omitempty"`
Versions map[string]interface{} `json:"versions,omitempty"`
}
type MessageHeader struct {
Status int `json:"status,omitempty"`
Location string `json:"location,omitempty"`
TimeStamp time.Time `json:"timestamp,omitempty"`
Host string `json:"host,omitempty"`
Build BuildVersion `json:"build,omitempty"`
}
func GetHostName() string {
host := os.Getenv("DOCKER_HOST_IP")
if len(host) == 0 {
host, _ = os.Hostname()
}
return host
}
type EmptyMessage struct {
Header MessageHeader `json:"header,omitempty"`
}
type AlertSeverity int
//goland:noinspection GoUnusedConst
const (
Info AlertSeverity = 0 // Nothing to worry about FYI
Warning AlertSeverity = 1 // Should be looked into soon
Error AlertSeverity = 2 // Houston we have a problem
Cleared AlertSeverity = 3 // The issue has been addressed
)
type AlertMessage struct {
Header MessageHeader `json:"header,omitempty"`
Severity AlertSeverity `json:"severity,omitempty"`
Source string `json:"source,omitempty"`
Message string `json:"message,omitempty"`
}
func (a *AlertMessage) GetSource() string {
if len(a.Source) == 0 {
return "unknown"
}
return a.Source
}
type ErrorMessage struct {
Header MessageHeader `json:"header,omitempty"`
Source string `json:"source,omitempty"`
Message string `json:"message,omitempty"`
}
type Text struct {
ID string `json:"id"`
Source string `json:"source,omitempty"`
Location string `json:"location,omitempty"`
TimeStamp time.Time `json:"timestamp"`
Host string `json:"host,omitempty"`
Severity AlertSeverity `json:"severity"`
Count int `json:"count,omitempty"`
Body string `json:"body"`
}
type Texts []Text
type TextMessage struct {
Header MessageHeader `json:"header,omitempty"`
Texts Texts `json:"texts,omitempty"`
}
type NetworkSourceType = string
//goland:noinspection GoUnusedConst
const (
NullSource NetworkSourceType = "" // Invalid Source ID
DockerSource NetworkSourceType = "docker" // Docker container ID
HostNameSource NetworkSourceType = "hostname" // Host name
IPAddressSource NetworkSourceType = "ipaddress" // IP Address
)
type Source struct {
Type NetworkSourceType `json:"type"`
Value string `json:"value,omitempty"`
Name string `json:"name,omitempty"`
Application string `json:"app,omitempty"`
}
type DeviceType = string
//goland:noinspection GoUnusedConst
const (
CameraDevice DeviceType = "camera" // Camera
SensorDevice DeviceType = "sensor" // Pressure Sensor
MotionDevice DeviceType = "motion" // Motion Sensor
SolarDevice DeviceType = "solar" // Solar System
)
type MotionMessage struct {
Header MessageHeader `json:"header,omitempty"`
Device DeviceType `json:"device,omitempty"`
Channel string `json:"channel,omitempty"`
TimeMs int64 `json:"time_ms,omitempty"`
Source Source `json:"source,omitempty"`
}
type TemperatureMessage struct {
Header MessageHeader `json:"header,omitempty"`
Celsius float32 `json:"celsius,omitempty"`
Humidity float32 `json:"humidity,omitempty"`
Fahrenheit float32 `json:"fahrenheit,omitempty"`
Time time.Time `json:"time,omitempty"`
}
type SuccessMessage struct {
Header MessageHeader `json:"header,omitempty"`
Message string `json:"message,omitempty"`
}
type ServiceStats map[string]string
type ServiceStatsMessage struct {
Header MessageHeader `json:"header,omitempty"`
Type DeviceType `json:"device_type,omitempty"`
DeviceName string `json:"device_name,omitempty"`
Stats ServiceStats `json:"stats,omitempty"`
}
type Regions []string
type WeatherAlertMessage struct {
Header MessageHeader `json:"header,omitempty"`
Message string `json:"message,omitempty"`
Expires time.Time `json:"expires,omitempty"`
Severity string `json:"severity,omitempty"`
Regions Regions `json:"Regions,omitempty"`
Id int64 `json:"id,omitempty"`
}
type AlarmMessage struct {
Header MessageHeader `json:"header,omitempty"`
}
type AlarmSensor struct {
Status string `json:"status,omitempty"`
Number string `json:"number,omitempty"`
Name string `json:"name,omitempty"`
Stamp int64 `json:"stamp,omitempty"`
Id string `json:"id,omitempty"`
}
type AlarmSensors map[string]AlarmSensor
type AlarmSensorsMessage struct {
Header MessageHeader `json:"header,omitempty"`
AlarmSensors AlarmSensors `json:"sensors,omitempty"`
Armed bool `json:"armed,omitempty"`
}
type AlarmSensorMessage struct {
Header MessageHeader `json:"header,omitempty"`
AlarmSensor AlarmSensor `json:"sensor,omitempty"`
Armed bool `json:"armed,omitempty"`
}
// ThrottleEntry is a time.Duration counter, starting at Min. After every call to
// the Duration method the current timing is multiplied by Factor, but it
// never exceeds Max.
type ThrottleEntry struct {
Count uint64 `json:"count,omitempty"`
Factor float64 `json:"factor,omitempty"`
Jitter bool `json:"jitter,omitempty"`
Min time.Duration `json:"min,omitempty"`
Max time.Duration `json:"max,omitempty"`
Stamp int64 `json:"stamp,omitempty"`
}
// Duration returns the duration for the current attempt before incrementing
// the attempt counter. See ForAttempt.
func (t *ThrottleEntry) Duration(minTime time.Duration, maxTime time.Duration) time.Duration {
d := t.ForAttempt(float64(atomic.AddUint64(&t.Count, 1)-1)-1, minTime, maxTime)
return d
}
const maxInt64 = float64(math.MaxInt64 - 512)
// ForAttempt returns the duration for a specific attempt. This is useful if
// you have a large number of independent ThrottleEntry, but you don't want to use
// unnecessary memory storing the back off parameters per back off. The first
// attempt should be 0.
func (t *ThrottleEntry) ForAttempt(attempt float64, minTime time.Duration, maxTime time.Duration) time.Duration {
// Zero-values are nonsensical, so we use
// them to apply defaults
minValue := t.Min
if minValue <= 0 {
minValue = minTime
}
maxValue := t.Max
if maxValue <= 0 {
maxValue = maxTime
}
if minValue >= maxValue {
// short-circuit
return maxValue
}
factor := t.Factor
if factor <= 0 {
factor = 2
}
//calculate this duration
minFloat := float64(minValue)
durationFloat := minFloat * math.Pow(factor, attempt)
if t.Jitter {
durationFloat = rand.Float64()*(durationFloat-minFloat) + minFloat
}
//ensure float64 won't overflow int64
if durationFloat > maxInt64 {
return maxValue
}
dur := time.Duration(durationFloat)
//keep within bounds
if dur < minValue {
return minValue
}
if dur > maxValue {
return maxValue
}
return dur
}
func (t *ThrottleEntry) Reset(minTime time.Duration, maxTime time.Duration) *ThrottleEntry {
t.Count = 0
t.Factor = 2
t.Jitter = false
t.Min = minTime
t.Max = maxTime
t.Stamp = time.Now().Unix()
return t
}
// Attempt returns the current attempt counter value.
func (t *ThrottleEntry) Attempt() uint64 {
return t.Count
}
// Copy returns a ThrottleEntry with equals constraints as the original
func (t *ThrottleEntry) Copy() *ThrottleEntry {
return &ThrottleEntry{
Count: t.Count,
Factor: t.Factor,
Jitter: t.Jitter,
Min: t.Min,
Max: t.Max,
Stamp: t.Stamp,
}
}
type ThrottleEntries []ThrottleEntry
type ThrottleEntriesMessage struct {
Header MessageHeader `json:"header,omitempty"`
ThrottleEntries ThrottleEntries `json:"entries,omitempty"`
Armed bool `json:"armed,omitempty"`
}
type SystemStatus string
const (
ONLINE SystemStatus = "ONLINE"
OFFLINE SystemStatus = "OFFLINE"
UNDEFINED SystemStatus = "UNDEFINED"
)
// noinspection GoUnusedExportedFunction
func ParseSystemState(state string) SystemStatus {
state = strings.ToUpper(state)
switch state {
case "ONLINE":
return ONLINE
case "OFFLINE":
return OFFLINE
}
return UNDEFINED
}
type SystemStatusMap map[string]SystemStatus
type SystemStatusMessage struct {
Header MessageHeader `json:"header,omitempty"`
SystemStatus SystemStatusMap `json:"message,omitempty"`
}
type DeviceState string
const (
ON DeviceState = "ON"
OFF DeviceState = "OFF"
UNKNOWN DeviceState = "UNKNOWN"
)
// noinspection GoUnusedExportedFunction
func ParseDeviceState(state string) DeviceState {
state = strings.ToUpper(state)
switch state {
case "ON":
return ON
case "OFF":
return OFF
}
return UNKNOWN
}
type LocationName string
type DeviceInfo struct {
Device string `json:"device,omitempty"`
State DeviceState `json:"state,omitempty"`
}
type DeviceInfoMap map[string]DeviceInfo
type DevicesInfoMessage struct {
Header MessageHeader `json:"header,omitempty"`
Devices DeviceInfoMap `json:"devices,omitempty"`
}
type UPSBattery struct {
Charge int `json:"charge,omitempty"`
ChargeLow int `json:"charge_low,omitempty"`
ChargeWarning int `json:"charge_warning,omitempty"`
Runtime int `json:"runtime,omitempty"`
RuntimeLow int `json:"runtime_low,omitempty"`
Type string `json:"type,omitempty"`
Voltage float32 `json:"voltage,omitempty"`
VoltageNominal float32 `json:"voltage_nominal,omitempty"`
}
type UPSDriver struct {
Name string `json:"name,omitempty"`
PollFreq int `json:"poll_freq,omitempty"`
PollInterval int `json:"poll_interval,omitempty"`
Port string `json:"port,omitempty"`
Synchronous bool `json:"synchronous,omitempty"`
Version string `json:"version,omitempty"`
VersionData string `json:"version_data,omitempty"`
VersionInternal string `json:"version_internal,omitempty"`
}
type UPSStatus struct {
Name string `json:"name,omitempty"`
Battery UPSBattery `json:"battery,omitempty"`
DeviceMfr string `json:"device_mfr,omitempty"`
DeviceModel string `json:"device_model,omitempty"`
DeviceType string `json:"device_type,omitempty"`
InputTransferHigh int `json:"input_transfer_high,omitempty"`
InputTransferLow int `json:"input_transfer_low,omitempty"`
InputVoltage float32 `json:"input_voltage,omitempty"`
InputVoltageNominal float32 `json:"input_voltage_nominal,omitempty"`
OutputVoltage float32 `json:"output_voltage,omitempty"`
BeeperStatus bool `json:"beeper_status,omitempty"`
DelayShutdown int `json:"delay_shutdown,omitempty"`
DelayStart int `json:"delay_start,omitempty"`
Load int `json:"load,omitempty"`
Mfr string `json:"mfr,omitempty"`
Model string `json:"model,omitempty"`
ProductId string `json:"product_id,omitempty"`
RealPowerNominal int `json:"real_power_nominal,omitempty"`
Status string `json:"status,omitempty"`
TestResult string `json:"test_result,omitempty"`
TimerShutdown int `json:"timer_shutdown,omitempty"`
TimerStart int `json:"timer_start,omitempty"`
VendorId string `json:"vendor_id,omitempty"`
}
type UPSStatusMessage struct {
Header MessageHeader `json:"header,omitempty"`
Sources []UPSStatus `json:"sources,omitempty"`
}
type KasaListMessage struct {
Header MessageHeader `json:"header,omitempty"`
Devices interface{} `json:"devices,omitempty"`
}
type KasaSetMessage struct {
Header MessageHeader `json:"header,omitempty"`
Alias string `json:"alias,omitempty"`
State bool `json:"state,omitempty"`
}
type ServiceMemory struct {
MaxUsage uint64 `json:"max_usage,omitempty"`
Usage uint64 `json:"usage,omitempty"`
Limit uint64 `json:"limit,omitempty"`
Commit uint64 `json:"commitbytes,omitempty"`
CommitPeak uint64 `json:"commitpeakbytes,omitempty"`
PrivateWorkingSet uint64 `json:"privateworkingset,omitempty"`
}
type ServiceNetworkStats struct {
RxDropped uint64 `json:"rx_dropped,omitempty"`
RxBytes uint64 `json:"rx_bytes,omitempty"`
RxErrors uint64 `json:"rx_errors,omitempty"`
TxPackets uint64 `json:"tx_packets,omitempty"`
TxDropped uint64 `json:"tx_dropped,omitempty"`
RxPackets uint64 `json:"rx_packets,omitempty"`
TxErrors uint64 `json:"tx_errors,omitempty"`
TxBytes uint64 `json:"tx_bytes,omitempty"`
}
type Service struct {
ID string `json:"id,omitempty"`
TTL time.Duration `json:"ttl,omitempty"`
TTLStamp time.Time `json:"ttl_stamp,omitempty"`
Name string `json:"name,omitempty"`
Attrs map[string]string `json:"attrs,omitempty"`
Status string `json:"status,omitempty"`
Hostname string `json:"hostname,omitempty"`
HostIP string `json:"host_ip,omitempty"`
Ports map[string]ServicePort `json:"origin,omitempty"`
RestartCount int `json:"restart_count,omitempty"`
Platform string `json:"platform,omitempty"`
Memory ServiceMemory `json:"memory,omitempty"`
Networks map[string]ServiceNetworkStats `json:"networks,omitempty"`
}
type Services []Service
type ServicePort struct {
HostPort string `json:"host_port,omitempty"`
HostIP string `json:"host_ip,omitempty"`
ExposedPort string `json:"exposed_port,omitempty"`
ExposedIP string `json:"exposed_ip,omitempty"`
PortType string `json:"port_type,omitempty"`
}
// noinspection GoUnusedConst
const (
ServiceEventStart = "start"
ServiceEventStop = "stop"
ServiceEventActive = "active"
ServiceEventVanished = "vanish"
)
type ServiceMessage struct {
Header MessageHeader `json:"header,omitempty"`
ServiceEvent string `json:"event,omitempty"`
Service Service `json:"service,omitempty"`
}
type ServiceListMessage struct {
Header MessageHeader `json:"header,omitempty"`
Services Services `json:"services,omitempty"`
}
type Observation struct {
StationID string `json:"stationID,omitempty"`
Name string `json:"name,omitempty"`
ObsTimeUtc time.Time `json:"obsTimeUtc,omitempty"`
ObsTimeLocal string `json:"obsTimeLocal,omitempty"`
Neighborhood string `json:"neighborhood,omitempty"`
SoftwareType string `json:"softwareType,omitempty"`
Country string `json:"country,omitempty"`
SolarRadiation string `json:"solarRadiation,omitempty"`
Lon float64 `json:"longitude,omitempty"`
RealtimeFrequency string `json:"realtimeFrequency,omitempty"`
Epoch int `json:"epoch,omitempty"`
Lat float64 `json:"latitude,omitempty"`
Uv float64 `json:"uv,omitempty"`
Winddir int `json:"winddir,omitempty"`
Humidity int `json:"humidity,omitempty"`
QcStatus int `json:"qcStatus,omitempty"`
Imperial struct {
Temp int `json:"temp,omitempty"`
HeatIndex int `json:"heatIndex,omitempty"`
Dewpt int `json:"dewpt,omitempty"`
WindChill int `json:"windChill,omitempty"`
WindSpeed int `json:"windSpeed,omitempty"`
WindGust int `json:"windGust,omitempty"`
Pressure float64 `json:"pressure,omitempty"`
PrecipRate float64 `json:"precipRate,omitempty"`
PrecipTotal float64 `json:"precipTotal,omitempty"`
Elev int `json:"elev,omitempty"`
} `json:"imperial,omitempty"`
}
type Observations []Observation
type WeatherMessage struct {
Header MessageHeader `json:"header,omitempty"`
Observations Observations `json:"observations,omitempty"`
}
// ForecastPoints holds the JSON values from /points/<lat,lon>
type ForecastPoints struct {
ID string `json:"@id,omitempty"`
CWA string `json:"cwa,omitempty"`
Office string `json:"forecastOffice,omitempty"`
GridX int64 `json:"gridX,omitempty"`
GridY int64 `json:"gridY,omitempty"`
EndpointForecast string `json:"forecast,omitempty"`
EndpointForecastHourly string `json:"forecastHourly,omitempty"`
EndpointObservationStations string `json:"observationStations,omitempty"`
EndpointForecastGridData string `json:"forecastGridData,omitempty"`
Timezone string `json:"timeZone,omitempty"`
RadarStation string `json:"radarStation,omitempty"`
}
// WeatherForecast holds the JSON values from /gridpoints/<cwa>/<x,y>/forecast
type WeatherForecast struct {
// capture data from the forecast
Updated string `json:"updated,omitempty"`
Units string `json:"units,omitempty"`
Elevation struct {
Value float64 `json:"value,omitempty"`
Units string `json:"unitCode,omitempty"`
} `json:"elevation"`
Periods []struct {
ID int32 `json:"number,omitempty"`
Name string `json:"name,omitempty"`
StartTime string `json:"startTime,omitempty"`
EndTime string `json:"endTime,omitempty"`
IsDaytime bool `json:"isDaytime,omitempty"`
Temperature float64 `json:"temperature,omitempty"`
TemperatureUnit string `json:"temperatureUnit,omitempty"`
WindSpeed string `json:"windSpeed,omitempty"`
WindDirection string `json:"windDirection,omitempty"`
Summary string `json:"shortForecast,omitempty"`
Details string `json:"detailedForecast,omitempty"`
} `json:"periods,omitempty"`
Point *ForecastPoints
}
type ForecastMessage struct {
Header MessageHeader `json:"header,omitempty"`
Forecast WeatherForecast `json:"forecast,omitempty"`
}
// ForecastStations holds the JSON values from /points/<lat,lon>/stations
type ForecastStations struct {
Stations []string `json:"observationStations,omitempty"`
}
type ForecastStationsMessage struct {
Header MessageHeader `json:"header,omitempty"`
Stations ForecastStations `json:"stations,omitempty"`
}
// ForecastGridpoint holds the JSON values from /gridpoints/<cwa>/<x,y>
// See https://weather-gov.github.io/api/gridpoints for information.
type ForecastGridpoint struct {
// capture data from the forecast
Updated string `json:"updateTime,omitempty"`
Elevation struct {
Value float64 `json:"value,omitempty"`
Units string `json:"unitCode,omitempty"`
} `json:"elevation,omitempty"`
Weather struct {
Values []struct {
ValidTime string `json:"validTime,omitempty"` // ISO 8601 time interval, e.g. 2019-07-04T18:00:00+00:00/PT3H
Value []struct {
Coverage string `json:"coverage,omitempty"`
Weather string `json:"weather,omitempty"`
Intensity string `json:"intensity,omitempty"`
} `json:"value,omitempty"`
} `json:"values,omitempty"`
} `json:"weather,omitempty"`
Hazards struct {
Values []struct {
ValidTime string `json:"validTime,omitempty"` // ISO 8601 time interval, e.g. 2019-07-04T18:00:00+00:00/PT3H
Value []struct {
Phenomenon string `json:"phenomenon,omitempty"`
Significance string `json:"significance,omitempty"`
EventNumber int32 `json:"event_number,omitempty"`
} `json:"value,omitempty"`
} `json:"values,omitempty"`
} `json:"hazards,omitempty"`
Temperature ForecastGridpointTimeSeries `json:"temperature,omitempty"`
Dewpoint ForecastGridpointTimeSeries `json:"dewpoint,omitempty"`
MaxTemperature ForecastGridpointTimeSeries `json:"maxTemperature"`
MinTemperature ForecastGridpointTimeSeries `json:"minTemperature,omitempty"`
RelativeHumidity ForecastGridpointTimeSeries `json:"relativeHumidity,omitempty"`
ApparentTemperature ForecastGridpointTimeSeries `json:"apparentTemperature,omitempty"`
HeatIndex ForecastGridpointTimeSeries `json:"heatIndex,omitempty"`
WindChill ForecastGridpointTimeSeries `json:"windChill,omitempty"`
SkyCover ForecastGridpointTimeSeries `json:"skyCover,omitempty"`
WindDirection ForecastGridpointTimeSeries `json:"windDirection,omitempty"`
WindSpeed ForecastGridpointTimeSeries `json:"windSpeed,omitempty"`
WindGust ForecastGridpointTimeSeries `json:"windGust,omitempty"`
ProbabilityOfPrecipitation ForecastGridpointTimeSeries `json:"probabilityOfPrecipitation,omitempty"`
QuantitativePrecipitation ForecastGridpointTimeSeries `json:"quantitativePrecipitation,omitempty"`
IceAccumulation ForecastGridpointTimeSeries `json:"iceAccumulation,omitempty"`
SnowfallAmount ForecastGridpointTimeSeries `json:"snowfallAmount,omitempty"`
SnowLevel ForecastGridpointTimeSeries `json:"snowLevel,omitempty"`
CeilingHeight ForecastGridpointTimeSeries `json:"ceilingHeight,omitempty"`
Visibility ForecastGridpointTimeSeries `json:"visibility,omitempty"`
TransportWindSpeed ForecastGridpointTimeSeries `json:"transportWindSpeed,omitempty"`
TransportWindDirection ForecastGridpointTimeSeries `json:"transportWindDirection,omitempty"`
MixingHeight ForecastGridpointTimeSeries `json:"mixingHeight,omitempty"`
HainesIndex ForecastGridpointTimeSeries `json:"hainesIndex,omitempty"`
LightningActivityLevel ForecastGridpointTimeSeries `json:"lightningActivityLevel,omitempty"`
TwentyFootWindSpeed ForecastGridpointTimeSeries `json:"twentyFootWindSpeed,omitempty"`
TwentyFootWindDirection ForecastGridpointTimeSeries `json:"twentyFootWindDirection,omitempty"`
WaveHeight ForecastGridpointTimeSeries `json:"waveHeight,omitempty"`
WavePeriod ForecastGridpointTimeSeries `json:"wavePeriod,omitempty"`
WaveDirection ForecastGridpointTimeSeries `json:"waveDirection,omitempty"`
PrimarySwellHeight ForecastGridpointTimeSeries `json:"primarySwellHeight,omitempty"`
PrimarySwellDirection ForecastGridpointTimeSeries `json:"primarySwellDirection,omitempty"`
SecondarySwellHeight ForecastGridpointTimeSeries `json:"secondarySwellHeight,omitempty"`
SecondarySwellDirection ForecastGridpointTimeSeries `json:"secondarySwellDirection,omitempty"`
WavePeriod2 ForecastGridpointTimeSeries `json:"wavePeriod2,omitempty"`
WindWaveHeight ForecastGridpointTimeSeries `json:"windWaveHeight,omitempty"`
DispersionIndex ForecastGridpointTimeSeries `json:"dispersionIndex,omitempty"`
Pressure ForecastGridpointTimeSeries `json:"pressure,omitempty"`
ProbabilityOfTropicalStormWinds ForecastGridpointTimeSeries `json:"probabilityOfTropicalStormWinds,omitempty"`
ProbabilityOfHurricaneWinds ForecastGridpointTimeSeries `json:"probabilityOfHurricaneWinds,omitempty"`
PotentialOf15mphWinds ForecastGridpointTimeSeries `json:"potentialOf15mphWinds,omitempty"`
PotentialOf25mphWinds ForecastGridpointTimeSeries `json:"potentialOf25mphWinds,omitempty"`
PotentialOf35mphWinds ForecastGridpointTimeSeries `json:"potentialOf35mphWinds,omitempty"`
PotentialOf45mphWinds ForecastGridpointTimeSeries `json:"potentialOf45mphWinds,omitempty"`
PotentialOf20mphWindGusts ForecastGridpointTimeSeries `json:"potentialOf20mphWindGusts,omitempty"`
PotentialOf30mphWindGusts ForecastGridpointTimeSeries `json:"potentialOf30mphWindGusts,omitempty"`
PotentialOf40mphWindGusts ForecastGridpointTimeSeries `json:"potentialOf40mphWindGusts,omitempty"`
PotentialOf50mphWindGusts ForecastGridpointTimeSeries `json:"potentialOf50mphWindGusts,omitempty"`
PotentialOf60mphWindGusts ForecastGridpointTimeSeries `json:"potentialOf60mphWindGusts,omitempty"`
GrasslandFireDangerIndex ForecastGridpointTimeSeries `json:"grasslandFireDangerIndex,omitempty"`
ProbabilityOfThunder ForecastGridpointTimeSeries `json:"probabilityOfThunder,omitempty"`
DavisStabilityIndex ForecastGridpointTimeSeries `json:"davisStabilityIndex,omitempty"`
AtmosphericDispersionIndex ForecastGridpointTimeSeries `json:"atmosphericDispersionIndex,omitempty"`
LowVisibilityOccurrenceRiskIndex ForecastGridpointTimeSeries `json:"lowVisibilityOccurrenceRiskIndex,omitempty"`
Stability ForecastGridpointTimeSeries `json:"stability,omitempty"`
RedFlagThreatIndex ForecastGridpointTimeSeries `json:"redFlagThreatIndex,omitempty"`
Point ForecastPoints
}
// ForecastGridpointTimeSeries holds a series of data from a gridpoint forecast
type ForecastGridpointTimeSeries struct {
Uom string `json:"uom"` // Unit of Measure
Values []struct {
ValidTime string `json:"validTime,omitempty"` // ISO 8601 time interval, e.g. 2019-07-04T18:00:00+00:00/PT3H
Value float64 `json:"value,omitempty"`
} `json:"values,omitempty"`
}
type ForecastGridpointMessage struct {
Header MessageHeader `json:"header,omitempty"`
Forecast ForecastGridpoint `json:"grid_forecast,omitempty"`
}
type DaylightDate struct {
Hours int `json:"hours,omitempty"`
Sunrise time.Time `json:"sunrise,omitempty"`
Sunset time.Time `json:"sunset,omitempty"`
}
type DaylightDates []DaylightDate
type DaylightMessage struct {
Header MessageHeader `json:"header,omitempty"`
DayLightDays DaylightDates `json:"days,omitempty"`
}
//goland:noinspection GoUnusedConst
const (
stateActive = "active"
stateHarvested = "harvested"
stateInactive = "destroyed"
phaseVegetative = "vegetative"
phaseFlowering = "flowering"
operationInsert = "insert"
operationUpsert = "upsert"
)
type Plant struct {
Id string `json:"id,omitempty"`
Tag string `json:"tag"`
Strain string `json:"strain"`
Location string `json:"location"`
Phase string `json:"phase"`
State string `json:"state"`
Group string `json:"group"`
GroupType string `json:"groupType"`
Audit bool `json:"audit"`
Bed string `json:"bed"`
GroupDate time.Time `json:"groupDate"`
CrateDate time.Time `json:"createDate"`
UpdateDate time.Time `json:"updateDate"`
SyncDate time.Time `json:"syncDate"`
}
type Plants []Plant
type PlantMessage struct {
Header MessageHeader `json:"header,omitempty"`
Plant Plant `json:"plant,omitempty"`
}
type PlantsMessage struct {
Header MessageHeader `json:"header,omitempty"`
Plants Plants `json:"plants,omitempty"`
}
type Tag struct {
Tag string `json:"tag,omitempty"`
Strain string `json:"strain,omitempty"`
Location string `json:"location,omitempty"`
Bed string `json:"bed,omitempty"`
Phase string `json:"phase,omitempty"`
State string `json:"state,omitempty"`
Audit bool `json:"audit,omitempty"`
}
type Tags []Tag
type TagsMessage struct {
Header MessageHeader `json:"header,omitempty"`
FloweringTags Tags `json:"floweringTags,omitempty"`
VegetativeTags Tags `json:"vegetativeTags,omitempty"`
DestroyedTags Tags `json:"destroyedTags,omitempty"`
HarvestedTags Tags `json:"harvestedTags,omitempty"`
}
type PlantNote struct {
Id string `json:"id,omitempty"`
Tag string `json:"tag,omitempty"`
Title string `json:"title,omitempty"`
Body string `json:"body,omitempty"`
CreateDate time.Time `json:"createDate,omitempty"`
UpdateDate time.Time `json:"updateDate,omitempty"`
}
type PlantNotes []PlantNote
type PlantNoteMessage struct {
Header MessageHeader `json:"header,omitempty"`
Note PlantNote `json:"note,omitempty"`
}
type PlantNotesMessage struct {
Header MessageHeader `json:"header,omitempty"`
Notes PlantNotes `json:"notes,omitempty"`
}
type LoginMessage struct {
Header MessageHeader `json:"header,omitempty"`
Settings map[string]string `json:"settings,omitempty"`
}
type BedsMessage struct {
Header MessageHeader `json:"header,omitempty"`
Beds map[string][]string `json:"beds,omitempty"`
}
type PurpleAirData struct {
APIVersion string `json:"api_version"`
TimeStamp int `json:"time_stamp"`
DataTimeStamp int `json:"data_time_stamp"`
Sensor struct {
SensorIndex int `json:"sensor_index"`
LastModified int `json:"last_modified"`
DateCreated int `json:"date_created"`
LastSeen int `json:"last_seen"`
Private int `json:"private"`
IsOwner int `json:"is_owner"`
Name string `json:"name"`
Icon int `json:"icon"`
LocationType int `json:"location_type"`
Model string `json:"model"`
Hardware string `json:"hardware"`
LedBrightness int `json:"led_brightness"`
FirmwareVersion string `json:"firmware_version"`
Rssi int `json:"rssi"`
Uptime int `json:"uptime"`
PaLatency int `json:"pa_latency"`
Memory int `json:"memory"`
PositionRating int `json:"position_rating"`
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
Altitude int `json:"altitude"`
ChannelState int `json:"channel_state"`
ChannelFlags int `json:"channel_flags"`
ChannelFlagsManual int `json:"channel_flags_manual"`
ChannelFlagsAuto int `json:"channel_flags_auto"`
Confidence int `json:"confidence"`
ConfidenceAuto int `json:"confidence_auto"`
ConfidenceManual int `json:"confidence_manual"`
Humidity int `json:"humidity"`
HumidityA int `json:"humidity_a"`
Temperature int `json:"temperature"`
TemperatureA int `json:"temperature_a"`
Pressure float64 `json:"pressure"`
PressureA float64 `json:"pressure_a"`
AnalogInput float64 `json:"analog_input"`
Pm10 float64 `json:"pm1.0"`
Pm10A float64 `json:"pm1.0_a"`
Pm10B float64 `json:"pm1.0_b"`
Pm25 float64 `json:"pm2.5"`
Pm25A float64 `json:"pm2.5_a"`
Pm25B float64 `json:"pm2.5_b"`
Pm25Alt float64 `json:"pm2.5_alt"`
Pm25AltA float64 `json:"pm2.5_alt_a"`
Pm25AltB float64 `json:"pm2.5_alt_b"`
Pm100 float64 `json:"pm10.0"`
Pm100A float64 `json:"pm10.0_a"`
Pm100B float64 `json:"pm10.0_b"`
Zero3UmCount int `json:"0.3_um_count"`
Zero3UmCountA int `json:"0.3_um_count_a"`
Zero3UmCountB int `json:"0.3_um_count_b"`
Zero5UmCount int `json:"0.5_um_count"`
Zero5UmCountA int `json:"0.5_um_count_a"`
Zero5UmCountB int `json:"0.5_um_count_b"`
One0UmCount int `json:"1.0_um_count"`
One0UmCountA int `json:"1.0_um_count_a"`
One0UmCountB int `json:"1.0_um_count_b"`
Two5UmCount int `json:"2.5_um_count"`
Two5UmCountA int `json:"2.5_um_count_a"`
Two5UmCountB int `json:"2.5_um_count_b"`
Five0UmCount int `json:"5.0_um_count"`
Five0UmCountA int `json:"5.0_um_count_a"`
Five0UmCountB int `json:"5.0_um_count_b"`
One00UmCount int `json:"10.0_um_count"`
One00UmCountA int `json:"10.0_um_count_a"`
One00UmCountB int `json:"10.0_um_count_b"`
Pm10Cf1 float64 `json:"pm1.0_cf_1"`
Pm10Cf1A float64 `json:"pm1.0_cf_1_a"`
Pm10Cf1B float64 `json:"pm1.0_cf_1_b"`
Pm10Atm float64 `json:"pm1.0_atm"`
Pm10AtmA float64 `json:"pm1.0_atm_a"`
Pm10AtmB float64 `json:"pm1.0_atm_b"`
Pm25Atm float64 `json:"pm2.5_atm"`
Pm25AtmA float64 `json:"pm2.5_atm_a"`
Pm25AtmB float64 `json:"pm2.5_atm_b"`
Pm25Cf1 float64 `json:"pm2.5_cf_1"`
Pm25Cf1A float64 `json:"pm2.5_cf_1_a"`
Pm25Cf1B float64 `json:"pm2.5_cf_1_b"`
Pm100Atm float64 `json:"pm10.0_atm"`
Pm100AtmA float64 `json:"pm10.0_atm_a"`
Pm100AtmB float64 `json:"pm10.0_atm_b"`
Pm100Cf1 float64 `json:"pm10.0_cf_1"`
Pm100Cf1A float64 `json:"pm10.0_cf_1_a"`
Pm100Cf1B float64 `json:"pm10.0_cf_1_b"`
PrimaryIDA int `json:"primary_id_a"`
PrimaryKeyA string `json:"primary_key_a"`
PrimaryIDB int `json:"primary_id_b"`
PrimaryKeyB string `json:"primary_key_b"`
SecondaryIDA int `json:"secondary_id_a"`
SecondaryKeyA string `json:"secondary_key_a"`
SecondaryIDB int `json:"secondary_id_b"`
SecondaryKeyB string `json:"secondary_key_b"`
Stats struct {
Pm25 float64 `json:"pm2.5"`
Pm2510Minute float64 `json:"pm2.5_10minute"`
Pm2530Minute float64 `json:"pm2.5_30minute"`
Pm2560Minute float64 `json:"pm2.5_60minute"`
Pm256Hour float64 `json:"pm2.5_6hour"`
Pm2524Hour float64 `json:"pm2.5_24hour"`
Pm251Week float64 `json:"pm2.5_1week"`
TimeStamp int `json:"time_stamp"`
} `json:"stats"`
StatsA struct {
Pm25 float64 `json:"pm2.5"`
Pm2510Minute float64 `json:"pm2.5_10minute"`
Pm2530Minute float64 `json:"pm2.5_30minute"`
Pm2560Minute float64 `json:"pm2.5_60minute"`
Pm256Hour float64 `json:"pm2.5_6hour"`
Pm2524Hour float64 `json:"pm2.5_24hour"`
Pm251Week float64 `json:"pm2.5_1week"`
TimeStamp int `json:"time_stamp"`
} `json:"stats_a"`
StatsB struct {
Pm25 float64 `json:"pm2.5"`
Pm2510Minute float64 `json:"pm2.5_10minute"`
Pm2530Minute float64 `json:"pm2.5_30minute"`
Pm2560Minute float64 `json:"pm2.5_60minute"`
Pm256Hour float64 `json:"pm2.5_6hour"`
Pm2524Hour float64 `json:"pm2.5_24hour"`
Pm251Week float64 `json:"pm2.5_1week"`
TimeStamp int `json:"time_stamp"`
} `json:"stats_b"`
} `json:"sensor"`
}
type PurpleAirMessage struct {
Header MessageHeader `json:"header,omitempty"`
Data PurpleAirData `json:"data,omitempty"`
}
type BuildRequestType string
//goland:noinspection GoUnusedConst
const (
BuildQuery BuildRequestType = "query"
BuildSync BuildRequestType = "sync"
BuildMake BuildRequestType = "make"
BuildPush BuildRequestType = "push"
BuildConstruct BuildRequestType = "construct"
)
type BuildHeader struct {
BuildId string `json:"buildId,omitempty"`
GitStashId string `json:"gitStashId,omitempty"`
}
type BuildRequestMessage struct {
Header MessageHeader `json:"header,omitempty"`
Build BuildHeader `json:"build,omitempty"`
Type BuildRequestType `json:"type,omitempty"`
}
type BuildResponseMessage struct {
Header MessageHeader `json:"header,omitempty"`
Build BuildHeader `json:"build,omitempty"`
Type BuildRequestType `json:"type,omitempty"`
Platform string `json:"platform,omitempty"`
Body string `json:"body,omitempty"`
}
type StatusMessage struct {
Header MessageHeader `json:"header,omitempty"`
States map[string]bool `json:"states,omitempty"`
}
type BleManufacturerData struct {
CompanyId uint16 `json:"company_id,omitempty"`
Name string `json:"name,omitempty"`
Services []string `json:"services,omitempty"`
Data []byte `json:"data,omitempty"`
}
type BleAdvertisementPayload struct {
LocalName string `json:"localName,omitempty"`
ManufacturerData []BleManufacturerData `json:"companies,omitempty"`
}
type BleDevice struct {
Address string `json:"address,omitempty"`
RSSI int16 `json:"rssi,omitempty"`
Name string `json:"name,omitempty"`
Advertisement BleAdvertisementPayload `json:"advertisement,omitempty"`
}
type BleAdvertisementMessage struct {
Header MessageHeader `json:"header,omitempty"`
Device BleDevice `json:"device,omitempty"`
}
// noinspection GoUnusedExportedFunction
func CreateHeader(status int, location string) MessageHeader {
// Do we have a build version?
//
var build BuildVersion
buildBytes, err := os.ReadFile("/opt/build_version.json")
if err == nil {
err = json.Unmarshal(buildBytes, &build)
log.Println("[INFO] Reading version: ", string(buildBytes))
} else {
log.Println("[ERROR] Unable to read /opt/build_version.json file:", err)
}
// Build Message Header
//
return MessageHeader{
Status: status,
Location: location,
TimeStamp: time.Now(),
Host: GetHostName(),
Build: build,
}
}