Inital
This commit is contained in:
3
.envrc
Normal file
3
.envrc
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
source_url "https://raw.githubusercontent.com/cachix/devenv/82c0147677e510b247d8b9165c54f73d32dfd899/direnvrc" "sha256-7u4iDd1nZpxL4tCzmPG0dQgC5V+/44Ba+tHkPob1v2k="
|
||||||
|
|
||||||
|
use devenv
|
||||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -23,3 +23,12 @@ go.work.sum
|
|||||||
|
|
||||||
# env file
|
# env file
|
||||||
.env
|
.env
|
||||||
|
# Devenv
|
||||||
|
.devenv*
|
||||||
|
devenv.local.nix
|
||||||
|
|
||||||
|
# direnv
|
||||||
|
.direnv
|
||||||
|
|
||||||
|
# pre-commit
|
||||||
|
.pre-commit-config.yaml
|
||||||
|
|||||||
32
config/config.go
Normal file
32
config/config.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LoadConfig liest die YAML-Konfigurationsdatei und parst sie in ein Config-Struct.
|
||||||
|
func loadConfig(path string) (*Config, error) {
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("fehler beim Lesen der Datei: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var cfg Config
|
||||||
|
if err := yaml.Unmarshal(data, &cfg); err != nil {
|
||||||
|
return nil, fmt.Errorf("fehler beim Parsen der YAML-Daten: %w", err)
|
||||||
|
}
|
||||||
|
return &cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetConfig() (*Config, error) {
|
||||||
|
config, err := loadConfig("misc/sample-config.yml")
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to read config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
|
||||||
|
}
|
||||||
24
config/data.go
Normal file
24
config/data.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
// Config bildet die Struktur der YAML-Konfiguration ab.
|
||||||
|
type Config struct {
|
||||||
|
Defaults Defaults `yaml:"defaults"`
|
||||||
|
Groups map[string]GroupDef `yaml:"groups"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defaults enthält Standardwerte.
|
||||||
|
type Defaults struct {
|
||||||
|
Temperatur int `yaml:"temperatur"`
|
||||||
|
Dimming int `yaml:"dimming"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupDef enthält die Details einer Gruppe, in diesem Fall eine Liste von Bulps.
|
||||||
|
type GroupDef struct {
|
||||||
|
Bulps []Bulp `yaml:"bulps"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bulp repräsentiert ein einzelnes Gerät.
|
||||||
|
type Bulp struct {
|
||||||
|
IP string `yaml:"ip"`
|
||||||
|
Port string `yaml:"port"`
|
||||||
|
}
|
||||||
66
controller/controller.go
Normal file
66
controller/controller.go
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO Implement wiz functions.
|
||||||
|
// https://dev.to/santosh/how-to-control-philips-wiz-bulb-using-go-2ad9
|
||||||
|
|
||||||
|
func TurnOn(ip string, port string, temperature int, dimming int) {
|
||||||
|
c, err := net.Dial("udp", fmt.Sprintf("%s:%s", ip, port))
|
||||||
|
if err != nil {
|
||||||
|
panic("Unable to connect to light bulp!")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Write([]byte(`{"method": "setPilot", "params":{"state": true, "temp": temperature, "dimming": dimming}}`))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TurnOff(ip string, port string) {
|
||||||
|
c, err := net.Dial("udp", fmt.Sprintf("%s:%s", ip, port))
|
||||||
|
if err != nil {
|
||||||
|
panic("Unable to connect to light bulp!")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Write([]byte(`{"method": "setPilot", "params":{"state": false}}`))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetStatus(ip string, port string) (*StatusResponse, error) {
|
||||||
|
// Verbindung per UDP herstellen
|
||||||
|
conn, err := net.Dial("udp", fmt.Sprintf("%s:%s", ip, port))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to connect to light bulb: %w", err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
// Senden der Anfrage
|
||||||
|
request := []byte(`{"method": "getPilot", "params":{}}`)
|
||||||
|
_, err = conn.Write(request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to send request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setzen eines Lese-Timeouts, da UDP keine Garantie für Antwortlieferung gibt.
|
||||||
|
deadline := time.Now().Add(3 * time.Second)
|
||||||
|
if err := conn.SetReadDeadline(deadline); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to set read deadline: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buffer, um die Antwort zu lesen
|
||||||
|
buffer := make([]byte, 2048)
|
||||||
|
n, err := conn.Read(buffer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to read response: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parsen der JSON-Antwort in das Struct
|
||||||
|
var status StatusResponse
|
||||||
|
if err := json.Unmarshal(buffer[:n], &status); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse response: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &status, nil
|
||||||
|
}
|
||||||
17
controller/data.go
Normal file
17
controller/data.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
type StatusResponse struct {
|
||||||
|
Method string `json:"method"`
|
||||||
|
Env string `json:"env"`
|
||||||
|
Result PilotDetails `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PilotDetails struct {
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
RSSI int `json:"rssi"`
|
||||||
|
Src string `json:"src"`
|
||||||
|
State bool `json:"state"`
|
||||||
|
SceneId int `json:"sceneId"`
|
||||||
|
Temp int `json:"temp"`
|
||||||
|
Dimming int `json:"dimming"`
|
||||||
|
}
|
||||||
100
devenv.lock
Normal file
100
devenv.lock
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"devenv": {
|
||||||
|
"locked": {
|
||||||
|
"dir": "src/modules",
|
||||||
|
"lastModified": 1739444039,
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "devenv",
|
||||||
|
"rev": "1235cd13f47df6ad19c8a183c6eabc1facb7c399",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"dir": "src/modules",
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "devenv",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-compat": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1733328505,
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gitignore": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"pre-commit-hooks",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1709087332,
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1733477122,
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "devenv-nixpkgs",
|
||||||
|
"rev": "7bd9e84d0452f6d2e63b6e6da29fe73fac951857",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "cachix",
|
||||||
|
"ref": "rolling",
|
||||||
|
"repo": "devenv-nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre-commit-hooks": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": "flake-compat",
|
||||||
|
"gitignore": "gitignore",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1737465171,
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "pre-commit-hooks.nix",
|
||||||
|
"rev": "9364dc02281ce2d37a1f55b6e51f7c0f65a75f17",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "pre-commit-hooks.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"devenv": "devenv",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"pre-commit-hooks": "pre-commit-hooks"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
47
devenv.nix
Normal file
47
devenv.nix
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
inputs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
# https://devenv.sh/basics/
|
||||||
|
env.GREET = "WIZ Controller";
|
||||||
|
|
||||||
|
# https://devenv.sh/packages/
|
||||||
|
packages = [pkgs.nmap];
|
||||||
|
|
||||||
|
# https://devenv.sh/languages/
|
||||||
|
languages.go.enable = true;
|
||||||
|
|
||||||
|
# https://devenv.sh/processes/
|
||||||
|
# processes.cargo-watch.exec = "cargo-watch";
|
||||||
|
|
||||||
|
# https://devenv.sh/services/
|
||||||
|
# services.postgres.enable = true;
|
||||||
|
|
||||||
|
# https://devenv.sh/scripts/
|
||||||
|
scripts.hello.exec = ''
|
||||||
|
echo hello from $GREET
|
||||||
|
'';
|
||||||
|
|
||||||
|
enterShell = ''
|
||||||
|
hello
|
||||||
|
'';
|
||||||
|
|
||||||
|
# https://devenv.sh/tasks/
|
||||||
|
# tasks = {
|
||||||
|
# "myproj:setup".exec = "mytool build";
|
||||||
|
# "devenv:enterShell".after = [ "myproj:setup" ];
|
||||||
|
# };
|
||||||
|
|
||||||
|
# https://devenv.sh/tests/
|
||||||
|
enterTest = ''
|
||||||
|
echo "Running tests"
|
||||||
|
'';
|
||||||
|
|
||||||
|
# https://devenv.sh/pre-commit-hooks/
|
||||||
|
# pre-commit.hooks.shellcheck.enable = true;
|
||||||
|
|
||||||
|
# See full reference at https://devenv.sh/reference/options/
|
||||||
|
}
|
||||||
15
devenv.yaml
Normal file
15
devenv.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# yaml-language-server: $schema=https://devenv.sh/devenv.schema.json
|
||||||
|
inputs:
|
||||||
|
nixpkgs:
|
||||||
|
url: github:cachix/devenv-nixpkgs/rolling
|
||||||
|
|
||||||
|
# If you're using non-OSS software, you can set allowUnfree to true.
|
||||||
|
# allowUnfree: true
|
||||||
|
|
||||||
|
# If you're willing to use a package that's vulnerable
|
||||||
|
# permittedInsecurePackages:
|
||||||
|
# - "openssl-1.1.1w"
|
||||||
|
|
||||||
|
# If you have more than one devenv you can merge them
|
||||||
|
#imports:
|
||||||
|
# - ./backend
|
||||||
5
go.mod
Normal file
5
go.mod
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module kattudden/wiz-controller
|
||||||
|
|
||||||
|
go 1.23.3
|
||||||
|
|
||||||
|
require gopkg.in/yaml.v2 v2.4.0
|
||||||
3
go.sum
Normal file
3
go.sum
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
28
main.go
Normal file
28
main.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"kattudden/wiz-controller/config"
|
||||||
|
"kattudden/wiz-controller/controller"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
config, err := config.GetConfig()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for groupName, group := range config.Groups {
|
||||||
|
fmt.Println("Gruppe:", groupName)
|
||||||
|
|
||||||
|
for _, bulp := range group.Bulps {
|
||||||
|
fmt.Printf(" Bulp: ip: %s, port: %s\n", bulp.IP, bulp.Port)
|
||||||
|
status, err := controller.GetStatus(bulp.IP, bulp.Port)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
fmt.Println("status:", status.Result.State)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
misc/sample-config.yml
Normal file
12
misc/sample-config.yml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
defaults:
|
||||||
|
temperatur: 2700
|
||||||
|
dimming: 100
|
||||||
|
groups:
|
||||||
|
wohnzimmer:
|
||||||
|
bulps:
|
||||||
|
- ip: "192.168.0.151"
|
||||||
|
port: "38899"
|
||||||
|
- ip: "192.168.0.152"
|
||||||
|
port: "38899"
|
||||||
|
- ip: "192.168.0.153"
|
||||||
|
port: "38899"
|
||||||
Reference in New Issue
Block a user