ts_salobj 4 is coming. This is a complete rewrite that uses OpenSplice dds libraries directly, instead of using SALPY libraries generated by ts_sal. This posting is intended to give an overview of what changed and some help with converting code.
Overview of changes:
- salobj 4 uses OpenSplice dds libraries directly, rather than SALPY libraries. salobj 4 gets its topic information from IDL files, which are generated by ts_sal.
- More topic fields are visible than with SALPY. All but one of these field names start with the prefix “private_” and salobj sets the values of these fields automatically. The fields are:
- component_nameId: the SAL index of the component. Example field names include TestId and ATPtgId.
- private_seqNum: the command ID. This is generated by the sender (e.g. salobj.RemoteCommand) and copied by the receiver (e.g. salobj.ControllerCommand) to the ackcmd samples it sends in response.
- private_rcvStamp: the time the sample was received
- private_sndStamp: The time the sample was sent
- private_host: an integer specified by environment variable LSST_DDS_IP; intended to be the sender’s IP address
- private_origin: the process ID of the sender
- Command acknowledgement uses the topic “ackcmd”.
- There is only one ackcmd topic per SAL component, and it is used for (shared by) all commands for that component. SAL differentiates between different commands by using a different range of
private_seqNum
for each command. - The field
private_seqNum
is the value salobj formerly called “command ID” or “cmd_id”. - Familiar fields include “ack”, “error”, “reason”
- There is only one ackcmd topic per SAL component, and it is used for (shared by) all commands for that component. SAL differentiates between different commands by using a different range of
- DDS code should use a single “domain participant” per process; this saves time and memory, as the domain participant contains the cache of topic data. salobj encapsulates the domain participant in a new class
Domain
. - I have changed salobj to expose as much of DDS as I felt we could manage.
Backward Incompatible Changes:
-
Remote
's constructor no longer blocks until historical data is read. Instead it has a new attributestart_task
that is set done when historical data is read and the remote is reading new data. - The
CommandIdData
class is gone because command ID is is available directly in the data as fieldprivate_seqNum
.do_
command methods and callbacks now simply receive the command data (as specified by the IDL, with the additional formerly hidden fields mentioned in the introduction). To update your code:- Change
id_data.data
todata
- Change
id_data.cmd_id
todata.private_seqNum
(rare) - Change
id_data
todata
- If you have unit tests that create
CommandIdData
instances, just make the data instead.
- Change
- The
CommandIdAck
class is gone.RemoteCommand.start
andnext_ackcmd
both receiveackcmd
topic data. To update your code:- Change
id_ack.cmd_id
toackcmd.private_seqNum
- Change
id_ack.ack
toackcmd
- Change
id_ack
toackcmd
- Change
- The command acknowledgement object is now called
ackcmd
instead ofack
,
to match the topic name and to eliminate the confusion ofack.ack
. - The
AckError
object now has just one field:ackcmd
, instead of two fieldscmd_id
andack
.- Change code that raises AckError (rare)
- Change access of error fields from
.ack
to.ackcmd
and.cmd_id
to.ackcmd.private_seqNum
.
-
SalInfo.makeAck
is nowSalInfo.makeAckCmd
and it has one new required parameter:private_seqNum
. - If your CSC has method
start
it now takes no arguments, becauseBaseCsc.start
now accepts no arguments; you no longer pass ininitial_simulation_mode
. - If your CSC implements
stop
, change it toclose_tasks
and in that method callawait super().close_tasks()
and close your own extra tasks.BaseCsc.stop
has been replaced byBaseCsc.close
which callsBaseCsc.close_tasks
andclose_tasks
is normally all a CSC will have to override. - salobj now uses IDL files instead of SALPY libraries. These files are built by ts_sal and kept in new package
ts_idl
. To make the IDL files usingmake_idl_files.py
for examplemake_idl_files.py Test Script ScriptQueue
.
We plan to have ts_sal generate modules for the enums found in the XML, but that is not yet supported. - Make
ts_idl
a dependency of your package, instead ofts_sal
- Read topics (RemoteEvent, RemoteTelemetry, ControllerCommand) do not have the
data
property; useget
instead. - You cannot set an array field to a scalar; with SALPY salobj this had the effect of setting every element
to the specified value, but it will raise an exception in dds salobj when sending the data. - If you try to send an array with too many values the extra items are silently ignored.
- Construct a
Controller
with(name, index)
instead of(SALPY_name, index)
. - Construct a
Remote
with(domain, name, index)
instead of(SALPY_name, index)
. Getdomain
fromcontroller.domain
or make one explicitly. I made this change because best practice is to have only one dds domain participant per process. - Shutdown requires more care, especially in unit tests. Everything is cleaned up eventually
if you just shut down the process, but it takes some time, and if too many things are being cleaned up at once in a unit test you may start running out of resources. Both Controller and Domain are async context managers, so you can use them as follows:
async with Controller(...) as controller: # or async with Domain() as domain: # ...do stuff here
-
SalInfo.start()
must be awaited after all topics have been created. Controller and Remote do this automatically, but it is important for code that has neither, such as some unit tests and Jupyter scripts. If you forget then read topics will not read any data. - The
Logger
class is gone; its functionality has been incorporated into theController
class. - CSCs and Scripts take several seconds to close, which is slower than it used to be. This may require small changes to existing unit tests.
Other changes:
- New method
ControllerCommand.set_start
allows you to specify command data and start a command using one call. - The default log level is now
INFO