diff options
| author | Oleg Pykhalov <go.wigust@gmail.com> | 2023-10-10 17:19:02 +0300 |
|---|---|---|
| committer | Oleg Pykhalov <go.wigust@gmail.com> | 2023-10-22 07:02:55 +0300 |
| commit | 4f75e84825247e5b6a780c10847b60d1c635c59c (patch) | |
| tree | 326e1bee993f57bfc9abf0765e7af638f4ed11ec | |
| download | ddcutil-daemon-4f75e84825247e5b6a780c10847b60d1c635c59c.tar.gz | |
Initial commit.
| -rw-r--r-- | .github/workflows/build.yml | 34 | ||||
| -rw-r--r-- | README.md | 50 | ||||
| -rw-r--r-- | ddcutil-daemon.json | 4 | ||||
| -rw-r--r-- | flake.lock | 25 | ||||
| -rw-r--r-- | flake.nix | 39 | ||||
| -rw-r--r-- | go.mod | 3 | ||||
| -rw-r--r-- | main.go | 176 |
7 files changed, 331 insertions, 0 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..3961181 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,34 @@ +name: "Build" +on: + pull_request: + push: +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2.4.0 + - uses: cachix/install-nix-action@v15 + with: + extra_nix_config: | + access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} + - run: nix build + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + draft: false + prerelease: false + - name: Upload Release Asset + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + asset_path: ./result/bin/ddcutil-daemon + asset_name: ddcutil-daemon + asset_content_type: application/octet-stream diff --git a/README.md b/README.md new file mode 100644 index 0000000..6d97db7 --- /dev/null +++ b/README.md @@ -0,0 +1,50 @@ +# Description + +HTTP service to control monitor brightness. + +# Requirements + +* go 1.17.11 +* ddcutil 1.2.2 +* linux 5.13.16 + +# Build + +``` shell +nix build +``` + +# Run + +``` +sudo result/bin/ddcutil-daemon +``` + +The `ddcutil` binary should run with root privileges, so we use `sudo`. + +# Usage + +Get current brightness cached value: +```shell +curl 127.0.0.1:49281/set +``` + +Set brightness to specific value: +```shell +curl --request POST --data '{'value': 5}' 127.0.0.1:49281/set +``` + +Increase brightness: +```shell +curl --request POST --data '{"value": 5}' 127.0.0.1:49281/increase +``` + +Decrease brightness: +```shell +curl --request POST --data '{"value": 5}' 127.0.0.1:49281/decrease +``` + +Toggle brightness between current and minimal values: +```shell +curl --request POST 127.0.0.1:49281/toggle +``` diff --git a/ddcutil-daemon.json b/ddcutil-daemon.json new file mode 100644 index 0000000..33e9a05 --- /dev/null +++ b/ddcutil-daemon.json @@ -0,0 +1,4 @@ +{ + "listen": "127.0.0.1:49281", + "vcp": "10" +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..858d802 --- /dev/null +++ b/flake.lock @@ -0,0 +1,25 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1697886341, + "narHash": "sha256-AdE67xPty9M9wn36nPVp6aDntIdigrs7UbyaGv1VAaM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "44881e03af1c730cbb1d72a4d41274a2c957813a", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..44823ef --- /dev/null +++ b/flake.nix @@ -0,0 +1,39 @@ +{ + description = "HTTP service to control monitor brightness"; + + outputs = { self, nixpkgs, ... }: + let system = "x86_64-linux"; + in { + packages.${system} = { + default = nixpkgs.legacyPackages.${system}.callPackage + ({ lib, go, buildGoModule }: + buildGoModule rec { + pname = "ddcutil-daemon"; + version = "0.0.1"; + src = ./.; + # preConfigure phase to compile a statically linked executable + preConfigure = '' + export CGO_ENABLED=0 + export GOOS=linux + export GOARCH=amd64 + ''; + ldflags = let t = "github.com/kitnil/ddcutil-daemon"; + in [ + "-s" # stripped binary + "-X ${t}.Version=${version}" + "-X ${t}.Branch=unknown" + "-X ${t}.BuildUser=nix@nixpkgs" + "-X ${t}.BuildDate=unknown" + "-X ${t}.GoVersion=${lib.getVersion go}" + ]; + vendorSha256 = null; + meta = with lib; { + description = "HTTP service to control monitor brightness."; + homepage = "https://github.com/kitnil/ddcutil-daemon"; + license = licenses.asl20; + platforms = platforms.unix; + }; + }) { }; + }; + }; +} @@ -0,0 +1,3 @@ +module github.com/kitnil/ddcutil-daemon + +go 1.17 @@ -0,0 +1,176 @@ +package main + +import ( + "encoding/json" + "io" + "io/ioutil" + "log" + "net/http" + "os" + "os/exec" + "strconv" + "strings" +) + +type Configuration struct { + Listen string + Vcp string +} + +var configuration = Configuration{ + Listen: "127.0.0.1:49281", + Vcp: "10"} + +type Brightness struct { + Lock bool + Value int + ToggledValue int +} + +var currentBrightness Brightness + +func update() { + if currentBrightness.Lock == false { + currentBrightness.Lock = true + cmd := exec.Command("ddcutil", "getvcp", "--brief", configuration.Vcp) + log.Println(cmd.String()) + out, err := cmd.CombinedOutput() + if err != nil { + log.Println(err) + return + } + outString := strings.Split(strings.Trim(string(out), "\n"), " ") + currentBrightness.Value, err = strconv.Atoi(outString[len(outString)-2]) + if err != nil { + log.Println(err) + return + } + log.Println("Current brightness is", currentBrightness.Value) + currentBrightness.Lock = false + } else { + log.Println("Active lock, no operation performed") + return + } +} + +func get(w http.ResponseWriter, r *http.Request) { + if r.Method == "GET" { + log.Println("Current brightness cached value is", + currentBrightness.Value) + } +} + +func ddcutilSetBrightness(brightness Brightness) { + if currentBrightness.Lock == false { + currentBrightness.Lock = true + cmd := exec.Command("ddcutil", "setvcp", configuration.Vcp, + strconv.Itoa(brightness.Value)) + log.Println(cmd.String()) + _, err := cmd.CombinedOutput() + if err != nil { + log.Println(err) + return + } + currentBrightness.Value = brightness.Value + currentBrightness.Lock = false + } else { + log.Println("Active lock, no operation performed") + return + } +} + +func set(w http.ResponseWriter, r *http.Request) { + if r.Method == "POST" { + body, err := io.ReadAll(r.Body) + if err != nil { + log.Println(err) + return + } + var brightness Brightness + json.Unmarshal([]byte(body), &brightness) + ddcutilSetBrightness(brightness) + } +} + +func decrease(w http.ResponseWriter, r *http.Request) { + if r.Method == "POST" { + body, err := io.ReadAll(r.Body) + if err != nil { + log.Println(err) + return + } + var brightness Brightness + json.Unmarshal([]byte(body), &brightness) + newValue := Brightness{Value: currentBrightness.Value - brightness.Value} + if newValue.Value < 0 { + log.Println("Brightness is minimum") + } else { + ddcutilSetBrightness(newValue) + log.Println("Current brightness is", currentBrightness.Value) + } + } else { + log.Println("Active lock, no operation performed") + return + } +} + +func increase(w http.ResponseWriter, r *http.Request) { + if r.Method == "POST" { + body, err := io.ReadAll(r.Body) + if err != nil { + log.Println(err) + return + } + var brightness Brightness + json.Unmarshal([]byte(body), &brightness) + newValue := Brightness{Value: currentBrightness.Value + brightness.Value} + if newValue.Value > 100 { + log.Println("Brightness is maximum") + } else { + ddcutilSetBrightness(newValue) + log.Println("Current brightness is", currentBrightness.Value) + } + } else { + log.Println("Active lock, no operation performed") + return + } +} + +func toggle(w http.ResponseWriter, r *http.Request) { + if r.Method == "POST" { + if currentBrightness.Value == 0 { + ddcutilSetBrightness(Brightness{Value: currentBrightness.ToggledValue}) + log.Println("Current brightness is", currentBrightness.Value) + } else { + currentBrightness.ToggledValue = currentBrightness.Value + ddcutilSetBrightness(Brightness{Value: 0}) + log.Println("Current brightness is", currentBrightness.Value) + } + } +} + +func main() { + jsonFile, err := os.Open("ddcutil-daemon.json") + if err != nil { + log.Fatalln(err) + } + byteValue, err := ioutil.ReadAll(jsonFile) + if err != nil { + log.Fatalln(err) + } + var configuration Configuration + json.Unmarshal(byteValue, &configuration) + jsonFile.Close() + + currentBrightness.Lock = false + update() + http.HandleFunc("/update", func(w http.ResponseWriter, r *http.Request) { + update() + }) + http.HandleFunc("/get", get) + http.HandleFunc("/set", set) + http.HandleFunc("/decrease", decrease) + http.HandleFunc("/increase", increase) + http.HandleFunc("/toggle", toggle) + log.Fatal(http.ListenAndServe(configuration.Listen, nil)) +} |
