forked from lorenzodonini/ocpp-go
/
handler.go
114 lines (99 loc) · 3.36 KB
/
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
package main
import (
"fmt"
"time"
"github.com/lorenzodonini/ocpp-go/ocpp2.0.1"
"github.com/lorenzodonini/ocpp-go/ocpp2.0.1/availability"
"github.com/lorenzodonini/ocpp-go/ocpp2.0.1/localauth"
"github.com/lorenzodonini/ocpp-go/ocpp2.0.1/reservation"
"github.com/lorenzodonini/ocpp-go/ocpp2.0.1/types"
)
// ConnectorInfo contains some simple state about a single connector.
type ConnectorInfo struct {
status availability.ConnectorStatus
availability availability.OperationalStatus
typ reservation.ConnectorType
}
// EVSEInfo contains some simple state
type EVSEInfo struct {
availability availability.OperationalStatus
currentTransaction string
currentReservation int
connectors map[int]ConnectorInfo
seqNo int
}
// ChargingStationHandler contains some simple state that a charge point needs to keep.
// In production this will typically be replaced by database/API calls.
type ChargingStationHandler struct {
availability availability.OperationalStatus
evse map[int]*EVSEInfo
configuration map[string]string
model string
vendor string
meterValue float64
localAuthList []localauth.AuthorizationData
localAuthListVersion int
monitoringLevel int
}
var chargingStation ocpp2.ChargingStation
func (evse *EVSEInfo) hasConnector(ID int) bool {
return ID > 0 && len(evse.connectors) > ID
}
func (evse *EVSEInfo) getConnectorOfType(typ reservation.ConnectorType) int {
for i, c := range evse.connectors {
if c.typ == typ {
return i
}
}
return -1
}
func (evse *EVSEInfo) nextSequence() int {
seq := evse.seqNo
evse.seqNo = seq + 1
return seq
}
var transactionID = 0
func nextTransactionID() string {
transactionID++
return fmt.Sprintf("%d", transactionID)
}
func checkError(err error) {
if err != nil {
log.Fatal(err)
}
}
func getExpiryDate(info *types.IdTokenInfo) string {
if info.CacheExpiryDateTime != nil {
return fmt.Sprintf("authorized until %v", info.CacheExpiryDateTime.String())
}
return ""
}
func updateOperationalStatus(stateHandler *ChargingStationHandler, evseID int, status availability.OperationalStatus) {
if evseID == 0 {
stateHandler.availability = status
log.Infof("operational status for charging station updated to: %v", status)
} else if evse, ok := stateHandler.evse[evseID]; !ok {
log.Errorf("couldn't update operational status for invalid evse %d", evseID)
return
} else {
evse.availability = status
log.Infof("operational status for evse %d updated to: %v", evseID, status)
}
}
func updateConnectorStatus(stateHandler *ChargingStationHandler, evseID int, connector int, status availability.ConnectorStatus) {
if evse, ok := stateHandler.evse[evseID]; !ok {
log.Errorf("couldn't update connector status for invalid evse %d", evseID)
return
} else if connector < 0 || connector > len(evse.connectors) {
log.Errorf("couldn't update status for evse %d with invalid connector %d", evseID, connector)
return
} else {
conn := evse.connectors[connector]
conn.status = status
evse.connectors[connector] = conn
// Send asynchronous status update
response, err := chargingStation.StatusNotification(types.NewDateTime(time.Now()), status, evseID, connector)
checkError(err)
logDefault(response.GetFeatureName()).Infof("status for evse %d - connector %d updated to: %v", evseID, connector, status)
}
}