ShellRechargeSolutionsEU / mobilityid

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Mobility ID Utils Build Status

About the library

Scala utils to parse, validate and convert electric mobility account identifier strings according to the ISO 15118-1, DIN SPEC 91286 & EMI3 standards.

Where to get it

To get the latest version of the library, publish the library to a repository and add the following to your SBT build:

And use the following library dependency:

libraryDependencies += "com.thenewmotion" %% "mobilityid" % "1.0.0"

How to use

Contract Id

There are 3 types of Contract Id:

  • DIN SPEC 91286, also known as EVCO-ID, e.g. NL-TNM-012204-5
  • ISO 15118-1, also known as EMA-ID, e.g. NL-TNM-000122045-U
  • EMI3, e.g. NL-TNM-C00122045-K

You can create an Contract Id object from a string in any of the 3 formats. If you supply a check digit, it will be validated. If it is not supplied, it will be calculated.

mobilityid> project core
mobilityid> console
scala> import com.thenewmotion.mobilityid._
import ContractIdStandard._

scala> ContractId[DIN]("NL-TNM-012204-5")
res1: com.thenewmotion.mobilityid.ContractId[com.thenewmotion.mobilityid.ContractIdStandard.DIN] = NL-TNM-012204-5

scala> ContractId[ISO]("NL-TNM-000122045")
res2: com.thenewmotion.mobilityid.ContractId[com.thenewmotion.mobilityid.ContractIdStandard.ISO] = NL-TNM-000122045-U

scala> ContractId[EMI3]("NL-TNM-C00122045")
res3: com.thenewmotion.mobilityid.ContractId[com.thenewmotion.mobilityid.ContractIdStandard.EMI3] = NL-TNM-C00122045-K

This fails because of an illegal character:

scala> ContractId[ISO]("NL-T|M-000122045")
java.lang.IllegalArgumentException: NL-T|M-000122045 is not a valid Contract Id for ISO 15118-1

If you have more detailed field information you can create a ContractId from the separate fields, choosing whether to supply a check digit:

scala> ContractId[ISO]("NL", "TNM", "000122045")
res4: com.thenewmotion.mobilityid.ContractId[com.thenewmotion.mobilityid.ContractIdStandard.ISO] = NL-TNM-000122045-U

scala> ContractId[ISO]("NL", "TNM", "000122045", 'U')
res5: com.thenewmotion.mobilityid.ContractId[com.thenewmotion.mobilityid.ContractIdStandard.ISO] = NL-TNM-000122045-U

This fails because of an invalid check digit:

scala> ContractId[ISO]("NL", "TNM", "000122045", 'X')
java.lang.IllegalArgumentException: Given check digit 'X' is not equal to computed 'U'

This fails because of an illegal character:

scala> ContractId[ISO]("NL", "T|M", "000122045")
java.lang.IllegalArgumentException: OperatorId must have a length of 3 and be ASCII letters or digits

Once you have an ContractId object you can convert it to another format:

scala> ContractId[ISO]("NL-TNM-000122045").convertTo[DIN]
res1:  com.thenewmotion.mobilityid.ContractId[com.thenewmotion.mobilityid.ContractIdStandard.DIN] = NL-TNM-012204-5

scala> ContractId[DIN]("NL-TNM-012204-5").convertTo[EMI3]
res2: com.thenewmotion.mobilityid.ContractId[com.thenewmotion.mobilityid.ContractIdStandard.EMI3] = NL-TNM-C00122045-K

Also you can print them in various formats

scala> val contractId = ContractId[ISO]("NL", "TNM", "012345678")
contractId: com.thenewmotion.mobilityid.ContractId[com.thenewmotion.mobilityid.ContractIdStandard.ISO] = NL-TNM-012345678-W

scala> contractId.toCompactString
res10: String = NLTNM012345678W

scala> contractId.toCompactStringWithoutCheckDigit
res11: String = NLTNM012345678

scala> contractId.toString
res12: String = NL-TNM-012345678-W

And you can get the party ID ("NL-TNM") which you can use to map a Contract Id to the provider that issued the token:

scala> contractId.partyId
res13: com.thenewmotion.mobilityid.PartyId = NL-TNM
Notes

This library is using the algorithm of check digit calculation for ISO 15118-1 Contract IDs described here: http://www.ochp.eu/id-validator/e-mobility-ids_evcoid_check-digit-calculation_explanation/

Changelog

ContractId[ISO] is roughly equivalent to the old EmaId class.

EmaId could parse both DIN and ISO format, converting the former to the latter on the fly, e.g.

scala> EmaId("NL-TNM-012204-5")
res0: com.thenewmotion.mobilityid.EmaId = NL-TNM-000122045-U

This will fail if replaced with ContractId[ISO] directly:

scala> ContractId[ISO]("NL-TNM-012204-5")
java.lang.IllegalArgumentException: NL-TNM-012204-5 is not a valid Contract Id for ISO 15118-1

It is now necessary to parse the DIN and convert it to another format, e.g.

scala> ContractId[DIN]("NL-TNM-012204-5").convertTo[ISO]
res0: com.thenewmotion.mobilityid.ContractId[com.thenewmotion.mobilityid.ContractIdStandard.ISO] = NL-TNM-000122045-U

