2025-01-18 14:53:29 +00:00
|
|
|
package hardware
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
_ "embed"
|
|
|
|
|
"io"
|
|
|
|
|
|
2025-10-25 12:25:09 +02:00
|
|
|
"unsafe"
|
2025-01-18 14:53:29 +00:00
|
|
|
|
2025-10-25 12:25:09 +02:00
|
|
|
"github.com/pkg/errors"
|
|
|
|
|
"github.com/rs/zerolog/log"
|
2025-01-18 14:53:29 +00:00
|
|
|
)
|
|
|
|
|
|
2025-10-25 12:25:09 +02:00
|
|
|
/*
|
|
|
|
|
#cgo LDFLAGS: -L${SRCDIR}/../build/bin -ldmxSender
|
|
|
|
|
#include "cpp/include/dmxSenderBridge.h"
|
|
|
|
|
*/
|
|
|
|
|
import "C"
|
2025-01-18 14:53:29 +00:00
|
|
|
|
|
|
|
|
// FTDIPeripheral contains the data of an FTDI peripheral
|
|
|
|
|
type FTDIPeripheral struct {
|
2025-01-26 12:01:31 +01:00
|
|
|
info PeripheralInfo // The peripheral basic data
|
2025-01-25 17:43:45 +00:00
|
|
|
settings map[string]interface{} // The settings of the peripheral
|
2025-10-25 12:25:09 +02:00
|
|
|
dmxDevice unsafe.Pointer // The command object for piloting the DMX ouptut
|
2025-01-25 17:43:45 +00:00
|
|
|
stdin io.WriteCloser // For writing in the DMX sender
|
|
|
|
|
stdout io.ReadCloser // For reading from the DMX sender
|
|
|
|
|
stderr io.ReadCloser // For reading the errors
|
|
|
|
|
disconnectChan chan struct{} // Channel to cancel the connection
|
|
|
|
|
errorsChan chan error // Channel to get the errors
|
2025-01-18 14:53:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NewFTDIPeripheral creates a new FTDI peripheral
|
2025-01-26 12:01:31 +01:00
|
|
|
func NewFTDIPeripheral(info PeripheralInfo) (*FTDIPeripheral, error) {
|
|
|
|
|
log.Info().Str("file", "FTDIPeripheral").Str("name", info.Name).Str("s/n", info.SerialNumber).Msg("FTDI peripheral created")
|
2025-01-25 17:43:45 +00:00
|
|
|
settings := make(map[string]interface{})
|
2025-01-18 14:53:29 +00:00
|
|
|
return &FTDIPeripheral{
|
2025-01-26 12:01:31 +01:00
|
|
|
info: info,
|
2025-10-25 12:25:09 +02:00
|
|
|
dmxDevice: C.dmx_create(),
|
2025-01-25 17:43:45 +00:00
|
|
|
settings: settings,
|
|
|
|
|
disconnectChan: make(chan struct{}),
|
|
|
|
|
errorsChan: make(chan error, 1),
|
2025-01-18 14:53:29 +00:00
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Connect connects the FTDI peripheral
|
2025-01-26 12:01:31 +01:00
|
|
|
func (p *FTDIPeripheral) Connect(ctx context.Context, location int) error {
|
2025-10-25 12:25:09 +02:00
|
|
|
// Check if the device has already been created
|
|
|
|
|
if p.dmxDevice == nil {
|
|
|
|
|
return errors.Errorf("the DMX device has not been created!")
|
2025-01-18 14:53:29 +00:00
|
|
|
}
|
|
|
|
|
|
2025-10-25 12:25:09 +02:00
|
|
|
// Connect the peripheral
|
|
|
|
|
log.Trace().Str("file", "FTDIPeripheral").Str("s/n", p.info.SerialNumber).Msg("connecting FTDI peripheral...")
|
|
|
|
|
err := C.dmx_connect(p.dmxDevice)
|
|
|
|
|
if err {
|
|
|
|
|
log.Error().Str("file", "FTDIPeripheral").Str("s/n", p.info.SerialNumber).Msg("unable to connect the DMX device")
|
|
|
|
|
return errors.Errorf("Unable to connect the DMX Device on the specified port")
|
2025-01-18 14:53:29 +00:00
|
|
|
}
|
|
|
|
|
|
2025-10-25 12:25:09 +02:00
|
|
|
//TODO: Destroy the object when context is done to avoid memory loss
|
|
|
|
|
|
|
|
|
|
log.Trace().Str("file", "FTDIPeripheral").Str("s/n", p.info.SerialNumber).Msg("DMX device connected successfully")
|
2025-01-18 14:53:29 +00:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Disconnect disconnects the FTDI peripheral
|
2025-08-31 11:15:38 +02:00
|
|
|
func (p *FTDIPeripheral) Disconnect() error {
|
2025-10-25 12:25:09 +02:00
|
|
|
// Check if the device has already been created
|
|
|
|
|
if p.dmxDevice == nil {
|
|
|
|
|
return errors.Errorf("the DMX device has not been created!")
|
2025-01-18 14:53:29 +00:00
|
|
|
}
|
2025-10-25 12:25:09 +02:00
|
|
|
|
|
|
|
|
//TODO: What actions for disconnecting the DMX device?
|
|
|
|
|
|
|
|
|
|
return nil
|
2025-01-18 14:53:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Activate activates the FTDI peripheral
|
|
|
|
|
func (p *FTDIPeripheral) Activate(ctx context.Context) error {
|
2025-10-25 12:25:09 +02:00
|
|
|
// Check if the device has already been created
|
|
|
|
|
if p.dmxDevice == nil {
|
|
|
|
|
return errors.Errorf("the DMX device has not been created!")
|
2025-01-18 14:53:29 +00:00
|
|
|
}
|
2025-10-25 12:25:09 +02:00
|
|
|
|
|
|
|
|
log.Trace().Str("file", "FTDIPeripheral").Str("s/n", p.info.SerialNumber).Msg("activating FTDI peripheral...")
|
|
|
|
|
|
|
|
|
|
C.dmx_activate(p.dmxDevice)
|
|
|
|
|
|
|
|
|
|
log.Trace().Str("file", "FTDIPeripheral").Str("s/n", p.info.SerialNumber).Msg("DMX device activated successfully")
|
|
|
|
|
|
|
|
|
|
return nil
|
2025-01-18 14:53:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Deactivate deactivates the FTDI peripheral
|
|
|
|
|
func (p *FTDIPeripheral) Deactivate(ctx context.Context) error {
|
2025-10-25 12:25:09 +02:00
|
|
|
// Check if the device has already been created
|
|
|
|
|
if p.dmxDevice == nil {
|
|
|
|
|
return errors.Errorf("the DMX device has not been created!")
|
2025-01-18 14:53:29 +00:00
|
|
|
}
|
2025-10-25 12:25:09 +02:00
|
|
|
|
|
|
|
|
log.Trace().Str("file", "FTDIPeripheral").Str("s/n", p.info.SerialNumber).Msg("deactivating FTDI peripheral...")
|
|
|
|
|
|
|
|
|
|
C.dmx_deactivate(p.dmxDevice)
|
|
|
|
|
|
|
|
|
|
log.Trace().Str("file", "FTDIPeripheral").Str("s/n", p.info.SerialNumber).Msg("DMX device deactivated successfully")
|
|
|
|
|
|
|
|
|
|
return nil
|
2025-01-18 14:53:29 +00:00
|
|
|
}
|
|
|
|
|
|
2025-01-26 12:01:31 +01:00
|
|
|
// SetSettings sets a specific setting for this peripheral
|
|
|
|
|
func (p *FTDIPeripheral) SetSettings(settings map[string]interface{}) error {
|
2025-01-25 17:43:45 +00:00
|
|
|
p.settings = settings
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-18 14:53:29 +00:00
|
|
|
// SetDeviceProperty sends a command to the specified device
|
2025-08-31 11:15:38 +02:00
|
|
|
func (p *FTDIPeripheral) SetDeviceProperty(ctx context.Context, channelNumber uint32, channelValue byte) error {
|
2025-10-25 12:25:09 +02:00
|
|
|
// Check if the device has already been created
|
|
|
|
|
if p.dmxDevice == nil {
|
|
|
|
|
return errors.Errorf("the DMX device has not been created!")
|
2025-01-18 14:53:29 +00:00
|
|
|
}
|
2025-10-25 12:25:09 +02:00
|
|
|
|
|
|
|
|
log.Trace().Str("file", "FTDIPeripheral").Str("s/n", p.info.SerialNumber).Msg("setting device property on FTDI peripheral...")
|
|
|
|
|
|
|
|
|
|
C.dmx_setValue(p.dmxDevice, C.int(channelNumber), C.int(channelValue))
|
|
|
|
|
|
|
|
|
|
log.Trace().Str("file", "FTDIPeripheral").Str("s/n", p.info.SerialNumber).Msg("device property set on FTDI peripheral successfully")
|
|
|
|
|
|
|
|
|
|
return nil
|
2025-01-18 14:53:29 +00:00
|
|
|
}
|
|
|
|
|
|
2025-01-25 17:43:45 +00:00
|
|
|
// GetSettings gets the peripheral settings
|
|
|
|
|
func (p *FTDIPeripheral) GetSettings() map[string]interface{} {
|
|
|
|
|
return p.settings
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-18 14:53:29 +00:00
|
|
|
// GetInfo gets all the peripheral information
|
|
|
|
|
func (p *FTDIPeripheral) GetInfo() PeripheralInfo {
|
2025-01-26 12:01:31 +01:00
|
|
|
return p.info
|
2025-01-18 14:53:29 +00:00
|
|
|
}
|