Skip to content

Commit 8e1ff19

Browse files
committed
0.6.4
- fixed PGN transmitter - changed build and publishing system to uv
1 parent 289cf87 commit 8e1ff19

File tree

9 files changed

+209
-56
lines changed

9 files changed

+209
-56
lines changed

.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.13

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,21 @@ A CAN bus J1939 controller simulator.
2828
![PCAN-View demo screenshot](https://raw.githubusercontent.com/cfsok/akrocansim/main/docs/images/demo_1_PCAN-View.png)
2929

3030
## Installation
31-
Python 3.11 (64-bit) or higher is required.
31+
1. Install uv, see https://docs.astral.sh/uv/getting-started/installation/#installing-uv
32+
2. `uv tool install akrocansim`
3233

34+
## Execution
3335
```
34-
pip install akrocansim
36+
akrocansim
3537
```
3638

39+
3740
## Prerequisites
3841
- A hardware CAN interface supported by python-can,
3942
see https://python-can.readthedocs.io/en/v4.3.1/interfaces.html.
4043
- A version of J1939 Digital Annex (J1939DA) from SAE International, see https://www.sae.org/standards/?search=j1939DA.
4144
- A way to convert `.xls` to `.xlsx` if your copy of the J1939DA is in `.xls` format.
4245

43-
## Usage
44-
```
45-
python -m akrocansim
46-
```
4746

4847
Upon initial run, a folder named `akrocansim` is created in your home folder hosting a starting configuration file.
4948

pyproject.toml

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,35 @@
1-
[build-system]
2-
requires = ["flit_core >=3.2,<4"]
3-
build-backend = "flit_core.buildapi"
4-
51
[project]
62
name = "akrocansim"
73
dynamic = ["version", "description"]
8-
authors = [{name = "Socrates Vlassis", email = "[email protected]"}]
4+
authors = [{name = "pullthebox", email = "[email protected]"}]
95
readme = "README.md"
106
license = {file = "LICENSE"}
117
classifiers = [
12-
"Programming Language :: Python :: 3",
13-
"Programming Language :: Python :: 3.11",
14-
"Programming Language :: Python :: 3.12",
8+
"Programming Language :: Python :: 3.13",
159
"License :: OSI Approved :: MIT License",
1610
"Development Status :: 4 - Beta",
1711
"Topic :: Software Development :: Embedded Systems",
1812
"Topic :: Software Development :: Embedded Systems :: Controller Area Network (CAN)",
1913
"Topic :: Software Development :: Embedded Systems :: Controller Area Network (CAN) :: J1939"
2014
]
2115
keywords = ["J1939", "CAN bus"]
22-
requires-python = ">=3.11"
16+
requires-python = ">=3.13"
2317
dependencies = [
24-
"dearpygui~=1.10.1",
25-
"python-can~=4.3.1",
26-
"openpyxl~=3.1.2",
27-
"semver~=3.0.2"
18+
"dearpygui==2.0.0",
19+
"python-can==4.5.0",
20+
"openpyxl==3.1.5",
21+
"semver==3.0.4",
2822
]
2923

24+
[project.scripts]
25+
akrocansim = "akrocansim:main"
26+
3027
[project.urls]
3128
Home = "https://github.com/cfsok/akrocansim"
29+
30+
[build-system]
31+
requires = ["hatchling"]
32+
build-backend = "hatchling.build"
33+
34+
[tool.hatch.version]
35+
path = "src/akrocansim/__init__.py"

requirements.txt

Lines changed: 0 additions & 3 deletions
This file was deleted.

src/akrocansim/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
"""akrocansim is a CAN bus J1939 controller simulator"""
22

3-
__version__ = '0.6.1'
3+
__version__ = '0.6.4'
44
__app_name__ = 'akro CAN simulator'
5+
6+
from . import gui
7+
8+
def main() -> None:
9+
gui.AkrocansimGui()

src/akrocansim/__main__.py

Lines changed: 0 additions & 3 deletions
This file was deleted.

src/akrocansim/transmitter.py

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,10 @@
33
import can
44

55

6-
_TX_MODE = 0
7-
_TX_MODE__STOP = 0 # global, local
8-
_TX_MODE__TX_CONT = 1 # global, local
9-
_TX_MODE__PER_PGN = 2 # global only
10-
_TX_MODE__TX_ONCE = 3 # local only
11-
_TX_RATE_SEC = 1
12-
_DATA = 2
6+
_INDIVIDUAL_TX_MODE__TX_CONT = 0
7+
_INDIVIDUAL_TX_MODE__TX_ONCE = 1
8+
_TX_RATE_SEC = 2
9+
_DATA = 3
1310

1411

1512
class Transmitter:
@@ -18,9 +15,12 @@ def __init__(self, J1939: dict):
1815
self.bus: can.BusABC = None
1916
self.PGNs_pending_tx = {}
2017

21-
self.global_tx_mode = _TX_MODE__STOP # _TX_MODE__STOP, _TX_MODE__TX_CONT, _TX_MODE__PER_PGN
18+
self.global_tx_mode__stop = True
19+
self.global_tx_mode__cont = False
20+
self.global_tx_mode__per_pgn = False
2221
self.tx_CAN_IDs = {} # {(CAN_ID: int, is_extended: bool): {
23-
# _TX_MODE: _TX_MODE__STOP, _TX_MODE__TX_CONT, _TX_MODE__TX_ONCE
22+
# _INDIVIDUAL_TX_MODE__TX_CONT: bool,
23+
# _INDIVIDUAL_TX_MODE__TX_ONCE: bool,
2424
# _TX_RATE_SEC: #,
2525
# _DATA: list
2626
# }
@@ -32,7 +32,8 @@ def register_tx_PGN(self, *, pgn, priority, source_address, tx_rate_ms):
3232
self.J1939_CAN_IDs[pgn] = (can_id, True)
3333
tx_rate_sec = tx_rate_ms / 1000
3434
self.tx_CAN_IDs[(can_id, True)] = {
35-
_TX_MODE: _TX_MODE__STOP,
35+
_INDIVIDUAL_TX_MODE__TX_CONT: False,
36+
_INDIVIDUAL_TX_MODE__TX_ONCE: False,
3637
_TX_RATE_SEC: tx_rate_sec,
3738
_DATA: [0 for _ in range(self._J1939[pgn]['PGN Data Length'])]
3839
}
@@ -43,42 +44,49 @@ def send_periodic(self, can_id, is_extended):
4344

4445
while True:
4546
time.sleep(signal_spec[_TX_RATE_SEC])
46-
if self.global_tx_mode == _TX_MODE__TX_CONT or signal_spec[_TX_MODE] == _TX_MODE__TX_CONT:
47+
if self.global_tx_mode__cont or (self.global_tx_mode__per_pgn and signal_spec[_INDIVIDUAL_TX_MODE__TX_CONT]):
48+
# transmit can message with 'can_id' this cycle
4749
pass
48-
elif self.global_tx_mode in [_TX_MODE__STOP, _TX_MODE__PER_PGN] \
49-
and signal_spec[_TX_MODE] == _TX_MODE__TX_ONCE:
50-
signal_spec[_TX_MODE] = _TX_MODE__STOP
50+
elif signal_spec[_INDIVIDUAL_TX_MODE__TX_ONCE]:
51+
# transmit can message with 'can_id' this cycle and stop
52+
signal_spec[_INDIVIDUAL_TX_MODE__TX_ONCE] = False
5153
else:
54+
# do not transmit can message with 'can_id' this cycle
5255
continue
5356

5457
if self.bus is not None:
5558
try:
56-
self.bus.send(can.Message(arbitration_id=can_id, is_extended_id=is_extended,
57-
data=signal_spec[_DATA]))
59+
self.bus.send(can.Message(arbitration_id=can_id, is_extended_id=is_extended, data=signal_spec[_DATA]))
5860
except can.CanOperationError:
5961
pass
6062

6163
def set_tx_mode_stop(self, pgn=None):
62-
if pgn is None:
63-
self.global_tx_mode = _TX_MODE__STOP
64-
else:
65-
self.tx_CAN_IDs[self.J1939_CAN_IDs[pgn]][_TX_MODE] = _TX_MODE__STOP
64+
if pgn is None: # global
65+
self.global_tx_mode__stop = True
66+
self.global_tx_mode__cont = False
67+
self.global_tx_mode__per_pgn = False
68+
else: # individual
69+
self.tx_CAN_IDs[self.J1939_CAN_IDs[pgn]][_INDIVIDUAL_TX_MODE__TX_CONT] = False
6670

6771
def set_tx_mode_continuous(self, pgn=None):
68-
if pgn is None:
69-
self.global_tx_mode = _TX_MODE__TX_CONT
70-
else:
71-
self.tx_CAN_IDs[self.J1939_CAN_IDs[pgn]][_TX_MODE] = _TX_MODE__TX_CONT
72+
if pgn is None: # global
73+
self.global_tx_mode__stop = False
74+
self.global_tx_mode__cont = True
75+
self.global_tx_mode__per_pgn = False
76+
else: # individual
77+
self.tx_CAN_IDs[self.J1939_CAN_IDs[pgn]][_INDIVIDUAL_TX_MODE__TX_CONT] = True
7278

7379
def set_tx_mode_per_PGN(self):
74-
self.global_tx_mode = _TX_MODE__PER_PGN
80+
self.global_tx_mode__stop = False
81+
self.global_tx_mode__cont = False
82+
self.global_tx_mode__per_pgn = True
7583

7684
def set_tx_once(self, pgn=None):
77-
if pgn is None:
85+
if pgn is None: # global
7886
for signal_spec in self.tx_CAN_IDs.values():
79-
signal_spec[_TX_MODE] = _TX_MODE__TX_ONCE
80-
else:
81-
self.tx_CAN_IDs[self.J1939_CAN_IDs[pgn]][_TX_MODE] = _TX_MODE__TX_ONCE
87+
signal_spec[_INDIVIDUAL_TX_MODE__TX_ONCE] = True
88+
else: # individual
89+
self.tx_CAN_IDs[self.J1939_CAN_IDs[pgn]][_INDIVIDUAL_TX_MODE__TX_ONCE] = True
8290

8391
def modify_pgn_tx_rate(self, pgn, tx_rate_ms):
8492
tx_rate_sec = tx_rate_ms / 1000

src/akrocansim_main.py

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)