You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by ld...@apache.org on 2020/10/07 10:01:55 UTC

[plc4x] branch feature/socketcan updated (2ced517 -> 0b699e8)

This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a change to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git.


 discard 2ced517  CANopen adjustments.
 discard 9df8c0f  Fix socketcan mspec.
 discard 6dfd504  More tests of canopen payload.
 discard e47f477  Fix socketcan mspec errors.
 discard 43b5696  Update service list for canopen.
 discard edb6a7d  Sketch of support for SDO operations.
 discard 1076f32  Fix socketcan transport.
 discard a44cc8b  More work on socketcan transport.
 discard ebaeb26  Focus on payloads and not frames.
 discard 0482a7f  Split different flavours of CAN formats.
 discard 907c178  More definitions of various frame formats.
 discard 93a9111  Step back to virtual fields in can transport.
 discard 31289a7  Tests for socketcan frames + manual parsing based on ReadBuffer api.
 discard b06a8e7  Scratch of socketcan transport and can frame definitions.
 discard 2713fbe  PLC4X-248 Permit more locations for MSpec comments.
     add 2d2c176  Cast to PLCValue within data-io-template
     add 5d54f43  Modbus.spec Sample Change
     add 0dad0a0  Add Datatype to ModbusField classes
     add 3239c78  Add sample PLCValue classes based on IEC 61131 datatypes.
     add 18247a4  Tidied up the IEC type classes INT and UINT.
     add 06bc37a  Fixed support for PLCLists for INT and UINT datatypes
     add 2028dcf  Cleaned up, it now supports BOOL, INT, UINT and REAL values.
     add 7432353  Test cases for some Encoding and Modbus Field methods.
     add 926116b  Add support for DINT data types
     add 67081d9  Included cast in data-io-template for value in if statement. This is to avoid needlessly casting it.
     add 1c2e2b6  Added test cases for negative REAL numbers.
     add 147aaab  Added most of the other datatypes and support in Modbus
     add c9d6ffa  Modbus now supports all numeric and string and char datatypes
     add 4e9ec88  Feature/Modbus Datatype - IEC 61131
     add 4e4c155  Change the data-io template to use DataType Instead of List
     add 83957d3  Tidying up.
     add fdb2a29  - Implemented most of the connection part of the S7 driver - Implemented a skeleton for the Modbus driver
     add 6aa844c  - Continued implementing the S7 driver
     add 1adf1be  PLC4X-239 - Read DTL (Date and Time) - Fixed the processing of Date and Time values when reading
     add 1689d43  PLC4X-239 - Read DTL (Date and Time) - Fixed the processing of Date and Time values when reading
     add d015359  - Continued implementing the read and write support
     add c7a058e  - Implemented the S7 address parser code
     add a8e8445  Merge branch 'develop' of https://gitbox.apache.org/repos/asf/plc4x into feature/plc4c
     add 28877a8  - Split up the s7 driver code into multiple files to be better manageable.
     add 8d5ca5a  - Cleanup and documentation.
     add 90edbd9  - Updated the modbus driver to match the structure of the S7 driver.
     add df4d588  - Implemented the skeleton for the modbus driver. - Resolved some naming conflicts.
     add 29615ae  - Fixed issues with the Docker build
     add 65ef1a6  - Fixed issues with the Docker build
     add 487efce  - Made the KNX driver add "area" and "line" to the PlcStructs it produces. - Ensured the connection state timer is stopped if the connection dies.
     add 64057df  PLC4X-248 Permit more locations for MSpec comments.
     add bc60162  - Make the NiFi module forward the exceptions which actually are the cause of a ProcessingException.
     add f2828a5  - Updated the release documentation for the code-generation part ...
     add 2309ba0  - Fixed an issue when reading floats
     add 361bbb4  - Minor housekeeping in the parent pom.
     add 9927030  Merge branch 'develop' of https://gitbox.apache.org/repos/asf/plc4x into feature/plc4c
     add 7991d4a  - Working on the C S7 driver
     add 0fe5340  - Updated to the freshly released build-tools version.
     add 001f8e3  Merge branch 'develop' of https://gitbox.apache.org/repos/asf/plc4x into feature/plc4c
     add 8204eea  - Fixed a bug in the C code generation of complex type arrays - Finished implementing the S7 connection part
     add 7d85b71  - Got the S7 PLC identifiation working - Got the first read-requests working
     add 8d1afb3  - PLC4X-207 - No registered handler found for message TPKTPacket[], , using default decode method - Communication with S7 and Modbus device hangs
     add a536ba9  - Continued working on the S7 C driver
     add 162bee0  - PLC4X-207 - No registered handler found for message TPKTPacket[], , using default decode method - Communication with S7 and Modbus device hangs
     add f8c744f  - Added code to reset id counters to Ads and AbEth protocols
     add d105ce4  Merge branch 'develop' of https://gitbox.apache.org/repos/asf/plc4x into feature/plc4c
     add 24f9505  - Got a first working version of the dataIo generation working in C
     add d762953  - Added code to reset id counters to Ads and AbEth protocols
     add b422f0e  Modbus/ Updated Documentation
     add cf806d1  Update modbus.adoc
     add ce04d55  Update modbus.adoc
     add 4c48776  Update modbus.adoc
     add b26af7a  Update modbus.adoc
     add 659d6b8  Merge pull request #184 from hutcheb/Modbus/UpdateDocumentation
     add 4442cc3  Merge branch 'develop' of https://gitbox.apache.org/repos/asf/plc4x into feature/plc4c
     add 199c784  Merge branch 'develop' of https://github.com/apache/plc4x into Feature/ModbusDataType
     add 4c75216  Modbus Write Extended Register Support
     add 46941a9  Feature/Modbus Write Extended Registers
     add df0adc8  - Continued Ben's great work towards this. - Refactored the existing Java type based PlcValues to a more generic IEC 61131-3 based type system. - Got everything working, all tests to pass etc and did some testing of S7 and Modbus reading.
     add e6312e2  - Undid a mess I created ;-)
     add d108a8f  - A bit of housekeeping.
     add cb80703  - Made the driver catch exceptions and report them better.
     add 898cd93  - A bit of housekeeping.
     add 3ef9006  Modbus Data Type Documentation
     add 24279ce  Updated based on issues fixed with CHAR and WCHAR.
     add 2f4d770  Merge pull request #188 from hutcheb/modbus_documentation
     add 62547f6  - Added a getInt() method that just relays to getInteger() to avoid problems with generated code (Hack for now) - Fixed a bug in the KNX driver's write support (Protocol Logig as well as the FieldHandler.
     add c99cf7b  - Added a JsonIgnore to the new getInt() method to prevent errors in the Integration Tests
     add ea1d8bb  Refactor Field Handler Classes
     add 28ec2bf  Fixed issue in new PlcValues.of function. Is able to correctly pass standard data types now.
     add e6df50e  Draft for writeFloat in WriteBUffer
     add 6db621a  Add support for writing floating point.
     add 3ca264c  Add support for Big Interger write (untested)
     add b78b299  replace Modbus fromPLCValue function with staticSerialise functions. (Needs to be fixed to include changes from Data Type PR)
     add ccdf77d  Merge branch 'develop' into Bug/AddWriteBufferSupportFloatBigInt
     add 0b7d25c  Moved Modbus over to use the static Serializer. I'll do some more testing tomorrow, but seems to work with Big Ints and Floats
     add 28a322b  Fixed support for ULINT writing
     add 4fdf673  Refactored the BigInteger functions
     add 77267cd  Merge branch 'Bug/AddWriteBufferSupportFloatBigInt' into RefactorFieldHandler
     add 27df4a6  Add support for writing arrays to the hello world write example.
     add dd0aab6  Merge branch 'Feature/Hello-World-Write-Arrays' into RefactorFieldHandler
     add 45d96cf  Implemented staticSerialize write list functions
     add cbe9243  Merge branch 'Bug/AddWriteBufferSupportFloatBigInt' into RefactorFieldHandler
     add e1c7701  Overrode methods on PlcValue classes and fixed list serializer
     add 95dcf27  Add Support for writing lists of booleans
     add 90fc914  Modified non Modbus field handler classes to modbus format Wasn't able to test other protocols.
     new b60bba2  - Updated my company
     new c825f97  - removed the toPlcValue method from the Message interface (It was actually only used in one place of the experimental BACnetIp driver)
     new fe7b9c1  Scratch of socketcan transport and can frame definitions.
     new 78fe2ee  Tests for socketcan frames + manual parsing based on ReadBuffer api.
     new 03ad153  Step back to virtual fields in can transport.
     new b304744  More definitions of various frame formats.
     new 4c3b4c1  Split different flavours of CAN formats.
     new d60b64a  Focus on payloads and not frames.
     new 846e03c  More work on socketcan transport.
     new ccdeb58  Fix socketcan transport.
     new 5196344  Sketch of support for SDO operations.
     new ea5b953  Update service list for canopen.
     new c7c28fd  Fix socketcan mspec errors.
     new 71301c9  More tests of canopen payload.
     new 8cb18bf  Fix socketcan mspec.
     new 695c0b6  CANopen adjustments.
     new 5d1e10c  Test of wireshark frames.
     new 93d5d70  CANopen milestone - support for segmentet SDO upload (read) requests.
     new 0b699e8  CANopen microstone - PDO & subscriptions.

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (2ced517)
            \
             N -- N -- N   refs/heads/feature/socketcan (0b699e8)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 19 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 RELEASE_NOTES                                      |  26 +-
 .../BaseFreemarkerLanguageTemplateHelper.java      |   4 +-
 .../apache/plc4x/language/c/CLanguageOutput.java   |   4 +-
 .../plc4x/language/c/CLanguageTemplateHelper.java  | 136 ++--
 .../resources/templates/c/data-io-template-c.ftlh  | 245 +++++++
 ...num-template-h.ftlh => data-io-template-h.ftlh} |  47 +-
 .../resources/templates/c/enum-template-c.ftlh     |  36 +-
 .../resources/templates/c/enum-template-h.ftlh     |   5 +
 .../resources/templates/c/pojo-template-c.ftlh     |  66 +-
 .../resources/templates/c/pojo-template-h.ftlh     |   4 +-
 .../language/java/JavaLanguageTemplateHelper.java  |  16 +-
 .../resources/templates/java/data-io-template.ftlh |  50 +-
 .../resources/templates/java/pojo-template.ftlh    |  93 ---
 .../definitions/DefaultDataIoTypeDefinition.java   |   2 -
 .../org/apache/plc4x/java/api/value/PlcBOOL.java   | 300 +++++++++
 .../org/apache/plc4x/java/api/value/PlcBYTE.java   | 310 +++++++++
 .../apache/plc4x/java/api/value/PlcBoolean.java    | 168 -----
 .../org/apache/plc4x/java/api/value/PlcByte.java   | 168 -----
 .../org/apache/plc4x/java/api/value/PlcCHAR.java   | 332 +++++++++
 .../org/apache/plc4x/java/api/value/PlcDINT.java   | 283 ++++++++
 .../org/apache/plc4x/java/api/value/PlcDWORD.java  | 313 +++++++++
 .../apache/plc4x/java/api/value/PlcIECValue.java   |  77 +++
 .../org/apache/plc4x/java/api/value/PlcINT.java    | 285 ++++++++
 .../apache/plc4x/java/api/value/PlcInteger.java    | 168 -----
 .../org/apache/plc4x/java/api/value/PlcLINT.java   | 281 ++++++++
 .../api/value/{PlcDouble.java => PlcLREAL.java}    | 110 ++-
 .../org/apache/plc4x/java/api/value/PlcLWORD.java  | 326 +++++++++
 .../org/apache/plc4x/java/api/value/PlcLong.java   | 168 -----
 .../org/apache/plc4x/java/api/value/PlcNull.java   |   5 +
 .../java/api/value/{PlcFloat.java => PlcREAL.java} | 109 ++-
 .../org/apache/plc4x/java/api/value/PlcSINT.java   | 290 ++++++++
 .../org/apache/plc4x/java/api/value/PlcShort.java  | 168 -----
 .../org/apache/plc4x/java/api/value/PlcUDINT.java  | 314 +++++++++
 .../org/apache/plc4x/java/api/value/PlcUINT.java   | 295 ++++++++
 .../org/apache/plc4x/java/api/value/PlcULINT.java  | 326 +++++++++
 .../org/apache/plc4x/java/api/value/PlcUSINT.java  | 310 +++++++++
 .../org/apache/plc4x/java/api/value/PlcValue.java  |   2 +
 .../plc4x/java/api/value/PlcValueAdapter.java      |  10 +
 .../org/apache/plc4x/java/api/value/PlcValues.java |  83 ++-
 .../org/apache/plc4x/java/api/value/PlcWCHAR.java  | 313 +++++++++
 .../org/apache/plc4x/java/api/value/PlcWORD.java   | 295 ++++++++
 .../java/abeth/protocol/AbEthProtocolLogic.java    |  13 +-
 .../java/abeth/protocol/Plc4xAbEthProtocol.java    |   4 +-
 .../plc4x/java/ads/field/AdsFieldHandler.java      | 740 ++++++++++-----------
 .../plc4x/java/ads/protocol/AdsProtocolLogic.java  |  52 +-
 .../attic/protocol/util/LittleEndianDecoder.java   |  62 +-
 .../src/test/resources/testsuite/AdsDriverIT.xml   |  12 +-
 .../java/eip/readwrite/field/EipFieldHandler.java  | 244 +------
 .../eip/readwrite/protocol/EipProtocolLogic.java   |  22 +-
 .../resources/testsuite/EIPDriverTestsuite.xml     |   2 +-
 .../readwrite/field/FirmataFieldHandler.java       |  95 +--
 .../readwrite/protocol/FirmataProtocolLogic.java   |  11 +-
 .../plc4x/java/knxnetip/ets5/Ets5Parser.java       |  21 +-
 .../plc4x/java/knxnetip/ets5/model/Ets5Model.java  |   8 +-
 .../java/knxnetip/field/KnxNetIpFieldHandler.java  |  67 +-
 .../knxnetip/protocol/KnxNetIpProtocolLogic.java   |  47 +-
 .../plc4x/java/knxnetip/utils/KnxHelper.java       |  11 +-
 .../java/modbus/field/ModbusExtendedRegister.java  |  22 +-
 .../plc4x/java/modbus/field/ModbusField.java       |  32 +-
 .../plc4x/java/modbus/field/ModbusFieldCoil.java   |  22 +-
 .../modbus/field/ModbusFieldDiscreteInput.java     |  22 +-
 .../java/modbus/field/ModbusFieldHandler.java      | 102 +--
 .../modbus/field/ModbusFieldHoldingRegister.java   |  22 +-
 .../modbus/field/ModbusFieldInputRegister.java     |  22 +-
 .../java/modbus/protocol/ModbusProtocolLogic.java  | 148 +++--
 .../apache/plc4x/java/modbus/ModbusEncodeTest.java | 187 ++++++
 .../plc4x/java/modbus/ModbusFieldDataTypeTest.java |  98 +++
 .../apache/plc4x/java/modbus/ModbusFieldTest.java  |  71 ++
 .../test/resources/testsuite/ModbusTestsuite.xml   |  57 ++
 .../opcua/connection/OpcuaTcpPlcConnection.java    |  26 +-
 .../java/opcua/protocol/OpcuaPlcFieldHandler.java  |  82 +--
 .../plc4x/java/s7/readwrite/field/S7Field.java     |  40 +-
 .../java/s7/readwrite/field/S7PlcFieldHandler.java | 376 +----------
 .../s7/readwrite/protocol/S7ProtocolLogic.java     |  24 +-
 .../s7/src/test/resources/testsuite/S7DriverIT.xml |   2 +-
 .../simulated/field/SimulatedFieldHandler.java     |  14 +-
 .../simulated/connection/SimulatedDeviceTest.java  |   4 +-
 .../watertank/service/WaterTankService.java        |   4 +-
 .../examples/helloplc4x/write/HelloPlc4xWrite.java |   8 +-
 .../plc4x/edgent/PlcConnectionAdapterTest.java     |   1 -
 .../org/apache/plc4x/nifi/Plc4xSinkProcessor.java  |   2 +-
 .../apache/plc4x/nifi/Plc4xSourceProcessor.java    |   2 +-
 .../apache/plc4x/java/spi/generation/Message.java  |   4 -
 .../plc4x/java/spi/generation/ReadBuffer.java      |  32 +-
 .../plc4x/java/spi/generation/WriteBuffer.java     |  65 +-
 .../java/spi/messages/DefaultPlcReadResponse.java  |   2 +-
 .../connectionpool/PooledPlcDriverManager.java     |   2 +-
 .../java/opm/PlcEntityManagerComplexTest.java      |   4 +-
 .../org/apache/plc4x/java/scraper/ScraperTest.java |   6 +-
 .../triggeredscraper/TriggeredScraperImplTest.java |  16 +-
 pom.xml                                            |  22 +-
 .../ads/src/main/resources/protocols/ads/ads.mspec |  60 +-
 .../src/main/resources/protocols/can/canopen.mspec | 281 ++++++--
 .../resources/protocols/knxnetip/knxnetip.mspec    |  28 +-
 .../main/resources/protocols/modbus/modbus.mspec   | 139 +++-
 .../s7/src/main/resources/protocols/s7/s7.mspec    |  30 +-
 .../java/examples/helloinflux/HelloInflux.java     |  22 +-
 sandbox/plc4c/api/include/plc4c/connection.h       |  10 +-
 sandbox/plc4c/api/include/plc4c/data.h             |  35 +-
 sandbox/plc4c/api/include/plc4c/read.h             |   1 +
 sandbox/plc4c/api/include/plc4c/types.h            |   7 +
 sandbox/plc4c/drivers/modbus/CMakeLists.txt        |  17 +-
 .../drivers/modbus/include/plc4c/driver_modbus.h   |   6 +-
 .../include/plc4c/driver_modbus_packets.h}         |  21 +-
 .../include/plc4c/driver_modbus_sm.h}              |  23 +-
 .../include/plc4c/driver_s7_encode_decode.h}       |  12 +-
 sandbox/plc4c/drivers/modbus/src/driver_modbus.c   |  16 +-
 .../modbus/src/driver_modbus_encode_decode.c       | 110 +++
 .../drivers/modbus/src/driver_modbus_packets.c     | 142 ++++
 .../drivers/modbus/src/driver_modbus_sm_connect.c  |  51 ++
 .../modbus/src/driver_modbus_sm_disconnect.c       |  74 +++
 .../drivers/modbus/src/driver_modbus_sm_read.c     | 119 ++++
 .../drivers/modbus/src/driver_modbus_sm_write.c    | 121 ++++
 sandbox/plc4c/drivers/s7/CMakeLists.txt            |  11 +-
 sandbox/plc4c/drivers/s7/include/plc4c/driver_s7.h |  59 ++
 .../include/plc4c/driver_s7_encode_decode.h}       |  23 +-
 .../drivers/s7/include/plc4c/driver_s7_packets.h   |  53 ++
 .../include/plc4c/driver_s7_sm.h}                  |  23 +-
 sandbox/plc4c/drivers/s7/src/driver_s7.c           |  90 ++-
 .../plc4c/drivers/s7/src/driver_s7_encode_decode.c | 346 ++++++++++
 sandbox/plc4c/drivers/s7/src/driver_s7_packets.c   | 524 +++++++++++++++
 .../plc4c/drivers/s7/src/driver_s7_sm_connect.c    | 348 ++++++++++
 .../plc4c/drivers/s7/src/driver_s7_sm_disconnect.c |  81 +++
 sandbox/plc4c/drivers/s7/src/driver_s7_sm_read.c   | 207 ++++++
 sandbox/plc4c/drivers/s7/src/driver_s7_sm_write.c  | 122 ++++
 .../plc4c/drivers/s7/test/s7_address_parser_test.c | 110 +++
 sandbox/plc4c/drivers/s7/test/s7_test.c            |   7 +-
 .../simulated/include/plc4c/driver_simulated.h     |   6 +-
 .../plc4c/drivers/simulated/src/driver_simulated.c |  15 +-
 sandbox/plc4c/examples/hello-world/CMakeLists.txt  |  11 +-
 .../plc4c/examples/hello-world/src/hello_world.c   |  59 +-
 .../device_group.h => modbus/include/data_item.h}  |  26 +-
 .../{includes => include}/modbus_constants.h       |   4 +-
 .../modbus/{includes => include}/modbus_pdu.h      |   4 +-
 .../modbus_pdu_read_file_record_request_item.h     |   4 +-
 .../modbus_pdu_read_file_record_response_item.h    |   4 +-
 .../modbus_pdu_write_file_record_request_item.h    |   4 +-
 .../modbus_pdu_write_file_record_response_item.h   |   4 +-
 .../{includes => include}/modbus_serial_adu.h      |   4 +-
 .../modbus/{includes => include}/modbus_tcp_adu.h  |   4 +-
 .../plc4c/generated-sources/modbus/src/data_item.c | 336 ++++++++++
 .../modbus/src/modbus_constants.c                  |  10 +-
 .../generated-sources/modbus/src/modbus_pdu.c      | 341 +++++-----
 .../src/modbus_pdu_read_file_record_request_item.c |  22 +-
 .../modbus_pdu_read_file_record_response_item.c    |  22 +-
 .../modbus_pdu_write_file_record_request_item.c    |  36 +-
 .../modbus_pdu_write_file_record_response_item.c   |  38 +-
 .../modbus/src/modbus_serial_adu.c                 |  26 +-
 .../generated-sources/modbus/src/modbus_tcp_adu.c  |  26 +-
 .../s7/{includes => include}/cotp_packet.h         |   4 +-
 .../s7/{includes => include}/cotp_parameter.h      |   4 +-
 .../s7/{includes => include}/cotp_protocol_class.h |   5 +
 .../s7/{includes => include}/cotp_tpdu_size.h      |   5 +
 .../device_group.h => include/data_item.h}         |  26 +-
 .../data_transport_error_code.h                    |   5 +
 .../s7/{includes => include}/data_transport_size.h |   5 +
 .../s7/{includes => include}/device_group.h        |   5 +
 .../s7/{includes => include}/memory_area.h         |   5 +
 .../s7/{includes => include}/s7_address.h          |   4 +-
 .../s7/{includes => include}/s7_message.h          |   4 +-
 .../s7/{includes => include}/s7_parameter.h        |   4 +-
 .../s7_parameter_user_data_item.h                  |   4 +-
 .../s7/{includes => include}/s7_payload.h          |   4 +-
 .../s7_payload_user_data_item.h                    |   4 +-
 .../s7_var_payload_data_item.h                     |   4 +-
 .../s7_var_payload_status_item.h                   |   4 +-
 .../s7_var_request_parameter_item.h                |   4 +-
 .../s7/{includes => include}/szl_data_tree_item.h  |   4 +-
 .../s7/{includes => include}/szl_id.h              |   4 +-
 .../{includes => include}/szl_module_type_class.h  |   5 +
 .../s7/{includes => include}/szl_sublist.h         |   5 +
 .../s7/{includes => include}/tpkt_packet.h         |   4 +-
 .../s7/{includes => include}/transport_size.h      |   5 +
 .../plc4c/generated-sources/s7/src/cotp_packet.c   |  94 +--
 .../generated-sources/s7/src/cotp_parameter.c      |  35 +-
 .../generated-sources/s7/src/cotp_protocol_class.c |  46 ++
 .../generated-sources/s7/src/cotp_tpdu_size.c      |  58 ++
 sandbox/plc4c/generated-sources/s7/src/data_item.c | 256 +++++++
 .../s7/src/data_transport_error_code.c             |  52 ++
 .../generated-sources/s7/src/data_transport_size.c |  58 ++
 .../plc4c/generated-sources/s7/src/device_group.c  |  34 +
 .../plc4c/generated-sources/s7/src/memory_area.c   |  70 ++
 .../plc4c/generated-sources/s7/src/s7_address.c    |  38 +-
 .../plc4c/generated-sources/s7/src/s7_message.c    |  54 +-
 .../plc4c/generated-sources/s7/src/s7_parameter.c  |  64 +-
 .../s7/src/s7_parameter_user_data_item.c           |  46 +-
 .../plc4c/generated-sources/s7/src/s7_payload.c    |  30 +-
 .../s7/src/s7_payload_user_data_item.c             |  40 +-
 .../s7/src/s7_var_payload_data_item.c              |  29 +-
 .../s7/src/s7_var_payload_status_item.c            |  10 +-
 .../s7/src/s7_var_request_parameter_item.c         |  18 +-
 .../generated-sources/s7/src/szl_data_tree_item.c  |  27 +-
 sandbox/plc4c/generated-sources/s7/src/szl_id.c    |  18 +-
 .../s7/src/szl_module_type_class.c                 |  40 ++
 .../plc4c/generated-sources/s7/src/szl_sublist.c   | 130 ++++
 .../plc4c/generated-sources/s7/src/tpkt_packet.c   |  22 +-
 .../generated-sources/s7/src/transport_size.c      | 112 ++++
 sandbox/plc4c/spi/include/plc4c/spi/read_buffer.h  |   7 +
 .../plc4c/spi/include/plc4c/spi/types_private.h    |  72 +-
 sandbox/plc4c/spi/src/connection.c                 |   5 +
 sandbox/plc4c/spi/src/data.c                       |  95 ++-
 sandbox/plc4c/spi/src/evaluation_helper.c          |   4 +
 sandbox/plc4c/spi/src/read.c                       |  24 +-
 sandbox/plc4c/spi/src/system.c                     |  41 +-
 sandbox/plc4c/spi/src/utils/list.c                 |   3 +-
 sandbox/plc4c/spi/src/write.c                      |   9 +-
 .../plc4c/transports/dummy/src/transport_dummy.c   |   5 +
 sandbox/plc4c/transports/serial/CMakeLists.txt     |   4 +-
 .../plc4c/transports/serial/src/transport_serial.c |  24 +
 sandbox/plc4c/transports/tcp/CMakeLists.txt        |   4 +-
 .../transports/tcp/include/plc4c/transport_tcp.h   |   8 +
 sandbox/plc4c/transports/tcp/src/transport_tcp.c   | 124 ++++
 .../configuration/BacNetIpConfiguration.java       |   5 +-
 .../plc4x/java/bacnetip/ede/model/Datapoint.java   |  20 +-
 .../bacnetip/protocol/BacNetIpProtocolLogic.java   |  23 +-
 .../apache/plc4x/java/can/CANOpenPlcDriver.java    |  29 +-
 .../org/apache/plc4x/java/can/api/CANFrame.java    |  11 +
 .../apache/plc4x/java/can/api/CANOpenFrame.java    |  66 ++
 .../api/conversation/canopen/CANConversation.java  |  18 +
 .../api/conversation/canopen/CANFrameBuilder.java  |  11 +
 .../conversation/canopen/CANOpenConversation.java  |  75 +++
 .../canopen/CANOpenConversationBase.java           |  15 +
 .../api/conversation/canopen/SDOConversation.java  |  43 ++
 .../canopen/SDODownloadConversation.java           |  97 +++
 .../canopen/SDOUploadConversation.java             |  98 +++
 .../api/segmentation/PlcSegmentationException.java |  21 +
 .../java/can/api/segmentation/Segmentation.java    | 131 ++++
 .../api/segmentation/accumulator/ByteStorage.java  |  59 ++
 .../can/api/segmentation/accumulator/Storage.java} |  40 +-
 .../java/can/configuration/CANConfiguration.java   |   4 +-
 .../java/can/context/CANOpenDriverContext.java     |   9 +
 .../apache/plc4x/java/can/field/CANOpenField.java  |  53 ++
 .../plc4x/java/can/field/CANOpenFieldHandler.java  |  72 ++
 .../plc4x/java/can/field/CANOpenNMTField.java      |  58 ++
 .../plc4x/java/can/field/CANOpenPDOField.java      |  64 ++
 .../plc4x/java/can/field/CANOpenSDOField.java      |  89 +++
 .../plc4x/java/can/helper/CANOpenHelper.java       |  27 +-
 .../apache/plc4x/java/can/helper/HeaderParser.java |  13 +-
 .../apache/plc4x/java/can/listener/Callback.java   |   8 +
 .../plc4x/java/can/listener/CompositeCallback.java |  25 +
 .../java/can/protocol/CANOpenProtocolLogic.java    | 286 +++++++-
 .../can/protocol/CANOpenSubscriptionHandle.java    |  28 +
 .../protocol/segmentation/CANOpenSegmentation.java |  86 +++
 .../java/can/socketcan/SocketCANConversation.java  |  49 ++
 .../java/can/socketcan/SocketCANDelegateFrame.java |  43 ++
 .../java/can/socketcan/SocketCANFrameBuilder.java  |  29 +
 .../plc4x/java/can/CANOpenWiresharkTest.java}      |  17 +-
 .../test/java/org/apache/plc4x/java/can/Main.java  |  48 ++
 .../{Main.java => field/CANOpenFieldSDOTest.java}  |  24 +-
 .../plc4x/java/can/field/CANOpenNMTFieldTest.java} |  39 +-
 .../testsuite/CANOpenPayloadTestSuite.xml          | 130 ++--
 .../testsuite/CANOpenWiresharkTestSuite.xml        | 278 ++++++++
 .../plc4x/java/df1/protocol/Plc4XDf1Protocol.java  |   6 +-
 .../asciidoc/developers/release/build-tools.adoc   |  36 +-
 src/site/asciidoc/developers/team.adoc             |   2 +-
 src/site/asciidoc/users/preparing-issues.adoc      |  19 +
 src/site/asciidoc/users/protocols/modbus.adoc      | 145 +++-
 257 files changed, 14545 insertions(+), 3673 deletions(-)
 create mode 100644 build-utils/language-c/src/main/resources/templates/c/data-io-template-c.ftlh
 copy build-utils/language-c/src/main/resources/templates/c/{enum-template-h.ftlh => data-io-template-h.ftlh} (50%)
 create mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcBOOL.java
 create mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcBYTE.java
 delete mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcBoolean.java
 delete mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcByte.java
 create mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcCHAR.java
 create mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcDINT.java
 create mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcDWORD.java
 create mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcIECValue.java
 create mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcINT.java
 delete mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcInteger.java
 create mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcLINT.java
 rename plc4j/api/src/main/java/org/apache/plc4x/java/api/value/{PlcDouble.java => PlcLREAL.java} (51%)
 create mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcLWORD.java
 delete mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcLong.java
 rename plc4j/api/src/main/java/org/apache/plc4x/java/api/value/{PlcFloat.java => PlcREAL.java} (50%)
 create mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcSINT.java
 delete mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcShort.java
 create mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcUDINT.java
 create mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcUINT.java
 create mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcULINT.java
 create mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcUSINT.java
 create mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcWCHAR.java
 create mode 100644 plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcWORD.java
 create mode 100644 plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusEncodeTest.java
 create mode 100644 plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusFieldDataTypeTest.java
 create mode 100644 plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/ModbusFieldTest.java
 copy sandbox/plc4c/drivers/{simulated/include/plc4c/driver_simulated.h => modbus/include/plc4c/driver_modbus_packets.h} (53%)
 copy sandbox/plc4c/drivers/{simulated/include/plc4c/driver_simulated.h => modbus/include/plc4c/driver_modbus_sm.h} (52%)
 copy sandbox/plc4c/drivers/{simulated/include/plc4c/driver_simulated.h => modbus/include/plc4c/driver_s7_encode_decode.h} (75%)
 create mode 100644 sandbox/plc4c/drivers/modbus/src/driver_modbus_encode_decode.c
 create mode 100644 sandbox/plc4c/drivers/modbus/src/driver_modbus_packets.c
 create mode 100644 sandbox/plc4c/drivers/modbus/src/driver_modbus_sm_connect.c
 create mode 100644 sandbox/plc4c/drivers/modbus/src/driver_modbus_sm_disconnect.c
 create mode 100644 sandbox/plc4c/drivers/modbus/src/driver_modbus_sm_read.c
 create mode 100644 sandbox/plc4c/drivers/modbus/src/driver_modbus_sm_write.c
 copy sandbox/plc4c/drivers/{modbus/include/plc4c/driver_modbus.h => s7/include/plc4c/driver_s7_encode_decode.h} (56%)
 create mode 100644 sandbox/plc4c/drivers/s7/include/plc4c/driver_s7_packets.h
 copy sandbox/plc4c/drivers/{simulated/include/plc4c/driver_simulated.h => s7/include/plc4c/driver_s7_sm.h} (53%)
 create mode 100644 sandbox/plc4c/drivers/s7/src/driver_s7_encode_decode.c
 create mode 100644 sandbox/plc4c/drivers/s7/src/driver_s7_packets.c
 create mode 100644 sandbox/plc4c/drivers/s7/src/driver_s7_sm_connect.c
 create mode 100644 sandbox/plc4c/drivers/s7/src/driver_s7_sm_disconnect.c
 create mode 100644 sandbox/plc4c/drivers/s7/src/driver_s7_sm_read.c
 create mode 100644 sandbox/plc4c/drivers/s7/src/driver_s7_sm_write.c
 create mode 100644 sandbox/plc4c/drivers/s7/test/s7_address_parser_test.c
 copy sandbox/plc4c/generated-sources/{s7/includes/device_group.h => modbus/include/data_item.h} (54%)
 rename sandbox/plc4c/generated-sources/modbus/{includes => include}/modbus_constants.h (92%)
 rename sandbox/plc4c/generated-sources/modbus/{includes => include}/modbus_pdu.h (98%)
 rename sandbox/plc4c/generated-sources/modbus/{includes => include}/modbus_pdu_read_file_record_request_item.h (89%)
 rename sandbox/plc4c/generated-sources/modbus/{includes => include}/modbus_pdu_read_file_record_response_item.h (89%)
 rename sandbox/plc4c/generated-sources/modbus/{includes => include}/modbus_pdu_write_file_record_request_item.h (89%)
 rename sandbox/plc4c/generated-sources/modbus/{includes => include}/modbus_pdu_write_file_record_response_item.h (89%)
 rename sandbox/plc4c/generated-sources/modbus/{includes => include}/modbus_serial_adu.h (91%)
 rename sandbox/plc4c/generated-sources/modbus/{includes => include}/modbus_tcp_adu.h (92%)
 create mode 100644 sandbox/plc4c/generated-sources/modbus/src/data_item.c
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/cotp_packet.h (96%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/cotp_parameter.h (95%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/cotp_protocol_class.h (85%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/cotp_tpdu_size.h (87%)
 copy sandbox/plc4c/generated-sources/s7/{includes/device_group.h => include/data_item.h} (55%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/data_transport_error_code.h (85%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/data_transport_size.h (86%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/device_group.h (85%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/memory_area.h (88%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/s7_address.h (95%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/s7_message.h (96%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/s7_parameter.h (96%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/s7_parameter_user_data_item.h (94%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/s7_payload.h (94%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/s7_payload_user_data_item.h (94%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/s7_var_payload_data_item.h (90%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/s7_var_payload_status_item.h (91%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/s7_var_request_parameter_item.h (94%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/szl_data_tree_item.h (92%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/szl_id.h (94%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/szl_module_type_class.h (84%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/szl_sublist.h (91%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/tpkt_packet.h (93%)
 rename sandbox/plc4c/generated-sources/s7/{includes => include}/transport_size.h (93%)
 create mode 100644 sandbox/plc4c/generated-sources/s7/src/data_item.c
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/CANFrame.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/CANOpenFrame.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANConversation.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANFrameBuilder.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANOpenConversation.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANOpenConversationBase.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDOConversation.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDODownloadConversation.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDOUploadConversation.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/PlcSegmentationException.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/Segmentation.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/accumulator/ByteStorage.java
 copy sandbox/test-java-can-driver/src/{test/java/org/apache/plc4x/java/can/Main.java => main/java/org/apache/plc4x/java/can/api/segmentation/accumulator/Storage.java} (57%)
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/context/CANOpenDriverContext.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenField.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenFieldHandler.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenNMTField.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenPDOField.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenSDOField.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/listener/Callback.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/listener/CompositeCallback.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenSubscriptionHandle.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/segmentation/CANOpenSegmentation.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/socketcan/SocketCANConversation.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/socketcan/SocketCANDelegateFrame.java
 create mode 100644 sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/socketcan/SocketCANFrameBuilder.java
 copy sandbox/{plc4c/transports/tcp/src/transport_tcp.c => test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenWiresharkTest.java} (73%)
 copy sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/{Main.java => field/CANOpenFieldSDOTest.java} (56%)
 copy sandbox/test-java-can-driver/src/{main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java => test/java/org/apache/plc4x/java/can/field/CANOpenNMTFieldTest.java} (50%)
 create mode 100644 sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenWiresharkTestSuite.xml
 create mode 100644 src/site/asciidoc/users/preparing-issues.adoc


[plc4x] 12/19: Update service list for canopen.

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit ea5b953c5ebdf12fc34fae0daa71c6e2cacb6fb9
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Tue Sep 1 11:42:00 2020 +0200

    Update service list for canopen.
---
 .../can/src/main/resources/protocols/can/canopen.mspec     |  9 +++++++++
 .../plc4x/java/can/protocol/CANOpenProtocolLogic.java      |  4 ++++
 .../test/resources/testsuite/CANOpenPayloadTestSuite.xml   | 14 ++++++++++++++
 3 files changed, 27 insertions(+)

diff --git a/protocols/can/src/main/resources/protocols/can/canopen.mspec b/protocols/can/src/main/resources/protocols/can/canopen.mspec
index d5160c6..0c4f175 100644
--- a/protocols/can/src/main/resources/protocols/can/canopen.mspec
+++ b/protocols/can/src/main/resources/protocols/can/canopen.mspec
@@ -19,9 +19,18 @@
 
 [enum uint 4 'CANOpenService'
     ['0b0000' BROADCAST   ]
+    ['0b0001' SYNC        ]
     ['0b1110' NMT         ]
     ['0b1100' SDO_REQUEST ]
     ['0b1011' SDO_RESPONSE]
+    ['0b0011' TPDO_1]
+    ['0b0100' RPDO_1]
+    ['0b0101' TPDO_2]
+    ['0b0110' RPDO_2]
+    ['0b0111' TPDO_3]
+    ['0b1000' RPDO_3]
+    ['0b1001' TPDO_4]
+    ['0b1010' RPDO_4]
 ]
 
 [enum uint 8 'NMTStateRequest'
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
index 9cc2fdb..0090e0e 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
@@ -114,4 +114,8 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
             (service.getValue() << 16 ) & 0x00ff0000;
     }
 
+    private CANOpenService serviceId(int nodeId) {
+        // form 32 bit socketcan identifier
+        return CANOpenService.valueOf((byte) (nodeId >> 7));
+    }
 }
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
index d7c1a33..ecf224b 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
@@ -50,6 +50,20 @@
   </testcase>
 
   <testcase>
+    <name>Network heartbeat, payload: 05</name>
+    <raw>05</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>NMT</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+        <state>OPERATIONAL</state>
+      </CANOpenNetworkPayload>
+    </xml>
+  </testcase>
+
+  <testcase>
     <name>SDO request, payload: 4317100000000000</name>
     <raw>4317100000000000</raw>
     <root-type>CANOpenPayload</root-type>


[plc4x] 08/19: Focus on payloads and not frames.

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit d60b64a21a0ca88d1b9b024634b4bd1216fde549
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Fri Aug 28 00:14:16 2020 +0200

    Focus on payloads and not frames.
---
 .../src/main/resources/protocols/can/canopen.mspec |  41 +++++----
 .../apache/plc4x/java/can/CANOpenPlcDriver.java    | 102 +++++++++++++++++++++
 .../java/can/protocol/CANOpenProtocolLogic.java    |  62 +++++++++++++
 .../{CANOpenTest.java => CANOpenPayloadTest.java}  |   6 +-
 ...enTestSuite.xml => CANOpenPayloadTestSuite.xml} |  11 ++-
 5 files changed, 198 insertions(+), 24 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/canopen.mspec b/protocols/can/src/main/resources/protocols/can/canopen.mspec
index 553d12a..54337b4 100644
--- a/protocols/can/src/main/resources/protocols/can/canopen.mspec
+++ b/protocols/can/src/main/resources/protocols/can/canopen.mspec
@@ -17,28 +17,35 @@
  * under the License.
  */
 
-[type 'CANOpenFrame'
-    [enum CANOpenService 'function']
-    [simple int 11 'identifier']
-    [reserved int 9 '0x0'] // filling gap used by extended frame, and extended marker which should always be 0
-    [simple bit 'remote']
-    [simple bit 'error']
-    [reserved int 5 '0x0']  // filling gap used by extended frame
-    [implicit uint 8 'size' 'COUNT(payload)']
-    [reserved uint 8 '0x0'] // in case of fd frame these are flags
-    [reserved uint 8 '0x0'] // padding 1
-    [reserved uint 8 '0x0'] // padding 2
-    [simple CANOpenPayload 'payload' ['function', 'size']]
+[enum uint 4 'CANOpenService'
+    ['0x00' BROADCAST]
+    ['0x07' NMT]
 ]
 
-[enum uint 4 'CANOpenService'
-    ['0b1110' NMT]
+[enum uint 8 'NMTStateRequest'
+    ['0x01' OPERATIONAL]
+    ['0x02' STOP]
+    ['0x80' PRE_OPERATIONAL]
+    ['0x81' RESET_NODE]
+    ['0x82' RESET_COMMUNICATION]
 ]
 
-[discriminatedType 'CANOpenPayload' [CANOpenService 'function', uint 8 'size']
+[enum uint 8 'NMTState'
+    ['0x00' BOOTED_UP]
+    ['0x04' STOPPED]
+    ['0x05' OPERATIONAL]
+    ['0x7f' PRE_OPERATIONAL]
+]
+
+[discriminatedType 'CANOpenPayload' [CANOpenService 'function']
     [typeSwitch 'function'
-        ['CANOpenService.NMT' CANOpenNetworkPayload [uint 8 'size']
-            [array int 8 'data' COUNT 'size']
+        ['CANOpenService.BROADCAST' CANOpenBroadcastPayload
+            [enum NMTStateRequest 'request']
+            [reserved uint 1 '0x0']
+            [simple uint 7 'node']
+        ]
+        ['CANOpenService.NMT' CANOpenNetworkPayload
+            [enum NMTState 'state']
         ]
     ]
 ]
\ No newline at end of file
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
new file mode 100644
index 0000000..b1c6fe6
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
@@ -0,0 +1,102 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+package org.apache.plc4x.java.can;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import org.apache.plc4x.java.can.configuration.CANConfiguration;
+import org.apache.plc4x.java.can.context.CANDriverContext;
+import org.apache.plc4x.java.can.field.CANFieldHandler;
+import org.apache.plc4x.java.can.protocol.CANOpenProtocolLogic;
+import org.apache.plc4x.java.can.protocol.CANProtocolLogic;
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.socketcan.readwrite.io.SocketCANFrameIO;
+import org.apache.plc4x.java.spi.configuration.Configuration;
+import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
+import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
+import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer;
+import tel.schich.javacan.CanFrame;
+
+import java.util.function.Consumer;
+import java.util.function.ToIntFunction;
+
+/**
+ */
+public class CANOpenPlcDriver extends GeneratedDriverBase<SocketCANFrame> {
+
+    @Override
+    public String getProtocolCode() {
+        return "can";
+    }
+
+    @Override
+    public String getProtocolName() {
+        return "Controller Area Network";
+    }
+
+    @Override
+    protected Class<? extends Configuration> getConfigurationType() {
+        return CANConfiguration.class;
+    }
+
+    @Override
+    protected String getDefaultTransport() {
+        return "javacan";
+    }
+
+    @Override
+    protected CANFieldHandler getFieldHandler() {
+        return new CANFieldHandler();
+    }
+
+    @Override
+    protected ProtocolStackConfigurer<SocketCANFrame> getStackConfigurer() {
+        return SingleProtocolStackConfigurer.builder(SocketCANFrame.class, SocketCANFrameIO.class)
+            .withProtocol(CANOpenProtocolLogic.class)
+            .withDriverContext(CANDriverContext.class)
+            .withPacketSizeEstimator(CANEstimator.class)
+            .build();
+    }
+
+    public static class CANEstimator implements ToIntFunction<ByteBuf> {
+        @Override
+        public int applyAsInt(ByteBuf byteBuf) {
+            if (byteBuf.readableBytes() >= 5) {
+
+                System.out.println(ByteBufUtil.prettyHexDump(byteBuf));
+                byte len = byteBuf.getByte(4);
+                System.out.println("Length " + (int) len);
+
+                CanFrame frame = CanFrame.create(byteBuf.nioBuffer());
+                System.out.println(frame);
+
+                return len + 8 /* overhead */;
+            }
+            return -1; //discard
+        }
+    }
+
+    public class CANCleaner implements Consumer<ByteBuf> {
+        @Override
+        public void accept(ByteBuf byteBuf) {
+            System.out.println("Discard");
+            byteBuf.readByte();
+        }
+    }
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
new file mode 100644
index 0000000..e6f18ca
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
@@ -0,0 +1,62 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.can.protocol;
+
+import org.apache.plc4x.java.canopen.readwrite.CANOpenPayload;
+import org.apache.plc4x.java.canopen.readwrite.io.CANOpenPayloadIO;
+import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService;
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.spi.ConversationContext;
+import org.apache.plc4x.java.spi.Plc4xProtocolBase;
+import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> {
+
+    private Logger logger = LoggerFactory.getLogger(CANOpenProtocolLogic.class);
+
+    @Override
+    public void onConnect(ConversationContext<SocketCANFrame> context) {
+        context.fireConnected();
+    }
+
+    @Override
+    protected void decode(ConversationContext<SocketCANFrame> context, SocketCANFrame msg) throws Exception {
+        logger.info("Decode CAN message {}", msg);
+
+        int identifier = msg.getIdentifier();
+        CANOpenService service = CANOpenService.valueOf((byte) (identifier >> 7));
+        if (service != null) {
+            ReadBuffer buffer = new ReadBuffer(msg.getData());
+            CANOpenPayload payload = CANOpenPayloadIO.staticParse(buffer, service);
+        }
+    }
+
+    @Override
+    public void close(ConversationContext<SocketCANFrame> context) {
+
+    }
+
+    @Override
+    public void onDisconnect(ConversationContext<SocketCANFrame> context) {
+
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenTest.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenPayloadTest.java
similarity index 84%
rename from sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenTest.java
rename to sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenPayloadTest.java
index a97a1eb..8af4f2b 100644
--- a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenTest.java
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenPayloadTest.java
@@ -21,10 +21,10 @@ package org.apache.plc4x.java.can;
 
 import org.apache.plc4x.test.parserserializer.ParserSerializerTestsuiteRunner;
 
-public class CANOpenTest extends ParserSerializerTestsuiteRunner {
+public class CANOpenPayloadTest extends ParserSerializerTestsuiteRunner {
 
-    public CANOpenTest() {
-        super("/testsuite/CANOpenTestSuite.xml");
+    public CANOpenPayloadTest() {
+        super("/testsuite/CANOpenPayloadTestSuite.xml");
     }
 
 }
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
similarity index 85%
rename from sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenTestSuite.xml
rename to sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
index b99128d..b5676d9 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
@@ -22,11 +22,14 @@
   <name>Tests of socketcan/CANopen frames.</name>
 
   <testcase>
-    <name>Network heartbeat frame: 728#05</name>
-    <raw>280700000100000005</raw>
-    <root-type>CANOpenFrame</root-type>
+    <name>Network heartbeat payload: 0000</name>
+    <raw>0000</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>NMT</arg1>
+    </parser-arguments>
     <xml>
-      <SocketCANFrame className="org.apache.plc4x.java.canopen.readwrite.CANOpenFrame">
+      <SocketCANFrame className="org.apache.plc4x.java.canopen.readwrite.CANOpenPayload">
         <function>15</function>
         <identifier>5</identifier>
         <extended>false</extended>


[plc4x] 17/19: Test of wireshark frames.

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 5d1e10c2c024a0424a8ee8b0d9669c1b71bd2f27
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Mon Sep 7 13:18:29 2020 +0200

    Test of wireshark frames.
---
 .../src/main/resources/protocols/can/canopen.mspec | 243 +++++++++++++++---
 .../plc4x/java/can/helper/CANOpenHelper.java       |  15 +-
 .../java/can/protocol/CANOpenProtocolLogic.java    |  26 +-
 .../plc4x/java/can/CANOpenWiresharkTest.java       |  30 +++
 .../testsuite/CANOpenPayloadTestSuite.xml          | 130 +++++-----
 .../testsuite/CANOpenWiresharkTestSuite.xml        | 278 +++++++++++++++++++++
 6 files changed, 616 insertions(+), 106 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/canopen.mspec b/protocols/can/src/main/resources/protocols/can/canopen.mspec
index bb825f3..e5e0fe1 100644
--- a/protocols/can/src/main/resources/protocols/can/canopen.mspec
+++ b/protocols/can/src/main/resources/protocols/can/canopen.mspec
@@ -36,7 +36,7 @@
 ]
 
 [enum uint 8 'NMTStateRequest'
-    ['0x01' OPERATIONAL]
+    ['0x01' START]
     ['0x02' STOP]
     ['0x80' PRE_OPERATIONAL]
     ['0x81' RESET_NODE]
@@ -58,7 +58,7 @@
             [simple uint 7 'node']
         ]
         ['CANOpenService.TIME' CANOpenTimeSynchronization
-            [simple TimeOfDay 'timeOfDay']
+            [simple CANOpenTime 'timeOfDay']
         ]
         ['CANOpenService.RECEIVE_PDO_1' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['1', 'true']]
@@ -84,12 +84,12 @@
         ['CANOpenService.TRANSMIT_PDO_4' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['1', 'false']]
         ]
-        ['CANOpenService.TRANSMIT_SDO' CANOpenSDORequest
-            [enum SDOCommand 'command']
+        ['CANOpenService.RECEIVE_SDO' CANOpenSDORequest
+            [enum SDORequestCommand 'command']
             [simple SDORequest 'request' ['command']]
         ]
-        ['CANOpenService.RECEIVE_SDO' CANOpenSDOResponse
-            [enum SDOCommand 'command']
+        ['CANOpenService.TRANSMIT_SDO' CANOpenSDOResponse
+            [enum SDOResponseCommand 'command']
             [simple SDOResponse 'response' ['command']]
         ]
         ['CANOpenService.HEARTBEAT' CANOpenHeartbeatPayload
@@ -98,82 +98,243 @@
     ]
 ]
 
-[type 'SDORequest' [SDOCommand 'command']
+[type 'SDORequest' [SDORequestCommand 'command']
     [typeSwitch 'command'
-        ['SDOCommand.INITIALIZE_DOWNLOAD' SDOInitializeDownloadRequest
+        ['SDORequestCommand.SEGMENT_DOWNLOAD' SDOSegmentDownloadRequest
+            [simple bit 'toggle']
+            [implicit uint 3 'size' '7 - COUNT(data)']
+            [simple bit 'last']
+            [array int 8 'data' COUNT '7 - size']
+            [padding uint 8 'alignment' '0x00' '7 - COUNT(data)']
+        ]
+        ['SDORequestCommand.INITIATE_DOWNLOAD' SDOInitiateDownloadRequest
             [reserved uint 1 '0x00']
-            [implicit uint 2 'size' 'expedited && indicated ? 4 - COUNT(data) : 0']
+            [implicit uint 2 'size' 'STATIC_CALL("org.apache.plc4x.java.can.helper.CANOpenHelper.count", expedited, indicated, payload)']
             [simple bit 'expedited']
             [simple bit 'indicated']
-            [simple Multiplexer 'address']
-            [array int 8 'data' COUNT '(expedited && indicated) ? 4 - size : 0']
-            [padding uint 8 'alignment' '0x00' '4 - (COUNT(data))']
+            [simple IndexAddress 'address']
+            [simple SDOInitiateUploadResponsePayload 'payload' ['expedited', 'indicated', 'size']]
+        ]
+        ['SDORequestCommand.INITIATE_UPLOAD' SDOInitiateUploadRequest
+            [reserved uint 5 '0x00']
+            [simple IndexAddress 'address']
+            [reserved int 32 '0x00'] // padding
+        ]
+        ['SDORequestCommand.SEGMENT_UPLOAD' SDOSegmentUploadRequest
+            [simple bit 'toggle']
+            [reserved uint 4 '0x00']
+            [reserved int 56 '0x00'] // padding
+        ]
+        ['SDORequestCommand.ABORT' SDOAbortRequest
+            [simple SDOAbort 'abort']
+        ]
+        ['SDORequestCommand.BLOCK' SDOBlockRequest
+            [simple SDOBlockData 'block']
         ]
-        ['SDOCommand.SEGMENT_DOWNLOAD' SDOSegmentDownloadRequest
+    ]
+]
+
+[type 'SDOBlockData'
+    [simple uint 5 'flags']
+    [array int 8 'data' COUNT '7']
+]
+
+[type 'SDOResponse' [SDOResponseCommand 'command']
+    [typeSwitch 'command'
+        ['SDOResponseCommand.SEGMENT_UPLOAD' SDOSegmentUploadResponse
             [simple bit 'toggle']
             [implicit uint 3 'size' '7 - COUNT(data)']
             [simple bit 'last']
-            [array int 8 'data' COUNT '7 - data']
-            [padding uint 8 'alignment' '0x00' '7 - (COUNT(data))']
+            [array int 8 'data' COUNT '7 - size']
+            [padding uint 8 'alignment' '0x00' '7 - COUNT(data)']
+        ]
+        ['SDOResponseCommand.SEGMENT_DOWNLOAD' SDOSegmentDownloadResponse
+            [simple bit 'toggle']
+            [reserved uint 4 '0x00'] // fill first byte
+            [reserved int 56 '0x00'] // padding
+        ]
+        ['SDOResponseCommand.INITIATE_UPLOAD' SDOInitiateUploadResponse
+            [reserved uint 1 '0x00']
+            [implicit uint 2 'size' 'STATIC_CALL("org.apache.plc4x.java.can.helper.CANOpenHelper.count", expedited, indicated, payload)']
+            [simple bit 'expedited']
+            [simple bit 'indicated']
+            [simple IndexAddress 'address']
+            [simple SDOInitiateUploadResponsePayload 'payload' ['expedited', 'indicated', 'size']]
         ]
-        ['SDOCommand.INITIALIZE_UPLOAD' SDOInitializeUploadRequest
+        ['SDOResponseCommand.INITIATE_DOWNLOAD' SDOInitiateDownloadResponse
             [reserved uint 5 '0x00']
-            [simple Multiplexer 'address']
+            [simple IndexAddress 'address']
             [reserved int 32 '0x00'] // padding
         ]
+        ['SDOResponseCommand.ABORT' SDOAbortResponse
+            [simple SDOAbort 'abort']
+        ]
+        ['SDOResponseCommand.BLOCK' SDOBlockResponse
+            [simple SDOBlockData 'block']
+        ]
     ]
 ]
 
-[type 'SDOResponse' [SDOCommand 'command']
-    [typeSwitch 'command'
-        ['SDOCommand.SEGMENT_UPLOAD' SDOSegmentUploadResponse
-            [reserved uint 5 '0x00']
-            [simple Multiplexer 'address']
-            [reserved int 32 '0x00'] // padding
+[type 'SDOInitiateUploadResponsePayload' [bit 'expedited', bit 'indicated', uint 2 'size']
+    [typeSwitch 'expedited', 'indicated'
+        ['true', 'true' SDOInitiateExpeditedUploadResponse [uint 2 'size']
+            [array int 8 'data' COUNT '4 - size']
+            [padding uint 8 'alignment' '0x00' '4 - COUNT(data)']
         ]
-        ['SDOCommand.INITIALIZE_DOWNLOAD' SDOInitializeDownloadResponse
-            [simple bit 'toggle']
-            [reserved uint 4 '0x00']
-            [reserved int 32 '0x00'] // padding
+        ['false', 'true' SDOInitiateSegmentedUploadResponse
+            [simple uint 32 'bytes']
         ]
-        ['SDOCommand.INITIALIZE_UPLOAD' SDOInitializeUploadResponse
-            [simple SDOSegment 'segment']
+        ['false', 'false' SDOInitiateSegmentedReservedResponse
+            [reserved int 32 '0x00']
         ]
     ]
 ]
 
+[type 'SDOAbort'
+    [reserved uint 5 '0x00']
+    [simple IndexAddress 'address']
+    [simple uint 32 'code']
+]
+
 [type 'SDOSegment'
     [reserved uint 1 '0x00']
     [implicit uint 2 'size' 'expedited && indicated ? 4 - COUNT(data) : 0']
     [simple bit 'expedited']
     [simple bit 'indicated']
-    [simple Multiplexer 'address']
+    [simple IndexAddress 'address']
     [array int 8 'data' COUNT '(expedited && indicated) ? 4 - size : 0']
     [padding uint 8 'alignment' '0x00' '4 - (COUNT(data))']
 ]
 
-[type 'Multiplexer'
+[type 'IndexAddress'
     [simple uint 16 'index']
     [simple uint 8 'subindex']
 ]
 
-[enum uint 3 'SDOCommand'
-    ['0x00' SEGMENT_DOWNLOAD]
-    ['0x01' INITIALIZE_DOWNLOAD]
-    ['0x02' INITIALIZE_UPLOAD]
-    ['0x03' SEGMENT_UPLOAD]
-    ['0x04' ABORT]
-    ['0x05' BLOCK_UPLOAD]
-    ['0x06' BLOCK_DOWNLOAD]
+[enum uint 3 'SDORequestCommand'
+    ['0x00' SEGMENT_DOWNLOAD  ]
+    ['0x01' INITIATE_DOWNLOAD ]
+    ['0x02' INITIATE_UPLOAD   ]
+    ['0x03' SEGMENT_UPLOAD    ]
+    ['0x04' ABORT             ]
+    ['0x05' BLOCK             ]
+]
+
+[enum uint 3 'SDOResponseCommand'
+    ['0x00' SEGMENT_UPLOAD    ]
+    ['0x01' SEGMENT_DOWNLOAD  ]
+    ['0x02' INITIATE_UPLOAD   ]
+    ['0x03' INITIATE_DOWNLOAD ]
+    ['0x04' ABORT             ]
+    ['0x06' BLOCK             ]
 ]
 
 [type 'CANOpenPDO' [uint 2 'index', bit 'receive']
     [array int 8 'data' COUNT '8']
 ]
 
-[type 'TimeOfDay'
-    // CiA 301 - section 7.1.6.5
+[type 'CANOpenTime'
+    // CiA 301 - section 7.1.6.5 and 7.1.6.6
     [simple uint 28 'millis']
     [reserved int 4 '0x00']
     [simple uint 16 'days']
+]
+
+[enum 'CANOpenDataType' [uint 8 'numBits']
+    [BOOLEAN     [ '1'] ]
+    [UNSIGNED8   [ '8'] ]
+    [UNSIGNED16  ['16'] ]
+    [UNSIGNED24  ['24'] ]
+    [UNSIGNED32  ['32'] ]
+    [UNSIGNED40  ['40'] ]
+    [UNSIGNED48  ['48'] ]
+    [UNSIGNED56  ['56'] ]
+    [UNSIGNED64  ['64'] ]
+    [INTEGER8    [ '8'] ]
+    [INTEGER16   ['16'] ]
+    [INTEGER24   ['24'] ]
+    [INTEGER32   ['32'] ]
+    [INTEGER40   ['40'] ]
+    [INTEGER48   ['48'] ]
+    [INTEGER56   ['56'] ]
+    [INTEGER64   ['64'] ]
+    [REAL32      ['32'] ]
+    [REAL64      ['64'] ]
+
+    // compound/complex types
+    [OCTET_STRING     [ '8'] ]
+    [VISIBLE_STRING   [ '8'] ]
+    [UNICODE_STRING   ['16'] ]
+    [TIME_OF_DAY      ['48'] ]
+    [TIME_DIFFERENCE  ['48'] ]
+]
+
+[dataIo 'DataItem' [CANOpenDataType 'dataType']
+    [typeSwitch 'dataType'
+        ['CANOpenDataType.BOOLEAN' Boolean
+            [simple bit 'value']
+        ]
+        ['CANOpenDataType.UNSIGNED8' Integer
+            [simple uint 8 'value']
+        ]
+        ['CANOpenDataType.UNSIGNED16' Integer
+            [simple uint 16 'value']
+        ]
+        ['CANOpenDataType.UNSIGNED24' Long
+            [simple uint 24 'value']
+        ]
+        ['CANOpenDataType.UNSIGNED32' Long
+            [simple uint 32 'value']
+        ]
+        ['CANOpenDataType.UNSIGNED40' BigInteger
+            [simple uint 40 'value']
+        ]
+        ['CANOpenDataType.UNSIGNED48' BigInteger
+            [simple uint 48 'value']
+        ]
+        ['CANOpenDataType.UNSIGNED56' BigInteger
+            [simple uint 56 'value']
+        ]
+        ['CANOpenDataType.UNSIGNED64' BigInteger
+            [simple uint 64 'value']
+        ]
+        ['CANOpenDataType.INTEGER8' Integer
+            [simple int 8 'value']
+        ]
+        ['CANOpenDataType.INTEGER16' Integer
+            [simple int 16 'value']
+        ]
+        ['CANOpenDataType.INTEGER24' Integer
+            [simple int 24 'value']
+        ]
+        ['CANOpenDataType.INTEGER32' Integer
+            [simple int 32 'value']
+        ]
+        ['CANOpenDataType.INTEGER40' Long
+            [simple int 40 'value']
+        ]
+        ['CANOpenDataType.INTEGER48' Long
+            [simple int 48 'value']
+        ]
+        ['CANOpenDataType.INTEGER56' Long
+            [simple int 56 'value']
+        ]
+        ['CANOpenDataType.INTEGER64' Long
+            [simple int 64 'value']
+        ]
+        ['CANOpenDataType.REAL32' Float
+            [simple float 8.23 'value']
+        ]
+        ['CANOpenDataType.REAL64' Double
+            [simple float 11.52 'value']
+        ]
+        ['CANOpenDataType.OCTET_STRING' String
+        ]
+        ['CANOpenDataType.VISIBLE_STRING' String
+        ]
+        //CANOpenDataType.TIME_OF_DAY' CANOpenTime
+        //CANOpenDataType.TIME_DIFFERENCE' CANOpenTime
+        ['CANOpenDataType.UNICODE_STRING' String
+        ]
+    ]
 ]
\ No newline at end of file
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/CANOpenHelper.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/CANOpenHelper.java
index 5f6b4d3..1a9a346 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/CANOpenHelper.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/CANOpenHelper.java
@@ -1,16 +1,27 @@
 package org.apache.plc4x.java.can.helper;
 
+import org.apache.plc4x.java.canopen.readwrite.SDOInitiateExpeditedUploadResponse;
+import org.apache.plc4x.java.canopen.readwrite.SDOInitiateUploadResponsePayload;
+import org.apache.plc4x.java.canopen.readwrite.SDOSegmentUploadResponse;
 import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService;
-import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
-import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 
+import static org.apache.plc4x.java.spi.generation.StaticHelper.COUNT;
+
 public class CANOpenHelper {
 
     public static CANOpenService readFunction(short identifier) {
         return CANOpenService.valueOf((byte) (identifier >> 7));
     }
 
+    public static int uploadPadding(SDOSegmentUploadResponse payload) {
+        return 7 - payload.getData().length;
+    }
+
+    public static int count(boolean expedited, boolean indicated, SDOInitiateUploadResponsePayload payload) {
+        return expedited && indicated && payload instanceof SDOInitiateExpeditedUploadResponse ? 4 - COUNT(((SDOInitiateExpeditedUploadResponse) payload).getData()) : 0;
+    }
+
     public static void writeFunction(WriteBuffer io, short identifier) {
         // NOOP - a placeholder to let mspec compile
     }
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
index c193ec3..fa6dab2 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
@@ -20,10 +20,8 @@ package org.apache.plc4x.java.can.protocol;
 
 import org.apache.plc4x.java.can.configuration.CANConfiguration;
 import org.apache.plc4x.java.canopen.readwrite.CANOpenHeartbeatPayload;
-import org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload;
 import org.apache.plc4x.java.canopen.readwrite.CANOpenPayload;
 import org.apache.plc4x.java.canopen.readwrite.io.CANOpenHeartbeatPayloadIO;
-import org.apache.plc4x.java.canopen.readwrite.io.CANOpenNetworkPayloadIO;
 import org.apache.plc4x.java.canopen.readwrite.io.CANOpenPayloadIO;
 import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService;
 import org.apache.plc4x.java.canopen.readwrite.types.NMTState;
@@ -88,7 +86,14 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
 
     @Override
     protected void decode(ConversationContext<SocketCANFrame> context, SocketCANFrame msg) throws Exception {
-        logger.info("Decode CAN message {}", msg);
+        CANOpenService service = serviceId(msg.getIdentifier());
+        CANOpenPayload payload = CANOpenPayloadIO.staticParse(new ReadBuffer(msg.getData()), service);
+
+        if (service != null) {
+            logger.info("Decoded CANOpen {} from {}, message {}", service, Math.abs(service.getMin() - msg.getIdentifier()), payload);
+        } else {
+            logger.info("CAN message {}, {}", msg.getIdentifier(), msg);
+        }
 
 //        int identifier = msg.getIdentifier();
 //        CANOpenService service = CANOpenService.valueOf((byte) (identifier >> 7));
@@ -107,7 +112,10 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
 
     @Override
     public void onDisconnect(ConversationContext<SocketCANFrame> context) {
-
+        if (this.heartbeat != null) {
+            this.heartbeat.cancel();
+            this.heartbeat = null;
+        }
     }
 
     private int cobId(CANOpenService service) {
@@ -118,6 +126,14 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
 
     private CANOpenService serviceId(int nodeId) {
         // form 32 bit socketcan identifier
-        return CANOpenService.valueOf((byte) (nodeId >> 7));
+        CANOpenService service = CANOpenService.valueOf((byte) (nodeId >> 7));
+        if (service == null) {
+            for (CANOpenService val : CANOpenService.values()) {
+                if (val.getMin() > nodeId && val.getMax() < nodeId) {
+                    return val;
+                }
+            }
+        }
+        return service;
     }
 }
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenWiresharkTest.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenWiresharkTest.java
new file mode 100644
index 0000000..3d1258a
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenWiresharkTest.java
@@ -0,0 +1,30 @@
+/*
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+*/
+
+package org.apache.plc4x.java.can;
+
+import org.apache.plc4x.test.parserserializer.ParserSerializerTestsuiteRunner;
+
+public class CANOpenWiresharkTest extends ParserSerializerTestsuiteRunner {
+
+    public CANOpenWiresharkTest() {
+        super("/testsuite/CANOpenWiresharkTestSuite.xml");
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
index 8537aee..2f2353f 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
@@ -34,7 +34,7 @@
     </parser-arguments>
     <xml>
       <CANOpenTimeSynchronization className="org.apache.plc4x.java.canopen.readwrite.CANOpenTimeSynchronization">
-        <timeOfDay className="org.apache.plc4x.java.canopen.readwrite.TimeOfDay">
+        <timeOfDay className="org.apache.plc4x.java.canopen.readwrite.CANOpenTime">
           <millis>-663027446</millis>
           <days>13392</days>
         </timeOfDay>
@@ -54,7 +54,7 @@
     </parser-arguments>
     <xml>
       <CANOpenTimeSynchronization className="org.apache.plc4x.java.canopen.readwrite.CANOpenTimeSynchronization">
-        <timeOfDay className="org.apache.plc4x.java.canopen.readwrite.TimeOfDay">
+        <timeOfDay className="org.apache.plc4x.java.canopen.readwrite.CANOpenTime">
           <millis>-392494841</millis>
           <days>13392</days>
         </timeOfDay>
@@ -105,27 +105,33 @@
   </testcase>
 
   <testcase>
-    <name>SDO request, payload: 43171000</name>
-    <raw>43171000</raw>
+    <name>SDO request, payload: 4317100000000000</name>
+    <raw>4317100000000000</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>RECEIVE_SDO</arg1>
+      <arg1>TRANSMIT_SDO</arg1>
     </parser-arguments>
     <xml>
-      <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
-        <command>INITIALIZE_UPLOAD</command>
-        <expedited>true</expedited>
-        <placement>true</placement>
-        <index>4119</index>
-        <subindex>0</subindex>
-        <data/>
-      </CANOpenSDORequest>
+      <CANOpenSDOResponse className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse">
+        <command>INITIATE_UPLOAD</command>
+        <response className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateUploadResponse">
+          <expedited>true</expedited>
+          <indicated>true</indicated>
+          <address className="org.apache.plc4x.java.canopen.readwrite.IndexAddress">
+            <index>4119</index>
+            <subindex>0</subindex>
+          </address>
+          <payload className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateExpeditedUploadResponse">
+            <data>AAAAAA==</data>
+          </payload>
+        </response>
+      </CANOpenSDOResponse>
     </xml>
   </testcase>
 
   <testcase>
-    <name>SDO request, payload: 00171000<!--A00F0000--></name>
-    <raw>00171000<!--A00F0000--></raw>
+    <name>SDO request, payload: 00171000A00F0000</name>
+    <raw>00171000A00F0000</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
       <arg1>RECEIVE_SDO</arg1>
@@ -133,87 +139,93 @@
     <xml>
       <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
         <command>SEGMENT_DOWNLOAD</command>
-        <expedited>false</expedited>
-        <placement>false</placement>
-        <index>4119</index>
-        <subindex>0</subindex>
-        <data/>
+        <request className="org.apache.plc4x.java.canopen.readwrite.SDOSegmentDownloadRequest">
+          <toggle>false</toggle>
+          <last>false</last>
+          <data>FxAAoA8AAA==</data>
+        </request>
       </CANOpenSDORequest>
     </xml>
   </testcase>
 
   <testcase>
-    <name>SDO write request, payload: 2B171000D00F</name>
-    <raw>2B171000D00F</raw>
+    <name>SDO write request, payload: 2B171000D00F0000</name>
+    <raw>2B171000D00F0000</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
       <arg1>RECEIVE_SDO</arg1>
     </parser-arguments>
     <xml>
       <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
-        <command>INITIALIZE_DOWNLOAD</command>
-        <expedited>true</expedited>
-        <placement>true</placement>
-        <index>4119</index>
-        <subindex>0</subindex>
-        <data>
-          <data>208</data>
-          <data>15</data>
-        </data>
+        <command>INITIATE_DOWNLOAD</command>
+        <request className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateDownloadRequest">
+          <expedited>true</expedited>
+          <indicated>true</indicated>
+          <address className="org.apache.plc4x.java.canopen.readwrite.IndexAddress">
+            <index>4119</index>
+            <subindex>0</subindex>
+          </address>
+          <payload className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateExpeditedUploadResponse">
+            <data>0A8=</data>
+          </payload>
+        </request>
       </CANOpenSDORequest>
     </xml>
   </testcase>
 
   <testcase>
-    <name>SDO write result, payload: 60171000<!--A00F0000--></name>
-    <raw>00171000<!--A00F0000--></raw>
+    <name>SDO write result, payload: 60171000A00F0000</name>
+    <raw>00171000A00F0000</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
       <arg1>TRANSMIT_SDO</arg1>
     </parser-arguments>
     <xml>
-      <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
-        <command>SEGMENT_DOWNLOAD</command>
-        <expedited>false</expedited>
-        <placement>false</placement>
-        <index>4119</index>
-        <subindex>0</subindex>
-        <data/>
-      </CANOpenSDORequest>
+      <CANOpenSDOResponse className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse">
+        <command>SEGMENT_UPLOAD</command>
+        <response className="org.apache.plc4x.java.canopen.readwrite.SDOSegmentUploadResponse">
+          <toggle>false</toggle>
+          <last>false</last>
+          <data>FxAAoA8AAA==</data>
+        </response>
+      </CANOpenSDOResponse>
     </xml>
   </testcase>
 
   <!-- samples -->
   <testcase>
-    <name>SDO response, payload: 60002000</name>
-    <raw>60002000</raw>
+    <name>SDO response, payload: 6000200000000000</name>
+    <raw>6000200000000000</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
       <arg1>TRANSMIT_SDO</arg1>
     </parser-arguments>
     <xml>
       <CANOpenSDOResponse className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse">
-        <command>SEGMENT_UPLOAD</command>
-        <expedited>false</expedited>
-        <placement>false</placement>
-        <index>8192</index>
-        <subindex>0</subindex>
-        <data/>
+        <command>INITIATE_DOWNLOAD</command>
+        <response className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateDownloadResponse">
+          <address className="org.apache.plc4x.java.canopen.readwrite.IndexAddress">
+            <index>8192</index>
+            <subindex>0</subindex>
+          </address>
+        </response>
       </CANOpenSDOResponse>
     </xml>
   </testcase>
 
   <testcase>
-    <name>PDO, payload: 78563412</name>
-    <raw>78563412</raw>
+    <name>PDO, payload: 7856341200000000</name>
+    <raw>7856341200000000</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>RECEIVE_SDO</arg1>
+      <arg1>RECEIVE_PDO_1</arg1>
     </parser-arguments>
     <xml>
-      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
-        <state>PRE_OPERATIONAL</state>
-      </CANOpenNetworkPayload>
+      <CANOpenPDOPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenPDOPayload">
+        <pdo className="org.apache.plc4x.java.canopen.readwrite.CANOpenPDO">
+          <data>eFY0EgAAAAA=</data>
+        </pdo>
+      </CANOpenPDOPayload>
     </xml>
   </testcase>
 
@@ -226,9 +238,11 @@
       <arg1>TRANSMIT_PDO_1</arg1>
     </parser-arguments>
     <xml>
-      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
-        <state>PRE_OPERATIONAL</state>
-      </CANOpenNetworkPayload>
+      <CANOpenPDOPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenPDOPayload">
+        <pdo className="org.apache.plc4x.java.canopen.readwrite.CANOpenPDO">
+          <data>+QE+AUwBXAE=</data>
+        </pdo>
+      </CANOpenPDOPayload>
     </xml>
   </testcase>
 
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenWiresharkTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenWiresharkTestSuite.xml
new file mode 100644
index 0000000..4bced77
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenWiresharkTestSuite.xml
@@ -0,0 +1,278 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+  -->
+<test:testsuite xmlns:test="https://plc4x.apache.org/schemas/parser-serializer-testsuite.xsd">
+
+  <name>Tests of CANopen frames from Wireshark sample PCAP files.</name>
+
+
+  <testcase>
+    <name>SDO initiate request: 4008100000000000</name>
+    <raw>4008100000000000</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>RECEIVE_SDO</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
+        <command>INITIATE_UPLOAD</command>
+        <request className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateUploadRequest">
+          <address className="org.apache.plc4x.java.canopen.readwrite.IndexAddress">
+            <index>4104</index>
+            <subindex>0</subindex>
+          </address>
+        </request>
+      </CANOpenSDORequest>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>SDO initiate response: 4108100015000000</name>
+    <raw>4108100015000000</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>TRANSMIT_SDO</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDOResponse className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse">
+        <command>INITIATE_UPLOAD</command>
+        <response className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateUploadResponse">
+          <expedited>false</expedited>
+          <indicated>true</indicated>
+          <address className="org.apache.plc4x.java.canopen.readwrite.IndexAddress">
+            <index>4104</index>
+            <subindex>0</subindex>
+          </address>
+          <payload className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateSegmentedUploadResponse">
+            <bytes>21</bytes>
+          </payload>
+        </response>
+      </CANOpenSDOResponse>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>SDO segment upload request: 6000000000000000</name>
+    <raw>6000000000000000</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>RECEIVE_SDO</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
+        <command>SEGMENT_UPLOAD</command>
+        <request className="org.apache.plc4x.java.canopen.readwrite.SDOSegmentUploadRequest">
+          <toggle>false</toggle>
+        </request>
+      </CANOpenSDORequest>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>SDO abort: 8000000021000008</name>
+    <raw>8000000021000008</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>RECEIVE_SDO</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
+        <command>ABORT</command>
+        <request className="org.apache.plc4x.java.canopen.readwrite.SDOAbortRequest">
+          <abort className="org.apache.plc4x.java.canopen.readwrite.SDOAbort">
+            <address className="org.apache.plc4x.java.canopen.readwrite.IndexAddress">
+              <index>0</index>
+              <subindex>0</subindex>
+            </address>
+            <code>134217761</code>
+          </abort>
+        </request>
+      </CANOpenSDORequest>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>SDO upload segment response: 00556c7472614869</name>
+    <raw>00556c7472614869</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>TRANSMIT_SDO</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDOResponse className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse">
+        <command>SEGMENT_UPLOAD</command>
+        <response className="org.apache.plc4x.java.canopen.readwrite.SDOSegmentUploadResponse">
+          <toggle>false</toggle>
+          <last>false</last>
+          <data>VWx0cmFIaQ==</data>
+        </response>
+      </CANOpenSDOResponse>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>SDO upload segment request: 7000000000000000</name>
+    <raw>7000000000000000</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>RECEIVE_SDO</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
+        <command>SEGMENT_UPLOAD</command>
+        <request className="org.apache.plc4x.java.canopen.readwrite.SDOSegmentUploadRequest">
+          <toggle>true</toggle>
+        </request>
+      </CANOpenSDORequest>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>SDO initiate upload request: 4008102a00000000</name>
+    <raw>4008102a00000000</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>RECEIVE_SDO</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
+        <command>INITIATE_UPLOAD</command>
+        <request className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateUploadRequest">
+          <address className="org.apache.plc4x.java.canopen.readwrite.IndexAddress">
+            <index>4104</index>
+            <subindex>42</subindex>
+          </address>
+        </request>
+      </CANOpenSDORequest>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>NMT start node 0x42: 0142</name>
+    <raw>0142</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>NMT</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+        <request>START</request>
+        <node>66</node>
+      </CANOpenNetworkPayload>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>NMT start node 0x00 (all): 0100</name>
+    <raw>0100</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>NMT</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+        <request>START</request>
+        <node>0</node>
+      </CANOpenNetworkPayload>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>NMT start node 0x42: 0263</name>
+    <raw>0263</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>NMT</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+        <request>STOP</request>
+        <node>99</node>
+      </CANOpenNetworkPayload>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>SDO initiate download request: 2300620161736466</name>
+    <raw>2300620161736466</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>RECEIVE_SDO</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
+        <command>INITIATE_DOWNLOAD</command>
+        <request className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateDownloadRequest">
+          <expedited>true</expedited>
+          <indicated>true</indicated>
+          <address className="org.apache.plc4x.java.canopen.readwrite.IndexAddress">
+            <index>25088</index>
+            <subindex>1</subindex>
+          </address>
+          <payload className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateExpeditedUploadResponse">
+            <data>YXNkZg==</data>
+          </payload>
+        </request>
+      </CANOpenSDORequest>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>SDO abort: 8000620100000206</name>
+    <raw>8000620100000206</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>TRANSMIT_SDO</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDOResponse className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse">
+        <command>ABORT</command>
+        <response className="org.apache.plc4x.java.canopen.readwrite.SDOAbortResponse">
+          <abort className="org.apache.plc4x.java.canopen.readwrite.SDOAbort">
+            <address className="org.apache.plc4x.java.canopen.readwrite.IndexAddress">
+              <index>25088</index>
+              <subindex>1</subindex>
+            </address>
+            <code>100794368</code>
+          </abort>
+        </response>
+      </CANOpenSDOResponse>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>SDO block upload: c208100015000000</name>
+    <raw>c208100015000000</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>TRANSMIT_SDO</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDOResponse className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse">
+        <command>BLOCK</command>
+        <response className="org.apache.plc4x.java.canopen.readwrite.SDOBlockResponse">
+          <block className="org.apache.plc4x.java.canopen.readwrite.SDOBlockData">
+            <flags>2</flags>
+            <data>CBAAFQAAAA==</data>
+          </block>
+        </response>
+      </CANOpenSDOResponse>
+    </xml>
+  </testcase>
+</test:testsuite>
\ No newline at end of file


[plc4x] 13/19: Fix socketcan mspec errors.

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit c7c28fd7dc379509045e0a95d4b31c7ea917abf6
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Tue Sep 1 17:58:00 2020 +0200

    Fix socketcan mspec errors.
---
 protocols/can/src/main/resources/protocols/can/socketcan.mspec | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/socketcan.mspec b/protocols/can/src/main/resources/protocols/can/socketcan.mspec
index e657a9d..201c0d6 100644
--- a/protocols/can/src/main/resources/protocols/can/socketcan.mspec
+++ b/protocols/can/src/main/resources/protocols/can/socketcan.mspec
@@ -28,7 +28,7 @@
         ]
 
         ['false' StandardSocketCANFrame
-            [const  uint 18 '0x0']
+            [const  uint 18 'spacing' '0x0']
             [simple uint 11 'identifier']
         ]
     ]
@@ -58,7 +58,7 @@
     [reserved uint 8 '0x0'] // padding 1
     [reserved uint 8 '0x0'] // padding 2
     [array int 8 'data' COUNT 'size']
-    [padding  uint 8 'pad' '0x00' '8 - (COUNT(data))']
+    [padding  uint 8 '0x00' '8 - (COUNT(data))']
 ]
 
 [type 'SocketCAN20AFrame'


[plc4x] 05/19: Step back to virtual fields in can transport.

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 03ad153c9cb2292a841d809f128106344e29a066
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Mon Aug 24 17:57:02 2020 +0200

    Step back to virtual fields in can transport.
---
 protocols/can/src/main/resources/protocols/can/can.mspec | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/can.mspec b/protocols/can/src/main/resources/protocols/can/can.mspec
index 113e304..16408fd 100644
--- a/protocols/can/src/main/resources/protocols/can/can.mspec
+++ b/protocols/can/src/main/resources/protocols/can/can.mspec
@@ -52,7 +52,7 @@ struct canfd_frame {
 };
 */
 
-[type 'OtherSocketCANFrame'
+[type 'SocketCANFrame'
     [simple int 32 'rawId']
     [virtual bit 'extended'
         'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isRemote", rawId)'
@@ -63,6 +63,7 @@ struct canfd_frame {
     [virtual bit 'error'
         'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isError", rawId)'
     ]
+    [implicit uint 8 'size' 'COUNT(data)']
 //    [typeSwitch 'extended'
 //        ['true' ExtendedOtherSocketCanFrame
 //            [simple uint 8 'flags']
@@ -71,13 +72,13 @@ struct canfd_frame {
             [reserved uint 8 '0x0']
 //        ]
 //    ]
-    [reserved uint 8 '0x0']
-    [reserved uint 8 '0x0']
-    [implicit uint 8 'size' 'COUNT(data)']
+    [reserved uint 8 '0x0'] //flags
+    [reserved uint 8 '0x0'] // padding 1
+    [reserved uint 8 '0x0'] // padding 2
     [array int 8 'data' COUNT 'size']
 ]
 
-[type 'SocketCANFrame'
+[type 'SimplifiedSocketCANFrame'
     [simple bit 'extended']
     [simple bit 'remote']
     [simple bit 'error']


[plc4x] 09/19: More work on socketcan transport.

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 846e03c372ac58499b168344ac7f29fbb6a8d489
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Fri Aug 28 12:05:30 2020 +0200

    More work on socketcan transport.
---
 .../socketcan/netty/SocketCANChannel.java          |  3 +-
 .../main/resources/protocols/can/socketcan.mspec   |  1 +
 .../apache/plc4x/java/can/CANOpenPlcDriver.java    |  4 +-
 .../java/can/configuration/CANConfiguration.java   | 11 +++++
 .../java/can/protocol/CANOpenProtocolLogic.java    | 49 +++++++++++++++++++++-
 .../services/org.apache.plc4x.java.api.PlcDriver   |  1 +
 .../test/java/org/apache/plc4x/java/can/Main.java  |  2 +-
 .../testsuite/CANOpenPayloadTestSuite.xml          | 29 ++++++++-----
 .../resources/testsuite/SocketCANTestSuite.xml     |  4 +-
 9 files changed, 86 insertions(+), 18 deletions(-)

diff --git a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannel.java b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannel.java
index 764d1f5..305d452 100644
--- a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannel.java
+++ b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannel.java
@@ -243,7 +243,8 @@ public class SocketCANChannel extends OioByteStreamChannel {
 
         @Override
         public void write(byte[] b, int off, int len) throws IOException {
-            ByteBuffer buffer = ByteBuffer.wrap(b, off, len);
+            ByteBuffer buffer = ByteBuffer.allocateDirect(len - off);
+            buffer.put(b, off, len);
             CanFrame frame = CanFrame.create(buffer);
             rawCanChannel.write(frame);
         }
diff --git a/protocols/can/src/main/resources/protocols/can/socketcan.mspec b/protocols/can/src/main/resources/protocols/can/socketcan.mspec
index e2e9e3b..e657a9d 100644
--- a/protocols/can/src/main/resources/protocols/can/socketcan.mspec
+++ b/protocols/can/src/main/resources/protocols/can/socketcan.mspec
@@ -58,6 +58,7 @@
     [reserved uint 8 '0x0'] // padding 1
     [reserved uint 8 '0x0'] // padding 2
     [array int 8 'data' COUNT 'size']
+    [padding  uint 8 'pad' '0x00' '8 - (COUNT(data))']
 ]
 
 [type 'SocketCAN20AFrame'
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
index b1c6fe6..4255ff2 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
@@ -42,12 +42,12 @@ public class CANOpenPlcDriver extends GeneratedDriverBase<SocketCANFrame> {
 
     @Override
     public String getProtocolCode() {
-        return "can";
+        return "canopen";
     }
 
     @Override
     public String getProtocolName() {
-        return "Controller Area Network";
+        return "CANopen";
     }
 
     @Override
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java
index 1a86e45..925ca15 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java
@@ -19,8 +19,19 @@ under the License.
 package org.apache.plc4x.java.can.configuration;
 
 import org.apache.plc4x.java.spi.configuration.Configuration;
+import org.apache.plc4x.java.spi.configuration.annotations.ConfigurationParameter;
 import org.apache.plc4x.java.transport.socketcan.CANTransportConfiguration;
 
 public class CANConfiguration implements Configuration, CANTransportConfiguration {
 
+    @ConfigurationParameter
+    private int nodeId;
+
+    public int getNodeId() {
+        return nodeId;
+    }
+
+    public void setNodeId(int nodeId) {
+        this.nodeId = nodeId;
+    }
 }
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
index e6f18ca..555ef92 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
@@ -18,23 +18,62 @@ under the License.
 */
 package org.apache.plc4x.java.can.protocol;
 
+import org.apache.plc4x.java.can.configuration.CANConfiguration;
+import org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload;
 import org.apache.plc4x.java.canopen.readwrite.CANOpenPayload;
+import org.apache.plc4x.java.canopen.readwrite.io.CANOpenNetworkPayloadIO;
 import org.apache.plc4x.java.canopen.readwrite.io.CANOpenPayloadIO;
 import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService;
+import org.apache.plc4x.java.canopen.readwrite.types.NMTState;
 import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
 import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
+import org.apache.plc4x.java.spi.configuration.HasConfiguration;
+import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.apache.plc4x.java.spi.generation.WriteBuffer;
+import org.apache.plc4x.java.spi.transaction.RequestTransactionManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> {
+import java.util.Timer;
+import java.util.TimerTask;
+
+public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> implements HasConfiguration<CANConfiguration> {
 
     private Logger logger = LoggerFactory.getLogger(CANOpenProtocolLogic.class);
 
+    private CANConfiguration configuration;
+    private RequestTransactionManager tm;
+
+    @Override
+    public void setConfiguration(CANConfiguration configuration) {
+        this.configuration = configuration;
+        // Set the transaction manager to allow only one message at a time.
+        this.tm = new RequestTransactionManager(1);
+    }
+
     @Override
     public void onConnect(ConversationContext<SocketCANFrame> context) {
-        context.fireConnected();
+        CANOpenNetworkPayload state = new CANOpenNetworkPayload(NMTState.BOOTED_UP);
+        WriteBuffer buffer = new WriteBuffer(1);
+        try {
+            CANOpenNetworkPayloadIO.staticSerialize(buffer, state);
+            context.sendToWire(new SocketCANFrame(cobId(CANOpenService.NMT), buffer.getData()));
+            context.fireConnected();
+
+            Timer heartbeat = new Timer();
+            heartbeat.scheduleAtFixedRate(new TimerTask() {
+                @Override
+                public void run() {
+                    CANOpenNetworkPayload state = new CANOpenNetworkPayload(NMTState.OPERATIONAL);
+                    WriteBuffer buffer = new WriteBuffer(1);
+                    context.sendToWire(new SocketCANFrame(cobId(CANOpenService.NMT), buffer.getData()));
+                }
+            }, 5000, 5000);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
     }
 
     @Override
@@ -46,6 +85,8 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> {
         if (service != null) {
             ReadBuffer buffer = new ReadBuffer(msg.getData());
             CANOpenPayload payload = CANOpenPayloadIO.staticParse(buffer, service);
+
+
         }
     }
 
@@ -59,4 +100,8 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> {
 
     }
 
+    private int cobId(CANOpenService service) {
+        return service.getValue() & configuration.getNodeId();
+    }
+
 }
diff --git a/sandbox/test-java-can-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver b/sandbox/test-java-can-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
index cb3d2ec..3bbef56 100644
--- a/sandbox/test-java-can-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
+++ b/sandbox/test-java-can-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
@@ -17,3 +17,4 @@
 # under the License.
 #
 org.apache.plc4x.java.can.CANPlcDriver
+org.apache.plc4x.java.can.CANOpenPlcDriver
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java
index 622f602..e8279b6 100644
--- a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java
@@ -29,7 +29,7 @@ public class Main {
     public static void main(String[] args) throws Exception {
         PlcDriverManager driverManager = new PlcDriverManager();
 
-        PlcConnection connection = driverManager.getConnection("can:javacan://vcan0");
+        PlcConnection connection = driverManager.getConnection("canopen:javacan://vcan0?nodeId=15");
 
     }
 
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
index b5676d9..773f608 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
@@ -22,21 +22,30 @@
   <name>Tests of socketcan/CANopen frames.</name>
 
   <testcase>
-    <name>Network heartbeat payload: 0000</name>
-    <raw>0000</raw>
+    <name>Network heartbeat payload: 00</name>
+    <raw>00</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
       <arg1>NMT</arg1>
     </parser-arguments>
     <xml>
-      <SocketCANFrame className="org.apache.plc4x.java.canopen.readwrite.CANOpenPayload">
-        <function>15</function>
-        <identifier>5</identifier>
-        <extended>false</extended>
-        <remote>false</remote>
-        <error>false</error>
-        <data>ESIzRFVmd4g=</data>
-      </SocketCANFrame>
+      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+        <state>BOOTED_UP</state>
+      </CANOpenNetworkPayload>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Network heartbeat payload: 7F</name>
+    <raw>7F</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>NMT</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+        <state>PRE_OPERATIONAL</state>
+      </CANOpenNetworkPayload>
     </xml>
   </testcase>
 
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
index 03eaaf1..84fc15e 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
@@ -39,7 +39,7 @@
 
   <testcase>
     <name>Standard frame with no payload: 5A1#</name>
-    <raw>a105000000000000</raw>
+    <raw>a1050000000000000000000000000000</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
       <SocketCANFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame">
@@ -55,7 +55,7 @@
 
   <testcase>
     <name>Remote transmission request: 5A1#R</name>
-    <raw>a105004000000000</raw>
+    <raw>a1050040000000000000000000000000</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
       <SocketCANFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame">


[plc4x] 15/19: Fix socketcan mspec.

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 8cb18bf154848b4794e638a73ea43020914cce98
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Thu Sep 3 13:40:38 2020 +0200

    Fix socketcan mspec.
---
 protocols/can/src/main/resources/protocols/can/socketcan.mspec | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/socketcan.mspec b/protocols/can/src/main/resources/protocols/can/socketcan.mspec
index 201c0d6..9440365 100644
--- a/protocols/can/src/main/resources/protocols/can/socketcan.mspec
+++ b/protocols/can/src/main/resources/protocols/can/socketcan.mspec
@@ -18,15 +18,13 @@
  */
 
 [type 'BrokenSocketCANFrame'
-    [discriminator bit 'extended']
     [simple bit 'remote']
     [simple bit 'error']
-    [simple bit 'extended']
+    [discriminator bit 'extended']
     [typeSwitch 'extended'
         ['true' ExtendedSocketCANFrame
             [simple uint 29 'identifier']
         ]
-
         ['false' StandardSocketCANFrame
             [const  uint 18 'spacing' '0x0']
             [simple uint 11 'identifier']
@@ -58,7 +56,7 @@
     [reserved uint 8 '0x0'] // padding 1
     [reserved uint 8 '0x0'] // padding 2
     [array int 8 'data' COUNT 'size']
-    [padding  uint 8 '0x00' '8 - (COUNT(data))']
+    [padding uint 8 'alignment' '0x00' '8 - (COUNT(data))']
 ]
 
 [type 'SocketCAN20AFrame'


[plc4x] 18/19: CANopen milestone - support for segmentet SDO upload (read) requests.

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 93d5d70fd5f3a28905d8fd0fe26b1b7d501fab15
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Tue Oct 6 10:58:09 2020 +0200

    CANopen milestone - support for segmentet SDO upload (read) requests.
---
 .../src/main/resources/protocols/can/canopen.mspec |  40 ++++--
 .../apache/plc4x/java/can/CANOpenPlcDriver.java    |  24 ++--
 .../org/apache/plc4x/java/can/api/CANFrame.java    |  11 ++
 .../apache/plc4x/java/can/api/CANOpenFrame.java    |  66 +++++++++
 .../api/conversation/canopen/CANConversation.java  |  18 +++
 .../api/conversation/canopen/CANFrameBuilder.java  |  11 ++
 .../conversation/canopen/CANOpenConversation.java  |  75 +++++++++++
 .../canopen/CANOpenConversationBase.java           |  15 +++
 .../api/conversation/canopen/SDOConversation.java  |  43 ++++++
 .../canopen/SDODownloadConversation.java           |  97 ++++++++++++++
 .../canopen/SDOUploadConversation.java             |  98 ++++++++++++++
 .../api/segmentation/PlcSegmentationException.java |  21 +++
 .../java/can/api/segmentation/Segmentation.java    | 131 ++++++++++++++++++
 .../api/segmentation/accumulator/ByteStorage.java  |  59 ++++++++
 .../can/api/segmentation/accumulator/Storage.java} |  40 ++++--
 .../java/can/configuration/CANConfiguration.java   |   4 +-
 .../java/can/context/CANOpenDriverContext.java     |   9 ++
 .../apache/plc4x/java/can/field/CANOpenField.java  |  51 +++++++
 .../plc4x/java/can/field/CANOpenFieldHandler.java  |  58 ++++++++
 .../plc4x/java/can/field/CANOpenNMTField.java      |  58 ++++++++
 .../plc4x/java/can/field/CANOpenSDOField.java      |  89 ++++++++++++
 .../plc4x/java/can/helper/CANOpenHelper.java       |  14 ++
 .../apache/plc4x/java/can/helper/HeaderParser.java |  13 +-
 .../apache/plc4x/java/can/listener/Callback.java   |   8 ++
 .../plc4x/java/can/listener/CompositeCallback.java |  25 ++++
 .../java/can/protocol/CANOpenProtocolLogic.java    | 149 +++++++++++++++++++--
 .../protocol/segmentation/CANOpenSegmentation.java |  86 ++++++++++++
 .../java/can/socketcan/SocketCANConversation.java  |  49 +++++++
 .../java/can/socketcan/SocketCANDelegateFrame.java |  43 ++++++
 .../java/can/socketcan/SocketCANFrameBuilder.java  |  29 ++++
 .../test/java/org/apache/plc4x/java/can/Main.java  |  48 +++++++
 .../{Main.java => field/CANOpenFieldSDOTest.java}  |  24 ++--
 .../plc4x/java/can/field/CANOpenNMTFieldTest.java} |  39 +++---
 33 files changed, 1467 insertions(+), 78 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/canopen.mspec b/protocols/can/src/main/resources/protocols/can/canopen.mspec
index e5e0fe1..3b1e49d 100644
--- a/protocols/can/src/main/resources/protocols/can/canopen.mspec
+++ b/protocols/can/src/main/resources/protocols/can/canopen.mspec
@@ -22,17 +22,17 @@
     ['0b0001' SYNC            ['0x80',  '0x80' , 'false' ] ]
     ['0b0001' EMCY            ['0x81',  '0xFF' , 'false' ] ]
     ['0b0010' TIME            ['0x100', '0x100', 'false' ] ]
-    ['0b0011' TRANSMIT_PDO_1  ['0x181', '0x1FF', 'true'  ] ]
-    ['0b0100' RECEIVE_PDO_1   ['0x201', '0x27F', 'true'  ] ]
-    ['0b0101' TRANSMIT_PDO_2  ['0x281', '0x2FF', 'true'  ] ]
-    ['0b0110' RECEIVE_PDO_2   ['0x301', '0x37F', 'true'  ] ]
-    ['0b0111' TRANSMIT_PDO_3  ['0x381', '0x3FF', 'true'  ] ]
-    ['0b1000' RECEIVE_PDO_3   ['0x401', '0x47F', 'true'  ] ]
-    ['0b1001' TRANSMIT_PDO_4  ['0x481', '0x4FF', 'true'  ] ]
-    ['0b1010' RECEIVE_PDO_4   ['0x501', '0x57F', 'true'  ] ]
-    ['0b1011' TRANSMIT_SDO    ['0x581', '0x5FF', 'false' ] ]
-    ['0b1100' RECEIVE_SDO     ['0x601', '0x67F', 'false' ] ]
-    ['0b1110' HEARTBEAT       ['0x701', '0x77F', 'false' ] ]
+    ['0b0011' TRANSMIT_PDO_1  ['0x180', '0x1FF', 'true'  ] ]
+    ['0b0100' RECEIVE_PDO_1   ['0x200', '0x27F', 'true'  ] ]
+    ['0b0101' TRANSMIT_PDO_2  ['0x280', '0x2FF', 'true'  ] ]
+    ['0b0110' RECEIVE_PDO_2   ['0x300', '0x37F', 'true'  ] ]
+    ['0b0111' TRANSMIT_PDO_3  ['0x380', '0x3FF', 'true'  ] ]
+    ['0b1000' RECEIVE_PDO_3   ['0x400', '0x47F', 'true'  ] ]
+    ['0b1001' TRANSMIT_PDO_4  ['0x480', '0x4FF', 'true'  ] ]
+    ['0b1010' RECEIVE_PDO_4   ['0x500', '0x57F', 'true'  ] ]
+    ['0b1011' TRANSMIT_SDO    ['0x580', '0x5FF', 'false' ] ]
+    ['0b1100' RECEIVE_SDO     ['0x600', '0x67F', 'false' ] ]
+    ['0b1110' HEARTBEAT       ['0x700', '0x77F', 'false' ] ]
 ]
 
 [enum uint 8 'NMTStateRequest'
@@ -262,6 +262,7 @@
     [REAL64      ['64'] ]
 
     // compound/complex types
+    [RECORD           [ '8'] ]
     [OCTET_STRING     [ '8'] ]
     [VISIBLE_STRING   [ '8'] ]
     [UNICODE_STRING   ['16'] ]
@@ -269,7 +270,7 @@
     [TIME_DIFFERENCE  ['48'] ]
 ]
 
-[dataIo 'DataItem' [CANOpenDataType 'dataType']
+[dataIo 'DataItem' [CANOpenDataType 'dataType', int 32 'size']
     [typeSwitch 'dataType'
         ['CANOpenDataType.BOOLEAN' Boolean
             [simple bit 'value']
@@ -328,13 +329,28 @@
         ['CANOpenDataType.REAL64' Double
             [simple float 11.52 'value']
         ]
+        ['CANOpenDataType.RECORD' List
+            [array int 8 'value' length 'size']
+        ]
         ['CANOpenDataType.OCTET_STRING' String
+            [manual string 'UTF-8' 'value'
+                'STATIC_CALL("org.apache.plc4x.java.can.helper.CANOpenHelper.parseString", io, size, _type.encoding)'
+                'STATIC_CALL("org.apache.plc4x.java.can.helper.CANOpenHelper.serializeString", io, _value, _type.encoding)' '_value.length'
+            ]
         ]
         ['CANOpenDataType.VISIBLE_STRING' String
+            [manual string 'UTF-8' 'value'
+                'STATIC_CALL("org.apache.plc4x.java.can.helper.CANOpenHelper.parseString", io, size, _type.encoding)'
+                'STATIC_CALL("org.apache.plc4x.java.can.helper.CANOpenHelper.serializeString", io, _value, _type.encoding)' '_value.length'
+            ]
         ]
         //CANOpenDataType.TIME_OF_DAY' CANOpenTime
         //CANOpenDataType.TIME_DIFFERENCE' CANOpenTime
         ['CANOpenDataType.UNICODE_STRING' String
+            [manual string 'UTF-8' 'value'
+                'STATIC_CALL("org.apache.plc4x.java.can.helper.CANOpenHelper.parseString", io, size, _type.encoding)'
+                'STATIC_CALL("org.apache.plc4x.java.can.helper.CANOpenHelper.serializeString", io, _value, _type.encoding)' '_value.length'
+            ]
         ]
     ]
 ]
\ No newline at end of file
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
index 6acff67..a8a5f7a 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
@@ -19,21 +19,18 @@
 package org.apache.plc4x.java.can;
 
 import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufUtil;
 import org.apache.plc4x.java.can.configuration.CANConfiguration;
-import org.apache.plc4x.java.can.context.CANDriverContext;
+import org.apache.plc4x.java.can.context.CANOpenDriverContext;
 import org.apache.plc4x.java.can.field.CANFieldHandler;
+import org.apache.plc4x.java.can.field.CANOpenFieldHandler;
 import org.apache.plc4x.java.can.protocol.CANOpenProtocolLogic;
-import org.apache.plc4x.java.can.protocol.CANProtocolLogic;
 import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
 import org.apache.plc4x.java.socketcan.readwrite.io.SocketCANFrameIO;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
 import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer;
-import tel.schich.javacan.CanFrame;
 
-import java.util.function.Consumer;
 import java.util.function.ToIntFunction;
 
 /**
@@ -56,21 +53,32 @@ public class CANOpenPlcDriver extends GeneratedDriverBase<SocketCANFrame> {
     }
 
     @Override
+    protected boolean canRead() {
+        return true;
+    }
+
+    @Override
+    protected boolean canWrite() {
+        return true;
+    }
+
+    @Override
     protected String getDefaultTransport() {
         return "javacan";
     }
 
     @Override
-    protected CANFieldHandler getFieldHandler() {
-        return new CANFieldHandler();
+    protected CANOpenFieldHandler getFieldHandler() {
+        return new CANOpenFieldHandler();
     }
 
     @Override
     protected ProtocolStackConfigurer<SocketCANFrame> getStackConfigurer() {
         return SingleProtocolStackConfigurer.builder(SocketCANFrame.class, SocketCANFrameIO.class)
             .withProtocol(CANOpenProtocolLogic.class)
-            .withDriverContext(CANDriverContext.class)
+            .withDriverContext(CANOpenDriverContext.class)
             .withPacketSizeEstimator(CANEstimator.class)
+            .littleEndian()
             .build();
     }
 
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/CANFrame.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/CANFrame.java
new file mode 100644
index 0000000..ff1cad6
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/CANFrame.java
@@ -0,0 +1,11 @@
+package org.apache.plc4x.java.can.api;
+
+public interface CANFrame {
+
+    int getIdentifier();
+    boolean getExtended();
+    boolean getRemote();
+    boolean getError();
+    byte[] getData();
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/CANOpenFrame.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/CANOpenFrame.java
new file mode 100644
index 0000000..27db3c2
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/CANOpenFrame.java
@@ -0,0 +1,66 @@
+package org.apache.plc4x.java.can.api;
+
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.apache.plc4x.java.canopen.readwrite.CANOpenPayload;
+import org.apache.plc4x.java.canopen.readwrite.io.CANOpenPayloadIO;
+import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService;
+import org.apache.plc4x.java.spi.generation.ParseException;
+import org.apache.plc4x.java.spi.generation.ReadBuffer;
+
+public class CANOpenFrame implements CANFrame {
+
+    private final CANFrame frame;
+
+    private final CANOpenPayload payload;
+
+    public CANOpenFrame(CANFrame frame) {
+        this.frame = frame;
+        try {
+            this.payload = CANOpenPayloadIO.staticParse(new ReadBuffer(frame.getData(), true), serviceId(frame.getIdentifier()));
+        } catch (ParseException e) {
+            throw new PlcRuntimeException("Could not parse CANopen payload", e);
+        }
+    }
+
+    public CANOpenPayload getPayload() {
+        return payload;
+    }
+
+    @Override
+    public int getIdentifier() {
+        return frame.getIdentifier();
+    }
+
+    @Override
+    public boolean getExtended() {
+        return frame.getExtended();
+    }
+
+    @Override
+    public boolean getRemote() {
+        return frame.getRemote();
+    }
+
+    @Override
+    public boolean getError() {
+        return frame.getError();
+    }
+
+    @Override
+    public byte[] getData() {
+        return frame.getData();
+    }
+
+    private CANOpenService serviceId(int cobId) {
+        // form 32 bit socketcan identifier
+        CANOpenService service = CANOpenService.valueOf((byte) (cobId >> 7));
+        if (service == null) {
+            for (CANOpenService val : CANOpenService.values()) {
+                if (val.getMin() > cobId && val.getMax() < cobId) {
+                    return val;
+                }
+            }
+        }
+        return service;
+    }
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANConversation.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANConversation.java
new file mode 100644
index 0000000..6df8b0c
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANConversation.java
@@ -0,0 +1,18 @@
+package org.apache.plc4x.java.can.api.conversation.canopen;
+
+import org.apache.plc4x.java.can.api.CANFrame;
+
+import java.util.function.BiConsumer;
+
+import org.apache.plc4x.java.spi.ConversationContext.SendRequestContext;
+import org.apache.plc4x.java.spi.transaction.RequestTransactionManager.RequestTransaction;
+
+public interface CANConversation<W extends CANFrame> {
+
+    CANFrameBuilder<W> frameBuilder();
+
+    void send(W frame, BiConsumer<RequestTransaction, SendRequestContext<W>> callback);
+
+
+}
+
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANFrameBuilder.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANFrameBuilder.java
new file mode 100644
index 0000000..53a68c3
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANFrameBuilder.java
@@ -0,0 +1,11 @@
+package org.apache.plc4x.java.can.api.conversation.canopen;
+
+public interface CANFrameBuilder<W> {
+
+    CANFrameBuilder<W> node(int node);
+
+    CANFrameBuilder<W> data(byte[] data);
+
+    W build();
+
+}
\ No newline at end of file
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANOpenConversation.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANOpenConversation.java
new file mode 100644
index 0000000..abe6aa0
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANOpenConversation.java
@@ -0,0 +1,75 @@
+package org.apache.plc4x.java.can.api.conversation.canopen;
+
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.apache.plc4x.java.can.api.CANFrame;
+import org.apache.plc4x.java.canopen.readwrite.CANOpenPayload;
+import org.apache.plc4x.java.canopen.readwrite.io.CANOpenPayloadIO;
+import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService;
+import org.apache.plc4x.java.spi.ConversationContext.SendRequestContext;
+import org.apache.plc4x.java.spi.generation.ParseException;
+import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.apache.plc4x.java.spi.generation.WriteBuffer;
+import org.apache.plc4x.java.spi.transaction.RequestTransactionManager.RequestTransaction;
+
+import java.util.function.BiConsumer;
+
+public class CANOpenConversation<W extends CANFrame> {
+
+    private final int node;
+    private final CANConversation<W> delegate;
+
+    public CANOpenConversation(int node, CANConversation<W> delegate) {
+        this.node = node;
+        this.delegate = delegate;
+    }
+
+    public SDOConversation<W> sdo() {
+        return new SDOConversation<>(this);
+    }
+
+    public void send(CANOpenService service, CANOpenPayload payload, BiConsumer<RequestTransaction, SendRequestContext<CANOpenPayload>> callback) {
+        CANFrameBuilder<W> builder = delegate.frameBuilder();
+        W frame = builder.node(service.getMin() + node).data(serialize(payload)).build();
+        delegate.send(frame, (tx, ctx) -> {
+            SendRequestContext<CANOpenPayload> unwrap = ctx
+//                .onError((response, error) -> {
+//                    System.err.println("Unexpected frame " + response + " " + error);
+//                })
+            .unwrap(CANOpenConversation.this::deserialize);
+            callback.accept(tx, unwrap);
+        });
+    }
+
+    private CANOpenPayload deserialize(CANFrame frame) {
+        try {
+            CANOpenService service = serviceId(frame.getIdentifier());
+            ReadBuffer buffer = new ReadBuffer(frame.getData(), true);
+            return CANOpenPayloadIO.staticParse(buffer, service);
+        } catch (ParseException e) {
+            throw new PlcRuntimeException("Could not deserialize CAN open payload", e);
+        }
+    }
+
+    private byte[] serialize(CANOpenPayload payload) {
+        try {
+            WriteBuffer buffer = new WriteBuffer(payload.getLengthInBytes(), true);
+            CANOpenPayloadIO.staticSerialize(buffer, payload);
+            return buffer.getData();
+        } catch (ParseException e) {
+            throw new PlcRuntimeException("Could not serialize CAN open payload", e);
+        }
+    }
+
+    private CANOpenService serviceId(int cobId) {
+        // form 32 bit socketcan identifier
+        CANOpenService service = CANOpenService.valueOf((byte) (cobId >> 7));
+        if (service == null) {
+            for (CANOpenService val : CANOpenService.values()) {
+                if (val.getMin() > cobId && val.getMax() < cobId) {
+                    return val;
+                }
+            }
+        }
+        return service;
+    }
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANOpenConversationBase.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANOpenConversationBase.java
new file mode 100644
index 0000000..60b87e4
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/CANOpenConversationBase.java
@@ -0,0 +1,15 @@
+package org.apache.plc4x.java.can.api.conversation.canopen;
+
+import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.canopen.readwrite.io.DataItemIO;
+import org.apache.plc4x.java.canopen.readwrite.types.CANOpenDataType;
+import org.apache.plc4x.java.spi.generation.ParseException;
+import org.apache.plc4x.java.spi.generation.ReadBuffer;
+
+public abstract class CANOpenConversationBase {
+
+    protected PlcValue decodeFrom(byte[] data, CANOpenDataType type, int length) throws ParseException {
+        return DataItemIO.staticParse(new ReadBuffer(data, true), type, length);
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDOConversation.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDOConversation.java
new file mode 100644
index 0000000..1447f08
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDOConversation.java
@@ -0,0 +1,43 @@
+package org.apache.plc4x.java.can.api.conversation.canopen;
+
+import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.can.api.CANFrame;
+import org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest;
+import org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse;
+import org.apache.plc4x.java.canopen.readwrite.IndexAddress;
+import org.apache.plc4x.java.canopen.readwrite.SDORequest;
+import org.apache.plc4x.java.canopen.readwrite.types.CANOpenDataType;
+import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService;
+import org.apache.plc4x.java.spi.ConversationContext.SendRequestContext;
+import org.apache.plc4x.java.spi.transaction.RequestTransactionManager.RequestTransaction;
+
+import java.util.function.BiConsumer;
+
+public class SDOConversation<W extends CANFrame> {
+
+    private final CANOpenConversation<W> delegate;
+
+    public SDOConversation(CANOpenConversation<W> delegate) {
+        this.delegate = delegate;
+    }
+
+    public SDODownloadConversation<W> download(IndexAddress indexAddress, PlcValue value, CANOpenDataType type) {
+        return new SDODownloadConversation<>(this, indexAddress, value, type);
+    }
+
+    public SDOUploadConversation<W> upload(IndexAddress indexAddress, CANOpenDataType type) {
+        return new SDOUploadConversation<>(this, indexAddress, type);
+    }
+
+    public void send(SDORequest request, BiConsumer<RequestTransaction, SendRequestContext<CANOpenSDOResponse>> callback) {
+        delegate.send(CANOpenService.RECEIVE_SDO, new CANOpenSDORequest(request.getCommand(), request), (tx, ctx) -> {
+            SendRequestContext<CANOpenSDOResponse> context = ctx
+//            .onError((response, error) -> {
+//                System.out.println("Unexpected frame " + response + " " + error);
+//            })
+            .only(CANOpenSDOResponse.class);
+            callback.accept(tx, context);
+        });
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDODownloadConversation.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDODownloadConversation.java
new file mode 100644
index 0000000..470e190
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDODownloadConversation.java
@@ -0,0 +1,97 @@
+package org.apache.plc4x.java.can.api.conversation.canopen;
+
+import org.apache.plc4x.java.api.exceptions.PlcException;
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.can.api.CANFrame;
+import org.apache.plc4x.java.can.api.segmentation.accumulator.ByteStorage;
+import org.apache.plc4x.java.canopen.readwrite.*;
+import org.apache.plc4x.java.canopen.readwrite.io.DataItemIO;
+import org.apache.plc4x.java.canopen.readwrite.types.CANOpenDataType;
+import org.apache.plc4x.java.canopen.readwrite.types.SDOResponseCommand;
+import org.apache.plc4x.java.spi.generation.ParseException;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.BiConsumer;
+
+public class SDODownloadConversation<W extends CANFrame> {
+
+    private final SDOConversation<W> delegate;
+    private final IndexAddress indexAddress;
+    private final byte[] data;
+
+    public SDODownloadConversation(SDOConversation<W> delegate, IndexAddress indexAddress, PlcValue value, CANOpenDataType type) {
+        this.delegate = delegate;
+        this.indexAddress = indexAddress;
+
+        try {
+            data = DataItemIO.staticSerialize(value, type,  null,true).getData();
+        } catch (ParseException e) {
+            throw new PlcRuntimeException("Could not serialize data", e);
+        }
+    }
+
+    public void execute(BiConsumer<PlcResponseCode, Throwable> receiver) throws PlcException {
+        if (data.length > 4) {
+            // segmented
+
+            SDOInitiateSegmentedUploadResponse size = new SDOInitiateSegmentedUploadResponse(data.length);
+            delegate.send(new SDOInitiateDownloadRequest(false, true, indexAddress, size), (tx, ctx) -> {
+                ctx.unwrap(CANOpenSDOResponse::getResponse)
+                    .check(p -> p.getCommand() == SDOResponseCommand.INITIATE_DOWNLOAD)
+                    .only(SDOInitiateDownloadResponse.class)
+                    .check(p -> indexAddress.equals(p.getAddress()))
+                    .handle(x -> {
+                        put(data, receiver, false, 0);
+                    });
+            });
+
+            return;
+        }
+
+        // expedited
+        SDOInitiateDownloadRequest rq = new SDOInitiateDownloadRequest(
+            true, true,
+            indexAddress,
+            new SDOInitiateExpeditedUploadResponse(data)
+        );
+
+        delegate.send(rq, (tx, ctx) ->
+            ctx.onError((response, error) -> {
+                System.out.println("Unexpected frame " + response + " " + error);
+            })
+            .unwrap(CANOpenSDOResponse::getResponse)
+            .check(r -> r.getCommand() == SDOResponseCommand.INITIATE_DOWNLOAD)
+            .handle(r -> {
+                System.out.println(r);
+            })
+        );
+    }
+
+    private void put(byte[] data, BiConsumer<PlcResponseCode, Throwable> receiver, boolean toggle, int offset) {
+        int remaining = data.length - offset;
+        byte[] segment = new byte[Math.min(remaining, 7)];
+        System.arraycopy(data, offset, segment, 0, segment.length);
+
+        delegate.send(new SDOSegmentDownloadRequest(toggle, remaining <= 7, segment), (tx, ctx) -> {
+            ctx.unwrap(CANOpenSDOResponse::getResponse)
+                .only(SDOSegmentDownloadResponse.class)
+                .onError((response, error) -> {
+                    System.out.println("Unexpected frame " + response + " " + error);
+                    receiver.accept(null, error);
+                })
+                .check(r -> r.getToggle() == toggle)
+                .handle(reply -> {
+                    if (offset + segment.length == data.length) {
+                        // validate offset
+                        receiver.accept(PlcResponseCode.OK, null);
+                    } else {
+                        put(data, receiver, !toggle, offset + segment.length);
+                    }
+                });
+        });
+    }
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDOUploadConversation.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDOUploadConversation.java
new file mode 100644
index 0000000..cb2d778
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/conversation/canopen/SDOUploadConversation.java
@@ -0,0 +1,98 @@
+package org.apache.plc4x.java.can.api.conversation.canopen;
+
+import org.apache.plc4x.java.api.exceptions.PlcException;
+import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.can.api.CANFrame;
+import org.apache.plc4x.java.can.api.segmentation.accumulator.ByteStorage;
+import org.apache.plc4x.java.canopen.readwrite.*;
+import org.apache.plc4x.java.canopen.readwrite.types.CANOpenDataType;
+import org.apache.plc4x.java.spi.generation.ParseException;
+
+import java.util.function.BiConsumer;
+
+public class SDOUploadConversation<W extends CANFrame> extends CANOpenConversationBase {
+
+    private final SDOConversation<W> delegate;
+    private final IndexAddress address;
+    private final CANOpenDataType type;
+
+    public SDOUploadConversation(SDOConversation<W> delegate, IndexAddress address, CANOpenDataType type) {
+        this.delegate = delegate;
+        this.address = address;
+        this.type = type;
+    }
+
+    public void execute(BiConsumer<PlcValue, Throwable> receiver) throws PlcException {
+        SDOInitiateUploadRequest rq = new SDOInitiateUploadRequest(address);
+
+        delegate.send(rq, (tx, ctx) ->
+            ctx
+//            .onError((response, error) -> {
+//                System.err.println("Unexpected frame " + response + " " + error);
+//                receiver.accept(null, error);
+//            })
+            .unwrap(CANOpenSDOResponse::getResponse)
+            .onError(((response, error) -> {
+                if (response instanceof SDOAbortResponse) {
+                    SDOAbortResponse abort = (SDOAbortResponse) response;
+                    SDOAbort sdoAbort = abort.getAbort();
+                    receiver.accept(null, new PlcException("Could not read value. Remote party reported code " + sdoAbort.getCode()));
+                } else {
+                    receiver.accept(null, error);
+                }
+            }))
+            .only(SDOInitiateUploadResponse.class)
+            .check(r -> r.getAddress().equals(address))
+            .handle(response -> {
+                handle(receiver, response);
+            })
+        );
+    }
+
+    private void handle(BiConsumer<PlcValue, Throwable> receiver, SDOInitiateUploadResponse answer) {
+        BiConsumer<Integer, byte[]> valueCallback = (length, bytes) -> {
+            try {
+                receiver.accept(decodeFrom(bytes, type, length), null);
+            } catch (ParseException e) {
+                receiver.accept(null, e);
+            }
+        };
+
+        if (answer.getExpedited() && answer.getIndicated() && answer.getPayload() instanceof SDOInitiateExpeditedUploadResponse) {
+            SDOInitiateExpeditedUploadResponse payload = (SDOInitiateExpeditedUploadResponse) answer.getPayload();
+            valueCallback.accept(payload.getData().length, payload.getData());
+        } else if (answer.getPayload() instanceof SDOInitiateSegmentedUploadResponse) {
+            ByteStorage.SDOUploadStorage storage = new ByteStorage.SDOUploadStorage();
+            storage.append(answer);
+
+            SDOInitiateSegmentedUploadResponse segment = (SDOInitiateSegmentedUploadResponse) answer.getPayload();
+            fetch(storage, valueCallback, receiver, false, Long.valueOf(segment.getBytes()).intValue());
+        } else {
+            receiver.accept(null, new PlcException("Unsupported SDO operation kind."));
+        }
+    }
+
+    private void fetch(ByteStorage.SDOUploadStorage storage, BiConsumer<Integer, byte[]> valueCallback, BiConsumer<PlcValue, Throwable> receiver, boolean toggle, int size) {
+        delegate.send(new SDOSegmentUploadRequest(toggle), (tx, ctx) -> {
+            ctx.unwrap(CANOpenSDOResponse::getResponse)
+                .only(SDOSegmentUploadResponse.class)
+                .onError((response, error) -> {
+                    System.out.println("Unexpected frame " + response + " " + error);
+                    receiver.accept(null, error);
+                })
+                .check(r -> r.getToggle() == toggle)
+                .handle(reply -> {
+                    storage.append(reply);
+
+                    if (reply.getLast()) {
+                        // validate size
+                        valueCallback.accept(Long.valueOf(size).intValue(), storage.get());
+                    } else {
+                        fetch(storage, valueCallback, receiver, !toggle, size);
+                    }
+                });
+        });
+    }
+
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/PlcSegmentationException.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/PlcSegmentationException.java
new file mode 100644
index 0000000..1023551
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/PlcSegmentationException.java
@@ -0,0 +1,21 @@
+package org.apache.plc4x.java.can.api.segmentation;
+
+import org.apache.plc4x.java.api.exceptions.PlcException;
+
+public class PlcSegmentationException extends PlcException {
+    public PlcSegmentationException(String message) {
+        super(message);
+    }
+
+    public PlcSegmentationException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public PlcSegmentationException(Throwable cause) {
+        super(cause);
+    }
+
+    public PlcSegmentationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+        super(message, cause, enableSuppression, writableStackTrace);
+    }
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/Segmentation.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/Segmentation.java
new file mode 100644
index 0000000..84f915d
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/Segmentation.java
@@ -0,0 +1,131 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.can.api.segmentation;
+
+import org.apache.plc4x.java.can.api.segmentation.accumulator.Storage;
+import org.apache.plc4x.java.spi.ConversationContext;
+import org.apache.plc4x.java.spi.transaction.RequestTransactionManager;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+
+/**
+ * Utility type for handling segmented request-response operations.
+ *
+ * Segmented operation is one which spans over multiple frames and contains of:
+ * - initialization
+ * - 0... n steps
+ * - finalization
+ *
+ * Depending on use case there might be 0 intermediate frames, leading to situation where requester sends segment request
+ * and answer comes in one shot.
+ */
+public abstract class Segmentation<C, T, R> {
+
+    private final Duration timeout;
+    private final Storage<T, R> storage;
+    private final Class<C> frameType;
+
+    private Supplier<T> request;
+    private Predicate<T> responseValidator;
+
+    private Predicate<T> finalStep;
+    private Consumer<List<T>> callback;
+    private Function<T, T> step;
+    private Predicate<T> stepValidator;
+    private List<T> answers = new ArrayList<>();
+
+    public Segmentation(Class<C> frameType, Duration timeout, Storage<T, R> storage) {
+        this.frameType = frameType;
+        this.timeout = timeout;
+        this.storage = storage;
+    }
+
+    public Segmentation<C, T, R> begin(Supplier<T> request, Predicate<T> requestAnswer) {
+        this.request = request;
+        this.responseValidator = requestAnswer;
+        return this;
+    }
+
+    public Segmentation<C, T, R> step(Function<T, T> step, Predicate<T> stepAnswer) {
+        this.step = step;
+        this.stepValidator = stepAnswer;
+        return this;
+    }
+
+    public Segmentation<C, T, R> end(Predicate<T> finalStep, Consumer<List<T>> callback) {
+        this.finalStep = finalStep;
+        this.callback = callback;
+        return this;
+    }
+
+    public void execute(RequestTransactionManager tm, ConversationContext<C> context) throws PlcSegmentationException {
+        Consumer<T> consumer = new Consumer<T>() {
+            @Override
+            public void accept(T payload) {
+                storage.append(payload);
+
+                if (finalStep.test(payload)) {
+                    callback.accept(answers);
+                } else {
+                    try {
+                        T apply = step.apply(payload);
+                        send(tm, context, () -> apply, stepValidator, this);
+                    } catch (PlcSegmentationException e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+            }
+        };
+        try {
+            send(tm, context, request, responseValidator, consumer);
+        } catch (RuntimeException e) {
+            if (e.getCause() != null) {
+                throw new PlcSegmentationException(e.getCause());
+            }
+            throw new PlcSegmentationException(e);
+        }
+    }
+
+    private void send(RequestTransactionManager tm, ConversationContext<C> context, Supplier<T> generator, Predicate<T> predicate, Consumer<T> callback) throws PlcSegmentationException {
+        C request = wrap(generator.get());
+
+        RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
+        transaction.submit(() -> context.sendRequest(request)
+            .expectResponse(frameType, timeout)
+            .unwrap(this::unwrap)
+            .check(predicate)
+            .onError((payload, error) -> transaction.endRequest())
+            .handle(payload -> {
+                callback.accept(payload);
+                transaction.endRequest();
+            })
+        );
+    }
+
+    protected abstract T unwrap(C frame);
+
+    protected abstract C wrap(T payload) throws PlcSegmentationException;
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/accumulator/ByteStorage.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/accumulator/ByteStorage.java
new file mode 100644
index 0000000..1f143f2
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/accumulator/ByteStorage.java
@@ -0,0 +1,59 @@
+package org.apache.plc4x.java.can.api.segmentation.accumulator;
+
+import org.apache.plc4x.java.canopen.readwrite.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+
+public class ByteStorage<T> implements Storage<T, byte[]> {
+
+    private final List<byte[]> segments = new ArrayList<>();
+    private final Function<T, byte[]> extractor;
+    private long size = 0;
+
+    public ByteStorage(Function<T, byte[]> extractor) {
+        this.extractor = extractor;
+    }
+
+    @Override
+    public void append(T frame) {
+        segments.add(extractor.apply(frame));
+        size += segments.get(segments.size() - 1).length;
+    }
+
+    public long size() {
+        return size;
+    }
+
+    @Override
+    public byte[] get() {
+        Optional<byte[]> collect = segments.stream().reduce((b1, b2) -> {
+            byte[] combined = new byte[b1.length + b2.length];
+            System.arraycopy(b1, 0, combined, 0, b1.length);
+            System.arraycopy(b2, 0, combined, b1.length, b2.length);
+            return combined;
+        });
+        return collect.orElse(new byte[0]);
+    }
+
+    public static class SDOUploadStorage extends ByteStorage<SDOResponse> {
+        public SDOUploadStorage() {
+            super((sdoResponse -> {
+                if (sdoResponse instanceof SDOSegmentUploadResponse) {
+                    return ((SDOSegmentUploadResponse) sdoResponse).getData();
+                }
+                if (sdoResponse instanceof SDOInitiateUploadResponse) {
+                    SDOInitiateUploadResponse initiate = (SDOInitiateUploadResponse) sdoResponse;
+
+                    if (initiate.getPayload() instanceof SDOInitiateExpeditedUploadResponse) {
+                        return ((SDOInitiateExpeditedUploadResponse) initiate.getPayload()).getData();
+                    }
+                }
+                return new byte[0];
+            }));
+        }
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/accumulator/Storage.java
similarity index 57%
copy from sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java
copy to sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/accumulator/Storage.java
index 8212bea..45c9567 100644
--- a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/api/segmentation/accumulator/Storage.java
@@ -16,21 +16,35 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 */
-package org.apache.plc4x.java.can;
-
-import org.apache.plc4x.java.PlcDriverManager;
-import org.apache.plc4x.java.api.PlcConnection;
+package org.apache.plc4x.java.can.api.segmentation.accumulator;
 
 /**
- * Here we begin .. ;-)
+ * A storage which is called for each received segment.
+ *
+ * @param <T> Type of frame.
+ * @param <R> Type of result.
  */
-public class Main {
-
-    public static void main(String[] args) throws Exception {
-        PlcDriverManager driverManager = new PlcDriverManager();
-
-        PlcConnection connection = driverManager.getConnection("canopen:javacan://vcan0?nodeId=11");
-
-    }
+public interface Storage<T, R> {
+
+    /**
+     * Appends segmented frame.
+     *
+     * @param frame Segmented frame.
+     */
+    void append(T frame);
+
+    /**
+     * Gets accumulated size of stored data.
+     *
+     * @return Occupied memory in bytes.
+     */
+    long size();
+
+    /**
+     * Retrieves final result from segmented payload.
+     *
+     * @return Assembled result.
+     */
+    R get();
 
 }
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java
index 214794d..fcb7194 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java
@@ -42,8 +42,8 @@ public class CANConfiguration implements Configuration, CANTransportConfiguratio
         return hearbeat;
     }
 
-    public void setHearbeat(boolean hearbeat) {
-        this.hearbeat = hearbeat;
+    public void setHeartbeat(boolean heartbeat) {
+        this.hearbeat = heartbeat;
     }
 
 }
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/context/CANOpenDriverContext.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/context/CANOpenDriverContext.java
new file mode 100644
index 0000000..31c0028
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/context/CANOpenDriverContext.java
@@ -0,0 +1,9 @@
+package org.apache.plc4x.java.can.context;
+
+import org.apache.plc4x.java.can.listener.CompositeCallback;
+
+public class CANOpenDriverContext extends CANDriverContext {
+
+    public final static CompositeCallback CALLBACK = new CompositeCallback();
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenField.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenField.java
new file mode 100644
index 0000000..6458848
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenField.java
@@ -0,0 +1,51 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.can.field;
+
+import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.PlcField;
+
+import java.util.regex.Pattern;
+
+/**
+ * Generic field type which defines node address and address pattern (index/subindex).
+ */
+public abstract class CANOpenField implements PlcField {
+
+    public static final Pattern ADDRESS_PATTERN = Pattern.compile("(?:(0[xX](?<indexHex>[0-9a-fA-F]+))|(?<index>\\d+))/(?:(0[xX](?<subIndexHex>[0-9a-fA-F]+))|(?<subIndex>\\d+)):(?<canDataType>\\w+)(\\[(?<numberOfElements>\\d)])?");
+    public static final Pattern NODE_PATTERN = Pattern.compile("(?<nodeId>\\d+)");
+
+    private final int nodeId;
+
+    public CANOpenField(int nodeId) {
+        this.nodeId = nodeId;
+    }
+
+    public int getNodeId() {
+        return nodeId;
+    }
+
+    public static CANOpenField of(String addressString) throws PlcInvalidFieldException {
+        if (CANOpenSDOField.matches(addressString)) {
+            return CANOpenSDOField.of(addressString);
+        }
+
+        throw new PlcInvalidFieldException("Unable to parse address: " + addressString);
+    }
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenFieldHandler.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenFieldHandler.java
new file mode 100644
index 0000000..cf37533
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenFieldHandler.java
@@ -0,0 +1,58 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.can.field;
+
+import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.value.PlcList;
+import org.apache.plc4x.java.api.value.PlcString;
+import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.spi.connection.DefaultPlcFieldHandler;
+import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
+
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+public class CANOpenFieldHandler extends DefaultPlcFieldHandler implements PlcFieldHandler {
+
+    @Override
+    public PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
+        return CANOpenField.of(fieldQuery);
+    }
+
+    @Override
+    public PlcValue encodeString(PlcField field, Object[] values) {
+        CANOpenSDOField coField = (CANOpenSDOField) field;
+        String[] strings = (String[]) values;
+
+        switch (coField.getCanOpenDataType()) {
+            case VISIBLE_STRING:
+            case OCTET_STRING:
+            case UNICODE_STRING:
+                if (values.length == 1) {
+                    return new PlcString(strings[0]);
+                } else {
+                    return new PlcList(Arrays.stream(strings).map(PlcString::new).collect(Collectors.toList()));
+                }
+        }
+
+        throw new PlcRuntimeException("Invalid encoder for type " + coField.getCanOpenDataType().name());
+    }
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenNMTField.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenNMTField.java
new file mode 100644
index 0000000..83bba15
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenNMTField.java
@@ -0,0 +1,58 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.can.field;
+
+import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CANOpenNMTField extends CANOpenField {
+
+    public static final Pattern ADDRESS_PATTERN = Pattern.compile("NMT|NMT:" + CANOpenField.NODE_PATTERN);
+
+    public CANOpenNMTField(int node) {
+        super(node);
+    }
+
+    public boolean isWildcard() {
+        return getNodeId() == 0;
+    }
+
+    public static boolean matches(String addressString) {
+        return ADDRESS_PATTERN.matcher(addressString).matches();
+    }
+
+    public static Matcher getMatcher(String addressString) throws PlcInvalidFieldException {
+        Matcher matcher = ADDRESS_PATTERN.matcher(addressString);
+        if (matcher.matches()) {
+            return matcher;
+        }
+
+        throw new PlcInvalidFieldException(addressString, ADDRESS_PATTERN);
+    }
+
+    public static CANOpenNMTField of(String addressString) {
+        Matcher matcher = getMatcher(addressString);
+        int nodeId = Integer.parseInt(matcher.group("nodeId"));
+
+        return new CANOpenNMTField(nodeId);
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenSDOField.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenSDOField.java
new file mode 100644
index 0000000..86882c0
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenSDOField.java
@@ -0,0 +1,89 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.can.field;
+
+import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.canopen.readwrite.types.CANOpenDataType;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CANOpenSDOField extends CANOpenField {
+
+    public static final Pattern ADDRESS_PATTERN = Pattern.compile("SDO:" + CANOpenField.NODE_PATTERN + ":" + CANOpenField.ADDRESS_PATTERN);
+    private final short index;
+    private final short subIndex;
+    private final CANOpenDataType canOpenDataType;
+
+    public CANOpenSDOField(int node, short index, short subIndex, CANOpenDataType canOpenDataType) {
+        super(node);
+        this.index = index;
+        this.subIndex = subIndex;
+        this.canOpenDataType = canOpenDataType;
+    }
+
+    public short getIndex() {
+        return index;
+    }
+
+    public short getSubIndex() {
+        return subIndex;
+    }
+
+    public CANOpenDataType getCanOpenDataType() {
+        return canOpenDataType;
+    }
+
+    public static boolean matches(String addressString) {
+        return ADDRESS_PATTERN.matcher(addressString).matches();
+    }
+
+    public static Matcher getMatcher(String addressString) throws PlcInvalidFieldException {
+        Matcher matcher = ADDRESS_PATTERN.matcher(addressString);
+        if (matcher.matches()) {
+            return matcher;
+        }
+
+        throw new PlcInvalidFieldException(addressString, ADDRESS_PATTERN);
+    }
+
+    public static CANOpenSDOField of(String addressString) {
+        Matcher matcher = getMatcher(addressString);
+        int nodeId = Integer.parseInt(matcher.group("nodeId"));
+
+        short index = parseHex(matcher.group("indexHex"), matcher.group("index"));
+        short subIndex = parseHex(matcher.group("subIndexHex"), matcher.group("subIndex"));
+
+        String canDataTypeString = matcher.group("canDataType");
+        CANOpenDataType canOpenDataType = CANOpenDataType.valueOf(canDataTypeString);
+
+        //String numberOfElementsString = matcher.group("numberOfElements");
+        //Integer numberOfElements = numberOfElementsString != null ? Integer.valueOf(numberOfElementsString) : null;
+
+        return new CANOpenSDOField(nodeId, index, subIndex, canOpenDataType);
+    }
+
+    private static Short parseHex(String hex, String dec) {
+        if (hex != null) {
+            return Short.parseShort(hex, 16);
+        }
+        return Short.parseShort(dec);
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/CANOpenHelper.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/CANOpenHelper.java
index 1a9a346..3f1e22a 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/CANOpenHelper.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/CANOpenHelper.java
@@ -1,9 +1,12 @@
 package org.apache.plc4x.java.can.helper;
 
+import org.apache.plc4x.java.api.value.PlcValue;
 import org.apache.plc4x.java.canopen.readwrite.SDOInitiateExpeditedUploadResponse;
 import org.apache.plc4x.java.canopen.readwrite.SDOInitiateUploadResponsePayload;
 import org.apache.plc4x.java.canopen.readwrite.SDOSegmentUploadResponse;
 import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService;
+import org.apache.plc4x.java.spi.generation.ParseException;
+import org.apache.plc4x.java.spi.generation.ReadBuffer;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 
 import static org.apache.plc4x.java.spi.generation.StaticHelper.COUNT;
@@ -26,4 +29,15 @@ public class CANOpenHelper {
         // NOOP - a placeholder to let mspec compile
     }
 
+    public static Object parseString(ReadBuffer io, int length, String charset) {
+        return io.readString(8 * length, charset);
+    }
+
+    public static void serializeString(WriteBuffer io, PlcValue value, String charset) throws ParseException {
+        io.writeString(8, charset, value.getString());
+    }
+
+    public static byte[] parseByteArray(ReadBuffer io, Integer length) {
+        return new byte[0];
+    }
 }
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java
index 2ad7a1c..9e549de 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java
@@ -6,6 +6,13 @@ import org.apache.plc4x.java.spi.generation.WriteBuffer;
 
 public class HeaderParser {
 
+    public static final int EFF_FLAG = 0b10000000_00000000_00000000_00000000;
+    public static final int RTR_FLAG = 0b01000000_00000000_00000000_00000000;
+    public static final int ERR_FLAG = 0b00100000_00000000_00000000_00000000;
+    public static final int SFF_MASK = 0b00000000_00000000_00000111_11111111;
+    public static final int EFF_MASK = 0b00011111_11111111_11111111_11111111;
+    public static final int ERR_MASK = EFF_MASK;
+
     public static final int EXTENDED_FRAME_FORMAT_FLAG = 0x80000000;
 
     public static final int REMOTE_TRANSMISSION_FLAG = 0x40000000;
@@ -17,10 +24,10 @@ public class HeaderParser {
     public static final int EXTENDED_FORMAT_IDENTIFIER_MASK = 0x1fffffff;
 
     public static int readIdentifier(int identifier) {
-        if ((identifier & EXTENDED_FORMAT_IDENTIFIER_MASK) == 0) {
-            return identifier & STANDARD_FORMAT_IDENTIFIER_MASK;
+        if ((isExtended(identifier))) {
+            return identifier & EXTENDED_FORMAT_IDENTIFIER_MASK;
         }
-        return identifier & EXTENDED_FORMAT_IDENTIFIER_MASK;
+        return identifier & STANDARD_FORMAT_IDENTIFIER_MASK;
     }
 
     public static void writeIdentifier(WriteBuffer buffer, SocketCANFrame frame) throws ParseException {
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/listener/Callback.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/listener/Callback.java
new file mode 100644
index 0000000..74d8764
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/listener/Callback.java
@@ -0,0 +1,8 @@
+package org.apache.plc4x.java.can.listener;
+
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
+
+public interface Callback {
+    void receive(SocketCANFrame frame);
+}
+
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/listener/CompositeCallback.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/listener/CompositeCallback.java
new file mode 100644
index 0000000..3ff5454
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/listener/CompositeCallback.java
@@ -0,0 +1,25 @@
+package org.apache.plc4x.java.can.listener;
+
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public class CompositeCallback implements Callback {
+
+    private List<Callback> callbacks = new CopyOnWriteArrayList<>();
+
+    @Override
+    public void receive(SocketCANFrame frame) {
+        callbacks.forEach(callback -> callback.receive(frame));
+    }
+
+    public boolean addCallback(Callback callback) {
+        return callbacks.add(callback);
+    }
+
+    public boolean removeCallback(Callback callback) {
+        return callbacks.remove(callback);
+    }
+}
+
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
index fa6dab2..b5aa34e 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
@@ -18,34 +18,58 @@ under the License.
 */
 package org.apache.plc4x.java.can.protocol;
 
+import org.apache.plc4x.java.api.messages.*;
+import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.apache.plc4x.java.api.value.PlcNull;
+import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.can.api.CANFrame;
+import org.apache.plc4x.java.can.api.conversation.canopen.CANConversation;
+import org.apache.plc4x.java.can.api.conversation.canopen.CANOpenConversation;
+import org.apache.plc4x.java.can.api.conversation.canopen.SDODownloadConversation;
+import org.apache.plc4x.java.can.api.conversation.canopen.SDOUploadConversation;
 import org.apache.plc4x.java.can.configuration.CANConfiguration;
-import org.apache.plc4x.java.canopen.readwrite.CANOpenHeartbeatPayload;
-import org.apache.plc4x.java.canopen.readwrite.CANOpenPayload;
+import org.apache.plc4x.java.can.context.CANOpenDriverContext;
+import org.apache.plc4x.java.can.field.CANOpenField;
+import org.apache.plc4x.java.can.field.CANOpenSDOField;
+import org.apache.plc4x.java.can.socketcan.SocketCANConversation;
+import org.apache.plc4x.java.canopen.readwrite.*;
 import org.apache.plc4x.java.canopen.readwrite.io.CANOpenHeartbeatPayloadIO;
 import org.apache.plc4x.java.canopen.readwrite.io.CANOpenPayloadIO;
+import org.apache.plc4x.java.canopen.readwrite.io.DataItemIO;
 import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService;
 import org.apache.plc4x.java.canopen.readwrite.types.NMTState;
 import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
 import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
 import org.apache.plc4x.java.spi.configuration.HasConfiguration;
+import org.apache.plc4x.java.spi.context.DriverContext;
 import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.ReadBuffer;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
+import org.apache.plc4x.java.spi.messages.*;
+import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
 import org.apache.plc4x.java.spi.transaction.RequestTransactionManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Timer;
 import java.util.TimerTask;
+import java.util.concurrent.CompletableFuture;
 
 public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> implements HasConfiguration<CANConfiguration> {
 
+    private static final Duration REQUEST_TIMEOUT = Duration.ofSeconds(10L);
     private Logger logger = LoggerFactory.getLogger(CANOpenProtocolLogic.class);
 
     private CANConfiguration configuration;
     private RequestTransactionManager tm;
     private Timer heartbeat;
+    private CANOpenDriverContext canContext;
+    private CANConversation<CANFrame> conversation;
 
     @Override
     public void setConfiguration(CANConfiguration configuration) {
@@ -55,11 +79,23 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
     }
 
     @Override
+    public void setDriverContext(DriverContext driverContext) {
+        super.setDriverContext(driverContext);
+        this.canContext = (CANOpenDriverContext) driverContext;
+
+        // Initialize Transaction Manager.
+        // Until the number of concurrent requests is successfully negotiated we set it to a
+        // maximum of only one request being able to be sent at a time. During the login process
+        // No concurrent requests can be sent anyway. It will be updated when receiving the
+        // S7ParameterSetupCommunication response.
+        this.tm = new RequestTransactionManager(1);
+    }
+
+    @Override
     public void onConnect(ConversationContext<SocketCANFrame> context) {
         try {
             if (configuration.isHeartbeat()) {
                 context.sendToWire(createFrame(new CANOpenHeartbeatPayload(NMTState.BOOTED_UP)));
-                context.fireConnected();
 
                 this.heartbeat = new Timer();
                 this.heartbeat.scheduleAtFixedRate(new TimerTask() {
@@ -73,15 +109,106 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
                     }
                 }, 5000, 5000);
             }
+            context.fireConnected();
         } catch (ParseException e) {
             e.printStackTrace();
         }
     }
 
+    @Override
+    public void setContext(ConversationContext<SocketCANFrame> context) {
+        super.setContext(context);
+        this.conversation = new SocketCANConversation(tm, context);
+    }
+
     private SocketCANFrame createFrame(CANOpenHeartbeatPayload state) throws ParseException {
-        WriteBuffer buffer = new WriteBuffer(state.getLengthInBytes());
+        WriteBuffer buffer = new WriteBuffer(state.getLengthInBytes(), true);
         CANOpenHeartbeatPayloadIO.staticSerialize(buffer, state);
-        return new SocketCANFrame(cobId(CANOpenService.HEARTBEAT), buffer.getData());
+        return new SocketCANFrame(cobId(configuration.getNodeId(), CANOpenService.HEARTBEAT), buffer.getData());
+    }
+
+    public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
+        CompletableFuture<PlcWriteResponse> response = new CompletableFuture<>();
+        if (writeRequest.getFieldNames().size() != 1) {
+            response.completeExceptionally(new IllegalArgumentException("Unsupported field"));
+            return response;
+        }
+
+        PlcField field = writeRequest.getFields().get(0);
+        if (!(field instanceof CANOpenField)) {
+            response.completeExceptionally(new IllegalArgumentException("Only CANOpenField instances are supported"));
+            return response;
+        }
+
+        if (!(field instanceof CANOpenSDOField)) {
+            response.completeExceptionally(new IllegalArgumentException("Only CANOpenSDOField instances are supported"));
+            return response;
+        };
+
+        writeInternally((InternalPlcWriteRequest) writeRequest, (CANOpenSDOField) field, response);
+        return response;
+    }
+
+    private void writeInternally(InternalPlcWriteRequest writeRequest, CANOpenSDOField field, CompletableFuture<PlcWriteResponse> response) {
+        CANOpenConversation<CANFrame> canopen = new CANOpenConversation<>(field.getNodeId(), conversation);
+
+        PlcValue writeValue = writeRequest.getPlcValues().get(0);
+
+        SDODownloadConversation<CANFrame> download = canopen.sdo().download(new IndexAddress(field.getIndex(), field.getSubIndex()), writeValue, field.getCanOpenDataType());
+        try {
+            download.execute((value, error) -> {
+                String fieldName = writeRequest.getFieldNames().iterator().next();
+                Map<String, PlcResponseCode> fields = new HashMap<>();
+                fields.put(fieldName, PlcResponseCode.OK);
+                response.complete(new DefaultPlcWriteResponse(writeRequest, fields));
+            });
+        } catch (Exception e) {
+            response.completeExceptionally(e);
+        }
+    }
+
+    public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
+        CompletableFuture<PlcReadResponse> response = new CompletableFuture<>();
+        if (readRequest.getFieldNames().size() != 1) {
+            response.completeExceptionally(new IllegalArgumentException("SDO requires single field to be read"));
+            return response;
+        }
+
+        PlcField field = readRequest.getFields().get(0);
+        if (!(field instanceof CANOpenField)) {
+            response.completeExceptionally(new IllegalArgumentException("Only CANOpenField instances are supported"));
+            return response;
+        }
+
+        if (!(field instanceof CANOpenSDOField)) {
+            response.completeExceptionally(new IllegalArgumentException("Only CANOpenSDOField instances are supported"));
+            return response;
+        };
+
+        readInternally((InternalPlcReadRequest) readRequest, (CANOpenSDOField) field, response);
+        return response;
+    }
+
+    @Override
+    public CompletableFuture<PlcSubscriptionResponse> subscribe(PlcSubscriptionRequest subscriptionRequest) {
+        ((InternalPlcSubscriptionRequest) subscriptionRequest).getSubscriptionFields().get(0).getPlcSubscriptionType();
+        return super.subscribe(subscriptionRequest);
+    }
+
+    private void readInternally(InternalPlcReadRequest readRequest, CANOpenSDOField field, CompletableFuture<PlcReadResponse> response) {
+        CANOpenConversation<CANFrame> canopen = new CANOpenConversation<>(field.getNodeId(), conversation);
+
+        SDOUploadConversation<CANFrame> upload = canopen.sdo().upload(new IndexAddress(field.getIndex(), field.getSubIndex()), field.getCanOpenDataType());
+        try {
+            upload.execute((value, error) -> {
+                String fieldName = readRequest.getFieldNames().iterator().next();
+                Map<String, ResponseItem<PlcValue>> fields = new HashMap<>();
+                fields.put(fieldName, new ResponseItem<>(PlcResponseCode.OK, value));
+                response.complete(new DefaultPlcReadResponse(readRequest, fields));
+            });
+        } catch (Exception e) {
+            response.completeExceptionally(e);
+        }
     }
 
     @Override
@@ -89,6 +216,8 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
         CANOpenService service = serviceId(msg.getIdentifier());
         CANOpenPayload payload = CANOpenPayloadIO.staticParse(new ReadBuffer(msg.getData()), service);
 
+        CANOpenDriverContext.CALLBACK.receive(msg);
+
         if (service != null) {
             logger.info("Decoded CANOpen {} from {}, message {}", service, Math.abs(service.getMin() - msg.getIdentifier()), payload);
         } else {
@@ -118,18 +247,18 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
         }
     }
 
-    private int cobId(CANOpenService service) {
+    private int cobId(int nodeId, CANOpenService service) {
         // form 32 bit socketcan identifier
-        return (configuration.getNodeId() << 24) & 0xff000000 |
+        return (nodeId << 24) & 0xff000000 |
             (service.getValue() << 16 ) & 0x00ff0000;
     }
 
-    private CANOpenService serviceId(int nodeId) {
+    private CANOpenService serviceId(int cobId) {
         // form 32 bit socketcan identifier
-        CANOpenService service = CANOpenService.valueOf((byte) (nodeId >> 7));
+        CANOpenService service = CANOpenService.valueOf((byte) (cobId >> 7));
         if (service == null) {
             for (CANOpenService val : CANOpenService.values()) {
-                if (val.getMin() > nodeId && val.getMax() < nodeId) {
+                if (val.getMin() > cobId && val.getMax() < cobId) {
                     return val;
                 }
             }
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/segmentation/CANOpenSegmentation.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/segmentation/CANOpenSegmentation.java
new file mode 100644
index 0000000..afea76e
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/segmentation/CANOpenSegmentation.java
@@ -0,0 +1,86 @@
+package org.apache.plc4x.java.can.protocol.segmentation;
+
+import org.apache.plc4x.java.can.api.segmentation.Segmentation;
+import org.apache.plc4x.java.can.api.segmentation.accumulator.Storage;
+import org.apache.plc4x.java.canopen.readwrite.CANOpenPayload;
+import org.apache.plc4x.java.canopen.readwrite.io.CANOpenPayloadIO;
+import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService;
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.spi.generation.ParseException;
+import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.apache.plc4x.java.spi.generation.WriteBuffer;
+
+import java.time.Duration;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+
+/**
+ * A basic utility to execute segmented operations.
+ */
+public class CANOpenSegmentation<R> extends Segmentation<SocketCANFrame, CANOpenPayload, R> {
+
+    private final CANOpenService service;
+    private final int node;
+
+    public CANOpenSegmentation(CANOpenService service, int node, Storage<CANOpenPayload, R> storage) {
+        super(SocketCANFrame.class, Duration.ofSeconds(10L), storage);
+
+        this.service = service;
+        this.node = node;
+    }
+
+    public CANOpenSegmentation<R> begin(Supplier<CANOpenPayload> request, Predicate<CANOpenPayload> requestAnswer) {
+        super.begin(request, requestAnswer);
+        return this;
+    }
+
+    public CANOpenSegmentation<R> step(Function<CANOpenPayload, CANOpenPayload> step, Predicate<CANOpenPayload> stepAnswer) {
+        super.step(step, stepAnswer);
+        return this;
+    }
+
+    public CANOpenSegmentation<R> end(Predicate<CANOpenPayload> finalStep, Consumer<List<CANOpenPayload>> callback) {
+        super.end(finalStep, callback);
+        return this;
+    }
+
+    protected CANOpenPayload unwrap(SocketCANFrame frame) {
+        return unsecure(() -> CANOpenPayloadIO.staticParse(new ReadBuffer(frame.getData()), serviceId(frame.getIdentifier())));
+    }
+
+    private <T> T unsecure(Callable<T> statement) {
+        try {
+            return statement.call();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    protected SocketCANFrame wrap(CANOpenPayload payload) {
+        try {
+            WriteBuffer io = new WriteBuffer(payload.getLengthInBytes(), true);
+            payload.getMessageIO().serialize(io, payload);
+            return new SocketCANFrame(service.getMin() + node, io.getData());
+        } catch (ParseException e) {
+            throw new RuntimeException("Could not construct segmented frame", e);
+        }
+    }
+
+    private CANOpenService serviceId(int cobId) {
+        // form 32 bit socketcan identifier
+        CANOpenService service = CANOpenService.valueOf((byte) (cobId >> 7));
+        if (service == null) {
+            for (CANOpenService val : CANOpenService.values()) {
+                if (val.getMin() > cobId && val.getMax() < cobId) {
+                    return val;
+                }
+            }
+        }
+        return service;
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/socketcan/SocketCANConversation.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/socketcan/SocketCANConversation.java
new file mode 100644
index 0000000..8b01c2a
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/socketcan/SocketCANConversation.java
@@ -0,0 +1,49 @@
+package org.apache.plc4x.java.can.socketcan;
+
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.apache.plc4x.java.can.api.CANFrame;
+import org.apache.plc4x.java.can.api.conversation.canopen.CANConversation;
+import org.apache.plc4x.java.can.api.conversation.canopen.CANFrameBuilder;
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.spi.ConversationContext;
+import org.apache.plc4x.java.spi.ConversationContext.SendRequestContext;
+import org.apache.plc4x.java.spi.transaction.RequestTransactionManager;
+import org.apache.plc4x.java.spi.transaction.RequestTransactionManager.RequestTransaction;
+
+import java.time.Duration;
+import java.util.function.BiConsumer;
+
+public class SocketCANConversation implements CANConversation<CANFrame> {
+
+    private final RequestTransactionManager tm;
+    private final ConversationContext<SocketCANFrame> context;
+
+    public SocketCANConversation(RequestTransactionManager tm, ConversationContext<SocketCANFrame> context) {
+        this.tm = tm;
+        this.context = context;
+    }
+
+    @Override
+    public CANFrameBuilder<CANFrame> frameBuilder() {
+        return new SocketCANFrameBuilder();
+    }
+
+    @Override
+    public void send(CANFrame frame, BiConsumer<RequestTransaction, SendRequestContext<CANFrame>> callback) {
+        if (frame instanceof SocketCANDelegateFrame) {
+            RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
+
+            ConversationContext.SendRequestContext<CANFrame> ctx = context.sendRequest(((SocketCANDelegateFrame) frame).getFrame())
+                .expectResponse(SocketCANFrame.class, Duration.ofSeconds(10L))
+//                .onError((response, error) -> {
+//                    System.err.println("Unexpected frame " + response + " " + error);
+//                })
+                .unwrap(SocketCANDelegateFrame::new);
+            //return CompletableFuture.completedFuture(new SocketCANTransactionContext<>(transaction, ctx));
+            callback.accept(transaction, ctx);
+            return;
+        }
+        throw new PlcRuntimeException("Unsupported frame type " + frame);
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/socketcan/SocketCANDelegateFrame.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/socketcan/SocketCANDelegateFrame.java
new file mode 100644
index 0000000..4bf323e
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/socketcan/SocketCANDelegateFrame.java
@@ -0,0 +1,43 @@
+package org.apache.plc4x.java.can.socketcan;
+
+import org.apache.plc4x.java.can.api.CANFrame;
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
+
+public class SocketCANDelegateFrame implements CANFrame {
+
+    private final SocketCANFrame frame;
+
+    public SocketCANDelegateFrame(SocketCANFrame frame) {
+        this.frame = frame;
+    }
+
+    @Override
+    public int getIdentifier() {
+        return frame.getIdentifier();
+    }
+
+    @Override
+    public boolean getExtended() {
+        return frame.getExtended();
+    }
+
+    @Override
+    public boolean getRemote() {
+        return frame.getRemote();
+    }
+
+    @Override
+    public boolean getError() {
+        return frame.getError();
+    }
+
+    @Override
+    public byte[] getData() {
+        return frame.getData();
+    }
+
+    public SocketCANFrame getFrame() {
+        return frame;
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/socketcan/SocketCANFrameBuilder.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/socketcan/SocketCANFrameBuilder.java
new file mode 100644
index 0000000..b13cd17
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/socketcan/SocketCANFrameBuilder.java
@@ -0,0 +1,29 @@
+package org.apache.plc4x.java.can.socketcan;
+
+import org.apache.plc4x.java.can.api.CANFrame;
+import org.apache.plc4x.java.can.api.conversation.canopen.CANFrameBuilder;
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
+
+public class SocketCANFrameBuilder implements CANFrameBuilder<CANFrame> {
+
+    private int node;
+    private byte[] data;
+
+    @Override
+    public CANFrameBuilder<CANFrame> node(int node) {
+        this.node = node;
+        return this;
+    }
+
+    @Override
+    public CANFrameBuilder<CANFrame> data(byte[] data) {
+        this.data = data;
+        return this;
+    }
+
+    @Override
+    public CANFrame build() {
+        return new SocketCANDelegateFrame(new SocketCANFrame(node, data));
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java
index 8212bea..f5550ae 100644
--- a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java
@@ -20,6 +20,15 @@ package org.apache.plc4x.java.can;
 
 import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+import org.apache.plc4x.java.api.messages.PlcWriteResponse;
+import org.apache.plc4x.java.can.context.CANOpenDriverContext;
+import org.apache.plc4x.java.can.listener.Callback;
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
+
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
 
 /**
  * Here we begin .. ;-)
@@ -29,8 +38,47 @@ public class Main {
     public static void main(String[] args) throws Exception {
         PlcDriverManager driverManager = new PlcDriverManager();
 
+        CANOpenDriverContext.CALLBACK.addCallback(new Callback() {
+            @Override
+            public void receive(SocketCANFrame frame) {
+                //System.err.println("Received frame " + frame);
+            }
+        });
+
         PlcConnection connection = driverManager.getConnection("canopen:javacan://vcan0?nodeId=11");
 
+        String value = "abcdef"; //UUID.randomUUID().toString();
+        CompletableFuture<? extends PlcWriteResponse> response = connection.writeRequestBuilder()
+            .addItem("foo", "SDO:13:0x2000/0x0:VISIBLE_STRING", value)
+            .build().execute();
+
+        response.whenComplete((writeReply, writeError) -> {
+            System.out.println("====================================");
+            if (writeError != null) {
+                System.out.println("Error ");
+                writeError.printStackTrace();
+            } else {
+                System.out.println("Result " + writeReply.getResponseCode("foo") + " " + value);
+
+                PlcReadRequest.Builder builder = connection.readRequestBuilder();
+                builder.addItem("foo", "SDO:13:0x2000/0x0:VISIBLE_STRING");
+                CompletableFuture<? extends PlcReadResponse> future = builder.build().execute();
+                future.whenComplete((readReply, readError) -> {
+                    System.out.println("====================================");
+                    if (readError != null) {
+                        System.out.println("Error ");
+                        readError.printStackTrace();
+                    } else {
+                        System.out.println("Result " + readReply.getString("foo"));
+                    }
+                });
+            }
+        });
+
+
+//        while (true) {
+
+//        }
     }
 
 }
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/field/CANOpenFieldSDOTest.java
similarity index 56%
copy from sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java
copy to sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/field/CANOpenFieldSDOTest.java
index 8212bea..a6ceae9 100644
--- a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/field/CANOpenFieldSDOTest.java
@@ -16,21 +16,23 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 */
-package org.apache.plc4x.java.can;
+package org.apache.plc4x.java.can.field;
 
-import org.apache.plc4x.java.PlcDriverManager;
-import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.canopen.readwrite.types.CANOpenDataType;
+import org.junit.jupiter.api.Test;
 
-/**
- * Here we begin .. ;-)
- */
-public class Main {
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
-    public static void main(String[] args) throws Exception {
-        PlcDriverManager driverManager = new PlcDriverManager();
+class CANOpenFieldSDOTest {
 
-        PlcConnection connection = driverManager.getConnection("canopen:javacan://vcan0?nodeId=11");
+    @Test
+    public void testFieldSyntax() {
+        final CANOpenSDOField canField = CANOpenSDOField.of("SDO:20:0x30/40:BOOLEAN");
 
+        assertEquals(20, canField.getNodeId());
+        assertEquals(0x30, canField.getIndex());
+        assertEquals(40, canField.getSubIndex());
+        assertEquals(CANOpenDataType.BOOLEAN, canField.getCanOpenDataType());
     }
 
-}
+}
\ No newline at end of file
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/field/CANOpenNMTFieldTest.java
similarity index 50%
copy from sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java
copy to sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/field/CANOpenNMTFieldTest.java
index 214794d..3f48fc1 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/field/CANOpenNMTFieldTest.java
@@ -16,34 +16,35 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 */
-package org.apache.plc4x.java.can.configuration;
+package org.apache.plc4x.java.can.field;
 
-import org.apache.plc4x.java.spi.configuration.Configuration;
-import org.apache.plc4x.java.spi.configuration.annotations.ConfigurationParameter;
-import org.apache.plc4x.java.transport.socketcan.CANTransportConfiguration;
+import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.junit.jupiter.api.Test;
 
-public class CANConfiguration implements Configuration, CANTransportConfiguration {
+import static org.junit.jupiter.api.Assertions.*;
 
-    @ConfigurationParameter
-    private int nodeId;
+class CANOpenNMTFieldTest {
 
-    @ConfigurationParameter
-    private boolean hearbeat;
+    @Test
+    public void testNodeSyntax() {
+        final CANOpenNMTField canField = CANOpenNMTField.of("NMT:20");
 
-    public int getNodeId() {
-        return nodeId;
+        assertEquals(20, canField.getNodeId());
+        assertFalse(canField.isWildcard());
     }
 
-    public void setNodeId(int nodeId) {
-        this.nodeId = nodeId;
-    }
+    @Test
+    public void testWildcardSyntax() {
+        final CANOpenNMTField canField = CANOpenNMTField.of("NMT:0");
 
-    public boolean isHeartbeat() {
-        return hearbeat;
+        assertEquals(0, canField.getNodeId());
+        assertTrue(canField.isWildcard());
     }
 
-    public void setHearbeat(boolean hearbeat) {
-        this.hearbeat = hearbeat;
+
+    @Test
+    public void testInvalidSyntax() {
+        assertThrows(PlcInvalidFieldException.class, () -> CANOpenNMTField.of("NMT:"));
     }
 
-}
+}
\ No newline at end of file


[plc4x] 14/19: More tests of canopen payload.

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 71301c964cba10d3395a6a88e290612d0022baf0
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Tue Sep 1 18:13:32 2020 +0200

    More tests of canopen payload.
---
 .../src/main/resources/protocols/can/canopen.mspec | 67 +++++++++++++++++-----
 .../testsuite/CANOpenPayloadTestSuite.xml          | 41 +++++++++++++
 2 files changed, 94 insertions(+), 14 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/canopen.mspec b/protocols/can/src/main/resources/protocols/can/canopen.mspec
index 0c4f175..c929ae4 100644
--- a/protocols/can/src/main/resources/protocols/can/canopen.mspec
+++ b/protocols/can/src/main/resources/protocols/can/canopen.mspec
@@ -17,20 +17,21 @@
  * under the License.
  */
 
-[enum uint 4 'CANOpenService'
-    ['0b0000' BROADCAST   ]
-    ['0b0001' SYNC        ]
-    ['0b1110' NMT         ]
-    ['0b1100' SDO_REQUEST ]
-    ['0b1011' SDO_RESPONSE]
-    ['0b0011' TPDO_1]
-    ['0b0100' RPDO_1]
-    ['0b0101' TPDO_2]
-    ['0b0110' RPDO_2]
-    ['0b0111' TPDO_3]
-    ['0b1000' RPDO_3]
-    ['0b1001' TPDO_4]
-    ['0b1010' RPDO_4]
+[enum uint 4 'CANOpenService' [bit 'sdo', bit 'pdo', bit 'transmit', bit 'receive']
+    ['0b0000' BROADCAST    ['false', 'false', 'false', 'false'] ]
+    ['0b0001' SYNC         ['false', 'false', 'false', 'false'] ]
+    ['0b0010' TIME         ['false', 'false', 'false', 'false'] ]
+    ['0b1110' NMT          ['false', 'false', 'false', 'false'] ]
+    ['0b1100' SDO_REQUEST  ['true',  'false', 'false', 'true' ] ]
+    ['0b1011' SDO_RESPONSE ['true',  'false', 'true',  'false'] ]
+    ['0b0011' TPDO_1       ['false', 'true',  'true',  'false'] ]
+    ['0b0100' RPDO_1       ['false', 'true',  'false', 'true' ] ]
+    ['0b0101' TPDO_2       ['false', 'true',  'true',  'false'] ]
+    ['0b0110' RPDO_2       ['false', 'true',  'false', 'true' ] ]
+    ['0b0111' TPDO_3       ['false', 'true',  'true',  'false'] ]
+    ['0b1000' RPDO_3       ['false', 'true',  'false', 'true' ] ]
+    ['0b1001' TPDO_4       ['false', 'true',  'true',  'false'] ]
+    ['0b1010' RPDO_4       ['false', 'true',  'false', 'true' ] ]
 ]
 
 [enum uint 8 'NMTStateRequest'
@@ -55,6 +56,9 @@
             [reserved uint 1 '0x00']
             [simple uint 7 'node']
         ]
+        ['CANOpenService.TIME' CANOpenTimeSynchronization
+            [simple TimeOfDay 'timeOfDay']
+        ]
         ['CANOpenService.NMT' CANOpenNetworkPayload
             [enum NMTState 'state']
         ]
@@ -78,6 +82,30 @@
             [simple uint 8 'subindex']
             [array uint 8 'data' COUNT 'size']
         ]
+        ['CANOpenService.RPDO_1' CANOpenRPDO
+            [simple CANOpenPDO 'pdo' ['1', 'true']]
+        ]
+        ['CANOpenService.TPDO_1' CANOpenTPDO
+            [simple CANOpenPDO 'pdo' ['1', 'false']]
+        ]
+        ['CANOpenService.RPDO_2' CANOpenRPDO
+            [simple CANOpenPDO 'pdo' ['2', 'true']]
+        ]
+        ['CANOpenService.TPDO_2' CANOpenTPDO
+            [simple CANOpenPDO 'pdo' ['1', 'false']]
+        ]
+        ['CANOpenService.RPDO_3' CANOpenRPDO
+            [simple CANOpenPDO 'pdo' ['3', 'true']]
+        ]
+        ['CANOpenService.TPDO_3' CANOpenTPDO
+            [simple CANOpenPDO 'pdo' ['1', 'false']]
+        ]
+        ['CANOpenService.RPDO_4' CANOpenRPDO
+            [simple CANOpenPDO 'pdo' ['4', 'true']]
+        ]
+        ['CANOpenService.TPDO_4' CANOpenTPDO
+            [simple CANOpenPDO 'pdo' ['1', 'false']]
+        ]
     ]
 ]
 
@@ -90,3 +118,14 @@
     ['0x05' BLOCK_UPLOAD]
     ['0x06' BLOCK_DOWNLOAD]
 ]
+
+[type 'CANOpenPDO' [uint 2 'index', bit 'receive']
+
+]
+
+[type 'TimeOfDay'
+    // CiA 301 - section 7.1.6.5
+    [simple uint 28 'millis']
+    [reserved int 4 '0x00']
+    [simple uint 16 'days']
+]
\ No newline at end of file
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
index ecf224b..3188005 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
@@ -21,6 +21,47 @@
 
   <name>Tests of CANopen frames payload.</name>
 
+
+  <testcase>
+    <name>Time synchronization, payload: A017BD805034</name>
+    <!--
+    Initial test payload was A017BD835034, however it does not align with CANOpen spec or mapping on our side is wrong
+    -->
+    <raw>A017BD805034</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>TIME</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenTimeSynchronization className="org.apache.plc4x.java.canopen.readwrite.CANOpenTimeSynchronization">
+        <timeOfDay className="org.apache.plc4x.java.canopen.readwrite.TimeOfDay">
+          <millis>-663027446</millis>
+          <days>13392</days>
+        </timeOfDay>
+      </CANOpenTimeSynchronization>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Time synchronization, payload: 7019BE805034</name>
+    <!--
+    Initial test payload was 7019BE835034, however it does not align with CANOpen spec or mapping on our side is wrong
+    -->
+    <raw>7019BE805034</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>TIME</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenTimeSynchronization className="org.apache.plc4x.java.canopen.readwrite.CANOpenTimeSynchronization">
+        <timeOfDay className="org.apache.plc4x.java.canopen.readwrite.TimeOfDay">
+          <millis>-392494841</millis>
+          <days>13392</days>
+        </timeOfDay>
+      </CANOpenTimeSynchronization>
+    </xml>
+  </testcase>
+
   <testcase>
     <name>Network heartbeat, payload: 00</name>
     <raw>00</raw>


[plc4x] 03/19: Scratch of socketcan transport and can frame definitions.

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit fe7b9c1ab31b76d45bc63a20686b64d06f46dab8
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Tue Aug 18 00:40:25 2020 +0200

    Scratch of socketcan transport and can frame definitions.
---
 plc4j/transports/pom.xml                           |   1 +
 plc4j/transports/socketcan/pom.xml                 |  81 +++++++
 .../socketcan/CANTransportConfiguration.java       |  25 ++
 .../socketcan/SocketCANChannelFactory.java         |  70 ++++++
 .../transport/socketcan/SocketCANTransport.java    |  46 ++++
 .../socketcan/netty/SocketCANChannel.java          | 267 +++++++++++++++++++++
 .../socketcan/netty/SocketCANChannelConfig.java    |  31 +++
 .../socketcan/netty/address/SocketCANAddress.java  |  40 +++
 .../org.apache.plc4x.java.spi.transport.Transport  |  20 ++
 protocols/can/pom.xml                              |  43 ++++
 .../org/apache/plc4x/protocol/can/CANProtocol.java |  46 ++++
 ...e.plc4x.plugins.codegenerator.protocol.Protocol |  19 ++
 .../can/src/main/resources/protocols/can/can.mspec |  77 ++++++
 protocols/pom.xml                                  |   1 +
 sandbox/pom.xml                                    |   1 +
 sandbox/test-java-can-driver/pom.xml               | 133 ++++++++++
 .../org/apache/plc4x/java/can/CANPlcDriver.java    | 102 ++++++++
 .../java/can/configuration/CANConfiguration.java   |  26 ++
 .../plc4x/java/can/context/CANDriverContext.java   |  24 ++
 .../plc4x/java/can/field/CANFieldHandler.java      |  33 +++
 .../plc4x/java/can/protocol/CANProtocolLogic.java  |  51 ++++
 .../services/org.apache.plc4x.java.api.PlcDriver   |  19 ++
 .../test/java/org/apache/plc4x/java/can/Main.java  |  36 +++
 23 files changed, 1192 insertions(+)

diff --git a/plc4j/transports/pom.xml b/plc4j/transports/pom.xml
index 644bf4d..a07d9a3 100644
--- a/plc4j/transports/pom.xml
+++ b/plc4j/transports/pom.xml
@@ -37,6 +37,7 @@
     <module>pcap-replay</module>
     <module>pcap-shared</module>
     <module>raw-socket</module>
+    <module>socketcan</module>
     <module>serial</module>
     <module>tcp</module>
     <module>udp</module>
diff --git a/plc4j/transports/socketcan/pom.xml b/plc4j/transports/socketcan/pom.xml
new file mode 100644
index 0000000..0e28c7b
--- /dev/null
+++ b/plc4j/transports/socketcan/pom.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.plc4x</groupId>
+    <artifactId>plc4j-transports</artifactId>
+    <version>0.8.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>plc4j-transport-socketcan</artifactId>
+  <name>PLC4J: Transports: SocketCAN</name>
+  <description>Base classes needed to implement plc4x drivers based on SocketCAN connections.</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-spi</artifactId>
+      <version>0.8.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>tel.schich</groupId>
+      <artifactId>javacan</artifactId>
+      <version>2.1.0</version>
+    </dependency>
+
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-transport</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-buffer</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <!--
+       Generate an OSGI compatible MANIFEST file.
+     -->
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
+            <Bundle-Activator>org.apache.plc4x.java.osgi.TransportActivator</Bundle-Activator>
+            <Export-Service>org.apache.plc4x.java.spi.transport.Transport,org.apache.plc4x.java.transport.socketcan.SocketCANTransport</Export-Service>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/CANTransportConfiguration.java b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/CANTransportConfiguration.java
new file mode 100644
index 0000000..791b465
--- /dev/null
+++ b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/CANTransportConfiguration.java
@@ -0,0 +1,25 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.transport.socketcan;
+
+import org.apache.plc4x.java.spi.transport.TransportConfiguration;
+
+public interface CANTransportConfiguration extends TransportConfiguration {
+
+}
diff --git a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANChannelFactory.java b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANChannelFactory.java
new file mode 100644
index 0000000..f4c7cc7
--- /dev/null
+++ b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANChannelFactory.java
@@ -0,0 +1,70 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.transport.socketcan;
+
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.Channel;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.ThreadPerChannelEventLoop;
+import io.netty.channel.oio.OioEventLoopGroup;
+import org.apache.plc4x.java.spi.configuration.HasConfiguration;
+import org.apache.plc4x.java.spi.connection.NettyChannelFactory;
+import org.apache.plc4x.java.transport.socketcan.netty.SocketCANChannel;
+import org.apache.plc4x.java.transport.socketcan.netty.address.SocketCANAddress;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SocketCANChannelFactory extends NettyChannelFactory implements HasConfiguration<CANTransportConfiguration> {
+
+    private static final Logger logger = LoggerFactory.getLogger(SocketCANChannelFactory.class);
+
+    private CANTransportConfiguration configuration;
+
+    public SocketCANChannelFactory(SocketCANAddress address) {
+        super(address);
+    }
+
+    @Override
+    public void setConfiguration(CANTransportConfiguration configuration) {
+        this.configuration = configuration;
+    }
+
+    @Override
+    public Class<? extends Channel> getChannel() {
+        return SocketCANChannel.class;
+    }
+
+    @Override
+    public boolean isPassive() {
+        return true;
+    }
+
+    @Override
+    public EventLoopGroup getEventLoopGroup() {
+        return new ThreadPerChannelEventLoop(new OioEventLoopGroup());
+    }
+
+    @Override
+    public void configureBootstrap(Bootstrap bootstrap) {
+        if(configuration != null) {
+            logger.info("Configuring Bootstrap with {}", configuration);
+        }
+    }
+
+}
diff --git a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANTransport.java b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANTransport.java
new file mode 100644
index 0000000..95279c1
--- /dev/null
+++ b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANTransport.java
@@ -0,0 +1,46 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.transport.socketcan;
+
+import org.apache.plc4x.java.spi.connection.ChannelFactory;
+import org.apache.plc4x.java.spi.transport.Transport;
+import org.apache.plc4x.java.transport.socketcan.netty.address.SocketCANAddress;
+
+/**
+ * CAN specific transport which rely on JavaCAN library.
+ */
+public class SocketCANTransport implements Transport {
+
+    @Override
+    public String getTransportCode() {
+        return "javacan";
+    }
+
+    @Override
+    public String getTransportName() {
+        return "JavaCAN Transport";
+    }
+
+    @Override
+    public ChannelFactory createChannelFactory(String transportConfig) {
+        SocketCANAddress address = new SocketCANAddress(transportConfig);
+        return new SocketCANChannelFactory(address);
+    }
+
+}
diff --git a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannel.java b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannel.java
new file mode 100644
index 0000000..764d1f5
--- /dev/null
+++ b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannel.java
@@ -0,0 +1,267 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.plc4x.java.transport.socketcan.netty;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelConfig;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelPromise;
+import io.netty.channel.oio.OioByteStreamChannel;
+import org.apache.plc4x.java.transport.socketcan.netty.address.SocketCANAddress;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import tel.schich.javacan.CanChannels;
+import tel.schich.javacan.CanFrame;
+import tel.schich.javacan.NetworkDevice;
+import tel.schich.javacan.RawCanChannel;
+import tel.schich.javacan.linux.LinuxNetworkDevice;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.SocketAddress;
+import java.net.SocketTimeoutException;
+import java.nio.ByteBuffer;
+
+/**
+ * A naive copy of pcap channel implementation which allows to pass over data to PLC4X as well as drop it back to JavaCAN.
+ * Sadly all this involves double parsing.
+ */
+public class SocketCANChannel extends OioByteStreamChannel {
+
+    private static final Logger logger = LoggerFactory.getLogger(SocketCANChannel.class);
+
+    private final SocketCANChannelConfig config;
+
+    private SocketCANAddress remoteRawSocketAddress;
+    private SocketAddress localAddress;
+    private RawCanChannel handle;
+    private Thread loopThread;
+
+    public SocketCANChannel() {
+        super(null);
+        config = new SocketCANChannelConfig(this);
+    }
+
+    @Override
+    protected boolean isInputShutdown() {
+        return false;
+    }
+
+    @Override
+    protected ChannelFuture shutdownInput() {
+        throw new UnsupportedOperationException("");
+    }
+
+    @Override
+    protected void doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
+        if (!(remoteAddress instanceof SocketCANAddress)) {
+            logger.error("Expecting remote address of type SocketCANAddress");
+            pipeline().fireExceptionCaught(new IllegalArgumentException("Expecting remote address of type SocketCANAddress"));
+            return;
+        }
+        this.localAddress = localAddress;
+        remoteRawSocketAddress = (SocketCANAddress) remoteAddress;
+
+        // Try to get the device name of the network interface that we want to open.
+        String interfaceName = getInterfaceName(remoteRawSocketAddress);
+        if(interfaceName == null) {
+            logger.error("Interface name is not specified and couldn't detect it automatically");
+            pipeline().fireExceptionCaught(new IllegalArgumentException("Interface name is not specified and couldn't detect it automatically"));
+            return;
+        }
+
+        NetworkDevice device = LinuxNetworkDevice.lookup(interfaceName);
+        // Get a handle to the network-device and open it.
+        handle = CanChannels.newRawChannel(device);
+
+        if(logger.isDebugEnabled()) {
+            logger.debug(String.format("Listening on device %s", interfaceName));
+        }
+
+        // TODO If the address allows fine tuning which packets to process, set a filter to reduce the load.
+//        String filter =
+//        if(filter.length() > 0) {
+//            handle.setFilter(filter, BpfProgram.BpfCompileMode.OPTIMIZE);
+//        }
+
+        // Create a buffer where the raw socket worker can send data to.
+        ByteBuf buffer = Unpooled.buffer();
+
+        // Start a thread that processes the callbacks from the raw socket and simply
+        // forwards the bytes read to the buffer.
+        loopThread = new Thread(() -> {
+            try {
+                while (!isInputShutdown()) {
+                    CanFrame frame = handle.read();
+                    ByteBuf frameBytes = ByteBufAllocator.DEFAULT.buffer();
+                    frameBytes.writeBytes(frame.getBuffer());
+                    String dump = ByteBufUtil.prettyHexDump(frameBytes);
+                    System.out.println(frame + "\n" + dump);
+                    buffer.writeBytes(frame.getBuffer());
+                }
+            } catch (IOException e) {
+                logger.warn("Could not read data", e);
+                pipeline().fireExceptionCaught(e);
+            }
+        });
+        loopThread.start();
+
+        activate(new CANInputStream(buffer), new CANOutputStream(handle));
+    }
+
+    @Override
+    protected SocketAddress localAddress0() {
+        return localAddress;
+    }
+
+    @Override
+    protected SocketAddress remoteAddress0() {
+        return remoteRawSocketAddress;
+    }
+
+    @Override
+    protected void doBind(SocketAddress localAddress) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    @Override
+    protected void doDisconnect() {
+        this.loopThread.interrupt();
+        if (this.handle != null) {
+            try {
+                this.handle.close();
+            } catch (IOException e) {
+                logger.error("Failed to close CAN socket!");
+            }
+        }
+    }
+
+    @Override
+    protected int doReadBytes(ByteBuf buf) throws Exception {
+        if (handle == null || !handle.isOpen()) {
+            return -1;
+        }
+        try {
+            return super.doReadBytes(buf);
+        } catch (SocketTimeoutException ignored) {
+            return 0;
+        }
+    }
+
+    @Override
+    public ChannelConfig config() {
+        return this.config;
+    }
+
+    @Override
+    public boolean isOpen() {
+        return true;
+    }
+
+    @Override
+    protected AbstractUnsafe newUnsafe() {
+        return new RawSocketUnsafe();
+    }
+
+    private String getInterfaceName(SocketCANAddress address) {
+        // If the device name is provided, simply use this.
+        if(address.getInterfaceName() != null) {
+            return address.getInterfaceName();
+        }
+
+        // TODO: Implement this ...
+        return null;
+    }
+
+    /**
+     * InputStream that fulfills the contract of Netty for read operations to timeout.
+     * Without this the InputStream would simply block indefinitely which would block
+     * the entire IO module.
+     */
+    private static class CANInputStream extends InputStream {
+        final ByteBuf buf;
+
+        private CANInputStream(ByteBuf buf) {
+            this.buf = buf;
+        }
+
+        @Override
+        public int available() {
+            return buf.readableBytes();
+        }
+
+        @Override
+        public int read() throws IOException {
+            // Timeout 10 ms
+            final long timeout = System.nanoTime() + 10_000;
+            // Yes, this could make the thread go nuts in case of no data,
+            // but the Netty guys are doing it the same way and there probably
+            // is a reason for it ;-)
+            while (System.nanoTime() < timeout) {
+                if (buf.readableBytes() > 0) {
+                    return buf.readByte() & 0xFF;
+                }
+            }
+            throw new SocketTimeoutException();
+        }
+    }
+
+
+    private static class CANOutputStream extends OutputStream {
+
+        private final RawCanChannel rawCanChannel;
+
+        public CANOutputStream(RawCanChannel rawCanChannel) {
+            this.rawCanChannel = rawCanChannel;
+        }
+
+        @Override
+        public void write(int b) throws IOException {
+            throw new IOException("Appending single bytes is not permitted. Use write(byte[], int, int)");
+        }
+
+        @Override
+        public void write(byte[] b, int off, int len) throws IOException {
+            ByteBuffer buffer = ByteBuffer.wrap(b, off, len);
+            CanFrame frame = CanFrame.create(buffer);
+            rawCanChannel.write(frame);
+        }
+    }
+
+    /**
+     * Internal helper to wrap access to unsafe operations (Only used internally by netty)
+     */
+    private class RawSocketUnsafe extends AbstractUnsafe {
+        @Override
+        public void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
+            try {
+                doConnect(remoteAddress, localAddress);
+                pipeline().fireChannelActive();
+                promise.setSuccess();
+            } catch (Exception e) {
+                promise.setFailure(e);
+            }
+        }
+    }
+}
diff --git a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannelConfig.java b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannelConfig.java
new file mode 100644
index 0000000..42f604a
--- /dev/null
+++ b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannelConfig.java
@@ -0,0 +1,31 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.transport.socketcan.netty;
+
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelConfig;
+import io.netty.channel.DefaultChannelConfig;
+
+public class SocketCANChannelConfig extends DefaultChannelConfig implements ChannelConfig {
+
+    public SocketCANChannelConfig(Channel channel) {
+        super(channel);
+    }
+
+}
diff --git a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/address/SocketCANAddress.java b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/address/SocketCANAddress.java
new file mode 100644
index 0000000..e11ff17
--- /dev/null
+++ b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/address/SocketCANAddress.java
@@ -0,0 +1,40 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.transport.socketcan.netty.address;
+
+import java.net.SocketAddress;
+
+/**
+ * Simple address implementation which covers only interface name.
+ */
+public class SocketCANAddress extends SocketAddress {
+
+    private static final long serialVersionUID = 1L;
+
+    private final String interfaceName;
+
+    public SocketCANAddress(String interfaceName) {
+        this.interfaceName = interfaceName;
+    }
+
+    public String getInterfaceName() {
+        return interfaceName;
+    }
+
+}
diff --git a/plc4j/transports/socketcan/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.transport.Transport b/plc4j/transports/socketcan/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.transport.Transport
new file mode 100644
index 0000000..31b1a03
--- /dev/null
+++ b/plc4j/transports/socketcan/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.transport.Transport
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+org.apache.plc4x.java.transport.socketcan.SocketCANTransport
\ No newline at end of file
diff --git a/protocols/can/pom.xml b/protocols/can/pom.xml
new file mode 100644
index 0000000..be98554
--- /dev/null
+++ b/protocols/can/pom.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.plc4x</groupId>
+    <artifactId>plc4x-protocols</artifactId>
+    <version>0.8.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>plc4x-protocols-can</artifactId>
+
+  <name>Protocols: CAN</name>
+  <description>CAN stands for Controller Area Network.</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4x-build-utils-protocol-base-mspec</artifactId>
+      <version>0.8.0-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java b/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java
new file mode 100644
index 0000000..853fb50
--- /dev/null
+++ b/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java
@@ -0,0 +1,46 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+package org.apache.plc4x.protocol.can;
+
+import org.apache.plc4x.plugins.codegenerator.language.mspec.parser.MessageFormatParser;
+import org.apache.plc4x.plugins.codegenerator.protocol.Protocol;
+import org.apache.plc4x.plugins.codegenerator.types.definitions.TypeDefinition;
+import org.apache.plc4x.plugins.codegenerator.types.exceptions.GenerationException;
+
+import java.io.InputStream;
+import java.util.Map;
+
+public class CANProtocol implements Protocol {
+
+    @Override
+    public String getName() {
+        return "can";
+    }
+
+    @Override
+    public Map<String, TypeDefinition> getTypeDefinitions() throws GenerationException {
+        InputStream schemaInputStream = CANProtocol.class.getResourceAsStream("/protocols/can/can.mspec");
+        if(schemaInputStream == null) {
+            throw new GenerationException("Error loading message-format schema for protocol '" + getName() + "'");
+        }
+        return new MessageFormatParser().parse(schemaInputStream);
+    }
+
+}
diff --git a/protocols/can/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol b/protocols/can/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol
new file mode 100644
index 0000000..d422eca
--- /dev/null
+++ b/protocols/can/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+org.apache.plc4x.protocol.can.CANProtocol
\ No newline at end of file
diff --git a/protocols/can/src/main/resources/protocols/can/can.mspec b/protocols/can/src/main/resources/protocols/can/can.mspec
new file mode 100644
index 0000000..bbee418
--- /dev/null
+++ b/protocols/can/src/main/resources/protocols/can/can.mspec
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+[type 'CANFrame'
+    [simple uint 11 'identifier']
+    [simple bit 'remoteTransmissionRequest']
+    [discriminator bit 'extended']
+    [typeSwitch 'extended'
+        ['false' CANDataFrame
+            [reserved uint 1 '0x0']
+        ]
+        ['true' ExtendedCANFrame
+            [simple uint 18 'extensionId']
+            [simple bit 'extensionRemoteTransmissionRequest']
+            [reserved uint 2 '0x0']
+        ]
+    ]
+    [simple uint 4 'length']
+    [array uint 8 'data' count 'length']
+    [simple uint 15 'crc']
+]
+
+/* These are structures defined in linux kernel, provided here just for information purposes
+struct can_frame {
+  canid_t can_id;  // 32 bit CAN_ID + EFF/RTR/ERR flags
+  __u8    can_dlc; // frame payload length in byte (0 .. 8)
+  __u8    __pad;   // padding
+  __u8    __res0;  // reserved / padding
+  __u8    __res1;  // reserved / padding
+  __u8    data[8] __attribute__((aligned(8)));
+};
+struct canfd_frame {
+  canid_t can_id;  // 32 bit CAN_ID + EFF/RTR/ERR flags
+  __u8    len;     // frame payload length in byte (0 .. 64)
+  __u8    flags;   // additional flags for CAN FD
+  __u8    __res0;  // reserved / padding
+  __u8    __res1;  // reserved / padding
+  __u8    data[64] __attribute__((aligned(8)));
+};
+*/
+
+[type 'SocketCANFrame'
+    [simple uint 29 'identifier']
+    [simple bit 'extended']
+    [simple bit 'remote']
+    [simple bit 'error']
+    [implicit uint 8 'length' 'ARRAY_SIZE_IN_BYTES(data)']
+    [typeSwitch 'extended', 'identifier'
+        ['true' SocketCANFDFrame
+            [simple uint 8 'flags']
+            [reserved uint 8 '0x0']
+            [reserved uint 8 '0x0']
+        ]
+        ['false' ScoketCANFrame
+            [reserved uint 8 '0x0']
+            [reserved uint 8 '0x0']
+            [reserved uint 8 '0x0']
+        ]
+    ]
+    [array int 8 'data' COUNT 'length']
+]
diff --git a/protocols/pom.xml b/protocols/pom.xml
index 1459800..2191ba9 100644
--- a/protocols/pom.xml
+++ b/protocols/pom.xml
@@ -43,6 +43,7 @@
     <module>knxnetip</module>
     <module>modbus</module>
     <module>s7</module>
+    <module>can</module>
   </modules>
 
   <build>
diff --git a/sandbox/pom.xml b/sandbox/pom.xml
index 1b438bf..7278668 100644
--- a/sandbox/pom.xml
+++ b/sandbox/pom.xml
@@ -42,6 +42,7 @@
 
     <module>test-java-bacnetip-driver</module>
     <module>test-java-df1-driver</module>
+    <module>test-java-can-driver</module>
 
     <module>test-streampipes-plc4x-adapters</module>
     <module>test-streampipes-plc4x-processors</module>
diff --git a/sandbox/test-java-can-driver/pom.xml b/sandbox/test-java-can-driver/pom.xml
new file mode 100644
index 0000000..86bfddf
--- /dev/null
+++ b/sandbox/test-java-can-driver/pom.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.plc4x.sandbox</groupId>
+    <artifactId>plc4x-sandbox</artifactId>
+    <version>0.8.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>test-java-can-driver</artifactId>
+
+  <name>Sandbox: Test Generated CAN Driver</name>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.plc4x.plugins</groupId>
+        <artifactId>plc4x-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>test</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>generate-driver</goal>
+            </goals>
+            <configuration>
+              <protocolName>can</protocolName>
+              <languageName>java</languageName>
+              <outputFlavor>read-write</outputFlavor>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-api</artifactId>
+      <version>0.8.0-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-transport-socketcan</artifactId>
+      <version>0.8.0-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-buffer</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-annotations</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>osgi.cmpn</artifactId>
+      <version>6.0.0</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4x-build-utils-language-java</artifactId>
+      <version>0.8.0-SNAPSHOT</version>
+      <!-- Scope is 'provided' as this way it's not shipped with the driver -->
+      <scope>provided</scope>
+    </dependency>
+
+    <!-- Logging -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>log4j-over-slf4j</artifactId>
+      <version>1.7.25</version>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4x-protocols-can</artifactId>
+      <version>0.8.0-SNAPSHOT</version>
+      <!-- Scope is 'provided' as this way it's not shipped with the driver -->
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-utils-test-utils</artifactId>
+      <version>0.8.0-SNAPSHOT</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.dataformat</groupId>
+      <artifactId>jackson-dataformat-xml</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANPlcDriver.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANPlcDriver.java
new file mode 100644
index 0000000..4b7eb16
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANPlcDriver.java
@@ -0,0 +1,102 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+package org.apache.plc4x.java.can;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.can.configuration.CANConfiguration;
+import org.apache.plc4x.java.can.context.CANDriverContext;
+import org.apache.plc4x.java.can.field.CANFieldHandler;
+import org.apache.plc4x.java.can.protocol.CANProtocolLogic;
+import org.apache.plc4x.java.can.readwrite.CANFrame;
+import org.apache.plc4x.java.can.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.can.readwrite.io.CANFrameIO;
+import org.apache.plc4x.java.can.readwrite.io.SocketCANFrameIO;
+import org.apache.plc4x.java.spi.configuration.Configuration;
+import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
+import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
+import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer;
+import tel.schich.javacan.CanFrame;
+import tel.schich.javacan.CanId;
+
+import java.util.function.Consumer;
+import java.util.function.ToIntFunction;
+
+/**
+ */
+public class CANPlcDriver extends GeneratedDriverBase<SocketCANFrame> {
+
+    @Override
+    public String getProtocolCode() {
+        return "can";
+    }
+
+    @Override
+    public String getProtocolName() {
+        return "Controller Area Network";
+    }
+
+    @Override
+    protected Class<? extends Configuration> getConfigurationType() {
+        return CANConfiguration.class;
+    }
+
+    @Override
+    protected String getDefaultTransport() {
+        return "javacan";
+    }
+
+    @Override
+    protected CANFieldHandler getFieldHandler() {
+        return new CANFieldHandler();
+    }
+
+    @Override
+    protected ProtocolStackConfigurer<SocketCANFrame> getStackConfigurer() {
+        return SingleProtocolStackConfigurer.builder(SocketCANFrame.class, SocketCANFrameIO.class)
+            .withProtocol(CANProtocolLogic.class)
+            .withDriverContext(CANDriverContext.class)
+            .withPacketSizeEstimator(CANEstimator.class)
+            //.withCorruptPacketRemover(CANCleaner.class)
+            .build();
+    }
+
+    public static class CANEstimator implements ToIntFunction<ByteBuf> {
+        @Override
+        public int applyAsInt(ByteBuf byteBuf) {
+            if (byteBuf.readableBytes() >= 5) {
+                System.out.println(ByteBufUtil.prettyHexDump(byteBuf));
+                byte len = byteBuf.getByte(4);
+                System.out.println("Length " + (int) len);
+                return len + 8 /* overhead */;
+            }
+            return -1; //discard
+        }
+    }
+
+    public class CANCleaner implements Consumer<ByteBuf> {
+        @Override
+        public void accept(ByteBuf byteBuf) {
+            System.out.println("Discard");
+            byteBuf.readByte();
+        }
+    }
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java
new file mode 100644
index 0000000..1a86e45
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java
@@ -0,0 +1,26 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.can.configuration;
+
+import org.apache.plc4x.java.spi.configuration.Configuration;
+import org.apache.plc4x.java.transport.socketcan.CANTransportConfiguration;
+
+public class CANConfiguration implements Configuration, CANTransportConfiguration {
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/context/CANDriverContext.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/context/CANDriverContext.java
new file mode 100644
index 0000000..4f0d553
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/context/CANDriverContext.java
@@ -0,0 +1,24 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.can.context;
+
+import org.apache.plc4x.java.spi.context.DriverContext;
+
+public class CANDriverContext implements DriverContext {
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANFieldHandler.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANFieldHandler.java
new file mode 100644
index 0000000..2f2c3f8
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANFieldHandler.java
@@ -0,0 +1,33 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.can.field;
+
+import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.spi.connection.DefaultPlcFieldHandler;
+import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
+
+public class CANFieldHandler extends DefaultPlcFieldHandler implements PlcFieldHandler {
+
+    @Override
+    public PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
+        return null;
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANProtocolLogic.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANProtocolLogic.java
new file mode 100644
index 0000000..57dd683
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANProtocolLogic.java
@@ -0,0 +1,51 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.can.protocol;
+
+import org.apache.plc4x.java.can.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.spi.ConversationContext;
+import org.apache.plc4x.java.spi.Plc4xProtocolBase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CANProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> {
+
+    private Logger logger = LoggerFactory.getLogger(CANProtocolLogic.class);
+
+    @Override
+    public void onConnect(ConversationContext<SocketCANFrame> context) {
+        context.fireConnected();
+    }
+
+    @Override
+    protected void decode(ConversationContext<SocketCANFrame> context, SocketCANFrame msg) throws Exception {
+        logger.info("Decode CAN message {}", msg);
+    }
+
+    @Override
+    public void close(ConversationContext<SocketCANFrame> context) {
+
+    }
+
+    @Override
+    public void onDisconnect(ConversationContext<SocketCANFrame> context) {
+
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver b/sandbox/test-java-can-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
new file mode 100644
index 0000000..cb3d2ec
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+org.apache.plc4x.java.can.CANPlcDriver
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java
new file mode 100644
index 0000000..622f602
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java
@@ -0,0 +1,36 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.can;
+
+import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnection;
+
+/**
+ * Here we begin .. ;-)
+ */
+public class Main {
+
+    public static void main(String[] args) throws Exception {
+        PlcDriverManager driverManager = new PlcDriverManager();
+
+        PlcConnection connection = driverManager.getConnection("can:javacan://vcan0");
+
+    }
+
+}


[plc4x] 06/19: More definitions of various frame formats.

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit b3047448bce7aedd074c0ecbd17547dad2284cf2
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Wed Aug 26 23:49:33 2020 +0200

    More definitions of various frame formats.
---
 .../can/src/main/resources/protocols/can/can.mspec | 67 ++++++++++++++++++----
 .../apache/plc4x/java/can/helper/HeaderParser.java |  4 +-
 .../apache/plc4x/java/can/ManualParserTest.java    |  3 +
 .../apache/plc4x/java/can/SocketCAN20ATest.java    | 30 ++++++++++
 ...tCANTestSuite.xml => SocketCAN20ATestSuite.xml} | 45 ++++++++++-----
 ...tCANTestSuite.xml => SocketCAN20BTestSuite.xml} | 26 ++-------
 .../resources/testsuite/SocketCANTestSuite.xml     | 42 ++++++++++----
 7 files changed, 156 insertions(+), 61 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/can.mspec b/protocols/can/src/main/resources/protocols/can/can.mspec
index 16408fd..147492b 100644
--- a/protocols/can/src/main/resources/protocols/can/can.mspec
+++ b/protocols/can/src/main/resources/protocols/can/can.mspec
@@ -52,10 +52,35 @@ struct canfd_frame {
 };
 */
 
+[type 'BrokenSocketCANFrame'
+    [discriminator bit 'extended']
+    [simple bit 'remote']
+    [simple bit 'error']
+    [simple bit 'extended']
+    [typeSwitch 'extended'
+        ['true' ExtendedSocketCANFrame
+            [simple uint 29 'identifier']
+        ]
+
+        ['false' StandardSocketCANFrame
+            [const  uint 18 '0x0']
+            [simple uint 11 'identifier']
+        ]
+    ]
+    [implicit uint 8 'size' 'COUNT(data)']
+    [reserved uint 8 '0x0'] // padding
+    [reserved uint 8 '0x0'] // reserved / padding
+    [reserved uint 8 '0x0'] // reserved / padding
+    [array int 8 'data' COUNT 'size']
+]
+
 [type 'SocketCANFrame'
     [simple int 32 'rawId']
+    [virtual int 32 'identifier'
+        'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.readIdentifier", rawId)'
+    ]
     [virtual bit 'extended'
-        'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isRemote", rawId)'
+        'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isExtended", rawId)'
     ]
     [virtual bit 'remote'
         'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isRemote", rawId)'
@@ -64,28 +89,48 @@ struct canfd_frame {
         'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isError", rawId)'
     ]
     [implicit uint 8 'size' 'COUNT(data)']
-//    [typeSwitch 'extended'
-//        ['true' ExtendedOtherSocketCanFrame
-//            [simple uint 8 'flags']
-//        ]
-//        ['false' ExtendedOtherSocketCanFrame
-            [reserved uint 8 '0x0']
-//        ]
-//    ]
     [reserved uint 8 '0x0'] //flags
     [reserved uint 8 '0x0'] // padding 1
     [reserved uint 8 '0x0'] // padding 2
     [array int 8 'data' COUNT 'size']
 ]
 
+[type 'SocketCAN20AFrame'
+    [simple int 16 'identifier']
+    [reserved int 8 '0x0'] // filling gap used by extended frame
+    [simple bit 'extended']
+    [simple bit 'remote']
+    [simple bit 'error']
+    [reserved int 5 '0x0']  // filling gap used by extended frame
+    [implicit uint 8 'size' 'COUNT(data)']
+    [reserved uint 8 '0x0'] // in case of fd frame these are flags
+    [reserved uint 8 '0x0'] // padding 1
+    [reserved uint 8 '0x0'] // padding 2
+    [array int 8 'data' COUNT 'size']
+]
+
 [type 'SimplifiedSocketCANFrame'
     [simple bit 'extended']
     [simple bit 'remote']
     [simple bit 'error']
     [simple uint 29 'identifier']
-    [implicit uint 8 'length' 'COUNT(data)']
+    //implicit uint 8 'size' 'COUNT(data)'
     [reserved uint 8 '0x0'] // flags
     [reserved uint 8 '0x0'] // padding
     [reserved uint 8 '0x0'] // padding
-    [array int 8 'data' COUNT 'length']
+    //array int 8 'data' COUNT 'size'
+]
+
+[enum 'CanOpenNMTCommand'
+    ['0x01', START_DEVICE]
+    ['0x02', STOP_DEVICE]
+    ['0x80', PRE_START]
+    ['0x81', RESET_DEVICE]
+    ['0x82', RESET_COMMUNICATION]
 ]
+
+[dataIo 'CANOpenFrame' [uint 4 'function', uint 7 nodeId, int 8 'data']
+    [discriminator uint 4 'afunction']
+    [typeSwitch 'afunction'
+    ]
+]
\ No newline at end of file
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java
index 3ce7f0f..c0363f6 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java
@@ -2,7 +2,6 @@ package org.apache.plc4x.java.can.helper;
 
 import org.apache.plc4x.java.can.readwrite.SocketCANFrame;
 import org.apache.plc4x.java.spi.generation.ParseException;
-import org.apache.plc4x.java.spi.generation.ReadBuffer;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 
 public class HeaderParser {
@@ -17,8 +16,7 @@ public class HeaderParser {
 
     public static final int EXTENDED_FORMAT_IDENTIFIER_MASK = 0x1fffffff;
 
-    public static int readIdentifier(ReadBuffer buffer) throws ParseException {
-        int identifier = buffer.readInt(32);
+    public static int readIdentifier(int identifier) {
         if ((identifier & EXTENDED_FORMAT_IDENTIFIER_MASK) == 0) {
             return identifier & STANDARD_FORMAT_IDENTIFIER_MASK;
         }
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/ManualParserTest.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/ManualParserTest.java
index 11c6ca6..c055513 100644
--- a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/ManualParserTest.java
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/ManualParserTest.java
@@ -18,6 +18,9 @@ public class ManualParserTest {
     // cansend 5A1#11.2233.44556677.88
     String STANDARD = "a1050000080000001122334455667788";
 
+    // cansend 5A1#R
+    String STANDARD_REPLY = "a1050040000000000000000000000000";
+
     // cansend 1E6EC676#05.05.1F.26.C3
     String EXTENDED = "76c66e9e0500000005051f26c3000000";
 
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/SocketCAN20ATest.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/SocketCAN20ATest.java
new file mode 100644
index 0000000..8d86d97
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/SocketCAN20ATest.java
@@ -0,0 +1,30 @@
+/*
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+*/
+
+package org.apache.plc4x.java.can;
+
+import org.apache.plc4x.test.parserserializer.ParserSerializerTestsuiteRunner;
+
+public class SocketCAN20ATest extends ParserSerializerTestsuiteRunner {
+
+    public SocketCAN20ATest() {
+        super("/testsuite/SocketCAN20ATestSuite.xml");
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20ATestSuite.xml
similarity index 53%
copy from sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
copy to sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20ATestSuite.xml
index 774563b..60140de 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20ATestSuite.xml
@@ -19,35 +19,50 @@
   -->
 <test:testsuite xmlns:test="https://plc4x.apache.org/schemas/parser-serializer-testsuite.xsd">
 
-  <name>CAN Standard Format Frame</name>
+  <name>Tests of socketcan/CAN 2.0A frames</name>
 
   <testcase>
-    <name>Extended frame 1E6EC676#05.05.1F.26.C3</name>
-    <raw>76c66e9e0500000005051f26c3000000</raw>
-    <root-type>SocketCANFrame</root-type>
+    <name>Standard frame with 5 byte payload: 5A1#11.2233.44556677.88</name>
+    <raw>a1050000080000001122334455667788</raw>
+    <root-type>SocketCAN20AFrame</root-type>
     <xml>
-      <SocketCANFDFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
-        <identifier>510576246</identifier>
-        <extended>true</extended>
+      <SocketCAN20AFrame className="org.apache.plc4x.java.can.readwrite.SocketCAN20AFrame">
+        <identifier>1441</identifier>
+        <extended>false</extended>
         <remote>false</remote>
-        <error>true</error>
-        <data></data>
-      </SocketCANFDFrame>
+        <error>false</error>
+        <data>ESIzRFVmd4g=</data>
+      </SocketCAN20AFrame>
     </xml>
   </testcase>
 
   <testcase>
-    <name>Standard frame 5A1#11.2233.44556677.88</name>
-    <raw>a1050000080000001122334455667788</raw>
-    <root-type>SocketCANFrame</root-type>
+    <name>Standard frame with no payload: 5A1#</name>
+    <raw>a105000000000000</raw>
+    <root-type>SocketCAN20AFrame</root-type>
     <xml>
-      <ScoketCANSFFrame className="org.apache.plc4x.java.can.readwrite.ScoketCANFrame">
+      <SocketCAN20AFrame className="org.apache.plc4x.java.can.readwrite.SocketCAN20AFrame">
         <identifier>1441</identifier>
         <extended>false</extended>
         <remote>false</remote>
         <error>false</error>
         <data></data>
-      </ScoketCANSFFrame>
+      </SocketCAN20AFrame>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Remote transmission request: 5A1#R</name>
+    <raw>a105004000000000</raw>
+    <root-type>SocketCAN20AFrame</root-type>
+    <xml>
+      <SocketCAN20AFrame className="org.apache.plc4x.java.can.readwrite.SocketCAN20AFrame">
+        <identifier>1441</identifier>
+        <extended>false</extended>
+        <remote>true</remote>
+        <error>false</error>
+        <data></data>
+      </SocketCAN20AFrame>
     </xml>
   </testcase>
 
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
similarity index 63%
copy from sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
copy to sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
index 774563b..e8f08f4 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
@@ -19,35 +19,21 @@
   -->
 <test:testsuite xmlns:test="https://plc4x.apache.org/schemas/parser-serializer-testsuite.xsd">
 
-  <name>CAN Standard Format Frame</name>
+  <name>Tests of socketcan/CAN 2.0B frames</name>
 
   <testcase>
     <name>Extended frame 1E6EC676#05.05.1F.26.C3</name>
-    <raw>76c66e9e0500000005051f26c3000000</raw>
+    <raw>76c66e9e0500000005051f26c3</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
-      <SocketCANFDFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+        <rawId>-1636907402</rawId>
+        <data>BQUfJsM=</data>
         <identifier>510576246</identifier>
         <extended>true</extended>
         <remote>false</remote>
-        <error>true</error>
-        <data></data>
-      </SocketCANFDFrame>
-    </xml>
-  </testcase>
-
-  <testcase>
-    <name>Standard frame 5A1#11.2233.44556677.88</name>
-    <raw>a1050000080000001122334455667788</raw>
-    <root-type>SocketCANFrame</root-type>
-    <xml>
-      <ScoketCANSFFrame className="org.apache.plc4x.java.can.readwrite.ScoketCANFrame">
-        <identifier>1441</identifier>
-        <extended>false</extended>
-        <remote>false</remote>
         <error>false</error>
-        <data></data>
-      </ScoketCANSFFrame>
+      </SocketCANFrame>
     </xml>
   </testcase>
 
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
index 774563b..f2518c0 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
@@ -22,32 +22,50 @@
   <name>CAN Standard Format Frame</name>
 
   <testcase>
-    <name>Extended frame 1E6EC676#05.05.1F.26.C3</name>
-    <raw>76c66e9e0500000005051f26c3000000</raw>
+    <name>Standard frame with 5 byte payload: 5A1#11.2233.44556677.88</name>
+    <raw>a1050000080000001122334455667788</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
-      <SocketCANFDFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
-        <identifier>510576246</identifier>
-        <extended>true</extended>
+      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+        <rawId>1441</rawId>
+        <data>ESIzRFVmd4g=</data>
+        <identifier>1441</identifier>
+        <extended>false</extended>
         <remote>false</remote>
-        <error>true</error>
-        <data></data>
-      </SocketCANFDFrame>
+        <error>false</error>
+      </SocketCANFrame>
     </xml>
   </testcase>
 
   <testcase>
-    <name>Standard frame 5A1#11.2233.44556677.88</name>
-    <raw>a1050000080000001122334455667788</raw>
+    <name>Standard frame with no payload: 5A1#</name>
+    <raw>a105000000000000</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
-      <ScoketCANSFFrame className="org.apache.plc4x.java.can.readwrite.ScoketCANFrame">
+      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+        <rawId>1441</rawId>
+        <data></data>
         <identifier>1441</identifier>
         <extended>false</extended>
         <remote>false</remote>
         <error>false</error>
+      </SocketCANFrame>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Remote transmission request: 5A1#R</name>
+    <raw>a105004000000000</raw>
+    <root-type>SocketCANFrame</root-type>
+    <xml>
+      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+        <rawId>1073743265</rawId>
         <data></data>
-      </ScoketCANSFFrame>
+        <identifier>1441</identifier>
+        <extended>false</extended>
+        <remote>true</remote>
+        <error>false</error>
+      </SocketCANFrame>
     </xml>
   </testcase>
 


[plc4x] 01/19: - Updated my company

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit b60bba25ea973b4d0d4a1eccfb3cb85813f95e47
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Thu Oct 1 13:54:29 2020 +0200

    - Updated my company
---
 src/site/asciidoc/developers/team.adoc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/site/asciidoc/developers/team.adoc b/src/site/asciidoc/developers/team.adoc
index 4014fed..e0a8ff4 100644
--- a/src/site/asciidoc/developers/team.adoc
+++ b/src/site/asciidoc/developers/team.adoc
@@ -28,7 +28,7 @@ Sorted by first name:
 
 IoT Consultant
 
-codecentric AG
+Mapped
 
 Frankfurt |Likes to swim outside the mainstream. He is really passionate about walking new paths. His first email to an Apache list on file was to the Cocoon project back in the year 2000. His direct involvement started in 2012 when he was elected to become an Apache Flex committer. Since then he became involved with a lot of Apache-internal groups and committees and was elected to become a Member of the Apache Software Foundation in 2015 and recently has taken up the role of mentoring s [...]
 | *Julian Feinauer*


[plc4x] 07/19: Split different flavours of CAN formats.

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 4c3b4c10f260e9bc66e51a6b1818425afdb0de01
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Thu Aug 27 22:59:52 2020 +0200

    Split different flavours of CAN formats.
---
 .../can/{CANProtocol.java => CAN20AProtocol.java}  |  6 +--
 .../can/{CANProtocol.java => CANOpenProtocol.java} |  6 +--
 .../{CANProtocol.java => SocketCANProtocol.java}   |  6 +--
 ...e.plc4x.plugins.codegenerator.protocol.Protocol |  4 +-
 .../src/main/resources/protocols/can/can20a.mspec  | 25 +++++++++
 .../src/main/resources/protocols/can/canopen.mspec | 44 ++++++++++++++++
 .../protocols/can/{can.mspec => socketcan.mspec}   | 61 ----------------------
 sandbox/test-java-can-driver/pom.xml               | 16 +++++-
 .../org/apache/plc4x/java/can/CANPlcDriver.java    |  4 +-
 .../plc4x/java/can/helper/CANOpenHelper.java       | 18 +++++++
 .../apache/plc4x/java/can/helper/HeaderParser.java |  2 +-
 .../plc4x/java/can/protocol/CANProtocolLogic.java  |  2 +-
 .../org/apache/plc4x/java/can/CANOpenTest.java}    | 32 ++++--------
 ...ketCAN20BTestSuite.xml => CANOpenTestSuite.xml} | 18 +++----
 .../resources/testsuite/SocketCAN20ATestSuite.xml  |  6 +--
 .../resources/testsuite/SocketCAN20BTestSuite.xml  |  2 +-
 .../resources/testsuite/SocketCANTestSuite.xml     |  6 +--
 17 files changed, 144 insertions(+), 114 deletions(-)

diff --git a/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java b/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CAN20AProtocol.java
similarity index 89%
copy from protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java
copy to protocols/can/src/main/java/org/apache/plc4x/protocol/can/CAN20AProtocol.java
index 853fb50..f93d868 100644
--- a/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java
+++ b/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CAN20AProtocol.java
@@ -27,16 +27,16 @@ import org.apache.plc4x.plugins.codegenerator.types.exceptions.GenerationExcepti
 import java.io.InputStream;
 import java.util.Map;
 
-public class CANProtocol implements Protocol {
+public class CAN20AProtocol implements Protocol {
 
     @Override
     public String getName() {
-        return "can";
+        return "can20a";
     }
 
     @Override
     public Map<String, TypeDefinition> getTypeDefinitions() throws GenerationException {
-        InputStream schemaInputStream = CANProtocol.class.getResourceAsStream("/protocols/can/can.mspec");
+        InputStream schemaInputStream = CAN20AProtocol.class.getResourceAsStream("/protocols/can/can20a.mspec");
         if(schemaInputStream == null) {
             throw new GenerationException("Error loading message-format schema for protocol '" + getName() + "'");
         }
diff --git a/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java b/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANOpenProtocol.java
similarity index 89%
copy from protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java
copy to protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANOpenProtocol.java
index 853fb50..e6ddd5a 100644
--- a/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java
+++ b/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANOpenProtocol.java
@@ -27,16 +27,16 @@ import org.apache.plc4x.plugins.codegenerator.types.exceptions.GenerationExcepti
 import java.io.InputStream;
 import java.util.Map;
 
-public class CANProtocol implements Protocol {
+public class CANOpenProtocol implements Protocol {
 
     @Override
     public String getName() {
-        return "can";
+        return "canopen";
     }
 
     @Override
     public Map<String, TypeDefinition> getTypeDefinitions() throws GenerationException {
-        InputStream schemaInputStream = CANProtocol.class.getResourceAsStream("/protocols/can/can.mspec");
+        InputStream schemaInputStream = CANOpenProtocol.class.getResourceAsStream("/protocols/can/canopen.mspec");
         if(schemaInputStream == null) {
             throw new GenerationException("Error loading message-format schema for protocol '" + getName() + "'");
         }
diff --git a/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java b/protocols/can/src/main/java/org/apache/plc4x/protocol/can/SocketCANProtocol.java
similarity index 88%
rename from protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java
rename to protocols/can/src/main/java/org/apache/plc4x/protocol/can/SocketCANProtocol.java
index 853fb50..dba9730 100644
--- a/protocols/can/src/main/java/org/apache/plc4x/protocol/can/CANProtocol.java
+++ b/protocols/can/src/main/java/org/apache/plc4x/protocol/can/SocketCANProtocol.java
@@ -27,16 +27,16 @@ import org.apache.plc4x.plugins.codegenerator.types.exceptions.GenerationExcepti
 import java.io.InputStream;
 import java.util.Map;
 
-public class CANProtocol implements Protocol {
+public class SocketCANProtocol implements Protocol {
 
     @Override
     public String getName() {
-        return "can";
+        return "socketcan";
     }
 
     @Override
     public Map<String, TypeDefinition> getTypeDefinitions() throws GenerationException {
-        InputStream schemaInputStream = CANProtocol.class.getResourceAsStream("/protocols/can/can.mspec");
+        InputStream schemaInputStream = SocketCANProtocol.class.getResourceAsStream("/protocols/can/socketcan.mspec");
         if(schemaInputStream == null) {
             throw new GenerationException("Error loading message-format schema for protocol '" + getName() + "'");
         }
diff --git a/protocols/can/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol b/protocols/can/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol
index d422eca..bf88883 100644
--- a/protocols/can/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol
+++ b/protocols/can/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol
@@ -16,4 +16,6 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-org.apache.plc4x.protocol.can.CANProtocol
\ No newline at end of file
+org.apache.plc4x.protocol.can.CAN20AProtocol
+org.apache.plc4x.protocol.can.SocketCANProtocol
+org.apache.plc4x.protocol.can.CANOpenProtocol
\ No newline at end of file
diff --git a/protocols/can/src/main/resources/protocols/can/can20a.mspec b/protocols/can/src/main/resources/protocols/can/can20a.mspec
new file mode 100644
index 0000000..ffa733a
--- /dev/null
+++ b/protocols/can/src/main/resources/protocols/can/can20a.mspec
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+[type 'CANFrame'
+    [simple uint 11 'identifier']
+    [simple bit 'extended']
+    [simple bit 'remote']
+    [simple bit 'error']
+]
\ No newline at end of file
diff --git a/protocols/can/src/main/resources/protocols/can/canopen.mspec b/protocols/can/src/main/resources/protocols/can/canopen.mspec
new file mode 100644
index 0000000..553d12a
--- /dev/null
+++ b/protocols/can/src/main/resources/protocols/can/canopen.mspec
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+[type 'CANOpenFrame'
+    [enum CANOpenService 'function']
+    [simple int 11 'identifier']
+    [reserved int 9 '0x0'] // filling gap used by extended frame, and extended marker which should always be 0
+    [simple bit 'remote']
+    [simple bit 'error']
+    [reserved int 5 '0x0']  // filling gap used by extended frame
+    [implicit uint 8 'size' 'COUNT(payload)']
+    [reserved uint 8 '0x0'] // in case of fd frame these are flags
+    [reserved uint 8 '0x0'] // padding 1
+    [reserved uint 8 '0x0'] // padding 2
+    [simple CANOpenPayload 'payload' ['function', 'size']]
+]
+
+[enum uint 4 'CANOpenService'
+    ['0b1110' NMT]
+]
+
+[discriminatedType 'CANOpenPayload' [CANOpenService 'function', uint 8 'size']
+    [typeSwitch 'function'
+        ['CANOpenService.NMT' CANOpenNetworkPayload [uint 8 'size']
+            [array int 8 'data' COUNT 'size']
+        ]
+    ]
+]
\ No newline at end of file
diff --git a/protocols/can/src/main/resources/protocols/can/can.mspec b/protocols/can/src/main/resources/protocols/can/socketcan.mspec
similarity index 61%
rename from protocols/can/src/main/resources/protocols/can/can.mspec
rename to protocols/can/src/main/resources/protocols/can/socketcan.mspec
index 147492b..e2e9e3b 100644
--- a/protocols/can/src/main/resources/protocols/can/can.mspec
+++ b/protocols/can/src/main/resources/protocols/can/socketcan.mspec
@@ -17,41 +17,6 @@
  * under the License.
  */
 
-[type 'CANFrame'
-    [simple CANHeader 'header']
-    [simple uint 11 'identifier']
-    [simple bit 'extended']
-    [simple bit 'remote']
-    [simple bit 'error']
-]
-
-[type 'CANHeader'
-    [simple uint 11 'identifier']
-    [simple bit 'extended']
-    [simple bit 'remote']
-    [simple bit 'error']
-
-]
-
-/* These are structures defined in linux kernel, provided here just for information purposes
-struct can_frame {
-  canid_t can_id;  // 32 bit CAN_ID + EFF/RTR/ERR flags
-  __u8    can_dlc; // frame payload length in byte (0 .. 8)
-  __u8    __pad;   // padding
-  __u8    __res0;  // reserved / padding
-  __u8    __res1;  // reserved / padding
-  __u8    data[8] __attribute__((aligned(8)));
-};
-struct canfd_frame {
-  canid_t can_id;  // 32 bit CAN_ID + EFF/RTR/ERR flags
-  __u8    len;     // frame payload length in byte (0 .. 64)
-  __u8    flags;   // additional flags for CAN FD
-  __u8    __res0;  // reserved / padding
-  __u8    __res1;  // reserved / padding
-  __u8    data[64] __attribute__((aligned(8)));
-};
-*/
-
 [type 'BrokenSocketCANFrame'
     [discriminator bit 'extended']
     [simple bit 'remote']
@@ -107,30 +72,4 @@ struct canfd_frame {
     [reserved uint 8 '0x0'] // padding 1
     [reserved uint 8 '0x0'] // padding 2
     [array int 8 'data' COUNT 'size']
-]
-
-[type 'SimplifiedSocketCANFrame'
-    [simple bit 'extended']
-    [simple bit 'remote']
-    [simple bit 'error']
-    [simple uint 29 'identifier']
-    //implicit uint 8 'size' 'COUNT(data)'
-    [reserved uint 8 '0x0'] // flags
-    [reserved uint 8 '0x0'] // padding
-    [reserved uint 8 '0x0'] // padding
-    //array int 8 'data' COUNT 'size'
-]
-
-[enum 'CanOpenNMTCommand'
-    ['0x01', START_DEVICE]
-    ['0x02', STOP_DEVICE]
-    ['0x80', PRE_START]
-    ['0x81', RESET_DEVICE]
-    ['0x82', RESET_COMMUNICATION]
-]
-
-[dataIo 'CANOpenFrame' [uint 4 'function', uint 7 nodeId, int 8 'data']
-    [discriminator uint 4 'afunction']
-    [typeSwitch 'afunction'
-    ]
 ]
\ No newline at end of file
diff --git a/sandbox/test-java-can-driver/pom.xml b/sandbox/test-java-can-driver/pom.xml
index 86bfddf..50e48e7 100644
--- a/sandbox/test-java-can-driver/pom.xml
+++ b/sandbox/test-java-can-driver/pom.xml
@@ -37,13 +37,25 @@
         <artifactId>plc4x-maven-plugin</artifactId>
         <executions>
           <execution>
-            <id>test</id>
+            <id>socketcan</id>
             <phase>generate-sources</phase>
             <goals>
               <goal>generate-driver</goal>
             </goals>
             <configuration>
-              <protocolName>can</protocolName>
+              <protocolName>socketcan</protocolName>
+              <languageName>java</languageName>
+              <outputFlavor>read-write</outputFlavor>
+            </configuration>
+          </execution>
+          <execution>
+            <id>canopen</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>generate-driver</goal>
+            </goals>
+            <configuration>
+              <protocolName>canopen</protocolName>
               <languageName>java</languageName>
               <outputFlavor>read-write</outputFlavor>
             </configuration>
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANPlcDriver.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANPlcDriver.java
index e1a55ed..c135280 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANPlcDriver.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANPlcDriver.java
@@ -24,8 +24,8 @@ import org.apache.plc4x.java.can.configuration.CANConfiguration;
 import org.apache.plc4x.java.can.context.CANDriverContext;
 import org.apache.plc4x.java.can.field.CANFieldHandler;
 import org.apache.plc4x.java.can.protocol.CANProtocolLogic;
-import org.apache.plc4x.java.can.readwrite.SocketCANFrame;
-import org.apache.plc4x.java.can.readwrite.io.SocketCANFrameIO;
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.socketcan.readwrite.io.SocketCANFrameIO;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/CANOpenHelper.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/CANOpenHelper.java
new file mode 100644
index 0000000..5f6b4d3
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/CANOpenHelper.java
@@ -0,0 +1,18 @@
+package org.apache.plc4x.java.can.helper;
+
+import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService;
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.spi.generation.ParseException;
+import org.apache.plc4x.java.spi.generation.WriteBuffer;
+
+public class CANOpenHelper {
+
+    public static CANOpenService readFunction(short identifier) {
+        return CANOpenService.valueOf((byte) (identifier >> 7));
+    }
+
+    public static void writeFunction(WriteBuffer io, short identifier) {
+        // NOOP - a placeholder to let mspec compile
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java
index c0363f6..2ad7a1c 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java
@@ -1,6 +1,6 @@
 package org.apache.plc4x.java.can.helper;
 
-import org.apache.plc4x.java.can.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
 import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANProtocolLogic.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANProtocolLogic.java
index 57dd683..b556a07 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANProtocolLogic.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANProtocolLogic.java
@@ -18,7 +18,7 @@ under the License.
 */
 package org.apache.plc4x.java.can.protocol;
 
-import org.apache.plc4x.java.can.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame;
 import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
 import org.slf4j.Logger;
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenTest.java
similarity index 52%
copy from sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
copy to sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenTest.java
index e8f08f4..a97a1eb 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/CANOpenTest.java
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
+/*
   Licensed to the Apache Software Foundation (ASF) under one
   or more contributor license agreements.  See the NOTICE file
   distributed with this work for additional information
@@ -16,25 +15,16 @@
   KIND, either express or implied.  See the License for the
   specific language governing permissions and limitations
   under the License.
-  -->
-<test:testsuite xmlns:test="https://plc4x.apache.org/schemas/parser-serializer-testsuite.xsd">
+*/
 
-  <name>Tests of socketcan/CAN 2.0B frames</name>
+package org.apache.plc4x.java.can;
 
-  <testcase>
-    <name>Extended frame 1E6EC676#05.05.1F.26.C3</name>
-    <raw>76c66e9e0500000005051f26c3</raw>
-    <root-type>SocketCANFrame</root-type>
-    <xml>
-      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
-        <rawId>-1636907402</rawId>
-        <data>BQUfJsM=</data>
-        <identifier>510576246</identifier>
-        <extended>true</extended>
-        <remote>false</remote>
-        <error>false</error>
-      </SocketCANFrame>
-    </xml>
-  </testcase>
+import org.apache.plc4x.test.parserserializer.ParserSerializerTestsuiteRunner;
 
-</test:testsuite>
\ No newline at end of file
+public class CANOpenTest extends ParserSerializerTestsuiteRunner {
+
+    public CANOpenTest() {
+        super("/testsuite/CANOpenTestSuite.xml");
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenTestSuite.xml
similarity index 71%
copy from sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
copy to sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenTestSuite.xml
index e8f08f4..b99128d 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenTestSuite.xml
@@ -19,20 +19,20 @@
   -->
 <test:testsuite xmlns:test="https://plc4x.apache.org/schemas/parser-serializer-testsuite.xsd">
 
-  <name>Tests of socketcan/CAN 2.0B frames</name>
+  <name>Tests of socketcan/CANopen frames.</name>
 
   <testcase>
-    <name>Extended frame 1E6EC676#05.05.1F.26.C3</name>
-    <raw>76c66e9e0500000005051f26c3</raw>
-    <root-type>SocketCANFrame</root-type>
+    <name>Network heartbeat frame: 728#05</name>
+    <raw>280700000100000005</raw>
+    <root-type>CANOpenFrame</root-type>
     <xml>
-      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
-        <rawId>-1636907402</rawId>
-        <data>BQUfJsM=</data>
-        <identifier>510576246</identifier>
-        <extended>true</extended>
+      <SocketCANFrame className="org.apache.plc4x.java.canopen.readwrite.CANOpenFrame">
+        <function>15</function>
+        <identifier>5</identifier>
+        <extended>false</extended>
         <remote>false</remote>
         <error>false</error>
+        <data>ESIzRFVmd4g=</data>
       </SocketCANFrame>
     </xml>
   </testcase>
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20ATestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20ATestSuite.xml
index 60140de..3e647c5 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20ATestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20ATestSuite.xml
@@ -26,7 +26,7 @@
     <raw>a1050000080000001122334455667788</raw>
     <root-type>SocketCAN20AFrame</root-type>
     <xml>
-      <SocketCAN20AFrame className="org.apache.plc4x.java.can.readwrite.SocketCAN20AFrame">
+      <SocketCAN20AFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCAN20AFrame">
         <identifier>1441</identifier>
         <extended>false</extended>
         <remote>false</remote>
@@ -41,7 +41,7 @@
     <raw>a105000000000000</raw>
     <root-type>SocketCAN20AFrame</root-type>
     <xml>
-      <SocketCAN20AFrame className="org.apache.plc4x.java.can.readwrite.SocketCAN20AFrame">
+      <SocketCAN20AFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCAN20AFrame">
         <identifier>1441</identifier>
         <extended>false</extended>
         <remote>false</remote>
@@ -56,7 +56,7 @@
     <raw>a105004000000000</raw>
     <root-type>SocketCAN20AFrame</root-type>
     <xml>
-      <SocketCAN20AFrame className="org.apache.plc4x.java.can.readwrite.SocketCAN20AFrame">
+      <SocketCAN20AFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCAN20AFrame">
         <identifier>1441</identifier>
         <extended>false</extended>
         <remote>true</remote>
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
index e8f08f4..0e9caf3 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCAN20BTestSuite.xml
@@ -26,7 +26,7 @@
     <raw>76c66e9e0500000005051f26c3</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
-      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+      <SocketCANFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame">
         <rawId>-1636907402</rawId>
         <data>BQUfJsM=</data>
         <identifier>510576246</identifier>
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
index f2518c0..03eaaf1 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
@@ -26,7 +26,7 @@
     <raw>a1050000080000001122334455667788</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
-      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+      <SocketCANFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame">
         <rawId>1441</rawId>
         <data>ESIzRFVmd4g=</data>
         <identifier>1441</identifier>
@@ -42,7 +42,7 @@
     <raw>a105000000000000</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
-      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+      <SocketCANFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame">
         <rawId>1441</rawId>
         <data></data>
         <identifier>1441</identifier>
@@ -58,7 +58,7 @@
     <raw>a105004000000000</raw>
     <root-type>SocketCANFrame</root-type>
     <xml>
-      <SocketCANFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+      <SocketCANFrame className="org.apache.plc4x.java.socketcan.readwrite.SocketCANFrame">
         <rawId>1073743265</rawId>
         <data></data>
         <identifier>1441</identifier>


[plc4x] 11/19: Sketch of support for SDO operations.

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 5196344464d048afe0edc1c6f6a858895a77f9b4
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Sat Aug 29 10:09:57 2020 +0200

    Sketch of support for SDO operations.
---
 .../src/main/resources/protocols/can/canopen.mspec |  40 ++++++-
 .../apache/plc4x/java/can/CANOpenPlcDriver.java    |  17 +--
 .../java/can/configuration/CANConfiguration.java   |  12 +++
 .../java/can/protocol/CANOpenProtocolLogic.java    |  58 ++++++-----
 .../test/java/org/apache/plc4x/java/can/Main.java  |   2 +-
 .../testsuite/CANOpenPayloadTestSuite.xml          | 115 ++++++++++++++++++++-
 6 files changed, 196 insertions(+), 48 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/canopen.mspec b/protocols/can/src/main/resources/protocols/can/canopen.mspec
index 54337b4..d5160c6 100644
--- a/protocols/can/src/main/resources/protocols/can/canopen.mspec
+++ b/protocols/can/src/main/resources/protocols/can/canopen.mspec
@@ -18,8 +18,10 @@
  */
 
 [enum uint 4 'CANOpenService'
-    ['0x00' BROADCAST]
-    ['0x07' NMT]
+    ['0b0000' BROADCAST   ]
+    ['0b1110' NMT         ]
+    ['0b1100' SDO_REQUEST ]
+    ['0b1011' SDO_RESPONSE]
 ]
 
 [enum uint 8 'NMTStateRequest'
@@ -41,11 +43,41 @@
     [typeSwitch 'function'
         ['CANOpenService.BROADCAST' CANOpenBroadcastPayload
             [enum NMTStateRequest 'request']
-            [reserved uint 1 '0x0']
+            [reserved uint 1 '0x00']
             [simple uint 7 'node']
         ]
         ['CANOpenService.NMT' CANOpenNetworkPayload
             [enum NMTState 'state']
         ]
+        ['CANOpenService.SDO_REQUEST' CANOpenSDORequest
+            [enum SDOCommand 'command']
+            [reserved uint 1 '0x00']
+            [implicit uint 2 'size' 'COUNT(data)']
+            [simple bit 'expedited'] // segmented
+            [simple bit 'placement']
+            [simple uint 16 'index']
+            [simple uint 8 'subindex']
+            [array uint 8 'data' COUNT 'size']
+        ]
+        ['CANOpenService.SDO_RESPONSE' CANOpenSDOResponse
+            [enum SDOCommand 'command']
+            [reserved uint 1 '0x00']
+            [implicit uint 2 'size' 'COUNT(data)']
+            [simple bit 'expedited'] // segmented
+            [simple bit 'placement']
+            [simple uint 16 'index']
+            [simple uint 8 'subindex']
+            [array uint 8 'data' COUNT 'size']
+        ]
     ]
-]
\ No newline at end of file
+]
+
+[enum uint 3 'SDOCommand'
+    ['0x00' SEGMENT_DOWNLOAD]
+    ['0x01' INITIALIZE_DOWNLOAD]
+    ['0x02' INITIALIZE_UPLOAD]
+    ['0x03' SEGMENT_UPLOAD]
+    ['0x04' ABORT]
+    ['0x05' BLOCK_UPLOAD]
+    ['0x06' BLOCK_DOWNLOAD]
+]
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
index 4255ff2..6acff67 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
@@ -78,25 +78,10 @@ public class CANOpenPlcDriver extends GeneratedDriverBase<SocketCANFrame> {
         @Override
         public int applyAsInt(ByteBuf byteBuf) {
             if (byteBuf.readableBytes() >= 5) {
-
-                System.out.println(ByteBufUtil.prettyHexDump(byteBuf));
-                byte len = byteBuf.getByte(4);
-                System.out.println("Length " + (int) len);
-
-                CanFrame frame = CanFrame.create(byteBuf.nioBuffer());
-                System.out.println(frame);
-
-                return len + 8 /* overhead */;
+                return 16; // socketcan transport always returns 16 bytes padded with zeros;
             }
             return -1; //discard
         }
     }
 
-    public class CANCleaner implements Consumer<ByteBuf> {
-        @Override
-        public void accept(ByteBuf byteBuf) {
-            System.out.println("Discard");
-            byteBuf.readByte();
-        }
-    }
 }
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java
index 925ca15..214794d 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/configuration/CANConfiguration.java
@@ -27,6 +27,9 @@ public class CANConfiguration implements Configuration, CANTransportConfiguratio
     @ConfigurationParameter
     private int nodeId;
 
+    @ConfigurationParameter
+    private boolean hearbeat;
+
     public int getNodeId() {
         return nodeId;
     }
@@ -34,4 +37,13 @@ public class CANConfiguration implements Configuration, CANTransportConfiguratio
     public void setNodeId(int nodeId) {
         this.nodeId = nodeId;
     }
+
+    public boolean isHeartbeat() {
+        return hearbeat;
+    }
+
+    public void setHearbeat(boolean hearbeat) {
+        this.hearbeat = hearbeat;
+    }
+
 }
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
index 555ef92..9cc2fdb 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
@@ -45,6 +45,7 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
 
     private CANConfiguration configuration;
     private RequestTransactionManager tm;
+    private Timer heartbeat;
 
     @Override
     public void setConfiguration(CANConfiguration configuration) {
@@ -55,39 +56,46 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
 
     @Override
     public void onConnect(ConversationContext<SocketCANFrame> context) {
-        CANOpenNetworkPayload state = new CANOpenNetworkPayload(NMTState.BOOTED_UP);
-        WriteBuffer buffer = new WriteBuffer(1);
         try {
-            CANOpenNetworkPayloadIO.staticSerialize(buffer, state);
-            context.sendToWire(new SocketCANFrame(cobId(CANOpenService.NMT), buffer.getData()));
-            context.fireConnected();
-
-            Timer heartbeat = new Timer();
-            heartbeat.scheduleAtFixedRate(new TimerTask() {
-                @Override
-                public void run() {
-                    CANOpenNetworkPayload state = new CANOpenNetworkPayload(NMTState.OPERATIONAL);
-                    WriteBuffer buffer = new WriteBuffer(1);
-                    context.sendToWire(new SocketCANFrame(cobId(CANOpenService.NMT), buffer.getData()));
-                }
-            }, 5000, 5000);
+            if (configuration.isHeartbeat()) {
+                context.sendToWire(createFrame(new CANOpenNetworkPayload(NMTState.BOOTED_UP)));
+                context.fireConnected();
+
+                this.heartbeat = new Timer();
+                this.heartbeat.scheduleAtFixedRate(new TimerTask() {
+                    @Override
+                    public void run() {
+                        try {
+                            context.sendToWire(createFrame(new CANOpenNetworkPayload(NMTState.OPERATIONAL)));
+                        } catch (ParseException e) {
+                            e.printStackTrace();
+                        }
+                    }
+                }, 5000, 5000);
+            }
         } catch (ParseException e) {
             e.printStackTrace();
         }
     }
 
+    private SocketCANFrame createFrame(CANOpenNetworkPayload state) throws ParseException {
+        WriteBuffer buffer = new WriteBuffer(state.getLengthInBytes());
+        CANOpenNetworkPayloadIO.staticSerialize(buffer, state);
+        return new SocketCANFrame(cobId(CANOpenService.NMT), buffer.getData());
+    }
+
     @Override
     protected void decode(ConversationContext<SocketCANFrame> context, SocketCANFrame msg) throws Exception {
         logger.info("Decode CAN message {}", msg);
 
-        int identifier = msg.getIdentifier();
-        CANOpenService service = CANOpenService.valueOf((byte) (identifier >> 7));
-        if (service != null) {
-            ReadBuffer buffer = new ReadBuffer(msg.getData());
-            CANOpenPayload payload = CANOpenPayloadIO.staticParse(buffer, service);
-
-
-        }
+//        int identifier = msg.getIdentifier();
+//        CANOpenService service = CANOpenService.valueOf((byte) (identifier >> 7));
+//        if (service != null) {
+//            ReadBuffer buffer = new ReadBuffer(msg.getData());
+//            CANOpenPayload payload = CANOpenPayloadIO.staticParse(buffer, service);
+//
+//
+//        }
     }
 
     @Override
@@ -101,7 +109,9 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
     }
 
     private int cobId(CANOpenService service) {
-        return service.getValue() & configuration.getNodeId();
+        // form 32 bit socketcan identifier
+        return (configuration.getNodeId() << 24) & 0xff000000 |
+            (service.getValue() << 16 ) & 0x00ff0000;
     }
 
 }
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java
index e8279b6..8212bea 100644
--- a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/Main.java
@@ -29,7 +29,7 @@ public class Main {
     public static void main(String[] args) throws Exception {
         PlcDriverManager driverManager = new PlcDriverManager();
 
-        PlcConnection connection = driverManager.getConnection("canopen:javacan://vcan0?nodeId=15");
+        PlcConnection connection = driverManager.getConnection("canopen:javacan://vcan0?nodeId=11");
 
     }
 
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
index 773f608..d7c1a33 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
@@ -19,10 +19,10 @@
   -->
 <test:testsuite xmlns:test="https://plc4x.apache.org/schemas/parser-serializer-testsuite.xsd">
 
-  <name>Tests of socketcan/CANopen frames.</name>
+  <name>Tests of CANopen frames payload.</name>
 
   <testcase>
-    <name>Network heartbeat payload: 00</name>
+    <name>Network heartbeat, payload: 00</name>
     <raw>00</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
@@ -36,7 +36,7 @@
   </testcase>
 
   <testcase>
-    <name>Network heartbeat payload: 7F</name>
+    <name>Network heartbeat, payload: 7F</name>
     <raw>7F</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
@@ -49,4 +49,113 @@
     </xml>
   </testcase>
 
+  <testcase>
+    <name>SDO request, payload: 4317100000000000</name>
+    <raw>4317100000000000</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>SDO_REQUEST</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
+        <command>INITIALIZE_UPLOAD</command>
+        <expedited>true</expedited>
+        <placement>true</placement>
+        <index>4119</index>
+        <subindex>0</subindex>
+        <data/>
+      </CANOpenSDORequest>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>SDO request, payload: 00171000A00F0000</name>
+    <raw>00171000A00F0000</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>SDO_REQUEST</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
+        <command>SEGMENT_DOWNLOAD</command>
+        <expedited>false</expedited>
+        <placement>false</placement>
+        <index>4119</index>
+        <subindex>0</subindex>
+        <data/>
+      </CANOpenSDORequest>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>SDO write request, payload: 2B171000D00F</name>
+    <raw>2B171000D00F</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>SDO_REQUEST</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
+        <command>INITIALIZE_DOWNLOAD</command>
+        <expedited>true</expedited>
+        <placement>true</placement>
+        <index>4119</index>
+        <subindex>0</subindex>
+        <data>
+          <data>208</data>
+          <data>15</data>
+        </data>
+      </CANOpenSDORequest>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>SDO write result, payload: 60171000D0F00000</name>
+    <raw>00171000A00F0000</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>SDO_REQUEST</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
+        <command>SEGMENT_DOWNLOAD</command>
+        <expedited>false</expedited>
+        <placement>false</placement>
+        <index>4119</index>
+        <subindex>0</subindex>
+        <data/>
+      </CANOpenSDORequest>
+    </xml>
+  </testcase>
+
+  <!-- samples -->
+  <testcase>
+    <name>SDO response, payload: 6000200000</name>
+    <raw>6000200000</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>SDO_RESPONSE</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+        <state>PRE_OPERATIONAL</state>
+      </CANOpenNetworkPayload>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>PDO, payload: 78563412</name>
+    <raw>78563412</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>SDO_RESPONSE</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+        <state>PRE_OPERATIONAL</state>
+      </CANOpenNetworkPayload>
+    </xml>
+
+  </testcase>
+
 </test:testsuite>
\ No newline at end of file


[plc4x] 04/19: Tests for socketcan frames + manual parsing based on ReadBuffer api.

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 78fe2eeecafd71638b87c4f5082ec09be5e5b03e
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Thu Aug 20 21:46:34 2020 +0200

    Tests for socketcan frames + manual parsing based on ReadBuffer api.
---
 .../can/src/main/resources/protocols/can/can.mspec | 71 ++++++++++-------
 .../org/apache/plc4x/java/can/CANPlcDriver.java    | 10 +--
 .../apache/plc4x/java/can/helper/HeaderParser.java | 44 +++++++++++
 .../apache/plc4x/java/can/ManualParserTest.java    | 92 ++++++++++++++++++++++
 .../org/apache/plc4x/java/can/SocketCANTest.java   | 30 +++++++
 .../resources/testsuite/SocketCANTestSuite.xml     | 54 +++++++++++++
 6 files changed, 267 insertions(+), 34 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/can.mspec b/protocols/can/src/main/resources/protocols/can/can.mspec
index bbee418..113e304 100644
--- a/protocols/can/src/main/resources/protocols/can/can.mspec
+++ b/protocols/can/src/main/resources/protocols/can/can.mspec
@@ -18,22 +18,19 @@
  */
 
 [type 'CANFrame'
+    [simple CANHeader 'header']
     [simple uint 11 'identifier']
-    [simple bit 'remoteTransmissionRequest']
-    [discriminator bit 'extended']
-    [typeSwitch 'extended'
-        ['false' CANDataFrame
-            [reserved uint 1 '0x0']
-        ]
-        ['true' ExtendedCANFrame
-            [simple uint 18 'extensionId']
-            [simple bit 'extensionRemoteTransmissionRequest']
-            [reserved uint 2 '0x0']
-        ]
-    ]
-    [simple uint 4 'length']
-    [array uint 8 'data' count 'length']
-    [simple uint 15 'crc']
+    [simple bit 'extended']
+    [simple bit 'remote']
+    [simple bit 'error']
+]
+
+[type 'CANHeader'
+    [simple uint 11 'identifier']
+    [simple bit 'extended']
+    [simple bit 'remote']
+    [simple bit 'error']
+
 ]
 
 /* These are structures defined in linux kernel, provided here just for information purposes
@@ -55,23 +52,39 @@ struct canfd_frame {
 };
 */
 
+[type 'OtherSocketCANFrame'
+    [simple int 32 'rawId']
+    [virtual bit 'extended'
+        'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isRemote", rawId)'
+    ]
+    [virtual bit 'remote'
+        'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isRemote", rawId)'
+    ]
+    [virtual bit 'error'
+        'STATIC_CALL("org.apache.plc4x.java.can.helper.HeaderParser.isError", rawId)'
+    ]
+//    [typeSwitch 'extended'
+//        ['true' ExtendedOtherSocketCanFrame
+//            [simple uint 8 'flags']
+//        ]
+//        ['false' ExtendedOtherSocketCanFrame
+            [reserved uint 8 '0x0']
+//        ]
+//    ]
+    [reserved uint 8 '0x0']
+    [reserved uint 8 '0x0']
+    [implicit uint 8 'size' 'COUNT(data)']
+    [array int 8 'data' COUNT 'size']
+]
+
 [type 'SocketCANFrame'
-    [simple uint 29 'identifier']
     [simple bit 'extended']
     [simple bit 'remote']
     [simple bit 'error']
-    [implicit uint 8 'length' 'ARRAY_SIZE_IN_BYTES(data)']
-    [typeSwitch 'extended', 'identifier'
-        ['true' SocketCANFDFrame
-            [simple uint 8 'flags']
-            [reserved uint 8 '0x0']
-            [reserved uint 8 '0x0']
-        ]
-        ['false' ScoketCANFrame
-            [reserved uint 8 '0x0']
-            [reserved uint 8 '0x0']
-            [reserved uint 8 '0x0']
-        ]
-    ]
+    [simple uint 29 'identifier']
+    [implicit uint 8 'length' 'COUNT(data)']
+    [reserved uint 8 '0x0'] // flags
+    [reserved uint 8 '0x0'] // padding
+    [reserved uint 8 '0x0'] // padding
     [array int 8 'data' COUNT 'length']
 ]
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANPlcDriver.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANPlcDriver.java
index 4b7eb16..e1a55ed 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANPlcDriver.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANPlcDriver.java
@@ -20,22 +20,17 @@ package org.apache.plc4x.java.can;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufUtil;
-import org.apache.plc4x.java.PlcDriverManager;
-import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.can.configuration.CANConfiguration;
 import org.apache.plc4x.java.can.context.CANDriverContext;
 import org.apache.plc4x.java.can.field.CANFieldHandler;
 import org.apache.plc4x.java.can.protocol.CANProtocolLogic;
-import org.apache.plc4x.java.can.readwrite.CANFrame;
 import org.apache.plc4x.java.can.readwrite.SocketCANFrame;
-import org.apache.plc4x.java.can.readwrite.io.CANFrameIO;
 import org.apache.plc4x.java.can.readwrite.io.SocketCANFrameIO;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
 import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer;
 import tel.schich.javacan.CanFrame;
-import tel.schich.javacan.CanId;
 
 import java.util.function.Consumer;
 import java.util.function.ToIntFunction;
@@ -83,9 +78,14 @@ public class CANPlcDriver extends GeneratedDriverBase<SocketCANFrame> {
         @Override
         public int applyAsInt(ByteBuf byteBuf) {
             if (byteBuf.readableBytes() >= 5) {
+
                 System.out.println(ByteBufUtil.prettyHexDump(byteBuf));
                 byte len = byteBuf.getByte(4);
                 System.out.println("Length " + (int) len);
+
+                CanFrame frame = CanFrame.create(byteBuf.nioBuffer());
+                System.out.println(frame);
+
                 return len + 8 /* overhead */;
             }
             return -1; //discard
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java
new file mode 100644
index 0000000..3ce7f0f
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/helper/HeaderParser.java
@@ -0,0 +1,44 @@
+package org.apache.plc4x.java.can.helper;
+
+import org.apache.plc4x.java.can.readwrite.SocketCANFrame;
+import org.apache.plc4x.java.spi.generation.ParseException;
+import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.apache.plc4x.java.spi.generation.WriteBuffer;
+
+public class HeaderParser {
+
+    public static final int EXTENDED_FRAME_FORMAT_FLAG = 0x80000000;
+
+    public static final int REMOTE_TRANSMISSION_FLAG = 0x40000000;
+
+    public static final int ERROR_FRAME_FLAG = 0x20000000;
+
+    public static final int STANDARD_FORMAT_IDENTIFIER_MASK = 0x7ff;
+
+    public static final int EXTENDED_FORMAT_IDENTIFIER_MASK = 0x1fffffff;
+
+    public static int readIdentifier(ReadBuffer buffer) throws ParseException {
+        int identifier = buffer.readInt(32);
+        if ((identifier & EXTENDED_FORMAT_IDENTIFIER_MASK) == 0) {
+            return identifier & STANDARD_FORMAT_IDENTIFIER_MASK;
+        }
+        return identifier & EXTENDED_FORMAT_IDENTIFIER_MASK;
+    }
+
+    public static void writeIdentifier(WriteBuffer buffer, SocketCANFrame frame) throws ParseException {
+
+    }
+
+    public static boolean isExtended(int identifier) {
+        return (identifier & EXTENDED_FRAME_FORMAT_FLAG) != 0;
+    }
+
+    public static boolean isRemote(int identifier) {
+        return (identifier & REMOTE_TRANSMISSION_FLAG) != 0;
+    }
+
+    public static boolean isError(int identifier) {
+        return (identifier & ERROR_FRAME_FLAG) != 0;
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/ManualParserTest.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/ManualParserTest.java
new file mode 100644
index 0000000..11c6ca6
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/ManualParserTest.java
@@ -0,0 +1,92 @@
+package org.apache.plc4x.java.can;
+
+import org.apache.commons.codec.binary.Hex;
+import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class ManualParserTest {
+
+    public static final int EXTENDED_FRAME_FORMAT_FLAG = 0b10000000_00000000_00000000_00000000;
+    public static final int REMOTE_TRANSMISSION_FLAG = 0b01000000_00000000_00000000_00000000;
+    public static final int ERROR_FRAME_FLAG = 0b00100000_00000000_00000000_00000000;
+
+    public static final int STANDARD_FORMAT_IDENTIFIER_MASK = 0b00000000_00000000_00000111_11111111;
+    public static final int EXTENDED_FORMAT_IDENTIFIER_MASK = 0b00011111_11111111_11111111_11111111;
+
+    // cansend 5A1#11.2233.44556677.88
+    String STANDARD = "a1050000080000001122334455667788";
+
+    // cansend 1E6EC676#05.05.1F.26.C3
+    String EXTENDED = "76c66e9e0500000005051f26c3000000";
+
+    @Test
+    public void readBufferTest() throws Exception {
+        ReadBuffer buffer = new ReadBuffer(new byte[]{(byte) 0xA1, 0x05, 0x00, 0x00}, true);
+        int value = buffer.readInt(32);
+
+        assertEquals(value, 0x5A1);
+    }
+
+    @Test
+    public void standardFrameParser() throws Exception {
+        SocketCanFrameStub frame = parse(STANDARD);
+        //System.out.println(frame);
+
+        assertEquals(frame.id, 0x5A1);
+        assertEquals(frame.extended, false);
+        assertEquals(frame.remote, false);
+        assertEquals(frame.error, false);
+        assertEquals(frame.data.length, 8);
+    }
+
+    @Test
+    public void extendedFrameParser() throws Exception {
+        SocketCanFrameStub frame = parse(EXTENDED);
+        //System.out.println(frame);
+
+        assertEquals(frame.id, 0x1e6ec676);
+        assertEquals(frame.extended, true);
+        assertEquals(frame.remote, false);
+        assertEquals(frame.error, false);
+        assertEquals(frame.data.length, 5);
+    }
+
+    public final static SocketCanFrameStub parse(String hex) throws Exception {
+        byte[] input = Hex.decodeHex(hex.toCharArray());
+
+        ReadBuffer readBuffer = new ReadBuffer(input, true);
+        int rawId = readBuffer.readInt(32);
+        boolean extended = (rawId & EXTENDED_FRAME_FORMAT_FLAG) != 0;
+        boolean remote = (rawId & REMOTE_TRANSMISSION_FLAG) != 0;
+        boolean error = (rawId & ERROR_FRAME_FLAG) != 0;
+        int id = extended ? (rawId & EXTENDED_FORMAT_IDENTIFIER_MASK) : (rawId & STANDARD_FORMAT_IDENTIFIER_MASK);
+        int length = readBuffer.readByte(8);
+        byte[] data = readBuffer.getBytes(8, 8 + length);
+
+        return new SocketCanFrameStub(
+            id, extended, remote, error, data
+        );
+    }
+
+    static class SocketCanFrameStub {
+        public int id;
+        public boolean extended;
+        public boolean remote;
+        public boolean error;
+        public byte[] data;
+
+        public SocketCanFrameStub(int id, boolean extended, boolean remote, boolean error, byte[] data) {
+            this.id = id;
+            this.extended = extended;
+            this.remote = remote;
+            this.error = error;
+            this.data = data;
+        }
+
+        public String toString() {
+            return "CAN Frame ID=" + Integer.toHexString(id) + ", extended=" + extended + ", remote=" + remote + ", error=" + error + ", data=" + Hex.encodeHexString(data);
+        }
+    }
+}
diff --git a/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/SocketCANTest.java b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/SocketCANTest.java
new file mode 100644
index 0000000..270b45a
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/test/java/org/apache/plc4x/java/can/SocketCANTest.java
@@ -0,0 +1,30 @@
+/*
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+*/
+
+package org.apache.plc4x.java.can;
+
+import org.apache.plc4x.test.parserserializer.ParserSerializerTestsuiteRunner;
+
+public class SocketCANTest extends ParserSerializerTestsuiteRunner {
+
+    public SocketCANTest() {
+        super("/testsuite/SocketCANTestSuite.xml");
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
new file mode 100644
index 0000000..774563b
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/SocketCANTestSuite.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+  -->
+<test:testsuite xmlns:test="https://plc4x.apache.org/schemas/parser-serializer-testsuite.xsd">
+
+  <name>CAN Standard Format Frame</name>
+
+  <testcase>
+    <name>Extended frame 1E6EC676#05.05.1F.26.C3</name>
+    <raw>76c66e9e0500000005051f26c3000000</raw>
+    <root-type>SocketCANFrame</root-type>
+    <xml>
+      <SocketCANFDFrame className="org.apache.plc4x.java.can.readwrite.SocketCANFrame">
+        <identifier>510576246</identifier>
+        <extended>true</extended>
+        <remote>false</remote>
+        <error>true</error>
+        <data></data>
+      </SocketCANFDFrame>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Standard frame 5A1#11.2233.44556677.88</name>
+    <raw>a1050000080000001122334455667788</raw>
+    <root-type>SocketCANFrame</root-type>
+    <xml>
+      <ScoketCANSFFrame className="org.apache.plc4x.java.can.readwrite.ScoketCANFrame">
+        <identifier>1441</identifier>
+        <extended>false</extended>
+        <remote>false</remote>
+        <error>false</error>
+        <data></data>
+      </ScoketCANSFFrame>
+    </xml>
+  </testcase>
+
+</test:testsuite>
\ No newline at end of file


[plc4x] 19/19: CANopen microstone - PDO & subscriptions.

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 0b699e83f23f00e66f776610011efb5eaa4ccb87
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Wed Oct 7 11:31:43 2020 +0200

    CANopen microstone - PDO & subscriptions.
---
 .../resources/templates/java/data-io-template.ftlh |  19 ++-
 .../org/apache/plc4x/java/api/value/PlcValues.java |   4 +
 .../src/main/resources/protocols/can/canopen.mspec |  40 +++---
 .../apache/plc4x/java/can/CANOpenPlcDriver.java    |   5 +
 .../apache/plc4x/java/can/field/CANOpenField.java  |   2 +
 .../plc4x/java/can/field/CANOpenFieldHandler.java  |  20 ++-
 .../plc4x/java/can/field/CANOpenPDOField.java      |  64 ++++++++++
 .../java/can/protocol/CANOpenProtocolLogic.java    | 137 +++++++++++++++++++--
 .../can/protocol/CANOpenSubscriptionHandle.java    |  28 +++++
 9 files changed, 281 insertions(+), 38 deletions(-)

diff --git a/build-utils/language-java/src/main/resources/templates/java/data-io-template.ftlh b/build-utils/language-java/src/main/resources/templates/java/data-io-template.ftlh
index 0d32a36..99b6871 100644
--- a/build-utils/language-java/src/main/resources/templates/java/data-io-template.ftlh
+++ b/build-utils/language-java/src/main/resources/templates/java/data-io-template.ftlh
@@ -119,10 +119,21 @@ public class ${type.name}IO {
                             <#if helper.isLengthArrayField(field)>
             // Length array
             int _${field.name}Length = ${helper.toParseExpression(field, field.loopExpression, type.parserArguments)};
-            List<${helper.getNonPrimitiveLanguageTypeNameForField(field)}> _${field.name}List = new LinkedList<>();
+            List<PlcValue> _${field.name}List = new LinkedList<>();
             int ${field.name}EndPos = io.getPos() + _${field.name}Length;
             while(io.getPos() < ${field.name}EndPos) {
-                _${field.name}List.add(<#if helper.isSimpleTypeReference(field.type)>${helper.getReadBufferReadMethodCall(field.type)}<#else>${field.type.name}IO.staticParse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(field.type, parserArgument?index), true)}) (${helper.toParseExpression(field, parserArgument, type.parserArguments)})<#sep>, </#sep></#list></#if>)</#if>);
+                _${field.name}List.add(
+                    <#if helper.isSimpleTypeReference(field.type)>PlcValues.of(${helper.getReadBufferReadMethodCall(field.type)})
+                    <#else>${field.type.name}IO.staticParse(io
+                        <#if field.params?has_content>,
+                            <#list field.params as parserArgument>
+                                (${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(field.type, parserArgument?index), true)}) (${helper.toParseExpression(field, parserArgument, type.parserArguments)})
+                                <#sep>, </#sep>
+                            </#list>
+                        </#if>
+                    )
+                    </#if>
+                );
                 <#-- After parsing, update the current position, but only if it's needed -->
                                 <#if field.loopExpression.contains("curPos")>
                 curPos = io.getPos() - startPos;
@@ -145,7 +156,6 @@ public class ${type.name}IO {
                 Convert the list into an array. However if the array is of a primitive
                 type we have to iterate over it's elements and explicitly cast them.
                 Otherwise a simple toArray call is fine.
-            -->
                             <#if helper.isSimpleTypeReference(field.type)>
             ${helper.getNonPrimitiveLanguageTypeNameForField(field)}[] ${field.name} = new ${helper.getNonPrimitiveLanguageTypeNameForField(field)}[_${field.name}List.size()];
             for(int i = 0; i < _${field.name}List.size(); i++) {
@@ -154,6 +164,9 @@ public class ${type.name}IO {
                             <#else>
             ${helper.getNonPrimitiveLanguageTypeNameForField(field)}[] ${field.name} = _${field.name}List.toArray(new ${helper.getNonPrimitiveLanguageTypeNameForField(field)}[0]);
                             </#if>
+
+            -->
+            List<?> value = _${field.name}List;
                         </#if>
                     <#break>
                     <#case "const">
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValues.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValues.java
index 291ccad..582e934 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValues.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/value/PlcValues.java
@@ -382,6 +382,10 @@ public class PlcValues {
         if(o == null) {
             return new PlcNull();
         }
+        if (o instanceof Byte) {
+            return new PlcBYTE((Byte) o);
+        }
+
         try {
             String simpleName = o.getClass().getSimpleName();
             Class<?> clazz = o.getClass();
diff --git a/protocols/can/src/main/resources/protocols/can/canopen.mspec b/protocols/can/src/main/resources/protocols/can/canopen.mspec
index 3b1e49d..10afdf9 100644
--- a/protocols/can/src/main/resources/protocols/can/canopen.mspec
+++ b/protocols/can/src/main/resources/protocols/can/canopen.mspec
@@ -272,64 +272,64 @@
 
 [dataIo 'DataItem' [CANOpenDataType 'dataType', int 32 'size']
     [typeSwitch 'dataType'
-        ['CANOpenDataType.BOOLEAN' Boolean
+        ['CANOpenDataType.BOOLEAN' BOOL
             [simple bit 'value']
         ]
-        ['CANOpenDataType.UNSIGNED8' Integer
+        ['CANOpenDataType.UNSIGNED8' USINT
             [simple uint 8 'value']
         ]
-        ['CANOpenDataType.UNSIGNED16' Integer
+        ['CANOpenDataType.UNSIGNED16' UINT
             [simple uint 16 'value']
         ]
-        ['CANOpenDataType.UNSIGNED24' Long
+        ['CANOpenDataType.UNSIGNED24' UDINT
             [simple uint 24 'value']
         ]
-        ['CANOpenDataType.UNSIGNED32' Long
+        ['CANOpenDataType.UNSIGNED32' UDINT
             [simple uint 32 'value']
         ]
-        ['CANOpenDataType.UNSIGNED40' BigInteger
+        ['CANOpenDataType.UNSIGNED40' ULINT
             [simple uint 40 'value']
         ]
-        ['CANOpenDataType.UNSIGNED48' BigInteger
+        ['CANOpenDataType.UNSIGNED48' ULINT
             [simple uint 48 'value']
         ]
-        ['CANOpenDataType.UNSIGNED56' BigInteger
+        ['CANOpenDataType.UNSIGNED56' ULINT
             [simple uint 56 'value']
         ]
-        ['CANOpenDataType.UNSIGNED64' BigInteger
+        ['CANOpenDataType.UNSIGNED64' ULINT
             [simple uint 64 'value']
         ]
-        ['CANOpenDataType.INTEGER8' Integer
+        ['CANOpenDataType.INTEGER8' SINT
             [simple int 8 'value']
         ]
-        ['CANOpenDataType.INTEGER16' Integer
+        ['CANOpenDataType.INTEGER16' INT
             [simple int 16 'value']
         ]
-        ['CANOpenDataType.INTEGER24' Integer
+        ['CANOpenDataType.INTEGER24' DINT
             [simple int 24 'value']
         ]
-        ['CANOpenDataType.INTEGER32' Integer
+        ['CANOpenDataType.INTEGER32' DINT
             [simple int 32 'value']
         ]
-        ['CANOpenDataType.INTEGER40' Long
+        ['CANOpenDataType.INTEGER40' LINT
             [simple int 40 'value']
         ]
-        ['CANOpenDataType.INTEGER48' Long
+        ['CANOpenDataType.INTEGER48' LINT
             [simple int 48 'value']
         ]
-        ['CANOpenDataType.INTEGER56' Long
+        ['CANOpenDataType.INTEGER56' LINT
             [simple int 56 'value']
         ]
-        ['CANOpenDataType.INTEGER64' Long
+        ['CANOpenDataType.INTEGER64' LINT
             [simple int 64 'value']
         ]
-        ['CANOpenDataType.REAL32' Float
+        ['CANOpenDataType.REAL32' REAL
             [simple float 8.23 'value']
         ]
-        ['CANOpenDataType.REAL64' Double
+        ['CANOpenDataType.REAL64' LREAL
             [simple float 11.52 'value']
         ]
-        ['CANOpenDataType.RECORD' List
+        ['CANOpenDataType.RECORD' List [int 32 'size']
             [array int 8 'value' length 'size']
         ]
         ['CANOpenDataType.OCTET_STRING' String
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
index a8a5f7a..c34806f 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/CANOpenPlcDriver.java
@@ -58,6 +58,11 @@ public class CANOpenPlcDriver extends GeneratedDriverBase<SocketCANFrame> {
     }
 
     @Override
+    protected boolean canSubscribe() {
+        return true;
+    }
+
+    @Override
     protected boolean canWrite() {
         return true;
     }
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenField.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenField.java
index 6458848..6917351 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenField.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenField.java
@@ -44,6 +44,8 @@ public abstract class CANOpenField implements PlcField {
     public static CANOpenField of(String addressString) throws PlcInvalidFieldException {
         if (CANOpenSDOField.matches(addressString)) {
             return CANOpenSDOField.of(addressString);
+        } else if (CANOpenPDOField.matches(addressString)) {
+            return CANOpenPDOField.of(addressString);
         }
 
         throw new PlcInvalidFieldException("Unable to parse address: " + addressString);
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenFieldHandler.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenFieldHandler.java
index cf37533..cb61195 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenFieldHandler.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenFieldHandler.java
@@ -21,13 +21,13 @@ package org.apache.plc4x.java.can.field;
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.model.PlcField;
-import org.apache.plc4x.java.api.value.PlcList;
-import org.apache.plc4x.java.api.value.PlcString;
-import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.api.value.*;
 import org.apache.plc4x.java.spi.connection.DefaultPlcFieldHandler;
 import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
 
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.stream.Collectors;
 
 public class CANOpenFieldHandler extends DefaultPlcFieldHandler implements PlcFieldHandler {
@@ -55,4 +55,18 @@ public class CANOpenFieldHandler extends DefaultPlcFieldHandler implements PlcFi
 
         throw new PlcRuntimeException("Invalid encoder for type " + coField.getCanOpenDataType().name());
     }
+
+    @Override
+    public PlcValue encodeByte(PlcField field, Object[] values) {
+        List<PlcValue> resultSet = new ArrayList<>();
+        for (Object item : values) {
+            resultSet.add(PlcValues.of((Byte) item));
+        }
+
+        if (resultSet.size() == 1) {
+            return resultSet.get(0);
+        } else {
+            return new PlcList(resultSet);
+        }
+    }
 }
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenPDOField.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenPDOField.java
new file mode 100644
index 0000000..f65e5b3
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/field/CANOpenPDOField.java
@@ -0,0 +1,64 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.java.can.field;
+
+import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.canopen.readwrite.types.CANOpenDataType;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CANOpenPDOField extends CANOpenField {
+
+    public static final Pattern ADDRESS_PATTERN = Pattern.compile("PDO:" + CANOpenField.NODE_PATTERN + ":(?<canDataType>\\w+)(\\[(?<numberOfElements>\\d)])?");
+    private final CANOpenDataType canOpenDataType;
+
+    public CANOpenPDOField(int node, CANOpenDataType canOpenDataType) {
+        super(node);
+        this.canOpenDataType = canOpenDataType;
+    }
+
+    public CANOpenDataType getCanOpenDataType() {
+        return canOpenDataType;
+    }
+
+    public static boolean matches(String addressString) {
+        return ADDRESS_PATTERN.matcher(addressString).matches();
+    }
+
+    public static Matcher getMatcher(String addressString) throws PlcInvalidFieldException {
+        Matcher matcher = ADDRESS_PATTERN.matcher(addressString);
+        if (matcher.matches()) {
+            return matcher;
+        }
+
+        throw new PlcInvalidFieldException(addressString, ADDRESS_PATTERN);
+    }
+
+    public static CANOpenPDOField of(String addressString) {
+        Matcher matcher = getMatcher(addressString);
+        int nodeId = Integer.parseInt(matcher.group("nodeId"));
+
+        String canDataTypeString = matcher.group("canDataType");
+        CANOpenDataType canOpenDataType = CANOpenDataType.valueOf(canDataTypeString);
+
+        return new CANOpenPDOField(nodeId, canOpenDataType);
+    }
+
+}
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
index b5aa34e..d96fe19 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
@@ -19,8 +19,12 @@ under the License.
 package org.apache.plc4x.java.can.protocol;
 
 import org.apache.plc4x.java.api.messages.*;
+import org.apache.plc4x.java.api.model.PlcConsumerRegistration;
 import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.model.PlcSubscriptionHandle;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.apache.plc4x.java.api.types.PlcSubscriptionType;
+import org.apache.plc4x.java.api.value.PlcList;
 import org.apache.plc4x.java.api.value.PlcNull;
 import org.apache.plc4x.java.api.value.PlcValue;
 import org.apache.plc4x.java.can.api.CANFrame;
@@ -31,6 +35,7 @@ import org.apache.plc4x.java.can.api.conversation.canopen.SDOUploadConversation;
 import org.apache.plc4x.java.can.configuration.CANConfiguration;
 import org.apache.plc4x.java.can.context.CANOpenDriverContext;
 import org.apache.plc4x.java.can.field.CANOpenField;
+import org.apache.plc4x.java.can.field.CANOpenPDOField;
 import org.apache.plc4x.java.can.field.CANOpenSDOField;
 import org.apache.plc4x.java.can.socketcan.SocketCANConversation;
 import org.apache.plc4x.java.canopen.readwrite.*;
@@ -49,18 +54,28 @@ import org.apache.plc4x.java.spi.generation.ReadBuffer;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 import org.apache.plc4x.java.spi.messages.*;
 import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
+import org.apache.plc4x.java.spi.model.DefaultPlcConsumerRegistration;
+import org.apache.plc4x.java.spi.model.InternalPlcSubscriptionHandle;
+import org.apache.plc4x.java.spi.model.SubscriptionPlcField;
 import org.apache.plc4x.java.spi.transaction.RequestTransactionManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.time.Duration;
+import java.time.Instant;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Timer;
 import java.util.TimerTask;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Consumer;
 
-public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> implements HasConfiguration<CANConfiguration> {
+public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> implements HasConfiguration<CANConfiguration>, PlcSubscriber {
 
     private static final Duration REQUEST_TIMEOUT = Duration.ofSeconds(10L);
     private Logger logger = LoggerFactory.getLogger(CANOpenProtocolLogic.class);
@@ -71,6 +86,8 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
     private CANOpenDriverContext canContext;
     private CANConversation<CANFrame> conversation;
 
+    private Map<DefaultPlcConsumerRegistration, Consumer<PlcSubscriptionEvent>> consumers = new ConcurrentHashMap<>();
+
     @Override
     public void setConfiguration(CANConfiguration configuration) {
         this.configuration = configuration;
@@ -130,7 +147,7 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
     public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
         CompletableFuture<PlcWriteResponse> response = new CompletableFuture<>();
         if (writeRequest.getFieldNames().size() != 1) {
-            response.completeExceptionally(new IllegalArgumentException("Unsupported field"));
+            response.completeExceptionally(new IllegalArgumentException("You can write only one field at the time"));
             return response;
         }
 
@@ -140,12 +157,16 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
             return response;
         }
 
-        if (!(field instanceof CANOpenSDOField)) {
-            response.completeExceptionally(new IllegalArgumentException("Only CANOpenSDOField instances are supported"));
+        if (field instanceof CANOpenSDOField) {
+            writeInternally((InternalPlcWriteRequest) writeRequest, (CANOpenSDOField) field, response);
             return response;
-        };
+        }
+        if (field instanceof CANOpenPDOField) {
+            writeInternally((InternalPlcWriteRequest) writeRequest, (CANOpenPDOField) field, response);
+            return response;
+        }
 
-        writeInternally((InternalPlcWriteRequest) writeRequest, (CANOpenSDOField) field, response);
+        response.completeExceptionally(new IllegalArgumentException("Only CANOpenSDOField instances are supported"));
         return response;
     }
 
@@ -158,15 +179,31 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
         try {
             download.execute((value, error) -> {
                 String fieldName = writeRequest.getFieldNames().iterator().next();
-                Map<String, PlcResponseCode> fields = new HashMap<>();
-                fields.put(fieldName, PlcResponseCode.OK);
-                response.complete(new DefaultPlcWriteResponse(writeRequest, fields));
+                response.complete(new DefaultPlcWriteResponse(writeRequest, Collections.singletonMap(fieldName, PlcResponseCode.OK)));
             });
         } catch (Exception e) {
             response.completeExceptionally(e);
         }
     }
 
+    private void writeInternally(InternalPlcWriteRequest writeRequest, CANOpenPDOField field, CompletableFuture<PlcWriteResponse> response) {
+        PlcValue writeValue = writeRequest.getPlcValues().get(0);
+
+        try {
+            String fieldName = writeRequest.getFieldNames().iterator().next();
+            //
+            WriteBuffer buffer = DataItemIO.staticSerialize(writeValue, field.getCanOpenDataType(), writeValue.getLength() / 8, true);
+            if (buffer != null) {
+                context.sendToWire(new SocketCANFrame(field.getNodeId(), buffer.getData()));
+                response.complete(new DefaultPlcWriteResponse(writeRequest, Collections.singletonMap(fieldName, PlcResponseCode.OK)));
+            } else {
+                response.complete(new DefaultPlcWriteResponse(writeRequest, Collections.singletonMap(fieldName, PlcResponseCode.INVALID_DATA)));
+            }
+        } catch (Exception e) {
+            response.completeExceptionally(e);
+        }
+    }
+
     public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
         CompletableFuture<PlcReadResponse> response = new CompletableFuture<>();
         if (readRequest.getFieldNames().size() != 1) {
@@ -190,9 +227,28 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
     }
 
     @Override
-    public CompletableFuture<PlcSubscriptionResponse> subscribe(PlcSubscriptionRequest subscriptionRequest) {
-        ((InternalPlcSubscriptionRequest) subscriptionRequest).getSubscriptionFields().get(0).getPlcSubscriptionType();
-        return super.subscribe(subscriptionRequest);
+    public CompletableFuture<PlcSubscriptionResponse> subscribe(PlcSubscriptionRequest request) {
+        InternalPlcSubscriptionRequest rq = (InternalPlcSubscriptionRequest) request;
+
+        List<SubscriptionPlcField> fields = rq.getSubscriptionFields();
+
+        Map<String, ResponseItem<PlcSubscriptionHandle>> answers = new LinkedHashMap<>();
+        DefaultPlcSubscriptionResponse response = new DefaultPlcSubscriptionResponse(rq, answers);
+
+        for (Map.Entry<String, SubscriptionPlcField> entry : rq.getSubscriptionPlcFieldMap().entrySet()) {
+            SubscriptionPlcField subscription = entry.getValue();
+            if (subscription.getPlcSubscriptionType() != PlcSubscriptionType.EVENT) {
+                answers.put(entry.getKey(), new ResponseItem<>(PlcResponseCode.UNSUPPORTED, null));
+            } else if (!(subscription.getPlcField() instanceof CANOpenPDOField)) {
+                answers.put(entry.getKey(), new ResponseItem<>(PlcResponseCode.INVALID_ADDRESS, null));
+            } else {
+                answers.put(entry.getKey(), new ResponseItem<>(PlcResponseCode.OK,
+                    new CANOpenSubscriptionHandle(this, entry.getKey(), (CANOpenPDOField) subscription.getPlcField())
+                ));
+            }
+        }
+
+        return CompletableFuture.completedFuture(response);
     }
 
     private void readInternally(InternalPlcReadRequest readRequest, CANOpenSDOField field, CompletableFuture<PlcReadResponse> response) {
@@ -220,6 +276,12 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
 
         if (service != null) {
             logger.info("Decoded CANOpen {} from {}, message {}", service, Math.abs(service.getMin() - msg.getIdentifier()), payload);
+
+            if (service.getPdo() && payload instanceof CANOpenPDOPayload) {
+                logger.info("Broadcasting PDO to subscribers");
+                publishEvent(msg.getIdentifier(), (CANOpenPDOPayload) payload);
+            }
+
         } else {
             logger.info("CAN message {}, {}", msg.getIdentifier(), msg);
         }
@@ -234,6 +296,57 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
 //        }
     }
 
+    private void publishEvent(int nodeId, CANOpenPDOPayload payload) {
+        for (Map.Entry<DefaultPlcConsumerRegistration, Consumer<PlcSubscriptionEvent>> entry : consumers.entrySet()) {
+            DefaultPlcConsumerRegistration registration = entry.getKey();
+            Consumer<PlcSubscriptionEvent> consumer = entry.getValue();
+
+            for (InternalPlcSubscriptionHandle handler : registration.getAssociatedHandles()) {
+                if (handler instanceof CANOpenSubscriptionHandle) {
+                    CANOpenSubscriptionHandle handle = (CANOpenSubscriptionHandle) handler;
+
+                    if (handle.matches(nodeId)) {
+                        CANOpenPDOField field = handle.getField();
+                        byte[] data = payload.getPdo().getData();
+                        try {
+                            PlcValue value = DataItemIO.staticParse(new ReadBuffer(data, true), field.getCanOpenDataType(), data.length);
+                            DefaultPlcSubscriptionEvent event = new DefaultPlcSubscriptionEvent(
+                                Instant.now(),
+                                Collections.singletonMap(
+                                    handle.getName(),
+                                    new ResponseItem<>(PlcResponseCode.OK, value)
+                                )
+                            );
+                            consumer.accept(event);
+                        } catch (ParseException e) {
+                            logger.warn("Could not parse data to desired type: {}", field.getCanOpenDataType(), e);
+                            DefaultPlcSubscriptionEvent event = new DefaultPlcSubscriptionEvent(
+                                Instant.now(),
+                                Collections.singletonMap(
+                                    handle.getName(),
+                                    new ResponseItem<>(PlcResponseCode.INVALID_DATA, new PlcNull())
+                                )
+                            );
+                            consumer.accept(event);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public PlcConsumerRegistration register(Consumer<PlcSubscriptionEvent> consumer, Collection<PlcSubscriptionHandle> handles) {
+        final DefaultPlcConsumerRegistration consumerRegistration =new DefaultPlcConsumerRegistration(this, consumer, handles.toArray(new InternalPlcSubscriptionHandle[0]));
+        consumers.put(consumerRegistration, consumer);
+        return consumerRegistration;
+    }
+
+    @Override
+    public void unregister(PlcConsumerRegistration registration) {
+        consumers.remove(registration);
+    }
+
     @Override
     public void close(ConversationContext<SocketCANFrame> context) {
 
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenSubscriptionHandle.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenSubscriptionHandle.java
new file mode 100644
index 0000000..07ecb3b
--- /dev/null
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenSubscriptionHandle.java
@@ -0,0 +1,28 @@
+package org.apache.plc4x.java.can.protocol;
+
+import org.apache.plc4x.java.can.field.CANOpenPDOField;
+import org.apache.plc4x.java.spi.messages.PlcSubscriber;
+import org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionHandle;
+
+public class CANOpenSubscriptionHandle extends DefaultPlcSubscriptionHandle {
+    private final String name;
+    private final CANOpenPDOField field;
+
+    public CANOpenSubscriptionHandle(PlcSubscriber subscriber, String name, CANOpenPDOField field) {
+        super(subscriber);
+        this.name = name;
+        this.field = field;
+    }
+
+    public boolean matches(int identifier) {
+        return field.getNodeId() == 0 || field.getNodeId() == identifier;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public CANOpenPDOField getField() {
+        return field;
+    }
+}


[plc4x] 16/19: CANopen adjustments.

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 695c0b651b7fdb98e0d8eea11289504c710151a4
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Thu Sep 3 13:46:10 2020 +0200

    CANopen adjustments.
---
 .../src/main/resources/protocols/can/canopen.mspec | 144 ++++++++++++++-------
 sandbox/test-java-can-driver/pom.xml               |   5 +
 .../java/can/protocol/CANOpenProtocolLogic.java    |  12 +-
 .../testsuite/CANOpenPayloadTestSuite.xml          |  71 ++++++----
 4 files changed, 153 insertions(+), 79 deletions(-)

diff --git a/protocols/can/src/main/resources/protocols/can/canopen.mspec b/protocols/can/src/main/resources/protocols/can/canopen.mspec
index c929ae4..bb825f3 100644
--- a/protocols/can/src/main/resources/protocols/can/canopen.mspec
+++ b/protocols/can/src/main/resources/protocols/can/canopen.mspec
@@ -17,21 +17,22 @@
  * under the License.
  */
 
-[enum uint 4 'CANOpenService' [bit 'sdo', bit 'pdo', bit 'transmit', bit 'receive']
-    ['0b0000' BROADCAST    ['false', 'false', 'false', 'false'] ]
-    ['0b0001' SYNC         ['false', 'false', 'false', 'false'] ]
-    ['0b0010' TIME         ['false', 'false', 'false', 'false'] ]
-    ['0b1110' NMT          ['false', 'false', 'false', 'false'] ]
-    ['0b1100' SDO_REQUEST  ['true',  'false', 'false', 'true' ] ]
-    ['0b1011' SDO_RESPONSE ['true',  'false', 'true',  'false'] ]
-    ['0b0011' TPDO_1       ['false', 'true',  'true',  'false'] ]
-    ['0b0100' RPDO_1       ['false', 'true',  'false', 'true' ] ]
-    ['0b0101' TPDO_2       ['false', 'true',  'true',  'false'] ]
-    ['0b0110' RPDO_2       ['false', 'true',  'false', 'true' ] ]
-    ['0b0111' TPDO_3       ['false', 'true',  'true',  'false'] ]
-    ['0b1000' RPDO_3       ['false', 'true',  'false', 'true' ] ]
-    ['0b1001' TPDO_4       ['false', 'true',  'true',  'false'] ]
-    ['0b1010' RPDO_4       ['false', 'true',  'false', 'true' ] ]
+[enum uint 4 'CANOpenService' [uint 8 'min', uint 8 'max', bit 'pdo']
+    ['0b0000' NMT             ['0',     '0'    , 'false' ] ]
+    ['0b0001' SYNC            ['0x80',  '0x80' , 'false' ] ]
+    ['0b0001' EMCY            ['0x81',  '0xFF' , 'false' ] ]
+    ['0b0010' TIME            ['0x100', '0x100', 'false' ] ]
+    ['0b0011' TRANSMIT_PDO_1  ['0x181', '0x1FF', 'true'  ] ]
+    ['0b0100' RECEIVE_PDO_1   ['0x201', '0x27F', 'true'  ] ]
+    ['0b0101' TRANSMIT_PDO_2  ['0x281', '0x2FF', 'true'  ] ]
+    ['0b0110' RECEIVE_PDO_2   ['0x301', '0x37F', 'true'  ] ]
+    ['0b0111' TRANSMIT_PDO_3  ['0x381', '0x3FF', 'true'  ] ]
+    ['0b1000' RECEIVE_PDO_3   ['0x401', '0x47F', 'true'  ] ]
+    ['0b1001' TRANSMIT_PDO_4  ['0x481', '0x4FF', 'true'  ] ]
+    ['0b1010' RECEIVE_PDO_4   ['0x501', '0x57F', 'true'  ] ]
+    ['0b1011' TRANSMIT_SDO    ['0x581', '0x5FF', 'false' ] ]
+    ['0b1100' RECEIVE_SDO     ['0x601', '0x67F', 'false' ] ]
+    ['0b1110' HEARTBEAT       ['0x701', '0x77F', 'false' ] ]
 ]
 
 [enum uint 8 'NMTStateRequest'
@@ -51,7 +52,7 @@
 
 [discriminatedType 'CANOpenPayload' [CANOpenService 'function']
     [typeSwitch 'function'
-        ['CANOpenService.BROADCAST' CANOpenBroadcastPayload
+        ['CANOpenService.NMT' CANOpenNetworkPayload
             [enum NMTStateRequest 'request']
             [reserved uint 1 '0x00']
             [simple uint 7 'node']
@@ -59,56 +60,103 @@
         ['CANOpenService.TIME' CANOpenTimeSynchronization
             [simple TimeOfDay 'timeOfDay']
         ]
-        ['CANOpenService.NMT' CANOpenNetworkPayload
-            [enum NMTState 'state']
-        ]
-        ['CANOpenService.SDO_REQUEST' CANOpenSDORequest
-            [enum SDOCommand 'command']
-            [reserved uint 1 '0x00']
-            [implicit uint 2 'size' 'COUNT(data)']
-            [simple bit 'expedited'] // segmented
-            [simple bit 'placement']
-            [simple uint 16 'index']
-            [simple uint 8 'subindex']
-            [array uint 8 'data' COUNT 'size']
-        ]
-        ['CANOpenService.SDO_RESPONSE' CANOpenSDOResponse
-            [enum SDOCommand 'command']
-            [reserved uint 1 '0x00']
-            [implicit uint 2 'size' 'COUNT(data)']
-            [simple bit 'expedited'] // segmented
-            [simple bit 'placement']
-            [simple uint 16 'index']
-            [simple uint 8 'subindex']
-            [array uint 8 'data' COUNT 'size']
-        ]
-        ['CANOpenService.RPDO_1' CANOpenRPDO
+        ['CANOpenService.RECEIVE_PDO_1' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['1', 'true']]
         ]
-        ['CANOpenService.TPDO_1' CANOpenTPDO
+        ['CANOpenService.TRANSMIT_PDO_1' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['1', 'false']]
         ]
-        ['CANOpenService.RPDO_2' CANOpenRPDO
+        ['CANOpenService.RECEIVE_PDO_2' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['2', 'true']]
         ]
-        ['CANOpenService.TPDO_2' CANOpenTPDO
+        ['CANOpenService.TRANSMIT_PDO_2' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['1', 'false']]
         ]
-        ['CANOpenService.RPDO_3' CANOpenRPDO
+        ['CANOpenService.RECEIVE_PDO_3' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['3', 'true']]
         ]
-        ['CANOpenService.TPDO_3' CANOpenTPDO
+        ['CANOpenService.TRANSMIT_PDO_3' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['1', 'false']]
         ]
-        ['CANOpenService.RPDO_4' CANOpenRPDO
+        ['CANOpenService.RECEIVE_PDO_4' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['4', 'true']]
         ]
-        ['CANOpenService.TPDO_4' CANOpenTPDO
+        ['CANOpenService.TRANSMIT_PDO_4' CANOpenPDOPayload
             [simple CANOpenPDO 'pdo' ['1', 'false']]
         ]
+        ['CANOpenService.TRANSMIT_SDO' CANOpenSDORequest
+            [enum SDOCommand 'command']
+            [simple SDORequest 'request' ['command']]
+        ]
+        ['CANOpenService.RECEIVE_SDO' CANOpenSDOResponse
+            [enum SDOCommand 'command']
+            [simple SDOResponse 'response' ['command']]
+        ]
+        ['CANOpenService.HEARTBEAT' CANOpenHeartbeatPayload
+            [enum NMTState 'state']
+        ]
+    ]
+]
+
+[type 'SDORequest' [SDOCommand 'command']
+    [typeSwitch 'command'
+        ['SDOCommand.INITIALIZE_DOWNLOAD' SDOInitializeDownloadRequest
+            [reserved uint 1 '0x00']
+            [implicit uint 2 'size' 'expedited && indicated ? 4 - COUNT(data) : 0']
+            [simple bit 'expedited']
+            [simple bit 'indicated']
+            [simple Multiplexer 'address']
+            [array int 8 'data' COUNT '(expedited && indicated) ? 4 - size : 0']
+            [padding uint 8 'alignment' '0x00' '4 - (COUNT(data))']
+        ]
+        ['SDOCommand.SEGMENT_DOWNLOAD' SDOSegmentDownloadRequest
+            [simple bit 'toggle']
+            [implicit uint 3 'size' '7 - COUNT(data)']
+            [simple bit 'last']
+            [array int 8 'data' COUNT '7 - data']
+            [padding uint 8 'alignment' '0x00' '7 - (COUNT(data))']
+        ]
+        ['SDOCommand.INITIALIZE_UPLOAD' SDOInitializeUploadRequest
+            [reserved uint 5 '0x00']
+            [simple Multiplexer 'address']
+            [reserved int 32 '0x00'] // padding
+        ]
+    ]
+]
+
+[type 'SDOResponse' [SDOCommand 'command']
+    [typeSwitch 'command'
+        ['SDOCommand.SEGMENT_UPLOAD' SDOSegmentUploadResponse
+            [reserved uint 5 '0x00']
+            [simple Multiplexer 'address']
+            [reserved int 32 '0x00'] // padding
+        ]
+        ['SDOCommand.INITIALIZE_DOWNLOAD' SDOInitializeDownloadResponse
+            [simple bit 'toggle']
+            [reserved uint 4 '0x00']
+            [reserved int 32 '0x00'] // padding
+        ]
+        ['SDOCommand.INITIALIZE_UPLOAD' SDOInitializeUploadResponse
+            [simple SDOSegment 'segment']
+        ]
     ]
 ]
 
+[type 'SDOSegment'
+    [reserved uint 1 '0x00']
+    [implicit uint 2 'size' 'expedited && indicated ? 4 - COUNT(data) : 0']
+    [simple bit 'expedited']
+    [simple bit 'indicated']
+    [simple Multiplexer 'address']
+    [array int 8 'data' COUNT '(expedited && indicated) ? 4 - size : 0']
+    [padding uint 8 'alignment' '0x00' '4 - (COUNT(data))']
+]
+
+[type 'Multiplexer'
+    [simple uint 16 'index']
+    [simple uint 8 'subindex']
+]
+
 [enum uint 3 'SDOCommand'
     ['0x00' SEGMENT_DOWNLOAD]
     ['0x01' INITIALIZE_DOWNLOAD]
@@ -120,7 +168,7 @@
 ]
 
 [type 'CANOpenPDO' [uint 2 'index', bit 'receive']
-
+    [array int 8 'data' COUNT '8']
 ]
 
 [type 'TimeOfDay'
diff --git a/sandbox/test-java-can-driver/pom.xml b/sandbox/test-java-can-driver/pom.xml
index 50e48e7..e3e72c4 100644
--- a/sandbox/test-java-can-driver/pom.xml
+++ b/sandbox/test-java-can-driver/pom.xml
@@ -73,6 +73,11 @@
     </dependency>
 
     <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-configuration2</artifactId>
+    </dependency>
+
+    <dependency>
       <groupId>org.apache.plc4x</groupId>
       <artifactId>plc4j-transport-socketcan</artifactId>
       <version>0.8.0-SNAPSHOT</version>
diff --git a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
index 0090e0e..c193ec3 100644
--- a/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
+++ b/sandbox/test-java-can-driver/src/main/java/org/apache/plc4x/java/can/protocol/CANOpenProtocolLogic.java
@@ -19,8 +19,10 @@ under the License.
 package org.apache.plc4x.java.can.protocol;
 
 import org.apache.plc4x.java.can.configuration.CANConfiguration;
+import org.apache.plc4x.java.canopen.readwrite.CANOpenHeartbeatPayload;
 import org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload;
 import org.apache.plc4x.java.canopen.readwrite.CANOpenPayload;
+import org.apache.plc4x.java.canopen.readwrite.io.CANOpenHeartbeatPayloadIO;
 import org.apache.plc4x.java.canopen.readwrite.io.CANOpenNetworkPayloadIO;
 import org.apache.plc4x.java.canopen.readwrite.io.CANOpenPayloadIO;
 import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService;
@@ -58,7 +60,7 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
     public void onConnect(ConversationContext<SocketCANFrame> context) {
         try {
             if (configuration.isHeartbeat()) {
-                context.sendToWire(createFrame(new CANOpenNetworkPayload(NMTState.BOOTED_UP)));
+                context.sendToWire(createFrame(new CANOpenHeartbeatPayload(NMTState.BOOTED_UP)));
                 context.fireConnected();
 
                 this.heartbeat = new Timer();
@@ -66,7 +68,7 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
                     @Override
                     public void run() {
                         try {
-                            context.sendToWire(createFrame(new CANOpenNetworkPayload(NMTState.OPERATIONAL)));
+                            context.sendToWire(createFrame(new CANOpenHeartbeatPayload(NMTState.OPERATIONAL)));
                         } catch (ParseException e) {
                             e.printStackTrace();
                         }
@@ -78,10 +80,10 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<SocketCANFrame> impl
         }
     }
 
-    private SocketCANFrame createFrame(CANOpenNetworkPayload state) throws ParseException {
+    private SocketCANFrame createFrame(CANOpenHeartbeatPayload state) throws ParseException {
         WriteBuffer buffer = new WriteBuffer(state.getLengthInBytes());
-        CANOpenNetworkPayloadIO.staticSerialize(buffer, state);
-        return new SocketCANFrame(cobId(CANOpenService.NMT), buffer.getData());
+        CANOpenHeartbeatPayloadIO.staticSerialize(buffer, state);
+        return new SocketCANFrame(cobId(CANOpenService.HEARTBEAT), buffer.getData());
     }
 
     @Override
diff --git a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
index 3188005..8537aee 100644
--- a/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
+++ b/sandbox/test-java-can-driver/src/test/resources/testsuite/CANOpenPayloadTestSuite.xml
@@ -67,12 +67,12 @@
     <raw>00</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>NMT</arg1>
+      <arg1>HEARTBEAT</arg1>
     </parser-arguments>
     <xml>
-      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+      <CANOpenHeartbeatPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenHeartbeatPayload">
         <state>BOOTED_UP</state>
-      </CANOpenNetworkPayload>
+      </CANOpenHeartbeatPayload>
     </xml>
   </testcase>
 
@@ -81,12 +81,12 @@
     <raw>7F</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>NMT</arg1>
+      <arg1>HEARTBEAT</arg1>
     </parser-arguments>
     <xml>
-      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+      <CANOpenHeartbeatPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenHeartbeatPayload">
         <state>PRE_OPERATIONAL</state>
-      </CANOpenNetworkPayload>
+      </CANOpenHeartbeatPayload>
     </xml>
   </testcase>
 
@@ -95,21 +95,21 @@
     <raw>05</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>NMT</arg1>
+      <arg1>HEARTBEAT</arg1>
     </parser-arguments>
     <xml>
-      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+      <CANOpenHeartbeatPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenHeartbeatPayload">
         <state>OPERATIONAL</state>
-      </CANOpenNetworkPayload>
+      </CANOpenHeartbeatPayload>
     </xml>
   </testcase>
 
   <testcase>
-    <name>SDO request, payload: 4317100000000000</name>
-    <raw>4317100000000000</raw>
+    <name>SDO request, payload: 43171000</name>
+    <raw>43171000</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>SDO_REQUEST</arg1>
+      <arg1>RECEIVE_SDO</arg1>
     </parser-arguments>
     <xml>
       <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
@@ -124,11 +124,11 @@
   </testcase>
 
   <testcase>
-    <name>SDO request, payload: 00171000A00F0000</name>
-    <raw>00171000A00F0000</raw>
+    <name>SDO request, payload: 00171000<!--A00F0000--></name>
+    <raw>00171000<!--A00F0000--></raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>SDO_REQUEST</arg1>
+      <arg1>RECEIVE_SDO</arg1>
     </parser-arguments>
     <xml>
       <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
@@ -147,7 +147,7 @@
     <raw>2B171000D00F</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>SDO_REQUEST</arg1>
+      <arg1>RECEIVE_SDO</arg1>
     </parser-arguments>
     <xml>
       <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
@@ -165,11 +165,11 @@
   </testcase>
 
   <testcase>
-    <name>SDO write result, payload: 60171000D0F00000</name>
-    <raw>00171000A00F0000</raw>
+    <name>SDO write result, payload: 60171000<!--A00F0000--></name>
+    <raw>00171000<!--A00F0000--></raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>SDO_REQUEST</arg1>
+      <arg1>TRANSMIT_SDO</arg1>
     </parser-arguments>
     <xml>
       <CANOpenSDORequest className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
@@ -185,16 +185,21 @@
 
   <!-- samples -->
   <testcase>
-    <name>SDO response, payload: 6000200000</name>
-    <raw>6000200000</raw>
+    <name>SDO response, payload: 60002000</name>
+    <raw>60002000</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>SDO_RESPONSE</arg1>
+      <arg1>TRANSMIT_SDO</arg1>
     </parser-arguments>
     <xml>
-      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
-        <state>PRE_OPERATIONAL</state>
-      </CANOpenNetworkPayload>
+      <CANOpenSDOResponse className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse">
+        <command>SEGMENT_UPLOAD</command>
+        <expedited>false</expedited>
+        <placement>false</placement>
+        <index>8192</index>
+        <subindex>0</subindex>
+        <data/>
+      </CANOpenSDOResponse>
     </xml>
   </testcase>
 
@@ -203,14 +208,28 @@
     <raw>78563412</raw>
     <root-type>CANOpenPayload</root-type>
     <parser-arguments>
-      <arg1>SDO_RESPONSE</arg1>
+      <arg1>RECEIVE_SDO</arg1>
     </parser-arguments>
     <xml>
       <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
         <state>PRE_OPERATIONAL</state>
       </CANOpenNetworkPayload>
     </xml>
+  </testcase>
+
 
+  <testcase>
+    <name>PDO, payload: F9013E014C015C01</name>
+    <raw>F9013E014C015C01</raw>
+    <root-type>CANOpenPayload</root-type>
+    <parser-arguments>
+      <arg1>TRANSMIT_PDO_1</arg1>
+    </parser-arguments>
+    <xml>
+      <CANOpenNetworkPayload className="org.apache.plc4x.java.canopen.readwrite.CANOpenNetworkPayload">
+        <state>PRE_OPERATIONAL</state>
+      </CANOpenNetworkPayload>
+    </xml>
   </testcase>
 
 </test:testsuite>
\ No newline at end of file


[plc4x] 02/19: - removed the toPlcValue method from the Message interface (It was actually only used in one place of the experimental BACnetIp driver)

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit c825f97ed974ce7a341ff83f637d8d301dbaf22a
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Tue Oct 6 13:58:15 2020 +0200

    - removed the toPlcValue method from the Message interface (It was actually only used in one place of the experimental BACnetIp driver)
---
 .../resources/templates/java/pojo-template.ftlh    | 93 ----------------------
 .../apache/plc4x/java/spi/generation/Message.java  |  4 -
 .../configuration/BacNetIpConfiguration.java       |  5 +-
 .../bacnetip/protocol/BacNetIpProtocolLogic.java   | 17 +++-
 4 files changed, 18 insertions(+), 101 deletions(-)

diff --git a/build-utils/language-java/src/main/resources/templates/java/pojo-template.ftlh b/build-utils/language-java/src/main/resources/templates/java/pojo-template.ftlh
index bf09737..e6d546d 100644
--- a/build-utils/language-java/src/main/resources/templates/java/pojo-template.ftlh
+++ b/build-utils/language-java/src/main/resources/templates/java/pojo-template.ftlh
@@ -290,99 +290,6 @@ public<#if helper.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${
         return lengthInBits;
     }
 
-    public PlcValue toPlcValue() {
-<#if type.propertyFields?has_content>
-        Map<String, PlcValue> fieldValues = new TreeMap<>();
-<#list type.propertyFields as field>
-<#switch field.typeName>
-<#case "array">
-    <#assign arrayField = field>
-
-        {
-            List<PlcValue> plcValues = new ArrayList<>(${arrayField.name}.length);
-            for(${helper.getLanguageTypeNameForField(field)} item : ${arrayField.name}) {
-        <#if helper.isSimpleTypeReference(arrayField.type)>
-                plcValues.add(PlcValues.of(item));
-        <#else>
-                plcValues.add(item.toPlcValue());
-        </#if>
-            }
-            fieldValues.put("${arrayField.name}", new PlcList(plcValues));
-        }
-    <#break>
-<#case "manualArray">
-    <#assign manualArrayField = field>
-
-        {
-            List<PlcValue> plcValues = new ArrayList<>(${manualArrayField.name}.length);
-            for(${helper.getLanguageTypeNameForField(field)} item : ${manualArrayField.name}) {
-                <#if helper.isSimpleTypeReference(manualArrayField.type)>
-                plcValues.add(PlcValues.of(item));
-                <#else>
-                plcValues.add(item.toPlcValue());
-                </#if>
-            }
-            fieldValues.put("${manualArrayField.name}", new PlcList(plcValues));
-        }
-<#break>
-<#case "enum">
-    <#assign enumField = field>
-
-        fieldValues.put("${enumField.name}", new PlcString(${enumField.name}.name()));
-<#break>
-<#case "manual">
-    <#assign manualField = field>
-
-    <#if helper.isSimpleTypeReference(manualField.type)>
-        fieldValues.put("${manualField.name}", PlcValues.of(${manualField.name}));
-    <#else>
-        fieldValues.put("${manualField.name}", ${manualField.name}.toPlcValue());
-    </#if>
-<#break>
-<#case "simple">
-    <#assign simpleField = field>
-
-    <#if helper.isSimpleTypeReference(simpleField.type)>
-        fieldValues.put("${simpleField.name}", PlcValues.of(${simpleField.name}));
-    <#else>
-        fieldValues.put("${simpleField.name}", ${simpleField.name}.toPlcValue());
-    </#if>
-<#break>
-<#case "optional">
-    <#assign optionalField = field>
-
-        if(${optionalField.name} != null) {
-            <#if helper.isSimpleTypeReference(optionalField.type)>
-            fieldValues.put("${optionalField.name}", PlcValues.of(${optionalField.name}));
-            <#else>
-            fieldValues.put("${optionalField.name}", ${optionalField.name}.toPlcValue());
-            </#if>
-        } else {
-            fieldValues.put("${optionalField.name}", null);
-        }
-<#break>
-<#case "switch">
-    <#assign switchField = field>
-
-        PlcStruct superStruct = (PlcStruct) super.toPlcValue();
-        fieldValues.putAll(superStruct.getStruct());
-<#break>
-<#case "virtual">
-    <#assign virtualField = field>
-    <#if helper.isSimpleTypeReference(virtualField.type)>
-
-        fieldValues.put("${virtualField.name}", PlcValues.of(${virtualField.name}));
-    </#if>
-<#break>
-</#switch>
-</#list>
-
-        return new PlcStruct(fieldValues);
-<#else>
-        return null;
-</#if>
-    }
-
     @Override
     @JsonIgnore
     public MessageIO<<#if type.parentType??>${type.parentType.name}<#else>${type.name}</#if>, <#if type.parentType??>${type.parentType.name}<#else>${type.name}</#if>> getMessageIO() {
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/Message.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/Message.java
index 7d9afef..5b394d3 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/Message.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/Message.java
@@ -19,16 +19,12 @@
 
 package org.apache.plc4x.java.spi.generation;
 
-import org.apache.plc4x.java.api.value.PlcValue;
-
 public interface Message {
 
     int getLengthInBytes();
 
     int getLengthInBits();
 
-    PlcValue toPlcValue();
-
     MessageIO<? extends Message, ? extends Message> getMessageIO();
 
 }
diff --git a/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/configuration/BacNetIpConfiguration.java b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/configuration/BacNetIpConfiguration.java
index 0056bda..b277519 100644
--- a/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/configuration/BacNetIpConfiguration.java
+++ b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/configuration/BacNetIpConfiguration.java
@@ -103,8 +103,11 @@ public class BacNetIpConfiguration implements Configuration, UdpTransportConfigu
             }
             // This is a normal udp packet.
             else {
-                return packet.getPayload().getPayload().getPayload().getRawData();
+                if((packet.getPayload() != null) && (packet.getPayload().getPayload() != null) && (packet.getPayload().getPayload().getPayload() != null)) {
+                    return packet.getPayload().getPayload().getPayload().getRawData();
+                }
             }
+            return null;
         };
     }
 
diff --git a/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/protocol/BacNetIpProtocolLogic.java b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/protocol/BacNetIpProtocolLogic.java
index 4e3992e..4041d1a 100644
--- a/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/protocol/BacNetIpProtocolLogic.java
+++ b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/protocol/BacNetIpProtocolLogic.java
@@ -136,7 +136,6 @@ public class BacNetIpProtocolLogic extends Plc4xProtocolBase<BVLC> implements Ha
                         // These are value change notifications. Ignore the rest.
                         if(notification.getPropertyIdentifier()[0] == (short) 0x55) {
                             final BACnetTag baCnetTag = notification.getValue();
-                            final PlcValue plcValue = baCnetTag.toPlcValue();
 
                             // Initialize an enriched version of the PlcStruct.
                             final Map<String, PlcValue> enrichedPlcValue = new HashMap<>();
@@ -144,8 +143,20 @@ public class BacNetIpProtocolLogic extends Plc4xProtocolBase<BVLC> implements Ha
                             enrichedPlcValue.put("objectType", new PlcDINT(objectType));
                             enrichedPlcValue.put("objectInstance", new PlcUDINT(objectInstance));
                             enrichedPlcValue.put("address", new PlcString(toString(curField)));
-                            // Add all of the existing attributes.
-                            enrichedPlcValue.putAll(plcValue.getStruct());
+
+                            // From the original BACNet tag
+                            enrichedPlcValue.put("typeOrTagNumber", PlcValues.of(baCnetTag.getTypeOrTagNumber()));
+                            enrichedPlcValue.put("lengthValueType", PlcValues.of(baCnetTag.getLengthValueType()));
+                            if(baCnetTag.getExtTagNumber() != null) {
+                                enrichedPlcValue.put("extTagNumber", PlcValues.of(baCnetTag.getExtTagNumber()));
+                            } else {
+                                enrichedPlcValue.put("extTagNumber", new PlcNull());
+                            }
+                            if(baCnetTag.getExtLength() != null) {
+                                enrichedPlcValue.put("extLength", PlcValues.of(baCnetTag.getExtLength()));
+                            } else {
+                                enrichedPlcValue.put("extLength", new PlcNull());
+                            }
 
                             // Use the information in the edeModel to enrich the information.
                             if(edeModel != null) {


[plc4x] 10/19: Fix socketcan transport.

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch feature/socketcan
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit ccdeb589e90ff15b93ec00492c697bda6c72888a
Author: Łukasz Dywicki <lu...@code-house.org>
AuthorDate: Sat Aug 29 10:08:17 2020 +0200

    Fix socketcan transport.
---
 .../plc4x/java/transport/socketcan/netty/SocketCANChannel.java   | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannel.java b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannel.java
index 305d452..b302a7d 100644
--- a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannel.java
+++ b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/netty/SocketCANChannel.java
@@ -114,10 +114,10 @@ public class SocketCANChannel extends OioByteStreamChannel {
             try {
                 while (!isInputShutdown()) {
                     CanFrame frame = handle.read();
-                    ByteBuf frameBytes = ByteBufAllocator.DEFAULT.buffer();
-                    frameBytes.writeBytes(frame.getBuffer());
-                    String dump = ByteBufUtil.prettyHexDump(frameBytes);
-                    System.out.println(frame + "\n" + dump);
+//                    ByteBuf frameBytes = ByteBufAllocator.DEFAULT.buffer();
+//                    frameBytes.writeBytes(frame.getBuffer());
+//                    String dump = ByteBufUtil.prettyHexDump(frameBytes);
+//                    System.out.println(frame + "\n" + dump);
                     buffer.writeBytes(frame.getBuffer());
                 }
             } catch (IOException e) {
@@ -245,6 +245,7 @@ public class SocketCANChannel extends OioByteStreamChannel {
         public void write(byte[] b, int off, int len) throws IOException {
             ByteBuffer buffer = ByteBuffer.allocateDirect(len - off);
             buffer.put(b, off, len);
+            buffer.flip();
             CanFrame frame = CanFrame.create(buffer);
             rawCanChannel.write(frame);
         }