generated from thinkode/modelRepository
renaming Finders and Peripherals to Providers and Endpoints
This commit is contained in:
@@ -11,33 +11,33 @@ import (
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
)
|
||||
|
||||
// PeripheralEvent is trigger by the finders when the scan is complete
|
||||
type PeripheralEvent string
|
||||
// EndpointEvent is trigger by the providers when the scan is complete
|
||||
type EndpointEvent string
|
||||
|
||||
// PeripheralStatus is the peripheral status (DISCONNECTED => CONNECTING => DEACTIVATED => ACTIVATED)
|
||||
type PeripheralStatus string
|
||||
// EndpointStatus is the endpoint status (DISCONNECTED => CONNECTING => DEACTIVATED => ACTIVATED)
|
||||
type EndpointStatus string
|
||||
|
||||
const (
|
||||
// PeripheralArrival is triggerd when a peripheral has been connected to the system
|
||||
PeripheralArrival PeripheralEvent = "PERIPHERAL_ARRIVAL"
|
||||
// PeripheralRemoval is triggered when a peripheral has been disconnected from the system
|
||||
PeripheralRemoval PeripheralEvent = "PERIPHERAL_REMOVAL"
|
||||
// PeripheralLoad is triggered when a peripheral is added to the project
|
||||
PeripheralLoad PeripheralEvent = "PERIPHERAL_LOAD"
|
||||
// PeripheralUnload is triggered when a peripheral is removed from the project
|
||||
PeripheralUnload PeripheralEvent = "PERIPHERAL_UNLOAD"
|
||||
// PeripheralStatusUpdated is triggered when a peripheral status has been updated (disconnected - connecting - deactivated - activated)
|
||||
PeripheralStatusUpdated PeripheralEvent = "PERIPHERAL_STATUS"
|
||||
// PeripheralEventEmitted is triggered when a peripheral event is emitted
|
||||
PeripheralEventEmitted PeripheralEvent = "PERIPHERAL_EVENT_EMITTED"
|
||||
// PeripheralStatusDisconnected : peripheral is now disconnected
|
||||
PeripheralStatusDisconnected PeripheralStatus = "PERIPHERAL_DISCONNECTED"
|
||||
// PeripheralStatusConnecting : peripheral is now connecting
|
||||
PeripheralStatusConnecting PeripheralStatus = "PERIPHERAL_CONNECTING"
|
||||
// PeripheralStatusDeactivated : peripheral is now deactivated
|
||||
PeripheralStatusDeactivated PeripheralStatus = "PERIPHERAL_DEACTIVATED"
|
||||
// PeripheralStatusActivated : peripheral is now activated
|
||||
PeripheralStatusActivated PeripheralStatus = "PERIPHERAL_ACTIVATED"
|
||||
// EndpointArrival is triggerd when a endpoint has been connected to the system
|
||||
EndpointArrival EndpointEvent = "PERIPHERAL_ARRIVAL"
|
||||
// EndpointRemoval is triggered when a endpoint has been disconnected from the system
|
||||
EndpointRemoval EndpointEvent = "PERIPHERAL_REMOVAL"
|
||||
// EndpointLoad is triggered when a endpoint is added to the project
|
||||
EndpointLoad EndpointEvent = "PERIPHERAL_LOAD"
|
||||
// EndpointUnload is triggered when a endpoint is removed from the project
|
||||
EndpointUnload EndpointEvent = "PERIPHERAL_UNLOAD"
|
||||
// EndpointStatusUpdated is triggered when a endpoint status has been updated (disconnected - connecting - deactivated - activated)
|
||||
EndpointStatusUpdated EndpointEvent = "PERIPHERAL_STATUS"
|
||||
// EndpointEventEmitted is triggered when a endpoint event is emitted
|
||||
EndpointEventEmitted EndpointEvent = "PERIPHERAL_EVENT_EMITTED"
|
||||
// EndpointStatusDisconnected : endpoint is now disconnected
|
||||
EndpointStatusDisconnected EndpointStatus = "PERIPHERAL_DISCONNECTED"
|
||||
// EndpointStatusConnecting : endpoint is now connecting
|
||||
EndpointStatusConnecting EndpointStatus = "PERIPHERAL_CONNECTING"
|
||||
// EndpointStatusDeactivated : endpoint is now deactivated
|
||||
EndpointStatusDeactivated EndpointStatus = "PERIPHERAL_DEACTIVATED"
|
||||
// EndpointStatusActivated : endpoint is now activated
|
||||
EndpointStatusActivated EndpointStatus = "PERIPHERAL_ACTIVATED"
|
||||
)
|
||||
|
||||
// Manager is the class who manages the hardware
|
||||
@@ -45,241 +45,241 @@ type Manager struct {
|
||||
mu sync.Mutex
|
||||
wg sync.WaitGroup
|
||||
|
||||
finders map[string]PeripheralFinder // The map of peripherals finders
|
||||
DetectedPeripherals map[string]Peripheral // The current list of peripherals
|
||||
SavedPeripherals map[string]PeripheralInfo // The list of stored peripherals
|
||||
providers map[string]EndpointProvider // The map of endpoints providers
|
||||
DetectedEndpoints map[string]Endpoint // The current list of endpoints
|
||||
SavedEndpoints map[string]EndpointInfo // The list of stored endpoints
|
||||
}
|
||||
|
||||
// NewManager creates a new hardware manager
|
||||
func NewManager() *Manager {
|
||||
log.Trace().Str("package", "hardware").Msg("Hardware instance created")
|
||||
return &Manager{
|
||||
finders: make(map[string]PeripheralFinder),
|
||||
DetectedPeripherals: make(map[string]Peripheral, 0),
|
||||
SavedPeripherals: make(map[string]PeripheralInfo, 0),
|
||||
providers: make(map[string]EndpointProvider),
|
||||
DetectedEndpoints: make(map[string]Endpoint, 0),
|
||||
SavedEndpoints: make(map[string]EndpointInfo, 0),
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterPeripheral registers a new peripheral
|
||||
func (h *Manager) RegisterPeripheral(ctx context.Context, peripheralInfo PeripheralInfo) (string, error) {
|
||||
// RegisterEndpoint registers a new endpoint
|
||||
func (h *Manager) RegisterEndpoint(ctx context.Context, endpointInfo EndpointInfo) (string, error) {
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
|
||||
// Create the peripheral from its finder (if needed)
|
||||
if finder, found := h.finders[peripheralInfo.ProtocolName]; found {
|
||||
// Create the endpoint from its provider (if needed)
|
||||
if provider, found := h.providers[endpointInfo.ProtocolName]; found {
|
||||
var err error
|
||||
peripheralInfo, err = finder.Create(ctx, peripheralInfo)
|
||||
endpointInfo, err = provider.Create(ctx, endpointInfo)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
// Do not save if the peripheral doesn't have a S/N
|
||||
if peripheralInfo.SerialNumber == "" {
|
||||
return "", fmt.Errorf("serial number is empty for this peripheral")
|
||||
// Do not save if the endpoint doesn't have a S/N
|
||||
if endpointInfo.SerialNumber == "" {
|
||||
return "", fmt.Errorf("serial number is empty for this endpoint")
|
||||
}
|
||||
|
||||
h.SavedPeripherals[peripheralInfo.SerialNumber] = peripheralInfo
|
||||
h.SavedEndpoints[endpointInfo.SerialNumber] = endpointInfo
|
||||
|
||||
runtime.EventsEmit(ctx, string(PeripheralStatusUpdated), peripheralInfo, PeripheralStatusDisconnected)
|
||||
runtime.EventsEmit(ctx, string(EndpointStatusUpdated), endpointInfo, EndpointStatusDisconnected)
|
||||
|
||||
// If already detected, connect it
|
||||
if peripheral, ok := h.DetectedPeripherals[peripheralInfo.SerialNumber]; ok {
|
||||
if endpoint, ok := h.DetectedEndpoints[endpointInfo.SerialNumber]; ok {
|
||||
h.wg.Add(1)
|
||||
go func() {
|
||||
defer h.wg.Done()
|
||||
err := peripheral.Connect(ctx)
|
||||
err := endpoint.Connect(ctx)
|
||||
if err != nil {
|
||||
log.Err(err).Str("file", "FTDIFinder").Str("peripheralSN", peripheralInfo.SerialNumber).Msg("unable to connect the peripheral")
|
||||
log.Err(err).Str("file", "FTDIProvider").Str("endpointSN", endpointInfo.SerialNumber).Msg("unable to connect the endpoint")
|
||||
return
|
||||
}
|
||||
// Peripheral connected, activate it
|
||||
err = peripheral.Activate(ctx)
|
||||
// Endpoint connected, activate it
|
||||
err = endpoint.Activate(ctx)
|
||||
if err != nil {
|
||||
log.Err(err).Str("file", "FTDIFinder").Str("peripheralSN", peripheralInfo.SerialNumber).Msg("unable to activate the FTDI peripheral")
|
||||
log.Err(err).Str("file", "FTDIProvider").Str("endpointSN", endpointInfo.SerialNumber).Msg("unable to activate the FTDI endpoint")
|
||||
return
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Emits the event in the hardware
|
||||
runtime.EventsEmit(ctx, string(PeripheralLoad), peripheralInfo)
|
||||
runtime.EventsEmit(ctx, string(EndpointLoad), endpointInfo)
|
||||
|
||||
return peripheralInfo.SerialNumber, nil
|
||||
return endpointInfo.SerialNumber, nil
|
||||
}
|
||||
|
||||
// UnregisterPeripheral unregisters an existing peripheral
|
||||
func (h *Manager) UnregisterPeripheral(ctx context.Context, peripheralInfo PeripheralInfo) error {
|
||||
// UnregisterEndpoint unregisters an existing endpoint
|
||||
func (h *Manager) UnregisterEndpoint(ctx context.Context, endpointInfo EndpointInfo) error {
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
|
||||
if peripheral, detected := h.DetectedPeripherals[peripheralInfo.SerialNumber]; detected {
|
||||
// Deactivating peripheral
|
||||
err := peripheral.Deactivate(ctx)
|
||||
if endpoint, detected := h.DetectedEndpoints[endpointInfo.SerialNumber]; detected {
|
||||
// Deactivating endpoint
|
||||
err := endpoint.Deactivate(ctx)
|
||||
if err != nil {
|
||||
log.Err(err).Str("sn", peripheralInfo.SerialNumber).Msg("unable to deactivate the peripheral")
|
||||
log.Err(err).Str("sn", endpointInfo.SerialNumber).Msg("unable to deactivate the endpoint")
|
||||
return nil
|
||||
}
|
||||
// Disconnecting peripheral
|
||||
err = peripheral.Disconnect(ctx)
|
||||
// Disconnecting endpoint
|
||||
err = endpoint.Disconnect(ctx)
|
||||
if err != nil {
|
||||
log.Err(err).Str("sn", peripheralInfo.SerialNumber).Msg("unable to disconnect the peripheral")
|
||||
log.Err(err).Str("sn", endpointInfo.SerialNumber).Msg("unable to disconnect the endpoint")
|
||||
return nil
|
||||
}
|
||||
// Remove the peripheral from its finder (if needed)
|
||||
if finder, found := h.finders[peripheralInfo.ProtocolName]; found {
|
||||
err = finder.Remove(ctx, peripheral)
|
||||
// Remove the endpoint from its provider (if needed)
|
||||
if provider, found := h.providers[endpointInfo.ProtocolName]; found {
|
||||
err = provider.Remove(ctx, endpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
delete(h.SavedPeripherals, peripheralInfo.SerialNumber)
|
||||
runtime.EventsEmit(ctx, string(PeripheralUnload), peripheralInfo)
|
||||
delete(h.SavedEndpoints, endpointInfo.SerialNumber)
|
||||
runtime.EventsEmit(ctx, string(EndpointUnload), endpointInfo)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPeripheralSettings gets the peripheral settings
|
||||
func (h *Manager) GetPeripheralSettings(peripheralSN string) (map[string]any, error) {
|
||||
// Return the specified peripheral
|
||||
peripheral, found := h.DetectedPeripherals[peripheralSN]
|
||||
// GetEndpointSettings gets the endpoint settings
|
||||
func (h *Manager) GetEndpointSettings(endpointSN string) (map[string]any, error) {
|
||||
// Return the specified endpoint
|
||||
endpoint, found := h.DetectedEndpoints[endpointSN]
|
||||
if !found {
|
||||
// Peripheral not detected, return the last settings saved
|
||||
if savedPeripheral, isFound := h.SavedPeripherals[peripheralSN]; isFound {
|
||||
return savedPeripheral.Settings, nil
|
||||
// Endpoint not detected, return the last settings saved
|
||||
if savedEndpoint, isFound := h.SavedEndpoints[endpointSN]; isFound {
|
||||
return savedEndpoint.Settings, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unable to found the peripheral")
|
||||
return nil, fmt.Errorf("unable to found the endpoint")
|
||||
}
|
||||
return peripheral.GetSettings(), nil
|
||||
return endpoint.GetSettings(), nil
|
||||
}
|
||||
|
||||
// SetPeripheralSettings sets the peripheral settings
|
||||
func (h *Manager) SetPeripheralSettings(ctx context.Context, peripheralSN string, settings map[string]any) error {
|
||||
peripheral, found := h.DetectedPeripherals[peripheralSN]
|
||||
// SetEndpointSettings sets the endpoint settings
|
||||
func (h *Manager) SetEndpointSettings(ctx context.Context, endpointSN string, settings map[string]any) error {
|
||||
endpoint, found := h.DetectedEndpoints[endpointSN]
|
||||
if !found {
|
||||
return fmt.Errorf("unable to found the FTDI peripheral")
|
||||
return fmt.Errorf("unable to found the FTDI endpoint")
|
||||
}
|
||||
return peripheral.SetSettings(ctx, settings)
|
||||
return endpoint.SetSettings(ctx, settings)
|
||||
}
|
||||
|
||||
// Start starts to find new peripheral events
|
||||
// Start starts to find new endpoint events
|
||||
func (h *Manager) Start(ctx context.Context) error {
|
||||
|
||||
// Register all the finders to use as hardware scanners
|
||||
h.RegisterFinder(NewFTDIFinder(3 * time.Second))
|
||||
h.RegisterFinder(NewOS2LFinder())
|
||||
h.RegisterFinder(NewMIDIFinder(3 * time.Second))
|
||||
// Register all the providers to use as hardware scanners
|
||||
h.RegisterProvider(NewFTDIProvider(3 * time.Second))
|
||||
h.RegisterProvider(NewOS2LProvider())
|
||||
h.RegisterProvider(NewMIDIProvider(3 * time.Second))
|
||||
|
||||
for finderName, finder := range h.finders {
|
||||
for providerName, provider := range h.providers {
|
||||
|
||||
// Initialize the finder
|
||||
err := finder.Initialize()
|
||||
// Initialize the provider
|
||||
err := provider.Initialize()
|
||||
if err != nil {
|
||||
log.Err(err).Str("file", "hardware").Str("finderName", finderName).Msg("unable to initialize finder")
|
||||
log.Err(err).Str("file", "hardware").Str("providerName", providerName).Msg("unable to initialize provider")
|
||||
return err
|
||||
}
|
||||
|
||||
// Set callback functions
|
||||
finder.OnArrival(h.OnPeripheralArrival)
|
||||
finder.OnRemoval(h.OnPeripheralRemoval)
|
||||
provider.OnArrival(h.OnEndpointArrival)
|
||||
provider.OnRemoval(h.OnEndpointRemoval)
|
||||
|
||||
// Start the finder
|
||||
err = finder.Start(ctx)
|
||||
// Start the provider
|
||||
err = provider.Start(ctx)
|
||||
if err != nil {
|
||||
log.Err(err).Str("file", "hardware").Str("finderName", finderName).Msg("unable to start finder")
|
||||
log.Err(err).Str("file", "hardware").Str("providerName", providerName).Msg("unable to start provider")
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// OnPeripheralArrival is called when a peripheral arrives in the system
|
||||
func (h *Manager) OnPeripheralArrival(ctx context.Context, peripheral Peripheral) {
|
||||
// Add the peripheral to the detected hardware
|
||||
h.DetectedPeripherals[peripheral.GetInfo().SerialNumber] = peripheral
|
||||
// OnEndpointArrival is called when a endpoint arrives in the system
|
||||
func (h *Manager) OnEndpointArrival(ctx context.Context, endpoint Endpoint) {
|
||||
// Add the endpoint to the detected hardware
|
||||
h.DetectedEndpoints[endpoint.GetInfo().SerialNumber] = endpoint
|
||||
|
||||
// If the peripheral is saved in the project, connect it
|
||||
if _, saved := h.SavedPeripherals[peripheral.GetInfo().SerialNumber]; saved {
|
||||
// If the endpoint is saved in the project, connect it
|
||||
if _, saved := h.SavedEndpoints[endpoint.GetInfo().SerialNumber]; saved {
|
||||
h.wg.Add(1)
|
||||
go func(p Peripheral) {
|
||||
go func(p Endpoint) {
|
||||
defer h.wg.Done()
|
||||
err := p.Connect(ctx)
|
||||
if err != nil {
|
||||
log.Err(err).Str("sn", p.GetInfo().SerialNumber).Msg("unable to connect the FTDI peripheral")
|
||||
log.Err(err).Str("sn", p.GetInfo().SerialNumber).Msg("unable to connect the FTDI endpoint")
|
||||
return
|
||||
}
|
||||
err = p.Activate(ctx)
|
||||
if err != nil {
|
||||
log.Err(err).Str("sn", p.GetInfo().SerialNumber).Msg("unable to activate the FTDI peripheral")
|
||||
log.Err(err).Str("sn", p.GetInfo().SerialNumber).Msg("unable to activate the FTDI endpoint")
|
||||
return
|
||||
}
|
||||
}(peripheral)
|
||||
}(endpoint)
|
||||
}
|
||||
|
||||
// TODO: Update the Peripheral reference in the corresponding devices
|
||||
// TODO: Update the Endpoint reference in the corresponding devices
|
||||
|
||||
runtime.EventsEmit(ctx, string(PeripheralArrival), peripheral.GetInfo())
|
||||
runtime.EventsEmit(ctx, string(EndpointArrival), endpoint.GetInfo())
|
||||
}
|
||||
|
||||
// OnPeripheralRemoval is called when a peripheral exits the system
|
||||
func (h *Manager) OnPeripheralRemoval(ctx context.Context, peripheral Peripheral) {
|
||||
// Properly deactivating and disconnecting the peripheral
|
||||
// OnEndpointRemoval is called when a endpoint exits the system
|
||||
func (h *Manager) OnEndpointRemoval(ctx context.Context, endpoint Endpoint) {
|
||||
// Properly deactivating and disconnecting the endpoint
|
||||
h.wg.Add(1)
|
||||
go func(p Peripheral) {
|
||||
go func(p Endpoint) {
|
||||
defer h.wg.Done()
|
||||
err := p.Deactivate(ctx)
|
||||
if err != nil {
|
||||
log.Err(err).Str("sn", p.GetInfo().SerialNumber).Msg("unable to deactivate peripheral after disconnection")
|
||||
log.Err(err).Str("sn", p.GetInfo().SerialNumber).Msg("unable to deactivate endpoint after disconnection")
|
||||
}
|
||||
err = p.Disconnect(ctx)
|
||||
if err != nil {
|
||||
log.Err(err).Str("sn", p.GetInfo().SerialNumber).Msg("unable to disconnect the peripheral after disconnection")
|
||||
log.Err(err).Str("sn", p.GetInfo().SerialNumber).Msg("unable to disconnect the endpoint after disconnection")
|
||||
}
|
||||
}(peripheral)
|
||||
}(endpoint)
|
||||
|
||||
// Remove the peripheral from the hardware
|
||||
delete(h.DetectedPeripherals, peripheral.GetInfo().SerialNumber)
|
||||
// Remove the endpoint from the hardware
|
||||
delete(h.DetectedEndpoints, endpoint.GetInfo().SerialNumber)
|
||||
|
||||
// TODO: Update the Peripheral reference in the corresponding devices
|
||||
runtime.EventsEmit(ctx, string(PeripheralRemoval), peripheral.GetInfo())
|
||||
// TODO: Update the Endpoint reference in the corresponding devices
|
||||
runtime.EventsEmit(ctx, string(EndpointRemoval), endpoint.GetInfo())
|
||||
}
|
||||
|
||||
// GetFinder returns a register finder
|
||||
func (h *Manager) GetFinder(finderName string) (PeripheralFinder, error) {
|
||||
finder, exists := h.finders[finderName]
|
||||
// GetProvider returns a register provider
|
||||
func (h *Manager) GetProvider(providerName string) (EndpointProvider, error) {
|
||||
provider, exists := h.providers[providerName]
|
||||
if !exists {
|
||||
log.Error().Str("file", "hardware").Str("finderName", finderName).Msg("unable to get the finder")
|
||||
return nil, fmt.Errorf("unable to locate the '%s' finder", finderName)
|
||||
log.Error().Str("file", "hardware").Str("providerName", providerName).Msg("unable to get the provider")
|
||||
return nil, fmt.Errorf("unable to locate the '%s' provider", providerName)
|
||||
}
|
||||
log.Debug().Str("file", "hardware").Str("finderName", finderName).Msg("got finder")
|
||||
return finder, nil
|
||||
log.Debug().Str("file", "hardware").Str("providerName", providerName).Msg("got provider")
|
||||
return provider, nil
|
||||
}
|
||||
|
||||
// RegisterFinder registers a new peripherals finder
|
||||
func (h *Manager) RegisterFinder(finder PeripheralFinder) {
|
||||
h.finders[finder.GetName()] = finder
|
||||
log.Info().Str("file", "hardware").Str("finderName", finder.GetName()).Msg("finder registered")
|
||||
// RegisterProvider registers a new endpoints provider
|
||||
func (h *Manager) RegisterProvider(provider EndpointProvider) {
|
||||
h.providers[provider.GetName()] = provider
|
||||
log.Info().Str("file", "hardware").Str("providerName", provider.GetName()).Msg("provider registered")
|
||||
}
|
||||
|
||||
// WaitStop stops the hardware manager
|
||||
func (h *Manager) WaitStop() error {
|
||||
log.Trace().Str("file", "hardware").Msg("closing the hardware manager")
|
||||
|
||||
// Stop each finder
|
||||
// Stop each provider
|
||||
var errs []error
|
||||
for name, f := range h.finders {
|
||||
for name, f := range h.providers {
|
||||
if err := f.WaitStop(); err != nil {
|
||||
errs = append(errs, fmt.Errorf("%s: %w", name, err))
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for all the peripherals to close
|
||||
log.Trace().Str("file", "MIDIFinder").Msg("closing all MIDI peripherals")
|
||||
for registeredPeripheralSN, registeredPeripheral := range h.DetectedPeripherals {
|
||||
err := registeredPeripheral.WaitStop()
|
||||
// Wait for all the endpoints to close
|
||||
log.Trace().Str("file", "MIDIProvider").Msg("closing all MIDI endpoints")
|
||||
for registeredEndpointSN, registeredEndpoint := range h.DetectedEndpoints {
|
||||
err := registeredEndpoint.WaitStop()
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("%s: %w", registeredPeripheralSN, err))
|
||||
errs = append(errs, fmt.Errorf("%s: %w", registeredEndpointSN, err))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user