// Descriptor identifies retained device metadata.
Descriptor Kind = "descriptor"
+
// Availability identifies retained device reachability.
Availability Kind = "availability"
+
// Reported identifies a retained point value.
Reported Kind = "reported"
+
// Telemetry identifies a non-retained measurement.
Telemetry Kind = "telemetry"
+
// Event identifies a non-retained occurrence.
Event Kind = "events"
+
// Command identifies a non-retained point request.
Command Kind = "commands"
+
// CommandBatch identifies an ordered group of point requests.
CommandBatch Kind = "batch"
+
// Result identifies a command outcome.
Result Kind = "results"
+
// HubStatus identifies retained Zigbee hub diagnostics.
HubStatus Kind = "status"
)
Target string
}
-// Topic validates the address and returns its exact publication topic.
-func (a Address) Topic() (string, error) {
+// topic validates the address and returns its exact publication topic.
+func (a Address) topic() (string, error) {
if !ValidID(a.ID) {
return "", fmt.Errorf("address ID must be a canonical ULID")
}
return Root + "/devices/" + a.ID + "/" + string(a.Kind) + "/" + a.Target, nil
}
-// ParseTopic rejects malformed topics, wildcards, and unsupported operations.
-func ParseTopic(topic string) (Address, error) {
+// parseTopic rejects malformed topics, wildcards, and unsupported operations.
+func parseTopic(topic string) (Address, error) {
parts := strings.Split(topic, "/")
if len(parts) < 5 || parts[0]+"/"+parts[1] != Root {
return Address{}, fmt.Errorf("topic must use the versioned root")
switch {
case len(parts) == 6 && parts[2] == "zigbee" && parts[3] == "hubs" && parts[5] == "status":
- address = Address{Kind: HubStatus, ID: parts[4]}
+ address = Address{
+ Kind: HubStatus,
+ ID: parts[4],
+ }
case (len(parts) == 5 || len(parts) == 6) && parts[2] == "devices":
- address = Address{Kind: Kind(parts[4]), ID: parts[3]}
+ address = Address{
+ Kind: Kind(parts[4]),
+ ID: parts[3],
+ }
if len(parts) == 6 {
address.Target = parts[5]
if address.Kind == Command && address.Target == "$batch" {
return Address{}, fmt.Errorf("topic layout is invalid")
}
- canonical, err := address.Topic()
+ canonical, err := address.topic()
if err != nil {
return Address{}, fmt.Errorf("validate topic address: %w", err)
}
// house-state input. Telemetry uses QoS 0. Other subscriptions use QoS 1.
func CoreSubscriptions() []Subscription {
return []Subscription{
- {Filter: Root + "/devices/+/descriptor", QoS: 1},
- {Filter: Root + "/devices/+/availability", QoS: 1},
- {Filter: Root + "/devices/+/reported/+", QoS: 1},
- {Filter: Root + "/devices/+/telemetry/+", QoS: 0},
- {Filter: Root + "/devices/+/events/+", QoS: 1},
- {Filter: Root + "/devices/+/results/+", QoS: 1},
+ {
+ Filter: Root + "/devices/+/descriptor",
+ QoS: 1,
+ },
+ {
+ Filter: Root + "/devices/+/availability",
+ QoS: 1,
+ },
+ {
+ Filter: Root + "/devices/+/reported/+",
+ QoS: 1,
+ },
+ {
+ Filter: Root + "/devices/+/telemetry/+",
+ QoS: 0,
+ },
+ {
+ Filter: Root + "/devices/+/events/+",
+ QoS: 1,
+ },
+ {
+ Filter: Root + "/devices/+/results/+",
+ QoS: 1,
+ },
}
}
return Subscription{}, fmt.Errorf("device ID must be a canonical ULID")
}
- return Subscription{Filter: Root + "/devices/" + deviceID + "/commands/+", QoS: 1}, nil
+ return Subscription{
+ Filter: Root + "/devices/" + deviceID + "/commands/+",
+ QoS: 1,
+ }, nil
}
// HubStatusSubscription returns the filter for all Zigbee hub diagnostics.
func HubStatusSubscription() Subscription {
- return Subscription{Filter: Root + "/zigbee/hubs/+/status", QoS: 1}
+ return Subscription{
+ Filter: Root + "/zigbee/hubs/+/status",
+ QoS: 1,
+ }
}