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.
Files changed (123) hide show
  1. is_matrix_forge/__init__.py +8 -0
  2. is_matrix_forge/assets/__init__.py +8 -0
  3. is_matrix_forge/assets/audio/__init__.py +36 -0
  4. is_matrix_forge/assets/audio/files/__init__.py +53 -0
  5. is_matrix_forge/assets/audio/files/plugged.wav +0 -0
  6. is_matrix_forge/assets/audio/files/unplugged.wav +0 -0
  7. is_matrix_forge/assets/char_map.json +2150 -0
  8. is_matrix_forge/assets/font_map.py +119 -0
  9. is_matrix_forge/common/__init__.py +0 -0
  10. is_matrix_forge/common/decorators/__init__.py +152 -0
  11. is_matrix_forge/common/dirs.py +20 -0
  12. is_matrix_forge/common/helpers/__init__.py +132 -0
  13. is_matrix_forge/common/helpers/github_api.py +67 -0
  14. is_matrix_forge/designer_gui/__init__.py +8 -0
  15. is_matrix_forge/designer_gui/main_window/__init__.py +252 -0
  16. is_matrix_forge/designer_gui/main_window/layout.py +117 -0
  17. is_matrix_forge/dev_tools/__init__.py +8 -0
  18. is_matrix_forge/dev_tools/debug.py +82 -0
  19. is_matrix_forge/dev_tools/presets.py +47 -0
  20. is_matrix_forge/inputmodule/__init__.py +164 -0
  21. is_matrix_forge/inputmodule/b1display.py +160 -0
  22. is_matrix_forge/inputmodule/c1minimal.py +35 -0
  23. is_matrix_forge/inputmodule/font.py +2166 -0
  24. is_matrix_forge/inputmodule/helpers/__init__.py +16 -0
  25. is_matrix_forge/inputmodule/ledmatrix.py +516 -0
  26. is_matrix_forge/led_matrix/Scripts/__init__.py +4 -0
  27. is_matrix_forge/led_matrix/Scripts/battery_monitor.py +152 -0
  28. is_matrix_forge/led_matrix/Scripts/install_presets/__init__.py +2 -0
  29. is_matrix_forge/led_matrix/Scripts/install_presets/arguments.py +84 -0
  30. is_matrix_forge/led_matrix/Scripts/install_presets/main.py +192 -0
  31. is_matrix_forge/led_matrix/__init__.py +7 -0
  32. is_matrix_forge/led_matrix/commands/__init__.py +84 -0
  33. is_matrix_forge/led_matrix/commands/map.py +46 -0
  34. is_matrix_forge/led_matrix/constants.py +82 -0
  35. is_matrix_forge/led_matrix/controller/__init__.py +26 -0
  36. is_matrix_forge/led_matrix/controller/controller.py +635 -0
  37. is_matrix_forge/led_matrix/controller/helpers/__init__.py +7 -0
  38. is_matrix_forge/led_matrix/controller/helpers/threading.py +41 -0
  39. is_matrix_forge/led_matrix/controller/multiton.py +32 -0
  40. is_matrix_forge/led_matrix/controller/threaded.py +72 -0
  41. is_matrix_forge/led_matrix/display/__init__.py +13 -0
  42. is_matrix_forge/led_matrix/display/animations/__init__.py +29 -0
  43. is_matrix_forge/led_matrix/display/animations/animation.py +593 -0
  44. is_matrix_forge/led_matrix/display/animations/effects/__init__.py +17 -0
  45. is_matrix_forge/led_matrix/display/animations/errors.py +23 -0
  46. is_matrix_forge/led_matrix/display/animations/font/__init__.py +17 -0
  47. is_matrix_forge/led_matrix/display/animations/font/font.py +4 -0
  48. is_matrix_forge/led_matrix/display/animations/font/map_builder.py +123 -0
  49. is_matrix_forge/led_matrix/display/animations/frame/__init__.py +47 -0
  50. is_matrix_forge/led_matrix/display/animations/frame/base.py +245 -0
  51. is_matrix_forge/led_matrix/display/animations/frame/helpers.py +67 -0
  52. is_matrix_forge/led_matrix/display/animations/keep_awake.py +1 -0
  53. is_matrix_forge/led_matrix/display/animations/plugged.py +0 -0
  54. is_matrix_forge/led_matrix/display/animations/text_scroller.py +104 -0
  55. is_matrix_forge/led_matrix/display/effects/__init__.py +17 -0
  56. is_matrix_forge/led_matrix/display/effects/breather.py +206 -0
  57. is_matrix_forge/led_matrix/display/effects/fade.py +0 -0
  58. is_matrix_forge/led_matrix/display/effects/scroller/__init__.py +92 -0
  59. is_matrix_forge/led_matrix/display/effects/scroller/base.py +76 -0
  60. is_matrix_forge/led_matrix/display/effects/scroller/helpers.py +62 -0
  61. is_matrix_forge/led_matrix/display/grid/__init__.py +9 -0
  62. is_matrix_forge/led_matrix/display/grid/grid.py +208 -0
  63. is_matrix_forge/led_matrix/display/grid/helpers.py +130 -0
  64. is_matrix_forge/led_matrix/display/grid/presets/__init__.py +64 -0
  65. is_matrix_forge/led_matrix/display/grid/presets/manifest.py +172 -0
  66. is_matrix_forge/led_matrix/display/helpers/__init__.py +110 -0
  67. is_matrix_forge/led_matrix/display/helpers/columns.py +33 -0
  68. is_matrix_forge/led_matrix/display/media.py +199 -0
  69. is_matrix_forge/led_matrix/display/patterns/__init__.py +59 -0
  70. is_matrix_forge/led_matrix/display/patterns/built_in/__init__.py +91 -0
  71. is_matrix_forge/led_matrix/display/patterns/built_in/commands.py +3 -0
  72. is_matrix_forge/led_matrix/display/patterns/built_in/constants.py +29 -0
  73. is_matrix_forge/led_matrix/display/patterns/built_in/stencils.py +70 -0
  74. is_matrix_forge/led_matrix/display/patterns/utils.py +2 -0
  75. is_matrix_forge/led_matrix/display/text/__init__.py +66 -0
  76. is_matrix_forge/led_matrix/display/text/scroller.py +136 -0
  77. is_matrix_forge/led_matrix/errors/__init__.py +4 -0
  78. is_matrix_forge/led_matrix/errors/base.py +14 -0
  79. is_matrix_forge/led_matrix/errors/grid.py +37 -0
  80. is_matrix_forge/led_matrix/errors/matrix.py +68 -0
  81. is_matrix_forge/led_matrix/errors/misc.py +36 -0
  82. is_matrix_forge/led_matrix/fonts.py +20 -0
  83. is_matrix_forge/led_matrix/hardware.py +172 -0
  84. is_matrix_forge/led_matrix/helpers/__init__.py +165 -0
  85. is_matrix_forge/led_matrix/helpers/core/__init__.py +17 -0
  86. is_matrix_forge/led_matrix/helpers/core/lazy_mod_load.py +84 -0
  87. is_matrix_forge/led_matrix/helpers/device.py +118 -0
  88. is_matrix_forge/led_matrix/helpers/status_handler.py +14 -0
  89. is_matrix_forge/led_matrix/helpers/stream/__init__.py +70 -0
  90. is_matrix_forge/led_matrix/helpers/stream/errors.py +17 -0
  91. is_matrix_forge/led_matrix/led_matrix.py +25 -0
  92. is_matrix_forge/led_matrix/status.py +8 -0
  93. is_matrix_forge/led_matrix/tools/__init__.py +8 -0
  94. is_matrix_forge/led_matrix/tools/identify.py +27 -0
  95. is_matrix_forge/led_matrix/utils/__init__.py +41 -0
  96. is_matrix_forge/log_engine.py +25 -0
  97. is_matrix_forge/monitor/__init__.py +68 -0
  98. is_matrix_forge/monitor/errors.py +35 -0
  99. is_matrix_forge/monitor/events.py +78 -0
  100. is_matrix_forge/monitor/gui/__init__.py +0 -0
  101. is_matrix_forge/monitor/gui/errors.py +35 -0
  102. is_matrix_forge/monitor/gui/event/__init__.py +8 -0
  103. is_matrix_forge/monitor/gui/event/collection.py +153 -0
  104. is_matrix_forge/monitor/gui/event/errors.py +58 -0
  105. is_matrix_forge/monitor/gui/event/event.py +226 -0
  106. is_matrix_forge/monitor/gui/layout/__init__.py +8 -0
  107. is_matrix_forge/monitor/gui/layout/base.py +147 -0
  108. is_matrix_forge/monitor/gui/metaclasses/__init__.py +20 -0
  109. is_matrix_forge/monitor/gui/windows/__init__.py +0 -0
  110. is_matrix_forge/monitor/gui/windows/base.py +325 -0
  111. is_matrix_forge/monitor/gui/windows/main/__init__.py +77 -0
  112. is_matrix_forge/monitor/gui/windows/main/layout.py +21 -0
  113. is_matrix_forge/monitor/helpers.py +55 -0
  114. is_matrix_forge/monitor/monitor.py +431 -0
  115. is_matrix_forge/notify/__init__.py +0 -0
  116. is_matrix_forge/notify/sounds/__init__.py +6 -0
  117. is_matrix_forge/notify/sounds/base.py +106 -0
  118. is_matrix_forge/progress.py +99 -0
  119. is_matrix_forge-1.0.0.dev1.dist-info/LICENSE.md +19 -0
  120. is_matrix_forge-1.0.0.dev1.dist-info/METADATA +190 -0
  121. is_matrix_forge-1.0.0.dev1.dist-info/RECORD +123 -0
  122. is_matrix_forge-1.0.0.dev1.dist-info/WHEEL +4 -0
  123. 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,7 @@
1
+
2
+
3
+ def get_controllers():
4
+ from is_matrix_forge.led_matrix.controller.controller import LEDMatrixController
5
+ from is_matrix_forge.led_matrix.constants import DEVICES
6
+
7
+ return [LEDMatrixController(device, 100) for device in DEVICES]
@@ -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)