OCPP: proactively trigger BootNotification after WebSocket connect (#28540)
This commit is contained in:
parent
d5c9db02c4
commit
20de0b9da1
2 changed files with 41 additions and 0 deletions
|
|
@ -4,6 +4,11 @@ import "time"
|
|||
|
||||
var Timeout = time.Minute // default request / response timeout on protocol level
|
||||
|
||||
// triggerBootDelay defines how long to wait after WebSocket connect before
|
||||
// proactively triggering a BootNotification. This allows the connection to
|
||||
// stabilize and gives the charger a chance to send a spontaneous BootNotification.
|
||||
const triggerBootDelay = 5 * time.Second
|
||||
|
||||
const (
|
||||
// Core profile keys
|
||||
KeyMeterValueSampleInterval = "MeterValueSampleInterval"
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/evcc-io/evcc/util"
|
||||
"github.com/lorenzodonini/ocpp-go/ocpp1.6/core"
|
||||
"github.com/lorenzodonini/ocpp-go/ocpp1.6/remotetrigger"
|
||||
"github.com/lorenzodonini/ocpp-go/ocpp1.6/types"
|
||||
)
|
||||
|
||||
|
|
@ -142,12 +143,47 @@ func (cp *CP) connect(connect bool) {
|
|||
// onTransportConnect is called when the WebSocket connection is established.
|
||||
// Instead of marking the CP as connected immediately, it waits for the
|
||||
// BootNotification handshake to complete (or a timeout to expire).
|
||||
//
|
||||
// Some chargers (e.g. Wallbox Pulsar Pro FW 6.x) do not send BootNotification
|
||||
// spontaneously on connect. For these chargers, we proactively trigger it
|
||||
// after a short delay, which typically yields a response within 1 second
|
||||
// instead of waiting for the full timeout.
|
||||
func (cp *CP) onTransportConnect() {
|
||||
cp.mu.Lock()
|
||||
defer cp.mu.Unlock()
|
||||
|
||||
cp.stopBootTimer()
|
||||
cp.bootTimer = time.AfterFunc(Timeout, cp.onBootTimeout)
|
||||
|
||||
// Proactively trigger BootNotification after a short delay.
|
||||
// This helps chargers that don't send it spontaneously (e.g. Wallbox FW 6.x).
|
||||
// The TriggerMessage is sent directly via the OCPP instance, bypassing the
|
||||
// Connected() check which would fail at this point.
|
||||
time.AfterFunc(triggerBootDelay, func() {
|
||||
cp.mu.RLock()
|
||||
// If BootNotification already arrived or timer was cancelled (disconnect),
|
||||
// there is nothing to do.
|
||||
if cp.bootTimer == nil || cp.BootNotificationResult != nil {
|
||||
cp.mu.RUnlock()
|
||||
return
|
||||
}
|
||||
cp.mu.RUnlock()
|
||||
|
||||
cp.log.DEBUG.Printf("proactively triggering BootNotification")
|
||||
|
||||
if err := Instance().TriggerMessage(
|
||||
cp.id,
|
||||
func(conf *remotetrigger.TriggerMessageConfirmation, err error) {
|
||||
if err != nil {
|
||||
cp.log.ERROR.Printf("trigger BootNotification response error: %v", err)
|
||||
}
|
||||
},
|
||||
core.BootNotificationFeatureName,
|
||||
func(request *remotetrigger.TriggerMessageRequest) {},
|
||||
); err != nil {
|
||||
cp.log.ERROR.Printf("failed to trigger BootNotification: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// onBootTimeout is called when the BootNotification wait timer expires.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue