Browse Source

inital commit of PCA9685 backend in go

master
Giovanni Harting 2 years ago
parent
commit
ffe46a0f4b
5 changed files with 261 additions and 0 deletions
  1. +99
    -0
      .gitignore
  2. +3
    -0
      .gitmodules
  3. +9
    -0
      config.yaml
  4. +149
    -0
      main.go
  5. +1
    -0
      proto

+ 99
- 0
.gitignore View File

@@ -0,0 +1,99 @@
# Created by https://www.gitignore.io/api/go,linux,intellij+all

### Go ###
# Binaries for programs and plugins
*.exe
*.dll
*.so
*.dylib

# Test binary, build with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/

### Intellij+all ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries

# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml

# Gradle:
.idea/**/gradle.xml
.idea/**/libraries

# CMake
cmake-build-debug/

# Mongo Explorer plugin:
.idea/**/mongoSettings.xml

## File-based project format:
*.iws

## Plugin-specific files:

# IntelliJ
/out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Cursive Clojure plugin
.idea/replstate.xml

# Ruby plugin and RubyMine
/.rakeTasks

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

### Intellij+all Patch ###
# Ignores the whole idea folder
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360

.idea/

### Linux ###
*~

# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*

# KDE directory preferences
.directory

# Linux trash folder which might appear on any partition or disk
.Trash-*

# .nfs files are created when an open file is removed but is still being accessed
.nfs*

# End of https://www.gitignore.io/api/go,linux,intellij+all

bin/
pkg/
src/


+ 3
- 0
.gitmodules View File

@@ -0,0 +1,3 @@
[submodule "proto"]
path = proto
url = git@github.com:LED-Freaks/LedD-protobuf.git

+ 9
- 0
config.yaml View File

@@ -0,0 +1,9 @@
name: PCA9685
ledd:
host: "127.0.0.1"
port: 5640
pca9685:
device: "dev/i2c-2"
address: 0x40
minpulse: 0
maxpulse: 1000

+ 149
- 0
main.go View File

@@ -0,0 +1,149 @@
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
}

+ 1
- 0
proto

@@ -0,0 +1 @@
Subproject commit c0b46db0cf38cfd192d6a787c0328cbff8db42fb

Loading…
Cancel
Save