first commit of files
This commit is contained in:
143
models/bus.go
Normal file
143
models/bus.go
Normal file
@@ -0,0 +1,143 @@
|
||||
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
|
||||
}
|
Reference in New Issue
Block a user