pysd10 0.2.0__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.
pysd10-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,124 @@
1
+ Metadata-Version: 2.4
2
+ Name: pysd10
3
+ Version: 0.2.0
4
+ Summary: Python client for the Epson SD-10 spectrophotometer over Bluetooth LE (spectrum and L*a*b*)
5
+ Requires-Python: >=3.9
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: bleak>=0.21
8
+ Provides-Extra: test
9
+ Requires-Dist: pytest; extra == "test"
10
+
11
+ # sd10
12
+
13
+ Python client for the **Epson SD-10** spectrophotometer over Bluetooth LE: take measurements and get
14
+ the 31-band spectrum (400–700 nm) and CIE L\*a\*b\* exactly as the Epson Spectrometer app computes it.
15
+
16
+ ## Install
17
+
18
+ ```
19
+ pip install -e path\to\sd10_client
20
+ ```
21
+
22
+ Requires Python 3.9+ and [bleak](https://github.com/hbldh/bleak) (installed automatically).
23
+
24
+ ## Quick start (blocking — scripts, Jupyter)
25
+
26
+ ```python
27
+ import sd10
28
+
29
+ result = sd10.measure_once() # connect, measure, disconnect
30
+ print(result.lab) # Lab(L=..., a=..., b=...)
31
+
32
+ with sd10.connect_sync() as dev: # keep the connection open
33
+ r = dev.measure(illuminant="D65", observer=10, m_factor=0)
34
+ print(r.lab, r.lch, r.spectrum)
35
+ print(r.lab_under("A", 2)) # same reading, other illuminant
36
+
37
+ for r in dev.button_measurements(): # react to the device's own button
38
+ print(r.lab)
39
+ ```
40
+
41
+ ## Async
42
+
43
+ ```python
44
+ import asyncio, sd10
45
+
46
+ async def main():
47
+ async with sd10.connect() as dev: # strongest SD-10, or connect("40:84:32:52:FD:0F")
48
+ print(await dev.get_info())
49
+ r = await dev.measure()
50
+ print(r.lab)
51
+ async for r in dev.button_measurements():
52
+ print(r.lab)
53
+
54
+ asyncio.run(main())
55
+ ```
56
+
57
+ ## API overview
58
+
59
+ | | |
60
+ |---|---|
61
+ | `scan()` / `scan_sync()` | nearby SD-10s (`address`, `name`, `rssi`) |
62
+ | `connect(address=None)` / `connect_sync(...)` | connect and open a session; on exit the device is handed back to its own UI |
63
+ | `dev.measure(illuminant, observer, m_factor, save)` | one spot measurement → `MeasurementResult` |
64
+ | `dev.button_measurements()` | iterator of results taken with the device button |
65
+ | `dev.get_history(after_id=0, limit=None, progress=None)` | download readings stored on the device (it keeps its last 100), oldest first; pass the last `identifier` you have as `after_id` to fetch only new ones |
66
+ | `dev.history_count(after_id=0)` | how many stored readings are newer than `after_id` |
67
+ | `dev.get_groups()` | colour groups (palettes) stored on the device: 4 slots × up to 80 L\*a\*b\* colours → `[ColorGroup]` |
68
+ | `dev.set_group(ColorGroup(slot, name, colors, illuminant, observer, m_factor, diff_formula, tolerance))` | store/replace a palette in slot 1–4 |
69
+ | `dev.delete_group(slot)` | clear a slot |
70
+ | `dev.calibrate()` | white calibration with the cover **closed** (raises `CoverOpen` otherwise) → `Status` |
71
+ | `dev.scan_row(expected=None, patches=None, tolerance=None, ...)` | scan one row of ≤18 patches by sliding the device; with `expected` + `tolerance` each patch is judged → `RowResult` |
72
+ | `dev.scan_palette_row(slot, row, patches_per_row=10)` | scan one row of a printed chart of a stored palette and compare with it → `RowResult` |
73
+ | `dev.scan_palette(slot, patches_per_row=10)` | whole chart, row by row (async iterator of `RowResult`), then `finish_chart()` |
74
+ | `dev.measure_palette_patch(slot, patch)` | spot-measure one patch against palette colour `patch` → `PatchResult` |
75
+ | `dev.get_info()`, `get_status()`, `get_name()`, `get_serial()`, `get_firmware_version()` | device info |
76
+ | `dev.get_setting(Setting.X)` / `set_setting(...)` | buzzer, panel direction, auto power-off, language |
77
+ | `dev.set_clock()`, `dev.set_name(...)` | |
78
+ | `dev.transact(frame)` | raw command (see `sd10.protocol`) |
79
+ | `MeasurementResult` | `.lab`, `.lch`, `.lab_under(ill, obs)`, `.spectrum`, `.wavelengths`, `.timestamp`, `.to_dict()` |
80
+ | `spectrum_to_lab(spectrum, illuminant, observer)` | offline conversion |
81
+ | `delta_e(ref, sample, "DE2000" / "DE94GA" / "DE94T" / "DE76")`, `delta_e_2000`, `delta_e_94`, `delta_e_76` | colour difference (matches Epson's library) |
82
+ | `median_lab(labs)` | per-component median of several readings (the app's "Median") |
83
+ | `color_scheme(lab, "complementary" / "split_complementary" / "analogous" / "triadic" / "tetradic", illuminant, observer)` | the app's "Color Scheme" |
84
+ | `lab_to_hex(lab, illuminant, observer)`, `lab_to_srgb`, `srgb_to_lab` | sRGB / HEX as the app shows it |
85
+ | `export_aco(path, colors, names)`, `read_aco(path)` | Adobe Color Swatch (.aco) files for Photoshop / Illustrator |
86
+
87
+ Illuminants: D50, D65, A, F1, F2, F3, F7–F12. Observers: 2, 10.
88
+
89
+ Errors derive from `sd10.SD10Error` (`DeviceNotFound`, `DeviceRefused`, `SD10Timeout`, `MeasurementFailed`,
90
+ `CoverClosed` — raised instead of measuring when the cover is shut, because the device would just repeat its
91
+ previous reading).
92
+ Enable `logging.getLogger("sd10").setLevel(logging.DEBUG)` to see all traffic.
93
+
94
+ ## Command line
95
+
96
+ ```
97
+ sd10 scan
98
+ sd10 measure --illuminant D65 --observer 10 [--spectrum] [--json]
99
+ sd10 listen # L*a*b* for every button press
100
+ sd10 history [--after ID] [--last N] [--json | --csv FILE] # readings stored on the device
101
+ sd10 history --aco FILE # stored readings as an Adobe Color Swatch
102
+ sd10 scan-row --patches 6 | --expected row.json [--tolerance 2]
103
+ sd10 chart SLOT [--per-row 10] # scan a printed chart of a stored palette
104
+ sd10 groups list | delete SLOT | export SLOT FILE(.json|.aco) | import FILE [--slot N]
105
+ sd10 groups from-history SLOT NAME --ids 951,952,953 [--illuminant D65 --tolerance 2]
106
+ sd10 info | calibrate | set-time | set-name NAME | raw ID TYPE [HEX]
107
+ ```
108
+
109
+ (`python -m sd10 ...` works without installing the script; global options such as `-a ADDRESS`
110
+ and `-v` go before the command.)
111
+
112
+ ## Notes
113
+
114
+ - The SD-10 accepts one host at a time — close the Epson app on your phone first.
115
+ - A random 16-byte host id is kept in `~/.sd10_app_id`, like the app does.
116
+ - L\*a\*b\* reproduces Epson's `librmcc` conversion to ~1e-6 ΔE; bands outside 400–700 nm count as
117
+ zero, so a perfect white reads L\* ≈ 99.99, same as the app.
118
+
119
+ ## Tests
120
+
121
+ ```
122
+ pip install -e path\to\sd10_client[test]
123
+ pytest path\to\sd10_client\tests
124
+ ```
pysd10-0.2.0/README.md ADDED
@@ -0,0 +1,114 @@
1
+ # sd10
2
+
3
+ Python client for the **Epson SD-10** spectrophotometer over Bluetooth LE: take measurements and get
4
+ the 31-band spectrum (400–700 nm) and CIE L\*a\*b\* exactly as the Epson Spectrometer app computes it.
5
+
6
+ ## Install
7
+
8
+ ```
9
+ pip install -e path\to\sd10_client
10
+ ```
11
+
12
+ Requires Python 3.9+ and [bleak](https://github.com/hbldh/bleak) (installed automatically).
13
+
14
+ ## Quick start (blocking — scripts, Jupyter)
15
+
16
+ ```python
17
+ import sd10
18
+
19
+ result = sd10.measure_once() # connect, measure, disconnect
20
+ print(result.lab) # Lab(L=..., a=..., b=...)
21
+
22
+ with sd10.connect_sync() as dev: # keep the connection open
23
+ r = dev.measure(illuminant="D65", observer=10, m_factor=0)
24
+ print(r.lab, r.lch, r.spectrum)
25
+ print(r.lab_under("A", 2)) # same reading, other illuminant
26
+
27
+ for r in dev.button_measurements(): # react to the device's own button
28
+ print(r.lab)
29
+ ```
30
+
31
+ ## Async
32
+
33
+ ```python
34
+ import asyncio, sd10
35
+
36
+ async def main():
37
+ async with sd10.connect() as dev: # strongest SD-10, or connect("40:84:32:52:FD:0F")
38
+ print(await dev.get_info())
39
+ r = await dev.measure()
40
+ print(r.lab)
41
+ async for r in dev.button_measurements():
42
+ print(r.lab)
43
+
44
+ asyncio.run(main())
45
+ ```
46
+
47
+ ## API overview
48
+
49
+ | | |
50
+ |---|---|
51
+ | `scan()` / `scan_sync()` | nearby SD-10s (`address`, `name`, `rssi`) |
52
+ | `connect(address=None)` / `connect_sync(...)` | connect and open a session; on exit the device is handed back to its own UI |
53
+ | `dev.measure(illuminant, observer, m_factor, save)` | one spot measurement → `MeasurementResult` |
54
+ | `dev.button_measurements()` | iterator of results taken with the device button |
55
+ | `dev.get_history(after_id=0, limit=None, progress=None)` | download readings stored on the device (it keeps its last 100), oldest first; pass the last `identifier` you have as `after_id` to fetch only new ones |
56
+ | `dev.history_count(after_id=0)` | how many stored readings are newer than `after_id` |
57
+ | `dev.get_groups()` | colour groups (palettes) stored on the device: 4 slots × up to 80 L\*a\*b\* colours → `[ColorGroup]` |
58
+ | `dev.set_group(ColorGroup(slot, name, colors, illuminant, observer, m_factor, diff_formula, tolerance))` | store/replace a palette in slot 1–4 |
59
+ | `dev.delete_group(slot)` | clear a slot |
60
+ | `dev.calibrate()` | white calibration with the cover **closed** (raises `CoverOpen` otherwise) → `Status` |
61
+ | `dev.scan_row(expected=None, patches=None, tolerance=None, ...)` | scan one row of ≤18 patches by sliding the device; with `expected` + `tolerance` each patch is judged → `RowResult` |
62
+ | `dev.scan_palette_row(slot, row, patches_per_row=10)` | scan one row of a printed chart of a stored palette and compare with it → `RowResult` |
63
+ | `dev.scan_palette(slot, patches_per_row=10)` | whole chart, row by row (async iterator of `RowResult`), then `finish_chart()` |
64
+ | `dev.measure_palette_patch(slot, patch)` | spot-measure one patch against palette colour `patch` → `PatchResult` |
65
+ | `dev.get_info()`, `get_status()`, `get_name()`, `get_serial()`, `get_firmware_version()` | device info |
66
+ | `dev.get_setting(Setting.X)` / `set_setting(...)` | buzzer, panel direction, auto power-off, language |
67
+ | `dev.set_clock()`, `dev.set_name(...)` | |
68
+ | `dev.transact(frame)` | raw command (see `sd10.protocol`) |
69
+ | `MeasurementResult` | `.lab`, `.lch`, `.lab_under(ill, obs)`, `.spectrum`, `.wavelengths`, `.timestamp`, `.to_dict()` |
70
+ | `spectrum_to_lab(spectrum, illuminant, observer)` | offline conversion |
71
+ | `delta_e(ref, sample, "DE2000" / "DE94GA" / "DE94T" / "DE76")`, `delta_e_2000`, `delta_e_94`, `delta_e_76` | colour difference (matches Epson's library) |
72
+ | `median_lab(labs)` | per-component median of several readings (the app's "Median") |
73
+ | `color_scheme(lab, "complementary" / "split_complementary" / "analogous" / "triadic" / "tetradic", illuminant, observer)` | the app's "Color Scheme" |
74
+ | `lab_to_hex(lab, illuminant, observer)`, `lab_to_srgb`, `srgb_to_lab` | sRGB / HEX as the app shows it |
75
+ | `export_aco(path, colors, names)`, `read_aco(path)` | Adobe Color Swatch (.aco) files for Photoshop / Illustrator |
76
+
77
+ Illuminants: D50, D65, A, F1, F2, F3, F7–F12. Observers: 2, 10.
78
+
79
+ Errors derive from `sd10.SD10Error` (`DeviceNotFound`, `DeviceRefused`, `SD10Timeout`, `MeasurementFailed`,
80
+ `CoverClosed` — raised instead of measuring when the cover is shut, because the device would just repeat its
81
+ previous reading).
82
+ Enable `logging.getLogger("sd10").setLevel(logging.DEBUG)` to see all traffic.
83
+
84
+ ## Command line
85
+
86
+ ```
87
+ sd10 scan
88
+ sd10 measure --illuminant D65 --observer 10 [--spectrum] [--json]
89
+ sd10 listen # L*a*b* for every button press
90
+ sd10 history [--after ID] [--last N] [--json | --csv FILE] # readings stored on the device
91
+ sd10 history --aco FILE # stored readings as an Adobe Color Swatch
92
+ sd10 scan-row --patches 6 | --expected row.json [--tolerance 2]
93
+ sd10 chart SLOT [--per-row 10] # scan a printed chart of a stored palette
94
+ sd10 groups list | delete SLOT | export SLOT FILE(.json|.aco) | import FILE [--slot N]
95
+ sd10 groups from-history SLOT NAME --ids 951,952,953 [--illuminant D65 --tolerance 2]
96
+ sd10 info | calibrate | set-time | set-name NAME | raw ID TYPE [HEX]
97
+ ```
98
+
99
+ (`python -m sd10 ...` works without installing the script; global options such as `-a ADDRESS`
100
+ and `-v` go before the command.)
101
+
102
+ ## Notes
103
+
104
+ - The SD-10 accepts one host at a time — close the Epson app on your phone first.
105
+ - A random 16-byte host id is kept in `~/.sd10_app_id`, like the app does.
106
+ - L\*a\*b\* reproduces Epson's `librmcc` conversion to ~1e-6 ΔE; bands outside 400–700 nm count as
107
+ zero, so a perfect white reads L\* ≈ 99.99, same as the app.
108
+
109
+ ## Tests
110
+
111
+ ```
112
+ pip install -e path\to\sd10_client[test]
113
+ pytest path\to\sd10_client\tests
114
+ ```
@@ -0,0 +1,23 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pysd10"
7
+ version = "0.2.0"
8
+ description = "Python client for the Epson SD-10 spectrophotometer over Bluetooth LE (spectrum and L*a*b*)"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ dependencies = ["bleak>=0.21"]
12
+
13
+ [project.optional-dependencies]
14
+ test = ["pytest"]
15
+
16
+ [project.scripts]
17
+ sd10 = "sd10.cli:main"
18
+
19
+ [tool.setuptools]
20
+ packages = ["sd10"]
21
+
22
+ [tool.setuptools.package-data]
23
+ sd10 = ["data/*.json", "py.typed"]
@@ -0,0 +1,124 @@
1
+ Metadata-Version: 2.4
2
+ Name: pysd10
3
+ Version: 0.2.0
4
+ Summary: Python client for the Epson SD-10 spectrophotometer over Bluetooth LE (spectrum and L*a*b*)
5
+ Requires-Python: >=3.9
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: bleak>=0.21
8
+ Provides-Extra: test
9
+ Requires-Dist: pytest; extra == "test"
10
+
11
+ # sd10
12
+
13
+ Python client for the **Epson SD-10** spectrophotometer over Bluetooth LE: take measurements and get
14
+ the 31-band spectrum (400–700 nm) and CIE L\*a\*b\* exactly as the Epson Spectrometer app computes it.
15
+
16
+ ## Install
17
+
18
+ ```
19
+ pip install -e path\to\sd10_client
20
+ ```
21
+
22
+ Requires Python 3.9+ and [bleak](https://github.com/hbldh/bleak) (installed automatically).
23
+
24
+ ## Quick start (blocking — scripts, Jupyter)
25
+
26
+ ```python
27
+ import sd10
28
+
29
+ result = sd10.measure_once() # connect, measure, disconnect
30
+ print(result.lab) # Lab(L=..., a=..., b=...)
31
+
32
+ with sd10.connect_sync() as dev: # keep the connection open
33
+ r = dev.measure(illuminant="D65", observer=10, m_factor=0)
34
+ print(r.lab, r.lch, r.spectrum)
35
+ print(r.lab_under("A", 2)) # same reading, other illuminant
36
+
37
+ for r in dev.button_measurements(): # react to the device's own button
38
+ print(r.lab)
39
+ ```
40
+
41
+ ## Async
42
+
43
+ ```python
44
+ import asyncio, sd10
45
+
46
+ async def main():
47
+ async with sd10.connect() as dev: # strongest SD-10, or connect("40:84:32:52:FD:0F")
48
+ print(await dev.get_info())
49
+ r = await dev.measure()
50
+ print(r.lab)
51
+ async for r in dev.button_measurements():
52
+ print(r.lab)
53
+
54
+ asyncio.run(main())
55
+ ```
56
+
57
+ ## API overview
58
+
59
+ | | |
60
+ |---|---|
61
+ | `scan()` / `scan_sync()` | nearby SD-10s (`address`, `name`, `rssi`) |
62
+ | `connect(address=None)` / `connect_sync(...)` | connect and open a session; on exit the device is handed back to its own UI |
63
+ | `dev.measure(illuminant, observer, m_factor, save)` | one spot measurement → `MeasurementResult` |
64
+ | `dev.button_measurements()` | iterator of results taken with the device button |
65
+ | `dev.get_history(after_id=0, limit=None, progress=None)` | download readings stored on the device (it keeps its last 100), oldest first; pass the last `identifier` you have as `after_id` to fetch only new ones |
66
+ | `dev.history_count(after_id=0)` | how many stored readings are newer than `after_id` |
67
+ | `dev.get_groups()` | colour groups (palettes) stored on the device: 4 slots × up to 80 L\*a\*b\* colours → `[ColorGroup]` |
68
+ | `dev.set_group(ColorGroup(slot, name, colors, illuminant, observer, m_factor, diff_formula, tolerance))` | store/replace a palette in slot 1–4 |
69
+ | `dev.delete_group(slot)` | clear a slot |
70
+ | `dev.calibrate()` | white calibration with the cover **closed** (raises `CoverOpen` otherwise) → `Status` |
71
+ | `dev.scan_row(expected=None, patches=None, tolerance=None, ...)` | scan one row of ≤18 patches by sliding the device; with `expected` + `tolerance` each patch is judged → `RowResult` |
72
+ | `dev.scan_palette_row(slot, row, patches_per_row=10)` | scan one row of a printed chart of a stored palette and compare with it → `RowResult` |
73
+ | `dev.scan_palette(slot, patches_per_row=10)` | whole chart, row by row (async iterator of `RowResult`), then `finish_chart()` |
74
+ | `dev.measure_palette_patch(slot, patch)` | spot-measure one patch against palette colour `patch` → `PatchResult` |
75
+ | `dev.get_info()`, `get_status()`, `get_name()`, `get_serial()`, `get_firmware_version()` | device info |
76
+ | `dev.get_setting(Setting.X)` / `set_setting(...)` | buzzer, panel direction, auto power-off, language |
77
+ | `dev.set_clock()`, `dev.set_name(...)` | |
78
+ | `dev.transact(frame)` | raw command (see `sd10.protocol`) |
79
+ | `MeasurementResult` | `.lab`, `.lch`, `.lab_under(ill, obs)`, `.spectrum`, `.wavelengths`, `.timestamp`, `.to_dict()` |
80
+ | `spectrum_to_lab(spectrum, illuminant, observer)` | offline conversion |
81
+ | `delta_e(ref, sample, "DE2000" / "DE94GA" / "DE94T" / "DE76")`, `delta_e_2000`, `delta_e_94`, `delta_e_76` | colour difference (matches Epson's library) |
82
+ | `median_lab(labs)` | per-component median of several readings (the app's "Median") |
83
+ | `color_scheme(lab, "complementary" / "split_complementary" / "analogous" / "triadic" / "tetradic", illuminant, observer)` | the app's "Color Scheme" |
84
+ | `lab_to_hex(lab, illuminant, observer)`, `lab_to_srgb`, `srgb_to_lab` | sRGB / HEX as the app shows it |
85
+ | `export_aco(path, colors, names)`, `read_aco(path)` | Adobe Color Swatch (.aco) files for Photoshop / Illustrator |
86
+
87
+ Illuminants: D50, D65, A, F1, F2, F3, F7–F12. Observers: 2, 10.
88
+
89
+ Errors derive from `sd10.SD10Error` (`DeviceNotFound`, `DeviceRefused`, `SD10Timeout`, `MeasurementFailed`,
90
+ `CoverClosed` — raised instead of measuring when the cover is shut, because the device would just repeat its
91
+ previous reading).
92
+ Enable `logging.getLogger("sd10").setLevel(logging.DEBUG)` to see all traffic.
93
+
94
+ ## Command line
95
+
96
+ ```
97
+ sd10 scan
98
+ sd10 measure --illuminant D65 --observer 10 [--spectrum] [--json]
99
+ sd10 listen # L*a*b* for every button press
100
+ sd10 history [--after ID] [--last N] [--json | --csv FILE] # readings stored on the device
101
+ sd10 history --aco FILE # stored readings as an Adobe Color Swatch
102
+ sd10 scan-row --patches 6 | --expected row.json [--tolerance 2]
103
+ sd10 chart SLOT [--per-row 10] # scan a printed chart of a stored palette
104
+ sd10 groups list | delete SLOT | export SLOT FILE(.json|.aco) | import FILE [--slot N]
105
+ sd10 groups from-history SLOT NAME --ids 951,952,953 [--illuminant D65 --tolerance 2]
106
+ sd10 info | calibrate | set-time | set-name NAME | raw ID TYPE [HEX]
107
+ ```
108
+
109
+ (`python -m sd10 ...` works without installing the script; global options such as `-a ADDRESS`
110
+ and `-v` go before the command.)
111
+
112
+ ## Notes
113
+
114
+ - The SD-10 accepts one host at a time — close the Epson app on your phone first.
115
+ - A random 16-byte host id is kept in `~/.sd10_app_id`, like the app does.
116
+ - L\*a\*b\* reproduces Epson's `librmcc` conversion to ~1e-6 ΔE; bands outside 400–700 nm count as
117
+ zero, so a perfect white reads L\* ≈ 99.99, same as the app.
118
+
119
+ ## Tests
120
+
121
+ ```
122
+ pip install -e path\to\sd10_client[test]
123
+ pytest path\to\sd10_client\tests
124
+ ```
@@ -0,0 +1,19 @@
1
+ README.md
2
+ pyproject.toml
3
+ pysd10.egg-info/PKG-INFO
4
+ pysd10.egg-info/SOURCES.txt
5
+ pysd10.egg-info/dependency_links.txt
6
+ pysd10.egg-info/entry_points.txt
7
+ pysd10.egg-info/requires.txt
8
+ pysd10.egg-info/top_level.txt
9
+ sd10/__init__.py
10
+ sd10/__main__.py
11
+ sd10/cli.py
12
+ sd10/client.py
13
+ sd10/color.py
14
+ sd10/export.py
15
+ sd10/protocol.py
16
+ sd10/py.typed
17
+ sd10/sync.py
18
+ sd10/data/lab_weights.json
19
+ tests/test_sd10.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ sd10 = sd10.cli:main
@@ -0,0 +1,4 @@
1
+ bleak>=0.21
2
+
3
+ [test]
4
+ pytest
@@ -0,0 +1 @@
1
+ sd10
@@ -0,0 +1,44 @@
1
+ """Python client for the Epson SD-10 spectrophotometer over Bluetooth LE.
2
+
3
+ Async::
4
+
5
+ import asyncio, sd10
6
+
7
+ async def main():
8
+ async with sd10.connect() as dev:
9
+ result = await dev.measure(illuminant="D65", observer=10)
10
+ print(result.lab, result.lch)
11
+
12
+ asyncio.run(main())
13
+
14
+ Blocking::
15
+
16
+ import sd10
17
+ print(sd10.measure_once().lab)
18
+
19
+ with sd10.connect_sync() as dev:
20
+ for result in dev.button_measurements():
21
+ print(result.lab)
22
+ """
23
+ from .client import (SD10, CalibrationNeeded, CoverClosed, CoverOpen, DeviceInfo, DeviceNotFound, DeviceRefused,
24
+ FoundDevice, MeasurementFailed, PatchResult, RowResult, SD10Error, SD10Timeout, connect,
25
+ find_device, load_app_id, scan)
26
+ from .color import (COLOR_SCHEMES, DELTA_E_FORMULAS, ILLUMINANTS, OBSERVERS, WAVELENGTHS, Lab, LCh, color_scheme,
27
+ delta_e, delta_e_76, delta_e_94, delta_e_2000, lab_to_hex, lab_to_srgb, median_lab,
28
+ spectrum_to_lab, srgb_to_lab)
29
+ from .export import aco_bytes, export_aco, read_aco
30
+ from .protocol import ColorGroup, Event, MeasurementResult, Method, Setting, Status
31
+ from .sync import SyncSD10, connect_sync, measure_once, scan_sync
32
+
33
+ __version__ = "0.2.0"
34
+
35
+ __all__ = [
36
+ "SD10", "connect", "scan", "find_device", "load_app_id", "DeviceInfo", "FoundDevice",
37
+ "SyncSD10", "connect_sync", "scan_sync", "measure_once",
38
+ "MeasurementResult", "Status", "Setting", "Event", "Method", "ColorGroup", "PatchResult", "RowResult",
39
+ "Lab", "LCh", "spectrum_to_lab", "delta_e", "delta_e_76", "delta_e_94", "delta_e_2000", "median_lab",
40
+ "color_scheme", "lab_to_srgb", "srgb_to_lab", "lab_to_hex", "COLOR_SCHEMES", "DELTA_E_FORMULAS",
41
+ "ILLUMINANTS", "OBSERVERS", "WAVELENGTHS", "export_aco", "aco_bytes", "read_aco",
42
+ "SD10Error", "SD10Timeout", "DeviceNotFound", "DeviceRefused", "MeasurementFailed", "CoverClosed",
43
+ "CalibrationNeeded", "CoverOpen",
44
+ ]
@@ -0,0 +1,3 @@
1
+ from .cli import main
2
+
3
+ main()