package led import ( "errors" "rpi-ci-led/pkg/ws2812b" "time" ) type LEDSvc struct { pin int count int blink map[int]chan struct{} done chan struct{} } var led *LEDSvc func Init(pin, count int) (*LEDSvc, error) { _, err := ws2812b.Init(pin, count, 255) if err != nil { return nil, err } return &LEDSvc{ pin: pin, count: count, blink: make(map[int]chan struct{}), done: make(chan struct{}), }, nil } func Get() *LEDSvc { if led == nil { panic(errors.New("not init")) } return led } func (p *LEDSvc) Stop() { for k := range p.blink { p.StopBlink(k) } ws2812b.ClearAll() close(p.done) } func (p *LEDSvc) SetColor(pos int, color uint32) error { if pos < 0 || pos > p.count { return errors.New("out of range") } if ch, ok := p.blink[pos]; ok { close(ch) delete(p.blink, pos) } ws2812b.WriteColor(pos, color) return nil } func (p *LEDSvc) StopBlink(pos int) { if ch, ok := p.blink[pos]; ok { close(ch) delete(p.blink, pos) } } func (p *LEDSvc) SetBlink(pos int, color uint32, interval time.Duration) { if ch, ok := p.blink[pos]; ok { close(ch) delete(p.blink, pos) } go func() { defer func() { ws2812b.WriteColor(pos, 0) delete(p.blink, pos) }() ch := make(chan struct{}) p.blink[pos] = ch timer := time.NewTicker(interval) on := false for { select { case <-ch: return case <-timer.C: if on { ws2812b.WriteColor(pos, 0) } else { ws2812b.WriteColor(pos, color) } on = !on } } }() } func (p *LEDSvc) Run() { ticker := time.NewTicker(time.Millisecond * 100) for { select { case <-p.done: return case <-ticker.C: } } }