package models import ( "fmt" "net" "time" "github.com/tatsushid/go-fastping" ) // Art-Net constants const ( artPort = 6454 ) // Art-Net Interface type Bus struct { ip string `yaml:"ip"` port int `yaml:"port"` Devices []*Device `yaml:"devices"` Data *DMX } // adds new Art-Net interface to driver port 0 = 6454 (default art-net) func NewBus(ip string, port int) *Bus { if port == 0 { port = artPort } i := Bus{ ip: ip, port: port, Data: NewDMXUniverse(), } return &i } // adds new dmx device to interface func (i *Bus) AddDevice(address uint, channels uint) (*Device, error) { d := NewDevice(address, channels, i.Data) i.Devices = append(i.Devices, d) return d, nil } // start polling dmx data in milliseconds 0 = aprox. 44Hertz func (i *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(i.ip), Port: i.port, }) if err != nil { return err } defer conn.Close() var errCount int for { go func() { for { if reached, _ := isUDPReachable(i.ip); !reached { if errCount > 20 { break } else { errCount += 1 return } } else { errCount = 0 break } } }() _, err = conn.Write(NewArtNetPackage(i.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 (i *Bus) SendData() error { // Send packet over UDP conn, err := net.DialUDP("udp", nil, &net.UDPAddr{ IP: net.ParseIP(i.ip), Port: i.port, }) if err != nil { return err } defer conn.Close() errChan := make(chan error) go func() { if reached, _ := isUDPReachable(i.ip); !reached { errChan <- fmt.Errorf("device not reachable") return } errChan <- nil }() err = <-errChan if err != nil { return err } _, err = conn.Write(NewArtNetPackage(i.Data)) return err } const ( protocolICMP = 1 ) 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 return } p.OnIdle = func() {} err = p.Run() return }