# ocpp
Type-safe [OCPP](https://openchargealliance.org/) (Open Charge Point Protocol)
message models and OCPP-J codecs for Gleam, generated from the OCA JSON
schemas with spec-derived documentation.
One package, every protocol version — each under its own namespace, so you
import only the version(s) you speak:
| Namespace | Contents |
|---|---|
| `ocpp`, `ocpp/rpc`, `ocpp/transport/json/*` | OCPP-J frame layer, RPC error codes, `DateTime`/`CustomData`/`JsonValue`, codec helpers |
| `ocpp/v1_6/*` | OCPP 1.6 (28 actions) |
| `ocpp/v2_0_1/*` | OCPP 2.0.1 (64 actions) |
| `ocpp/v2_1/*` | OCPP 2.1 (91 actions) |
Each version namespaces **one module per spec entity**, so the module is the
namespace and no name carries a type prefix:
```gleam
import ocpp/v2_0_1/enums/boot_reason
import ocpp/v2_0_1/messages/boot_notification
// Build a request from its required fields (optionals default to None):
let request =
boot_notification.new_request(
charging_station: station,
reason: boot_reason.PowerUp,
)
// Encode / decode the exact OCPP-J JSON (schema constraints enforced):
let wire = boot_notification.request_to_json(request)
json.parse(body, boot_notification.response_decoder())
```
Dispatch by action string (`ocpp/v2_0_1/dispatch`) maps a wire frame's action
to the right decoder and back; the frame layer lives in
`ocpp/transport/json/frame`.
## Development
The per-version modules are **generated** — do not edit them by hand. The
generator lives in `dev/` (so it ships with neither the package nor its
dependencies). To regenerate from the vendored schemas, from the repo root:
```sh
gleam dev # writes the staging tree under generated/
gleam format generated
for v in v1_6 v2_0_1 v2_1; do
rsync -a --delete generated/ocpp/$v/ src/ocpp/$v/
done
```
Run the tests (codec round-trips and codegen suites together):
```sh
gleam test
```