Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions plugins.json
Original file line number Diff line number Diff line change
Expand Up @@ -507,10 +507,10 @@
"plugin_path": "plugins/mqtt-notifications",
"stars": 0,
"downloads": 0,
"last_updated": "2026-07-31",
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.1.1"
"latest_version": "1.2.0"
},
{
"id": "music",
Expand Down Expand Up @@ -975,10 +975,10 @@
"plugin_path": "plugins/youtube-stats",
"stars": 0,
"downloads": 0,
"last_updated": "2026-07-31",
"last_updated": "2026-09-02",
"verified": true,
"screenshot": "",
"latest_version": "1.1.1"
"latest_version": "1.2.0"
},
{
"id": "ledmatrix-elections",
Expand Down
38 changes: 29 additions & 9 deletions plugins/mqtt-notifications/config_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,16 @@
"items": {
"type": "string"
},
"default": ["homeassistant/ledmatrix/+"],
"default": [
"homeassistant/ledmatrix/+"
],
"description": "Array of MQTT topics to subscribe to. Supports wildcards: + (single level) and # (multi-level)"
}
},
"required": ["host", "port"],
"required": [
"host",
"port"
],
"additionalProperties": false
},
"display": {
Expand Down Expand Up @@ -115,7 +120,11 @@
},
"minItems": 3,
"maxItems": 3,
"default": [255, 255, 255],
"default": [
255,
255,
255
],
"description": "RGB text color [R, G, B]",
"x-advanced": true
},
Expand All @@ -128,7 +137,11 @@
},
"minItems": 3,
"maxItems": 3,
"default": [0, 0, 0],
"default": [
0,
0,
0
],
"description": "RGB background color [R, G, B]",
"x-advanced": true
},
Expand Down Expand Up @@ -174,8 +187,7 @@
"4x6-font.ttf",
"5by7.regular.ttf",
"5x7.bdf",
"4x6.bdf",
"cozette.bdf"
"4x6.bdf"
],
"default": "PressStart2P-Regular.ttf",
"x-advanced": true
Expand All @@ -190,14 +202,22 @@
"x-advanced": true
}
},
"x-propertyOrder": ["font", "font_size"],
"x-propertyOrder": [
"font",
"font_size"
],
"additionalProperties": false
}
},
"x-propertyOrder": ["message_text"],
"x-propertyOrder": [
"message_text"
],
"additionalProperties": false
}
},
"required": ["enabled", "mqtt"],
"required": [
"enabled",
"mqtt"
],
"additionalProperties": false
}
27 changes: 27 additions & 0 deletions plugins/mqtt-notifications/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,20 @@ def _load_font(self):
self.logger.error("Failed to load font %s: %s", font_path, e)
return ImageFont.load_default()

@staticmethod
def _bdf_pixel_size(path):
"""The pixel size a .bdf font declares, or None if it does not."""
try:
with open(path, "r", encoding="latin-1") as handle:
for line in handle:
if line.startswith("PIXEL_SIZE"):
return int(line.split()[1])
if line.startswith("CHARS"):
break # past the header
except (OSError, ValueError, IndexError):
return None
return None

