Technical documentation and specifications for message exchanges between hardware devices and sales clients in bus. All communication is to be done through MQTT with JSON as payload.
Scope of this specification is primarly for Møre og Romsdal Fylkeskommune and FRAM, but the overall ambition is for a broad consensus with other operators and authorities.
Allows client to subscribe to diagnostics from specific device.
Sends diagnostics information for device to sales clients. Could be used by sales clients to show alerts, debug and keep general status of connection information of different devices.
/device/[deviceId]/diagnostics
Devices should respond with diagnostics in two cases: on initial startup and as a response to a diagnostics check. See related topics in next section.
This topic is available for sales clients to subscribe to diagnostics data on specific devices.
/device/diagnostics
/device/diagnostics/request
and
/device/[deviceId]/diagnostics/request
{
"manufacturer": "Acme",
"model": "NFC2000b",
"serial": "F0A222100004",
"firmwareVersion": "0.9.6.0",
"standardVersion": "1.0.0",
"ipAddress": "192.168.99.11",
"label": "front",
"functionality": ["nfc", "barcode"],
"status": "OK",
"statusText": "no errors"
}
{
"manufacturer": "Acme",
"model": "LocOmotive2",
"serial": "LL0A222100004",
"firmwareVersion": "0.9.0.0",
"standardVersion": "1.1.0",
"ipAddress": "192.168.99.12",
"label": "",
"functionality": ["location"],
"status": "OK",
"statusText": "no errors"
}
Accepts the following message:
Diagnostics information for specific device
{
"$schema": "./diagnostics.schema.json",
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"deviceId": "flv202400004",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"manufacturer": "Acme",
"model": "NFC2000b",
"serial": "F0A222100004",
"firmwareVersion": "0.9.6.0",
"standardVersion": "1.0.0",
"ipAddress": "192.168.99.11",
"label": "front",
"functionality": [
"nfc",
"barcode"
],
"status": "OK",
"statusText": "no errors"
}
Request diagnostics from a specific device. Can be called periodically by
polling from sales client. A request will cause a diagnostics event to be passed
from device specidied by deviceId
in topic.
/device/[deviceId]/diagnostics/request
Request diagnostics check from specific device. See related topics in next section.
/device/[deviceId]/diagnostics
/device/diagnostics
/device/diagnostics/request
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z"
}
Accepts the following message:
Request diagnostics check from specific device
{
"$schema": "./request.schema.json",
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z"
}
Sends diagnostics information for device to sales clients. Could be used by sales clients to show alerts, debug and keep general status of connection information of different devices.
/device/diagnostics
Devices should respond with diagnostics in two cases: on initial startup and as a response to a diagnostics check. See related topics in next section.
/device/[deviceId]/diagnostics
/device/diagnostics/request
and
/device/[deviceId]/diagnostics/request
{
"manufacturer": "Acme",
"model": "NFC2000b",
"serial": "F0A222100004",
"firmwareVersion": "0.9.6.0",
"standardVersion": "1.0.0",
"ipAddress": "192.168.99.11",
"label": "front",
"functionality": ["nfc", "barcode"],
"status": "OK",
"statusText": "no errors"
}
{
"manufacturer": "Acme",
"model": "LocOmotive2",
"serial": "LL0A222100004",
"firmwareVersion": "0.9.0.0",
"standardVersion": "1.1.0",
"ipAddress": "192.168.99.12",
"label": "",
"functionality": ["location"],
"status": "OK",
"statusText": "no errors"
}
Accepts the following message:
Diagnostics information on device
{
"$schema": "./diagnostics.schema.json",
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"deviceId": "flv202400004",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"manufacturer": "Acme",
"model": "NFC2000b",
"serial": "F0A222100004",
"firmwareVersion": "0.9.6.0",
"standardVersion": "1.0.0",
"ipAddress": "192.168.99.11",
"label": "front",
"functionality": [
"nfc",
"barcode"
],
"status": "OK",
"statusText": "no errors"
}
Request diagnostics from all connected devices. Can be called periodically by polling from sales client. A request will cause a diagnostics event to be passed from all devices.
/device/diagnostics/request
Request diagnostics check from device. See related topics in next section.
/device/[deviceId]/diagnostics
/device/diagnostics
/device/[deviceId]/diagnostics/request
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z"
}
Accepts the following message:
Request diagnostics check from all devices
{
"$schema": "./request.schema.json",
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z"
}
Provides periodic GPS location data specified in decimal format by latitude and longitude. Should be send once every second. No need for a MQTT QoS guarantee as package loss is acceptable.
/sensors/location
Provided periodic location data.
{
"traceId": "48b12d1f-6b96-4f70-94f9-f785cef96812",
"eventTimestamp": "2023-09-01T23:45:52Z",
"latitudeDegree": 62.734393,
"longitudeDegree": 7.150033,
"altitude": 124,
"messageNumber": 12345,
"speedOverGround": 15.3,
"trackDegreeTrue": 324,
"signalQuality": 1,
"numberOfSatellites": 12,
"hdop": 2.4
}
Specification based on and should be compatible with Ruter specification. As such it it is licensed under Apache License 2.0 and originally created by Ruter AS.
Accepts the following message:
Location sensor data
{
"traceId": "48b12d1f-6b96-4f70-94f9-f785cef96812",
"eventTimestamp": "2023-09-01T23:45:52Z",
"latitudeDegree": 62.734393,
"longitudeDegree": 7.150033,
"altitude": 124,
"messageNumber": 12345,
"speedOverGround": 15.3,
"trackDegreeTrue": 324,
"signalQuality": 1,
"numberOfSatellites": 12,
"hdop": 2.4
}
A method for setting specific configuration for specific device. Can set one or many options at once. Will only overwrite the passed configuration.
validators/[deviceId]/configure
dumpCardMode
: See NFC flow chart for implications of card dump mode.timeout
: Settings for timeout behavior with timout in seconds and message
when it is timed out. Timeout of 0 will be no timeout (not recommended)/validators/[deviceId]/configure/request
/validators/[deviceId]/configure/current
/validators/configure
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"dumpCardMode": true
}
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"timeout": {
"timeInSeconds": 10,
"message": "Ingen kontakt med tjeneste. Gå på bussen"
}
}
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"dumpCardMode": true,
"timeout": {
"timeInSeconds": 10,
"message": "Ingen kontakt med tjeneste. Gå på bussen"
}
}
Accepts the following message:
Set new configuration
{
"$schema": "./configure.schema.json",
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"timeout": {
"timeInSeconds": 10,
"message": "Ingen kontakt med tjeneste. Gå på bussen"
}
}
Subscribe to topic to get list of currently set configuration for specific
device. Payload will be similar to /validators/configure
and
/validators/[deviceId]/configure
.
/validators/[deviceId]/configure/current
/validators/[deviceId]/configure/request
/validators/[deviceId]/configure
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"dumpCardMode": true,
"timeout": {
"timeInSeconds": 10,
"message": "Ingen kontakt med tjeneste. Gå på bussen"
}
}
Accepts the following message:
List of current configuration
{
"$schema": "./current.schema.json",
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"dumpCardMode": true,
"timeout": {
"timeInSeconds": 10,
"message": "Ingen kontakt med tjeneste. Gå på bussen"
}
}
Request currently set configuration from specific device.
/validators/[deviceId]/configure/request
/validators/[deviceId]/configure/current
/validators/[deviceId]/configure
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z"
}
Accepts the following message:
Request current configuration
{
"$schema": "./request.schema.json",
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z"
}
Response sent after finished validation on client. Response can be both success, fail and error. In the current specification the response method is limited to a variant type/enum, and it's up to the device to handle the proper response in form of icon, color and sound.
Device should optionally recieve title and description if supported by the device.
validators/[deviceId]/response
{
"traceId": "48b12d1f-6b96-4f70-94f9-f785cef96812",
"eventTimestamp": "2023-09-01T23:45:52Z",
"result": {
"title": "Godkjent",
"description": "Validert 22/04/2020 13:19 Enkeltbillett 1 Voksen ",
"validity": "VALID"
}
}
Accepts the following message:
Response sent to devices after inspection result has been found.
{
"traceId": "48b12d1f-6b96-4f70-94f9-f785cef96812",
"eventTimestamp": "2023-09-01T23:45:52Z",
"result": {
"validity": "VALID"
}
}
Passenger want to use the service and presents their barcode containing a token referencing an account containing possible travel rights.
Barcode should be transmitted as base64 encoded URL string without padding.
validators/barcode
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"deviceId": "flv202400004",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"barcode": "CtYBCtMBCtN...VDRFNBKgsIpdicoAYQ4NeUdzAB"
}
Accepts the following message:
A barcode containing account tokens to be validated.
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"deviceId": "flv202400004",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"barcode": "CtYBCtMBCtN...VDRFNBKgsIpdicoAYQ4NeUdzAB"
}
A method for setting configuration for all device at once. Can set one or many options at once. Will only overwrite the passed configuration.
validators/configure
dumpCardMode
: See NFC flow chart for implications of card dump mode.timeout
: Settings for timeout behavior with timout in seconds and message
when it is timed out. Timeout of 0 will be no timeout (not recommended)/validators/configure/request
/validators/configure/current
/validators/[deviceId]/configure
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"dumpCardMode": true
}
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"timeout": {
"timeInSeconds": 10,
"message": "Ingen kontakt med tjeneste. Gå på bussen"
}
}
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"dumpCardMode": true,
"timeout": {
"timeInSeconds": 10,
"message": "Ingen kontakt med tjeneste. Gå på bussen"
}
}
Accepts the following message:
Set new configuration
{
"$schema": "./configure.schema.json",
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"timeout": {
"timeInSeconds": 10,
"message": "Ingen kontakt med tjeneste. Gå på bussen"
}
}
Subscribe to topic to get list of currently set configuration for specific
device. Payload will be similar to /validators/configure
and
/validators/[deviceId]/configure
.
/validators/configure/current
/validators/[configure/request
/validators/configure
/validators/[deviceId]/configure/current
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"dumpCardMode": true,
"timeout": {
"timeInSeconds": 10,
"message": "Ingen kontakt med tjeneste. Gå på bussen"
}
}
Accepts the following message:
List of current configuration
{
"$schema": "./current.schema.json",
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"dumpCardMode": true,
"timeout": {
"timeInSeconds": 10,
"message": "Ingen kontakt med tjeneste. Gå på bussen"
}
}
Request currently set configuration from all devices.
/validators/configure/request
/validators/configure/current
/validators/configure
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z"
}
Accepts the following message:
Request current configuration
{
"$schema": "./request.schema.json",
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"eventTimestamp": "2023-04-22T10:28:37.337Z"
}
When a passenger intends to use the service, they present their travel card, which may have a token referencing an account with corresponding travel rights. In cases where there is no token present, the serial number of the travel card will be used. If there is a customer account associated with that serial number, a potential token will be generated and written back to the travel card. See diagram for total flow.
Token should be transmitted as base64 encoded URL string without padding.
validators/nfc
If the device is configured accordingly, the complete content of the card can be
transferred from the device, as depicted in the flow chart. This simplifies the
client's perspective as it enables direct access to the card's content. Please
refer to the validators/configure
topic for the configuration flag that
determines whether cardContent
is set. Below are examples demonstrating the
scenarios when cardContent
is enabled.
This concept is applicable in situations where the smart card holds various types of travel rights and there is a requirement to prioritize among them. Examples of such types include NOD (Name Origin Destination), account-based, and others.
Only supported type for now is nsd
and that needs to be set as type
, for
future proofing when new types are added.
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"deviceId": "flv202400004",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"travelCardNumber": "323116753",
"token": "CtYBCtMBCtN...VDRFNBKgsIpdicoAYQ4NeUdzAB"
}
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"deviceId": "flv202400004",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"travelCardNumber": "323116753",
"cardContent": [
{
"appId": "<ID>",
"type": "nsd",
"files": [{ "fileNumber": "<FileNumber>", "content": "0x0032" }]
}
]
}
flowchart TD
A[Customer shows card] --> B(NFC device\nreads card)
B --> B1{Is supported card?}
B1 -->|no| ResponseInvalid_0[Built in response:\n Not valid]
B1 -->|Yes| C{Device contains\naccess keys}
C -->|Yes| AC1_Dump{Is dump card content\nconfig active?}
AC1_Dump -->|Yes| AC1_Dump_1(Read entire\ncard content)
AC1_Dump_1 -->|/validators/nfc|AC4
AC1_Dump -->|No| AC1(Read card,\nfetch NSD serial number and\npotential token)
AC1 --> AC2{Is token\non card?}
AC2 -->|Yes| AC3(Read token)
AC3 -->|/validators/nfc| AC4{Does token\nexists at Provider?}
AC4 -->|Yes| AC5(Validate Token)
AC5 -->|"/validators/[deviceId]/response"| AC6[Show response\nto customer]
AC4 -->|Blocked/removed| AC7(APDU Subprocess\nRemove token from card)
AC7 -->|"/validators/[deviceId]/response"| ResponseInvalid
C -->|No| NAC1(Fetch NSD serial number)
NAC1 -->|/validators/nfc| NAC2(APDU Subprocess\nFetch token)
NAC2 --> NAC3{Is token\non card?}
AC2 -->|No| AC2_Get(Send only serial number)
AC2_Get -->|/validators/nfc| NoToken(Get token from\nserial number)
NAC3 -->|No| NoToken
NAC3 -->|Yes| NACToken1{Does token\nexists at Provider?}
NACToken1 -->|Blocked/removed| NACToken1No(APDU Subprocess\nRemove token from card)
NACToken1No -->|"/validators/[deviceId]/response"| NACToken1NoResponse[Show response\nto customer]
NoToken --> FetchTokenStatus{Does token\nexists at Provider?}
FetchTokenStatus-->|Blocked/removed| FetchTokenInvalid(No valid travel right)
FetchTokenStatus-->|Not found| FetchTokenInvalid
FetchTokenInvalid -->|"/validators/[deviceId]/response"| ResponseInvalid[Show response:\n Not valid]
FetchTokenStatus-->|Found| FetchTokenFound(APDU Subprocess:\nWrite token to card)
FetchTokenFound -->|Yes| FetchTokenFoundValidate(Validate Token)
FetchTokenFoundValidate -->|"/validators/[deviceId]/response"| FetchTokenResponse[Show response\nto customer]
NACToken1 -->|Found| FetchTokenFoundValidate
apdu
topics for communication and data exchange.Accepts the following message:
Validating NFC card containing account tokens to be validated.
{
"$schema": "./nfc.schema.json",
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"deviceId": "flv202400004",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"travelCardNumber": "323116753",
"token": "CtYBCtMBCtN...VDRFNBKgsIpdicoAYQ4NeUdzAB",
"cardContent": [
{
"appId": "<ID>",
"type": "nsd",
"files": [
{
"fileNumber": "<FileNumber>",
"content": "0x0032"
}
]
}
]
}
Transmit series of APDU commands in hexadecimals. Each command with an specified
ID. Commands will generate response passed from device to client on topic
validators/apdu/receive
with corresponding commandId
.
APDU commands can be used to read or write specific values from travel cards or other NFC based devices.
transceiveId
can be used to link transmit
and receive
events.
eventTimestamp
is the time the command transmit request is generated.
validators/nfc/apdu/[deviceId]/transmit
All commands should be represented as hex, starting with 0x. See examples. Expected status is optional. If result of executing command does not match expected status prefix, result is ommited in the receive event.
0xAF
and continuationContinuation on 0xAF
is handled implicitly if expStatus
is set as 0x00
,
depending on apdu type. See description below.
expStatus=0x00
or empty and first bytes in response indicates more data
(0xAF
) the device should fetch all data until end and give result as
concatinated byte array.expStatus=0xAF
is transmitted it is not handled automatically by the
device.See related transmit topic: validators/nfc/apdu/receive
.
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"deviceId": "flv202400004",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"transceiveId": "c28f206d-8016-4d22-b21b-70d8d6d2fea4",
"apduType": "desfire",
"command": [
{ "commandId": 1, "frame": "0x0080", "expStatus": "0x00" },
{ "commandId": 2, "frame": "0x000000100000", "expStatus": "0x00" },
{ "commandId": 3, "frame": "0x0180", "expStatus": "0x00" },
{ "commandId": 4, "frame": "0x07", "expStatus": "0x00" }
]
}
Link to APDU-documentation.
Accepts the following message:
Transmit sequence of APDU commands
{
"$schema": "./transmit.schema.json",
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"deviceId": "flv202400004",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"transceiveId": "c28f206d-8016-4d22-b21b-70d8d6d2fea4",
"apduType": "desfire",
"command": [
{
"commandId": 1,
"frame": "0x0080",
"expStatus": "0x00"
},
{
"commandId": 2,
"frame": "0x000000100000",
"expStatus": "0x00"
},
{
"commandId": 3,
"frame": "0x0180",
"expStatus": "0x00"
},
{
"commandId": 4,
"frame": "0x07",
"expStatus": "0x00"
}
]
}
Recieve result from commands passed through transmit topic. Will contain list of
results corresponding to the results transmitted, with the same specified
commandId
s.
transceiveId
can be used to link transmit
and receive
events.
eventTimestamp
is the time the first command result is generated.
validators/nfc/apdu/receive
All result frames should be represneted as hex, starting with 0x. See examples. If result of executing command does not match expected status prefix passed in the transmit event, result should be ommited.
0xAF
and continuationContinuation on 0xAF
is handled implicitly if expStatus
as passed in by
transmit is set as 0x00
. See description below.
expStatus=0x00
or empty and first bytes in response indicates more data
(0xAF
) the device should fetch all data until end and give result as
concatinated byte array.expStatus=0xAF
is transmitted it is not handled automatically by the
device.See related transmit topic:
validators/nfc/apdu/[deviceId]/transmit
.
{
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"deviceId": "flv202400004",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"transceiveId": "c28f206d-8016-4d22-b21b-70d8d6d2fea4",
"apduType": "desfire",
"result": [
{ "commandId": 1, "frame": "0x00" },
{ "commandId": 2, "frame": "0x0090800002000280" },
{ "commandId": 3, "frame": "0x00" },
{ "commandId": 4, "frame": "" }
]
}
Link to APDU-documentation.
Accepts the following message:
APDU results given on specific transceiveId
{
"$schema": "./receive.schema.json",
"traceId": "543070fe-ef32-11ed-a05b-0242ac120003",
"deviceId": "flv202400004",
"eventTimestamp": "2023-04-22T10:28:37.337Z",
"transceiveId": "c28f206d-8016-4d22-b21b-70d8d6d2fea4",
"apduType": "desfire",
"result": [
{
"commandId": 1,
"frame": "0x00"
},
{
"commandId": 2,
"frame": "0x0090800002000280"
},
{
"commandId": 3,
"frame": "0x00"
},
{
"commandId": 4,
"frame": ""
}
]
}