Skip to content

Commit 4dcff80

Browse files
author
haschtl
committed
add min notification brightness
1 parent 536fa70 commit 4dcff80

File tree

12 files changed

+99
-9
lines changed

12 files changed

+99
-9
lines changed

custom_components/quarzlampe/status_store.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ def float_or_none(key: str) -> float | None:
142142
"music_mode": kv.get("music_mode"),
143143
"music_mod": float_or_none("music_mod"),
144144
"music_kick_ms": float_or_none("music_kick_ms"),
145+
"notif_min": float_or_none("notif_min"),
145146
"music_env": float_or_none("music_env"),
146147
"music_level": float_or_none("music_level"),
147148
"music_smooth": float_or_none("music_smooth"),

frontend/src/cards/NotifyCard.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ type Props = {
1212
setNotifyFade: (v: number) => void;
1313
notifyRepeat: number;
1414
setNotifyRepeat: (v: number) => void;
15+
notifyMin: number;
16+
setNotifyMin: (v: number) => void;
1517
handleNotify: (seq: string, fade?: number, repeat?: number) => void;
1618
sendCmd: (cmd: string) => void;
1719
};
1820

19-
export function NotifyCard({ notifySeq, setNotifySeq, notifyFade, setNotifyFade, notifyRepeat, setNotifyRepeat, handleNotify, sendCmd }: Props) {
21+
export function NotifyCard({ notifySeq, setNotifySeq, notifyFade, setNotifyFade, notifyRepeat, setNotifyRepeat, notifyMin, setNotifyMin, handleNotify, sendCmd }: Props) {
2022
return (
2123
<Card>
2224
<CardHeader>
@@ -77,6 +79,26 @@ export function NotifyCard({ notifySeq, setNotifySeq, notifyFade, setNotifyFade,
7779
className="w-20"
7880
/>
7981
</div>
82+
<div>
83+
<Label className="m-0 text-muted">
84+
<Trans k="label.notifyMin">Notify min (%)</Trans>
85+
</Label>
86+
<Input
87+
type="number"
88+
min={0}
89+
max={100}
90+
step={1}
91+
value={notifyMin}
92+
onChange={(e) => setNotifyMin(Number(e.target.value))}
93+
onBlur={(e) => {
94+
const v = Math.min(100, Math.max(0, Number(e.target.value)));
95+
setNotifyMin(v);
96+
sendCmd(`notify min ${v.toFixed(1)}`);
97+
}}
98+
className="w-24"
99+
suffix="%"
100+
/>
101+
</div>
80102
</div>
81103
</div>
82104
<div className="flex items-end gap-2">

frontend/src/hooks/status.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ export type DeviceStatus = {
9595
musicEnv?: number;
9696
musicLevel?: number;
9797
musicKickMs?: number;
98+
notifyMin?: number;
9899
clapEnabled?: boolean;
99100
clapThreshold?: number;
100101
clapCooldownMs?: number;
@@ -148,6 +149,16 @@ export function parseStatusLine(line: string, setStatus: Dispatch<SetStateAction
148149
}));
149150
return true;
150151
}
152+
if (line.startsWith('[Brightness]')) {
153+
const match = line.match(/Brightness\]\s*([0-9.]+)/i);
154+
const val = match ? parseFloat(match[1]) : undefined;
155+
setStatus((s) => ({
156+
...s,
157+
brightness: Number.isFinite(val ?? NaN) ? val : s.brightness,
158+
lastStatusAt: Date.now(),
159+
}));
160+
return true;
161+
}
151162
if (line.startsWith('STATUS')) {
152163
const parts = line.split('|').slice(1);
153164
const kv: Record<string, string> = {};
@@ -176,6 +187,7 @@ export function parseStatusLine(line: string, setStatus: Dispatch<SetStateAction
176187
const outputMode = kv.out ? (kv.out.toLowerCase().startsWith('ana') ? 'analog' : 'pwm') : undefined;
177188
const hasMusic = kv.music ? isAvailable('music') : s.hasMusic;
178189
const hasPoti = kv.poti ? isAvailable('poti') : s.hasPoti;
190+
const notifyMin = kv.notif_min ? asNum('notif_min') : s.notifyMin;
179191
const potiVal = Object.prototype.hasOwnProperty.call(kv, 'poti_val') ? asNum('poti_val') : undefined;
180192
const potiRaw = Object.prototype.hasOwnProperty.call(kv, 'poti_raw') ? asInt('poti_raw') : undefined;
181193
const potiMin = Object.prototype.hasOwnProperty.call(kv, 'poti_min') ? asNum('poti_min') : undefined;
@@ -284,6 +296,7 @@ export function parseStatusLine(line: string, setStatus: Dispatch<SetStateAction
284296
musicMode: kv.music_mode ?? s.musicMode,
285297
musicMod: asNum('music_mod') ?? s.musicMod,
286298
musicKickMs: asNum('music_kick_ms') ?? s.musicKickMs,
299+
notifyMin,
287300
clapEnabled: kv.clap ? kv.clap.toUpperCase() === 'ON' : hasMusic === false ? false : s.clapEnabled,
288301
clapThreshold: asNum('clap_thr') ?? s.clapThreshold,
289302
clapCooldownMs: asInt('clap_cool') ?? s.clapCooldownMs,

frontend/src/i18n.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ const translations: Record<Lang, Record<string, string>> = {
111111
"label.values": "Values (0..1 CSV)",
112112
"label.step": "Step",
113113
"label.repeat": "Repeat",
114+
"label.notifyMin": "Min. Notify-Helligkeit (%)",
114115
"label.lightGain": "Light gain",
115116
"label.musicGain": "Music gain",
116117
"label.clapThr": "Clap thr",
@@ -365,6 +366,8 @@ const translations: Record<Lang, Record<string, string>> = {
365366
"filter.delayMix": "Mix",
366367
"filter.presets": "Presets",
367368
"label.repeat": "Wiederholen",
369+
"label.notifyMin": "Min. Notify-Helligkeit (%)",
370+
"label.notifyMin": "Notify min (%)",
368371
"label.lightGain": "Licht-Gain",
369372
"label.musicGain": "Musik-Gain",
370373
"label.clapThr": "Klatsch-Schwelle",

frontend/src/sections/ActionsSection.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useMemo, useState } from 'react';
1+
import { useEffect, useMemo, useState } from 'react';
22
import { MorseCard } from '@/cards/MorseCard';
33
import { NotifyCard } from '@/cards/NotifyCard';
44
import { WakeSleepCard } from '@/cards/WakeSleepCard';
@@ -10,6 +10,7 @@ export function ActionsSection() {
1010
const [notifySeq, setNotifySeq] = useState('80 40 80 120');
1111
const [notifyFade, setNotifyFade] = useState(0);
1212
const [notifyRepeat, setNotifyRepeat] = useState(1);
13+
const [notifyMin, setNotifyMin] = useState(10);
1314
const [wakeDuration, setWakeDuration] = useState(180);
1415
const [wakeMode, setWakeMode] = useState('');
1516
const [wakeBri, setWakeBri] = useState('');
@@ -43,6 +44,13 @@ export function ActionsSection() {
4344
sendCmd(cmd).catch((e) => console.warn(e));
4445
};
4546

47+
// Sync min notify brightness from status if available
48+
useEffect(() => {
49+
if (typeof status.notifyMin === 'number' && !Number.isNaN(status.notifyMin)) {
50+
setNotifyMin(status.notifyMin);
51+
}
52+
}, [status.notifyMin]);
53+
4654
const handleWake = () => {
4755
const parts = ['wake'];
4856
if (wakeSoft) parts.push('soft');
@@ -76,6 +84,8 @@ export function ActionsSection() {
7684
setNotifyFade={setNotifyFade}
7785
notifyRepeat={notifyRepeat}
7886
setNotifyRepeat={setNotifyRepeat}
87+
notifyMin={notifyMin}
88+
setNotifyMin={setNotifyMin}
7989
handleNotify={handleNotify}
8090
sendCmd={sendCmd}
8191
/>

include/notifications.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ extern bool notifyInvert;
1010
extern bool notifyRestoreLamp;
1111
extern bool notifyPrevLampOn;
1212
extern bool notifyActive;
13-
extern uint32_t notifyFadeMs;
13+
extern uint32_t notifyFadeMs;
14+
extern float notifyMinBrightness; // 0..1 floor for notify output

include/settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ constexpr float LIGHT_CLAMP_MIN_DEFAULT = 0.2f;
8080
constexpr float LIGHT_CLAMP_MAX_DEFAULT = 1.0f;
8181
constexpr float BRI_MIN_DEFAULT = 0.00f;
8282
constexpr float BRI_MAX_DEFAULT = 1.00f;
83+
constexpr float NOTIFY_MIN_BRI_DEFAULT = 0.10f; ///< Minimal brightness for notify pulses (0..1)
8384
constexpr uint32_t CUSTOM_STEP_MS_DEFAULT = 800;///< default step time for custom pattern
8485
// Require an incoming command before any feedback is printed/sent (set via -DREQUIRE_FEEDBACK_HANDSHAKE=1)
8586
#ifndef REQUIRE_FEEDBACK_HANDSHAKE

src/command.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,19 @@ void handleCommand(String line)
10141014
{
10151015
std::vector<uint32_t> seq;
10161016
notifyFadeMs = 0;
1017+
if (lower.startsWith("notify min"))
1018+
{
1019+
float v = line.substring(10).toFloat();
1020+
v = clamp01(v / 100.0f);
1021+
if (v < 0.0f)
1022+
v = 0.0f;
1023+
if (v > 1.0f)
1024+
v = 1.0f;
1025+
notifyMinBrightness = v;
1026+
saveSettings();
1027+
sendFeedback(String(F("[Notify] min_bri=")) + String(v * 100.0f, 1) + F("%"));
1028+
return;
1029+
}
10171030
String args = line.substring(6);
10181031
args.trim();
10191032
while (args.length() > 0)

src/main.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -247,10 +247,8 @@ void updatePatternEngine()
247247
adjusted = 1.0f;
248248
relative = adjusted;
249249
float combined = lampEnabled ? relative * masterBrightness * ambientScale * outputScale : 0.0f;
250-
#ifndef ENABLE_MUSIC_MODE
251-
if (musicEnabled)
252-
combined *= musicModScale;
253-
#endif
250+
251+
// Notifications: ignore pattern; use brightness+ambient only with a floor.
254252
if (notifyActive && !notifySeq.empty())
255253
{
256254
uint32_t dtStage = now - notifyStageStartMs;
@@ -279,6 +277,12 @@ void updatePatternEngine()
279277
}
280278
if (notifyActive)
281279
{
280+
// Start from brightness * ambient, with a minimum brightness to stay visible.
281+
float base = masterBrightness;
282+
if (base < notifyMinBrightness)
283+
base = notifyMinBrightness;
284+
base *= ambientScale;
285+
282286
bool onPhase = (notifyIdx % 2 == 0);
283287
float scale = notifyInvert ? (onPhase ? 0.0f : 1.0f) : (onPhase ? 1.0f : 0.0f);
284288
if (notifyFadeMs > 0)
@@ -299,9 +303,14 @@ void updatePatternEngine()
299303
else
300304
scale = onPhase ? s : (1.0f - s);
301305
}
302-
combined *= scale;
306+
combined = base * scale;
303307
}
304308
}
309+
310+
#ifndef ENABLE_MUSIC_MODE
311+
if (musicEnabled && !notifyActive)
312+
combined *= musicModScale;
313+
#endif
305314
if (patternFadeEnabled)
306315
{
307316
if (patternFilterLastMs == 0)

src/notifications.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

22
#include "Arduino.h"
3+
#include "settings.h"
34
#include <vector>
45

56
// Notify blink
@@ -10,4 +11,5 @@ bool notifyInvert = false;
1011
bool notifyRestoreLamp = false;
1112
bool notifyPrevLampOn = false;
1213
bool notifyActive = false;
13-
uint32_t notifyFadeMs = 0;
14+
uint32_t notifyFadeMs = 0;
15+
float notifyMinBrightness = Settings::NOTIFY_MIN_BRI_DEFAULT;

0 commit comments

Comments
 (0)