From f11cb57dfc2f1233fe198d7f89514370162f0ec1 Mon Sep 17 00:00:00 2001 From: AKP Date: Thu, 31 Mar 2022 10:43:42 +0100 Subject: [PATCH] Add WiFi and IP address blocks --- cmd/bar/main.go | 2 + go.mod | 7 +- go.sum | 4 + internal/providers/ipAddr.go | 77 +++++++++++++++++++ internal/providers/providers.go | 7 -- internal/providers/wifi.go | 128 ++++++++++++++++++++++++++++++++ 6 files changed, 217 insertions(+), 8 deletions(-) create mode 100644 go.sum create mode 100644 internal/providers/ipAddr.go create mode 100644 internal/providers/wifi.go diff --git a/cmd/bar/main.go b/cmd/bar/main.go index 077c00f..2a936e9 100644 --- a/cmd/bar/main.go +++ b/cmd/bar/main.go @@ -25,6 +25,8 @@ func run() error { } blocks := []i3bar.BlockGenerator{ + providers.NewIPAddress("wlp0s20f3"), + providers.NewWiFi("wlp0s20f3", 75), providers.NewBattery("BAT0", 80, 30, 20), providers.NewDisk("/", 30, 10), providers.NewCPU(20, 50), diff --git a/go.mod b/go.mod index 3456b17..f2ada1f 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,8 @@ module github.com/codemicro/bar -go 1.17 +go 1.18 + +require ( + github.com/samber/lo v1.11.0 // indirect + golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..0302b0b --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +github.com/samber/lo v1.11.0 h1:JfeYozXL1xfkhRUFOfH13ociyeiLSC/GRJjGKI668xM= +github.com/samber/lo v1.11.0/go.mod h1:2I7tgIv8Q1SG2xEIkRq0F2i2zgxVpnyPOP0d3Gj2r+A= +golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM= +golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= diff --git a/internal/providers/ipAddr.go b/internal/providers/ipAddr.go new file mode 100644 index 0000000..c96b53f --- /dev/null +++ b/internal/providers/ipAddr.go @@ -0,0 +1,77 @@ +package providers + +import ( + "fmt" + "strings" + + "github.com/codemicro/bar/internal/i3bar" + "github.com/samber/lo" +) + +type IPAddress struct { + Adapter string +} + +func NewIPAddress(adapter string) i3bar.BlockGenerator { + return &IPAddress{ + Adapter: adapter, + } +} + +func (g *IPAddress) getAdapterIPAddress() (string, error) { + // call ifconfig + output, err := runCommand("ifconfig") + if err != nil { + return "", err + } + + adapters := lo.Filter( + strings.Split(string(output), "\n\n"), + func(x string, _ int) bool { + return x != "" + }, + ) + + var ipAddr string + + // parse output + // split by \n\n + for _, adapter := range adapters { + fields := strings.Fields(adapter) + + if !strings.EqualFold( + strings.TrimSuffix(fields[0], ":"), g.Adapter, + ) { + continue + } + + for i, field := range fields { + if field == "inet" { + ipAddr = fields[i+1] + break + } + } + } + + return ipAddr, nil +} + +func (g *IPAddress) Block(colors *i3bar.ColorSet) (*i3bar.Block, error) { + ipAddr, err := g.getAdapterIPAddress() + if err != nil { + return nil, err + } + + block := new(i3bar.Block) + + if ipAddr == "" { + block.TextColor = colors.Bad + block.FullText = fmt.Sprintf("%s no IP", g.Adapter) + block.ShortText = "no IP" + } else { + block.TextColor = colors.Good + block.FullText = ipAddr + } + + return block, nil +} diff --git a/internal/providers/providers.go b/internal/providers/providers.go index 856333c..f90095f 100644 --- a/internal/providers/providers.go +++ b/internal/providers/providers.go @@ -4,15 +4,8 @@ import ( "fmt" "os/exec" "strings" - - "github.com/codemicro/bar/internal/i3bar" ) -var Known = map[string]func() i3bar.BlockGenerator{ - "datetime": NewDateTime, - "pulseaudioVolume": NewPulseaudioVolume, -} - func runCommand(program string, args ...string) ([]byte, error) { cmd := exec.Command(program, args...) out, err := cmd.Output() diff --git a/internal/providers/wifi.go b/internal/providers/wifi.go new file mode 100644 index 0000000..70945f7 --- /dev/null +++ b/internal/providers/wifi.go @@ -0,0 +1,128 @@ +package providers + +import ( + "fmt" + "regexp" + "strconv" + "strings" + + "github.com/codemicro/bar/internal/i3bar" + "github.com/samber/lo" +) + +type WiFi struct { + Adapter string + OkThreshold float32 +} + +func NewWiFi(adapter string, okThreshold float32) i3bar.BlockGenerator { + return &WiFi{ + Adapter: adapter, + OkThreshold: okThreshold, + } +} + +var ( + // For use with iwconfig + essidRegexp = regexp.MustCompile(`ESSID:(?:"(.+)"|off/any)`) + frequencyRegexp = regexp.MustCompile(`Frequency:(\d(?:\.\d+)? [a-zA-Z]Hz)`) + linkQualityRegexp = regexp.MustCompile(`Link Quality=(\d+\/\d+)`) +) + +func (g *WiFi) getAdapterIPAddress() (string, error) { + // call ifconfig + output, err := runCommand("ifconfig") + if err != nil { + return "", err + } + + adapters := lo.Filter( + strings.Split(string(output), "\n\n"), + func(x string, _ int) bool { + return x != "" + }, + ) + + var ipAddr string + + // parse output + // split by \n\n + for _, adapter := range adapters { + fields := strings.Fields(adapter) + + if !strings.EqualFold( + strings.TrimSuffix(fields[0], ":"), g.Adapter, + ) { + continue + } + + for i, field := range fields { + if field == "inet" { + ipAddr = fields[i+1] + break + } + } + } + + return ipAddr, nil +} + +func (g *WiFi) getConnectionInfo() (ssid, frequency string, linkQuality float32, err error) { + output, err := runCommand("iwconfig") + if err != nil { + return "", "", 0, err + } + + adapters := lo.Filter(strings.Split(string(output), "\n\n"), func(x string, _ int) bool { + return x != "" + }) + + for _, adapterInfo := range adapters { + if !strings.HasPrefix(adapterInfo, g.Adapter) { + continue + } + + if essidRegexp.MatchString(adapterInfo) { + ssid = essidRegexp.FindStringSubmatch(adapterInfo)[1] + } + + if frequencyRegexp.MatchString(adapterInfo) { + frequency = frequencyRegexp.FindStringSubmatch(adapterInfo)[1] + } + + if linkQualityRegexp.MatchString(adapterInfo) { + eqn := linkQualityRegexp.FindStringSubmatch(adapterInfo)[1] + sp := strings.Split(eqn, "/") + num, _ := strconv.Atoi(sp[0]) + denom, _ := strconv.Atoi(sp[1]) + linkQuality = (float32(num) / float32(denom)) * 100 + } + } + + return +} + +func (g *WiFi) Block(colors *i3bar.ColorSet) (*i3bar.Block, error) { + ssid, frequency, linkQuality, err := g.getConnectionInfo() + if err != nil { + return nil, err + } + + block := new(i3bar.Block) + + if ssid == "" { + block.TextColor = colors.Bad + block.FullText = fmt.Sprintf("%s not connected", g.Adapter) + block.ShortText = "not connected" + } else { + + if linkQuality < g.OkThreshold && g.OkThreshold != 0 { + block.TextColor = colors.Warning + } + + block.TextColor = colors.Good + block.FullText = fmt.Sprintf("%s (%s) %.0f%%", ssid, strings.ReplaceAll(frequency, " ", ""), linkQuality) + } + + return block, nil +}