jeefs 0.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
jeefs-0.1.3/PKG-INFO ADDED
@@ -0,0 +1,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: jeefs
3
+ Version: 0.1.3
4
+ Summary: JEEFS EEPROM header parser (JetHome EEPROM File System)
5
+ Author-email: Viacheslav Bocharov <vb@jethome.com>
6
+ License-Expression: GPL-2.0-or-later OR Apache-2.0
7
+ Project-URL: Homepage, https://github.com/jethome-iot/jeefs
8
+ Project-URL: Repository, https://github.com/jethome-iot/jeefs
9
+ Project-URL: Documentation, https://github.com/jethome-iot/jeefs/tree/master/docs/python
10
+ Project-URL: Issues, https://github.com/jethome-iot/jeefs/issues
11
+ Keywords: eeprom,jethome,jeefs,embedded,header
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Software Development :: Embedded Systems
19
+ Classifier: Topic :: System :: Hardware
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ Provides-Extra: test
23
+ Requires-Dist: pytest>=7.0; extra == "test"
24
+
25
+ # JEEFS Header — Python Package
26
+
27
+ Pure Python library for parsing and generating JEEFS EEPROM headers. The main API class `EEPROMHeaderV3` handles v3 headers; constants and field offsets for all versions (v1/v2/v3) are available via `jeefs.constants`. No native dependencies.
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ pip install jeefs
33
+ ```
34
+
35
+ ## Dependencies
36
+
37
+ - Python >= 3.10
38
+ - No external runtime dependencies (uses stdlib `struct`, `binascii`)
39
+
40
+ ## Building / Development
41
+
42
+ ```bash
43
+ cd python
44
+ uv venv .venv && uv pip install -e ".[test]"
45
+ .venv/bin/python -m pytest tests/ -v
46
+ ```
47
+
48
+ ## API
49
+
50
+ ### `EEPROMHeaderV3` — main dataclass
51
+
52
+ ```python
53
+ from jeefs.header import EEPROMHeaderV3
54
+ ```
55
+
56
+ #### Creating a header
57
+
58
+ ```python
59
+ header = EEPROMHeaderV3(
60
+ boardname="JetHub-D1p",
61
+ boardversion="2.0",
62
+ serial="SN-2024-001",
63
+ mac="F0:57:8D:01:02:03",
64
+ )
65
+ binary = header.to_bytes() # 256-byte binary
66
+ ```
67
+
68
+ #### Parsing from binary
69
+
70
+ ```python
71
+ header = EEPROMHeaderV3.from_bytes(raw_data)
72
+ print(header.boardname) # "JetHub-D1p"
73
+ print(header.mac) # "F0:57:8D:01:02:03"
74
+ print(header.serial) # "SN-2024-001"
75
+ ```
76
+
77
+ #### CRC verification
78
+
79
+ ```python
80
+ # Instance method
81
+ header = EEPROMHeaderV3.from_bytes(data)
82
+ is_valid = header.verify_crc(data)
83
+
84
+ # Static method (no instance needed)
85
+ is_valid = EEPROMHeaderV3.verify_crc_static(data)
86
+ ```
87
+
88
+ #### Validation
89
+
90
+ ```python
91
+ errors = header.validate()
92
+ if errors:
93
+ print("Invalid:", errors)
94
+ ```
95
+
96
+ #### Partition image
97
+
98
+ ```python
99
+ image = header.to_partition_image() # 4096-byte flash image
100
+ ```
101
+
102
+ ### Fields
103
+
104
+ | Field | Type | Description |
105
+ |-------|------|-------------|
106
+ | `boardname` | `str` | Board name (max 31 chars) |
107
+ | `boardversion` | `str` | Board version (max 31 chars) |
108
+ | `serial` | `str` | Serial number (max 31 chars) |
109
+ | `usid` | `str` | CPU eFuse USID |
110
+ | `cpuid` | `str` | CPU ID |
111
+ | `mac` | `str` | MAC address ("AA:BB:CC:DD:EE:FF") |
112
+ | `signature` | `bytes` | ECDSA signature (raw r\|\|s) |
113
+ | `signature_algorithm` | `SignatureAlgorithm` | NONE / SECP192R1 / SECP256R1 |
114
+ | `timestamp` | `int \| None` | Unix timestamp (auto-set if None/0) |
115
+
116
+ ### `SignatureAlgorithm` enum
117
+
118
+ ```python
119
+ from jeefs.constants import SignatureAlgorithm
120
+
121
+ SignatureAlgorithm.NONE # 0
122
+ SignatureAlgorithm.SECP192R1 # 1 (48-byte signature)
123
+ SignatureAlgorithm.SECP256R1 # 2 (64-byte signature)
124
+ ```
125
+
126
+ ### Constants
127
+
128
+ ```python
129
+ from jeefs.constants import (
130
+ EEPROM_MAGIC, # b"JETHOME\x00"
131
+ EEPROM_HEADER_SIZE, # 256
132
+ EEPROM_FIELDS, # dict of {field: (offset, size)}
133
+ EEPROM_CRC_COVERAGE, # 252
134
+ EEPROM_PARTITION_SIZE, # 4096
135
+ )
136
+ ```
137
+
138
+ ## Usage example
139
+
140
+ See [examples/python/read_header.py](https://github.com/jethome-iot/jeefs/blob/master/examples/python/read_header.py) — reads an EEPROM binary, prints version, CRC status, board name, MAC address, and full v3 fields.
141
+
142
+ ## Testing
143
+
144
+ ```bash
145
+ cd python
146
+ python -m pytest tests/ -v # 58 tests
147
+ ```
148
+
149
+ ## Format specification
150
+
151
+ - [Header common properties](https://github.com/jethome-iot/jeefs/blob/master/docs/format/header-common.md)
152
+ - [Header v3](https://github.com/jethome-iot/jeefs/blob/master/docs/format/header-v3.md)
153
+ - [Full format spec](https://github.com/jethome-iot/jeefs/blob/master/EEPROM_FORMAT.md)
jeefs-0.1.3/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # JEEFS Header — Python Package
2
+
3
+ Pure Python library for parsing and generating JEEFS EEPROM headers. The main API class `EEPROMHeaderV3` handles v3 headers; constants and field offsets for all versions (v1/v2/v3) are available via `jeefs.constants`. No native dependencies.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install jeefs
9
+ ```
10
+
11
+ ## Dependencies
12
+
13
+ - Python >= 3.10
14
+ - No external runtime dependencies (uses stdlib `struct`, `binascii`)
15
+
16
+ ## Building / Development
17
+
18
+ ```bash
19
+ cd python
20
+ uv venv .venv && uv pip install -e ".[test]"
21
+ .venv/bin/python -m pytest tests/ -v
22
+ ```
23
+
24
+ ## API
25
+
26
+ ### `EEPROMHeaderV3` — main dataclass
27
+
28
+ ```python
29
+ from jeefs.header import EEPROMHeaderV3
30
+ ```
31
+
32
+ #### Creating a header
33
+
34
+ ```python
35
+ header = EEPROMHeaderV3(
36
+ boardname="JetHub-D1p",
37
+ boardversion="2.0",
38
+ serial="SN-2024-001",
39
+ mac="F0:57:8D:01:02:03",
40
+ )
41
+ binary = header.to_bytes() # 256-byte binary
42
+ ```
43
+
44
+ #### Parsing from binary
45
+
46
+ ```python
47
+ header = EEPROMHeaderV3.from_bytes(raw_data)
48
+ print(header.boardname) # "JetHub-D1p"
49
+ print(header.mac) # "F0:57:8D:01:02:03"
50
+ print(header.serial) # "SN-2024-001"
51
+ ```
52
+
53
+ #### CRC verification
54
+
55
+ ```python
56
+ # Instance method
57
+ header = EEPROMHeaderV3.from_bytes(data)
58
+ is_valid = header.verify_crc(data)
59
+
60
+ # Static method (no instance needed)
61
+ is_valid = EEPROMHeaderV3.verify_crc_static(data)
62
+ ```
63
+
64
+ #### Validation
65
+
66
+ ```python
67
+ errors = header.validate()
68
+ if errors:
69
+ print("Invalid:", errors)
70
+ ```
71
+
72
+ #### Partition image
73
+
74
+ ```python
75
+ image = header.to_partition_image() # 4096-byte flash image
76
+ ```
77
+
78
+ ### Fields
79
+
80
+ | Field | Type | Description |
81
+ |-------|------|-------------|
82
+ | `boardname` | `str` | Board name (max 31 chars) |
83
+ | `boardversion` | `str` | Board version (max 31 chars) |
84
+ | `serial` | `str` | Serial number (max 31 chars) |
85
+ | `usid` | `str` | CPU eFuse USID |
86
+ | `cpuid` | `str` | CPU ID |
87
+ | `mac` | `str` | MAC address ("AA:BB:CC:DD:EE:FF") |
88
+ | `signature` | `bytes` | ECDSA signature (raw r\|\|s) |
89
+ | `signature_algorithm` | `SignatureAlgorithm` | NONE / SECP192R1 / SECP256R1 |
90
+ | `timestamp` | `int \| None` | Unix timestamp (auto-set if None/0) |
91
+
92
+ ### `SignatureAlgorithm` enum
93
+
94
+ ```python
95
+ from jeefs.constants import SignatureAlgorithm
96
+
97
+ SignatureAlgorithm.NONE # 0
98
+ SignatureAlgorithm.SECP192R1 # 1 (48-byte signature)
99
+ SignatureAlgorithm.SECP256R1 # 2 (64-byte signature)
100
+ ```
101
+
102
+ ### Constants
103
+
104
+ ```python
105
+ from jeefs.constants import (
106
+ EEPROM_MAGIC, # b"JETHOME\x00"
107
+ EEPROM_HEADER_SIZE, # 256
108
+ EEPROM_FIELDS, # dict of {field: (offset, size)}
109
+ EEPROM_CRC_COVERAGE, # 252
110
+ EEPROM_PARTITION_SIZE, # 4096
111
+ )
112
+ ```
113
+
114
+ ## Usage example
115
+
116
+ See [examples/python/read_header.py](https://github.com/jethome-iot/jeefs/blob/master/examples/python/read_header.py) — reads an EEPROM binary, prints version, CRC status, board name, MAC address, and full v3 fields.
117
+
118
+ ## Testing
119
+
120
+ ```bash
121
+ cd python
122
+ python -m pytest tests/ -v # 58 tests
123
+ ```
124
+
125
+ ## Format specification
126
+
127
+ - [Header common properties](https://github.com/jethome-iot/jeefs/blob/master/docs/format/header-common.md)
128
+ - [Header v3](https://github.com/jethome-iot/jeefs/blob/master/docs/format/header-v3.md)
129
+ - [Full format spec](https://github.com/jethome-iot/jeefs/blob/master/EEPROM_FORMAT.md)
@@ -0,0 +1,32 @@
1
+ # SPDX-License-Identifier: (GPL-2.0+ or Apache-2.0)
2
+ """EEPROM header generation, parsing, and validation.
3
+
4
+ Provides a single source of truth for JEEPROMHeaderv3 binary format.
5
+ """
6
+
7
+ from .constants import (
8
+ EEPROM_CRC_COVERAGE,
9
+ EEPROM_FIELDS,
10
+ EEPROM_HEADER_SIZE,
11
+ EEPROM_HEADER_VERSION,
12
+ EEPROM_MAGIC,
13
+ EEPROM_PARTITION_SIZE,
14
+ EEPROM_SIGNATURE_FIELD_SIZE,
15
+ SIGNATURE_SIZES,
16
+ SignatureAlgorithm,
17
+ )
18
+ from .header import EEPROMHeaderV3, parse_mac_string
19
+
20
+ __all__ = [
21
+ "EEPROMHeaderV3",
22
+ "SignatureAlgorithm",
23
+ "SIGNATURE_SIZES",
24
+ "EEPROM_FIELDS",
25
+ "EEPROM_HEADER_SIZE",
26
+ "EEPROM_HEADER_VERSION",
27
+ "EEPROM_MAGIC",
28
+ "EEPROM_CRC_COVERAGE",
29
+ "EEPROM_SIGNATURE_FIELD_SIZE",
30
+ "EEPROM_PARTITION_SIZE",
31
+ "parse_mac_string",
32
+ ]
@@ -0,0 +1,10 @@
1
+ # SPDX-License-Identifier: (GPL-2.0+ or Apache-2.0)
2
+ """EEPROM header constants and signature algorithm definitions.
3
+
4
+ Re-exports all constants from the auto-generated constants_generated module.
5
+ The generated module is the single source of truth — produced by:
6
+ python -m jeefs_codegen --specs docs/format/*.md --py-output python/jeefs/constants_generated.py
7
+ """
8
+
9
+ from .constants_generated import * # noqa: F401,F403
10
+ from .constants_generated import SignatureAlgorithm # explicit for type checkers
@@ -0,0 +1,130 @@
1
+ # SPDX-License-Identifier: (GPL-2.0+ or Apache-2.0)
2
+ """EEPROM format constants — auto-generated from docs/format/*.md.
3
+
4
+ DO NOT EDIT — regenerate with:
5
+ python -m jeefs_codegen --specs docs/format/*.md --py-output python/jeefs/constants_generated.py
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from enum import IntEnum
11
+
12
+
13
+ class SignatureAlgorithm(IntEnum):
14
+ """JEEFSSignatureAlgorithm values.
15
+
16
+ Values:
17
+ NONE: No signature (0)
18
+ SECP192R1: ECDSA secp192r1/NIST P-192, r‖s (1)
19
+ SECP256R1: ECDSA secp256r1/NIST P-256, r‖s (2)
20
+ """
21
+
22
+ NONE = 0
23
+ SECP192R1 = 1
24
+ SECP256R1 = 2
25
+
26
+ @classmethod
27
+ def from_int(cls, value: int) -> "SignatureAlgorithm":
28
+ """Convert integer to enum, raising ValueError for unknown."""
29
+ try:
30
+ return cls(value)
31
+ except ValueError:
32
+ valid = ", ".join(f"{m.value}={m.name}" for m in cls)
33
+ raise ValueError(
34
+ f"Unknown value={value}. Valid values: {valid}"
35
+ ) from None
36
+
37
+ SIGNATURE_SIZES: dict[SignatureAlgorithm, int] = {
38
+ SignatureAlgorithm.NONE: 0,
39
+ SignatureAlgorithm.SECP192R1: 48,
40
+ SignatureAlgorithm.SECP256R1: 64,
41
+ }
42
+ """Signature byte size per algorithm (raw r||s format)."""
43
+
44
+ # --- Named constants ---
45
+
46
+ EEPROM_MAGIC = b"JETHOME\x00"
47
+ EEPROM_MAGIC_LENGTH = 8
48
+ EEPROM_HEADER_VERSION = 3
49
+ EEPROM_SIGNATURE_FIELD_SIZE = 64
50
+ EEPROM_FILE_NAME_LENGTH = 15
51
+ EEPROM_MAC_LENGTH = 6
52
+ EEPROM_SERIAL_LENGTH = 32
53
+ EEPROM_USID_LENGTH = 32
54
+ EEPROM_CPUID_LENGTH = 32
55
+ EEPROM_BOARDNAME_LENGTH = 31
56
+ EEPROM_BOARDVERSION_LENGTH = 31
57
+ EEPROM_EMPTYBYTE = 0x00
58
+ EEPROM_PARTITION_SIZE = 4096
59
+
60
+ # Field offsets and sizes for JEEPROMHeaderv3
61
+ EEPROM_FIELDS: dict[str, tuple[int, int]] = {
62
+ "magic": (0, 8),
63
+ "version": (8, 1),
64
+ "signature_version": (9, 1),
65
+ "header_reserved": (10, 2),
66
+ "boardname": (12, 32),
67
+ "boardversion": (44, 32),
68
+ "serial": (76, 32),
69
+ "usid": (108, 32),
70
+ "cpuid": (140, 32),
71
+ "mac": (172, 6),
72
+ "reserved2": (178, 2),
73
+ "signature": (180, 64),
74
+ "timestamp": (244, 8),
75
+ "crc32": (252, 4),
76
+ }
77
+ EEPROM_HEADER_SIZE = 256
78
+ EEPROM_CRC_COVERAGE = 252
79
+
80
+ # Field offsets and sizes for JEEPROMHeaderv2
81
+ EEPROM_FIELDS_V2: dict[str, tuple[int, int]] = {
82
+ "magic": (0, 8),
83
+ "version": (8, 1),
84
+ "reserved1": (9, 3),
85
+ "boardname": (12, 32),
86
+ "boardversion": (44, 32),
87
+ "serial": (76, 32),
88
+ "usid": (108, 32),
89
+ "cpuid": (140, 32),
90
+ "mac": (172, 6),
91
+ "reserved2": (178, 2),
92
+ "reserved3": (180, 72),
93
+ "crc32": (252, 4),
94
+ }
95
+ EEPROM_V2_HEADER_SIZE = 256
96
+ EEPROM_V2_CRC_COVERAGE = 252
97
+
98
+ # Field offsets and sizes for JEEPROMHeaderv1
99
+ EEPROM_FIELDS_V1: dict[str, tuple[int, int]] = {
100
+ "magic": (0, 8),
101
+ "version": (8, 1),
102
+ "reserved1": (9, 3),
103
+ "boardname": (12, 32),
104
+ "boardversion": (44, 32),
105
+ "serial": (76, 32),
106
+ "usid": (108, 32),
107
+ "cpuid": (140, 32),
108
+ "mac": (172, 6),
109
+ "reserved2": (178, 2),
110
+ "modules": (180, 32),
111
+ "reserved3": (212, 296),
112
+ "crc32": (508, 4),
113
+ }
114
+ EEPROM_V1_HEADER_SIZE = 512
115
+ EEPROM_V1_CRC_COVERAGE = 508
116
+
117
+ # Field offsets and sizes for JEEPROMHeaderversion
118
+ EEPROM_FIELDS_JEEPROMHEADERVERSION: dict[str, tuple[int, int]] = {
119
+ "magic": (0, 8),
120
+ "version": (8, 1),
121
+ "reserved1": (9, 3),
122
+ }
123
+
124
+ # Field offsets and sizes for JEEFSFileHeaderv1
125
+ EEPROM_FIELDS_JEEFSFILEHEADERV1: dict[str, tuple[int, int]] = {
126
+ "name": (0, 16),
127
+ "dataSize": (16, 2),
128
+ "crc32": (18, 4),
129
+ "nextFileAddress": (22, 2),
130
+ }