This commit is contained in:
Michael Lehmann
2025-02-18 21:06:52 +01:00
parent da6b2ec0ef
commit 088a15975c
13 changed files with 361 additions and 0 deletions

3
.envrc Normal file
View File

@@ -0,0 +1,3 @@
source_url "https://raw.githubusercontent.com/cachix/devenv/82c0147677e510b247d8b9165c54f73d32dfd899/direnvrc" "sha256-7u4iDd1nZpxL4tCzmPG0dQgC5V+/44Ba+tHkPob1v2k="
use devenv

9
.gitignore vendored
View File

@@ -23,3 +23,12 @@ go.work.sum
# env file
.env
# Devenv
.devenv*
devenv.local.nix
# direnv
.direnv
# pre-commit
.pre-commit-config.yaml

32
config/config.go Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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"