This commit is contained in:
commit
ec0ccab3a9
36
.air.toml
Normal file
36
.air.toml
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
root = "."
|
||||||
|
testdata_dir = "testdata"
|
||||||
|
tmp_dir = "tmp"
|
||||||
|
|
||||||
|
[build]
|
||||||
|
bin = "./tmp/main"
|
||||||
|
cmd = "go build -o ./tmp/main ."
|
||||||
|
delay = 1000
|
||||||
|
exclude_dir = ["assets", "tmp", "vendor", "testdata", "storage"]
|
||||||
|
exclude_file = []
|
||||||
|
exclude_regex = ["_test.go"]
|
||||||
|
exclude_unchanged = false
|
||||||
|
follow_symlink = false
|
||||||
|
full_bin = ""
|
||||||
|
include_dir = []
|
||||||
|
include_ext = ["go", "tpl", "tmpl", "html"]
|
||||||
|
kill_delay = "0s"
|
||||||
|
log = "build-errors.log"
|
||||||
|
send_interrupt = false
|
||||||
|
stop_on_error = true
|
||||||
|
|
||||||
|
[color]
|
||||||
|
app = ""
|
||||||
|
build = "yellow"
|
||||||
|
main = "magenta"
|
||||||
|
runner = "green"
|
||||||
|
watcher = "cyan"
|
||||||
|
|
||||||
|
[log]
|
||||||
|
time = false
|
||||||
|
|
||||||
|
[misc]
|
||||||
|
clean_on_exit = false
|
||||||
|
|
||||||
|
[screen]
|
||||||
|
clear_on_rebuild = false
|
4
.dockerignore
Normal file
4
.dockerignore
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
.git/
|
||||||
|
storage/
|
||||||
|
automation
|
||||||
|
.env
|
47
.drone.yml
Normal file
47
.drone.yml
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: default
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: build
|
||||||
|
image: docker
|
||||||
|
volumes:
|
||||||
|
- name: socket
|
||||||
|
path: /var/run/docker.sock
|
||||||
|
commands:
|
||||||
|
- docker build -t inventory .
|
||||||
|
|
||||||
|
- name: deploy
|
||||||
|
image: docker
|
||||||
|
volumes:
|
||||||
|
- name: socket
|
||||||
|
path: /var/run/docker.sock
|
||||||
|
environment:
|
||||||
|
MQTT_HOST:
|
||||||
|
from_secret: MQTT_HOST
|
||||||
|
MQTT_PORT:
|
||||||
|
from_secret: MQTT_PORT
|
||||||
|
MQTT_USER:
|
||||||
|
from_secret: MQTT_USER
|
||||||
|
MQTT_PASS:
|
||||||
|
from_secret: MQTT_PASS
|
||||||
|
HUE_BRIDGE:
|
||||||
|
from_secret: HUE_BRIDGE
|
||||||
|
commands:
|
||||||
|
- docker stop automation || true
|
||||||
|
|
||||||
|
- docker rm automation || true
|
||||||
|
|
||||||
|
- docker run -e MQTT_HOST=$MQTT_HOST -e MQTT_PORT=$MQTT_PORT -e MQTT_USER=$MQTT_USER -e MQTT_PASS=$MQTT_PASS -e HUE_BRIDGE=$HUE_BRIDGE --network mqtt --name automation -d automation
|
||||||
|
|
||||||
|
when:
|
||||||
|
branch:
|
||||||
|
- master
|
||||||
|
event:
|
||||||
|
exclude:
|
||||||
|
- pull_request
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- name: socket
|
||||||
|
host:
|
||||||
|
path: /var/run/docker.sock
|
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
storage
|
||||||
|
automation
|
||||||
|
.env
|
18
Dockerfile
Normal file
18
Dockerfile
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
FROM golang:alpine as build-automation
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
COPY ./go.mod .
|
||||||
|
COPY ./go.sum .
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN go build
|
||||||
|
|
||||||
|
|
||||||
|
FROM golang:alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=build-automation /src/automation /app/automation
|
||||||
|
|
||||||
|
CMD ["/app/automation"]
|
16
go.mod
Normal file
16
go.mod
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
module automation
|
||||||
|
|
||||||
|
go 1.17
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/amimof/huego v1.2.1 // indirect
|
||||||
|
github.com/eclipse/paho.mqtt.golang v1.3.5 // indirect
|
||||||
|
github.com/gorilla/websocket v1.4.2 // indirect
|
||||||
|
github.com/joho/godotenv v1.4.0 // indirect
|
||||||
|
github.com/k0kubun/pp v3.0.1+incompatible // indirect
|
||||||
|
github.com/kelvins/sunrisesunset v0.0.0-20210220141756-39fa1bd816d5 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
|
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
|
||||||
|
)
|
32
go.sum
Normal file
32
go.sum
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
github.com/amimof/huego v1.2.1 h1:kd36vsieclW4fZ4Vqii9DNU2+6ptWWtkp4OG0AXM8HE=
|
||||||
|
github.com/amimof/huego v1.2.1/go.mod h1:z1Sy7Rrdzmb+XsGHVEhODrRJRDq4RCFW7trCI5cKmeA=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/eclipse/paho.mqtt.golang v1.3.5 h1:sWtmgNxYM9P2sP+xEItMozsR3w0cqZFlqnNN1bdl41Y=
|
||||||
|
github.com/eclipse/paho.mqtt.golang v1.3.5/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc=
|
||||||
|
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||||
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/jarcoal/httpmock v1.0.4/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
|
||||||
|
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
|
||||||
|
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
|
github.com/k0kubun/pp v3.0.1+incompatible h1:3tqvf7QgUnZ5tXO6pNAZlrvHgl6DvifjDrd9g2S9Z40=
|
||||||
|
github.com/k0kubun/pp v3.0.1+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg=
|
||||||
|
github.com/kelvins/sunrisesunset v0.0.0-20210220141756-39fa1bd816d5 h1:ouekCqYkMw4QXFCaLyYqjBe99/MUW4Qf3DJhCRh1G18=
|
||||||
|
github.com/kelvins/sunrisesunset v0.0.0-20210220141756-39fa1bd816d5/go.mod h1:3oZ7G+fb8Z8KF+KPHxeDO3GWpEjgvk/f+d/yaxmDRT4=
|
||||||
|
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||||
|
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||||
|
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||||
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 h1:Jcxah/M+oLZ/R4/z5RzfPzGbPXnVDPkEDtf2JnuxN+U=
|
||||||
|
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo=
|
||||||
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
230
main.go
Normal file
230
main.go
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/amimof/huego"
|
||||||
|
MQTT "github.com/eclipse/paho.mqtt.golang"
|
||||||
|
"github.com/joho/godotenv"
|
||||||
|
"github.com/kelvins/sunrisesunset"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Location struct {
|
||||||
|
Longitude float32 `json:"lon"`
|
||||||
|
Latitude float32 `json:"lat"`
|
||||||
|
Altitude int `json:"alt"`
|
||||||
|
InRegions []string `json:"inregions"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultHandler MQTT.MessageHandler = func(client MQTT.Client, msg MQTT.Message) {
|
||||||
|
fmt.Printf("TOPIC: %s\n", msg.Topic())
|
||||||
|
fmt.Printf("MSG: %s\n", msg.Payload())
|
||||||
|
}
|
||||||
|
|
||||||
|
const groupId = 1
|
||||||
|
const brightness = 100
|
||||||
|
|
||||||
|
func getNextSunriseSunset() (time.Time, time.Time) {
|
||||||
|
p := sunrisesunset.Parameters{
|
||||||
|
Latitude: 51.9808334,
|
||||||
|
Longitude: 4.347818,
|
||||||
|
Date: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
sunrise, sunset, err := p.GetSunriseSunset()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
p2 := sunrisesunset.Parameters{
|
||||||
|
Latitude: 51.9808334,
|
||||||
|
Longitude: 4.347818,
|
||||||
|
Date: time.Now().Add(time.Hour * 24),
|
||||||
|
}
|
||||||
|
sunrise2, sunset2, err := p2.GetSunriseSunset()
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
if now.After(sunrise) {
|
||||||
|
sunrise = sunrise2
|
||||||
|
}
|
||||||
|
|
||||||
|
if now.After(sunset) {
|
||||||
|
sunset = sunset2
|
||||||
|
}
|
||||||
|
|
||||||
|
return sunrise, sunset
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDay() bool {
|
||||||
|
p := sunrisesunset.Parameters{
|
||||||
|
Latitude: 51.9808334,
|
||||||
|
Longitude: 4.347818,
|
||||||
|
Date: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
sunrise, sunset, err := p.GetSunriseSunset()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.Now().After(sunrise) && time.Now().Before(sunset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func allLightsOff(bridge *huego.Bridge) {
|
||||||
|
lights, _ := bridge.GetLights()
|
||||||
|
for _, l := range lights {
|
||||||
|
l.Off()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
_ = godotenv.Load()
|
||||||
|
|
||||||
|
host, ok := os.LookupEnv("MQTT_HOST")
|
||||||
|
if !ok {
|
||||||
|
host = "localhost"
|
||||||
|
}
|
||||||
|
port, ok := os.LookupEnv("MQTT_PORT")
|
||||||
|
if !ok {
|
||||||
|
port = "1883"
|
||||||
|
}
|
||||||
|
user, ok := os.LookupEnv("MQTT_USER")
|
||||||
|
if !ok {
|
||||||
|
user = "test"
|
||||||
|
}
|
||||||
|
pass, ok := os.LookupEnv("MQTT_PASS")
|
||||||
|
if !ok {
|
||||||
|
pass = "test"
|
||||||
|
}
|
||||||
|
login, ok := os.LookupEnv("HUE_BRIDGE")
|
||||||
|
|
||||||
|
fmt.Println(host, port, user, pass, login)
|
||||||
|
|
||||||
|
halt := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(halt, os.Interrupt, syscall.SIGTERM)
|
||||||
|
|
||||||
|
bridge, _ := huego.Discover()
|
||||||
|
bridge = bridge.Login(login)
|
||||||
|
livingRoom, _ := bridge.GetGroup(groupId)
|
||||||
|
|
||||||
|
opts := MQTT.NewClientOptions().AddBroker(fmt.Sprintf("%s:%s", host, port))
|
||||||
|
opts.SetClientID("automation")
|
||||||
|
opts.SetDefaultPublishHandler(defaultHandler)
|
||||||
|
opts.SetUsername(user)
|
||||||
|
opts.SetPassword(pass)
|
||||||
|
|
||||||
|
c := MQTT.NewClient(opts)
|
||||||
|
if token := c.Connect(); token.Wait() && token.Error() != nil {
|
||||||
|
panic(token.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
home := make(chan bool, 1)
|
||||||
|
var locationHandler MQTT.MessageHandler = func(client MQTT.Client, msg MQTT.Message) {
|
||||||
|
var location Location
|
||||||
|
json.Unmarshal(msg.Payload(), &location)
|
||||||
|
|
||||||
|
fmt.Println(location)
|
||||||
|
temp := false
|
||||||
|
for _, region := range location.InRegions {
|
||||||
|
if region == "home" {
|
||||||
|
temp = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println(temp)
|
||||||
|
|
||||||
|
home <- temp
|
||||||
|
}
|
||||||
|
|
||||||
|
if token := c.Subscribe("owntracks/mqtt/apollo", 0, locationHandler); token.Wait() && token.Error() != nil {
|
||||||
|
fmt.Println(token.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup initial states
|
||||||
|
isHome := false
|
||||||
|
|
||||||
|
sunrise, sunset := getNextSunriseSunset()
|
||||||
|
sunriseTimer := time.NewTimer(sunrise.Sub(time.Now()))
|
||||||
|
sunsetTimer := time.NewTimer(sunset.Sub(time.Now()))
|
||||||
|
|
||||||
|
// Create the ticker, but stop it
|
||||||
|
ticker := time.NewTicker(time.Second)
|
||||||
|
ticker.Stop()
|
||||||
|
|
||||||
|
var brightness uint8 = 0
|
||||||
|
|
||||||
|
// Event loop
|
||||||
|
events:
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case temp := <-home:
|
||||||
|
// Only do stuff if the state changes
|
||||||
|
if temp == isHome {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
isHome = temp
|
||||||
|
|
||||||
|
if isHome {
|
||||||
|
fmt.Println("Coming home")
|
||||||
|
if !isDay() {
|
||||||
|
fmt.Println("\tTurning on lights in the living room")
|
||||||
|
livingRoom.Bri(0xff)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Stop the ticker in case it is running
|
||||||
|
ticker.Stop()
|
||||||
|
|
||||||
|
fmt.Println("Leaving home")
|
||||||
|
allLightsOff(bridge)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
case <-sunriseTimer.C:
|
||||||
|
fmt.Println("Sun is rising, turning off all lights")
|
||||||
|
allLightsOff(bridge)
|
||||||
|
|
||||||
|
// Set new timer
|
||||||
|
sunrise, _ := getNextSunriseSunset()
|
||||||
|
sunriseTimer.Reset(sunrise.Sub(time.Now()))
|
||||||
|
|
||||||
|
case <-sunsetTimer.C:
|
||||||
|
fmt.Println("Sun is setting")
|
||||||
|
if isHome {
|
||||||
|
fmt.Println("\tGradually turning on lights in the living room")
|
||||||
|
// Start the ticker to gradually turn on the living room lights
|
||||||
|
ticker.Reset(1200 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set new timer
|
||||||
|
_, sunset := getNextSunriseSunset()
|
||||||
|
sunsetTimer.Reset(sunset.Sub(time.Now()))
|
||||||
|
|
||||||
|
case <-ticker.C:
|
||||||
|
fmt.Println("Setting brightness:", brightness)
|
||||||
|
livingRoom.Bri(brightness)
|
||||||
|
|
||||||
|
brightness++
|
||||||
|
if brightness == 0xff {
|
||||||
|
fmt.Println("Lights are now on, stopping ticker")
|
||||||
|
ticker.Stop()
|
||||||
|
brightness = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
case <-halt:
|
||||||
|
break events
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
if token := c.Unsubscribe("owntracks/mqtt/apollo"); token.Wait() && token.Error() != nil {
|
||||||
|
fmt.Println(token.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Disconnect(250)
|
||||||
|
}
|
Reference in New Issue
Block a user