Skip to content

Commit

Permalink
light
Browse files Browse the repository at this point in the history
  • Loading branch information
balazsgrill committed Mar 15, 2024
1 parent 01184ab commit 3096c9f
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 55 deletions.
73 changes: 73 additions & 0 deletions base.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package hass

import (
"fmt"
"strconv"
"strings"
)

type BaseSensor[SensorEvent any] struct {
events chan SensorEvent
}
Expand Down Expand Up @@ -32,3 +38,70 @@ func (b *baseActuator) init(context IPubSubRuntime, topic string) {
func (s *baseActuator) send(action string) {
s.client.Send(s.topic, []byte(action))
}

type stateField[Type any] struct {
actuator *baseActuator
values chan Type
key string
}

func (state *stateField[Type]) send(command string) {
state.actuator.send(fmt.Sprintf("{\"%s\":%s}", state.key, command))
}

func (d *stateField[_]) Close() error {
close(d.values)
return nil
}

func (d *stateField[T]) Events() chan T {
return d.values
}

type intStateField struct {
stateField[int]
scale int
}

func (d *intStateField) SetValue(value int) {
d.send(strconv.Itoa(value))
}

func (field *intStateField) Process(state map[string]interface{}) {
if value, exists := state[field.key]; exists {
v, err := strconv.Atoi(fmt.Sprint(value))
if err != nil {
field.values <- v
}
}
}

func (field *intStateField) Scale() int {
return field.scale
}

type onOffStateField struct {
stateField[bool]
}

func (field *onOffStateField) Process(state map[string]interface{}) {
if value, exists := state[field.key]; exists {
str := fmt.Sprint(value)
if strings.EqualFold("ON", str) {
field.values <- true
}
if strings.EqualFold("OFF", str) {
field.values <- true
}
}
}

func (d *onOffStateField) SetValue(on bool) {
var v string
if on {
v = "ON"
} else {
v = "OFF"
}
d.send(v)
}
7 changes: 4 additions & 3 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ type Light struct {
BrightnessCommandTopic string `json:"brightness_command_topic,omitempty"`
BrightnessScale int32 `json:"brightness_scale"`
BrightnessStateTopic string `json:"brightness_state_topic,omitempty"`
ColorTemp bool `json:"color_temp,omitempty"`
ColorMode bool `json:"color_mode,omitempty"`
SupportedColorModes []string `json:"supported_color_modes,omitempty"`
OnCommandType string `json:"on_command_type,omitempty"`
StateTopic string `json:"state_topic,omitempty"`
Effect bool `json:"effect,omitempty"`
Expand All @@ -65,7 +66,7 @@ type Light struct {
XY bool `json:"xy,omitempty"`
}

//https://www.home-assistant.io/integrations/sensor.mqtt/
// https://www.home-assistant.io/integrations/sensor.mqtt/
type Sensor struct {
BasicConfig
Name string `json:"name,omitempty"`
Expand All @@ -77,7 +78,7 @@ type Sensor struct {
DeviceClass string `json:"device_class,omitempty"`
}

//https://www.home-assistant.io/integrations/switch.mqtt/
// https://www.home-assistant.io/integrations/switch.mqtt/
type Switch struct {
BasicConfig
CommandTopic string `json:"command_topic,omitempty"`
Expand Down
2 changes: 1 addition & 1 deletion devices.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ type ILight interface {
}

type IIntSettable interface {
ISensor[int]
SetValue(value int)
Scale() int
Values() chan int
}
104 changes: 53 additions & 51 deletions light.go
Original file line number Diff line number Diff line change
@@ -1,73 +1,87 @@
package hass

import (
"fmt"
"strconv"
"encoding/json"
"log"
)

type LightState struct {
Brightness int `json:"brightness,omitempty"`
ColorMode string `json:"color_mode,omitempty"`
ColorTemp int `json:"color_temp,omitempty"`
State string `json:"state,omitempty"`
}

type light_impl struct {
actuator baseActuator
state light_state[bool]
brightness *light_state[int]
color_temp *light_state[int]
}

type light_state[Type any] struct {
light *baseActuator
values chan Type
key string
}

func (state *light_state[Type]) send(command string) {
state.light.send(fmt.Sprintf("{\"%s\":%s}", state.key, command))
state onOffStateField
brightness *intStateField
color_temp *intStateField
}

var _ ILight = &light_impl{}

func NewLight(pubsub IPubSubRuntime, config Light) ILight {
func NewLight(pubsub IPubSubRuntime, config *Light) ILight {
result := &light_impl{
actuator: baseActuator{
client: pubsub,
topic: config.CommandTopic,
},
}
result.state = light_state[bool]{
light: &result.actuator,
values: make(chan bool),
key: "state",
pubsub.Receive(config.StateTopic, func(topic string, payload []byte) {
var data map[string]interface{}
err := json.Unmarshal(payload, &data)
if err != nil {
log.Println(err)
return
}
// TODO Check fields and propagate to state fields
result.state.Process(data)
if result.brightness != nil {
result.brightness.Process(data)
}
if result.color_temp != nil {
result.color_temp.Process(data)
}
})

result.state = onOffStateField{
stateField: stateField[bool]{
actuator: &result.actuator,
values: make(chan bool),
key: "state",
},
}
if config.Brightness {
result.brightness = &light_state[int]{
light: &result.actuator,
values: make(chan int),
key: "brightness",
result.brightness = &intStateField{
stateField: stateField[int]{
actuator: &result.actuator,
values: make(chan int),
key: "brightness",
},
scale: int(config.BrightnessScale),
}
}
if config.ColorMode {
for _, colormode := range config.SupportedColorModes {
switch colormode {
case "color_temp":
result.color_temp = &intStateField{
stateField: stateField[int]{
actuator: &result.actuator,
values: make(chan int),
key: "color_temp",
},
scale: 254,
}
}
}
}
return result
}

func (d *light_impl) State() ISensor[bool] {
return d.State()
return &d.state
}

func (d *light_impl) Toggle() {
d.state.send("TOGGLE")
}
func (d *light_impl) Set(on bool) {
var v string
if on {
v = "ON"
} else {
v = "OFF"
}
d.state.send(v)
d.state.SetValue(on)
}

func (d *light_impl) Brightness() IIntSettable {
Expand All @@ -77,15 +91,3 @@ func (d *light_impl) Brightness() IIntSettable {
func (d *light_impl) ColorTemp() IIntSettable {
return d.color_temp
}

func (d *light_state[T]) SetValue(value int) {
d.send(strconv.Itoa(value))
}

func (d *light_state[_]) Scale() int {
return 254
}

func (d *light_state[T]) Values() chan T {
return d.values
}

0 comments on commit 3096c9f

Please sign in to comment.