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
|
||||
# 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