Note that conversion from DIN to ISO format (as defined at https://github.com/e-clearing-net/OCHP/blob/master/OCHP.md#contractid-or-evco-id) is deprecated, and it is better to convert from DIN to EMI3 (as defined at http://emi3group.com/documents-links/)

scala> ContractId[DIN]("NL-TNM-012204-5").convertTo[EMI3]
res1: com.thenewmotion.mobilityid.ContractId[com.thenewmotion.mobilityid.ContractIdStandard.EMI3] = NL-TNM-C00122045-K

EVSE-ID

You can create an EvseId object from a string in ISO 15118-1 or DIN SPEC 91286 format:

scala> import com.thenewmotion.mobilityid._
import com.thenewmotion.mobilityid._

scala> EvseId("NL*TNM*E01225045")
res1: Option[com.thenewmotion.mobilityid.EvseId] = Some(NL*TNM*E01225045)

scala> EvseId("NLTNME01225045")
res2: Option[com.thenewmotion.mobilityid.EvseId] = Some(NL*TNM*E01225045)

scala> EvseId("+31*734*7734634")
res3: Option[com.thenewmotion.mobilityid.EvseId] = Some(31*734*7734634)

This fails because of an illegal character:

scala> EvseId("NL*T|M*E01225045")
res4: Option[com.thenewmotion.mobilityid.EvseId] = None

If you have more detailed field information you can create an EvseId from the separate fields:

scala> EvseId("NL", "TNM", "E000122045")
res5: com.thenewmotion.mobilityid.EvseId = NL*TNM*E000122045

scala> EvseId("+31", "734", "000122045")
res6: com.thenewmotion.mobilityid.EvseId = +31*734*000122045

This fails because of an illegal character in the operator id for DIN format:

scala> EvseId("+31", "7A4", "000122045")
java.lang.IllegalArgumentException: Invalid operatorId for DIN format

This fails because powerOutletId must begin with 'E' when using ISO format

scala> EvseId("NL", "TNM", "000122045")
java.lang.IllegalArgumentException: Invalid powerOutletId for ISO format

You can pattern match on whether the EVSEId is of ISO or DIN format:

scala> def getFormat(e: EvseId) = e match { case _: EvseIdIso => "IsIso" case _: EvseIdDin => "IsDin" }
getFormat: (e: com.thenewmotion.mobilityid.EvseId)String

scala> val evseIdIso = EvseId("NL", "TNM", "E000122045")
evseIdIso: com.thenewmotion.mobilityid.EvseId = NL*TNM*E000122045

scala> getFormat(evseIdIso)
res7: String = IsIso

scala> val evseIdDin = EvseId("+31", "734", "000122045")
evseIdDin: com.thenewmotion.mobilityid.EvseId = +31*734*000122045

scala> getFormat(evseIdDin)
res8: String = IsDin

Also you can print them in full format or compact format (only ISO standard):

scala> val evseIdIso = EvseId("NL", "TNM", "E000122045")
evseIdIso: com.thenewmotion.mobilityid.EvseId = NL*TNM*E000122045

scala> evseIdIso.toString
res9: String = NL*TNM*E000122045

scala> evseIdIso match { case e: EvseIdIso => e.toCompactString }
res10: String = NLTNME000122045

scala> val evseIdDin = EvseId("+31", "734", "000122045")
evseIdDin: com.thenewmotion.mobilityid.EvseId = +31*734*000122045

scala> evseIdDin.toString
res11: String = +31*734*000122045

And you can get the party ID ("NL-TNM") which you can use to map an EVSE-ID to the operator of the EVSE (only ISO standard):

scala> evseIdIso.partyId
res12: com.thenewmotion.mobilityid.PartyId = NL-TNM
Notes

It is NOT possible to compare two EvseId objects where one is DIN format the other is ISO, as the 2 formats use different country identifiers and different operator codes

Party ID

As noted above, the library can give you PartyId instances representing the party that issued a token or operates an EVSE. You can also creates instances of these from a String, so you can check if a certain token comes from a known provider like this:

scala> import com.thenewmotion.mobilityid.PartyId
import com.thenewmotion.mobilityid.PartyId

scala> val newMotionNetherlands = PartyId("NL*TNM").get
newMotionNetherlands: com.thenewmotion.mobilityid.PartyId = NL-TNM

scala> ContractId[ISO]("NL", "TNM", "000122045").partyId == newMotionNetherlands
res4: Boolean = true

scala> ContractId[ISO]("DE", "8LN", "000001292").partyId == newMotionNetherlands
res5: Boolean = false

Interpolators module

Can be imported with this dependency

libraryDependencies += "com.thenewmotion" %% "mobilityid-interpolators" % "1.0.0"

then it can be used like this:

scala> import com.thenewmotion.mobilityid.interpolators._
import com.thenewmotion.mobilityid.interpolators._

scala> evseId"ABC"
<console>:11: error: not a valid EvseId
              evseId"ABC"
                     ^

scala> evseId"NL*TNM*E840*6487"
res2: com.thenewmotion.mobilityid.EvseId = NL*TNM*E840*6487

scala> contractIdISO"ooopsie"
<console>:11: error: ooopsie is not a valid Contract Id for ISO 15118-1
                     contractIdISO"ooopsie"

scala> contractIdISO"NL-TNM-000722345-X"
res4: com.thenewmotion.mobilityid.ContractId[com.thenewmotion.mobilityid.ContractIdStandard.ISO] = NL-TNM-000722345-X

About

License:Other


Languages

Language:Scala 100.0%