SMA: remove remote control (BC) (#23906)
This commit is contained in:
parent
16f4681429
commit
148aa76b67
28 changed files with 35 additions and 254 deletions
|
|
@ -92,7 +92,6 @@ export default {
|
|||
case "singlePhase":
|
||||
case "enabled":
|
||||
case "configured":
|
||||
case "allowControl":
|
||||
return value
|
||||
? this.$t("config.deviceValue.yes")
|
||||
: this.$t("config.deviceValue.no");
|
||||
|
|
|
|||
|
|
@ -10,19 +10,6 @@
|
|||
@changed="$emit('changed')"
|
||||
>
|
||||
<template #default="{ values }">
|
||||
<FormRow id="shmControl" :label="$t('config.shm.labelControl')" optional>
|
||||
<div class="d-flex">
|
||||
<input
|
||||
id="shmControl"
|
||||
v-model="values.allowControl"
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<label class="form-check-label ms-2" for="shmControl">
|
||||
{{ $t("config.shm.labelAllowControl") }}
|
||||
</label>
|
||||
</div>
|
||||
</FormRow>
|
||||
<PropertyCollapsible>
|
||||
<template #advanced>
|
||||
<p>{{ $t("config.shm.descriptionIds") }}</p>
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ export interface HemsConfig {
|
|||
}
|
||||
|
||||
export interface ShmConfig {
|
||||
allowControl: boolean;
|
||||
vendorId: string;
|
||||
deviceId: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -638,8 +638,7 @@ export default defineComponent({
|
|||
return this.vehicles.map((v) => ({ key: v.name, name: v.config?.title || v.name }));
|
||||
},
|
||||
shmTags() {
|
||||
const { allowControl } = store.state?.shm || {};
|
||||
return { allowControl: { value: allowControl || false } };
|
||||
return { configured: { value: true } };
|
||||
},
|
||||
hemsTags() {
|
||||
const { type } = store.state?.hems || {};
|
||||
|
|
|
|||
|
|
@ -152,14 +152,13 @@ type Loadpoint struct {
|
|||
planActive bool // charge plan exists and has a currently active slot
|
||||
|
||||
// cached state
|
||||
status api.ChargeStatus // Charger status
|
||||
remoteDemand loadpoint.RemoteDemand // External status demand
|
||||
chargePower float64 // Charging power
|
||||
chargeCurrents []float64 // Phase currents
|
||||
connectedTime time.Time // Time when vehicle was connected
|
||||
pvTimer time.Time // PV enabled/disable timer
|
||||
phaseTimer time.Time // 1p3p switch timer
|
||||
wakeUpTimer *Timer // Vehicle wake-up timeout
|
||||
status api.ChargeStatus // Charger status
|
||||
chargePower float64 // Charging power
|
||||
chargeCurrents []float64 // Phase currents
|
||||
connectedTime time.Time // Time when vehicle was connected
|
||||
pvTimer time.Time // PV enabled/disable timer
|
||||
phaseTimer time.Time // 1p3p switch timer
|
||||
wakeUpTimer *Timer // Vehicle wake-up timeout
|
||||
|
||||
// charge progress
|
||||
vehicleSoc float64 // Vehicle or charger soc
|
||||
|
|
@ -1045,14 +1044,6 @@ func (lp *Loadpoint) disableUnlessClimater() error {
|
|||
return lp.setLimit(current)
|
||||
}
|
||||
|
||||
// remoteControlled returns true if remote control status is active
|
||||
func (lp *Loadpoint) remoteControlled(demand loadpoint.RemoteDemand) bool {
|
||||
lp.Lock()
|
||||
defer lp.Unlock()
|
||||
|
||||
return lp.remoteDemand == demand
|
||||
}
|
||||
|
||||
// statusEvents converts the observed charger status change into a logical sequence of events
|
||||
func statusEvents(prevStatus, status api.ChargeStatus) []string {
|
||||
res := make([]string, 0, 2)
|
||||
|
|
@ -1914,9 +1905,6 @@ func (lp *Loadpoint) Update(sitePower, batteryBoostPower float64, consumption, f
|
|||
return
|
||||
}
|
||||
|
||||
// track if remote disabled is actually active
|
||||
remoteDisabled := loadpoint.RemoteEnable
|
||||
|
||||
mode := lp.GetMode()
|
||||
lp.publish(keys.Mode, mode)
|
||||
|
||||
|
|
@ -1933,10 +1921,6 @@ func (lp *Loadpoint) Update(sitePower, batteryBoostPower float64, consumption, f
|
|||
case lp.scalePhasesRequired():
|
||||
err = lp.scalePhases(lp.phasesConfigured)
|
||||
|
||||
case lp.remoteControlled(loadpoint.RemoteHardDisable):
|
||||
remoteDisabled = loadpoint.RemoteHardDisable
|
||||
fallthrough
|
||||
|
||||
case mode == api.ModeOff:
|
||||
var current float64
|
||||
if welcomeCharge {
|
||||
|
|
@ -2000,12 +1984,6 @@ func (lp *Loadpoint) Update(sitePower, batteryBoostPower float64, consumption, f
|
|||
lp.resetPVTimer()
|
||||
}
|
||||
|
||||
// Sunny Home Manager
|
||||
if lp.remoteControlled(loadpoint.RemoteSoftDisable) {
|
||||
remoteDisabled = loadpoint.RemoteSoftDisable
|
||||
targetCurrent = 0
|
||||
}
|
||||
|
||||
err = lp.setLimit(targetCurrent)
|
||||
}
|
||||
|
||||
|
|
@ -2022,9 +2000,10 @@ func (lp *Loadpoint) Update(sitePower, batteryBoostPower float64, consumption, f
|
|||
}
|
||||
|
||||
// effective disabled status
|
||||
if remoteDisabled != loadpoint.RemoteEnable {
|
||||
lp.publish(keys.RemoteDisabled, remoteDisabled)
|
||||
}
|
||||
// TODO use for §14a
|
||||
// if remoteDisabled != loadpoint.RemoteEnable {
|
||||
// lp.publish(keys.RemoteDisabled, remoteDisabled)
|
||||
// }
|
||||
|
||||
// log any error
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -162,9 +162,6 @@ type API interface {
|
|||
// SetBatteryBoost sets the battery boost
|
||||
SetBatteryBoost(enable bool) error
|
||||
|
||||
// RemoteControl sets remote status demand
|
||||
RemoteControl(string, RemoteDemand)
|
||||
|
||||
//
|
||||
// smart grid charging
|
||||
//
|
||||
|
|
|
|||
|
|
@ -700,18 +700,6 @@ func (mr *MockAPIMockRecorder) PublishEffectiveValues() *gomock.Call {
|
|||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublishEffectiveValues", reflect.TypeOf((*MockAPI)(nil).PublishEffectiveValues))
|
||||
}
|
||||
|
||||
// RemoteControl mocks base method.
|
||||
func (m *MockAPI) RemoteControl(arg0 string, arg1 RemoteDemand) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "RemoteControl", arg0, arg1)
|
||||
}
|
||||
|
||||
// RemoteControl indicates an expected call of RemoteControl.
|
||||
func (mr *MockAPIMockRecorder) RemoteControl(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoteControl", reflect.TypeOf((*MockAPI)(nil).RemoteControl), arg0, arg1)
|
||||
}
|
||||
|
||||
// SetBatteryBoost mocks base method.
|
||||
func (m *MockAPI) SetBatteryBoost(enable bool) error {
|
||||
m.ctrl.T.Helper()
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
package loadpoint
|
||||
|
||||
import "strings"
|
||||
|
||||
// RemoteDemand defines external status demand
|
||||
type RemoteDemand string
|
||||
|
||||
// remote status demand definition
|
||||
const (
|
||||
RemoteEnable RemoteDemand = ""
|
||||
RemoteHardDisable RemoteDemand = "hard"
|
||||
RemoteSoftDisable RemoteDemand = "soft"
|
||||
)
|
||||
|
||||
// RemoteDemandString converts string to RemoteDemand
|
||||
func RemoteDemandString(demand string) (RemoteDemand, error) {
|
||||
switch strings.ToLower(demand) {
|
||||
case string(RemoteHardDisable):
|
||||
return RemoteHardDisable, nil
|
||||
case string(RemoteSoftDisable):
|
||||
return RemoteSoftDisable, nil
|
||||
default:
|
||||
return RemoteEnable, nil
|
||||
}
|
||||
}
|
||||
|
|
@ -578,24 +578,6 @@ func (lp *Loadpoint) SetBatteryBoost(enable bool) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// RemoteControl sets remote status demand
|
||||
func (lp *Loadpoint) RemoteControl(source string, demand loadpoint.RemoteDemand) {
|
||||
lp.Lock()
|
||||
defer lp.Unlock()
|
||||
|
||||
lp.log.DEBUG.Println("remote demand:", demand)
|
||||
|
||||
// apply immediately
|
||||
if lp.remoteDemand != demand {
|
||||
lp.remoteDemand = demand
|
||||
|
||||
lp.publish(keys.RemoteDisabled, demand)
|
||||
lp.publish(keys.RemoteDisabledSource, source)
|
||||
|
||||
lp.requestUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
// HasChargeMeter determines if a physical charge meter is attached
|
||||
func (lp *Loadpoint) HasChargeMeter() bool {
|
||||
_, isWrapped := lp.chargeMeter.(*wrapper.ChargeMeter)
|
||||
|
|
|
|||
|
|
@ -37,20 +37,19 @@ var serverName = "EVCC SEMP Server " + util.Version
|
|||
|
||||
// SEMP is the SMA SEMP server
|
||||
type SEMP struct {
|
||||
log *util.Logger
|
||||
controllable bool
|
||||
vid string
|
||||
did []byte
|
||||
uid string
|
||||
hostURI string
|
||||
port int
|
||||
site site.API
|
||||
log *util.Logger
|
||||
vid string
|
||||
did []byte
|
||||
uid string
|
||||
hostURI string
|
||||
port int
|
||||
site site.API
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
AllowControl bool `json:"allowControl"`
|
||||
VendorId string `json:"vendorId"`
|
||||
DeviceId string `json:"deviceId"`
|
||||
AllowControl_ bool `json:"allowControl,omitempty"` // deprecated
|
||||
VendorId string `json:"vendorId"`
|
||||
DeviceId string `json:"deviceId"`
|
||||
}
|
||||
|
||||
// NewFromConfig creates a new SEMP instance from configuration and starts it
|
||||
|
|
@ -83,12 +82,11 @@ func NewFromConfig(cfg Config, site site.API, addr string, router *mux.Router) e
|
|||
}
|
||||
|
||||
s := &SEMP{
|
||||
log: util.NewLogger("semp"),
|
||||
site: site,
|
||||
uid: uid.String(),
|
||||
vid: vendorId,
|
||||
did: did,
|
||||
controllable: cfg.AllowControl,
|
||||
log: util.NewLogger("semp"),
|
||||
site: site,
|
||||
uid: uid.String(),
|
||||
vid: vendorId,
|
||||
did: did,
|
||||
}
|
||||
|
||||
// find external port
|
||||
|
|
@ -368,19 +366,15 @@ func (s *SEMP) deviceStatus(id int, lp loadpoint.API) DeviceStatus {
|
|||
chargePower := lp.GetChargePower()
|
||||
|
||||
status := lp.GetStatus()
|
||||
mode := lp.GetMode()
|
||||
isPV := mode == api.ModeMinPV || mode == api.ModePV
|
||||
|
||||
deviceStatus := StatusOff
|
||||
if status == api.StatusC {
|
||||
deviceStatus = StatusOn
|
||||
}
|
||||
|
||||
connected := status == api.StatusB || status == api.StatusC
|
||||
|
||||
res := DeviceStatus{
|
||||
DeviceID: s.deviceID(id),
|
||||
EMSignalsAccepted: s.controllable && isPV && connected,
|
||||
EMSignalsAccepted: false,
|
||||
PowerInfo: PowerInfo{
|
||||
AveragePower: int(chargePower),
|
||||
AveragingInterval: 60,
|
||||
|
|
@ -461,41 +455,12 @@ func (s *SEMP) allPlanningRequest() (res []PlanningRequest) {
|
|||
func (s *SEMP) deviceControlHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var msg EM2Device
|
||||
|
||||
err := xml.NewDecoder(r.Body).Decode(&msg)
|
||||
s.log.TRACE.Printf("recv: %+v", msg)
|
||||
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
if err := xml.NewDecoder(r.Body).Decode(&msg); err == nil {
|
||||
s.log.TRACE.Printf("recv: %+v", msg)
|
||||
} else {
|
||||
s.log.ERROR.Printf("recv: %+v", msg)
|
||||
}
|
||||
|
||||
for _, dev := range msg.DeviceControl {
|
||||
did := dev.DeviceID
|
||||
|
||||
for id, lp := range s.site.Loadpoints() {
|
||||
if did != s.deviceID(id) {
|
||||
continue
|
||||
}
|
||||
|
||||
if mode := lp.GetMode(); mode != api.ModeMinPV && mode != api.ModePV {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// ignore requests if not controllable
|
||||
if !s.controllable {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
demand := loadpoint.RemoteSoftDisable
|
||||
if dev.On {
|
||||
demand = loadpoint.RemoteEnable
|
||||
}
|
||||
|
||||
lp.RemoteControl(sempController, demand)
|
||||
}
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
// ignore control requests
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@
|
|||
"title": "Поведение на управление"
|
||||
},
|
||||
"deviceValue": {
|
||||
"allowControl": "Разреши контрол",
|
||||
"amount": "Количество",
|
||||
"broker": "Брокер",
|
||||
"bucket": "Кофа",
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@
|
|||
"title": "Chování systému"
|
||||
},
|
||||
"deviceValue": {
|
||||
"allowControl": "Povolit ovládání",
|
||||
"amount": "Množství",
|
||||
"broker": "Broker",
|
||||
"bucket": "Úložiště (bucket)",
|
||||
|
|
@ -440,8 +439,6 @@
|
|||
"descriptionIds": "V Sunny Portálu každé zařízení potřebuje unikátní identifikátor. EVCC generuje tento identifikátor v závisosti na vašem HW. Pokud zmigrujete EVCC na jiný HW mohou se tyto identifikátory změnit. Pokud chcete uchovat statistiky můžete zde přepsat generované identifikátory. Otevřete SEMP URL (/semp) abyste zkontrolovali současné identifikátory.",
|
||||
"descriptionSempUrl": "SEMP URL",
|
||||
"descriptionVendorId": "8 znaků HEX string. Obecné předpony všech entit. Ve výchozím stavu EVCC použije vlastní interní ID.",
|
||||
"labelAllowControl": "Povolit dodatečné limity výkonu doporučené SHM.",
|
||||
"labelControl": "Povolit ovládání",
|
||||
"labelDeviceId": "ID zařízení",
|
||||
"labelVendorId": "ID výrobce",
|
||||
"title": "SMA Sunny Home Manager"
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@
|
|||
"title": "kontrol adfærd"
|
||||
},
|
||||
"deviceValue": {
|
||||
"allowControl": "Tillad kontrol",
|
||||
"amount": "Mængde",
|
||||
"broker": "Broker",
|
||||
"bucket": "Bucket",
|
||||
|
|
@ -447,8 +446,6 @@
|
|||
"descriptionIds": "I Sunny Portal skal hver forbrugsenhed have en unik identifikator. evcc genererer en unik identifikator baseret på din hardware. Hvis du flytter evcc til en anden hardware, kan disse identifikatorer ændre sig. Hvis du vil bevare historikken, kan du tilsidesætte de genererede identifikatorer her. Åbn SEMP-URL’en (/semp) for at tjekke dine nuværende identifikatorer.",
|
||||
"descriptionSempUrl": "SEMP URL",
|
||||
"descriptionVendorId": "8-tegns HEX-streng. Generelt præfiks for alle enheder. Som standard vil evcc bruge sit eget interne leverandør-ID.",
|
||||
"labelAllowControl": "Accepter yderligere anbefalinger om effektgrænser fra SHM.",
|
||||
"labelControl": "Tillad kontrol",
|
||||
"labelDeviceId": "Enheds ID",
|
||||
"labelVendorId": "Leverandør-ID",
|
||||
"title": "SMA Sunny Home Manager"
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@
|
|||
"title": "Regelverhalten"
|
||||
},
|
||||
"deviceValue": {
|
||||
"allowControl": "Steuerung erlauben",
|
||||
"amount": "Anzahl",
|
||||
"broker": "Broker",
|
||||
"bucket": "Bucket",
|
||||
|
|
@ -447,8 +446,6 @@
|
|||
"descriptionIds": "Im Sunny Portal benötigt jeder Verbraucher (Ladepunkt, ..) eine eindeutige Kennung. evcc generiert basierend auf deiner Hardware eine eindeutige Kennung. Wenn du evcc auf andere Hardware migrierst, kann sich diese Kennung ändern. Um die Historie zu erhalten, kannst du die generierten Kennungen hier überschreiben. Öffne die SEMP-URL (/semp), um deine aktuellen Kennungen zu überprüfen.",
|
||||
"descriptionSempUrl": "SEMP-URL",
|
||||
"descriptionVendorId": "8-stelliger HEX-String. Allgemeines Präfix aller Entitäten. Standardmäßig verwendet evcc seine eigene interne Hersteller-ID.",
|
||||
"labelAllowControl": "Zusätzlich Leistungsbegrenzungsempfehlungen vom SHM akzeptieren.",
|
||||
"labelControl": "Steuerung erlauben",
|
||||
"labelDeviceId": "Geräte-ID",
|
||||
"labelVendorId": "Hersteller-ID",
|
||||
"title": "SMA Sunny Home Manager"
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@
|
|||
"title": "Control behavior"
|
||||
},
|
||||
"deviceValue": {
|
||||
"allowControl": "Allow control",
|
||||
"amount": "Amount",
|
||||
"broker": "Broker",
|
||||
"bucket": "Bucket",
|
||||
|
|
@ -447,8 +446,6 @@
|
|||
"descriptionIds": "In Sunny Portal every consumer device needs a unique identifier. evcc generates a unique identifier based on your hardware. If you migrate evcc to another hardware these identifiers might change. If you want to maintain history you can override the generated identifiers here. Open the SEMP URL (/semp) to check your current identifiers.",
|
||||
"descriptionSempUrl": "SEMP URL",
|
||||
"descriptionVendorId": "8 characters HEX string. General prefix of all entities. By default evcc will use its own internal vendor ID.",
|
||||
"labelAllowControl": "Accept additional power limit recommendations from SHM.",
|
||||
"labelControl": "Allow control",
|
||||
"labelDeviceId": "Device ID",
|
||||
"labelVendorId": "Vendor ID",
|
||||
"title": "SMA Sunny Home Manager"
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@
|
|||
"title": "Määrittele toimintaa"
|
||||
},
|
||||
"deviceValue": {
|
||||
"allowControl": "Salli säätäminen",
|
||||
"amount": "Määrä",
|
||||
"broker": "Välittäjä (Broker)",
|
||||
"bucket": "Bucket",
|
||||
|
|
@ -443,8 +442,6 @@
|
|||
"descriptionIds": "Sunny Portal -järjestelmässä jokainen käyttölaite vaatii yksilöllisen tunnisteen. Evcc luo yksilöllisen tunnisteen laitteistosi perusteella. Jos siirrät evcc:n asennuksen toiseen laitteistoon nämä tunnisteet voivat muuttua. Jos haluat pitää vanhat tunnisteet, voit automaattiset luodut tunnisteet tässä. Avaa SEMP URL (/semp) tarkistaaksesi nykyiset tunnisteesi.",
|
||||
"descriptionSempUrl": "SEMP URL",
|
||||
"descriptionVendorId": "8-merkkinen HEX-merkkijono. Yleinen etuliite kaikille laitteille. Oletuksena evcc käyttää sisäistä valmistajatunnistettaan.",
|
||||
"labelAllowControl": "Hyväksy lisätehorajasuositukset SHM:lta.",
|
||||
"labelControl": "Salli hallinta",
|
||||
"labelDeviceId": "Laite-ID",
|
||||
"labelVendorId": "Valmistaja-ID",
|
||||
"title": "SMA Sunny Home Manager"
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@
|
|||
"title": "Comportement du contrôle"
|
||||
},
|
||||
"deviceValue": {
|
||||
"allowControl": "Permettre contrôle",
|
||||
"amount": "Montant",
|
||||
"broker": "Courtier",
|
||||
"bucket": "Bucket",
|
||||
|
|
@ -443,8 +442,6 @@
|
|||
"descriptionIds": "Dans Sunny Portal, chaque appareil consommateur doit disposer d'un identifiant unique. evcc génère un identifiant unique basé sur votre matériel. Si vous migrez evcc vers un autre matériel, ces identifiants peuvent changer. Si vous souhaitez conserver l'historique, vous pouvez remplacer les identifiants générés ici. Ouvrez l'URL SEMP (/semp) pour vérifier vos identifiants actuels.",
|
||||
"descriptionSempUrl": "URL SEMP",
|
||||
"descriptionVendorId": "Chaîne HEX à 8 caractères. Préfixe général de toutes les entités. Par défaut, evcc utilisera son propre identifiant fournisseur interne.",
|
||||
"labelAllowControl": "Accepter les recommandations supplémentaires de SHM concernant les limites de puissance.",
|
||||
"labelControl": "Autoriser le contrôle",
|
||||
"labelDeviceId": "Identifiant de l'appareil",
|
||||
"labelVendorId": "Identifiant du fournisseur",
|
||||
"title": "SMA Sunny Home Manager"
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@
|
|||
"title": "Ponašanje upravljanja"
|
||||
},
|
||||
"deviceValue": {
|
||||
"allowControl": "Dozvoli kontrolu",
|
||||
"amount": "Iznos",
|
||||
"broker": "Posrednik",
|
||||
"bucket": "Kanta",
|
||||
|
|
@ -443,8 +442,6 @@
|
|||
"descriptionIds": "U Sunny Portalu svaki potrošački uređaj mora imati jedinstveni identifikator. evcc generira jedinstveni identifikator na temelju vašeg hardvera. Ako evcc premjestite na drugi hardver, ti se identifikatori mogu promijeniti. Ako želite zadržati povijest, ovdje možete nadjačati generirane identifikatore. Otvorite SEMP URL (/semp) kako biste provjerili svoje trenutačne identifikatore.",
|
||||
"descriptionSempUrl": "SEMP URL",
|
||||
"descriptionVendorId": "HEX izraz od 8 znakova. Prefiks za sve objekte. Uobičajeno je da evcc koristi svoj interni ID.",
|
||||
"labelAllowControl": "Prihvati dodatna ograničenja snage prema savjetima SHM-a.",
|
||||
"labelControl": "Dozvoli kontrolu",
|
||||
"labelDeviceId": "ID uređaja",
|
||||
"labelVendorId": "ID proizvođača",
|
||||
"title": "SMA Sunny Home Manager"
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@
|
|||
"title": "Kontrollverhalen"
|
||||
},
|
||||
"deviceValue": {
|
||||
"allowControl": "Steierung erlaben",
|
||||
"amount": "Unzahl",
|
||||
"broker": "Broker",
|
||||
"bucket": "Eemer",
|
||||
|
|
@ -447,8 +446,6 @@
|
|||
"descriptionIds": "Am Sunny Portal brauch all Ladung (Luedpunkt, etc.) eng eenzegaarteg Identifikatioun. evcc generéiert eng eenzegaarteg Identifikatioun, déi op Ärer Hardware baséiert. Wann Dir evcc op aner Hardware migréiert, kann dësen Identifikator sech änneren. Fir den Historique ze späicheren, kënnt Dir déi generéiert Identifikatoren hei iwwerschreiwen. Maacht d'SEMP URL op (/semp) fir Är aktuell Identifikatoren ze kontrolléieren.",
|
||||
"descriptionSempUrl": "SEMP-URL",
|
||||
"descriptionVendorId": "8-stellegen HEX-String. Allgemenge Präfix fir all Entiéiten. Standardméisseg verwennt evcc seng eegen intern Hiersteller-ID.",
|
||||
"labelAllowControl": "Zousätzlech Recommandatioune fir d'Leeschtungslimit vun SHM z'akzeptéieren.",
|
||||
"labelControl": "Steierung erlaben",
|
||||
"labelDeviceId": "Geräter-ID",
|
||||
"labelVendorId": "Hiersteller-ID",
|
||||
"title": "SMA Sunny Home Manager"
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@
|
|||
"title": "Valdymo elgesys"
|
||||
},
|
||||
"deviceValue": {
|
||||
"allowControl": "Leisti valdymą",
|
||||
"amount": "Kiekis",
|
||||
"broker": "Broker sistema",
|
||||
"bucket": "Bucket",
|
||||
|
|
@ -200,7 +199,6 @@
|
|||
"description": "Įrašo įkrovimo ir kitus duomenis į InfluxDB. Duomenims vizualizuoti naudokite \"Grafana\" ar panašius įrankius.",
|
||||
"descriptionToken": "Patikrinkite InfluxDB dokumentaciją, kad sužinotumėte, kaip ją sukurti. https://docs.influxdata.com/influxdb/v2/admin/",
|
||||
"labelBucket": "Bucket",
|
||||
"labelCheckInsecure": "Leisti savarankiškai pasirašytus sertifikatus",
|
||||
"labelDatabase": "Duomenų bazė",
|
||||
"labelInsecure": "Sertifikato patvirtinimas",
|
||||
"labelOrg": "Organizacija",
|
||||
|
|
@ -372,7 +370,6 @@
|
|||
"protocolValueTcp": "TCP"
|
||||
},
|
||||
"modbusproxy": {
|
||||
"description": "Leisti keliems klientams pasiekti vieną „Modbus“ įrenginį.",
|
||||
"title": "Modbus Proxy"
|
||||
},
|
||||
"mqtt": {
|
||||
|
|
@ -382,7 +379,6 @@
|
|||
"descriptionTopic": "Palikite tuščią, kad išjungtumėte publikavimą.",
|
||||
"labelBroker": "Broker",
|
||||
"labelCaCert": "Serverio sertifikatas (CA)",
|
||||
"labelCheckInsecure": "Leisti savarankiškai pasirašytus sertifikatus",
|
||||
"labelClientCert": "Kliento sertifikatas",
|
||||
"labelClientId": "Kliento ID",
|
||||
"labelClientKey": "Kliento raktas",
|
||||
|
|
@ -447,8 +443,6 @@
|
|||
"descriptionIds": "Sunny Portal sistemoje kiekvienam vartotojo įrenginiui reikalingas unikalus identifikatorius. evcc generuoja unikalų identifikatorių pagal jūsų aparatinę įrangą. Jei migruosite evcc į kitą aparatinę įrangą, šie identifikatoriai gali pasikeisti. Jei norite išsaugoti istoriją, čia galite pakeisti sugeneruotus identifikatorius. Atidarykite SEMP URL (/semp), kad patikrintumėte dabartinius identifikatorius.",
|
||||
"descriptionSempUrl": "SEMP URL",
|
||||
"descriptionVendorId": "8 simbolių HEX eilutė. Bendras visų objektų prefiksas. Pagal numatytuosius nustatymus evcc naudos savo vidinį tiekėjo ID.",
|
||||
"labelAllowControl": "Priimti papildomas SHM galios ribojimo rekomendacijas.",
|
||||
"labelControl": "Leisti valdyti",
|
||||
"labelDeviceId": "Įrenginio ID",
|
||||
"labelVendorId": "Gamintojo ID",
|
||||
"title": "SMA Sunny Home Manager"
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@
|
|||
"title": "Regelgedrag"
|
||||
},
|
||||
"deviceValue": {
|
||||
"allowControl": "Besturing toestaan",
|
||||
"amount": "Aantal",
|
||||
"broker": "Agent",
|
||||
"bucket": "Bucket",
|
||||
|
|
@ -444,8 +443,6 @@
|
|||
"descriptionIds": "In Sunny Portal heeft elk consumentenapparaat een unieke identificatiecode nodig. evcc genereert een unieke identificatiecode op basis van uw hardware. Als u evcc naar andere hardware migreert, kunnen deze identificatiecodes veranderen. Als u de geschiedenis wilt behouden, kunt u de gegenereerde identificatiecodes hier overschrijven. Open de SEMP-URL (/semp) om uw huidige identificatiecodes te controleren.",
|
||||
"descriptionSempUrl": "SEMP URL",
|
||||
"descriptionVendorId": "8 karakters HEX string. Algemene prefix van alle onderdelen. Standaard zal evcc zijn eigen vendor ID gebruiken.",
|
||||
"labelAllowControl": "Sta additionele aanbevelingen stroombegrenzing toe van SHM.",
|
||||
"labelControl": "Besturing toestaan",
|
||||
"labelDeviceId": "Device ID",
|
||||
"labelVendorId": "Vendor ID",
|
||||
"title": "SMA Sunny Home Manager"
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@
|
|||
"title": "Comportamento de controlo"
|
||||
},
|
||||
"deviceValue": {
|
||||
"allowControl": "Permitir controlo",
|
||||
"amount": "Quantidade",
|
||||
"broker": "Broker",
|
||||
"bucket": "Bucket",
|
||||
|
|
@ -440,8 +439,6 @@
|
|||
"descriptionIds": "No Sunny Portal cada dispositivo necessita duma identidade única. O evcc gera uma identidade única com base no seu hardware. Se migrar o evcc para outro hardware estas identidades podem mudar. Se quiser manter o histórico pode substituir as identidades geradas aqui. Abra o SEMP URL(/semp) para ver as identidade atuais.",
|
||||
"descriptionSempUrl": "SEMP URL",
|
||||
"descriptionVendorId": "string 8 caratecteres HEX. Prefixo geral de todas as entidades. O evcc usa o seu próprio vendor ID interno Por defeito.",
|
||||
"labelAllowControl": "Aceitar recomendações adicionais de limite de potência do SHM.",
|
||||
"labelControl": "Permitir controlo",
|
||||
"labelDeviceId": "Device ID",
|
||||
"labelVendorId": "Vendor ID",
|
||||
"title": "SMA Sunny Home Manager"
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@
|
|||
"title": "Nadzor vedenja"
|
||||
},
|
||||
"deviceValue": {
|
||||
"allowControl": "Dovoli nadzor",
|
||||
"amount": "Znesek",
|
||||
"broker": "Broker",
|
||||
"bucket": "Vedro",
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@
|
|||
"title": "Kontrollera beteende"
|
||||
},
|
||||
"deviceValue": {
|
||||
"allowControl": "Tillåt styrning",
|
||||
"amount": "Belopp",
|
||||
"broker": "Broker",
|
||||
"bucket": "Bucket",
|
||||
|
|
@ -447,8 +446,6 @@
|
|||
"descriptionIds": "I Sunny Portal behöver varje konsumentenhet en unik identifierare. evcc genererar en unik identifierare baserat på din hårdvara. Om du migrerar evcc till en annan hårdvara kan dessa identifierare ändras. Om du vill behålla historiken kan du åsidosätta de genererade identifierarna här. Öppna SEMP-URL:en (/semp) för att kontrollera dina aktuella identifierare.",
|
||||
"descriptionSempUrl": "SEMP URL",
|
||||
"descriptionVendorId": "Hexsträng med 8 tecken. Generellt prefix för alla entiteter. Evcc använder sitt egna tillverkar-ID som standard.",
|
||||
"labelAllowControl": "Tillåt rekommendationer från SHM för effektgränser.",
|
||||
"labelControl": "Tillåt styrning",
|
||||
"labelDeviceId": "Device ID",
|
||||
"labelVendorId": "Tillverkar-ID",
|
||||
"title": "SMA Sunny Home Manager"
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@
|
|||
"title": "Контрольна поведінка"
|
||||
},
|
||||
"deviceValue": {
|
||||
"allowControl": "Дозволити керування",
|
||||
"amount": "Сума",
|
||||
"broker": "Брокер",
|
||||
"bucket": "Відро",
|
||||
|
|
@ -447,8 +446,6 @@
|
|||
"descriptionIds": "У Sunny Portal кожне споживче обладнання потребує унікального ідентифікатора. evcc генерує унікальний ідентифікатор на основі вашого обладнання. Якщо ви перенесете evcc на інше обладнання, ці ідентифікатори можуть змінитися. Якщо ви хочете зберегти історію, ви можете замінити згенеровані ідентифікатори тут. Відкрийте URL-адресу SEMP (/semp), щоб перевірити ваші поточні ідентифікатори.",
|
||||
"descriptionSempUrl": "SEMP URL",
|
||||
"descriptionVendorId": "8-символьний шістнадцятковий рядок. Загальний префікс усіх об'єктів. За замовчуванням evcc використовуватиме власний внутрішній ідентифікатор постачальника.",
|
||||
"labelAllowControl": "Прийміть додаткові рекомендації щодо обмеження потужності від SHM.",
|
||||
"labelControl": "Дозволити керування",
|
||||
"labelDeviceId": "Ідентифікатор пристрою",
|
||||
"labelVendorId": "Ідентифікатор постачальника",
|
||||
"title": "SMA Сонячний домашній менеджер"
|
||||
|
|
|
|||
|
|
@ -201,7 +201,6 @@ func (s *HTTPd) RegisterSiteHandlers(site site.API, valueChan chan<- util.Param)
|
|||
"vehicle": {"POST", "/vehicle/{name:[a-zA-Z0-9_.:-]+}", vehicleSelectHandler(site, lp)},
|
||||
"vehicle2": {"DELETE", "/vehicle", vehicleRemoveHandler(lp)},
|
||||
"vehicleDetect": {"PATCH", "/vehicle", vehicleDetectHandler(lp)},
|
||||
"remotedemand": {"POST", "/remotedemand/{demand:[a-z]+}/{source:[0-9a-zA-Z_-]+}", remoteDemandHandler(lp)},
|
||||
"enableThreshold": {"POST", "/enable/threshold/{value:-?[0-9.]+}", floatHandler(pass(lp.SetEnableThreshold), lp.GetEnableThreshold)},
|
||||
"enableDelay": {"POST", "/enable/delay/{value:[0-9]+}", durationHandler(pass(lp.SetEnableDelay), lp.GetEnableDelay)},
|
||||
"disableThreshold": {"POST", "/disable/threshold/{value:-?[0-9.]+}", floatHandler(pass(lp.SetDisableThreshold), lp.GetDisableThreshold)},
|
||||
|
|
|
|||
|
|
@ -32,32 +32,6 @@ type PlanPreviewResponse struct {
|
|||
Power float64 `json:"power"`
|
||||
}
|
||||
|
||||
// remoteDemandHandler updates minimum soc
|
||||
func remoteDemandHandler(lp loadpoint.API) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
|
||||
source := vars["source"]
|
||||
demand, err := loadpoint.RemoteDemandString(vars["demand"])
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
lp.RemoteControl(source, demand)
|
||||
|
||||
res := struct {
|
||||
Demand loadpoint.RemoteDemand `json:"demand"`
|
||||
Source string `json:"source"`
|
||||
}{
|
||||
Source: source,
|
||||
Demand: demand,
|
||||
}
|
||||
|
||||
jsonWrite(w, res)
|
||||
}
|
||||
}
|
||||
|
||||
// planHandler returns the current plan
|
||||
func planHandler(lp loadpoint.API) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
|||
|
|
@ -21,18 +21,12 @@ test.describe("SHM", () => {
|
|||
await enableExperimental(page, false);
|
||||
|
||||
const shmCard = page.getByTestId("shm");
|
||||
await expect(shmCard).toContainText(["Allow control", "no"].join(""));
|
||||
|
||||
// configure SHM with allow control and IDs
|
||||
// configure SHM with IDs
|
||||
await shmCard.getByRole("button", { name: "edit" }).click();
|
||||
const modal = page.getByTestId("shm-modal");
|
||||
await expectModalVisible(modal);
|
||||
|
||||
const allowControl = modal.getByRole("checkbox", { name: "Allow control" });
|
||||
await expect(allowControl).not.toBeChecked();
|
||||
await allowControl.check();
|
||||
await expect(allowControl).toBeChecked();
|
||||
|
||||
await modal.getByRole("button", { name: "Show advanced settings" }).click();
|
||||
|
||||
// test vendor ID validation
|
||||
|
|
@ -52,16 +46,13 @@ test.describe("SHM", () => {
|
|||
|
||||
await modal.getByRole("button", { name: "Save" }).click();
|
||||
await expectModalHidden(modal);
|
||||
await expect(shmCard).toContainText(["Allow control", "yes"].join(""));
|
||||
|
||||
// verify persistence after restart
|
||||
await restart(CONFIG);
|
||||
await page.goto("/#/config");
|
||||
|
||||
await expect(shmCard).toContainText(["Allow control", "yes"].join(""));
|
||||
await shmCard.getByRole("button", { name: "edit" }).click();
|
||||
await expectModalVisible(modal);
|
||||
await expect(allowControl).toBeChecked();
|
||||
await expect(vendor).toHaveValue(VALID_VENDOR_ID);
|
||||
await expect(device).toHaveValue(VALID_DEVICE_ID);
|
||||
|
||||
|
|
@ -75,14 +66,5 @@ test.describe("SHM", () => {
|
|||
`<DeviceId>F-${VALID_VENDOR_ID}-${VALID_DEVICE_ID.toLowerCase()}-00</DeviceId>`
|
||||
);
|
||||
await sempPage.close();
|
||||
|
||||
// uncheck allow control
|
||||
await allowControl.uncheck();
|
||||
await expect(allowControl).not.toBeChecked();
|
||||
await modal.getByRole("button", { name: "Save" }).click();
|
||||
await expectModalHidden(modal);
|
||||
|
||||
// verify it shows as disabled
|
||||
await expect(shmCard).toContainText(["Allow control", "no"].join(""));
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue