forked from lorenzodonini/ocpp-go
/
reservation_handler.go
132 lines (126 loc) · 4.98 KB
/
reservation_handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package main
import (
"fmt"
"github.com/lorenzodonini/ocpp-go/ocpp2.0.1/availability"
"github.com/lorenzodonini/ocpp-go/ocpp2.0.1/reservation"
"github.com/lorenzodonini/ocpp-go/ocpp2.0.1/types"
)
func (handler *ChargingStationHandler) OnCancelReservation(request *reservation.CancelReservationRequest) (resp *reservation.CancelReservationResponse, err error) {
for i, e := range handler.evse {
if e.currentReservation == request.ReservationID {
// Found reservation -> cancel
e.currentReservation = -1
for j := range e.connectors {
if e.connectors[j].status == availability.ConnectorStatusReserved {
go updateConnectorStatus(handler, i, j, availability.ConnectorStatusAvailable)
break
}
}
logDefault(request.GetFeatureName()).Infof("reservation %v for evse %d canceled", request.ReservationID, i)
resp = reservation.NewCancelReservationResponse(reservation.CancelReservationStatusAccepted)
return
}
}
// Didn't find reservation -> reject
logDefault(request.GetFeatureName()).Infof("couldn't cancel reservation %v: reservation not found!", request.ReservationID)
resp = reservation.NewCancelReservationResponse(reservation.CancelReservationStatusRejected)
return
}
func (handler *ChargingStationHandler) OnReserveNow(request *reservation.ReserveNowRequest) (resp *reservation.ReserveNowResponse, err error) {
var reservedEvse int
var reservedConnector int
var status reservation.ReserveNowStatus
status, reservedEvse, reservedConnector, err = handler.findConnector(request.EvseID, request.ConnectorType)
if err != nil {
logDefault(request.GetFeatureName()).Error(err)
}
resp = reservation.NewReserveNowResponse(status)
if resp.Status != reservation.ReserveNowStatusAccepted {
resp.StatusInfo = types.NewStatusInfo("code", err.Error())
return
}
// Complete reservation
evse := handler.evse[reservedEvse]
evse.currentReservation = request.ID
logDefault(request.GetFeatureName()).Infof("reservation %v accepted for evse %v, connector %v",
request.ID, reservedEvse, reservedConnector)
go updateConnectorStatus(handler, reservedEvse, reservedConnector, availability.ConnectorStatusReserved)
// TODO: the logic above is incomplete. Advanced support for reservation management is missing.
// TODO: automatically remove reservation after expiryDate
return
}
func (handler *ChargingStationHandler) findConnector(requestedEVSE *int, connectorType reservation.ConnectorType) (status reservation.ReserveNowStatus, evseID int, connectorID int, err error) {
status = reservation.ReserveNowStatusAccepted
if requestedEVSE != nil {
evseID = *requestedEVSE
evse, ok := handler.evse[evseID]
if !ok {
status = reservation.ReserveNowStatusRejected
err = fmt.Errorf("couldn't reserve a connector for invalid evse %d", evseID)
return
} else if evse.currentReservation != 0 {
status = reservation.ReserveNowStatusOccupied
err = fmt.Errorf("evse %v already has a pending reservation", evseID)
return
} else if evse.availability == availability.OperationalStatusInoperative {
status = reservation.ReserveNowStatusUnavailable
err = fmt.Errorf("evse %v is currently not operative", evseID)
return
}
for i, c := range evse.connectors {
if connectorType != "" && c.typ != connectorType {
continue
}
switch c.status {
case availability.ConnectorStatusReserved, availability.ConnectorStatusOccupied:
status = reservation.ReserveNowStatusOccupied
case availability.ConnectorStatusUnavailable:
status = reservation.ReserveNowStatusUnavailable
case availability.ConnectorStatusFaulted:
status = reservation.ReserveNowStatusUnavailable
case availability.ConnectorStatusAvailable:
// Found an available connector
status = reservation.ReserveNowStatusAccepted
connectorID = i
return
}
}
} else {
// Find suitable evse + connector
for j, e := range handler.evse {
evseID = j
if e.currentReservation != 0 {
status = reservation.ReserveNowStatusOccupied
err = fmt.Errorf("evse %v already has a pending reservation", evseID)
return
} else if e.availability == availability.OperationalStatusInoperative {
status = reservation.ReserveNowStatusUnavailable
err = fmt.Errorf("evse %v is currently not operative", evseID)
return
}
for i, c := range e.connectors {
if connectorType != "" && c.typ != connectorType {
continue
}
switch c.status {
case availability.ConnectorStatusReserved, availability.ConnectorStatusOccupied:
status = reservation.ReserveNowStatusOccupied
case availability.ConnectorStatusUnavailable:
status = reservation.ReserveNowStatusUnavailable
case availability.ConnectorStatusFaulted:
status = reservation.ReserveNowStatusUnavailable
case availability.ConnectorStatusAvailable:
// Found an available connector
status = reservation.ReserveNowStatusAccepted
connectorID = i
return
}
}
}
if status == "" {
status = reservation.ReserveNowStatusRejected
err = fmt.Errorf("no available evse found")
}
}
return
}