When discovering PDOs over the gRPC Network RPC, every entry in the response has address_info.data_type = RSIDataTypeINT32 regardless of the underlying CoE object’s type as declared in the ENI. Sample data is then packed into FirmwareValue.int32_value zero-extended for 16-bit channels, with no sign extension. This causes signed-16-bit PDOs (notably CiA-402 0x6077 Torque actual value, declared INT in the ENI) to surface with wrong sign in our application
The C++ RapidCode::MotionController API does not have this issue because NetworkInputDataTypeNameGet() returned the ENI string (e.g. “INT”, “DINT”, “UINT”) and I mapped it to RSIDataType. The gRPC PdoInputInfo proto carries no equivalent string field, so once data_type is collapsed to INT32 the type is unrecoverable.
Requested fix (preferred order):
Populate address_info.data_type with the ENI/CoE-declared RSIDataType per PDO (not always INT32). The mapping is the same one NetworkInputDataTypeNameGet() uses internally — INT → INT16, UINT → UINT16, DINT → INT32, etc. This restores feature parity with the in-process C++ API.
Alternatively (or additionally), expose the CoE type name string on PdoInputInfo / PdoOutputInfo (e.g. add string data_type_name = 5; to PdoInputInfo). The string would mirror the local NetworkInputDataTypeNameGet(i) return value and let clients run their own conversion.
We’re working around this by overriding the declared type for known signed-16 PDOs (Torque actual value) and sign-extending from int32_value ourselves but this only covers the PDO names we’ve enumerated.
Thanks for the detailed write-up. Diagnosis and proposed fixes are spot-on. We’ve opened a tracking issue and plan to ship both:
1. Populate address_info.data_type from the ENI-declared CoE type.INT → INT16, UINT → UINT16, DINT → INT32, UDINT → UINT32, REAL → FLOAT, etc., with a sensible fallback for type names that don’t have a direct RSIDataType analogue. This gives the CiA-402 PDOs you called out (Torque actual value, Modes of operation display, Position actual value, and the rest) correct sign and width through the existing int16_value / uint16_value / int32_value cells in FirmwareValue.
A quick note on why we need the fallback: across the ESI files we ship support for, the type-name surface is wider than the CiA-402 primitives. Our library spans ~220 vendor ESIs and contains around 1,600 distinct type-name strings. Roughly 70% of occurrences are the standard primitives that map cleanly to RSIDataType. The rest is a long tail: vendor-defined record types (DT8000, DT1A00-style names that resolve to per-vendor RECORD definitions), ARRAY[N] OF BYTE for module-mapped I/O, sub-byte widths like BIT2/BIT4, and odd widths like INT24/UINT48. We won’t try to invent RSIDataType values for all of those. The second change is how we expose them.
2. Add a string data_type_name field to PdoInputInfo / PdoOutputInfo. Mirrors the local NetworkInputDataTypeNameGet(i) / NetworkOutputDataTypeNameGet(i) return value. Wire-compatible (purely additive). Even after (1) lands this is the right escape hatch for vendor-specific or composite types that don’t map cleanly to a single RSIDataType, and it lets you disambiguate cases like DINT vs REAL where bit width alone isn’t enough.
Both will ship together in the next release with hardware regression tests against 0x6077 (INT) and 0x6061 (SINT) so this stays fixed.
Short-term:bit_size is on PdoInputInfo / PdoOutputInfo today and tells you the channel width (8/16/32/64). It’s not a complete substitute. It doesn’t distinguish signed vs unsigned, or int vs float at the same width. But for the specific signed-16 cases you described, your existing approach (whitelist by PDO name, sign-extend client-side) is reasonable until the proper fix ships. We wouldn’t recommend a generic bit_size-based heuristic since it mis-handles UINT Statusword / Controlword (16-bit unsigned) and conflates DINT with REAL at 32 bits.
We’ll follow up here once the next release is out.
Hi, wanted to close the loop with a status update. The fixes we described in our previous response have all been implemented, as well as some further, wire-breaking changes to our gRPC. The following changes will be present in our next release:
Properly Data Types:address_info.data_type now reflects the actual ENI-declared type on both PDOInputInfo and PDOOutputInfo, rather than always reporting RSIDataTypeINT32. Types with no corresponding RSIDataType use a fallback that you can still interpret with the bit-size.
E.g., Your specific case of 0x6077 Torque actual value should now surface as RSIDataTypeINT16 with the value correctly sign-extended, and should no longer need your client-side workaround.
Backup Type String: We also added the suggested data_type_name field to store the raw ENI string for vendor-specific edge cases.
Native RSIDataTypeINT8 / RSIDataTypeUINT8:SINT and USINT/BYTE now map to proper 8-bit enum values rather than widening to 16-bit.
Typed PDO Value (wire-breaking): To make type-handling more convenient, the PdoInputStatus and PdoOutputStatus value fields are now typed FirmwareValue messages instead of raw int64. Note: this is a wire-breaking proto change. It will introduce compiler errors, and any gRPC stubs from our proto will need to be regenerated.
If you hit any issues, please reply here with your ENI type string and PDO object index and we’ll triage quickly. Thanks again for the detailed report.