OCPP-J Codec
Wire Format
The OCPP-J protocol (JSON over WebSocket) uses JSON arrays with a message type ID as the first element:
| Type | ID | Format | Purpose |
|---|---|---|---|
Call | 2 | [2, unique_id, action, payload] | Request from client or server |
CallResult | 3 | [3, unique_id, payload] | Successful response |
CallError | 4 | [4, unique_id, error_code, description, details] | Error response |
The unique_id correlates a CallResult or CallError back to its originating Call.
Message Types
using OCPPDataThe three concrete subtypes of OCPPMessage:
using InteractiveUtils: subtypes
subtypes(OCPPMessage)3-element Vector{Any}:
Call
CallError
CallResultConstructing Messages
Convenience constructors auto-fill message_type_id:
call = Call("id-1", "Heartbeat", Dict{String,Any}())Call(2, "id-1", "Heartbeat", Dict{String, Any}())result = CallResult("id-1", Dict{String,Any}("status" => "Accepted"))CallResult(3, "id-1", Dict{String, Any}("status" => "Accepted"))error = CallError("id-1", "NotImplemented", "Not supported", Dict{String,Any}())CallError(4, "id-1", "NotImplemented", "Not supported", Dict{String, Any}())Encoding
encode converts an OCPPMessage to a JSON string ready for WebSocket transmission:
encode(call)"[2,\"id-1\",\"Heartbeat\",{}]"encode(result)"[3,\"id-1\",{\"status\":\"Accepted\"}]"encode(error)"[4,\"id-1\",\"NotImplemented\",\"Not supported\",{}]"Decoding
decode parses a raw JSON string back into the appropriate OCPPMessage subtype:
decoded = decode("[2,\"id-1\",\"Heartbeat\",{}]")Call(2, "id-1", "Heartbeat", Dict{String, Any}())decoded isa Calltruedecoded.action"Heartbeat"decoded.payloadDict{String, Any}()Decoding a CallResult:
decode("[3,\"id-1\",{\"status\":\"Accepted\"}]")CallResult(3, "id-1", Dict{String, Any}("status" => "Accepted"))Decoding a CallError:
decode("[4,\"id-1\",\"NotImplemented\",\"Not supported\",{}]")CallError(4, "id-1", "NotImplemented", "Not supported", Dict{String, Any}())Round-Trip
msg = Call("abc-123", "BootNotification", Dict{String,Any}(
"chargePointVendor" => "V",
"chargePointModel" => "M",
))
wire = encode(msg)"[2,\"abc-123\",\"BootNotification\",{\"chargePointVendor\":\"V\",\"chargePointModel\":\"M\"}]"decoded = decode(wire)
decoded.action, decoded.payload("BootNotification", Dict{String, Any}("chargePointVendor" => "V", "chargePointModel" => "M"))Generating Unique IDs
id = generate_unique_id()
println(id) # UUID v4 string
length(id) # 36 characters (8-4-4-4-12 format)36