Use a short OCPP UniqueId to support firmware that truncates the echo… - #106
Use a short OCPP UniqueId to support firmware that truncates the echo…#106loosrob wants to merge 2 commits into
Conversation
|
Cutting a 32-character GUID down to 11 characters seems like a much higher risk of collisions. I would prefer a solution using case-sensitive characters (like Base64 does) to extend the possible range and reduce the probability of collisions. The necessary function would only require a few lines of code. |
Per review: replaces 11-char hex truncation with a 62-char alphanumeric set. Tested on live eNovates hardware — IDs echo back intact and correlate.
|
Updated to use a 62-character alphanumeric alphabet (A–Z, a–z, 0–9) at 11 chars — ~65 bits, essentially matching Base64 without the +///= characters that could interfere with the JSON/WebSocket framing. Uses a crypto RNG rather than truncating a GUID. Tested on the live eNovates charger: the 11-char alphanumeric IDs echo back intact (e.g. vGRNWkGMCbw, VEUYyGe0MYH) and correlate correctly, so the firmware truncates purely by length, not character set. GetConfiguration returns cleanly. (Minor note: there's a negligible modulo bias since 256 isn't a multiple of 62 — happy to switch to rejection sampling if you'd prefer it perfectly uniform.) |
Use a short OCPP UniqueId to support firmware that truncates the echoed id
Summary
Server-initiated OCPP 1.6 messages currently use a full 32-character GUID as the
message
UniqueId:This PR replaces that with an 11-character id via a small helper
(
NewShortUniqueId()), applied to all six existing server-initiated senders inOCPPMiddleware.OCPP16.cs.Motivation
Per OCPP-J, a charge point must echo the request's
UniqueIdback in itsCALLRESULT, andReceive16correlates the response by looking that id up in_requestQueue. Most chargers (including KEBA) echo the full id and work fine.However, at least one firmware family — eNovates, seen on a Bluecorner "Curved"
charge point (firmware
70.13.0) — truncates the echoedUniqueIdto 11characters. When a 32-char GUID is sent, the truncated echo never matches the
queued id, so every server-initiated request logs:
and the API caller receives
{"status":"Timeout"}after 60 s even though thecharger answered correctly.
Example (sent vs. echoed, consistent across requests):
Fix
11 hex chars is ~44 bits of entropy — far more than enough uniqueness for these
one-at-a-time backend requests.
Compatibility
This is backward compatible. Spec-compliant chargers echo the shorter id
unchanged, so correlation continues to work exactly as before. Verified against a
live eNovates-based charge point: with the fix, server-initiated requests
(Reset, GetConfiguration, etc.) correlate correctly and the API returns the
charger's real answer instead of a false timeout.
Scope
Only
OCPP.Core.Server/OCPPMiddleware.OCPP16.csis changed: the new helper plussix one-line replacements in the existing senders (Reset16, UnlockConnector16,
SetChargingProfile16, ClearChargingProfile16, RemoteStartTransaction16,
RemoteStopTransaction16).
Note on overlap with the GetConfiguration/ChangeConfiguration PR
If my other PR (adding GetConfiguration/ChangeConfiguration) is merged first,
this file will have moved and this PR will need a trivial rebase (the same helper
and the same one-line swaps, additionally applied to the two new senders). Happy
to rebase whenever suits — just let me know the preferred order. The two changes
are logically independent; I kept them apart so this firmware-workaround can be
accepted, gated behind a flag, or declined on its own merits.
Licensed under GPLv3, consistent with the rest of the project.