You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: docs/communication.md
+101-46
Original file line number
Diff line number
Diff line change
@@ -1,8 +1,8 @@
1
1
# Communication
2
-
libproc includes a low-ish overhead communication protocol that attempts to reduce the time and busywork required of developers. The communication protocol is based on [XDR (External Data Representation Standard)](https://tools.ietf.org/html/rfc4506). There are minimal changes to the over-the-wire protocol and more changes to the XDR schema syntax, each of which is described in the following sections.
2
+
libproc includes a low-ish overhead communication protocol that attempts to reduce the time and busywork required of developers. The communication protocol is based on [XDR (External Data Representation Standard)](https://tools.ietf.org/html/rfc4506). There are minimal changes to the over-the-wire protocol and more changes to the XDR schema syntax, each of which is described in the following sections.
3
3
4
4
# Schema
5
-
The objective of the schema is to streamline the developer's time when defining additional command formats. The schema is a modified version of the XDR schema. Most of the additions focus on adding support for consolid command and data documentation, but there are also additions to help the format scale to a more distributed architecture, such as namespaces and include directives. There is a custom, python-based parser in the xdrgen folder of libproc.
5
+
The objective of the schema is to streamline the developer's time when defining additional command formats. The schema is a modified version of the XDR schema. Most of the additions focus on adding support for consolid command and data documentation, but there are also additions to help the format scale to a more distributed architecture, such as namespaces and include directives. There is a custom, python-based parser in the xdrgen folder of libproc.
6
6
7
7
## Schema Narrative
8
8
@@ -11,22 +11,22 @@ The schema must start with a namespace declaration:
11
11
```
12
12
namespace ID;
13
13
```
14
-
The root namespace is assumed to be `IPC`. All other namespaces fall under IPC. Sub-namespaces can exist via imports. Namespaces in imported files are added under the namespace of their parent file.
14
+
The root namespace is assumed to be `IPC`. All other namespaces fall under IPC. Sub-namespaces can exist via imports. Namespaces in imported files are added under the namespace of their parent file.
15
15
16
16
### Imports
17
-
The import directive can be used at any time at the top-level of the schema file. Importing another schema file is an easy way to delegate parts of the schema to sub-modules within the same process. All imported items are incorporated into the root schema in a sub-namespace. The format of the import statement is:
17
+
The import directive can be used at any time at the top-level of the schema file. Importing another schema file is an easy way to delegate parts of the schema to sub-modules within the same process. All imported items are incorporated into the root schema in a sub-namespace. The format of the import statement is:
18
18
```
19
19
import "relative path to .x file";
20
20
```
21
21
### Constants
22
-
Constants are a good way ensure all command, structure, and error numbers come from a consistent number space. They get converted into the appropriate constant type of the target language. The syntax for constants is:
22
+
Constants are a good way ensure all command, structure, and error numbers come from a consistent number space. They get converted into the appropriate constant type of the target language. The syntax for constants is:
23
23
```
24
24
const BASE = VALUE;
25
25
```
26
26
The VALUE can be expressed in either decimal or hexadecimal.
27
27
28
28
### Enumerations
29
-
Enumerations are used for multiple purposes. First, you must use enumerated types as the basis for type numbers, command numbers, and error numbers. You should also use them when storing enumerated types in a structure. The syntax for enumerations is:
29
+
Enumerations are used for multiple purposes. First, you must use enumerated types as the basis for type numbers, command numbers, and error numbers. You should also use them when storing enumerated types in a structure. The syntax for enumerations is:
30
30
```
31
31
enum NAME {
32
32
ITEM1 = VALUE1;
@@ -36,33 +36,52 @@ enum NAME {
36
36
A value can either be a constant, numeric literal, or a constant plus a numeric literal.
37
37
38
38
### Errors
39
-
Error values get assigned a textual description. This assists in documentation and auto-generating code that produces more human readable error messages. The syntax for errors is:
39
+
Error values get assigned a textual description. This assists in documentation and auto-generating code that produces more human readable error messages. The syntax for errors is:
40
40
```
41
41
error ENUM_NAME::ENUM_ITEM = "error message";
42
42
```
43
-
Note that all error numbers must be defined as an enumerated type. You must specify both the name of the enumerated type and the name of the item when specifying the error number.
43
+
Note that all error numbers must be defined as an enumerated type. You must specify both the name of the enumerated type and the name of the item when specifying the error number.
44
44
45
45
### Commands
46
-
Commands specify the actual commands sent over the network to control the target process. There are two general types of commands. First, you can specify commands that can be handled by a callback function in the process. This can also return data via a response. The second type of command is one that only returns data without side effects. This type of command is so prevalent that there is special handling code in libproc to streamline it and make it more flexible. The syntax for commands is:
46
+
Commands specify the actual commands sent over the network to control the target process. There are two general types of commands: Generic commands and handled commands. Generic commands are commands that are only used to aggregate and return data. Handled commands are commands that and handled explicitly by a callback function.
As with other numbers, all command numbers must be defined as an enumerated type. Enumerated type names must include both the enumeration name and the item name, separated by double colons. The summaryfield is required but the other fields are only needed some of the time.
59
+
All commands must be defined as an enumerated type. Enumerated type names must include both the enumeration name and the item name, separated by double colons. The `summary` and `types`field are required, but the `param` field is optional. Descriptions of the command's values are listed below.
55
60
56
-
`summary`: A textual description of what the command does. This description flows down to command-line help messages and other documentation.
61
+
`summary`: A textual description of what the command does. This description flows down to command-line help messages and other documentation.
57
62
58
-
`params`: If present it specifies the structure number of the parameters to the command. The structure must be defined in a structure statement (see the next section). Commands that do not require parameters may omit this option and will automatically be given a void param.
63
+
`params`: If present it specifies the structure number of the parameters to the command. The structure must be defined in a structure statement (see the next section). Commands that do not require parameters may omit this option and will automatically be given a void parameter.
59
64
60
-
`types`: A comma separated list of structure numbers to request for this command. This triggers the special handling code that automatically responds with the correct structures. When using they types option you do not specify a command number. The list of types gets set to the remote process using a built-in command.
65
+
`types`: A comma separated list of structures used in this command.
61
66
62
-
`...} = ENUM_NAME::ENUM_ITEM`: This option specifies the number of this command. It is mutually exclusive with the `types` field.
67
+
#### Handled commands
68
+
Handled command have a similar syntax.
69
+
```
70
+
command "command-name" {
71
+
summary "command description";
72
+
param ENUM_NAME::ENUM_ITEM;
73
+
} = ENUM_NAME::ENUM_ITEM;
74
+
```
75
+
As with generic commands, the summary field is required but the `param` field is optional.
76
+
77
+
`summary`: A textual description of what the command does. This description flows down to command-line help messages and other documentation.
78
+
79
+
`param`: If present it specifies the structure number of the parameters to the command. The structure must be defined in a structure statement (see the next section). Commands that do not require parameters may omit this option and will automatically be given a void param.
80
+
81
+
`...} = ENUM_NAME::ENUM_ITEM`: Specifies this commands number.
63
82
64
83
### Structures
65
-
Structures define the data that gets sent over the network. They result in an equivalent language-level structure and code that automatically encodes it and decodes it for transmission. They also include field-level documentation and identifiers that are included in generated documentation and command line utilities. The syntax for structure definitions is:
84
+
Structures define the data that gets sent over the network. They result in an equivalent language-level structure and code that automatically encodes it and decodes it for transmission. They also include field-level documentation and identifiers that are included in generated documentation and command line utilities. The syntax for structure definitions is:
66
85
```
67
86
struct Name {
68
87
fieldtype fieldname {
@@ -78,30 +97,30 @@ struct Name {
78
97
...
79
98
} = ENUM_NAME::ENUM_ITEM;
80
99
```
81
-
Structure names must be unique within the namespace. They must have one or more field definitions. The field documentation appears in the `{}` block following the fieldname and before the semi-colon. It is optional but strongly encouraged. In some cases, just as a length field for an array, require no documentation.
100
+
Structure names must be unique within the namespace. They must have one or more field definitions. The field documentation appears in the `{}` block following the fieldname and before the semi-colon. It is optional but strongly encouraged. In some cases, just as a length field for an array, require no documentation.
82
101
83
-
`fieldtype`: The type of the structure field. Available types are: `int`, `unsigned int`, `hyper`, `unsigned hyper`, `float`, `string`, `opaque`, and any enumeration or structure name.
102
+
`fieldtype`: The type of the structure field. Available types are: `int`, `unsigned int`, `hyper`, `unsigned hyper`, `float`, `string`, `opaque`, and any enumeration or structure name.
84
103
85
-
When specifying an array you must separately declare a field to hold the array length and it must be before the array in the structure. Use the `[]` syntax to specify a field as an array and denote the field that serves as the length.
104
+
When specifying an array you must separately declare a field to hold the array length and it must be before the array in the structure. Use the `[]` syntax to specify a field as an array and denote the field that serves as the length.
86
105
87
-
`...} = ENUM_NAME::ENUM_ITEM`: This option specifies the number of this structure.
106
+
`...} = ENUM_NAME::ENUM_ITEM`: This option specifies the number of this structure.`ENUM_NAME` is case-insensitive.
88
107
89
108
#### Field Documentation Options
90
-
The following options are available for fields. These options can be specified in any order:
109
+
The following options are available for fields. These options can be specified in any order:
91
110
92
-
`name`: Provides a textual, human-readable name for this field. This is used in documentation and when printing the field to stdout in human-readable form.
111
+
`name`: Provides a textual, human-readable name for this field. This is used in documentation and when printing the field to stdout in human-readable form.
93
112
94
-
`type`: A globally unique identifier for this field. It isn't a quoted string and needs to follow standard language identifier rules. The key needs to be globally unique among all fields in the entire combined schema. The key is used when producing key=value pair output and comma separated output. It is also used to identify the field when automatically parsing from the command line. If this field is omitted the field will not be available for printing or scanning from a command line.
113
+
`type`: A globally unique identifier for this field. It isn't a quoted string and needs to follow standard language identifier rules. The key needs to be globally unique among all fields in the entire combined schema. The key is used when producing key=value pair output and comma separated output. It is also used to identify the field when automatically parsing from the command line. If this field is omitted the field will not be available for printing or scanning from a command line.
95
114
96
-
`description`: A longer description of this field. It is used for documentation and command line help.
115
+
`description`: A longer description of this field. It is used for documentation and command line help.
97
116
98
117
`unit`: The unit label for the engineering units of the field.
99
118
100
-
`divisor`: `offset`: Used to specify a linear conversion from raw units to engineering units. The raw value is converted as follows: `(value/divisor) + offset`. The values in the structure are always transmitted as raw values. If no values are provided 0 is assumed. A 0 divisor results in no conversion, not a math error.
119
+
`divisor`: `offset`: Used to specify a linear conversion from raw units to engineering units. The raw value is converted as follows: `(value/divisor) + offset`. The values in the structure are always transmitted as raw values. If no values are provided 0 is assumed. A 0 divisor results in no conversion, not a math error.
101
120
102
121
### Number spaces
103
-
All enumeration, structure, and command numbers need to be globally unique in order for the system to work correctly. All the numeric values are 4 bytes long. Numbers are allocated in 1-byte chunks to help minimize coordination overhead. The high-order byte of all command numbers must be zero. The number allocations are
104
-
documented in the [libproc number allocation table](https://github.com/PolySat/libproc/blob/xdr-updates/docs/number_allocations.md). This table must be updated prior to use any numbers.
122
+
All enumeration, structure, and command numbers need to be globally unique in order for the system to work correctly. All the numeric values are 4 bytes long. Numbers are allocated in 1-byte chunks to help minimize coordination overhead. The high-order byte of all command numbers must be zero. The number allocations are
123
+
documented in the [libproc number allocation table](https://github.com/PolySat/libproc/blob/xdr-updates/docs/number_allocations.md). This table must be updated prior to use any numbers.
105
124
106
125
## Example
107
126
The following example shows a small schema, including structures, commands, and errors.
@@ -114,7 +133,6 @@ const ERR_BASE = 0x02FFFF00;
114
133
115
134
enum Cmds {
116
135
SET_SPEED = CMD_BASE + 0
117
-
118
136
};
119
137
120
138
enum Types {
@@ -123,10 +141,9 @@ enum Types {
123
141
};
124
142
125
143
enum Responses {
126
-
BAD_SPEED = TYPE_BASE + 0
144
+
BAD_SPEED = ERR_BASE + 0
127
145
};
128
146
129
-
130
147
error Responses::BAD_SPEED = "User specified an unsupported speed";
131
148
132
149
struct Speed {
@@ -148,33 +165,33 @@ struct Speed {
148
165
description "The rotational speed of the z-axis wheel";
149
166
unit "RPM";
150
167
};
151
-
};
168
+
} = types::SPEED_SETTINGS;
152
169
153
170
struct Debug {
154
171
unsigned int state {
155
172
name "State";
156
173
key wheel_state;
157
-
description "The state of the wheel driver. Provides a bit-field of internal information.";
174
+
description "The state of the wheel driver. Provides a bit-field of internal information.";
158
175
};
159
-
};
176
+
} = Types::DEBUG;
160
177
161
178
command "example-set-wheel-speed" {
162
-
summary "Sets the speed of the reaction wheels";
163
-
param types::Speed;
164
-
} = cmds::SET_SPEED;
179
+
summary "Handled command setting the speed of the reaction wheels";
180
+
param Types::SPEED_SETTINGS;
181
+
} = Cmds::SET_SPEED;
165
182
166
183
command "example-debug" {
167
-
summary "Provides debugging data about the wheel sub-system";
168
-
types = types::DEBUG;
184
+
summary "Generic command providing debugging data about the wheel sub-system";
185
+
types = Types::DEBUG;
169
186
};
170
187
171
188
```
172
189
173
190
## Built-in Functionality
174
-
libproc includes some built-in functionality to support universal features across all programs. The include providing generic structures for commands, responses, common error messages, and process heartbeats. All the constants, structures, and related functions can be found in libproc's "cmd_schema.h" header file.
191
+
libproc includes some built-in functionality to support universal features across all programs. The library provides general structures for commands, responses, common error messages, and process heartbeats. All the constants, structures, and related functions can be found in libproc's "cmd_schema.h" header file.
175
192
176
193
### Heartbeat Structure
177
-
Heartbeats can be requested via the `IPC::types::HEARTBEAT` structure and `IPC::cmds::DATA_REQ` command. It contains basic command, response, and heartbeat counters.
194
+
Heartbeats can be requested via the `IPC::Types::HEARTBEAT` structure and `IPC::Cmds::DATA_REQ` command. It contains basic command, response, and heartbeat counters.
178
195
179
196
### Errors
180
197
libproc provides 4 error messages, including one that denotes success:
@@ -194,19 +211,57 @@ The built-in structures include the following:
194
211
195
212
### Commands
196
213
The built-in commands include the following:
197
-
`IPC::cmds::DATA_REQ`: The command to request data structures by number.
198
-
`IPC::types::HEARTBEAT`: The command to request a heartbeat from the process.
199
-
214
+
`IPC::Cmds::DATA_REQ`: The command to request data structures by number.
215
+
`IPC::Types::HEARTBEAT`: The command to request a heartbeat from the process.
200
216
201
217
# Parser
202
-
The parser and code generator is written in Python. It can be found in xdrgen/xdrgen within the libproc project. To use the parser run the following:
218
+
The parser and code generator is written in Python. It can be found in xdrgen/xdrgen within the libproc project. To use the parser run the following:
where <prefix> is the base name of the output file you want. This will generate both a <prefix>.c and <prefix>.h file.
222
+
where <prefix> is the base name of the output file you want. This will generate both a <prefix>.c and <prefix>.h file.
207
223
208
224
# C API
209
225
226
+
## Generic commands
227
+
Generic commands are handled internally within libproc. The response structures are created via populators. The following code is a populator from the example schema above.
0 commit comments