Skip to main content

README.md

# 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
```