We've launched our new site at www.openlighting.org. This wiki will remain and be updated with more technical information.
Difference between revisions of "RDM PID Definitions"
From wiki.openlighting.org
(→Optional Fields) |
Peternewman (talk | contribs) m (Fix some links) |
||
(17 intermediate revisions by 2 users not shown) | |||
Line 3: | Line 3: | ||
[[OLA]] reads the structure of [[RDM]] parameter messages at runtime. This allows the users to update PID definitions without upgrading the binaries and also means we can add knowledge of new manufacturer PIDs to the RDM controller software very quickly. | [[OLA]] reads the structure of [[RDM]] parameter messages at runtime. This allows the users to update PID definitions without upgrading the binaries and also means we can add knowledge of new manufacturer PIDs to the RDM controller software very quickly. | ||
− | + | To enable this, we've designed a parameter definition language which allows us to describe the structure of RDM parameter messages in a language-independent manner. This language has the following assumptions: | |
− | + | * The structure of a message (i.e. # of repeated values and the length of variable sized fields) must be able to be determined solely from the parameter definition and the length of the message. All parameters in E1.20 and E1.37-1 conform to this, as well as every manufacturer parameter I've encountered. This means that only one variable-sized field can be present in each message, and that [http://en.wikipedia.org/wiki/Type-length-value TLV] style messages aren't supported. | |
+ | |||
+ | To get the full benefits of the definition language, the parameter definitions should also: | ||
+ | |||
+ | * Use big-endian for multi-byte fields | ||
+ | * When integer values are used, the values are stores as normal int values, not as ASCII. | ||
+ | |||
+ | The canonical parameter definitions are stored on the http://rdm.openlighting.org site. The data from the site is used to generate an ASCII [https://github.com/google/protobuf protocol buffer] which is then checked into the OLA codebase and distributed with the tarball. One day we may support automatic updating of the parameter definition files. | ||
+ | |||
+ | You can see the latest pid protobufs at <tt>[[code:data/rdm/pids.proto|pids.proto]]</tt> and <tt>[[code:data/rdm/manufacturer_pids.proto|manufacturer_pids.proto]]</tt>. In the tarball the files are in <tt>data/rdm/</tt> and they are usually installed into <tt>/usr/local/share/ola/pids/</tt>. | ||
== Adding New Parameters == | == Adding New Parameters == | ||
− | Parameters are added to the rdm.openlighting.org site by specifying the message structure, as well as properties like the parameter name and | + | Parameters are added to the rdm.openlighting.org site by specifying the message structure, as well as properties like the parameter name and PID in a Python file. To get started, clone the rdm.openlighting.org code from https://github.com/OpenLightingProject/rdm-app. The definitions are found in <tt>data/pid_data.py</tt>. Once you have edited this file push the change to a public git repo and email the open-lighting list asking for a pull request. Simon will sanity check the new parameters and push them to the rdm.openlighting.org site. |
+ | |||
+ | You can use RDM Pid Builder to add your definitions: | ||
+ | http://imaginux.com/lighting/pids/addpids.php | ||
+ | |||
+ | Or use the tool locally: | ||
+ | https://github.com/RenZ0/rdm-pid-builder | ||
== Structure == | == Structure == | ||
+ | |||
+ | The section describes the syntax of the parameter definition language in the Python representation used by the rdm.openlighting.org site. The protobuf representation is very similar and the concepts are the same for both representations. | ||
The parameter definitions file is just a Python data structure. At the top level there are two variables <tt>MANUFACTURER_PIDS</tt> and <tt>ESTA_PIDS</tt>. | The parameter definitions file is just a Python data structure. At the top level there are two variables <tt>MANUFACTURER_PIDS</tt> and <tt>ESTA_PIDS</tt>. | ||
Line 54: | Line 71: | ||
; name | ; name | ||
: The name of the PID, should be in CAPS like the names in E1.20 | : The name of the PID, should be in CAPS like the names in E1.20 | ||
− | ; | + | ; link |
: A URL pointing to where this information was obtained, set to the empty string is there isn't one | : A URL pointing to where this information was obtained, set to the empty string is there isn't one | ||
; notes | ; notes | ||
Line 76: | Line 93: | ||
== Items == | == Items == | ||
− | Items represent the data fields within each message. An item can be a group of items, | + | Items represent the data fields within each message. An item can also be a group of items, which is how repeated fields are supported. There are only two required attributes for an item: |
+ | |||
<pre> | <pre> | ||
{ | { | ||
− | 'name': < | + | 'name': <string>, |
'type': <string>', | 'type': <string>', | ||
} | } | ||
</pre> | </pre> | ||
− | + | Item names should be all lower case, with spaces replaced by _ . In OLA, item names are run through CustomCapitalizeLabel() before being displayed to the user. This replaces '_' with ' ' and capitalizes words. For more details see the code in [[code:common/utils/StringUtils.cpp|StringUtils.cpp]]. | |
+ | |||
+ | The valid item types are: | ||
* bool | * bool | ||
Line 94: | Line 114: | ||
* int32 | * int32 | ||
* string | * string | ||
− | * group | + | * group, a group of items, see below for more details. |
− | * ipv4 | + | * ipv4, a 32 bit IP address |
− | * uid | + | * mac, a 48 bit MAC address |
+ | * uid, a 48 bit UID. | ||
+ | |||
+ | All multi-byte items are big endian. | ||
+ | |||
+ | === Optional Attributes === | ||
+ | |||
+ | These are only defined for certain item types. | ||
+ | |||
+ | ==== Labels ==== | ||
− | + | Labels can be used with int items (uint8, uint16, uint32, int8, int16, int32) to attach string descriptions to values. | |
− | + | Using DISPLAY_INVERT as an example: | |
− | labels | + | <pre> |
− | multiplier | + | {'name': 'invert_status', 'type': 'uint8', |
− | + | 'labels': [(0, 'Off'), (1, 'On'), (2, 'Auto')], | |
− | min_size | + | } |
− | + | </pre> | |
+ | |||
+ | Labels implicitly restrict the values that the item can hold. In the example above, a value outside the range 0-2 will generate an exception. | ||
+ | |||
+ | ==== Ranges ==== | ||
+ | |||
+ | Ranges are used to limit the values for an int item. Using REAL_TIME_CLOCK as the example: | ||
+ | |||
+ | <pre> | ||
+ | {'name': 'month', 'type': 'uint8', 'range': [(1, 12)]} | ||
+ | </pre> | ||
+ | |||
+ | If both ranges and labels are specified, the union of values is used as the set of allowed values for the item. | ||
+ | |||
+ | ==== Multiplier ==== | ||
+ | |||
+ | This is used to shift the decimal point for int items. For example, in PRESET_INFO, the fade times are reported in 10ths of a second. | ||
+ | |||
+ | <pre> | ||
+ | {'name': 'max_preset_fade_time', 'type': 'uint16', 'multiplier': -1}, | ||
+ | </pre> | ||
+ | |||
+ | ==== Max Size ==== | ||
+ | |||
+ | This limits the maximum size of a string, or the maximum allowed groups in a repeated item. From DEVICE_LABEL: | ||
+ | |||
+ | <pre> | ||
+ | {'name': 'label', 'max_size': 32, 'type': 'string'} | ||
+ | </pre> | ||
+ | |||
+ | ==== Min Size ==== | ||
+ | |||
+ | The opposite of max_size, used for strings and groups. From LANGUAGE_CAPABILITIES: | ||
+ | |||
+ | <pre> | ||
+ | {'name': 'language', 'max_size': 2, 'min_size': 2, 'type': 'string'} | ||
+ | </pre> | ||
+ | |||
+ | === Item Groups === | ||
+ | |||
+ | |||
+ | TODO: fill this in | ||
== Examples == | == Examples == | ||
− | == DEVICE_INFO == | + | These examples show how parameters from E1.20 are described using the PID Definitions Syntax. |
+ | |||
+ | === DEVICE_INFO === | ||
A simple example is DEVICE_INFO. This is only defined for GET commands, and returns a message with various mixed-type fields: | A simple example is DEVICE_INFO. This is only defined for GET commands, and returns a message with various mixed-type fields: | ||
Line 133: | Line 205: | ||
</pre> | </pre> | ||
− | == DEVICE_LABEL == | + | === DEVICE_LABEL === |
DEVICE_LABEL is defined for GET and SET. This example shows how to limit the length of a string. | DEVICE_LABEL is defined for GET and SET. This example shows how to limit the length of a string. | ||
Line 151: | Line 223: | ||
'value': 130}, | 'value': 130}, | ||
} | } | ||
+ | </pre> | ||
+ | |||
+ | === SLOT_INFO === | ||
+ | |||
+ | This example shows how repeated fields work: | ||
+ | |||
+ | <pre> | ||
+ | {'get_request': {'items': []}, | ||
+ | 'get_response': {'items': [ | ||
+ | {'name': 'slots', | ||
+ | 'type': 'group', | ||
+ | 'items': [ | ||
+ | {'name': 'slot_offset', 'type': 'uint16'}, | ||
+ | {'name': 'slot_type', 'type': 'uint8'}, | ||
+ | {'name': 'slot_label_id', 'type': 'uint16'} | ||
+ | ]}, | ||
+ | ]}, | ||
+ | 'get_sub_device_range': 2, | ||
+ | 'name': 'SLOT_INFO', | ||
+ | 'value': 288}, | ||
</pre> | </pre> |
Latest revision as of 16:54, 2 November 2015
Contents
Parameter Definitions and OLA
OLA reads the structure of RDM parameter messages at runtime. This allows the users to update PID definitions without upgrading the binaries and also means we can add knowledge of new manufacturer PIDs to the RDM controller software very quickly.
To enable this, we've designed a parameter definition language which allows us to describe the structure of RDM parameter messages in a language-independent manner. This language has the following assumptions:
- The structure of a message (i.e. # of repeated values and the length of variable sized fields) must be able to be determined solely from the parameter definition and the length of the message. All parameters in E1.20 and E1.37-1 conform to this, as well as every manufacturer parameter I've encountered. This means that only one variable-sized field can be present in each message, and that TLV style messages aren't supported.
To get the full benefits of the definition language, the parameter definitions should also:
- Use big-endian for multi-byte fields
- When integer values are used, the values are stores as normal int values, not as ASCII.
The canonical parameter definitions are stored on the http://rdm.openlighting.org site. The data from the site is used to generate an ASCII protocol buffer which is then checked into the OLA codebase and distributed with the tarball. One day we may support automatic updating of the parameter definition files.
You can see the latest pid protobufs at pids.proto and manufacturer_pids.proto. In the tarball the files are in data/rdm/ and they are usually installed into /usr/local/share/ola/pids/.
Adding New Parameters
Parameters are added to the rdm.openlighting.org site by specifying the message structure, as well as properties like the parameter name and PID in a Python file. To get started, clone the rdm.openlighting.org code from https://github.com/OpenLightingProject/rdm-app. The definitions are found in data/pid_data.py. Once you have edited this file push the change to a public git repo and email the open-lighting list asking for a pull request. Simon will sanity check the new parameters and push them to the rdm.openlighting.org site.
You can use RDM Pid Builder to add your definitions: http://imaginux.com/lighting/pids/addpids.php
Or use the tool locally: https://github.com/RenZ0/rdm-pid-builder
Structure
The section describes the syntax of the parameter definition language in the Python representation used by the rdm.openlighting.org site. The protobuf representation is very similar and the concepts are the same for both representations.
The parameter definitions file is just a Python data structure. At the top level there are two variables MANUFACTURER_PIDS and ESTA_PIDS.
MANUFACTURER_PIDS = [ {'id': <int>, # the manufacturer ID, written in hex 'name': <string>, # the manufacturer name 'pids': [<parameter_definition>], }, ... ] ESTA_PIDS = [ <parameter_definition> ]
Each Parameter Definition takes the form:
{ 'get_request': {'items': [<item>]}, 'get_response': {'items': [<item>]}, 'get_sub_device_range': <int>, 'name': <string>, 'set_request': {'items': [<item>]}, 'set_response': {'items': [<item>]}, 'set_sub_device_range': <int>, 'link': <string>, # the URL for more information 'notes': <string>, 'value': <int>, # the PID }
- {get,set}_request
- The structure of the GET / SET request. This specifies a list of items which are the fields in the parameter message. See the section below for more details.
- {get,set}_response
- The structure of the GET / SET response, same structure as the _request fields.
- {get,set}_sub_device_range
- A value between 0 and 3 which places restrictions on the value of the SubDevice field in the RDM message.
- name
- The name of the PID, should be in CAPS like the names in E1.20
- link
- A URL pointing to where this information was obtained, set to the empty string is there isn't one
- notes
- A text description of what this parameter does. This should be explain to the user how to use the parameter.
- value
- The parameter ID (PID).
The allowed values for the sub_device_ranges are:
- 0
- ROOT_DEVICE, implies the subdevice field is 0x0000
- 1
- ROOT_OR_ALL_SUBDEVICE, the subdevice field is 0x0000 to 0x0200 or 0xffff
- 2
- ROOT_OR_SUBDEVICE, the subdevice field is 0x0000 to 0x0200
- 3
- ONLY_SUBDEVICES, the sub device field is 0x0001 to 0x0200
If a {get,set}_request field isn't present, this means the parameter doesn't support the GET / SET operation. In that case the corresponding _response field should also not be present. Note that this differs from a _request field which is present, but contains no items. The latter means that the parameter data length is 0.
Items
Items represent the data fields within each message. An item can also be a group of items, which is how repeated fields are supported. There are only two required attributes for an item:
{ 'name': <string>, 'type': <string>', }
Item names should be all lower case, with spaces replaced by _ . In OLA, item names are run through CustomCapitalizeLabel() before being displayed to the user. This replaces '_' with ' ' and capitalizes words. For more details see the code in StringUtils.cpp.
The valid item types are:
- bool
- uint8
- uint16
- uint32
- int8
- int16
- int32
- string
- group, a group of items, see below for more details.
- ipv4, a 32 bit IP address
- mac, a 48 bit MAC address
- uid, a 48 bit UID.
All multi-byte items are big endian.
Optional Attributes
These are only defined for certain item types.
Labels
Labels can be used with int items (uint8, uint16, uint32, int8, int16, int32) to attach string descriptions to values.
Using DISPLAY_INVERT as an example:
{'name': 'invert_status', 'type': 'uint8', 'labels': [(0, 'Off'), (1, 'On'), (2, 'Auto')], }
Labels implicitly restrict the values that the item can hold. In the example above, a value outside the range 0-2 will generate an exception.
Ranges
Ranges are used to limit the values for an int item. Using REAL_TIME_CLOCK as the example:
{'name': 'month', 'type': 'uint8', 'range': [(1, 12)]}
If both ranges and labels are specified, the union of values is used as the set of allowed values for the item.
Multiplier
This is used to shift the decimal point for int items. For example, in PRESET_INFO, the fade times are reported in 10ths of a second.
{'name': 'max_preset_fade_time', 'type': 'uint16', 'multiplier': -1},
Max Size
This limits the maximum size of a string, or the maximum allowed groups in a repeated item. From DEVICE_LABEL:
{'name': 'label', 'max_size': 32, 'type': 'string'}
Min Size
The opposite of max_size, used for strings and groups. From LANGUAGE_CAPABILITIES:
{'name': 'language', 'max_size': 2, 'min_size': 2, 'type': 'string'}
Item Groups
TODO: fill this in
Examples
These examples show how parameters from E1.20 are described using the PID Definitions Syntax.
DEVICE_INFO
A simple example is DEVICE_INFO. This is only defined for GET commands, and returns a message with various mixed-type fields:
{'get_request': {'items': []}, 'get_response': {'items': [ {'name': 'protocol_major', 'type': 'uint8'}, {'name': 'protocol_minor', 'type': 'uint8'}, {'name': 'device_model', 'type': 'uint16'}, {'name': 'product_category', 'type': 'uint16'}, {'name': 'software_version','type': 'uint32'}, {'name': 'dmx_footprint', 'type': 'uint16'}, {'name': 'current_personality', 'type': 'uint8'}, {'name': 'personality_count','type': 'uint8'}, {'name': 'dmx_start_address', 'type': 'uint16'}, {'name': 'sub_device_count','type': 'uint16'}, {'name': 'sensor_count', 'type': 'uint8'}]}, 'get_sub_device_range': 2, 'name': 'DEVICE_INFO', 'value': 96},
DEVICE_LABEL
DEVICE_LABEL is defined for GET and SET. This example shows how to limit the length of a string.
{'get_request': {'items': []}, 'get_response': {'items': [ {'name': 'label', 'max_size': 32, 'type': 'string'} ]}, 'get_sub_device_range': 2, 'name': 'DEVICE_LABEL', 'set_request': {'items': [ {'name': 'label','max_size': 32, 'type': 'string'} ]}, 'set_response': {'items': []}, 'set_sub_device_range': 1, 'value': 130}, }
SLOT_INFO
This example shows how repeated fields work:
{'get_request': {'items': []}, 'get_response': {'items': [ {'name': 'slots', 'type': 'group', 'items': [ {'name': 'slot_offset', 'type': 'uint16'}, {'name': 'slot_type', 'type': 'uint8'}, {'name': 'slot_label_id', 'type': 'uint16'} ]}, ]}, 'get_sub_device_range': 2, 'name': 'SLOT_INFO', 'value': 288},