You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Polybar中用Golang避免循环并实现Hue灯切换

解决Polybar控制Philips Hue灯的循环切换与状态显示问题

问题核心

  • 直接用Polybar custom/script 的 exec 属性调用切换程序时,因模块周期性重复执行exec,导致灯反复开关
  • 点击触发切换无法同步显示状态图标,需要让exec负责查询状态、点击事件负责执行切换

修复步骤

1. 修改Golang代码,支持双模式运行

让程序通过命令行参数区分「查询状态」和「执行切换」两种模式:

package main

import (
    "encoding/json"
    "flag"
    "fmt"
    "log"
    "net/http"
    "strings"
)

type config struct {
    ip   string
    user string
}

type State struct {
    On bool `json:"on"`
}
type StatusResponse struct {
    State State `json:"state"`
}

func main() {
    var cfg config
    var mode string

    flag.StringVar(&cfg.ip, "ip", "myip", "PHUE IP address")
    flag.StringVar(&cfg.user, "user", "my-user", "PHUE User")
    flag.StringVar(&mode, "mode", "status", "运行模式: status(查询状态)/toggle(切换开关)")
    flag.Parse()

    light1On := getLightStatus(cfg.ip, cfg.user, "1")
    light4On := getLightStatus(cfg.ip, cfg.user, "4")

    switch mode {
    case "toggle":
        // 执行切换逻辑:统一开关灯
        targetState := !(light1On && light4On)
        action := "off"
        if targetState {
            action = "on"
        }
        turnLight(cfg.ip, cfg.user, "1", action)
        turnLight(cfg.ip, cfg.user, "4", action)
    case "status":
        // 输出状态对应的图标(可替换为你需要的图标字符)
        if light1On && light4On {
            fmt.Println("") // 灯亮图标
        } else {
            fmt.Println("") // 灯灭图标
        }
    }
}

// 重命名函数更准确
func turnLight(ip, user, lightID, action string) {
    url := fmt.Sprintf("http://%s/api/%s/lights/%s/state", ip, user, lightID)
    var turnStatus string

    if action == "on" {
        turnStatus = `{"on":true}`
    } else if action == "off" {
        turnStatus = `{"on":false}`
    } else {
        log.Fatalf("无效的action: %s", action)
    }

    req, err := http.NewRequest(http.MethodPut, url, strings.NewReader(turnStatus))
    if err != nil {
        log.Fatalf("创建请求失败: %v", err)
    }
    req.Header.Set("Content-Type", "application/json")

    client := http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        log.Fatalf("发送请求失败: %v", err)
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        log.Fatalf("响应状态异常: %s", resp.Status)
    }
}

func getLightStatus(ip, user, lightID string) bool {
    url := fmt.Sprintf("http://%s/api/%s/lights/%s", ip, user, lightID)

    resp, err := http.Get(url)
    if err != nil {
        log.Fatalf("获取状态失败: %v", err)
    }
    defer resp.Body.Close()

    var status StatusResponse
    dec := json.NewDecoder(resp.Body)
    err = dec.Decode(&status)
    if err != nil {
        log.Fatalf("解析响应失败: %v", err)
    }

    return status.State.On
}

2. 调整Polybar配置

让exec定期查询状态显示图标,click-left触发切换操作:

[module/hue]
type = custom/script
format = "%{T2}%{F#f6e58d}%output% %{F-}%{T-}Philip HUE"
; 每隔2秒查询一次状态,可根据需求调整
interval = 2
; 执行状态查询模式,替换为你的HUE桥接器IP和用户ID
exec = ~/.config/scripts/main -ip "你的HUE桥接器IP" -user "你的HUE用户ID" -mode status
; 点击时执行切换模式,加&让后台运行避免阻塞Polybar
click-left = exec ~/.config/scripts/main -ip "你的HUE桥接器IP" -user "你的HUE用户ID" -mode toggle &

关键说明

  • 避免循环:将切换逻辑从exec移到click-left,exec仅负责查询状态,模块定期执行exec只会更新图标,不会触发开关
  • 状态同步:通过interval参数控制状态刷新频率,确保图标和实际灯状态一致
  • 图标替换:代码中的和是Nerd Fonts图标,可根据你的字体替换为其他合适的开关图标

内容的提问来源于stack exchange,提问作者xDonYeyox

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 07:08:14