Skip to main content

pamoja-can

CAN 2.0 and CAN-FD frames with 11- and 29-bit identifiers, plus J1939 decode and compose. One capability of pamoja, one memory-safe Rust core with bindings for TypeScript, Python, and C#.

API reference read the guide documentation

Install

pip install pamoja-can
from pamoja import can

This pulls in pamoja-native, the compiled engine. pip install pamoja is the whole framework in one package.

Example

The script the test suite runs, spliced here as it ran.

From bindings/python/guides/can.py:

from pamoja.can import (
    NOT_AVAILABLE,
    Priority,
    broadcast_j1939,
    compose_j1939,
    decode_j1939,
    fd_frame,
    frame,
    signals,
    signals_from,
)
from pamoja.core import PamojaError

# The nodes on this bus, by the address each answers to, and the two parameter groups
# in play. J1939 publishes both, so naming them is what makes the traffic readable.
ENGINE = 0
GATEWAY = 1
GEARBOX = 33
ENGINE_CONTROLLER_1 = 61_444  # carries engine speed
REQUEST = 59_904  # asks another node for a parameter group

# Where engine speed sits inside that group, and the scale the standard fixes for it.
# Naming both is what stops a sender and a receiver disagreeing about either.
ENGINE_SPEED_AT = 3
RPM_PER_BIT = 0.125

# J1939 keeps its addressing inside the CAN identifier: a priority, the parameter
# group, and the address of whatever sent it. A broadcast has no destination, so it is
# its own constructor rather than a magic address a caller has to know.
speed_id = broadcast_j1939(Priority.CONTROL, ENGINE_CONTROLLER_1, ENGINE)
speed = decode_j1939(speed_id)
print(f"broadcast pgn {speed.pgn} at priority {speed.priority}")

# A parameter group below the PDU1 limit is addressed rather than broadcast, so those
# eight identifier bits carry a destination instead of extending the group number.
request_id = compose_j1939(Priority.DEFAULT, REQUEST, GATEWAY, GEARBOX)
print(f"request   pgn {decode_j1939(request_id).pgn} addressed to node {GEARBOX}")

# Reading one back off the bus is the same thing in reverse, so a receiver never
# unpacks 29 bits by hand.
heard = decode_j1939(request_id)
print(f"heard     from node {heard.source} for node {heard.destination}")

# The payload. Every signal starts marked not available, and this controller reports
# only engine speed, so that is the only one it writes.
reported = signals()
reported.set_u16(ENGINE_SPEED_AT, int(1000 / RPM_PER_BIT))
eec1 = frame(speed_id, reported.bytes, extended=True)

# The receiving node reads the same offset back, so neither end slices the payload.
rpm = signals_from(eec1.data).u16(ENGINE_SPEED_AT) * RPM_PER_BIT
print(f"engine    {rpm} rpm, carried in {eec1.dlc} bytes")

# Above eight bytes CAN-FD encodes the length in steps rather than exactly, and a
# classic frame still refuses a ninth byte.
print(f"32 bytes carries length code {fd_frame(speed_id, bytes(32), extended=True).dlc}")
try:
    frame(speed_id, bytes(9), extended=True)
    print("a classic frame took nine bytes, which should never happen")
except PamojaError as error:
    print(f"classic   refused nine bytes: {error}")

# J1939 never rides an 11-bit identifier, so a standard frame is not one of its
# messages however its bits happen to line up.
print(f"an 11-bit identifier is J1939: {decode_j1939(291, extended=False) is not None}")

The same capability in every language

Language Package Reference
Rust pamoja-can reference, docs.rs, install
TypeScript @pamoja/can reference, install
Python pamoja-can reference, install
C# Pamoja.Can reference, install

Documentation

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pamoja_can-0.1.17.tar.gz (5.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pamoja_can-0.1.17-py3-none-any.whl (6.0 kB view details)

Uploaded Python 3

File details

Details for the file pamoja_can-0.1.17.tar.gz.

File metadata

  • Download URL: pamoja_can-0.1.17.tar.gz
  • Upload date:
  • Size: 5.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.15

File hashes

Hashes for pamoja_can-0.1.17.tar.gz
Algorithm Hash digest
SHA256 aa3f69367310eed95af13de752f55f7a2ae14bffcfd324e52032d1bc2be74bcd
MD5 9caeeb5f568d3b293115fde952dfcbfc
BLAKE2b-256 ab37f33e03b43f801d27e1b00716de551fb6d3cfc5d922bfd2b8fda15bab04a9

See more details on using hashes here.

File details

Details for the file pamoja_can-0.1.17-py3-none-any.whl.

File metadata

  • Download URL: pamoja_can-0.1.17-py3-none-any.whl
  • Upload date:
  • Size: 6.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.15

File hashes

Hashes for pamoja_can-0.1.17-py3-none-any.whl
Algorithm Hash digest
SHA256 58e7fb0848d21b1d75c8474681accad232cf7d7f1d4086ce4b05be54b2a26214
MD5 1386462ca03ed38c6ad81a766199b861
BLAKE2b-256 bf211f925629e64c5ce192d76ce4d1f782b0c093eea36bbb3a07e8e3a733307b

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.17 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page