One ceiling, one slider, in the card that owns it
The current limit sat in the control card and in the settings card at once. Over the cloud those were not two settings that happen to agree: the "limit" command builds its frame from the same table entry the maxCurrentA setting does, so it was one wire field with two controls. The control card gives it up wherever a settings card can take it — which, now that the cloud has one, is both transports that read the charger. OCPP keeps its slider. A charging profile is not a setting the charger reports, so there is no settings card to move it to, and clearing a limit is OCPP's alone: the cloud sets a ceiling and has no message for "no ceiling". Taking the control away there would have left those modes unable to set a limit at all. It arrives in the settings card as the slider it was, not as the number box the table gave it. Slider rows stack — label and the value it is at on one line, the track beneath, the floor hint under that — because a ceiling is a thing you slide between two known ends rather than type. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
dde5410788
commit
e190364c77
@@ -602,7 +602,10 @@ const MQTT_SETTING_BLOCKS = [
|
||||
id: "charging",
|
||||
title: "blockCharging",
|
||||
fields: [
|
||||
{ key: "maxCurrentA", at: "settings.maxCurrentA", label: "maxCurrentSet", type: "number", min: LIMIT_FLOOR, max: null, step: 1, unit: "A" },
|
||||
// A slider rather than a box, like the control card had and the Modbus
|
||||
// settings card still has: it is the same value they set, and a ceiling
|
||||
// is a thing you slide between two known ends rather than type.
|
||||
{ key: "maxCurrentA", at: "settings.maxCurrentA", label: "maxCurrentSet", type: "slider", min: LIMIT_FLOOR, max: null, step: 1, unit: "A", hint: "limitFloorHint" },
|
||||
{ key: "autoStart", at: "settings.autoStart", label: "autoStart", type: "switch" },
|
||||
{ key: "randomDelay", at: "settings.randomDelay", label: "randomDelay", type: "switch" },
|
||||
{ key: "plugLock", at: "settings.plugLock", label: "plugLock", type: "switch" },
|
||||
@@ -2013,14 +2016,18 @@ onMounted(async () => {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- The limit, everywhere but the local path. There the settings card
|
||||
owns it: it is the charger's own ceiling register, read back and
|
||||
written, and the same slider in two cards was the same register
|
||||
twice. Neither OCPP nor the cloud has a settings card to move it to
|
||||
— a charging profile is not a setting the charger reports — so here
|
||||
it stays. Clearing it is OCPP's alone: the cloud sets a ceiling and
|
||||
has no message for "no ceiling". -->
|
||||
<div v-if="!ctlIsModbus" class="mt-3">
|
||||
<!-- The limit, only where nothing else owns it. Both transports that
|
||||
read the charger have a settings card now, and on both the limit is
|
||||
the charger's own ceiling — the same register over Modbus, the same
|
||||
wire field over the cloud, where "limit" and the maxCurrentA
|
||||
setting are built from one table. The same slider in two cards was
|
||||
that one value twice.
|
||||
|
||||
OCPP is the exception and keeps it: a charging profile is not a
|
||||
setting the charger reports, so there is no settings card to move
|
||||
it to. Clearing it is OCPP's alone too — the cloud sets a ceiling
|
||||
and has no message for "no ceiling". -->
|
||||
<div v-if="!ctlReadsDevice" class="mt-3">
|
||||
<label class="dh-label flex justify-between">
|
||||
<span>{{ t("charging.control.limit") }}</span><span class="data text-body">{{ limitAmps }} A</span>
|
||||
</label>
|
||||
@@ -2415,11 +2422,29 @@ onMounted(async () => {
|
||||
<section v-for="block in mqttSettingBlocks" :key="block.id" class="mt-2 rounded-control bg-sunken p-3">
|
||||
<h4 class="eyebrow">{{ t(`charging.modbus.${block.title}`) }}</h4>
|
||||
<div class="mt-2 flex flex-col gap-2">
|
||||
<div
|
||||
v-for="f in block.fields"
|
||||
:key="f.key || f.from"
|
||||
class="flex items-center justify-between gap-3"
|
||||
>
|
||||
<template v-for="f in block.fields" :key="f.key || f.from">
|
||||
<!-- A slider needs the width, so its row stacks: the label and
|
||||
the value it is at on one line, the track under them. -->
|
||||
<div v-if="f.type === 'slider'">
|
||||
<label class="dh-label flex justify-between" :for="`set-${f.key}`">
|
||||
<span>{{ t(`charging.modbus.${f.label}`) }}</span>
|
||||
<span class="data text-body">{{ mqttDraft[f.key] }} {{ f.unit }}</span>
|
||||
</label>
|
||||
<input
|
||||
:id="`set-${f.key}`"
|
||||
v-model.number="mqttDraft[f.key]"
|
||||
type="range"
|
||||
:min="f.min"
|
||||
:max="fieldMax(f)"
|
||||
:step="f.step"
|
||||
class="w-full accent-[var(--accent)]"
|
||||
/>
|
||||
<p v-if="f.hint" class="mt-1 text-[11px] text-muted">
|
||||
{{ t(`charging.modbus.${f.hint}`, { amps: f.min }) }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div v-else class="flex items-center justify-between gap-3">
|
||||
<label class="dh-label !mb-0 min-w-0 grow" :for="`set-${f.key || f.from}`">
|
||||
{{ t(`charging.modbus.${f.label}`) }}
|
||||
</label>
|
||||
@@ -2478,6 +2503,7 @@ onMounted(async () => {
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<p v-if="block.warning" class="mt-2 text-[11px]" style="color: var(--warning-600)">
|
||||
|
||||
Reference in New Issue
Block a user