package main import ( "fmt" "image" "image/color" "net" "time" "git.openpdu.org/OpenPDU/openpdu/config" "git.openpdu.org/OpenPDU/openpdu/i2c" "git.openpdu.org/OpenPDU/openpdu/outlet" "git.openpdu.org/OpenPDU/openpdu/syslog" "golang.org/x/image/font" "golang.org/x/image/font/basicfont" "golang.org/x/image/math/fixed" "periph.io/x/devices/v3/ssd1306" ) func init() { syslog.Info("display setup") config.SetDefault("Display.Type", "none") config.SetDefault("Display.W", 128) config.SetDefault("Display.H", 32) config.SetDefault("Display.Rotated", false) config.SetDefault("Display.SwapTopBottom", false) config.SetDefault("Display.networkinterface", "eth0") } func displayLoop() { for { if config.GetString("Display.Type") != "ssd1306" { time.Sleep(1 * time.Second) continue } syslog.Info("ssd1306 display starting loop") if i2c.I2Cbus == nil { syslog.Warning("ssd1306 i2cbus not found") time.Sleep(1 * time.Second) continue } opts := ssd1306.Opts{ W: config.GetInt("Display.W"), H: config.GetInt("Display.H"), Rotated: config.GetBool("Display.Rotated"), Sequential: true, SwapTopBottom: config.GetBool("Display.SwapTopBottom"), } // Open a handle to a ssd1306 connected on the I²C bus: dev, err := ssd1306.NewI2C(i2c.I2Cbus, &opts) if err != nil { syslog.Err(err.Error()) } syslog.Info("ssd1306 display setup completed") for { err := disp(dev) if err != nil { syslog.Err(err.Error()) time.Sleep(1 * time.Second) syslog.Warning("ssd1306 display disp error") continue } } } } func addLabel(img *image.RGBA, x, y int, label string) { col := color.RGBA{200, 100, 0, 255} point := fixed.Point26_6{fixed.Int26_6(x * 64), fixed.Int26_6(y * 64)} d := &font.Drawer{ Dst: img, Src: image.NewUniform(col), Face: basicfont.Face7x13, Dot: point, } d.DrawString(label) } func getIPs() map[string]string { out := map[string]string{} ifaces, _ := net.Interfaces() // handle err for _, i := range ifaces { if i.Name == "lo" { continue } addrs, _ := i.Addrs() // handle err for _, addr := range addrs { var ip net.IP switch v := addr.(type) { case *net.IPNet: ip = v.IP case *net.IPAddr: ip = v.IP } // process IP address if ip.To4() == nil { continue } if len(out) < 1 { out[i.Name] = ip.String() } } } return out } func dispOutletStatusString() string { out := "" for o := range outlet.Outlets { if outlet.Outlets[o].Channel.Status() { out += fmt.Sprint(outlet.Outlets[o].Num) } else { out += "." } } return out } func disp(dev *ssd1306.Dev) error { img := image.NewRGBA(image.Rect(0, 0, 128, 32)) iface := config.GetString("Display.NetworkInterface") ips := getIPs() ip, found := ips[iface] if !found { ip = "unknown" } lineHeight := 12 posX := 12 posY := lineHeight addLabel(img, posX, posY, ip) posY += lineHeight addLabel(img, posX, posY, dispOutletStatusString()) return dev.Draw(img.Bounds(), img, image.Point{}) }