As a basis for discussion, the Demos/Can folder has been modified in several ways. If we agree on the changes there, we can use the same structure for the other demos.
Remove the yaml/json configurations. Instead, a new folder Demos/SampleConfigurations with useful yaml configs is provided.
Split into one demo per participant
No usage of std::cout, std::cerr except printing command line argument usage
Use the SIL Kit Logger for printing
Header-only SignalHandler and CommandLineParser in Demos/include.
No usage of Press any key
If possible, demos should work without requiring any command line arguments at all
The splitted demos (CanReaderDemo, CanWriterDemo)
use the new ApplicationBase that provides all functionality that is not related to CAN (e.g. sync/async behvior)
use a CanDemoCommon.hpp for common behavior (here: Frame*Handler). Participant specific code (here: SendFrame) is implemented in the participant specific demo.
Minimal demo SimpleCan
The SimpleCan demo is not using the ApplicationBase to showcase basic SIL Kit usage. It is sync-only, only takes a participant name as command line argument and sends/receives CAN frames. Focus here is on minimizing lines of code. Such a simple demo could be unique for CAN and is not necessary for each bus system.
The ApplicationBase
Implements a set of default command line arguments (except --network which is an extension provided by the CAN Demo) :
.\SilKitDemoCanReader.exe --help
Usage: D:\git\sil-kit-1\_build\x64-debug\Debug\SilKitDemoCanReader.exe [--help] [--name <participantName>] [--registry-uri <silkitUri>] [--log <level>] [--config <filePath>] [--async] [--duration <sim step duration in us>] [--fast] [--network <name>]
Arguments:
-h, --help: Get this help.
-n, --name <participantName>: The participant name used to take part in the simulation. Defaults to 'CanReader'.
-u, --registry-uri <silkitUri>: The registry URI to connect to. Defaults to 'silkit://localhost:8500'.
-l, --log <level>: Log to stdout with level 'trace', 'debug', 'warn', 'info', 'error', 'critical' or 'off'. Defaults to 'info' if the '--config' option is not specified. Set to 'off' to explicitly turn off stdout logging. Cannot be used together with '--config'.
-c, --config <filePath>: Path to the Participant configuration YAML or JSON file. Cannot be used together with '--log'.
-a, --async: run in asynchronous mode. Cannot be used together with '--duration'.
-d, --duration <sim step duration in us>: The step size in microseconds of the participant. Defaults to 1000us. Cannot be used together with '--async'.
-f, --fast: Run the simulation as fast as possible. By default, the execution is slowed down to a single work cycle per second. Cannot be used together with '--config'.
-n, --network: Name of the CAN network to use. Defaults to 'CAN1'.
The constructor also takes a struct with the arguments that can be used to define defaults per demo implementation (e.g. Can Demos should run with stepSize = 5ms)
Provides an interface (pure virtual functions) that must be implemented by the demo:
AddCommandLineArgs(): Inject additional demo args. Here, the CAN demo adds a --network arg to set a network name.
EvaluateCommandLineArgs(): Evaluate the additional args after parsing. Here, the --network is evaluated and used in the controller creation
CreateControllers(): Called before lifecycle setup
InitControllers(): Called in CommunicationReadyHandler()
DoWorkAsync(): Called in the worker thread in async mode
DoWorkSync(std::chrono::nanoseconds now): Called in the SimulationStepHandler
A SignalHandler is used that stops the demo in any state on CTRL-C
Public methods:
SetupCommandLineArgs(int argc, char** argv, std::unordered_set<DefaultArg> excludedCommandLineArgs = {}): To split command line arg setup and the simulation run. Optionally, a set of default args can be excluded.
Run(): The actual simulation run. The workflow is:
// Create participant
SetupParticipant();
// Stop() on Ctrl-C
SetupSignalHandler();
// app: Controller creation
CreateControllers();
// React on valid start / simulation abort
// app: Controller initialization in CommunicationReadyHandler
SetupLifecycle();
// sync: Create timeSyncService and simulationStepHandler
// app: DoWorkSync
// async: Create thread and couple to starting handler
// app: DoWorkASync
SetupDoWork();
// Start lifecycle
Launch();
// Wait for lifecycle to end
// async: Join worker thread
WaitUntilDone();
No usage of the userContext paramter when sending a frame. This is actually not needed for the C++-API, as the context can always be captured when setting up the handlers. Also, the original CAN Demo used the userContext for data transport, which was misleading.
As a basis for discussion, the Demos/Can folder has been modified in several ways. If we agree on the changes there, we can use the same structure for the other demos.
TL;DR
Central modifications / guidelines
std::cout
,std::cerr
except printing command line argument usageThe splitted demos (CanReaderDemo, CanWriterDemo)
ApplicationBase
that provides all functionality that is not related to CAN (e.g. sync/async behvior)Frame*Handler
). Participant specific code (here:SendFrame
) is implemented in the participant specific demo.Minimal demo SimpleCan
The SimpleCan demo is not using the
ApplicationBase
to showcase basic SIL Kit usage. It is sync-only, only takes a participant name as command line argument and sends/receives CAN frames. Focus here is on minimizing lines of code. Such a simple demo could be unique for CAN and is not necessary for each bus system.The
ApplicationBase
--network
which is an extension provided by the CAN Demo) :AddCommandLineArgs()
: Inject additional demo args. Here, the CAN demo adds a--network
arg to set a network name.EvaluateCommandLineArgs()
: Evaluate the additional args after parsing. Here, the--network
is evaluated and used in the controller creationCreateControllers()
: Called before lifecycle setupInitControllers()
: Called inCommunicationReadyHandler()
DoWorkAsync()
: Called in the worker thread in async modeDoWorkSync(std::chrono::nanoseconds now)
: Called in theSimulationStepHandler
Public methods:
SetupCommandLineArgs(int argc, char** argv, std::unordered_set<DefaultArg> excludedCommandLineArgs = {})
: To split command line arg setup and the simulation run. Optionally, a set of default args can be excluded.Run()
: The actual simulation run. The workflow is:Demo main then is as simple as:
Functional changes of the CAN Demo itself
userContext
paramter when sending a frame. This is actually not needed for the C++-API, as the context can always be captured when setting up the handlers. Also, the original CAN Demo used the userContext for data transport, which was misleading.