Added light sensor
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Dreaded_X 2022-11-23 01:16:46 +01:00
parent 780f633c90
commit f13ee65ead
Signed by: Dreaded_X
GPG Key ID: 76BDEC4E165D8AD9
10 changed files with 193 additions and 21 deletions

View File

@ -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
View 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)
})
}

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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)
} }
} }

View File

@ -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
} }

View 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
}

View File

@ -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"`
}

View File

@ -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)
} }

View File

@ -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())
} }