Files
LedD.PCA9685/main.go

150 lines
2.7 KiB
Go

package main
import (
"github.com/op/go-logging"
"golang.org/x/exp/io/i2c"
"gopkg.in/yaml.v2"
"os"
"os/signal"
"syscall"
"io/ioutil"
"net"
"encoding/binary"
"gen/ledd"
"github.com/golang/protobuf/proto"
"github.com/sergiorb/pca9685-golang/device"
"fmt"
)
// CONSTANTS
const VERSION = "0.1"
const RESOLUTION = 4096
const CHANNEL = 16
// STRUCTS
type config struct {
Name string
Ledd struct {
Host string
Port int
}
Pca9685 struct {
Device string
Address int
MinPulse int
MaxPulse int
}
}
type LedD struct {
name string
socket net.Conn
data chan []byte
}
var log = logging.MustGetLogger("LedD")
var ledDaemon = &LedD{}
var pca9685 = device.PCA9685{}
func check(e error) {
if e != nil {
panic(e)
}
}
func (ledd *LedD) receive() {
for {
message := make([]byte, 4096)
length, err := ledd.socket.Read(message)
if err != nil {
ledd.socket.Close()
break
}
if length > 0 {
msgLen := binary.BigEndian.Uint32(message[0:3])
log.Debugf("[%s] Read %d bytes, first protobuf is %d long", ledd.name, length, msgLen)
backendMsg := &ledd.BackendWrapperMessage{}
err = proto.Unmarshal(message[4:msgLen], backendMsg)
if err != nil {
log.Warningf("[%s] Couldn't decode protobuf msg!", backend.niceName())
continue
}
switch msg := backendMsg.Msg.(type) {
case *ledd.BackendWrapperMessage_MLedd:
ledd.name = msg.MLedd.Name
log.Infof("Connection with LedD (%s) etablished and registered", msg.MLedd.Name)
}
}
}
}
func (ledd *LedD) send() {
defer ledd.socket.Close()
for {
select {
case message, ok := <-ledd.data:
if !ok {
return
}
ledd.socket.Write(message)
}
}
}
func main() {
killSignals := make(chan os.Signal, 1)
signal.Notify(killSignals, syscall.SIGINT, syscall.SIGTERM)
log.Info("LedD", VERSION)
config := config{}
content, err := ioutil.ReadFile("config.yaml")
check(err)
err = yaml.Unmarshal(content, &config)
check(err)
i2cDevice, err := i2c.Open(&i2c.Devfs{Dev: config.Pca9685.Device}, config.Pca9685.Address)
check(err)
defer i2cDevice.Close()
pca9685 := device.NewPCA9685(i2cDevice, "PWM Controller", config.Pca9685.MinPulse, config.Pca9685.MaxPulse, log)
pca9685.Init()
conn, err := net.Dial("tcp4", fmt.Sprintf("%s:%d", config.Ledd.Host, config.Ledd.Port))
check(err)
ledDaemon = &LedD{
socket:conn,
data: make (chan []byte),
}
go ledDaemon.send()
go ledDaemon.receive()
wrapperMsg := &ledd.BackendWrapperMessage{
Msg: &ledd.BackendWrapperMessage_MBackend{
MBackend: &ledd.Backend{
Name: config.Name,
Channel: CHANNEL,
Type: "PCA9685",
Resolution: RESOLUTION,
Version: VERSION,
},
},
}
data, err := proto.Marshal(wrapperMsg)
check(err)
ledDaemon.data <- data
<-killSignals
}