Skip to content

Commit c16f7a4

Browse files
committed
Store status in redis and restore on startup
1 parent cd9c3ea commit c16f7a4

File tree

10 files changed

+134
-11
lines changed

10 files changed

+134
-11
lines changed

broker.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
type broker struct {
99
client *redis.Client
1010
pubsub *redis.PubSub
11+
topic string
1112
}
1213

1314
func newBroker(cfg config.RedisConfig) (*broker, error) {
@@ -23,6 +24,7 @@ func newBroker(cfg config.RedisConfig) (*broker, error) {
2324
return &broker{
2425
client: client,
2526
pubsub: pubsub,
27+
topic: cfg.Topic,
2628
}, nil
2729
}
2830

@@ -37,6 +39,21 @@ func (b *broker) listen(messages chan string, errors chan error) {
3739
}
3840
}
3941

42+
func (b *broker) updateStatus(status chan Status, errors chan error) {
43+
for {
44+
s := <-status
45+
err := b.client.HMSet(b.topic+":"+s.Device, s.Params).Err()
46+
if err != nil {
47+
errors <- err
48+
}
49+
50+
}
51+
}
52+
53+
func (b *broker) fetchStatus(device string) (map[string]string, error) {
54+
return b.client.HGetAll(b.topic + ":" + device).Result()
55+
}
56+
4057
func (b *broker) Close() {
4158
b.pubsub.Close()
4259
b.client.Close()

driver/direct.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package driver
22

33
import (
44
"errors"
5+
"fmt"
56

67
"github.com/xanecs/lighthouse/config"
78

@@ -54,8 +55,17 @@ func (d *directDriver) HandleMessage(action string, p params) error {
5455
return d.write()
5556
}
5657

57-
func (d *directDriver) Status() map[string]interface{} {
58-
return map[string]interface{}{"power": d.state}
58+
func (d *directDriver) Status() map[string]string {
59+
return map[string]string{"power": fmt.Sprint(d.state)}
60+
}
61+
62+
func (d *directDriver) Restore(status map[string]string) error {
63+
v, ok := status["power"]
64+
if !ok {
65+
return errors.New("Missing parameter power")
66+
}
67+
d.state = v == trueStr
68+
return d.write()
5969
}
6070

6171
func newDirectDriver(cfg config.DeviceConfig, connection gobot.Connection) (*directDriver, error) {

driver/driver.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ const (
2222
// Device represents a device that can handle messages
2323
type Device interface {
2424
HandleMessage(string, params) error
25-
Status() map[string]interface{}
25+
Status() map[string]string
26+
Restore(map[string]string) error
2627
}
2728

2829
// NewDriver creates a new Driver from a device config

driver/params.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ package driver
22

33
import "errors"
44

5+
const (
6+
trueStr = "true"
7+
)
8+
59
type params map[string]interface{}
610

711
func (p params) getBool(key string) (bool, error) {

driver/pwm.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package driver
22

33
import (
44
"errors"
5+
"fmt"
6+
"strconv"
57

68
"github.com/xanecs/lighthouse/config"
79

@@ -79,8 +81,26 @@ func (p *pwmDriver) HandleMessage(action string, par params) error {
7981
return p.write()
8082
}
8183

82-
func (p *pwmDriver) Status() map[string]interface{} {
83-
return map[string]interface{}{"power": p.power, "brightness": p.brightness / 255.0}
84+
func (p *pwmDriver) Status() map[string]string {
85+
return map[string]string{"power": fmt.Sprint(p.power), "brightness": fmt.Sprint(float64(p.brightness) / 255.0)}
86+
}
87+
88+
func (p *pwmDriver) Restore(status map[string]string) error {
89+
pwr, ok := status["power"]
90+
if !ok {
91+
return errors.New("Missing parameter 'power'")
92+
}
93+
p.power = pwr == trueStr
94+
brightStr, ok := status["brightness"]
95+
if !ok {
96+
return errors.New("Missing parameter 'brightness'")
97+
}
98+
bright, err := strconv.ParseFloat(brightStr, 64)
99+
if err != nil {
100+
return err
101+
}
102+
p.brightness = byte(bright * 255)
103+
return p.write()
84104
}
85105

86106
func newPwmDriver(cfg config.DeviceConfig, connection gobot.Connection) (*pwmDriver, error) {

driver/rgb.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package driver
22

33
import (
44
"errors"
5+
"fmt"
56

67
"github.com/xanecs/lighthouse/config"
78

@@ -77,8 +78,31 @@ func (r *rgbDriver) HandleMessage(action string, p params) error {
7778
return r.write()
7879
}
7980

80-
func (r *rgbDriver) Status() map[string]interface{} {
81-
return map[string]interface{}{"power": r.power, "color": r.color}
81+
func (r *rgbDriver) Status() map[string]string {
82+
return map[string]string{
83+
"power": fmt.Sprint(r.power),
84+
"red": fmt.Sprint(r.color.red),
85+
"green": fmt.Sprint(r.color.green),
86+
"blue": fmt.Sprint(r.color.blue),
87+
}
88+
}
89+
90+
func (r *rgbDriver) Restore(status map[string]string) error {
91+
par := make(params)
92+
for k, v := range status {
93+
par[k] = v
94+
}
95+
clr, err := parseColor(par)
96+
if err != nil {
97+
return err
98+
}
99+
r.color = clr
100+
powerStr, ok := status["power"]
101+
if !ok {
102+
return errors.New("Missing parameter 'power'")
103+
}
104+
r.power = powerStr == trueStr
105+
return r.write()
82106
}
83107

84108
func (r *rgbDriver) Driver() gobot.Device {

driver/servo.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package driver
22

33
import (
44
"errors"
5+
"fmt"
6+
"strconv"
57

68
"github.com/xanecs/lighthouse/config"
79
"gobot.io/x/gobot"
@@ -72,8 +74,27 @@ func (s *servoDriver) HandleMessage(action string, p params) error {
7274
return s.write()
7375
}
7476

75-
func (s *servoDriver) Status() map[string]interface{} {
76-
return map[string]interface{}{"power": s.power, "angle": s.angle}
77+
func (s *servoDriver) Status() map[string]string {
78+
return map[string]string{"power": fmt.Sprint(s.power), "angle": fmt.Sprint(s.angle)}
79+
}
80+
81+
func (s *servoDriver) Restore(status map[string]string) error {
82+
powerStr, ok := status["power"]
83+
if !ok {
84+
return errors.New("Missing parameter 'power'")
85+
}
86+
s.power = powerStr == trueStr
87+
88+
angleStr, ok := status["angle"]
89+
if !ok {
90+
return errors.New("Missing parameter 'angle'")
91+
}
92+
angle, err := strconv.ParseUint(angleStr, 10, 8)
93+
if err != nil {
94+
return err
95+
}
96+
s.angle = uint8(angle)
97+
return s.write()
7798
}
7899

79100
func newServoDriver(cfg config.DeviceConfig, connection gobot.Connection) (*servoDriver, error) {

hardware.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package main
22

33
import (
44
"errors"
5+
"fmt"
6+
"os"
57

68
"github.com/xanecs/lighthouse/config"
79
"github.com/xanecs/lighthouse/driver"
@@ -57,8 +59,20 @@ func (h *Hardware) Stop() {
5759
}
5860
}
5961

62+
// Restore all Hardware from database
63+
func (h *Hardware) Restore(b *broker) {
64+
for name, dev := range h.devices {
65+
status, err := b.fetchStatus(name)
66+
if err != nil {
67+
fmt.Fprintln(os.Stderr, err)
68+
continue
69+
}
70+
dev.Restore(status)
71+
}
72+
}
73+
6074
// Listen processes Messages from a channel
61-
func (h *Hardware) Listen(in chan Message, chanErr chan error) {
75+
func (h *Hardware) Listen(in chan Message, out chan Status, chanErr chan error) {
6276
for {
6377
msg := <-in
6478
dev := h.devices[msg.Device]
@@ -68,6 +82,8 @@ func (h *Hardware) Listen(in chan Message, chanErr chan error) {
6882
}
6983
if err := dev.HandleMessage(msg.Action, msg.Params); err != nil {
7084
chanErr <- err
85+
continue
7186
}
87+
out <- Status{msg.Device, dev.Status()}
7288
}
7389
}

main.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,17 @@ func main() {
2929
}
3030
defer broker.Close()
3131

32+
hardware.Restore(broker)
33+
3234
chanErr := make(chan error)
3335
brokerMsg := make(chan string)
3436
parsedMsg := make(chan Message)
37+
status := make(chan Status)
3538

3639
go broker.listen(brokerMsg, chanErr)
3740
go Parser(brokerMsg, parsedMsg, chanErr)
38-
go hardware.Listen(parsedMsg, chanErr)
41+
go hardware.Listen(parsedMsg, status, chanErr)
42+
go broker.updateStatus(status, chanErr)
3943

4044
for {
4145
err := <-chanErr

message.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,9 @@ func Parser(in chan string, out chan Message, errOut chan error) {
2222
out <- msg
2323
}
2424
}
25+
26+
// Status represents the state of a device
27+
type Status struct {
28+
Device string
29+
Params map[string]string
30+
}

0 commit comments

Comments
 (0)