arson on a massive scale
This commit is contained in:
commit
5233111f25
|
@ -0,0 +1,35 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/rileys-trash-can/newtecrs82obs"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
log.Fatalf("Usage: log <serial>")
|
||||
}
|
||||
|
||||
port := os.Args[1]
|
||||
conn, err := nt8.Open(port)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to connect: %s", err)
|
||||
}
|
||||
|
||||
conn.InitBlynk()
|
||||
|
||||
ch := conn.ReadCh()
|
||||
|
||||
for {
|
||||
e := <-ch
|
||||
|
||||
switch event := e.(type) {
|
||||
case *nt8.EventButton:
|
||||
log.Printf("%T %#v", event, event)
|
||||
|
||||
case *nt8.EventSlider:
|
||||
log.Printf("%X %3d", event.Type, event.Value)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
serial.port: "/dev/ttyUSB0"
|
||||
|
||||
boolshit: true
|
||||
|
||||
obs.addr: "10.10.42.160:4444"
|
||||
obs.pass: "asdfgh"
|
||||
|
||||
trans.auto: "Fade"
|
||||
trans.take: "Cut"
|
|
@ -0,0 +1,343 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
obs "github.com/andreykaipov/goobs"
|
||||
obse "github.com/andreykaipov/goobs/api/events"
|
||||
obss "github.com/andreykaipov/goobs/api/events/subscriptions"
|
||||
obssc "github.com/andreykaipov/goobs/api/requests/scenes"
|
||||
obst "github.com/andreykaipov/goobs/api/requests/transitions"
|
||||
"github.com/rileys-trash-can/newtecrs82obs"
|
||||
"gopkg.in/yaml.v3"
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
)
|
||||
|
||||
var Config config
|
||||
|
||||
type config struct {
|
||||
Serial string `yaml:"serial.port"`
|
||||
|
||||
Boolshit bool `yaml:"boolshit"` // enables disables bullshit
|
||||
|
||||
OBSAddr string `yaml:"obs.addr"` // ip with port
|
||||
OBSPass string `yaml:"obs.pass"` // password
|
||||
|
||||
TransAuto string `yaml:"trans.auto"` // transition used for auto button
|
||||
TransTake string `yaml:"trans.take"` // transition used for take button
|
||||
}
|
||||
|
||||
func readconfig() {
|
||||
f, err := os.OpenFile("config.yml", os.O_RDONLY, 0755)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to open config: %s", err)
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
dec := yaml.NewDecoder(f)
|
||||
err = dec.Decode(&Config)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to decode config: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.SetFlags(log.Flags() | log.Lshortfile)
|
||||
|
||||
readconfig()
|
||||
|
||||
port := Config.Serial
|
||||
conn, err := nt8.Open(port)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to connect: %s", err)
|
||||
}
|
||||
|
||||
// conn.InitBlynk()
|
||||
|
||||
ch := conn.ReadCh()
|
||||
|
||||
obsc, err := obs.New(Config.OBSAddr,
|
||||
obs.WithPassword(Config.OBSPass),
|
||||
obs.WithEventSubscriptions(obss.Scenes),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to connect: %s", err)
|
||||
}
|
||||
|
||||
t, err := obsc.Transitions.GetTransitionKindList()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to connect gtkl: %s", err)
|
||||
}
|
||||
|
||||
for _, name := range t.TransitionKinds {
|
||||
log.Printf(" > %s", name)
|
||||
}
|
||||
|
||||
sl, err := obsc.Scenes.GetSceneList()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to gsl: %s", err)
|
||||
}
|
||||
|
||||
sceneindex := make([]string, 8)
|
||||
scenenamemap := make(map[string]int)
|
||||
|
||||
lim := lower(len(sl.Scenes), 8)
|
||||
for i := 0; i < lim; i++ {
|
||||
sceneindex[i] = sl.Scenes[lim-i-1].SceneName
|
||||
scenenamemap[sl.Scenes[lim-i-1].SceneName] = i
|
||||
}
|
||||
|
||||
for k, v := range sceneindex {
|
||||
log.Printf("%d %v", k, v)
|
||||
}
|
||||
log.Printf("scenemap: %+#v", scenenamemap)
|
||||
|
||||
const (
|
||||
TBAR uint8 = iota
|
||||
)
|
||||
|
||||
ticker := time.NewTicker(time.Second / 10)
|
||||
changed := make(map[uint8]struct{})
|
||||
debounce := make(map[uint16]time.Time)
|
||||
var tbarbos float64
|
||||
|
||||
deb := func(t uint16) bool {
|
||||
now := time.Now()
|
||||
|
||||
last, ok := debounce[t]
|
||||
if !ok {
|
||||
debounce[t] = now
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
if last.Before(now.Add(-time.Millisecond * 100)) {
|
||||
debounce[t] = now
|
||||
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
go obsc.Listen(func(l any) {
|
||||
switch event := l.(type) {
|
||||
case *obse.CurrentPreviewSceneChanged:
|
||||
log.Printf("current preview scene: %s %d", event.SceneName, scenenamemap[event.SceneName]+1)
|
||||
program := make([]nt8.CmdLight, 0)
|
||||
|
||||
for i := uint8(0); i < 8; i++ {
|
||||
program = append(program, nt8.CmdLight{
|
||||
Type: nt8.ButtonPreview,
|
||||
Value: i,
|
||||
State: nt8.LightOff,
|
||||
})
|
||||
}
|
||||
|
||||
program[7-scenenamemap[event.SceneName]].State = nt8.LightOn
|
||||
|
||||
conn.LightCmdCh <- program
|
||||
break
|
||||
|
||||
case *obse.CurrentProgramSceneChanged:
|
||||
log.Printf("current program scene: %s %d", event.SceneName, scenenamemap[event.SceneName]+1)
|
||||
program := make([]nt8.CmdLight, 0)
|
||||
|
||||
for i := uint8(0); i < 8; i++ {
|
||||
program = append(program, nt8.CmdLight{
|
||||
Type: nt8.ButtonProgram,
|
||||
Value: i,
|
||||
State: nt8.LightOff,
|
||||
})
|
||||
}
|
||||
|
||||
program[7-scenenamemap[event.SceneName]].State = nt8.LightOn
|
||||
|
||||
conn.LightCmdCh <- program
|
||||
break
|
||||
|
||||
default:
|
||||
//log.Printf("non handled thingy %T", event)
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
if _, ok := changed[TBAR]; ok {
|
||||
_, err = obsc.Transitions.SetTBarPosition(&obst.SetTBarPositionParams{
|
||||
Position: i(tbarbos),
|
||||
Release: i(tbarbos == 0 || tbarbos == 1),
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Error setting tbar: %s", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
changed = make(map[uint8]struct{})
|
||||
|
||||
case e := <-ch:
|
||||
switch event := e.(type) {
|
||||
case *nt8.EventButton:
|
||||
if event.Direction != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
switch event.Type {
|
||||
case nt8.ButtonProgram:
|
||||
log.Printf("Setting Program to %d", 7-event.Value)
|
||||
obsc.Scenes.SetCurrentProgramScene(&obssc.SetCurrentProgramSceneParams{
|
||||
SceneName: &sceneindex[7-event.Value],
|
||||
})
|
||||
|
||||
break
|
||||
case nt8.ButtonPreview:
|
||||
log.Printf("Setting Program to %d", 7-event.Value)
|
||||
obsc.Scenes.SetCurrentPreviewScene(&obssc.SetCurrentPreviewSceneParams{
|
||||
SceneName: &sceneindex[7-event.Value],
|
||||
})
|
||||
|
||||
break
|
||||
case nt8.ButtonAutoTakeDSK:
|
||||
switch event.Value {
|
||||
case 0x01: // TAKE or 0x02
|
||||
if deb(nt8.ButtonAutoTakeDSK<<8 | 0x01) {
|
||||
continue
|
||||
}
|
||||
|
||||
go func() {
|
||||
oldprog, err := obsc.Scenes.GetCurrentProgramScene()
|
||||
if err != nil {
|
||||
log.Printf("oldprogram: %s (uuid %s)", oldprog.SceneName, oldprog.SceneUuid)
|
||||
}
|
||||
|
||||
_, err = obsc.Transitions.SetCurrentSceneTransition(&obst.SetCurrentSceneTransitionParams{
|
||||
TransitionName: &Config.TransTake,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("set transition: %s", err)
|
||||
}
|
||||
|
||||
_, err = obsc.Transitions.TriggerStudioModeTransition()
|
||||
if err != nil {
|
||||
log.Printf("Studiomodetransition: %s", err)
|
||||
}
|
||||
|
||||
_, err = obsc.Scenes.SetCurrentPreviewScene(&obssc.SetCurrentPreviewSceneParams{
|
||||
SceneUuid: &oldprog.SceneUuid,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("set current preview: %s", err)
|
||||
}
|
||||
}()
|
||||
case 0x03: // AUTO
|
||||
|
||||
go func() {
|
||||
oldprog, err := obsc.Scenes.GetCurrentProgramScene()
|
||||
if err != nil {
|
||||
log.Printf("oldprogram: %s (uuid %s)", oldprog.SceneName, oldprog.SceneUuid)
|
||||
}
|
||||
|
||||
_, err = obsc.Transitions.SetCurrentSceneTransition(&obst.SetCurrentSceneTransitionParams{
|
||||
TransitionName: &Config.TransAuto,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("set transition: %s", err)
|
||||
}
|
||||
|
||||
_, err = obsc.Transitions.TriggerStudioModeTransition()
|
||||
if err != nil {
|
||||
log.Printf("Studiomodetransition: %s", err)
|
||||
}
|
||||
|
||||
_, err = obsc.Scenes.SetCurrentPreviewScene(&obssc.SetCurrentPreviewSceneParams{
|
||||
SceneUuid: &oldprog.SceneUuid,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("set current preview: %s", err)
|
||||
}
|
||||
}()
|
||||
if Config.Boolshit {
|
||||
go exec.Command("gti").Run()
|
||||
}
|
||||
|
||||
case 0x05: // DDR
|
||||
if Config.Boolshit {
|
||||
println(" ____ ____ ____\n| _ \\| _ \\| _ \\\n| | | | | | | |_) |\n| |_| | |_| | _ <\n|____/|____/|_| \\_\\")
|
||||
println(ddrquote())
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
case *nt8.EventSlider:
|
||||
if event.Type == nt8.SliderTbar {
|
||||
value := (float64(event.Value)) / 250
|
||||
if value > 1 {
|
||||
value = 1
|
||||
|
||||
}
|
||||
|
||||
if value < 0 {
|
||||
value = 0
|
||||
}
|
||||
|
||||
log.Printf("tbar %1.3f", value)
|
||||
|
||||
tbarbos = value
|
||||
changed[TBAR] = struct{}{}
|
||||
continue
|
||||
}
|
||||
|
||||
log.Printf("%X %3d", event.Type, event.Value)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
obsc.Disconnect()
|
||||
}
|
||||
|
||||
func i[K any](a K) *K {
|
||||
return &a
|
||||
}
|
||||
|
||||
func lower(a, b int) int {
|
||||
if a > b {
|
||||
return b
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
var ddrquotes = []string{
|
||||
"Niemand hat die Absicht eine Mauer zu bauen",
|
||||
"Den Sozialismus in seinem Lauf, hält weder Ochs noch Esel auf.",
|
||||
"Frieden ist nicht alles, aber ohne Frieden ist alles nichts.",
|
||||
"Wir müssen lernen, wie die Gesellschaft so zu gestalten, dass die Menschen glücklich sind.",
|
||||
"Die Partei hat immer recht.",
|
||||
"Vorwärts immer, rückwärts nimmer!",
|
||||
"Den Sozialismus in seinem Lauf, hält weder Ochs noch Esel auf.",
|
||||
"Frieden ist nicht alles, aber ohne Frieden ist alles nichts.",
|
||||
"Wir müssen lernen, wie die Gesellschaft so zu gestalten, dass die Menschen glücklich sind.",
|
||||
"Die Partei hat immer recht.",
|
||||
"Vorwärts immer, rückwärts nimmer!",
|
||||
"Wer kämpft, kann verlieren. Wer nicht kämpft, hat schon verloren.",
|
||||
"Es muss demokratisiert werden im tiefsten Sinne des Wortes, die Wirtschaft, die Wissenschaft, das kulturelle Leben.",
|
||||
"Freundschaft, das ist das schönste auf der Welt.",
|
||||
"Niemand hat die Absicht, eine Mauer zu errichten.",
|
||||
"Die Wahrheit ist, dass wir noch nicht da sind, wo wir sein sollten.",
|
||||
"Die Zukunft gehört dem Sozialismus.",
|
||||
"Der Weg der sozialistischen Partei ist der Weg des Volkes.",
|
||||
"Wir haben das Glück, in einer Zeit zu leben, in der wir Zeugen eines großen historischen Wandels sind.",
|
||||
"Sozialismus ist das Gegenteil von Egoismus.",
|
||||
"Die Kunst ist eine Waffe der Revolution.",
|
||||
}
|
||||
|
||||
func ddrquote() string {
|
||||
return ddrquotes[rand.Intn(len(ddrquotes))]
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
module github.com/rileys-trash-can/newtecrs82obs
|
||||
|
||||
go 1.22.1
|
||||
|
||||
require (
|
||||
github.com/andreykaipov/goobs v1.2.3
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/gorilla/websocket v1.5.1 // indirect
|
||||
github.com/hashicorp/logutils v1.0.0 // indirect
|
||||
github.com/mmcloughlin/profile v0.1.1 // indirect
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/sys v0.18.0 // indirect
|
||||
)
|
|
@ -0,0 +1,28 @@
|
|||
github.com/andreykaipov/goobs v1.2.3 h1:zqqr8mYwPNLHmoVMRPAJ7tcafO/CR7xua7rPoDMpDZ8=
|
||||
github.com/andreykaipov/goobs v1.2.3/go.mod h1:D7+36C+8xY/aCHhwWZlyHbqApAfGPc3mFN3uhUjjnk0=
|
||||
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
||||
github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/mmcloughlin/profile v0.1.1 h1:jhDmAqPyebOsVDOCICJoINoLb/AnLBaUw58nFzxWS2w=
|
||||
github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU=
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 h1:UyzmZLoiDWMRywV4DUYb9Fbt8uiOSooupjTq10vpvnU=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
@ -0,0 +1,378 @@
|
|||
package nt8
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/tarm/serial"
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Connection struct {
|
||||
*serial.Port
|
||||
|
||||
LightCmdCh chan<- []CmdLight
|
||||
}
|
||||
|
||||
func Open(name string) (*Connection, error) {
|
||||
p, err := serial.OpenPort(&serial.Config{
|
||||
Name: name,
|
||||
Baud: 9600,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := &Connection{p, nil}
|
||||
go c.handleCmds()
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
type Event interface {
|
||||
event()
|
||||
}
|
||||
|
||||
type EventButton struct {
|
||||
Type EventButtonType
|
||||
Direction Direction
|
||||
|
||||
Value uint8
|
||||
}
|
||||
|
||||
type Direction uint8
|
||||
|
||||
const (
|
||||
Down Direction = iota
|
||||
Up
|
||||
)
|
||||
|
||||
func (*EventButton) event() {}
|
||||
|
||||
type EventButtonType uint8
|
||||
|
||||
const (
|
||||
ButtonProgram EventButtonType = 0b0010
|
||||
ButtonPreview = 0b0001
|
||||
ButtonAutoTakeDSK = 0b0011
|
||||
)
|
||||
|
||||
type EventSlider struct {
|
||||
Type EventSliderType
|
||||
|
||||
Value uint8
|
||||
}
|
||||
|
||||
func (*EventSlider) event() {}
|
||||
|
||||
type EventSliderType uint8
|
||||
|
||||
const (
|
||||
SliderTbar EventSliderType = iota
|
||||
RotA
|
||||
RotB
|
||||
RotC
|
||||
)
|
||||
|
||||
type CmdLight struct {
|
||||
Type EventButtonType
|
||||
Value uint8
|
||||
|
||||
State Light
|
||||
}
|
||||
|
||||
type Light uint8
|
||||
|
||||
const (
|
||||
LightOn Light = iota
|
||||
LightOff
|
||||
)
|
||||
|
||||
// first nibble of first byte is ignored
|
||||
func (c *Connection) WriteCmd(cmd [2]byte) (err error) {
|
||||
h := strings.ToUpper(hex.EncodeToString(cmd[:]))
|
||||
|
||||
log.Printf("sending: ~%s\r", h[1:])
|
||||
_, err = fmt.Fprintf(c.Port, "~%s\r", h[1:])
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Connection) handleCmds() {
|
||||
ch := make(chan []CmdLight)
|
||||
c.LightCmdCh = ch
|
||||
|
||||
ledmap := make(map[EventButtonType]uint8)
|
||||
ledmap[ButtonProgram] = 0xFF
|
||||
ledmap[ButtonPreview] = 0xFF
|
||||
ledmap[ButtonAutoTakeDSK] = 0xFF
|
||||
|
||||
for {
|
||||
changed := make(map[EventButtonType]bool)
|
||||
|
||||
cmds := <-ch
|
||||
//log.Printf("got cmds: %d %#v", len(cmds), nil)
|
||||
|
||||
for _, cmd := range cmds {
|
||||
var (
|
||||
oldstate = T(ledmap[cmd.Type]&(1<<cmd.Value) == 0, LightOn, LightOff)
|
||||
state = cmd.State
|
||||
)
|
||||
|
||||
// log.Printf("oldstate: %01b state %01b", oldstate, state)
|
||||
|
||||
if oldstate != state {
|
||||
ledmap[cmd.Type] ^= (1 << cmd.Value)
|
||||
changed[cmd.Type] = true
|
||||
// send updated state:
|
||||
}
|
||||
}
|
||||
|
||||
for t := range changed {
|
||||
err := c.WriteCmd([2]byte{
|
||||
byte(t),
|
||||
ledmap[t],
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to wrtie CMD: %s", err)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// does fancy blinky blinky sequence
|
||||
func (conn *Connection) InitBlynk() {
|
||||
cmd := CmdLight{}
|
||||
c := time.NewTicker(time.Second / 16)
|
||||
|
||||
for i := uint8(0); i < 8; i++ {
|
||||
<-c.C
|
||||
cmd.Type = ButtonProgram
|
||||
cmd.Value = 7 - i
|
||||
cmd.State = LightOn
|
||||
|
||||
conn.LightCmdCh <- []CmdLight{cmd}
|
||||
}
|
||||
|
||||
for i := uint8(0); i < 8; i++ {
|
||||
<-c.C
|
||||
cmd.Type = ButtonPreview
|
||||
cmd.Value = 7 - i
|
||||
cmd.State = LightOn
|
||||
|
||||
conn.LightCmdCh <- []CmdLight{cmd}
|
||||
}
|
||||
|
||||
for i := uint8(0); i < 4; i++ {
|
||||
<-c.C
|
||||
cmd.Type = ButtonAutoTakeDSK
|
||||
cmd.Value = 7 - i
|
||||
cmd.State = LightOn
|
||||
|
||||
conn.LightCmdCh <- []CmdLight{cmd}
|
||||
}
|
||||
|
||||
for i := uint8(0); i < 3; i++ {
|
||||
<-c.C
|
||||
cmd.Type = ButtonAutoTakeDSK
|
||||
cmd.Value = i
|
||||
cmd.State = LightOn
|
||||
|
||||
conn.LightCmdCh <- []CmdLight{cmd}
|
||||
}
|
||||
|
||||
// off
|
||||
for i := uint8(0); i < 8; i++ {
|
||||
<-c.C
|
||||
cmd.Type = ButtonProgram
|
||||
cmd.Value = 7 - i
|
||||
cmd.State = LightOff
|
||||
|
||||
conn.LightCmdCh <- []CmdLight{cmd}
|
||||
}
|
||||
|
||||
for i := uint8(0); i < 8; i++ {
|
||||
<-c.C
|
||||
cmd.Type = ButtonPreview
|
||||
cmd.Value = 7 - i
|
||||
cmd.State = LightOff
|
||||
|
||||
conn.LightCmdCh <- []CmdLight{cmd}
|
||||
}
|
||||
|
||||
for i := uint8(0); i < 4; i++ {
|
||||
<-c.C
|
||||
cmd.Type = ButtonAutoTakeDSK
|
||||
cmd.Value = 7 - i
|
||||
cmd.State = LightOff
|
||||
|
||||
conn.LightCmdCh <- []CmdLight{cmd}
|
||||
}
|
||||
|
||||
for i := uint8(0); i < 3; i++ {
|
||||
<-c.C
|
||||
cmd.Type = ButtonAutoTakeDSK
|
||||
cmd.Value = i
|
||||
cmd.State = LightOff
|
||||
|
||||
conn.LightCmdCh <- []CmdLight{cmd}
|
||||
}
|
||||
|
||||
c.Stop()
|
||||
|
||||
}
|
||||
|
||||
func (c *Connection) ReadCh() <-chan Event {
|
||||
ch := make(chan Event, 2)
|
||||
|
||||
go func() {
|
||||
r := bufio.NewReader(c.Port)
|
||||
cmd := make([]byte, 2)
|
||||
|
||||
var (
|
||||
program byte = 0xFF
|
||||
preview byte = 0xFF
|
||||
|
||||
atdst byte = 0xFF
|
||||
)
|
||||
|
||||
for {
|
||||
hcmd, err := r.ReadBytes('\r')
|
||||
if err != nil {
|
||||
log.Printf("Error reading: %s", err)
|
||||
}
|
||||
|
||||
if errors.Is(err, io.EOF) {
|
||||
log.Printf("FATAL; EOF")
|
||||
return
|
||||
}
|
||||
|
||||
if len(hcmd) != 5 {
|
||||
log.Printf("illigal command received: %02X %s %d", hcmd, hcmd, len(hcmd))
|
||||
continue
|
||||
}
|
||||
|
||||
//log.Printf("%v %s", hcmd[1:4], hcmd[1:4])
|
||||
|
||||
_, err = hex.Decode(cmd, append([]byte("0"), hcmd[1:4]...))
|
||||
if err != nil {
|
||||
log.Printf("Failed to decode hex command: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
//log.Printf("%08b %d", cmd, len(cmd))
|
||||
|
||||
segment := cmd[0]
|
||||
//log.Printf("Segment: 0b %04b 0x %1X", segment, segment)
|
||||
|
||||
switch segment {
|
||||
case 0b0010: // program
|
||||
for i := uint8(0); i < 8; i++ {
|
||||
mask := byte(1 << i)
|
||||
|
||||
state := cmd[1] & mask
|
||||
oldstate := program & mask
|
||||
|
||||
if state != oldstate {
|
||||
/* log.Printf("mask: %08b", mask)
|
||||
log.Printf("sta: %08b", state)
|
||||
log.Printf("osta: %08b", oldstate)
|
||||
*/
|
||||
|
||||
program ^= mask // toggle oldstate
|
||||
|
||||
ch <- &EventButton{
|
||||
Type: ButtonProgram,
|
||||
Direction: T(state == 0, Down, Up),
|
||||
|
||||
Value: i,
|
||||
}
|
||||
}
|
||||
}
|
||||
case 0b0001: // preview
|
||||
for i := uint8(0); i < 8; i++ {
|
||||
mask := byte(1 << i)
|
||||
|
||||
state := cmd[1] & mask
|
||||
oldstate := preview & mask
|
||||
|
||||
if state != oldstate {
|
||||
/* log.Printf("mask: %08b", mask)
|
||||
log.Printf("sta: %08b", state)
|
||||
log.Printf("osta: %08b", oldstate)
|
||||
*/
|
||||
preview ^= mask // toggle oldstate
|
||||
|
||||
ch <- &EventButton{
|
||||
Type: ButtonPreview,
|
||||
Direction: T(state == 0, Down, Up),
|
||||
|
||||
Value: i,
|
||||
}
|
||||
}
|
||||
}
|
||||
case 0b0011: // atdsk
|
||||
for i := uint8(0); i < 8; i++ {
|
||||
mask := byte(1 << i)
|
||||
|
||||
state := cmd[1] & mask
|
||||
oldstate := atdst & mask
|
||||
|
||||
if state != oldstate {
|
||||
/* log.Printf("mask: %08b", mask)
|
||||
log.Printf("sta: %08b", state)
|
||||
log.Printf("osta: %08b", oldstate)
|
||||
*/
|
||||
|
||||
atdst ^= mask // toggle oldstate
|
||||
|
||||
ch <- &EventButton{
|
||||
Type: ButtonAutoTakeDSK,
|
||||
Direction: T(state == 0, Down, Up),
|
||||
|
||||
Value: i,
|
||||
}
|
||||
}
|
||||
}
|
||||
case 0b0100: // slider1
|
||||
ch <- &EventSlider{
|
||||
Type: SliderTbar,
|
||||
|
||||
Value: cmd[1],
|
||||
}
|
||||
case 0b0101: // slider1
|
||||
ch <- &EventSlider{
|
||||
Type: RotA,
|
||||
|
||||
Value: cmd[1],
|
||||
}
|
||||
case 0b0110: // slider1
|
||||
ch <- &EventSlider{
|
||||
Type: RotB,
|
||||
|
||||
Value: cmd[1],
|
||||
}
|
||||
case 0b0111: // slider1
|
||||
ch <- &EventSlider{
|
||||
Type: RotC,
|
||||
|
||||
Value: cmd[1],
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
func T[K any](c bool, a, b K) K {
|
||||
if c {
|
||||
return a
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
Loading…
Reference in New Issue