This commit is contained in:
parent
780f633c90
commit
f13ee65ead
|
@ -39,4 +39,5 @@ func RegisterAutomations(client paho.Client, prefix string, hue *hue.Hue, notify
|
||||||
presenceAutomation(client, hue, notify, home)
|
presenceAutomation(client, hue, notify, home)
|
||||||
mixerAutomation(client, home)
|
mixerAutomation(client, home)
|
||||||
kettleAutomation(client, prefix, home)
|
kettleAutomation(client, prefix, home)
|
||||||
|
darknessAutomation(client, hue)
|
||||||
}
|
}
|
||||||
|
|
14
automation/dark.go
Normal file
14
automation/dark.go
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package automation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"automation/integration/hue"
|
||||||
|
"automation/integration/zigbee"
|
||||||
|
|
||||||
|
paho "github.com/eclipse/paho.mqtt.golang"
|
||||||
|
)
|
||||||
|
|
||||||
|
func darknessAutomation(client paho.Client, hue *hue.Hue) {
|
||||||
|
on(client, "automation/darkness/living", func(message zigbee.DarknessPayload) {
|
||||||
|
// hue.SetFlag(43, message.IsDark)
|
||||||
|
})
|
||||||
|
}
|
|
@ -11,7 +11,6 @@ func (n InternalName) Room() string {
|
||||||
room = s[0]
|
room = s[0]
|
||||||
}
|
}
|
||||||
room = strings.ReplaceAll(room, "_", " ")
|
room = strings.ReplaceAll(room, "_", " ")
|
||||||
room = strings.Title(room)
|
|
||||||
|
|
||||||
return room
|
return room
|
||||||
}
|
}
|
||||||
|
@ -22,7 +21,6 @@ func (n InternalName) Name() string {
|
||||||
if len(s) > 1 {
|
if len(s) > 1 {
|
||||||
name = s[1]
|
name = s[1]
|
||||||
}
|
}
|
||||||
name = strings.Title(name)
|
|
||||||
|
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"automation/integration/google"
|
"automation/integration/google"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type computer struct {
|
type computer struct {
|
||||||
|
@ -49,9 +50,12 @@ func (c *computer) Sync() *google.Device {
|
||||||
DefaultNames: []string{
|
DefaultNames: []string{
|
||||||
"Computer",
|
"Computer",
|
||||||
},
|
},
|
||||||
Name: c.GetID().Name(),
|
Name: strings.Title(c.GetID().Name()),
|
||||||
|
}
|
||||||
|
room := strings.Title(c.GetID().Room())
|
||||||
|
if len(room) > 1 {
|
||||||
|
device.RoomHint = room
|
||||||
}
|
}
|
||||||
device.RoomHint = c.GetID().Room()
|
|
||||||
|
|
||||||
return device
|
return device
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,17 +17,21 @@ func DevicesHandler(client paho.Client, prefix string, home *home.Home) {
|
||||||
json.Unmarshal(msg.Payload(), &devices)
|
json.Unmarshal(msg.Payload(), &devices)
|
||||||
|
|
||||||
for name, d := range device.GetDevices[Device](&home.Devices) {
|
for name, d := range device.GetDevices[Device](&home.Devices) {
|
||||||
d.Delete()
|
d.Delete(client)
|
||||||
// Delete all zigbee devices from the device list
|
// Delete all zigbee devices from the device list
|
||||||
delete(home.Devices, name)
|
delete(home.Devices, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, d := range devices {
|
for _, d := range devices {
|
||||||
|
d.MQTTAddress = fmt.Sprintf("%s/%s", prefix, d.FriendlyName.String())
|
||||||
|
|
||||||
switch d.Description {
|
switch d.Description {
|
||||||
case "Kettle":
|
case "Kettle":
|
||||||
d.MQTTAddress = fmt.Sprintf("%s/%s", prefix, d.FriendlyName.String())
|
|
||||||
kettle := NewKettle(d, client, home.Service)
|
kettle := NewKettle(d, client, home.Service)
|
||||||
home.AddDevice(kettle)
|
home.AddDevice(kettle)
|
||||||
|
case "LightSensor":
|
||||||
|
lightSensor := NewLightSensor(d, client)
|
||||||
|
home.AddDevice(lightSensor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
paho "github.com/eclipse/paho.mqtt.golang"
|
paho "github.com/eclipse/paho.mqtt.golang"
|
||||||
|
@ -36,7 +37,10 @@ func NewKettle(info Info, client paho.Client, service *google.Service) *kettle {
|
||||||
|
|
||||||
func (k *kettle) stateHandler(client paho.Client, msg paho.Message) {
|
func (k *kettle) stateHandler(client paho.Client, msg paho.Message) {
|
||||||
var payload OnOffState
|
var payload OnOffState
|
||||||
json.Unmarshal(msg.Payload(), &payload)
|
if err := json.Unmarshal(msg.Payload(), &payload); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Update the internal state
|
// Update the internal state
|
||||||
k.isOn = payload.State
|
k.isOn = payload.State
|
||||||
|
@ -65,8 +69,8 @@ var _ Device = (*kettle)(nil)
|
||||||
func (k *kettle) IsZigbeeDevice() {}
|
func (k *kettle) IsZigbeeDevice() {}
|
||||||
|
|
||||||
// zigbee.Device
|
// zigbee.Device
|
||||||
func (k *kettle) Delete() {
|
func (k *kettle) Delete(client paho.Client) {
|
||||||
if token := k.client.Unsubscribe(k.info.MQTTAddress); token.Wait() && token.Error() != nil {
|
if token := client.Unsubscribe(k.info.MQTTAddress); token.Wait() && token.Error() != nil {
|
||||||
log.Println(token.Error())
|
log.Println(token.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,11 +88,11 @@ func (k *kettle) Sync() *google.Device {
|
||||||
DefaultNames: []string{
|
DefaultNames: []string{
|
||||||
"Kettle",
|
"Kettle",
|
||||||
},
|
},
|
||||||
Name: k.GetID().Name(),
|
Name: strings.Title(k.GetID().Name()),
|
||||||
}
|
}
|
||||||
|
|
||||||
device.WillReportState = true
|
device.WillReportState = true
|
||||||
room := k.GetID().Room()
|
room := strings.Title(k.GetID().Room())
|
||||||
if len(room) > 1 {
|
if len(room) > 1 {
|
||||||
device.RoomHint = room
|
device.RoomHint = room
|
||||||
}
|
}
|
||||||
|
|
140
integration/zigbee/light_sensor.go
Normal file
140
integration/zigbee/light_sensor.go
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
package zigbee
|
||||||
|
|
||||||
|
import (
|
||||||
|
"automation/device"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
paho "github.com/eclipse/paho.mqtt.golang"
|
||||||
|
)
|
||||||
|
|
||||||
|
type lightSensor struct {
|
||||||
|
info Info
|
||||||
|
|
||||||
|
minValue int
|
||||||
|
maxValue int
|
||||||
|
timeout time.Duration
|
||||||
|
|
||||||
|
couldBeDark bool
|
||||||
|
isDark bool
|
||||||
|
initialized bool
|
||||||
|
timer *time.Timer
|
||||||
|
}
|
||||||
|
|
||||||
|
type DarknessPayload struct {
|
||||||
|
IsDark bool `json:"is_dark"`
|
||||||
|
Updated int64 `json:"updated"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLightSensor(info Info, client paho.Client) *lightSensor {
|
||||||
|
l := &lightSensor{info: info}
|
||||||
|
|
||||||
|
// @TODO Two completely random values for now
|
||||||
|
l.minValue = 8000
|
||||||
|
l.maxValue = 16000
|
||||||
|
|
||||||
|
l.timeout = time.Minute
|
||||||
|
l.timer = time.NewTimer(l.timeout)
|
||||||
|
l.timer.Stop()
|
||||||
|
|
||||||
|
if token := client.Subscribe(l.info.MQTTAddress, 1, l.stateHandler); token.Wait() && token.Error() != nil {
|
||||||
|
log.Println(token.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
<-l.timer.C
|
||||||
|
l.isDark = l.couldBeDark
|
||||||
|
|
||||||
|
log.Println("Is dark:", l.isDark)
|
||||||
|
|
||||||
|
payload, err := json.Marshal(DarknessPayload{
|
||||||
|
IsDark: l.isDark,
|
||||||
|
Updated: time.Now().UnixMilli(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if token := client.Publish(l.darknessTopic(), 1, true, payload); token.Wait() && token.Error() != nil {
|
||||||
|
log.Println(token.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *lightSensor) darknessTopic() string {
|
||||||
|
return fmt.Sprintf("automation/darkness/%s", l.info.FriendlyName.Room())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *lightSensor) stateHandler(client paho.Client, msg paho.Message) {
|
||||||
|
var message LightSensorState
|
||||||
|
if err := json.Unmarshal(msg.Payload(), &message); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(l.isDark, l.couldBeDark, message.Illuminance, l.maxValue, l.minValue)
|
||||||
|
|
||||||
|
if !l.initialized {
|
||||||
|
if message.Illuminance > l.maxValue {
|
||||||
|
l.couldBeDark = false
|
||||||
|
} else {
|
||||||
|
l.couldBeDark = true
|
||||||
|
}
|
||||||
|
|
||||||
|
l.initialized = true
|
||||||
|
l.timer.Reset(time.Millisecond)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if message.Illuminance > l.maxValue {
|
||||||
|
if l.isDark && l.couldBeDark {
|
||||||
|
log.Println("Could be light, starting timer")
|
||||||
|
l.couldBeDark = false
|
||||||
|
l.timer.Reset(l.timeout)
|
||||||
|
} else if !l.isDark {
|
||||||
|
log.Println("Is not dark, canceling timer")
|
||||||
|
l.couldBeDark = false
|
||||||
|
l.timer.Stop()
|
||||||
|
}
|
||||||
|
} else if message.Illuminance < l.minValue {
|
||||||
|
if !l.isDark && !l.couldBeDark {
|
||||||
|
log.Println("Could be dark, starting timer")
|
||||||
|
l.couldBeDark = true
|
||||||
|
l.timer.Reset(l.timeout)
|
||||||
|
} else if l.isDark {
|
||||||
|
log.Println("Is dark, canceling timer")
|
||||||
|
l.couldBeDark = true
|
||||||
|
l.timer.Stop()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// log.Println("In between the threshold, canceling timer for now keeping the current state")
|
||||||
|
l.couldBeDark = l.isDark
|
||||||
|
l.timer.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// zigbee.Device
|
||||||
|
var _ Device = (*lightSensor)(nil)
|
||||||
|
|
||||||
|
func (l *lightSensor) IsZigbeeDevice() {}
|
||||||
|
|
||||||
|
func (l *lightSensor) Delete(client paho.Client) {
|
||||||
|
if token := client.Unsubscribe(l.darknessTopic()); token.Wait() && token.Error() != nil {
|
||||||
|
log.Println(token.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// device.Base
|
||||||
|
var _ device.Basic = (*lightSensor)(nil)
|
||||||
|
|
||||||
|
func (l *lightSensor) GetID() device.InternalName {
|
||||||
|
return l.info.FriendlyName
|
||||||
|
}
|
|
@ -32,3 +32,7 @@ const (
|
||||||
type RemoteState struct {
|
type RemoteState struct {
|
||||||
Action RemoteAction `json:"action"`
|
Action RemoteAction `json:"action"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LightSensorState struct {
|
||||||
|
Illuminance int `json:"illuminance"`
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
package zigbee
|
package zigbee
|
||||||
|
|
||||||
import "automation/device"
|
import (
|
||||||
|
"automation/device"
|
||||||
|
|
||||||
|
paho "github.com/eclipse/paho.mqtt.golang"
|
||||||
|
)
|
||||||
|
|
||||||
type Info struct {
|
type Info struct {
|
||||||
IEEEAdress string `json:"ieee_address"`
|
IEEEAdress string `json:"ieee_address"`
|
||||||
FriendlyName device.InternalName `json:"friendly_name"`
|
FriendlyName device.InternalName `json:"friendly_name"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Manufacturer string `json:"manufacturer"`
|
Manufacturer string `json:"manufacturer"`
|
||||||
ModelID string `json:"model_id"`
|
ModelID string `json:"model_id"`
|
||||||
SoftwareBuildID string `json:"software_build_id"`
|
SoftwareBuildID string `json:"software_build_id"`
|
||||||
|
|
||||||
MQTTAddress string `json:"-"`
|
MQTTAddress string `json:"-"`
|
||||||
}
|
}
|
||||||
|
@ -17,5 +21,5 @@ type Device interface {
|
||||||
device.Basic
|
device.Basic
|
||||||
|
|
||||||
IsZigbeeDevice()
|
IsZigbeeDevice()
|
||||||
Delete()
|
Delete(client paho.Client)
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,16 +53,15 @@ func (p *Presence) devicePresenceHandler(client paho.Client, msg paho.Message) {
|
||||||
if p.presence != present {
|
if p.presence != present {
|
||||||
p.presence = present
|
p.presence = present
|
||||||
|
|
||||||
msg, err := json.Marshal(Message{
|
payload, err := json.Marshal(Message{
|
||||||
State: present,
|
State: present,
|
||||||
Updated: time.Now().UnixMilli(),
|
Updated: time.Now().UnixMilli(),
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
token := client.Publish("automation/presence", 1, true, msg)
|
token := client.Publish("automation/presence", 1, true, payload)
|
||||||
if token.Wait() && token.Error() != nil {
|
if token.Wait() && token.Error() != nil {
|
||||||
log.Println(token.Error())
|
log.Println(token.Error())
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue
Block a user