Compare commits
5 commits
fd3cae1866
...
a53a5c3517
| Author | SHA1 | Date | |
|---|---|---|---|
| a53a5c3517 | |||
| de506fc8f3 | |||
| a163ba1deb | |||
| 4540fc0c59 | |||
| b054b02be6 |
12 changed files with 333 additions and 201 deletions
9
.editorconfig
Normal file
9
.editorconfig
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.json]
|
||||||
|
indent_style = tab
|
||||||
|
tab_width = 4
|
||||||
11
README.md
11
README.md
|
|
@ -6,7 +6,8 @@
|
||||||
$ curl http://localhost:8080 | jq
|
$ curl http://localhost:8080 | jq
|
||||||
{
|
{
|
||||||
"api_compatibility": [
|
"api_compatibility": [
|
||||||
"14"
|
"14",
|
||||||
|
"15"
|
||||||
],
|
],
|
||||||
"space": "CCCHH",
|
"space": "CCCHH",
|
||||||
...
|
...
|
||||||
|
|
@ -15,16 +16,16 @@ $ curl http://localhost:8080 | jq
|
||||||
|
|
||||||
## Configuring
|
## Configuring
|
||||||
|
|
||||||
spaceapid has to be configured via one or multiple json files.
|
`spaceapid` has to be configured via one or multiple json files.
|
||||||
A sample configuration is provided as [config-template.json](./config-template.json).
|
A sample configuration is provided as [config-template.json](./config-template.json).
|
||||||
The config consists of three parts:
|
The config consists of three parts:
|
||||||
|
|
||||||
- `"credentials"`
|
- `"credentials"`
|
||||||
- List of Username/Password credentials for HTTP BasicAuth
|
- List of Username/Password credentials for HTTP BasicAuth
|
||||||
- `"dynamic"`
|
- `"dynamic"`
|
||||||
- The configuration for the dynamic parts of the message
|
- The dynamic parts of the message
|
||||||
- `"response"`
|
- `"static"`
|
||||||
- The static (pre-filled) parts of the response
|
- The static (pre-filled) parts of the message
|
||||||
|
|
||||||
See [Running](#Running) for details.
|
See [Running](#Running) for details.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,9 +66,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"response": {
|
"static": {
|
||||||
"api_compatibility": [
|
"api_compatibility": [
|
||||||
"14"
|
"14",
|
||||||
|
"15"
|
||||||
],
|
],
|
||||||
"space": "CCCHH",
|
"space": "CCCHH",
|
||||||
"logo": "https://hamburg.ccc.de/images/logo.svg",
|
"logo": "https://hamburg.ccc.de/images/logo.svg",
|
||||||
|
|
|
||||||
|
|
@ -86,9 +86,9 @@ func ParseConfiguration() (conf SpaceapidConfig) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if compatible with v14
|
// Sanity check: Config should declare compatibility with current SpaceAPI message version
|
||||||
if !slices.Contains(conf.Response.APICompatibility, "14") {
|
if !slices.Contains(conf.Response.APICompatibility, types.CurrentMessageVersion) {
|
||||||
log.Fatalln("Provided file doesn't specify compatibility with API version 14")
|
log.Fatalln("Provided config doesn't specify compatibility with current API version", types.CurrentMessageVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize fields for environment sensors
|
// Initialize fields for environment sensors
|
||||||
|
|
|
||||||
|
|
@ -34,5 +34,5 @@ type SpaceapidConfig struct {
|
||||||
// The dynamic part of the spaceapi JSON
|
// The dynamic part of the spaceapi JSON
|
||||||
Dynamic DynamicStateConfig `json:"dynamic"`
|
Dynamic DynamicStateConfig `json:"dynamic"`
|
||||||
// The static part of the spaceapi JSON
|
// The static part of the spaceapi JSON
|
||||||
Response types.SpaceAPIResponseV14 `json:"response"`
|
Response types.SpaceAPIResponse `json:"static"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"git.hamburg.ccc.de/ccchh/spaceapid/types"
|
"git.hamburg.ccc.de/ccchh/spaceapid/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Root(resp *types.SpaceAPIResponseV14) func(http.ResponseWriter, *http.Request) {
|
func Root(resp *types.SpaceAPIResponse) func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
// Check if GET method
|
// Check if GET method
|
||||||
if r.Method != http.MethodGet {
|
if r.Method != http.MethodGet {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"git.hamburg.ccc.de/ccchh/spaceapid/types"
|
"git.hamburg.ccc.de/ccchh/spaceapid/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func EnvironmentSensor(
|
func EnvironmentSensorPUT(
|
||||||
authDB config.HTTPBACredentials, validCredentials []config.HTTPBACredentialID,
|
authDB config.HTTPBACredentials, validCredentials []config.HTTPBACredentialID,
|
||||||
resp *types.EnvironmentSensor,
|
resp *types.EnvironmentSensor,
|
||||||
) func(http.ResponseWriter, *http.Request) {
|
) func(http.ResponseWriter, *http.Request) {
|
||||||
|
|
@ -35,3 +35,20 @@ func EnvironmentSensor(
|
||||||
resp.LastChange = time.Now().Unix()
|
resp.LastChange = time.Now().Unix()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func EnvironmentSensorDELETE(
|
||||||
|
authDB config.HTTPBACredentials, validCredentials []config.HTTPBACredentialID,
|
||||||
|
resp *types.EnvironmentSensor,
|
||||||
|
) func(http.ResponseWriter, *http.Request) {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
_, err := updateEndpointValidator(authDB, validCredentials, w, r)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set SpaceAPI response values
|
||||||
|
resp.Value = 0
|
||||||
|
resp.LastChange = time.Now().Unix()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import (
|
||||||
|
|
||||||
func StateOpen(
|
func StateOpen(
|
||||||
authDB config.HTTPBACredentials, validCredentials []config.HTTPBACredentialID,
|
authDB config.HTTPBACredentials, validCredentials []config.HTTPBACredentialID,
|
||||||
resp *types.SpaceState,
|
resp *types.SpaceAPIState,
|
||||||
) func(http.ResponseWriter, *http.Request) {
|
) func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
body, err := updateEndpointValidator(authDB, validCredentials, w, r)
|
body, err := updateEndpointValidator(authDB, validCredentials, w, r)
|
||||||
|
|
@ -37,7 +37,7 @@ func StateOpen(
|
||||||
|
|
||||||
func StateMessagePUT(
|
func StateMessagePUT(
|
||||||
authDB config.HTTPBACredentials, validCredentials []config.HTTPBACredentialID,
|
authDB config.HTTPBACredentials, validCredentials []config.HTTPBACredentialID,
|
||||||
resp *types.SpaceState,
|
resp *types.SpaceAPIState,
|
||||||
) func(http.ResponseWriter, *http.Request) {
|
) func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
body, err := updateEndpointValidator(authDB, validCredentials, w, r)
|
body, err := updateEndpointValidator(authDB, validCredentials, w, r)
|
||||||
|
|
@ -54,7 +54,7 @@ func StateMessagePUT(
|
||||||
|
|
||||||
func StateMessageDELETE(
|
func StateMessageDELETE(
|
||||||
authDB config.HTTPBACredentials, validCredentials []config.HTTPBACredentialID,
|
authDB config.HTTPBACredentials, validCredentials []config.HTTPBACredentialID,
|
||||||
resp *types.SpaceState,
|
resp *types.SpaceAPIState,
|
||||||
) func(http.ResponseWriter, *http.Request) {
|
) func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
_, err := updateEndpointValidator(authDB, validCredentials, w, r)
|
_, err := updateEndpointValidator(authDB, validCredentials, w, r)
|
||||||
|
|
|
||||||
17
main.go
17
main.go
|
|
@ -25,6 +25,9 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
if version == "" {
|
||||||
|
version = "unknown"
|
||||||
|
}
|
||||||
log.Println("SpaceAPId version", version)
|
log.Println("SpaceAPId version", version)
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
@ -43,7 +46,7 @@ func main() {
|
||||||
// Register signal handler
|
// Register signal handler
|
||||||
sc := make(chan os.Signal, 1)
|
sc := make(chan os.Signal, 1)
|
||||||
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM)
|
||||||
go func(resp *types.SpaceAPIResponseV14) {
|
go func(resp *types.SpaceAPIResponse) {
|
||||||
<-sc
|
<-sc
|
||||||
log.Println("Saving state and shutting down...")
|
log.Println("Saving state and shutting down...")
|
||||||
persistence.SaveCurrentState(*resp)
|
persistence.SaveCurrentState(*resp)
|
||||||
|
|
@ -68,12 +71,18 @@ func main() {
|
||||||
// Register handlers for environmental sensors
|
// Register handlers for environmental sensors
|
||||||
for sensorType, envSensorConfigs := range conf.Dynamic.Sensors {
|
for sensorType, envSensorConfigs := range conf.Dynamic.Sensors {
|
||||||
for i, envSensorConfig := range envSensorConfigs {
|
for i, envSensorConfig := range envSensorConfigs {
|
||||||
urlPattern := "PUT " + util.GetSensorURLPath(
|
urlPattern := util.GetSensorURLPath(
|
||||||
sensorType, envSensorConfig.SensorData.Location, envSensorConfig.SensorData.Name,
|
sensorType, envSensorConfig.SensorData.Location, envSensorConfig.SensorData.Name,
|
||||||
)
|
)
|
||||||
http.HandleFunc(
|
http.HandleFunc(
|
||||||
urlPattern,
|
"PUT "+urlPattern,
|
||||||
handlers.EnvironmentSensor(
|
handlers.EnvironmentSensorPUT(
|
||||||
|
conf.Credentials, envSensorConfig.AllowedCredentials, &conf.Response.Sensors[sensorType][i],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
http.HandleFunc(
|
||||||
|
"DELETE "+urlPattern,
|
||||||
|
handlers.EnvironmentSensorDELETE(
|
||||||
conf.Credentials, envSensorConfig.AllowedCredentials, &conf.Response.Sensors[sensorType][i],
|
conf.Credentials, envSensorConfig.AllowedCredentials, &conf.Response.Sensors[sensorType][i],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,11 @@ const (
|
||||||
|
|
||||||
// MergeOldState merges a given SpaceAPIResponse with the state saved at the time of last program exit and then deletes
|
// MergeOldState merges a given SpaceAPIResponse with the state saved at the time of last program exit and then deletes
|
||||||
// the file containing the old state.
|
// the file containing the old state.
|
||||||
func MergeOldState(response *types.SpaceAPIResponseV14) {
|
func MergeOldState(response *types.SpaceAPIResponse) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
oldState []byte
|
oldState []byte
|
||||||
persistedState types.PersistentStateV14
|
persistedState types.PersistentSpaceState
|
||||||
)
|
)
|
||||||
|
|
||||||
log.Println("Merging old state from", persistentStatePath, "...")
|
log.Println("Merging old state from", persistentStatePath, "...")
|
||||||
|
|
@ -48,7 +48,7 @@ func MergeOldState(response *types.SpaceAPIResponseV14) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge state
|
// Merge state
|
||||||
response.State = persistedState.State
|
response.State.FromPersistentSpaceState(persistedState)
|
||||||
|
|
||||||
// Merge sensors
|
// Merge sensors
|
||||||
for key, environmentSensors := range persistedState.Sensors {
|
for key, environmentSensors := range persistedState.Sensors {
|
||||||
|
|
@ -72,7 +72,7 @@ removeOld:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SaveCurrentState(response types.SpaceAPIResponseV14) {
|
func SaveCurrentState(response types.SpaceAPIResponse) {
|
||||||
// Create state directory if not present
|
// Create state directory if not present
|
||||||
err := os.MkdirAll(persistentStateDir, 0750)
|
err := os.MkdirAll(persistentStateDir, 0750)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -87,7 +87,7 @@ func SaveCurrentState(response types.SpaceAPIResponseV14) {
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
// Create persistent state
|
// Create persistent state
|
||||||
persistentStateV14 := types.PersistentStateV14{
|
persistentStateV14 := types.PersistentSpaceState{
|
||||||
State: struct {
|
State: struct {
|
||||||
Open bool `json:"open"`
|
Open bool `json:"open"`
|
||||||
LastChange int64 `json:"lastchange"`
|
LastChange int64 `json:"lastchange"`
|
||||||
|
|
|
||||||
69
types/v14.go
69
types/v14.go
|
|
@ -1,69 +0,0 @@
|
||||||
package types
|
|
||||||
|
|
||||||
type SpaceAPIResponseV14 struct {
|
|
||||||
APICompatibility []string `json:"api_compatibility"`
|
|
||||||
Space string `json:"space"`
|
|
||||||
Logo string `json:"logo"`
|
|
||||||
ExtCCC string `json:"ext_ccc"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
Location struct {
|
|
||||||
Address string `json:"address"`
|
|
||||||
Lat float64 `json:"lat"`
|
|
||||||
Lon float64 `json:"lon"`
|
|
||||||
} `json:"location"`
|
|
||||||
State SpaceState `json:"state"`
|
|
||||||
Contact struct {
|
|
||||||
Phone string `json:"phone"`
|
|
||||||
IRC string `json:"irc"`
|
|
||||||
Mastodon string `json:"mastodon"`
|
|
||||||
Email string `json:"email"`
|
|
||||||
ML string `json:"ml"`
|
|
||||||
Matrix string `json:"matrix"`
|
|
||||||
} `json:"contact"`
|
|
||||||
Sensors map[string][]EnvironmentSensor `json:"sensors"`
|
|
||||||
Feeds struct {
|
|
||||||
Blog struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
} `json:"blog"`
|
|
||||||
Calendar struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
} `json:"calendar"`
|
|
||||||
} `json:"feeds"`
|
|
||||||
Links []struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
} `json:"links"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SpaceState struct {
|
|
||||||
Open bool `json:"open"`
|
|
||||||
LastChange int64 `json:"lastchange"`
|
|
||||||
Message string `json:"message,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type EnvironmentSensor struct {
|
|
||||||
Value float64 `json:"value"`
|
|
||||||
Unit string `json:"unit"`
|
|
||||||
Location string `json:"location,omitempty"`
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
Description string `json:"description,omitempty"`
|
|
||||||
LastChange int64 `json:"lastchange,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PersistentStateV14 struct {
|
|
||||||
State struct {
|
|
||||||
Open bool `json:"open"`
|
|
||||||
LastChange int64 `json:"lastchange"`
|
|
||||||
Message string `json:"message,omitempty"`
|
|
||||||
} `json:"state"`
|
|
||||||
Sensors map[string][]PersistentEnvironmentSensor `json:"sensors,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PersistentEnvironmentSensor struct {
|
|
||||||
Value float64 `json:"value"`
|
|
||||||
Location string `json:"location,omitempty"`
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
LastChange int64 `json:"lastchange"`
|
|
||||||
}
|
|
||||||
164
types/v15.go
Normal file
164
types/v15.go
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
const CurrentMessageVersion = "15"
|
||||||
|
|
||||||
|
// SpaceAPIResponse represents the contents of the SpaceAPI message
|
||||||
|
//
|
||||||
|
// Currently implemented version: 15
|
||||||
|
type SpaceAPIResponse struct {
|
||||||
|
APICompatibility []string `json:"api_compatibility"` // REQUIRED
|
||||||
|
Space string `json:"space"` // REQUIRED
|
||||||
|
Logo string `json:"logo"` // REQUIRED
|
||||||
|
URL string `json:"url"` // REQUIRED
|
||||||
|
|
||||||
|
// Minimum number of properties: 1
|
||||||
|
Location struct {
|
||||||
|
Address string `json:"address,omitzero"`
|
||||||
|
Lat float64 `json:"lat,omitzero"`
|
||||||
|
Lon float64 `json:"lon,omitzero"`
|
||||||
|
Timezone string `json:"timezone,omitzero"`
|
||||||
|
CountryCode string `json:"country_code,omitzero"`
|
||||||
|
Hint string `json:"hint,omitzero"`
|
||||||
|
// Minimum number of items: 1
|
||||||
|
Areas []SpaceAPILocationAreas `json:"areas,omitempty"`
|
||||||
|
} `json:"location,omitzero"`
|
||||||
|
|
||||||
|
SpaceFed struct {
|
||||||
|
SpaceNet bool `json:"spacenet,omitzero"`
|
||||||
|
SpaceSAML bool `json:"spacesaml,omitzero"`
|
||||||
|
} `json:"spacefed,omitzero"`
|
||||||
|
|
||||||
|
Cam []string `json:"cam,omitempty"`
|
||||||
|
|
||||||
|
State SpaceAPIState `json:"state,omitzero"`
|
||||||
|
|
||||||
|
Events []SpaceAPIEvents `json:"events,omitempty"`
|
||||||
|
|
||||||
|
Contact struct {
|
||||||
|
Phone string `json:"phone,omitzero"`
|
||||||
|
Sip string `json:"sip,omitzero"`
|
||||||
|
// keymasters
|
||||||
|
Keymasters []struct {
|
||||||
|
Name string `json:"name,omitzero"`
|
||||||
|
IRCNick string `json:"irc_nick,omitzero"`
|
||||||
|
Phone string `json:"phone,omitzero"`
|
||||||
|
Email string `json:"email,omitzero"`
|
||||||
|
Twitter string `json:"twitter,omitzero"`
|
||||||
|
Xmpp string `json:"xmpp,omitzero"`
|
||||||
|
Mastodon string `json:"mastodon,omitzero"`
|
||||||
|
Matrix string `json:"matrix,omitzero"`
|
||||||
|
} `json:"keymasters,omitempty"`
|
||||||
|
IRC string `json:"irc,omitzero"`
|
||||||
|
Twitter string `json:"twitter,omitzero"`
|
||||||
|
Mastodon string `json:"mastodon,omitzero"`
|
||||||
|
Facebook string `json:"facebook,omitzero"`
|
||||||
|
Identica string `json:"identica,omitzero"`
|
||||||
|
Foursquare string `json:"foursquare,omitzero"`
|
||||||
|
Email string `json:"email,omitzero"`
|
||||||
|
ML string `json:"ml,omitzero"`
|
||||||
|
XMPP string `json:"xmpp,omitzero"`
|
||||||
|
IssueMail string `json:"issue_mail,omitzero"`
|
||||||
|
Gopher string `json:"gopher,omitzero"`
|
||||||
|
Matrix string `json:"matrix,omitzero"`
|
||||||
|
Mumble string `json:"mumble,omitzero"`
|
||||||
|
} `json:"contact"`
|
||||||
|
|
||||||
|
Sensors map[string][]EnvironmentSensor `json:"sensors,omitempty"`
|
||||||
|
|
||||||
|
Feeds struct {
|
||||||
|
Blog struct {
|
||||||
|
Type string `json:"type,omitzero"`
|
||||||
|
URL string `json:"url"` // REQUIRED
|
||||||
|
} `json:"blog,omitzero"`
|
||||||
|
Wiki struct {
|
||||||
|
Type string `json:"type,omitzero"`
|
||||||
|
URL string `json:"url"` // REQUIRED
|
||||||
|
} `json:"wiki,omitzero"`
|
||||||
|
Calendar struct {
|
||||||
|
Type string `json:"type,omitzero"`
|
||||||
|
URL string `json:"url"` // REQUIRED
|
||||||
|
} `json:"calendar,omitzero"`
|
||||||
|
Flickr struct {
|
||||||
|
Type string `json:"type,omitzero"`
|
||||||
|
URL string `json:"url"` // REQUIRED
|
||||||
|
} `json:"flickr,omitzero"`
|
||||||
|
} `json:"feeds,omitzero"`
|
||||||
|
|
||||||
|
Projects []string `json:"projects,omitempty"`
|
||||||
|
|
||||||
|
Links []struct {
|
||||||
|
Name string `json:"name"` // REQUIRED
|
||||||
|
URL string `json:"url"` // REQUIRED
|
||||||
|
Description string `json:"description,omitzero"`
|
||||||
|
} `json:"links,omitempty"`
|
||||||
|
|
||||||
|
MembershipPlans []struct {
|
||||||
|
Name string `json:"name"` // REQUIRED
|
||||||
|
Value int64 `json:"value"` // REQUIRED
|
||||||
|
Currency string `json:"currency"` // REQUIRED
|
||||||
|
BillingInterval string `json:"billing_interval"` // REQUIRED
|
||||||
|
Description string `json:"description,omitzero"`
|
||||||
|
} `json:"membership_plans,omitempty"`
|
||||||
|
|
||||||
|
LinkedSpaces []struct {
|
||||||
|
Endpoint string `json:"endpoint,omitzero"`
|
||||||
|
Website string `json:"website,omitzero"`
|
||||||
|
} `json:"linked_spaces,omitempty"`
|
||||||
|
|
||||||
|
ExtCCC string `json:"ext_ccc,omitzero"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SpaceAPILocationAreas struct {
|
||||||
|
Name string `json:"name,omitzero"`
|
||||||
|
Description string `json:"description,omitzero"`
|
||||||
|
SquareMeters float64 `json:"square_meters"` // REQUIRED
|
||||||
|
}
|
||||||
|
|
||||||
|
type SpaceAPIState struct {
|
||||||
|
Open bool `json:"open,omitempty"`
|
||||||
|
LastChange int64 `json:"lastchange,omitempty"`
|
||||||
|
TriggerPerson string `json:"trigger_person,omitempty"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
Icon struct {
|
||||||
|
Open string `json:"open,omitempty"` // REQUIRED
|
||||||
|
Closed string `json:"closed,omitempty"` // REQUIRED
|
||||||
|
} `json:"icon,omitzero"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SpaceAPIState) FromPersistentSpaceState(ps PersistentSpaceState) {
|
||||||
|
s.Open = ps.State.Open
|
||||||
|
s.LastChange = ps.State.LastChange
|
||||||
|
s.Message = ps.State.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
type SpaceAPIEvents struct {
|
||||||
|
Name string `json:"name"` // REQUIRED
|
||||||
|
Type string `json:"type"` // REQUIRED
|
||||||
|
Timestamp int64 `json:"timestamp"` // REQUIRED
|
||||||
|
Extra string `json:"extra,omitzero"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type EnvironmentSensor struct {
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
Unit string `json:"unit"`
|
||||||
|
Location string `json:"location,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
LastChange int64 `json:"lastchange,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PersistentSpaceState struct {
|
||||||
|
State struct {
|
||||||
|
Open bool `json:"open"`
|
||||||
|
LastChange int64 `json:"lastchange"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
} `json:"state"`
|
||||||
|
Sensors map[string][]PersistentEnvironmentSensor `json:"sensors,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PersistentEnvironmentSensor struct {
|
||||||
|
Value float64 `json:"value"`
|
||||||
|
Location string `json:"location,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
LastChange int64 `json:"lastchange"`
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue