generated from thinkode/modelRepository
hardware code cleaning
This commit is contained in:
217
hardware/endpointsHandler.go
Normal file
217
hardware/endpointsHandler.go
Normal file
@@ -0,0 +1,217 @@
|
||||
package hardware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
)
|
||||
|
||||
// EndpointEvent is trigger by the providers when the scan is complete
|
||||
type EndpointEvent string
|
||||
|
||||
// EndpointStatus is the endpoint status (DISCONNECTED => CONNECTING => DEACTIVATED => ACTIVATED)
|
||||
type EndpointStatus string
|
||||
|
||||
const (
|
||||
// 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"
|
||||
)
|
||||
|
||||
// Endpoint represents the methods used to manage a endpoint (input or output hardware)
|
||||
type Endpoint interface {
|
||||
Connect(context.Context) error // Connect the endpoint
|
||||
// SetEventCallback(func(any)) // Callback is called when an event is emitted from the endpoint
|
||||
Disconnect(context.Context) error // Disconnect the endpoint
|
||||
Activate(context.Context) error // Activate the endpoint
|
||||
Deactivate(context.Context) error // Deactivate the endpoint
|
||||
// AddDevice(Device) error // Add a device to the endpoint
|
||||
// RemoveDevice(Device) error // Remove a device to the endpoint
|
||||
GetSettings() map[string]any // Get the endpoint settings
|
||||
SetSettings(context.Context, map[string]any) error // Set a endpoint setting
|
||||
SetDeviceProperty(context.Context, uint32, byte) error // Update a device property
|
||||
WaitStop() error // Properly close the endpoint
|
||||
|
||||
GetInfo() EndpointInfo // Get the endpoint information
|
||||
}
|
||||
|
||||
// EndpointInfo represents a endpoint information
|
||||
type EndpointInfo struct {
|
||||
Name string `yaml:"name"` // Name of the endpoint
|
||||
SerialNumber string `yaml:"sn"` // S/N of the endpoint
|
||||
ProtocolName string `yaml:"protocol"` // Protocol name of the endpoint
|
||||
Settings map[string]any `yaml:"settings"` // Endpoint settings
|
||||
}
|
||||
|
||||
// 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 endpoint from its provider (if needed)
|
||||
if provider, found := h.providers[endpointInfo.ProtocolName]; found {
|
||||
var err error
|
||||
endpointInfo, err = provider.Create(ctx, endpointInfo)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
// 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.SavedEndpoints[endpointInfo.SerialNumber] = endpointInfo
|
||||
|
||||
runtime.EventsEmit(ctx, string(EndpointStatusUpdated), endpointInfo, EndpointStatusDisconnected)
|
||||
|
||||
// If already detected, connect it
|
||||
if endpoint, ok := h.DetectedEndpoints[endpointInfo.SerialNumber]; ok {
|
||||
h.wg.Add(1)
|
||||
go func() {
|
||||
defer h.wg.Done()
|
||||
err := endpoint.Connect(ctx)
|
||||
if err != nil {
|
||||
log.Err(err).Str("file", "FTDIProvider").Str("endpointSN", endpointInfo.SerialNumber).Msg("unable to connect the endpoint")
|
||||
return
|
||||
}
|
||||
// Endpoint connected, activate it
|
||||
err = endpoint.Activate(ctx)
|
||||
if err != nil {
|
||||
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(EndpointLoad), endpointInfo)
|
||||
|
||||
return endpointInfo.SerialNumber, nil
|
||||
}
|
||||
|
||||
// UnregisterEndpoint unregisters an existing endpoint
|
||||
func (h *Manager) UnregisterEndpoint(ctx context.Context, endpointInfo EndpointInfo) error {
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
|
||||
if endpoint, detected := h.DetectedEndpoints[endpointInfo.SerialNumber]; detected {
|
||||
// Deactivating endpoint
|
||||
err := endpoint.Deactivate(ctx)
|
||||
if err != nil {
|
||||
log.Err(err).Str("sn", endpointInfo.SerialNumber).Msg("unable to deactivate the endpoint")
|
||||
return nil
|
||||
}
|
||||
// Disconnecting endpoint
|
||||
err = endpoint.Disconnect(ctx)
|
||||
if err != nil {
|
||||
log.Err(err).Str("sn", endpointInfo.SerialNumber).Msg("unable to disconnect the endpoint")
|
||||
return nil
|
||||
}
|
||||
// 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.SavedEndpoints, endpointInfo.SerialNumber)
|
||||
runtime.EventsEmit(ctx, string(EndpointUnload), endpointInfo)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// 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 endpoint")
|
||||
}
|
||||
return endpoint.GetSettings(), nil
|
||||
}
|
||||
|
||||
// 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 endpoint")
|
||||
}
|
||||
return endpoint.SetSettings(ctx, settings)
|
||||
}
|
||||
|
||||
// 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 endpoint is saved in the project, connect it
|
||||
if _, saved := h.SavedEndpoints[endpoint.GetInfo().SerialNumber]; saved {
|
||||
h.wg.Add(1)
|
||||
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 endpoint")
|
||||
return
|
||||
}
|
||||
err = p.Activate(ctx)
|
||||
if err != nil {
|
||||
log.Err(err).Str("sn", p.GetInfo().SerialNumber).Msg("unable to activate the FTDI endpoint")
|
||||
return
|
||||
}
|
||||
}(endpoint)
|
||||
}
|
||||
|
||||
// TODO: Update the Endpoint reference in the corresponding devices
|
||||
|
||||
runtime.EventsEmit(ctx, string(EndpointArrival), endpoint.GetInfo())
|
||||
}
|
||||
|
||||
// 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 Endpoint) {
|
||||
defer h.wg.Done()
|
||||
err := p.Deactivate(ctx)
|
||||
if err != nil {
|
||||
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 endpoint after disconnection")
|
||||
}
|
||||
}(endpoint)
|
||||
|
||||
// Remove the endpoint from the hardware
|
||||
delete(h.DetectedEndpoints, endpoint.GetInfo().SerialNumber)
|
||||
|
||||
// TODO: Update the Endpoint reference in the corresponding devices
|
||||
runtime.EventsEmit(ctx, string(EndpointRemoval), endpoint.GetInfo())
|
||||
}
|
||||
Reference in New Issue
Block a user