129 lines
10 KiB
Markdown
129 lines
10 KiB
Markdown
# 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`).
|
|
|
|
* **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.
|
|
|
|
* **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.
|
|
|
|
* **Physical Communication Layer:**
|
|
* **Serial Port (`_serialPortUtility`):** An instance of `System.IO.Ports.SerialPort` used for direct serial communication. Configured based on settings in `UtilityMaselli.Setup` (COM port, baud rate, etc.).
|
|
* **Socket Communication (`_maselliSocketUtility`):** An instance of `MaselliSocket.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.
|
|
|
|
* **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 corresponding `ClassVariabile` objects in `UtilityMaselli.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.
|
|
|
|
* **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 of `ILoggerService`) is used to log communication errors and significant events.
|
|
|
|
## 3. Service Operations and Flow
|
|
|
|
### 3.1. Initialization and Instrument Addition
|
|
|
|
1. The `ClassSerialeStrumenti` service is typically initialized once at application startup.
|
|
2. Instruments (instances of `ClassStrumentoMaselli` derivatives) are added to the service using the `AddStrumento()` method. This registers them for management.
|
|
3. The service attempts to open the configured communication port (serial or socket) via `ApriPortaComunicazione()`.
|
|
|
|
### 3.2. Submitting Commands
|
|
|
|
1. Other parts of the application (e.g., UI event handlers, automated processes) submit commands to instruments by calling `InserisciComandoSeriale()`.
|
|
2. This method populates a `ComandoSeriale` object with the necessary details (instrument address, command type, function number, value, etc.) and adds it to the `QueueComandiSeriali`.
|
|
|
|
### 3.3. Command Processing Cycle (Timer Tick)
|
|
|
|
1. The `_timerSerialeUtility_Elapsed` event handler executes periodically.
|
|
2. **Command Sending:**
|
|
* The service checks if the communication line is free (`_statoComunicazione == StatiComunicazione.LIBERO`).
|
|
* It iterates through `ListaStrumenti`. For each instrument, it checks its `FaseComunicazione`.
|
|
* 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 from `QueueComandiSeriali`).
|
|
* 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.
|
|
3. **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 global `UtilityMaselli.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` or `ModifiedReceived` are invoked.
|
|
4. **State Transitions:**
|
|
* Based on successful command execution or received data, the instrument's `FaseComunicazione` is updated (e.g., from `RECOGNIZE_EQUIPMENT` to `SEND_STARTUP_COMMANDS`, then to `LINKED`).
|
|
|
|
### 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 corresponding `ClassVariabile` in `UtilityMaselli.Variabili` (based on instrument and function number) and updates its `Valore` 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 of `ClassVariabile` objects that this service reads from (for "M" commands, using the current value in the variable if not explicitly provided in `ComandoSeriale`) 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 from `UtilityMaselli.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. |