10 KiB
Instrument Communication Service
This document describes the Instrument Communication Service, a core component of the software responsible for managing all aspects of communication with connected Maselli instruments. The primary class implementing this service is Uc09_Utility.ClassSerialeStrumenti
.
1. Overview and Purpose
The Instrument Communication Service acts as a central hub for bi-directional data exchange between the software application and one or more Maselli instruments. Its main purpose is to abstract the complexities of low-level communication protocols and hardware interfaces, providing a consistent way for other parts of the application to interact with instruments.
Key Responsibilities:
- Multi-Instrument Management: Handles communication with multiple instruments, potentially on different lines or addresses.
- Command Queuing and Dispatch: Manages a queue of commands to be sent to instruments, ensuring orderly and timely execution.
- Protocol Implementation: Encodes outgoing commands and decodes incoming responses according to the Maselli Proprietary Serial/Socket Protocol.
- Transport Layer Abstraction: Supports communication over both direct serial (RS-232/RS-485) connections and TCP/IP sockets (Ethernet Bridge).
- Instrument Lifecycle Management: Handles instrument detection, recognition, initialization, active communication, and graceful disconnection.
- Data Synchronization: Updates shared data structures (e.g.,
UtilityMaselli.Variabili
) with values read from instruments. - Event Notification: Provides callbacks or events for significant communication occurrences (e.g., data received, protocol change).
- Error Handling and Logging: Detects communication errors, retries commands, and logs relevant information.
2. Core Class: Uc09_Utility.ClassSerialeStrumenti
This class is the heart of the Instrument Communication Service.
Key Internal Components and Mechanisms:
-
Instrument Registry (
ListaStrumenti
):- A list (
List<ClassStrumentoMaselli>
) that holds instances of all instruments the service is configured to manage. - Each
ClassStrumentoMaselli
object contains instrument-specific details like address, function numbers, and communication state (InstrumentSerial
).
- A list (
-
Command Queue (
QueueComandiSeriali
):- A thread-safe queue (
ConcurrentQueue<ComandoSeriale>
) that stores commands submitted from various parts of the application. - Commands are processed in a FIFO (First-In, First-Out) manner, though the service prioritizes commands for instruments that are actively communicating.
- A thread-safe queue (
-
Main Processing Loop (driven by
_timerSerialeUtility
):- A
System.Timers.Timer
periodically triggers the main logic of the service. - This loop iterates through the
ListaStrumenti
, processing each instrument based on its current communication phase (InstrumentSerial.FaseComunicazione
). - It handles sending commands from the queue, managing timeouts, processing received data, and transitioning instruments through different communication states.
- A
-
Physical Communication Layer:
- Serial Port (
_serialPortUtility
): An instance ofSystem.IO.Ports.SerialPort
used for direct serial communication. Configured based on settings inUtilityMaselli.Setup
(COM port, baud rate, etc.). - Socket Communication (
_maselliSocketUtility
): An instance ofMaselliSocket.ClassMaselliSocket
used when the Ethernet bridge is enabled (UtilityMaselli.Setup.EnableEthernetBridge
). This class encapsulates TCP/IP client socket operations. - The service seamlessly switches between these layers based on configuration.
- Serial Port (
-
Protocol Encoding/Decoding Engine:
PreparaComando()
: Constructs the full command string according to the Maselli protocol, including address, command type, function number, value, length, and checksum.CalcolaChecksum()
: Calculates the checksum for outgoing commands.GestioneComandoRicevuto()
: The primary method for parsing incoming responses. It checks for protocol errors (e.g.,NOxx
), identifies response types (data, image, acknowledgment), and routes data for further processing.DecoderProtocolloMaselli()
: Extracts values from standard data responses (!VALUE
) and updates the correspondingClassVariabile
objects inUtilityMaselli.Variabili
.DecodificaImmagine()
: Handles the more complex task of parsing and assembling image data received from instruments.
-
Communication State Machine (
InstrumentSerial.FaseComunicazione
):- Each instrument managed by the service has an associated communication phase. The service transitions instruments through these phases:
- Initial connection attempts.
- Sending "super commands" for recognition or protocol forcing.
- Instrument recognition (matching response with
Identifier.RecognizingStrings
). - Sending instrument-specific startup commands.
LINKED
state for active data exchange.- Handling image requests and multi-part responses.
- Closing communication and sending exit commands.
- Each instrument managed by the service has an associated communication phase. The service transitions instruments through these phases:
-
Error Handling and Retries:
- The service checks for protocol errors (
NOxx
) in responses. - Commands can have a retry count (
ComandoSeriale.NumeroRipetizioni
). If a command fails (timeout or error response), it can be re-queued for a limited number of retries. - The
CommunicationHandlerLoggerService
(an implementation ofILoggerService
) is used to log communication errors and significant events.
- The service checks for protocol errors (
3. Service Operations and Flow
3.1. Initialization and Instrument Addition
- The
ClassSerialeStrumenti
service is typically initialized once at application startup. - Instruments (instances of
ClassStrumentoMaselli
derivatives) are added to the service using theAddStrumento()
method. This registers them for management. - The service attempts to open the configured communication port (serial or socket) via
ApriPortaComunicazione()
.
3.2. Submitting Commands
- Other parts of the application (e.g., UI event handlers, automated processes) submit commands to instruments by calling
InserisciComandoSeriale()
. - This method populates a
ComandoSeriale
object with the necessary details (instrument address, command type, function number, value, etc.) and adds it to theQueueComandiSeriali
.
3.3. Command Processing Cycle (Timer Tick)
- The
_timerSerialeUtility_Elapsed
event handler executes periodically. - Command Sending:
- The service checks if the communication line is free (
_statoComunicazione == StatiComunicazione.LIBERO
). - It iterates through
ListaStrumenti
. For each instrument, it checks itsFaseComunicazione
. - If an instrument is in a state to send commands (e.g.,
SEND_SUPER_COMMAND_RECOGNIZE_EQUIPMENT
,LINKED
), the service dequeues the next relevant command (either a special command or fromQueueComandiSeriali
). - The command is formatted using
PreparaComando()
. - The formatted command is sent via
_serialPortUtility.Write()
or_maselliSocketUtility.Send()
. - The service transitions to a
WAIT_RX
state and sets a timeout for the response.
- The service checks if the communication line is free (
- Response Handling:
- Data received on the serial port (
_serialPortUtility_DataReceived
) or socket (_maselliSocketUtility.eventoResponseEthBridge
) triggers processing. - The received data is passed to
GestioneComandoRicevuto()
. - This method parses the response, checks for errors, and determines the response type.
- If it's a data response,
DecoderProtocolloMaselli()
updates the globalUtilityMaselli.Variabili
. - If it's an image response,
DecodificaImmagine()
processes the image data. - The command status (
ComandoSeriale.Stato
) is updated (e.g.,OK_COMMAND
,ERROR_COMMAND
). - Relevant callbacks/events like
ReceiveCallback
orModifiedReceived
are invoked.
- Data received on the serial port (
- State Transitions:
- Based on successful command execution or received data, the instrument's
FaseComunicazione
is updated (e.g., fromRECOGNIZE_EQUIPMENT
toSEND_STARTUP_COMMANDS
, then toLINKED
).
- Based on successful command execution or received data, the instrument's
3.4. Instrument Recognition
- During initial phases, the service sends "super commands" (e.g., requesting instrument memory name).
- The response is compared against
Identifier.RecognizingStrings
for each configured instrument. - Once a match is found,
Identifier.EquipmentRecognized
is set to true, and the instrument model may be further refined (e.g., differentiating UC07 from UC08 based on the memory name). - The
ProtocolChangedToMaselli
event can be raised if the instrument confirms it's in Maselli mode.
3.5. Data Synchronization
- When
DecoderProtocolloMaselli()
successfully parses a response to a read command (V
), it finds the correspondingClassVariabile
inUtilityMaselli.Variabili
(based on instrument and function number) and updates itsValore
property. - This makes the latest instrument data available to the rest of the application.
4. Interaction with Other System Components
UtilityMaselli.Setup
: Provides configuration parameters for the communication channel (port, speed, bridge settings).UtilityMaselli.Variabili
: The global list ofClassVariabile
objects that this service reads from (for "M" commands, using the current value in the variable if not explicitly provided inComandoSeriale
) and writes to (after "V" commands).ClassStrumentoMaselli
(and derivatives): Provide instrument-specific information like address, function number definitions, startup/exit commands, and recognizing strings.- Application Logic/UI: Submits commands via
InserisciComandoSeriale()
and consumes data fromUtilityMaselli.Variabili
. Listens to events from the service for UI updates. MaselliSocket.ClassMaselliSocket
: Used as the transport layer when Ethernet bridge is active.CommunicationHandlerLoggerService
: Used for logging errors and important communication events.
5. Service Robustness
- Timeouts: Manages timeouts for responses to prevent indefinite blocking.
- Retries: Failed commands can be retried a configurable number of times.
- Checksums: Validates command integrity for serial transmission.
- Error Logging: Provides diagnostic information for troubleshooting.
- Concurrent Queue: Ensures thread-safe command submission.
The Instrument Communication Service is thus a critical and complex component, orchestrating the entire flow of information between the software and the physical Maselli instruments.