Telemeterable Design Pattern
Intent
Decouple the collection of the telemetry data to be provided by an object from their content and format.
Based On
This is pattern is derived from the telemetry management management pattern of the AOCS Framework.
Motivation
Virtually all on-board systems generate telemetry data. The telemetry data are collected from the modules or components that make up the on-board applications and are then formatted in packets that are forwarded to the ground. The telemetry data supplied by a module or component represent a snapshot of its internal state. Often the same module or component should supply different information depending on the mission phase or on the OBS operational model.
The telemetry data collection service is usually organized around a telemetry manager module that uses the getter methods exposed by other modules to retrieve the data to be included in a telemetry packet. Thus, the information as to which data should be collected is usually centralized in the telemetry manager. This has three drawbacks:
- it makes the telemetry manager module complex
- it creates a strong coupling between the telemetry manager and the modules that supply telemetry data
- it hinders the reuse of the telemetry manager because the type of data to be included in telemetry vary across applications
- shifting responsibility for creating the telemetry data generated by a component to the component itself, and
- by introducing an abstract interface to decouple the component that collects the telemetry data from the components that provide them
Dictionary Entries
The following abstractions or domain-wide concepts are defined to support the implementation of this design pattern:
Structure
This design pattern is built around an abstract interface to represent the telemeterable abstraction: telemeterable components are components that implement the abstract interface Telemeterable
. This interface defines the operations that a telemetry manager component needs in order to control the acquisition of telemetry data from the telemeterable component. The basic operation is getTelemetryImage
that directs the component to return its telemetry image.
getTelemetryImage
. Interface Telemeterable
accordingly defines operations to control the telemetry format.
Participants
Client
:The component that is responsible for collecting the telemetry data. Telemeterable
:The abstract interface that characterizes all components that are potential sources of telemetry data. ConcreteTmComponent
:Component implementing interface Telemeterable
that represents a specific and concrete component that provides telemetry data.
Collaborations
The typical operational scenario for this design pattern is:
- A client component is configured with a list of telemeterable components and, when it is activated, it goes through the list and asks each component in the list to supply its telemetry image.
Consequences
-
Clients are decoupled from the format and content of the telemetry image provided by a component: they only see components of abstract
Telemeterable
type. Changing the concrete component that is supplying the telemetry data has no impact on the component that processes the telemetry data. - If an existing component has to be turned into a source of telemetry data, it is necessary to subclass it and create a new component with the desired implementation of the telemeterable methods. This may lead to a proliferation of classes.
- This design pattern is only useful if the parts of the OBS code that are to supply telemetry data are organized as objects instantiated from classes (as opposed to, for instance, C-style modules).
- Application of this design pattern simplifies the client component but adds complexity to the telemeterable components because it makes them responsible for organizing their own telemetry images. This is the price paid to make telemetry handling application-independent.
Applicability
This design pattern is useful when:
- there is a need to acquire housekeeping data from the components in an application and it is necessary to be able to vary the format and content of the housekeeping data supplied by each component.
- there is no rigid requirement on the exact layout of the telemetry data to be provided to the client (if there were, then the telemetry item pattern should be used).
Implementation Issues
How is the collection of the telemetry image to be implemented? One solution is to have iterator methods that return the telemetry image as a sequence of bytes:
interface Telemeterable { byte getFirstTmByte(); byte getNextTmByte(); bool isLastByte(); . . . }An alternative solution is that proposed by the telemetry management design pattern in the AOCS Framework where the telemeterable component is passed a pointer to the component representing the telemetry channel and is responsible for directly writing its telemetry image to the telemetry channel. See also the telemetry stream design pattern.
The physical channel to which the telemetry data must be written often has a fixed capacity. The telemetry manager therefore may need to check that the size of the telemetry size to be provided by a given telemeterable component is compatible with this capacity. It may therefore be useful to endow the Telemeterable interface with a method like getTelemetryImageSize
that returns the size in bytes of the telemetry image to be generated by a component.
The concept proposed here imposes some constraints on the layout of the telemetry data. This is because the telemetry manager, which is responsible for assembling the telemetry data, does not know the meaning of the data it retrieves from the telemeterable objects: it collects the telemetry data as anonymous strings of bytes.
These constraints can be a problem when the layout of the telemetry data is specified as an application requirement. In such a case, an additional component is required to perform the translation from the on-board to the on-ground layout of the telemetry data.
In a framework perspective, the algorithm used to perform the translation from on-board to on-ground layout should be seen as a variation point and the translation component should become a plug-in component for the telemetry manager. One way in which this could be done is illustrated below by means of pseudo-code example.
The telemetry manager component is defined as follows:
class TelemetryManager { Telemeterable* tmList[N]; char* tmBuffer[M]; TelemetryFormatter* tmFormatter; void ativate() { // Load the TM buffer with formatted TM data for (int i=1; i++; i<N) { tmBuffer[i]=tmList[tmFormatter->getNextTmComp[i]]->getNext(); // Send the TM buffer to the telemetry stream . . . } // The TelemetryFormatter is a plug-in component for // the TM manager void loadTelemetryFormatter(TelemetryFormatter* tmFmt) { tmFormatter = tmFmt; } . . . // other methods }In this implementation the TM manager maintains, as usual, a list of telemeterable objects and when it is activated it goes through the list to ask each telemetry object to return its telemetry data. Here it is assumed that the telemeterable objects return their telemetry data as a sequence of bytes that are returned one by one by successively calling an iteration method
getNext()
. The telemetry manager must store the telemetry data in a telemetry
buffer that in the above pseudo-code is represented by an array of bytes (variable tmBuffer
).
In the simple implementation of the design pattern, the telemetry data are stored in the
telemetry buffer in the same order in which they are collected and the layout of the telemetry
buffer cannot therefore be controlled. In the implementation shown above instead, the order in
which the telemetry data are collected is encapsulated in a TelemetryFormatter
component.
This component defines an iterator method getNextTmComp()
that returns the index of the
telemeterable component that must be queried for its next telemetry data item.
The telemetry formatter is a plug-in component for the telemetry manager that can now be customized to implement different telemetry layouts.
If the telemetry data are organized as a set of independent telemetry items, the telemetry item pattern might provide a better design solution to the telemetry management problem.
OBS Framework Mapping
The implementation of this design pattern in the OBS Framework is supported by the following classes:
- Telemeterableabstract interface --> not directly supported in the OBS Framework
Sample Code
One of the sample code examples of the event design pattern discussed how event repositories can be set up that could be used to model the history data collection. The history data need to be sent to the ground as telemetry data. This means that the corresponding event repository should be made to implement interface Telemeterable
. Consider for instance the ControllerEventRepository
class introduced at the end of the previously mentioned sample code section. This should be implemented as follows:
class ControllerEventRepository: EventRepository, Telemeterable { // add an event of type ControllerEvent to the repository void create(int evtType, float[] rd); // Iterators to return the content of //the repository buffer byte-by-byte byte getFirstTmByte() { . . . } byte getNextTmByte(){ . . . } bool isLastByte(){ . . . } // The format of the controller TM image //is fixed: dummy implementation void setTelemetryFormat(int newFormat) { return; } }The above implementation assumes that there is only telemetry format associated to the event repository.
Remarks
None
Author
A. Pasetti (P&P Software)
Last Modified
2002-06-22