def _load_element_font(self, element_cfg: Dict[str, Any]):
"""Resolve the message_text customization font, or None for the default.

Expand Down Expand Up @@ -213,6 +227,19 @@ def _load_element_font(self, element_cfg: Dict[str, Any]):
font = ImageFont.truetype(path, size)
break
except Exception as e:
# A .bdf is a bitmap face and exists at exactly one pixel
# size; FreeType rejects any other with "invalid pixel
# size". Asking for the configured size therefore failed
# for every bitmap face in the picker and fell back to the
# default, so choosing one appeared to do nothing. Retry at
# the size the file declares.
native = self._bdf_pixel_size(path)
if native is not None and native != size:
try:
font = ImageFont.truetype(path, native)
break
except Exception:
pass
self.logger.warning("Could not load font %s@%s: %s", name, size, e)
if font is None and not any(os.path.exists(p) for p in candidates):
self.logger.warning("Font file not found: %s; using default font", name)
Expand Down
10 changes: 8 additions & 2 deletions plugins/mqtt-notifications/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "mqtt-notifications",
"name": "MQTT Notifications",
"version": "1.1.1",
"version": "1.2.0",
"author": "ChuckBuilds",
"description": "Display text or images from HomeAssistant via MQTT. Supports dynamic MQTT topics with wildcard support for flexible notification handling that interrupts the normal display rotation.",
"category": "integration",
Expand All @@ -18,6 +18,12 @@
"entry_point": "manager.py",
"class_name": "MQTTNotificationsPlugin",
"versions": [
{
"version": "1.2.0",
"released": "2026-09-02",
"notes": "Load a bitmap font at its own pixel size, and drop one that has no font file. A .bdf exists at exactly one pixel size and FreeType rejects any other, so every .bdf in the font picker failed at the configured font_size and silently fell back to the default face -- choosing one appeared to do nothing. Bitmap faces are now retried at the size the file's PIXEL_SIZE header declares. cozette.bdf is removed from the picker: the file is shipped by neither the core nor the plugin, so it could only ever fall back. Same fix already landed for clock-simple, news and tide-display, which share this loader.",
"ledmatrix_min_version": "2.0.0"
},
{
"version": "1.1.1",
"released": "2026-08-15",
Expand Down Expand Up @@ -46,7 +52,7 @@
"ledmatrix_min_version": "2.0.0"
}
],
"last_updated": "2026-07-31",
"last_updated": "2026-09-02",
"stars": 0,
"downloads": 0,
"verified": true,
Expand Down
27 changes: 27 additions & 0 deletions plugins/youtube-stats/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,20 @@
else:
self.logger.info("YouTube Stats plugin disabled")

@staticmethod
def _bdf_pixel_size(path):
"""The pixel size a .bdf font declares, or None if it does not."""
try:
with open(path, "r", encoding="latin-1") as handle:
for line in handle:
if line.startswith("PIXEL_SIZE"):
return int(line.split()[1])
if line.startswith("CHARS"):
break # past the header
except (OSError, ValueError, IndexError):
return None
return None

def _load_element_font(self, element_cfg: Dict[str, Any]):
"""Resolve an element's configured font, or None for the default.

Expand Down Expand Up @@ -120,6 +134,19 @@
font = ImageFont.truetype(path, size)
break
except Exception as e:
# A .bdf is a bitmap face and exists at exactly one pixel
# size; FreeType rejects any other with "invalid pixel
# size". Asking for the configured size therefore failed
# for every bitmap face in the picker and fell back to the
# default, so choosing one appeared to do nothing. Retry at
# the size the file declares.
native = self._bdf_pixel_size(path)
if native is not None and native != size:
try:
font = ImageFont.truetype(path, native)
break
except Exception:

Check warning on line 148 in plugins/youtube-stats/manager.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

plugins/youtube-stats/manager.py#L148

Try, Except, Pass detected.
pass
self.logger.warning(f"Could not load font {name}@{size}: {e}")
if font is None and not any(os.path.exists(p) for p in candidates):
self.logger.warning(f"Font file not found: {name}; using default font")
Expand Down
10 changes: 8 additions & 2 deletions plugins/youtube-stats/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "youtube-stats",
"name": "YouTube Stats",
"version": "1.1.1",
"version": "1.2.0",
"author": "ChuckBuilds",
"description": "Display YouTube channel statistics including subscriber count, total views, and channel name on your LED matrix",
"category": "social",
Expand Down Expand Up @@ -33,6 +33,12 @@
}
],
"versions": [
{
"version": "1.2.0",
"released": "2026-09-02",
"ledmatrix_min_version": "2.0.0",
"notes": "Load a bitmap font at its own pixel size. A .bdf exists at exactly one pixel size and FreeType rejects any other, so every .bdf in the font picker failed at the configured font_size and silently fell back to the default face -- choosing one appeared to do nothing. Bitmap faces are now retried at the size the file's PIXEL_SIZE header declares. Same fix already landed for clock-simple, news and tide-display, which share this loader."
},
{
"version": "1.1.1",
"released": "2026-08-22",
Expand Down Expand Up @@ -61,7 +67,7 @@
"ledmatrix_min": "2.0.0"
}
],
"last_updated": "2026-07-31",
"last_updated": "2026-09-02",
"compatible_versions": [
">=2.0.0"
]
Expand Down
Loading