Skip to content

Commit cbe5154

Browse files
andigclaude
andcommitted
refactor(multiplex): simplify to let users choose which protocols to register
Instead of hardcoding both OCPP 1.6 and 2.0.1 servers, the multiplex package now provides a shared WebSocket server that users can use to create their own OCPP servers. This gives full flexibility over which protocols to support. Before: server := multiplex.NewMultiProtocolServer() server.OCPP16Server().SetCoreHandler(...) After: mux := multiplex.NewServer() cs := ocpp16.NewCentralSystem(nil, mux.WebSocketServer()) cs.SetCoreHandler(...) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent feb5a73 commit cbe5154

3 files changed

Lines changed: 82 additions & 242 deletions

File tree

example/multiplex/main.go

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ import (
1212
"time"
1313

1414
"github.com/lorenzodonini/ocpp-go/multiplex"
15+
ocpp16 "github.com/lorenzodonini/ocpp-go/ocpp1.6"
1516
"github.com/lorenzodonini/ocpp-go/ocpp1.6/core"
1617
"github.com/lorenzodonini/ocpp-go/ocpp1.6/types"
18+
ocpp2 "github.com/lorenzodonini/ocpp-go/ocpp2.0.1"
1719
"github.com/lorenzodonini/ocpp-go/ocpp2.0.1/provisioning"
1820
types2 "github.com/lorenzodonini/ocpp-go/ocpp2.0.1/types"
19-
"github.com/lorenzodonini/ocpp-go/ws"
2021
)
2122

2223
// OCPP 1.6 handler
@@ -76,22 +77,30 @@ func (h *ocpp201Handler) OnNotifyReport(chargingStationId string, request *provi
7677
}
7778

