Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
155 commits
Select commit Hold shift + click to select a range
0aa8c1f
Add claude init
RaulSMS May 20, 2026
ea76186
feat: support all four DM1 SPN conversion methods
RaulSMS May 20, 2026
122be7c
Merge pull request #1 from RaulSMS/claude-helper
RaulSMS May 20, 2026
f71df59
Merge pull request #2 from RaulSMS/add-DM1-CMs
RaulSMS May 20, 2026
edb5a5e
feat: remove numpy
khauersp Jun 8, 2026
4a3066c
test: add coverage for j1939_22 logic
khauersp Jun 9, 2026
3403261
test: clean up docs and remove constant
khauersp Jun 9, 2026
ba43a25
feat: use constants instead of hardcoded numbers
khauersp Jun 10, 2026
8f9d243
feat: remove numpy dependency (#4)
khauersp Jun 17, 2026
821427d
feat: make general threading and other
khauersp May 27, 2026
d655a82
feat: update threading safety
khauersp May 28, 2026
536e252
docs: remove unneeded documentation
khauersp Jun 4, 2026
c2a4696
test: add docs and clean up test
khauersp Jun 8, 2026
f4086b2
docs: remove unused docs
khauersp Jun 8, 2026
4511ca7
feat: address threading concerns and increase
khauersp Jun 10, 2026
85e52cd
feat: undo threading change for memory_access
khauersp Jun 10, 2026
ae0b176
chore: address ci issue to install pytest
khauersp Jun 10, 2026
4b13ab0
test: skip latency test since it has some
khauersp Jun 10, 2026
74a64ea
test: skip another timing specific test
khauersp Jun 10, 2026
950845d
feat: raise error on feeder not stopping
khauersp Jun 10, 2026
15bfdb8
Merge branch 'master' into feature/general-threading-improvements
khauersp Jun 17, 2026
977d9fb
fix: protect send_pgn buffer writes with _buffer_lock in j1939_21
RaulSMS Jun 17, 2026
e008ac9
test: add concurrency tests for send_pgn buffer lock in j1939_21
RaulSMS Jun 17, 2026
9ad2bb6
chore: merge pull request #19 from RaulSMS/fix/pr5-buffer-lock-and-tests
khauersp Jun 17, 2026
a687294
fix: replace deprecated bustype= with interface= for python-can >= 4.…
RaulSMS Jun 18, 2026
5f3dd38
fix: stop shipping test_helpers as an installed package
RaulSMS Jun 18, 2026
42632ac
test: add regression test for bypass_address_claim with address 0x00 …
RaulSMS Jun 18, 2026
abe8825
Merge branch 'master' into feature/general-threading-improvements
RaulSMS Jun 18, 2026
03259fd
Merge pull request #5 from khauersp/feature/general-threading-improve…
RaulSMS Jun 18, 2026
73d000e
Merge branch 'master' into fix/test-helpers-not-installed
RaulSMS Jun 18, 2026
c6a5ad0
refactor: change directory structure for tests
khauersp Jun 18, 2026
d58f9a1
Merge pull request #15 from RaulSMS/feature/change-directory-structure
RaulSMS Jun 18, 2026
56a81b4
fix: declare Python 3.10 as minimum version and expand CI matrix
RaulSMS Jun 18, 2026
7f27675
fix: replace removed ruff E999 rule with python compileall
RaulSMS Jun 18, 2026
5be4ea0
fix: use vermin to enforce Python 3.10 minimum version in CI
RaulSMS Jun 18, 2026
6036329
fix(lint): fix F401/F403 import issues in __init__.py and setup.py
RaulSMS Jun 18, 2026
102e48d
fix(lint): remove dead receive/send helpers from test_ecu.py
RaulSMS Jun 18, 2026
2fd60d7
fix(lint): replace == None/True/False with identity/truthiness checks
RaulSMS Jun 18, 2026
d1dceea
fix(lint): remove unused imports from examples (F401)
RaulSMS Jun 18, 2026
de12fbb
ci: add ruff lint job and configure target-version
RaulSMS Jun 18, 2026
c656aae
Potential fix for code scanning alert no. 1: Workflow does not contai…
RaulSMS Jun 18, 2026
e3e710e
Merge pull request #13 from RaulSMS/fix/test-helpers-not-installed
RaulSMS Jun 19, 2026
e3df02e
chore: merge master into fix/ruff-linting, resolve conflicts
RaulSMS Jun 19, 2026
78b0872
fix: add lint extra to setup.py and use it in CI
RaulSMS Jun 19, 2026
77f1869
docs: add CONTRIBUTING.md with setup, style, and PR checklist
RaulSMS Jun 19, 2026
00d178f
Merge branch 'master' into fix/python-version-compatibility
RaulSMS Jun 19, 2026
e287d44
fix(test): replace fixed sleep with deadline-bounded poll in test_add…
RaulSMS Jun 19, 2026
07b6e3b
ci: pin actions/checkout and actions/setup-python to Node 24-compatib…
RaulSMS Jun 19, 2026
ecc4217
fix/ruff settigns
RaulSMS Jun 19, 2026
c28901a
fix/ new ruff findings
RaulSMS Jun 19, 2026
8a1ce3e
fix/ circular imports after ruff fixes
RaulSMS Jun 19, 2026
04ed152
Activate skkiped threading test
RaulSMS Jun 19, 2026
f7ea4a4
feat(docs): Update sphinx/readthedocs configuration (With autogenerat…
sharma9012mahesh Jun 19, 2026
dcde6b5
docs: Point to forked repo
RaulSMS Jun 19, 2026
8f2be3f
Merge branch 'master' into docs/contributing
RaulSMS Jun 19, 2026
b73e475
fix: enable previously skipped timer and memory_access tests with rel…
RaulSMS Jun 19, 2026
53202ad
feat: migrate packaging to pyproject.toml for PyPI publication as pyt…
RaulSMS Jun 19, 2026
fac138a
Merge pull request #26 from sharma9012mahesh/feature/readthedocs
RaulSMS Jun 19, 2026
6229c71
Merge pull request #17 from RaulSMS/fix/python-version-compatibility
RaulSMS Jun 19, 2026
8cf6fd1
Merge branch 'master' into docs/contributing
RaulSMS Jun 19, 2026
cd64e91
Merge pull request #23 from RaulSMS/docs/contributing
RaulSMS Jun 22, 2026
71ed181
Merge branch 'master' into alert-autofix-1
RaulSMS Jun 22, 2026
0055088
Merge pull request #20 from RaulSMS/alert-autofix-1
RaulSMS Jun 22, 2026
e49f29a
Update format READMErst -> README.md
RaulSMS Jun 22, 2026
f0bdb7b
Merge branch 'master' into feat/pypi-packaging
RaulSMS Jun 22, 2026
ef52aa9
Fix: hidden characters in toml file
RaulSMS Jun 22, 2026
b15f2d5
Fix: wheel build warnings
RaulSMS Jun 22, 2026
9911f27
Change version to 0.1.0
RaulSMS Jun 22, 2026
bffb680
Add build and publish to CI
RaulSMS Jun 22, 2026
fba6dcc
Speed up CI by cache dependencies
RaulSMS Jun 22, 2026
0ca4b9b
Split CI and publish workflows
RaulSMS Jun 22, 2026
ed51c0f
docs: add release process to contributing.md
RaulSMS Jun 22, 2026
f19e3eb
Merge branch 'master' into fix/ruff-linting
RaulSMS Jun 22, 2026
a0dbbc7
fix: PR 30 comments
RaulSMS Jun 22, 2026
fd9855c
Merge pull request #30 from RaulSMS/feat/pypi-packaging
RaulSMS Jun 23, 2026
bfa855e
Merge branch 'master' into fix/ruff-linting
RaulSMS Jun 23, 2026
2622e72
ci: Add pyright type checking
sharma9012mahesh Jun 23, 2026
6bf6bce
Add optional lint dependencies
RaulSMS Jun 23, 2026
bfc057a
fix(pyright): resolve pyright type errors across j1939 stack
sharma9012mahesh Jun 23, 2026
ee92aa9
Add Scorecard workflow for supply-chain security
RaulSMS Jun 24, 2026
080519a
Merge pull request #39 from sharma9012mahesh/master
RaulSMS Jun 24, 2026
4d1baec
Merge branch 'master' into fix/ruff-linting
RaulSMS Jun 24, 2026
f6282f3
fix: ruff errors introduced on PR#39 merge
RaulSMS Jun 24, 2026
41624fd
Merge branch 'master' into scorecard
RaulSMS Jun 24, 2026
85d100a
Merge pull request #40 from RaulSMS/scorecard
RaulSMS Jun 24, 2026
61881d0
Merge branch 'master' into fix/ruff-linting
RaulSMS Jun 24, 2026
65b3971
Configure Dependabot for GitHub Actions and pip
RaulSMS Jun 24, 2026
fff80c0
Fix: sigend releases
RaulSMS Jun 24, 2026
62065d8
fix: add final newline
RaulSMS Jun 24, 2026
96ef756
Merge pull request #43 from RaulSMS/add-dependantbot
RaulSMS Jun 24, 2026
cb215cd
chore(deps): bump actions/setup-python from 5.3.0 to 6.3.0
dependabot[bot] Jun 24, 2026
c6234d8
Merge branch 'master' into fix/signed-releases
RaulSMS Jun 24, 2026
e672e78
Merge pull request #44 from RaulSMS/fix/signed-releases
RaulSMS Jun 24, 2026
d7c1a67
Merge branch 'master' into dependabot/github_actions/actions/setup-py…
RaulSMS Jun 24, 2026
56e662c
Merge pull request #45 from RaulSMS/dependabot/github_actions/actions…
RaulSMS Jun 24, 2026
25267a6
Merge branch 'master' into fix/ruff-linting
RaulSMS Jun 24, 2026
652ea97
fix: bump release version
RaulSMS Jun 24, 2026
90656fb
Merge pull request #52 from RaulSMS/fix/bump-release-version
RaulSMS Jun 24, 2026
9eadd54
chore(deps): update sphinx-rtd-theme requirement from >=3.0 to >=3.1.0
dependabot[bot] Jun 24, 2026
b2b22c3
chore: Merge pull request #51 from RaulSMS/dependabot/pip/sphinx-rtd-…
drewr95 Jun 29, 2026
232b83f
chore(deps): update sphinx requirement from >=7.0 to >=8.1.3
dependabot[bot] Jun 29, 2026
993564f
chore: Merge pull request #50 from RaulSMS/dependabot/pip/sphinx-gte-…
drewr95 Jun 29, 2026
a8f0502
Merge remote-tracking branch 'origin/master' into fix/ruff-linting
Copilot Jun 29, 2026
f67be70
chore(deps): bump ossf/scorecard-action from 2.4.1 to 2.4.3
dependabot[bot] Jun 24, 2026
e8001d8
chore: merge pull request #49 from RaulSMS/dependabot/github_actions/…
khauersp Jun 29, 2026
1054cd4
chore(deps): bump softprops/action-gh-release from 2 to 3
dependabot[bot] Jun 24, 2026
fb34220
chore: merge pull request #48 from RaulSMS/dependabot/github_actions/…
khauersp Jun 29, 2026
04b5274
chore(deps): bump github/codeql-action from 3 to 4
dependabot[bot] Jun 24, 2026
e45df00
chore: Merge pull request #46 from RaulSMS/dependabot/github_actions/…
drewr95 Jun 29, 2026
4bf1b51
chore(deps): bump actions/checkout from 4.2.2 to 7.0.0
dependabot[bot] Jun 29, 2026
de3fd9c
Pin checkout action to commit SHA
Copilot Jun 30, 2026
3ab0e11
chore: Merge pull request #47 from RaulSMS/dependabot/github_actions/…
drewr95 Jun 30, 2026
b2bf709
feat: add COMMANDED_ADDRESS to PGN table. #54
drewr95 Jun 30, 2026
4b57b0e
feat: implement Commanded Address handling in ControllerApplication #54
drewr95 Jun 30, 2026
da8e1b2
feat: route Commanded Address to registered CAs in notify method #54
drewr95 Jun 30, 2026
25cd9fe
test: add tests for Commanded Address handling in test_ca.py #54
drewr95 Jun 30, 2026
caf134e
feat: route Commanded Address to registered CAs in J1939_22 class #54
drewr95 Jun 30, 2026
58d88d3
test: add tests for Commanded Address routing in TestCommandedAddress…
drewr95 Jun 30, 2026
d82283c
feat: enhance Commanded Address handling to ignore invalid source add…
drewr95 Jun 30, 2026
5c27b43
chore: merge pull request #55 from RaulSMS/feature/54-commanded-address
khauersp Jun 30, 2026
f75ca9a
feat: implement ownership checks for destination addresses in J1939_2…
drewr95 Jul 1, 2026
ae8e868
test: add test for wildcard subscriber observing address-claim broadc…
drewr95 Jul 1, 2026
f1cbd98
feat: forward address claims to subscribers for passive monitoring in…
drewr95 Jul 2, 2026
06bba08
chore: Merge pull request #60 from RaulSMS/feature/54-commanded-address
drewr95 Jul 2, 2026
2fe6ae3
Merge branch 'master' into fix/ruff-linting
khauersp Jul 7, 2026
1dfd951
chore(deps): bump actions/upload-artifact from 4.6.1 to 7.0.1
dependabot[bot] Jul 1, 2026
c4f41cd
chore: Merge pull request #58 from RaulSMS/dependabot/github_actions/…
khauersp Jul 7, 2026
d402aed
Merge branch 'master' into fix/ruff-linting
khauersp Jul 7, 2026
677e703
Merge pull request #19 from RaulSMS/fix/ruff-linting
VKlueber Jul 8, 2026
0360e48
chore(deps): bump slsa-framework/slsa-github-generator/.github/workfl…
dependabot[bot] Jul 8, 2026
5f3bad1
Log errors instead of crash when trying to send can messages
kellergoech Jul 14, 2026
7d1d862
chore: merge pull request #57 from RaulSMS/dependabot/github_actions/…
khauersp Jul 20, 2026
89c0198
feat: add bus to construction logic for ecu
khauersp Jul 10, 2026
749e5f3
test: add coverage for new bus logic
khauersp Jul 10, 2026
e04feea
feat: raise error on args and clean up notifier
khauersp Jul 20, 2026
cf87742
chore: Merge pull request #62 from RaulSMS/feature/add-support-for-bu…
drewr95 Jul 21, 2026
14b0785
feat: implement a queue for the notifier
khauersp Jul 20, 2026
b349398
test: add coverage for queue
khauersp Jul 21, 2026
fbdf6d9
docs: remove unneeded documentation
khauersp Jul 21, 2026
7077534
docs: remove some more unneeded documentation
khauersp Jul 21, 2026
5fabfd7
feat: add more docs and clean up some potential
khauersp Jul 21, 2026
26c9820
feat: bound the queue to make it safer
khauersp Jul 22, 2026
70768f8
chore: merge pull request #65 use dispatch thread
khauersp Jul 22, 2026
4517976
chore(deps): bump actions/setup-python from 6.3.0 to 7.0.0
dependabot[bot] Jul 22, 2026
61f7b5b
chore: merge pull request #67 from RaulSMS/dependabot/github_actions/…
khauersp Jul 22, 2026
98b1bef
chore(deps): bump actions/checkout from 7.0.0 to 7.0.1
dependabot[bot] Jul 22, 2026
ff6ad85
chore: merge pull request #66 from RaulSMS/dependabot/github_actions/…
khauersp Jul 22, 2026
6784485
chore(deps): bump ossf/scorecard-action from 2.4.3 to 2.4.4
dependabot[bot] Jul 29, 2026
debb741
chore: merge pull request #68 from RaulSMS/dependabot/github_actions/…
khauersp Jul 31, 2026
f4dcb3e
Merge branch 'master' into patch-2
RaulSMS Aug 11, 2026
69b20d1
Merge pull request #63 from kellergoech/patch-2
RaulSMS Aug 11, 2026
cbbe703
fix: reset MessageListener.stopped when re-adding to a notifier
drewr95 Aug 14, 2026
90e24e0
test: add regression test for stale listener.stopped after re-add
drewr95 Aug 14, 2026
dbaf1df
chore: Merge pull request #71 from RaulSMS/fix/stale-listener-stopped…
drewr95 Aug 14, 2026
f3b9215
fix(j1939-21): respect sequence number for fragmented frames on reass…
drewr95 Aug 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
69 changes: 51 additions & 18 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -1,46 +1,79 @@
# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the workflow will run
permissions:
contents: read

on:
push:
branches:
- master
- develop
tags:
- v*
pull_request:
branches:
- "**"
schedule:
# Daily at 10:55
- cron: '55 10 * * *'

# Allows you to run this workflow manually from the Actions tab
- cron: '55 10 * * 0'
workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "test"
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- uses: actions/setup-python@v7.0.0
with:
python-version: '3.10'
cache: 'pip' # Safely caches dependencies

- name: Install dependencies
run: pip install -e .[lint]

- name: Check style and syntax (Ruff)
run: ruff check .

- name: Check minimum Python version compatibility (Vermin)
run: vermin --target=3.10- --no-parse-comments --no-tips j1939/

- name: Run Pyright
run: pyright

test:
# The type of runner that the job will run on
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ['3.10', '3.11', '3.12', '3.13']

steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/setup-python@v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- uses: actions/setup-python@v7.0.0
with:
python-version: '3.10'

- uses: actions/checkout@v2
python-version: ${{ matrix.python-version }}
cache: 'pip'

- name: install dependencies
run: pip3 install .
run: pip3 install -e .[test]

- name: Run tests
run: pytest . --pyargs

build_check:
name: Verify Package Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- uses: actions/setup-python@v7.0.0
with:
python-version: '3.12'
cache: 'pip'

- name: Install build tools
run: pip install build twine

- name: Verify package build and metadata
run: |
python -m build
python -m twine check dist/*
60 changes: 60 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Publish Release

on:
push:
tags:
- v*

permissions:
contents: read

jobs:
build_and_publish:
name: Build, Release, and Publish
runs-on: ubuntu-latest
outputs:
hashes: ${{ steps.hash.outputs.hashes }}
permissions:
id-token: write # Required for PyPI OIDC and SLSA provenance
contents: write # Required to create a GitHub Release

steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up Python
uses: actions/setup-python@v7.0.0
with:
python-version: '3.12'

- name: Install build tools
run: pip install build

- name: Build sdist and wheel
run: python -m build

- name: Generate hashes for SLSA
id: hash
run: |
cd dist && echo "hashes=$(sha256sum * | base64 -w0)" >> "$GITHUB_OUTPUT"

- name: Create GitHub Release
uses: softprops/action-gh-release@v3
with:
files: |
dist/*.tar.gz
dist/*.whl
generate_release_notes: true

- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1

provenance:
needs: [build_and_publish]
permissions:
actions: read
id-token: write
contents: write
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
with:
base64-subjects: "${{ needs.build_and_publish.outputs.hashes }}"
upload-assets: true
78 changes: 78 additions & 0 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# This workflow uses actions that are not certified by GitHub. They are provided
# by a third-party and are governed by separate terms of service, privacy
# policy, and support documentation.

name: Scorecard supply-chain security
on:
# For Branch-Protection check. Only the default branch is supported. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
branch_protection_rule:
# To guarantee Maintained check is occasionally updated. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
schedule:
- cron: '23 10 * * 4'
push:
branches: [ "master" ]

# Declare default permissions as read only.
permissions: read-all

jobs:
analysis:
name: Scorecard analysis
runs-on: ubuntu-latest
# `publish_results: true` only works when run from the default branch. conditional can be removed if disabled.
if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request'
permissions:
# Needed to upload the results to code-scanning dashboard.
security-events: write
# Needed to publish results and get a badge (see publish_results below).
id-token: write
# Uncomment the permissions below if installing in a private repository.
# contents: read
# actions: read

steps:
- name: "Checkout code"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: "Run analysis"
uses: ossf/scorecard-action@2d1146689b8cda280b9bc96326124645441f03bc # v2.4.4
with:
results_file: results.sarif
results_format: sarif
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
# - you want to enable the Branch-Protection check on a *public* repository, or
# - you are installing Scorecard on a *private* repository
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional.
# repo_token: ${{ secrets.SCORECARD_TOKEN }}

# Public repositories:
# - Publish results to OpenSSF REST API for easy access by consumers
# - Allows the repository to include the Scorecard badge.
# - See https://github.com/ossf/scorecard-action#publishing-results.
# For private repositories:
# - `publish_results` will always be set to `false`, regardless
# of the value entered here.
publish_results: true

# (Optional) Uncomment file_mode if you have a .gitattributes with files marked export-ignore
# file_mode: git

# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: SARIF file
path: results.sarif
retention-days: 5

# Upload the results to GitHub's code scanning dashboard (optional).
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: results.sarif
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ instance/

# Sphinx documentation
docs/_build/
docs/examples.rst
docs/source/j1939.rst
docs/source/modules.rst

# PyBuilder
target/
Expand Down
20 changes: 20 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

# Required
version: 2

# Set the OS, Python version, and other tools you might need
build:
os: ubuntu-24.04
tools:
python: "3.12"

# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py

# Declare the Python requirements required to build your documentation
python:
install:
- requirements: docs/requirements.txt
78 changes: 78 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project

`can-j1939` is a Python implementation of the SAE J1939 protocol stack on top of
[python-can](https://python-can.readthedocs.org/). It supports both J1939-21 and J1939-22 (J1939-FD)
data link layers, including transport protocols (BAM, CMDT / RTS-CTS), address claiming, and a
number of diagnostic messages (DM1, DM11, DM14, DM22).

## Common commands

```bash
# Install the package (editable for development)
pip install -e .

# Run the full test suite (matches CI)
pytest . --pyargs

# Run a single test file / test
pytest test/test_ecu.py
pytest test/test_memory_access.py::TestMemoryAccess::test_some_name -v
```

CI runs `pytest . --pyargs` on Python 3.10 across Ubuntu/macOS/Windows
(`.github/workflows/CI.yml`).

## Architecture

The stack is layered: an **ECU** owns a **data-link layer** object and one or more
**ControllerApplications**. Background work runs on a dedicated job thread.

- `j1939/electronic_control_unit.py` — `ElectronicControlUnit` is the entry point. It owns the
`can.Bus`, a `MessageListener`, a job thread (`_async_job_thread`) that drives timers and
transport-protocol timeouts, and a list of subscribers. The `data_link_layer` constructor arg
(`'j1939-21'` or `'j1939-22'`) selects which DLL is instantiated. The ECU passes the DLL a
small surface of callbacks: `send_message`, `_job_thread_wakeup`, `_notify_subscribers`,
`_is_message_acceptable`. For tests, `send_message=` can be injected to bypass real CAN I/O.
- `j1939/j1939_21.py` and `j1939/j1939_22.py` — the two DLL implementations. They share the
callback signature above and implement the transport protocols (TP-BAM, TP-CMDT / RTS-CTS,
and for J1939-22 the FD multi-session variants and Multi-PG / FEFF). Changes that touch
protocol behaviour usually need parallel updates in both files.
- `j1939/controller_application.py` — `ControllerApplication` (CA) implements J1939/81 address
claiming, state machine (`NONE` → `WAITING_VETO` → `NORMAL` / `CANNOT_CLAIM`), per-CA
subscriptions, and `send_pgn` (which dispatches to the ECU's DLL).
- `j1939/name.py`, `j1939/parameter_group_number.py`, `j1939/message_id.py` — value objects for
the J1939 NAME, PGN encoding, and 29-bit CAN identifier framing.
- `j1939/diagnostic_messages.py`, `j1939/memory_access.py`, `j1939/Dm14Query.py`,
`j1939/Dm14Server.py`, `j1939/error_info.py` — diagnostic-message support (DM1/DM11/DM14/DM22),
including the DM14 memory-access client (`Dm14Query`) and server (`Dm14Server`).
- `j1939/__init__.py` is the public API surface — anything users are expected to import lives
here.

### Threading model

All I/O and protocol timing flows through the ECU's job thread. The DLL never blocks on I/O
itself — it enqueues work and calls `_job_thread_wakeup` to nudge the thread. Callbacks
registered via `ca.subscribe(...)` or `ca.add_timer(...)` run on that job thread, so they
must not block.

### Tests

- `test/` holds unit tests. `test/helpers/feeder.py` provides the `Feeder` fixture (registered
in `test/conftest.py`) which is the standard way to drive the stack from tests: it
replaces `ElectronicControlUnit.send_message` with a simulated bus, lets the test queue
expected RX/TX messages and PDUs in order, and asserts that the stack produces the expected
TX sequence. New protocol-level tests should follow that pattern instead of mocking
`python-can` directly.
- `test/helpers/feeder.AcceptAllCA` is a CA subclass with `message_acceptable` overridden to
accept everything — use it when a test needs to receive peer-to-peer messages without setting
up a real claim.

### Examples

`examples/` contains runnable scripts mirroring the README quick-start (simple receive, own CA
producer, transport protocols, multi-PG, diagnostic messages). When adding a new public
feature, prefer extending an existing example over inventing a new pattern in the docs.
Loading