This repository contains multiple implementations of the same mobility ID domain:
scala/: original Scala implementation (dev.juherr.mobilityid:mobilityid, sbt 2, Scala 2.13 + 3.9 LTS, specs2)java/: Java 21 port (mobilityid4j, Gradle)go/: Go port (mobilityid.juherr.dev/go)php/: PHP port (juherr/mobility-id, PHP 8.4+)ts/: TypeScript port (@juherr/mobilityid, Bun + Vite+)
cd scala
sbt --server --batch "+test"Run a single Scala suite:
cd scala
sbt --server --batch "core/testOnly com.thenewmotion.mobilityid.ContractIdSpec"cd java
./gradlew testRun a single Java suite:
cd java
./gradlew test --tests "*ContractIdTest"cd ts
vp install
vp checkRun a single TypeScript test pattern:
cd ts
vp test ContractId- Scala docs and original usage examples:
scala/README.md - Java-specific docs and design choices:
java/README.md - Go-specific docs and design choices:
go/README.md - PHP-specific docs and design choices:
php/README.md - TypeScript-specific docs and design choices:
ts/README.md
Every port parses ISO EVSE ids case-insensitively, the E id type included, and renders them in
uppercase: fr*55c*e84400*svg*1 is FR*55C*E84400*SVG*1. Only ASCII letters are folded. DIN ids
are digits only and are unaffected. Protocols disagree on case and length, and the parsers
follow the most tolerant of them:
- OCPI 2.3.0
types
EVSE.evse_idasCiString(48), a case-insensitive string. The CDRs module does the same. - OCHP writes the id type as the
ABNF literal
"E". Quoted ABNF strings are case-insensitive (RFC 5234 §2.3). OCHP allows 31 characters after it, as these parsers do. - OICP 2.3
EvseIDTypeis an uppercase-only pattern with an outlet suffix of up to 30 characters. An id these parsers accept can therefore still be refused by OICP. Render it withtoString()to get the uppercase form, and check the length where OICP applies.
The libraries do not ship protocol-specific validators.
- Renovate manages GitHub Actions, Gradle, npm, sbt/Scala, and
mise.tomltool versions (.github/renovate.json). mise.tomluses simplified version formats: major.minor for sbt/gradle (e.g.,2.0,9.7), major only for Java/Node (e.g.,21,24). SeeAGENTS.mdfor configuration details.- CI validates Gradle Wrapper integrity on every run (
gradle/actions/wrapper-validation). - Gradle distribution integrity is pinned with
distributionSha256Suminjava/gradle/wrapper/gradle-wrapper.properties. .github/workflows/dependency-submission.ymlsubmits the resolved Gradle dependency graph (transitive dependencies and build plugins included) to GitHub onmain; GitHub parses the npm, Composer, Go and Actions manifests itself.- Pull requests get a dependency review gate (
actions/dependency-review-action, high+ in any scope): theTrusted dependency reviewcommit status, computed frommainby.github/workflows/trusted-dependency-review.yml(seeCONTRIBUTING.md); Dependabot alerts covermaincontinuously. - OWASP Dependency-Check scans the full Java dependency set weekly on
main(and on demand) in.github/workflows/security.yml; it is not a pull request gate.
Run from java/:
./gradlew check
./gradlew javadocJar sourcesJar
./gradlew publishToMavenLocalmobilityid4j is published to the Maven Central Portal through the nmcp Gradle plugin; details in java/README.md.
- Java, TypeScript and PHP are released together by the manually dispatched
Releaseworkflow (.github/workflows/release.yml): it validatesCHANGELOG.mdand.github/release-notes/X.Y.Z.md, publishesmobilityid4jto Maven Central,@juherr/mobilityidto npm and thephp/split to thejuherr/mobility-id-phpmirror that Packagist follows, then creates the signedvX.Y.Ztag and the GitHub Release. - Go is released from
go/vX.Y.Ztags (.github/workflows/release-go.yml). - Procedure and required secrets:
CONTRIBUTING.md.
- Repository-level license:
LICENSE - Original Scala license file preserved at:
scala/LICENSE
Many thanks to the original Mobility ID Utils authors and contributors at The New Motion (now Shell Recharge Solutions EU) for creating and open-sourcing the Scala implementation that this repository builds upon.