IS-Matrix-Forge 1.0.0.dev1__py3-none-any.whl
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.
- is_matrix_forge/__init__.py +8 -0
- is_matrix_forge/assets/__init__.py +8 -0
- is_matrix_forge/assets/audio/__init__.py +36 -0
- is_matrix_forge/assets/audio/files/__init__.py +53 -0
- is_matrix_forge/assets/audio/files/plugged.wav +0 -0
- is_matrix_forge/assets/audio/files/unplugged.wav +0 -0
- is_matrix_forge/assets/char_map.json +2150 -0
- is_matrix_forge/assets/font_map.py +119 -0
- is_matrix_forge/common/__init__.py +0 -0
- is_matrix_forge/common/decorators/__init__.py +152 -0
- is_matrix_forge/common/dirs.py +20 -0
- is_matrix_forge/common/helpers/__init__.py +132 -0
- is_matrix_forge/common/helpers/github_api.py +67 -0
- is_matrix_forge/designer_gui/__init__.py +8 -0
- is_matrix_forge/designer_gui/main_window/__init__.py +252 -0
- is_matrix_forge/designer_gui/main_window/layout.py +117 -0
- is_matrix_forge/dev_tools/__init__.py +8 -0
- is_matrix_forge/dev_tools/debug.py +82 -0
- is_matrix_forge/dev_tools/presets.py +47 -0
- is_matrix_forge/inputmodule/__init__.py +164 -0
- is_matrix_forge/inputmodule/b1display.py +160 -0
- is_matrix_forge/inputmodule/c1minimal.py +35 -0
- is_matrix_forge/inputmodule/font.py +2166 -0
- is_matrix_forge/inputmodule/helpers/__init__.py +16 -0
- is_matrix_forge/inputmodule/ledmatrix.py +516 -0
- is_matrix_forge/led_matrix/Scripts/__init__.py +4 -0
- is_matrix_forge/led_matrix/Scripts/battery_monitor.py +152 -0
- is_matrix_forge/led_matrix/Scripts/install_presets/__init__.py +2 -0
- is_matrix_forge/led_matrix/Scripts/install_presets/arguments.py +84 -0
- is_matrix_forge/led_matrix/Scripts/install_presets/main.py +192 -0
- is_matrix_forge/led_matrix/__init__.py +7 -0
- is_matrix_forge/led_matrix/commands/__init__.py +84 -0
- is_matrix_forge/led_matrix/commands/map.py +46 -0
- is_matrix_forge/led_matrix/constants.py +82 -0
- is_matrix_forge/led_matrix/controller/__init__.py +26 -0
- is_matrix_forge/led_matrix/controller/controller.py +635 -0
- is_matrix_forge/led_matrix/controller/helpers/__init__.py +7 -0
- is_matrix_forge/led_matrix/controller/helpers/threading.py +41 -0
- is_matrix_forge/led_matrix/controller/multiton.py +32 -0
- is_matrix_forge/led_matrix/controller/threaded.py +72 -0
- is_matrix_forge/led_matrix/display/__init__.py +13 -0
- is_matrix_forge/led_matrix/display/animations/__init__.py +29 -0
- is_matrix_forge/led_matrix/display/animations/animation.py +593 -0
- is_matrix_forge/led_matrix/display/animations/effects/__init__.py +17 -0
- is_matrix_forge/led_matrix/display/animations/errors.py +23 -0
- is_matrix_forge/led_matrix/display/animations/font/__init__.py +17 -0
- is_matrix_forge/led_matrix/display/animations/font/font.py +4 -0
- is_matrix_forge/led_matrix/display/animations/font/map_builder.py +123 -0
- is_matrix_forge/led_matrix/display/animations/frame/__init__.py +47 -0
- is_matrix_forge/led_matrix/display/animations/frame/base.py +245 -0
- is_matrix_forge/led_matrix/display/animations/frame/helpers.py +67 -0
- is_matrix_forge/led_matrix/display/animations/keep_awake.py +1 -0
- is_matrix_forge/led_matrix/display/animations/plugged.py +0 -0
- is_matrix_forge/led_matrix/display/animations/text_scroller.py +104 -0
- is_matrix_forge/led_matrix/display/effects/__init__.py +17 -0
- is_matrix_forge/led_matrix/display/effects/breather.py +206 -0
- is_matrix_forge/led_matrix/display/effects/fade.py +0 -0
- is_matrix_forge/led_matrix/display/effects/scroller/__init__.py +92 -0
- is_matrix_forge/led_matrix/display/effects/scroller/base.py +76 -0
- is_matrix_forge/led_matrix/display/effects/scroller/helpers.py +62 -0
- is_matrix_forge/led_matrix/display/grid/__init__.py +9 -0
- is_matrix_forge/led_matrix/display/grid/grid.py +208 -0
- is_matrix_forge/led_matrix/display/grid/helpers.py +130 -0
- is_matrix_forge/led_matrix/display/grid/presets/__init__.py +64 -0
- is_matrix_forge/led_matrix/display/grid/presets/manifest.py +172 -0
- is_matrix_forge/led_matrix/display/helpers/__init__.py +110 -0
- is_matrix_forge/led_matrix/display/helpers/columns.py +33 -0
- is_matrix_forge/led_matrix/display/media.py +199 -0
- is_matrix_forge/led_matrix/display/patterns/__init__.py +59 -0
- is_matrix_forge/led_matrix/display/patterns/built_in/__init__.py +91 -0
- is_matrix_forge/led_matrix/display/patterns/built_in/commands.py +3 -0
- is_matrix_forge/led_matrix/display/patterns/built_in/constants.py +29 -0
- is_matrix_forge/led_matrix/display/patterns/built_in/stencils.py +70 -0
- is_matrix_forge/led_matrix/display/patterns/utils.py +2 -0
- is_matrix_forge/led_matrix/display/text/__init__.py +66 -0
- is_matrix_forge/led_matrix/display/text/scroller.py +136 -0
- is_matrix_forge/led_matrix/errors/__init__.py +4 -0
- is_matrix_forge/led_matrix/errors/base.py +14 -0
- is_matrix_forge/led_matrix/errors/grid.py +37 -0
- is_matrix_forge/led_matrix/errors/matrix.py +68 -0
- is_matrix_forge/led_matrix/errors/misc.py +36 -0
- is_matrix_forge/led_matrix/fonts.py +20 -0
- is_matrix_forge/led_matrix/hardware.py +172 -0
- is_matrix_forge/led_matrix/helpers/__init__.py +165 -0
- is_matrix_forge/led_matrix/helpers/core/__init__.py +17 -0
- is_matrix_forge/led_matrix/helpers/core/lazy_mod_load.py +84 -0
- is_matrix_forge/led_matrix/helpers/device.py +118 -0
- is_matrix_forge/led_matrix/helpers/status_handler.py +14 -0
- is_matrix_forge/led_matrix/helpers/stream/__init__.py +70 -0
- is_matrix_forge/led_matrix/helpers/stream/errors.py +17 -0
- is_matrix_forge/led_matrix/led_matrix.py +25 -0
- is_matrix_forge/led_matrix/status.py +8 -0
- is_matrix_forge/led_matrix/tools/__init__.py +8 -0
- is_matrix_forge/led_matrix/tools/identify.py +27 -0
- is_matrix_forge/led_matrix/utils/__init__.py +41 -0
- is_matrix_forge/log_engine.py +25 -0
- is_matrix_forge/monitor/__init__.py +68 -0
- is_matrix_forge/monitor/errors.py +35 -0
- is_matrix_forge/monitor/events.py +78 -0
- is_matrix_forge/monitor/gui/__init__.py +0 -0
- is_matrix_forge/monitor/gui/errors.py +35 -0
- is_matrix_forge/monitor/gui/event/__init__.py +8 -0
- is_matrix_forge/monitor/gui/event/collection.py +153 -0
- is_matrix_forge/monitor/gui/event/errors.py +58 -0
- is_matrix_forge/monitor/gui/event/event.py +226 -0
- is_matrix_forge/monitor/gui/layout/__init__.py +8 -0
- is_matrix_forge/monitor/gui/layout/base.py +147 -0
- is_matrix_forge/monitor/gui/metaclasses/__init__.py +20 -0
- is_matrix_forge/monitor/gui/windows/__init__.py +0 -0
- is_matrix_forge/monitor/gui/windows/base.py +325 -0
- is_matrix_forge/monitor/gui/windows/main/__init__.py +77 -0
- is_matrix_forge/monitor/gui/windows/main/layout.py +21 -0
- is_matrix_forge/monitor/helpers.py +55 -0
- is_matrix_forge/monitor/monitor.py +431 -0
- is_matrix_forge/notify/__init__.py +0 -0
- is_matrix_forge/notify/sounds/__init__.py +6 -0
- is_matrix_forge/notify/sounds/base.py +106 -0
- is_matrix_forge/progress.py +99 -0
- is_matrix_forge-1.0.0.dev1.dist-info/LICENSE.md +19 -0
- is_matrix_forge-1.0.0.dev1.dist-info/METADATA +190 -0
- is_matrix_forge-1.0.0.dev1.dist-info/RECORD +123 -0
- is_matrix_forge-1.0.0.dev1.dist-info/WHEEL +4 -0
- is_matrix_forge-1.0.0.dev1.dist-info/entry_points.txt +5 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author:
|
|
3
|
+
Inspyre Softworks
|
|
4
|
+
|
|
5
|
+
Project:
|
|
6
|
+
led-matrix-battery
|
|
7
|
+
|
|
8
|
+
File:
|
|
9
|
+
is_matrix_forge/led_matrix/Scripts/install_presets/arguments.py
|
|
10
|
+
|
|
11
|
+
Description:
|
|
12
|
+
Holds the Arguments class for the command-line arguments for the preset
|
|
13
|
+
installer.
|
|
14
|
+
"""
|
|
15
|
+
from argparse import ArgumentParser
|
|
16
|
+
from is_matrix_forge.log_engine import LOG_LEVELS
|
|
17
|
+
from is_matrix_forge.led_matrix.constants import APP_DIRS
|
|
18
|
+
from is_matrix_forge.common.helpers.github_api import REPO_PRESETS_URL
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Arguments(ArgumentParser):
|
|
22
|
+
|
|
23
|
+
def __init__(self, *args, **kwargs):
|
|
24
|
+
super().__init__(
|
|
25
|
+
'LEDMatrixLib:install_presets',
|
|
26
|
+
description='Download and install premade LED matrix grid design patterns from GitHub.',
|
|
27
|
+
)
|
|
28
|
+
self.__parsed = None
|
|
29
|
+
|
|
30
|
+
self.__build()
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def parsed(self):
|
|
34
|
+
"""
|
|
35
|
+
Returns the parsed command-line arguments.
|
|
36
|
+
"""
|
|
37
|
+
if self.__parsed is None:
|
|
38
|
+
self.parse()
|
|
39
|
+
|
|
40
|
+
return self.__parsed
|
|
41
|
+
|
|
42
|
+
def __build(self):
|
|
43
|
+
"""
|
|
44
|
+
Build the command-line arguments.
|
|
45
|
+
"""
|
|
46
|
+
# Add the `URL` argument
|
|
47
|
+
self.add_argument(
|
|
48
|
+
'--url',
|
|
49
|
+
help='GitHub API URL to download presets from.',
|
|
50
|
+
default=REPO_PRESETS_URL,
|
|
51
|
+
action='store'
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# Add the `app-dir` argument
|
|
55
|
+
self.add_argument(
|
|
56
|
+
'--app-dir',
|
|
57
|
+
help='The directory in which this app can save its files.',
|
|
58
|
+
default=APP_DIRS.user_data_path,
|
|
59
|
+
action='store'
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Add the `overwrite` argument.
|
|
63
|
+
self.add_argument(
|
|
64
|
+
'--overwrite',
|
|
65
|
+
help='Overwrite existing preset files to be replaced.',
|
|
66
|
+
action='store_true',
|
|
67
|
+
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# Add the `no-progress` argument.
|
|
71
|
+
self.add_argument(
|
|
72
|
+
'--no-progress',
|
|
73
|
+
help='Disable progress bars.',
|
|
74
|
+
action='store_true'
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
def parse(self):
|
|
78
|
+
"""
|
|
79
|
+
Parse the command-line arguments.
|
|
80
|
+
|
|
81
|
+
Note:
|
|
82
|
+
Once this method is run, it will define `Arguments.parsed`.
|
|
83
|
+
"""
|
|
84
|
+
self.__parsed = self.parse_args()
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author:
|
|
3
|
+
Taylor B.
|
|
4
|
+
|
|
5
|
+
Project:
|
|
6
|
+
led-matrix-battery
|
|
7
|
+
|
|
8
|
+
File:
|
|
9
|
+
is_matrix_forge/led_matrix/Scripts/install_presets/main.py
|
|
10
|
+
|
|
11
|
+
Description:
|
|
12
|
+
Provides a CLI to download JSON preset files from the GitHub repository and save them locally,
|
|
13
|
+
ensuring local files are fresh by verifying and re-downloading if checksums differ.
|
|
14
|
+
|
|
15
|
+
Classes:
|
|
16
|
+
- PresetInstaller
|
|
17
|
+
|
|
18
|
+
Functions:
|
|
19
|
+
- main
|
|
20
|
+
|
|
21
|
+
Constants:
|
|
22
|
+
- API_URL
|
|
23
|
+
- REQ_HEADERS
|
|
24
|
+
- REPO_PRESETS_URL
|
|
25
|
+
|
|
26
|
+
Dependencies:
|
|
27
|
+
- typing
|
|
28
|
+
- pathlib
|
|
29
|
+
- requests
|
|
30
|
+
- tqdm
|
|
31
|
+
- inspy_logger
|
|
32
|
+
- inspyre_toolbox.path_man.provision_path
|
|
33
|
+
- is_matrix_forge.common.helpers.verify_checksum
|
|
34
|
+
- is_matrix_forge.led_matrix.constants.PROJECT_URLS, APP_DIRS
|
|
35
|
+
- is_matrix_forge.common.helpers.github_api.assemble_github_content_path_url
|
|
36
|
+
- is_matrix_forge.led_matrix.display.grid.presets.manifest.GridPresetManifest
|
|
37
|
+
|
|
38
|
+
Example Usage:
|
|
39
|
+
python -m is_matrix_forge.preset_installer \
|
|
40
|
+
--app-dir /path/to/data \
|
|
41
|
+
--overwrite \
|
|
42
|
+
--no-progress
|
|
43
|
+
"""
|
|
44
|
+
import argparse
|
|
45
|
+
from typing import List, Dict, Optional, Union
|
|
46
|
+
from pathlib import Path
|
|
47
|
+
import requests
|
|
48
|
+
import hashlib
|
|
49
|
+
from is_matrix_forge.progress import tqdm
|
|
50
|
+
|
|
51
|
+
from is_matrix_forge.led_matrix.constants import PROJECT_URLS, APP_DIRS, GITHUB_REQ_HEADERS as REQ_HEADERS
|
|
52
|
+
from is_matrix_forge.led_matrix.display.grid.presets.manifest import GridPresetManifest
|
|
53
|
+
from inspy_logger import InspyLogger, Loggable
|
|
54
|
+
from inspyre_toolbox.path_man import provision_path
|
|
55
|
+
from is_matrix_forge.common.helpers.github_api import assemble_github_content_path_url as assemble_url, REPO_PRESETS_URL
|
|
56
|
+
|
|
57
|
+
LOGGER = InspyLogger('LEDMatrixLib:PresetInstaller', console_level='info', no_file_logging=True)
|
|
58
|
+
|
|
59
|
+
API_URL = PROJECT_URLS['github_api']
|
|
60
|
+
REQ_HEADERS = {"Accept": "application/vnd.github.v3+json"}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def github_blob_sha(content: bytes) -> str:
|
|
64
|
+
header = f"blob {len(content)}\0".encode()
|
|
65
|
+
return hashlib.sha1(header + content).hexdigest()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class PresetInstaller(Loggable):
|
|
69
|
+
def __init__(
|
|
70
|
+
self,
|
|
71
|
+
url: str = REPO_PRESETS_URL,
|
|
72
|
+
headers: Optional[Dict[str, str]] = None,
|
|
73
|
+
app_dir: Union[str, Path] = APP_DIRS.user_data_path,
|
|
74
|
+
overwrite_existing: bool = False,
|
|
75
|
+
with_progress: bool = True
|
|
76
|
+
):
|
|
77
|
+
super().__init__(LOGGER)
|
|
78
|
+
self.url = url
|
|
79
|
+
self.headers = headers or REQ_HEADERS
|
|
80
|
+
self.app_dir = provision_path(app_dir)
|
|
81
|
+
self.overwrite = overwrite_existing
|
|
82
|
+
self.with_progress = with_progress
|
|
83
|
+
|
|
84
|
+
self.presets_dir = self.app_dir / 'presets'
|
|
85
|
+
self.presets_dir.mkdir(parents=True, exist_ok=True)
|
|
86
|
+
self.log = self.class_logger
|
|
87
|
+
|
|
88
|
+
def run(self):
|
|
89
|
+
log = self.method_logger
|
|
90
|
+
log.debug(f"Fetching file list from {self.url}")
|
|
91
|
+
files = self.get_file_list()
|
|
92
|
+
iterator = tqdm(files, desc="Processing files", unit="file") if self.with_progress else files
|
|
93
|
+
|
|
94
|
+
for f in iterator:
|
|
95
|
+
if self._is_json(f):
|
|
96
|
+
self._process_file(f)
|
|
97
|
+
else:
|
|
98
|
+
log.debug(f"Skipping non-JSON file: {f.get('name')}")
|
|
99
|
+
|
|
100
|
+
manifest_path = self.presets_dir / "manifest.json"
|
|
101
|
+
manifest = GridPresetManifest(manifest_path)
|
|
102
|
+
manifest.scan(self.presets_dir)
|
|
103
|
+
|
|
104
|
+
def get_file_list(self) -> List[Dict]:
|
|
105
|
+
res = requests.get(self.url, headers=self.headers)
|
|
106
|
+
res.raise_for_status()
|
|
107
|
+
return res.json()
|
|
108
|
+
|
|
109
|
+
@staticmethod
|
|
110
|
+
def _is_json(file_info: Dict) -> bool:
|
|
111
|
+
"""
|
|
112
|
+
Upon receipt of file info, verify that it's for a JSON file (has the .json extension).
|
|
113
|
+
"""
|
|
114
|
+
return file_info.get('type') == 'file' and file_info.get('name', '').endswith('.json')
|
|
115
|
+
|
|
116
|
+
def _process_file(self, file_info: Dict):
|
|
117
|
+
name = file_info['name']
|
|
118
|
+
local_path = self.presets_dir / name
|
|
119
|
+
|
|
120
|
+
res = requests.get(file_info['download_url'])
|
|
121
|
+
res.raise_for_status()
|
|
122
|
+
content = res.content
|
|
123
|
+
|
|
124
|
+
actual_sha = github_blob_sha(content)
|
|
125
|
+
expected_sha = file_info['sha']
|
|
126
|
+
|
|
127
|
+
if actual_sha != expected_sha:
|
|
128
|
+
self.log.error(f"GitHub SHA mismatch for {name}")
|
|
129
|
+
raise ValueError(f"GitHub blob SHA mismatch for {name}")
|
|
130
|
+
|
|
131
|
+
self.save_file(local_path, content.decode('utf-8'), overwrite=True)
|
|
132
|
+
|
|
133
|
+
def _download_file(self, file_info: Dict, local_path: Path):
|
|
134
|
+
if self.with_progress:
|
|
135
|
+
self._download_with_progress(file_info, local_path)
|
|
136
|
+
else:
|
|
137
|
+
self._download_simple(file_info, local_path)
|
|
138
|
+
|
|
139
|
+
def _download_simple(self, file_info: Dict, local_path: Path):
|
|
140
|
+
res = requests.get(file_info['download_url'])
|
|
141
|
+
res.raise_for_status()
|
|
142
|
+
self.save_file(local_path, res.content.decode('utf-8'), overwrite=True)
|
|
143
|
+
|
|
144
|
+
def _download_with_progress(self, file_info: Dict, local_path: Path):
|
|
145
|
+
url = file_info['download_url']
|
|
146
|
+
res = requests.get(url, stream=True)
|
|
147
|
+
res.raise_for_status()
|
|
148
|
+
total = int(res.headers.get('content-length', 0))
|
|
149
|
+
bar = tqdm(total=total, unit='B', unit_scale=True, desc=f"Downloading {file_info['name']}", leave=False)
|
|
150
|
+
|
|
151
|
+
chunks = []
|
|
152
|
+
for chunk in res.iter_content(chunk_size=1024):
|
|
153
|
+
if chunk:
|
|
154
|
+
chunks.append(chunk)
|
|
155
|
+
bar.update(len(chunk))
|
|
156
|
+
bar.close()
|
|
157
|
+
|
|
158
|
+
content = b''.join(chunks).decode('utf-8')
|
|
159
|
+
self.save_file(local_path, content, overwrite=True)
|
|
160
|
+
|
|
161
|
+
def save_file(self, path: Path, data: str, overwrite: bool = False):
|
|
162
|
+
log = self.method_logger
|
|
163
|
+
path = provision_path(path)
|
|
164
|
+
if path.exists() and not overwrite:
|
|
165
|
+
log.warning(f"Skipping existing file {path}")
|
|
166
|
+
return
|
|
167
|
+
with open(path, 'w') as f:
|
|
168
|
+
f.write(data)
|
|
169
|
+
log.debug(f"Wrote file {path}")
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def main():
|
|
173
|
+
parser = argparse.ArgumentParser(description="Install JSON presets from GitHub")
|
|
174
|
+
parser.add_argument('--url', help="GitHub API URL for presets", default=REPO_PRESETS_URL)
|
|
175
|
+
parser.add_argument('--app-dir', help="Local directory to save presets", default=str(APP_DIRS.user_data_path))
|
|
176
|
+
parser.add_argument('--overwrite', help="Overwrite existing files", action='store_true')
|
|
177
|
+
parser.add_argument('--no-progress', help="Disable progress bars", action='store_false', dest='with_progress')
|
|
178
|
+
|
|
179
|
+
args = parser.parse_args()
|
|
180
|
+
|
|
181
|
+
installer = PresetInstaller(
|
|
182
|
+
url=args.url,
|
|
183
|
+
headers=REQ_HEADERS,
|
|
184
|
+
app_dir=args.app_dir,
|
|
185
|
+
overwrite_existing=args.overwrite,
|
|
186
|
+
with_progress=args.with_progress
|
|
187
|
+
)
|
|
188
|
+
installer.run()
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
if __name__ == '__main__':
|
|
192
|
+
main()
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
Author:
|
|
5
|
+
Inspyre Softworks
|
|
6
|
+
|
|
7
|
+
Project:
|
|
8
|
+
led-matrix-battery
|
|
9
|
+
|
|
10
|
+
File:
|
|
11
|
+
is_matrix_forge/led_matrix/commands/__init__.py
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
Description:
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
from typing import List, Optional, ByteString
|
|
19
|
+
|
|
20
|
+
import serial
|
|
21
|
+
from serial.tools.list_ports_common import ListPortInfo
|
|
22
|
+
|
|
23
|
+
from is_matrix_forge.led_matrix.constants import RESPONSE_SIZE, FWK_MAGIC
|
|
24
|
+
from is_matrix_forge.led_matrix.helpers import disconnect_dev
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def send_command_raw(dev: ListPortInfo, command: List[int], with_response: bool = False, response_size: Optional[int] = None) -> Optional[ByteString]:
|
|
28
|
+
"""
|
|
29
|
+
Send a command to the device using a new serial connection.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
dev (ListPortInfo): The device to send the command to.
|
|
33
|
+
command (List[int]): The command to send.
|
|
34
|
+
with_response (bool, optional): Whether to wait for a response from the device. Defaults to False.
|
|
35
|
+
response_size (Optional[int], optional): The size of the response to expect. Defaults to None.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Optional[ByteString]: The response from the device, if any, or None if no response or an error occurred.
|
|
39
|
+
|
|
40
|
+
Raises:
|
|
41
|
+
IOError, OSError: If there is an error communicating with the device.
|
|
42
|
+
"""
|
|
43
|
+
# print(f"Sending command: {command}")
|
|
44
|
+
res_size = response_size or RESPONSE_SIZE
|
|
45
|
+
try:
|
|
46
|
+
with serial.Serial(dev.device, 115200) as s:
|
|
47
|
+
s.write(command)
|
|
48
|
+
|
|
49
|
+
return s.read(res_size) if with_response else None
|
|
50
|
+
except (IOError, OSError) as _ex:
|
|
51
|
+
disconnect_dev(dev.device)
|
|
52
|
+
return None
|
|
53
|
+
# print("Error: ", ex)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def send_command(
|
|
57
|
+
dev: ListPortInfo,
|
|
58
|
+
command: int,
|
|
59
|
+
parameters: Optional[List[int]] = None,
|
|
60
|
+
with_response: bool = False
|
|
61
|
+
) -> Optional[ByteString]:
|
|
62
|
+
"""
|
|
63
|
+
Send a command to the device using a new serial connection.
|
|
64
|
+
|
|
65
|
+
Parameters:
|
|
66
|
+
dev (ListPortInfo):
|
|
67
|
+
The device to send the command to.
|
|
68
|
+
|
|
69
|
+
command (int):
|
|
70
|
+
The command to send.
|
|
71
|
+
|
|
72
|
+
parameters (Optional[List[int]], optional):
|
|
73
|
+
The parameters to send with the command. Defaults to None.
|
|
74
|
+
|
|
75
|
+
with_response (bool, optional):
|
|
76
|
+
Whether to wait for a response from the device. Defaults to False.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
Optional[ByteString]:
|
|
80
|
+
The response from the device, if any, or None if no response or an error occurred.
|
|
81
|
+
"""
|
|
82
|
+
if parameters is None:
|
|
83
|
+
parameters = []
|
|
84
|
+
return send_command_raw(dev, FWK_MAGIC + [command] + parameters, with_response)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
Author:
|
|
5
|
+
Inspyre Softworks
|
|
6
|
+
|
|
7
|
+
Project:
|
|
8
|
+
led-matrix-battery
|
|
9
|
+
|
|
10
|
+
File:
|
|
11
|
+
${DIR_PATH}/${FILE_NAME}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
Description:
|
|
15
|
+
$DESCRIPTION
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
from enum import IntEnum
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class CommandVals(IntEnum):
|
|
22
|
+
Brightness = 0x00
|
|
23
|
+
Pattern = 0x01
|
|
24
|
+
BootloaderReset = 0x02
|
|
25
|
+
Sleep = 0x03
|
|
26
|
+
Animate = 0x04
|
|
27
|
+
Panic = 0x05
|
|
28
|
+
Draw = 0x06
|
|
29
|
+
StageGreyCol = 0x07
|
|
30
|
+
DrawGreyColBuffer = 0x08
|
|
31
|
+
SetText = 0x09
|
|
32
|
+
StartGame = 0x10
|
|
33
|
+
GameControl = 0x11
|
|
34
|
+
GameStatus = 0x12
|
|
35
|
+
SetColor = 0x13
|
|
36
|
+
DisplayOn = 0x14
|
|
37
|
+
InvertScreen = 0x15
|
|
38
|
+
SetPixelColumn = 0x16
|
|
39
|
+
FlushFramebuffer = 0x17
|
|
40
|
+
ClearRam = 0x18
|
|
41
|
+
ScreenSaver = 0x19
|
|
42
|
+
SetFps = 0x1A
|
|
43
|
+
SetPowerMode = 0x1B
|
|
44
|
+
PwmFreq = 0x1E
|
|
45
|
+
DebugMode = 0x1F
|
|
46
|
+
Version = 0x20
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Constants for the LED Matrix Battery Monitor.
|
|
3
|
+
|
|
4
|
+
This module defines various constants used throughout the application, including:
|
|
5
|
+
- Serial communication settings (baudrate, response size)
|
|
6
|
+
- Hardware identifiers (magic numbers, product ID, vendor ID)
|
|
7
|
+
- Matrix dimensions (height, width)
|
|
8
|
+
- Grayscale conversion constants for different input sources
|
|
9
|
+
- Physical slot mapping for device locations
|
|
10
|
+
- Project URLs for external resources
|
|
11
|
+
"""
|
|
12
|
+
from is_matrix_forge.common.dirs import PRESETS_DIR
|
|
13
|
+
|
|
14
|
+
# Hardware identifiers
|
|
15
|
+
FWK_MAGIC = [0x32, 0xAC]
|
|
16
|
+
PID = 0x20
|
|
17
|
+
SN_PREFIX = 'FRAK'
|
|
18
|
+
VID = 0x32AC
|
|
19
|
+
|
|
20
|
+
# Serial configuration
|
|
21
|
+
DEFAULT_BAUDRATE = 115_200
|
|
22
|
+
RESPONSE_SIZE = 32
|
|
23
|
+
|
|
24
|
+
# Disconnected device placeholder
|
|
25
|
+
DISCONNECTED_DEVS = []
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# Matrix dimensions
|
|
29
|
+
HEIGHT = 34
|
|
30
|
+
WIDTH = 9
|
|
31
|
+
|
|
32
|
+
# Project URLs
|
|
33
|
+
PROJECT_URLS = {
|
|
34
|
+
'github_api': 'https://api.github.com/repos/Inspyre-Softworks/led-matrix-battery/contents'
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
GITHUB_REQ_HEADERS = {"Accept": "application/vnd.github.v3+json"}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# Physical slot mapping
|
|
41
|
+
SLOT_MAP = {
|
|
42
|
+
'1-3.2': {'abbrev': 'R1', 'side': 'right', 'slot': 1},
|
|
43
|
+
'1-3.3': {'abbrev': 'R2', 'side': 'right', 'slot': 2},
|
|
44
|
+
'1-4.2': {'abbrev': 'L1', 'side': 'left', 'slot': 1},
|
|
45
|
+
'1-4.3': {'abbrev': 'L2', 'side': 'left', 'slot': 2},
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
from cv2 import COLOR_BGR2GRAY, COLOR_RGB2GRAY
|
|
50
|
+
from is_matrix_forge.led_matrix.helpers.device import DEVICES
|
|
51
|
+
from is_matrix_forge.common.dirs import APP_DIRS
|
|
52
|
+
from is_matrix_forge.dev_tools.presets import MANIFEST_FILE_NAME
|
|
53
|
+
|
|
54
|
+
MANIFEST_FILE_PATH = PRESETS_DIR.joinpath(MANIFEST_FILE_NAME)
|
|
55
|
+
|
|
56
|
+
# Grayscale conversion constants
|
|
57
|
+
GRAYSCALE_CVT = {
|
|
58
|
+
'camera': COLOR_BGR2GRAY,
|
|
59
|
+
'video': COLOR_RGB2GRAY,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# Cleanup
|
|
64
|
+
del COLOR_BGR2GRAY, COLOR_RGB2GRAY
|
|
65
|
+
|
|
66
|
+
__all__ = [
|
|
67
|
+
'APP_DIRS',
|
|
68
|
+
'DEFAULT_BAUDRATE',
|
|
69
|
+
'DEVICES',
|
|
70
|
+
'DISCONNECTED_DEVS',
|
|
71
|
+
'FWK_MAGIC',
|
|
72
|
+
'GITHUB_REQ_HEADERS',
|
|
73
|
+
'GRAYSCALE_CVT',
|
|
74
|
+
'HEIGHT',
|
|
75
|
+
'PID',
|
|
76
|
+
'PROJECT_URLS',
|
|
77
|
+
'RESPONSE_SIZE',
|
|
78
|
+
'SN_PREFIX',
|
|
79
|
+
'SLOT_MAP',
|
|
80
|
+
'VID',
|
|
81
|
+
'WIDTH',
|
|
82
|
+
]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""
|
|
2
|
+
LED Matrix Controller Module.
|
|
3
|
+
|
|
4
|
+
This module provides the main controller class for interacting with LED matrix devices.
|
|
5
|
+
It handles device communication, animation control, pattern display, and other
|
|
6
|
+
operations related to the LED matrix hardware.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
# Standard library
|
|
12
|
+
from typing import Optional
|
|
13
|
+
|
|
14
|
+
# Third‑party
|
|
15
|
+
|
|
16
|
+
# Inspyre‑Softworks
|
|
17
|
+
|
|
18
|
+
from .multiton import MultitonMeta
|
|
19
|
+
from is_matrix_forge.led_matrix.constants import HEIGHT, WIDTH
|
|
20
|
+
|
|
21
|
+
from is_matrix_forge.led_matrix.display.grid.grid import Grid
|
|
22
|
+
from .helpers.threading import synchronized
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def generate_blank_grid(width: Optional[int] = None, height: Optional[int] = None) -> Grid:
|
|
26
|
+
return Grid.load_blank_grid(width=width or WIDTH, height=height or HEIGHT)
|