//
//  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
//
//      https://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.
//
:imagesdir: ../../images/users/protocols
:icons: font

= Generic CAN

Generic CAN is a transport-agnostic driver for raw xref:protocols/can.adoc[CAN Bus] traffic. It
applies no application-layer protocol of its own: every field is addressed as a raw node id plus a
data type, and the values written or received for a single node id are packed into a single CAN
frame in field order. It is a good fit where the devices on the bus speak a proprietary or
undocumented protocol built directly on raw CAN frames - anything that follows a specific
higher-level protocol on top of CAN bus, such as CANopen, is better served by
xref:protocols/canopen.adoc[CANopen].

== Supported Operations

[cols="2,2a,5a"]
|===
|Name |Value |Description

| publish
| `write`
| Publishes a CAN frame via the CAN transport.

| receive
| `subscribe`
| Listens for incoming CAN frames matching a subscribed node id.

|===

There is no read support; the driver only writes and subscribes.

== Connection String

[source]
----
genericcan:can-socketcan://{interface}[?{options}]
genericcan:can-virtualcan://{bus-name}[?{options}]
----

[source]
----
genericcan:can-socketcan://can0
genericcan:can-virtualcan://test
----

== Connection String Options

include::partial$genericcan.adoc[]

== Tag Addresses

Addressing is implemented in Java. There is no read support; the driver writes and subscribes. See
the xref:protocols/index.adoc[protocol support matrix] for what each implementation does.

=== General Format

----
nodeId:type[arraySize]
----

`nodeId` is a plain (non-hexadecimal) integer CAN node/frame identifier. `type` is one of the data
types listed below. `arraySize` is optional; see xref:array-notation.adoc[Addressing arrays].

The underlying pattern (`GenericCANTag.java:36-37`) is
`(?<nodeId>\d+):(?<dataType>\w+)(?:\[(?<arraySize>\d+)\])?`. It is not anchored with `^`/`$`, but
`GenericCANTag.matches()` (`GenericCANTag.java:83`) applies it with `Matcher.matches()`, which
requires the whole input string to match. Trailing text after a valid address is therefore
rejected, not silently ignored.

You can use multiple fields to write and subscribe actual data. All fields together must sum up to
64 bits. If you subscribe to less than the frame contains, the remaining data is discarded and not
available via the PLC4X API. Written and received data is ordered the same as the fields in the
request.

=== Data Types

[cols="2,2,2"]
|===
|Address Type        |Length (in bits)| PLC4X Type
| BOOLEAN            |        1 | BOOL
| UNSIGNED8          |        8 | USINT
| UNSIGNED16         |       16 | UINT
| UNSIGNED24         |       24 | UDINT
| UNSIGNED32         |       32 | UDINT
| UNSIGNED40         |       40 | ULINT
| UNSIGNED48         |       48 | ULINT
| UNSIGNED56         |       56 | ULINT
| UNSIGNED64         |       64 | ULINT
| INTEGER8           |        8 | SINT
| INTEGER16          |       16 | INT
| INTEGER24          |       24 | DINT
| INTEGER32          |       32 | DINT
| INTEGER40          |       40 | LINT
| INTEGER48          |       48 | LINT
| INTEGER56          |       56 | LINT
| INTEGER64          |       64 | LINT
| REAL32             |       32 | REAL
| REAL64             |       64 | LREAL
|===

This type table is similar to CANopen's. The main difference is the lack of support for string
types.

=== Examples

----
200:BYTE
200:BYTE[8]
----

== More Information

* xref:protocols/can.adoc[CAN Bus] - the shared transport and frame model used by this driver.
* xref:protocols/canopen.adoc[CANopen] - the driver to use for devices that follow the CANopen
application layer instead of raw frames.