7879
func main() {
79-
// Create multi-protocol server
80-
server := multiplex.NewMultiProtocolServer()
80+
// Create multiplex server with shared WebSocket server
81+
mux := multiplex.NewServer()
82+
83+
// Create OCPP servers using the shared WebSocket server.
84+
// You can create only the servers you need.
85+
cs := ocpp16.NewCentralSystem(nil, mux.WebSocketServer())
86+
csms := ocpp2.NewCSMS(nil, mux.WebSocketServer())
8187

8288
// Register OCPP 1.6 handlers
83-
server.OCPP16Server().SetCoreHandler(&ocpp16Handler{})
89+
cs.SetCoreHandler(&ocpp16Handler{})
90+
cs.SetNewChargePointHandler(func(cp ocpp16.ChargePointConnection) {
91+
fmt.Printf("New OCPP 1.6 client connected: %s\n", cp.ID())
92+
})
93+
cs.SetChargePointDisconnectedHandler(func(cp ocpp16.ChargePointConnection) {
94+
fmt.Printf("OCPP 1.6 client disconnected: %s\n", cp.ID())
95+
})
8496

8597
// Register OCPP 2.0.1 handlers
86-
server.OCPP201Server().SetProvisioningHandler(&ocpp201Handler{})
87-
88-
// Track connections and their protocol versions
89-
server.SetNewClientHandler(func(channel ws.Channel) {
90-
fmt.Printf("New client connected: %s (protocol: %s)\n", channel.ID(), channel.Subprotocol())
98+
csms.SetProvisioningHandler(&ocpp201Handler{})
99+
csms.SetNewChargingStationHandler(func(station ocpp2.ChargingStationConnection) {
100+
fmt.Printf("New OCPP 2.0.1 client connected: %s\n", station.ID())
91101
})
92-
93-
server.SetDisconnectedClientHandler(func(channel ws.Channel) {
94-
fmt.Printf("Client disconnected: %s\n", channel.ID())
102+
csms.SetChargingStationDisconnectedHandler(func(station ocpp2.ChargingStationConnection) {
103+
fmt.Printf("OCPP 2.0.1 client disconnected: %s\n", station.ID())
95104
})
96105

97106
// Start listening on port 8080
@@ -101,5 +110,8 @@ func main() {
101110
fmt.Println("Clients can connect with either protocol. The server will negotiate")
102111
fmt.Println("based on the Sec-WebSocket-Protocol header.")
103112

104-
server.Start(8080, "/ocpp/{id}")
113+
// Start both OCPP servers - ws.Server.Start() is idempotent,
114+
// so only the first call actually starts the server
115+
go cs.Start(8080, "/ocpp/{id}")
116+
csms.Start(8080, "/ocpp/{id}")
105117
}

multiplex/multiplex.go

Lines changed: 28 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,10 @@
11
// Package multiplex provides protocol multiplexing support for OCPP servers.
2-
// It allows a single WebSocket server to handle both OCPP 1.6 and OCPP 2.0.1 clients
2+
// It allows a single WebSocket server to handle multiple OCPP protocol versions
33
// on the same port, using WebSocket subprotocol negotiation to route connections
44
// to the appropriate handler.
55
package multiplex
66

7-
import (
8-
ocpp16 "github.com/lorenzodonini/ocpp-go/ocpp1.6"
9-
ocpp2 "github.com/lorenzodonini/ocpp-go/ocpp2.0.1"
10-
"github.com/lorenzodonini/ocpp-go/ws"
11-
)
12-
13-
// ProtocolVersion represents an OCPP protocol version.
14-
type ProtocolVersion string
15-
16-
const (
17-
// V16 represents OCPP 1.6
18-
V16 ProtocolVersion = "ocpp1.6"
19-
// V201 represents OCPP 2.0.1
20-
V201 ProtocolVersion = "ocpp2.0.1"
21-
)
7+
import "github.com/lorenzodonini/ocpp-go/ws"
228

239
// Subprotocol constants for WebSocket negotiation.
2410
const (
@@ -55,47 +41,39 @@ const (
5541
// })
5642
type SubprotocolSelector func(clientID string, requestedSubprotocols []string) string
5743

58-
// MultiProtocolServer is a server that can handle both OCPP 1.6 and OCPP 2.0.1 clients
59-
// on a single port. It uses WebSocket subprotocol negotiation to determine which
60-
// protocol version each client uses.
61-
type MultiProtocolServer interface {
62-
// Start begins listening for connections on the specified port and path.
63-
// The function blocks until Stop is called.
64-
//
65-
// Example:
66-
// go server.Start(8080, "/ocpp/{id}")
67-
Start(port int, listenPath string)
68-
69-
// Stop gracefully shuts down the server.
70-
Stop()
71-
72-
// OCPP16Server returns the underlying OCPP 1.6 Central System.
73-
// Use this to register handlers for OCPP 1.6 messages.
74-
OCPP16Server() ocpp16.CentralSystem
75-
76-
// OCPP201Server returns the underlying OCPP 2.0.1 CSMS.
77-
// Use this to register handlers for OCPP 2.0.1 messages.
78-
OCPP201Server() ocpp2.CSMS
44+
// Server provides a shared WebSocket server for multiple OCPP protocol versions.
45+
// Create OCPP servers (CentralSystem, CSMS) using the shared WebSocketServer(),
46+
// then call Start() on each one. The ws.Server.Start() method is idempotent,
47+
// so only the first call actually starts the server.
48+
//
49+
// Example usage:
50+
//
51+
// // Create multiplex server
52+
// mux := multiplex.NewServer()
53+
//
54+
// // Create only the OCPP servers you need
55+
// cs := ocpp16.NewCentralSystem(nil, mux.WebSocketServer())
56+
// csms := ocpp2.NewCSMS(nil, mux.WebSocketServer())
57+
//
58+
// // Register handlers
59+
// cs.SetCoreHandler(&myOCPP16Handler{})
60+
// csms.SetProvisioningHandler(&myOCPP201Handler{})
61+
//
62+
// // Start servers (ws.Server.Start is idempotent)
63+
// go cs.Start(8080, "/ocpp/{id}")
64+
// csms.Start(8080, "/ocpp/{id}")
65+
type Server interface {
66+
// WebSocketServer returns the underlying ws.Server.
67+
// Use this when creating OCPP servers to share the same WebSocket connection.
68+
WebSocketServer() ws.Server
7969

8070
// SetSubprotocolSelector sets a custom callback for choosing which subprotocol
81-
// to use when a client requests multiple subprotocols. This allows the application
82-
// to implement custom protocol selection logic (e.g., prefer OCPP 2.0.1 over 1.6).
83-
// If not set, the default behavior is used (first mutually-supported protocol).
71+
// to use when a client requests multiple subprotocols.
8472
SetSubprotocolSelector(selector SubprotocolSelector)
8573

86-
// SetNewClientHandler sets a callback for all new client connections,
87-
// regardless of protocol version. The callback receives the WebSocket channel
88-
// which can be used to determine the protocol via channel.Subprotocol().
89-
SetNewClientHandler(handler func(channel ws.Channel))
90-
91-
// SetDisconnectedClientHandler sets a callback for all client disconnections,
92-
// regardless of protocol version.
93-
SetDisconnectedClientHandler(handler func(channel ws.Channel))
94-
9574
// SetBasicAuthHandler enables HTTP Basic Authentication for all connections.
9675
SetBasicAuthHandler(handler func(username, password string) bool)
9776

9877
// SetCheckClientHandler sets a validation handler for incoming connections.
99-
// Return false to reject the connection.
10078
SetCheckClientHandler(handler ws.CheckClientHandler)
10179
}

0 commit comments

Comments
 (0)