package models import ( "fmt" "log" "net" "time" "github.com/tatsushid/go-fastping" ) // Art-Net constants const ( artPort = 6454 ) // Art-Net Interface type Bus struct { Name string `yaml:"name" json:"name"` Ip string `yaml:"ip" json:"ip"` Port *int `yaml:"port" json:"port,omitempty"` Data *DMX `yaml:"-" json:"-"` } // adds new Art-Net interface to driver port 0 = 6454 (default art-net) func NewBus(name, ip string, port int) *Bus { if port == 0 { port = artPort } i := Bus{ Name: name, Ip: ip, Port: &port, Data: NewDMXUniverse(), } return &i } // get bus port from pointer func (b *Bus) GetPort() int { if b.Port == nil { return artPort } return *b.Port } // start polling dmx data in milliseconds 0 = aprox. 44Hertz func (b *Bus) Poll(interval time.Duration) error { if interval == 0 { interval = 23 } // Send packet over UDP conn, err := net.DialUDP("udp", nil, &net.UDPAddr{ IP: net.ParseIP(b.Ip), Port: *b.Port, }) if err != nil { return err } defer conn.Close() var errCount int for { go func() { for { if reached, _ := isUDPReachable(b.Ip); !reached { if errCount > 20 { break } else { errCount += 1 return } } else { errCount = 0 break } } }() _, err = conn.Write(NewArtNetPackage(b.Data)) if err != nil { return err } if errCount > 5 { return fmt.Errorf("device not reachable") } time.Sleep(23 * time.Millisecond) } } // start polling dmx data in milliseconds 0 = aprox. 44Hertz func (b *Bus) SendData() error { // Send packet over UDP conn, err := net.DialUDP("udp", nil, &net.UDPAddr{ IP: net.ParseIP(b.Ip), Port: *b.Port, }) if err != nil { return err } defer conn.Close() go func() { if reached, err := isUDPReachable(b.Ip); err != nil { log.Println(err) return } else if !reached { log.Println("device not reachable") return } }() _, err = conn.Write(NewArtNetPackage(b.Data)) return err } func isUDPReachable(ip string) (recieved bool, err error) { p := fastping.NewPinger() ra, err := net.ResolveIPAddr("ip4:icmp", ip) if err != nil { return } p.AddIPAddr(ra) p.OnRecv = func(addr *net.IPAddr, rtt time.Duration) { recieved = true } p.OnIdle = func() {} err = p.Run() return }