_ .-') _ _ .-') ('-. .-') _ ( ( OO) ) ( \( -O ) ( OO ).-. ( OO) ) \ .'_ ,------. / . --. / ,------. / '._ ,`'--..._) | /`. ' | \-. \ ('-| _.---' |'--...__) | | \ ' | / | | .-'-' | | (OO|(_\ '--. .--' | | ' | | |_.' | \| |_.' | / | '--. | | | | / : | . '.' | .-. | \_)| .--' | | | '--' / | |\ \ | | | | \| |_) | | `-------' `--' '--' `--' `--' `--' `--'
Motivation
Sometimes it is necessary to perform single action PDM or send a piece of additional information to individual PDM without touching configuration. This approach allow to selectively adjust individual PDMs according user needs.
1. Requirements
1.1. Flexibility
To make the solution more flexible, PDM offers set of Remote actions which can be called from PDM.control. Each remote action is defined by its number and can carry optional arguments. Remote action can be added to the firmware and executed without update of PDM.control.
1.2. Scheduling
It is not possible to establish direct communication with PDM. Therefore it is necessary to queue remote action on PDM.control’s side. PDM has to be notified in a reply on keep alive message about existing requests in the queue.
1.3. Order
Actions has to be executed in the order which they was entered. If action is requested by user multiple times it has to be executed multiple times in correct order relative to other requested actions. The same action can be run for example with different arguments.
1.4. Progress report
Not all remote actions can be performed just in the moment when PDM receives the request. Some actions can even take long time to complete execution or has planned waiting time. Therefore the user must not be immediately informed about action result. Anyway it is necessary to inform him about progress or intermediate results.
1.5. Abort
Do we really need this? Some remote actions can be scheduled for later time by PDM. There has to be possibility to abort remote actins.
There can be two cases.
-
Action was not requested on PDM and still stays in queue on PDM.control.
-
Action was already transferred to PDM but not yet executed.
2. Design V1
There is already implementation of remote actions (let call it V1), which was created earlier. It does not fulfill all requirements mentioned above. It will be also described here for the sake of completeness and backward compatibility.
2.1. Scheduling
PDM.control keeps the queue of actions which was entered by user in the database.
Then it sends one action at the time.
Action number is transferred in mnemonic CMD
and its arguments in mnemonic CAR
.
Additionally mnemonic WTS
is send to allow the PDM to distinguish between new actions and those which was already received and are just repeated.
Type of mnemonic WTS
is long.
Its value should be considered as arbitrary value.
Currently it contains action creation time as unix time stamp.
This implementation detail can be changed in future.
PDM may not respond to the request immediately. If processing time is longer then keep alive interval, action request will be simply repeated.
2.2. Order
Action request is signalled to PDM, until PDM will complete it, in every keep alive response. It means that it is not possible that multiple actions run at the same time.
Originally it was expected that each action will be completed within few minutes (time shorter than keep alive interval).
2.3. Progress report
Not supported.
The only way how to interact with running action is to close it from PDM side.
PDM has to send status message with mnemonic CMD
where the action number is mentioned.
It resolve the action with result equal of alert type of status message itself.
2.4. Abort
If the action was not sent to PDM it is simply removed from waiting queue. It it is already running then the abort is not supported any more.
3. Design V2
New implementation (which is partly compatible with Design V1).
3.1. Scheduling, ordering
To keep compatibility with Design V1 there is also next action send in mnemonic CMD
which transfers next action number in the PDM.control queue. Rest of mnemonics from V1 is also transferred.
Additionally, to increase throughput, PDM.control may send a batch of actions from its queue in mnemonic CME
in JSON format.
At most first 10 commands will be send.
[
{ "id":123, "cmd": 83, "args": "-r 80 --force" },
{ "id":129, "cmd": 11, "args": "-b 139" },
]
Individual action in array keeps order defined by user in UI. Requests are repeated in response to keep alive unless PDM acknowledge reception.
Meaning of individual fields is following:
-
id
- unique action id (int4). ReplacesWTS
. -
cmd
- action number. ReplacesCMD
. -
args
- action arguments. ReplacesCAR
.
3.2. Progress update
PDM may update progress of running actions.
3.2.1. Update
Progress update is done by sending mnemonic CPR
.
PDM can mention one or more actions got from PDM.control.
Example of progress report is shown below.
[
{
"severity": 0,
"progress": 0,
"text":
{
"id": 5,
"template": "Accepted for processing.",
}
},
{
"severity": 2,
"progress": 1,
"text":
{
"id": 7,
"template": "Reconnecting network {1}.",
"args" [{"val": "Vodafone"}]
}
}
]
Meaning of individual fields is following.
Progress update can be send multiple times even for the same progress level.
For example the remote action may report waiting progress:
[{"id":7, "severity": 0, "progress": 1, "text": {"id": 11, "template": "Waiting for no sale period."}}]
and later on
[{"id":7, "severity": 0, "progress": 1, "text": {"id": 15, "template": "Card reader is not yet ready."}}]
Running progress can be also reported multiple times First we issue warning about payment memory.
[{"id":123, "severity": 2, "progress": 2, "text": {"id": 16, "template": "Payment memory is not empty."}}]
Then info about available memory.
[{"id":123, "severity": 1, "progress": 2, "text": {"id": 17, "template": "Available memory 768 kB."}}]
3.2.2. Complete
Running action can be closed in two ways.
Status message
To complete running action, must PDM send status message which mentioned action number in mnemonic CMD
in the same way as in V1.
In case, that there are open multiple actions with the same number (maybe with different arguments) only the first remote action will be closed.
To close all of them, multiple status messages must be send in the same order as remote action request was provided.
PDM is responsible to maintain action order, if it want to use this method.
Alternatively mnemonic CME
can be used to indicate ids of remote actions which should be closed.
For example array below will close remote actions with id 123,184 and 77.
If such an ID does not exist or does not belong to the PDM, it is silently ignored.
[123,184,77]
Because IDs uniquely identify remote action, is orderer of array elements not important. Remote actions can be also close in different ordter then they was requested.
Progress report
PDM may also complete remote action by updating its status. Field severity
transfers operation result.
It this case there will be no status message in log book.
Remote action will be closed ad hock without any trace in status log.
[{"id":123, "severity": 0, "progress": 3, "text": {"id": 17, "template": "Network switched successfully."}}]
Although it is technically possible to send multiple update for completed
progress report, it is discouraged to do so, to avoid user confusing.
4. JSON types
4.1. Progress
Progress describes state in which current action is. Do we need more or less states?.
enum Progress {
// Action was received by PDM and waits for processing
acknowledged = 0,
// Action is currently prevented from execution, by required conditions. E.g. it waits for its time.
waiting,
// Action is running.
running,
// Action is completed.
completed
}
4.2. Severity
Defines how this status impact the system. It is compatible with status messages AlertType.
enum Severity {
none = 0,
info,
warning,
error,
critical
}
4.3. Text
Types describing a way how to transfer texts from action updates.
/**
* Text associated with remote action progress update.
*/
interface Text {
/** Text ID. Probably not needed. */
id: number;
/** Text template. E.g. "The quick {1} {2} jumped over the lazy {3}." */
template: string;
/** Template arguments. */
args: Array<Argument>;
}
/**
* Text argument.
* It is composed from value and optional formatting hint.
*/
interface Argument {
// Argument value
val: string | number;
// How to format argument value. If omitted it is presented as it is.
fh?: FormattingHint;
}
// !!! This structure is not yet fully finished
/**
* Defines what kind of value is present.
* UI formatter may take advantage from it and format value better than just plain text.
*/
enum FormattingHint {
// Lookup localized value in dictionary
lookup,
// ISO formatted date time
iso_date_time
}
5. Action text messages
5.1. Templates
PDM sends a template with placeholders like this:
"At {1,time} on {1,date}, there was {2,lookup} on {3} {0,number,integer}."
Index | Value |
---|---|
0 |
7 |
1 |
"2053-06-03T12:30" |
2 |
"a disturbance in the Force" |
3 |
"planet" |
The result text will be:
At 12:30 PM on Jul 3, 2053, there was a disturbance in the Force on planet 7.
5.2. Translation
The challenge is, how to present the text from action progress to the user, in his own language and simultaneously stay open for new text from PDM without necessity to update PDM.control just because of new text.
5.2.1. Solution
The idea here is to use text it self as translation key. If translation is not found the the key it self is used. In this case the user will see English texts for new texts from PDM. The older text which are already translated in PDM.control will be used in user’s native language (at least after PDM.control update).
5.2.2. Pitfall
Suppose to have following text resource
Key | German | Czech |
---|---|---|
Green {0} jumped over {1}. |
Grüner {0} sprang über einen {1}. |
Zelená {0} přeskočila {1}. |
elephant |
Elefant |
slon |
cow |
Kuh |
kráva |
river |
Flus |
řeka |
field |
Feld |
pole |
This approach will work well for languages without declination. But there is catch in languages which do need declination. Compare results for English, German, Czech.
En: Green frog jumped over river. De: Grüner Elephant sprang über einen Flus. Cz: Zelená slon přeskočila řeku.
En: Green cow jumped over field. De: Grüner Kuh sprang über einen Feld. Cz: Zelená kráva přeskočila pole.
As you can see, the grammar may not be correct in all cases.