Skip to content

Commit 4ec6837

Browse files
authored
feat: adds ais-encode (CLI) (#186)
* feat: adds ais-encode (CLI) * fix: remove wheel and build as runtime requirements * doc: remove ./ from docstring * fix: shift had no effect * chore: updates changelog * feat: adds test_cli_encode.py
1 parent 1064f7f commit 4ec6837

File tree

11 files changed

+634
-225
lines changed

11 files changed

+634
-225
lines changed

CHANGELOG.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
====================
22
pyais CHANGELOG
33
====================
4+
-------------------------------------------------------------------------------
5+
Version 2.12.0 12 Jul 2025
6+
-------------------------------------------------------------------------------
7+
* BREAKING: Renamed pyais/main.py to pyais/ais_decode.py
8+
* direct imports from pyais.main will fail
9+
* added ais-encode as installable CLI tool via pip install
410
-------------------------------------------------------------------------------
511
Version 2.11.1 30 Jun 2025
612
-------------------------------------------------------------------------------

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ clean:
2424
rm -f .coverage
2525

2626
ensure-no-print:
27-
grep -r --exclude main.py --exclude '*.pyc' -i 'print(' ./pyais && (echo "Debug print statement found"; exit 1)||true
27+
grep -r --exclude ais_encode.py --exclude ais_decode.py --exclude '*.pyc' -i 'print(' ./pyais && (echo "Debug print statement found"; exit 1)||true
2828

2929
test: run_tests flake type-check ensure-no-print
3030

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ print(encoded)
208208

209209
### CLI encoder
210210

211-
There is also a AIS JSON to NMEA Encoder: [examples/ais-encode](examples/ais-encode). It reads JSON from stdin and outputs encoded NMEA AIS messages to stdout.
211+
There is also a AIS JSON to NMEA Encoder for your CLI: `ais-encode`. It reads JSON from stdin and outputs encoded NMEA AIS messages to stdout. Refer to `ais-encode --help`.
212212

213213
# Under the hood
214214

pyais/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from pyais.tracker import AISTracker, AISTrack
66

77
__license__ = 'MIT'
8-
__version__ = '2.11.1'
8+
__version__ = '2.12.0'
99
__author__ = 'Leon Morten Richter'
1010

1111
__all__ = (
File renamed without changes.
Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,16 @@
1414
Usage Examples:
1515
--------------
1616
1. Encode a single AIS position report:
17-
$ echo '{"msg_type":1,"mmsi":231234000,"turn":5.0,"speed":10.1,"lon":5,"lat":59,"course":356.0}' | ./ais-encode
17+
$ echo '{"msg_type":1,"mmsi":231234000,"turn":5.0,"speed":10.1,"lon":5,"lat":59,"course":356.0}' | ais-encode
1818
1919
2. Encode multiple messages from line-delimited JSON:
20-
$ cat ais_messages.jsonl | ./ais-encode --mode lines
20+
$ cat ais_messages.jsonl | ais-encode --mode lines
2121
2222
3. Process a continuous stream of AIS data:
23-
$ nc 153.44.253.27 5631 | ais-decode --json | jq -c | ./ais-encode --mode stream
23+
$ nc 153.44.253.27 5631 | ais-decode --json | jq -c | ais-encode --mode stream
2424
2525
4. Convert decoded AIS messages back to NMEA:
26-
$ ais-decode --json < nmea.txt | ./ais-encode
26+
$ ais-decode --json < nmea.txt | ais-encode
2727
2828
Input Format:
2929
------------
@@ -72,7 +72,7 @@
7272

7373

7474
class AISJSONDecoder(json.JSONDecoder):
75-
def __init__(self, *args, **kwargs) -> None:
75+
def __init__(self, *args: Any, **kwargs: Any) -> None:
7676
super().__init__(object_hook=self._filter_hook, *args, **kwargs)
7777

7878
def _filter_hook(self, obj: Any) -> dict[str, Any]:
@@ -91,6 +91,22 @@ def create_parser() -> argparse.ArgumentParser:
9191
default='auto',
9292
help='JSON reading mode'
9393
)
94+
95+
parser.add_argument(
96+
'--talker',
97+
choices=['AIVDM', 'AIVDO',],
98+
default='AIVDM',
99+
help='AIVDM (default) is used for reports from other ships. AIVDO is used for own ship.',
100+
type=str.upper
101+
)
102+
103+
parser.add_argument(
104+
'--radio',
105+
choices=['A', 'B',],
106+
default='A',
107+
help='The radio channel. Can be either "A" (default) or "B".',
108+
type=str.upper
109+
)
94110
return parser
95111

96112

@@ -150,7 +166,7 @@ def main() -> int:
150166
for data in read(args.mode):
151167
try:
152168
# encode NMEA AIS message
153-
encoded = encode_dict(data)
169+
encoded = encode_dict(data, talker_id=args.talker, radio_channel=args.radio)
154170
except Exception as e:
155171
print(f'Failed to encode: {e}.', file=sys.stderr)
156172
continue

pyais/util.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def decode_bin_as_ascii6(bit_arr: bitarray) -> str:
6969

7070
# Last entry may not have 6 bits
7171
if len(c) != 6:
72-
n >> (6 - len(c))
72+
n >>= (6 - len(c))
7373

7474
if n < 0x20:
7575
n += 0x40

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,12 @@ dev = ['mypy', 'flake8', 'coverage', 'twine', 'sphinx', 'pytest', 'pytest-cov']
4343
"Source" = "https://github.com/M0r13n/pyais"
4444

4545
[project.scripts]
46-
ais-decode = "pyais.main:main"
46+
ais-decode = "pyais.ais_decode:main"
47+
ais-encode = "pyais.ais_encode:main"
4748

4849
[tool.setuptools]
4950
package-data = {"pyais" = ["py.typed"]}
50-
51+
packages = ["pyais"]
5152

5253
[build-system]
5354
requires = ["setuptools>=43.0.0", "wheel"]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import sys
33
import unittest
44

5-
from pyais.main import decode_single, decode_from_file, create_parser, decode_from_socket
5+
from pyais.ais_decode import decode_single, decode_from_file, create_parser, decode_from_socket
66

77

88
class TestMainApp(unittest.TestCase):

0 commit comments

Comments
 (0)