feat: complete OCPP 2.1 transport — SEND, CALLRESULTERROR, WebSocket compression, JWS signed messages - #9
Merged
Merged
Conversation
The typed handler interfaces + RegisterCSMS/RegisterCP are the recommended way to register handlers, so make the README quickstart and the CSMS examples use them: embed UnimplementedCSMSHandler and implement only the messages you handle. - README CSMS quickstart uses v16h.RegisterCSMS; csms.On kept as a documented single-handler/dynamic alternative. - csms-minimal, migration-after: small handler structs. - csms-full: *app implements CSMSHandler (embeds UnimplementedCSMSHandler); the per-message closures become methods registered in one RegisterCSMS call.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Completes OCPP 2.1 OCPP-J transport support. A full audit against the OCPP 2.1
spec (Parts 0/1/2/4 + appendices) confirmed the message set was already complete
(91/91 messages) but three transport-layer capabilities were missing. This PR
adds all three:
SEND(MessageTypeId 6) &CALLRESULTERROR(MessageTypeId 5) — the twomessage types introduced in OCPP 2.1 Part 4.
CALL/SENDmessages.What's included
SEND & CALLRESULTERROR
core/ocppj: parse/encode for types 5 & 6; unknown message types ignored per §4.4.core/dispatcher: inbound routing, no-responseSENDhandler dispatch (withpanic recovery),
DoSendfire-and-forget, and activeCALLRESULTERRORon aninvalid inbound
CALLRESULT(2.1 only).ocppj.SendMessage,cp.Send/OnSend,csms.Send/OnSend.SENDmessages; generatedNotifyPeriodicEventStream.WebSocket compression (RFC 7692)
transport.CompressionModeenum; enabled by default (NoContextTakeover) onboth CP and CSMS, negotiated automatically and degrading gracefully.
cp.WithCompression/csms.WithCompressionoptions.permessage-deflateis negotiated on the upgrade response.Signed Messages (JWS)
core/ocppj/signing:Signer/Verifier/UnwrapPayloadusinggo-jose/go-jose/v4; Flattened JWS, ES256/RS256/RS384 only,x5t#S256plusOCPPAction/OCPPMessageTypeIdprotected headers.[type, id, "<Action>-Signed", {JWS}].RequireSignatureVerification.cp/csmsWithSigner/WithVerifier/WithRequireSignature.Spec decisions (documented in code)
CALL); the §7.1{Extension}element is omitted because it contradicts §4.2.1 ("a CALL alwaysconsists of 4 elements"). Isolated so a future OCA erratum is a small change.
CALL/SENDonly.Action-less replies (
CALLRESULT/CALLERROR/CALLRESULTERROR) are out ofscope (spec-undefined); the
signingprimitives are public for manual use.Testing
core/ocppj,core/dispatcher,cp/csms,core/ocppj/signing, andinternal/e2e(TDD throughout, including spec-alignedrejection cases: tampered payload, wrong key, disallowed alg, header mismatch).
go build ./...,go vet ./..., andgo test ./...all pass.Dependencies
github.com/go-jose/go-jose/v4to a direct dependency (it was alreadypresent in the module graph as a transitive dependency).
🤖 Generated with Claude Code