Clipper - metrodroid/metrodroid GitHub Wiki

Clipper is a MIFARE DESFire based public transit ticketing system in use by multiple agencies in San Francisco (and the greater Bay Area), CA, USA.
The system was originally developed as TransLink by ERG and Motorola (many fareboxes in use bare ERG logos), but since launch is administered by Cubic (value-add machines are of a standard Cubic design, similar to those in Los Angeles and Brisbane).
Clipper uses a different card format to other Cubic and ERG systems.
All values on the card are big-endian, and timestamps are stored as seconds since 1900-01-01 00:00:00 UTC.
All data is in application ID 0x9011f2.
Support for this card was mostly inherited from Farebot. Compatibility with original TransLink cards is unknown. Travel passes are not yet supported.
File 0x1 (Card Metadata)
| First | Last | Length | Field description |
|---|---|---|---|
| 8 | 9 | 2 | Card expiry date, in days since 1900-01-01 |
File 0x2 (Balance)
| First | Last | Length | Field description |
|---|---|---|---|
| 4 | 7 | 4 | Last use timestamp |
| 18 | 19 | 2 | Card balance (cents) |
File 0x4 (Refills)
Refill records are 32 bytes long. Each record has the following format:
| First | Last | Length | Field description |
|---|---|---|---|
| 2 | 3 | 2 | Transit agency |
| 4 | 7 | 4 | Timestamp |
| 8 | 11 | 4 | Machine ID (on receipts, this is shown in hex) |
| 14 | 15 | 2 | Refill amount (in cents) |
File 0x5
Probably a pointers file
File 0x6
Probably a pointers file
File 0x8
| First | Last | Length | Field description |
|---|---|---|---|
| 0 | 0 | 1 | Const 0x1 |
| 1 | 4 | 4 | Serial |
| 5 | 5 | 1 | Const 0x1 |
| 6 | 7 | 2 | Zero-filled |
| 8 | 8 | 1 | Const 0xf (Ticket type?) |
| 9 | 31 | 23 | Zero-filled |
File 0xe (Trips)
Trip records are 32 bytes long.
Each trip contains 1 or 2 records corresponding to it -- one which has only an entry timestamp and station ID, but may also have one with an exit timestamp and station ID. Only certain transit modes require "tapping off" when exiting a station (eg: Caltrain).
Each record has the following format:
| First | Last | Length | Field description |
|---|---|---|---|
| 1 | 1 | 1 | Transfer counter |
| 2 | 3 | 2 | Transit agency |
| 4 | 2 | 2 | Something about transfers |
| 6 | 7 | 2 | Fare (in cents) |
| 8 | 9 | 2 | Pointer to validation/subscription |
| 10 | 11 | 2 | Vehicle number |
| 12 | 15 | 4 | Entry timestamp |
| 16 | 19 | 4 | Exit timestamp (optional) |
| 20 | 21 | 2 | Entry station ID |
| 22 | 23 | 2 | Exit station ID (optional) |
| 28 | 29 | 2 | Route ID |
| 30 | 31 | 2 | Transport code |
File 0xf (Validations and subscriptions and partial trips)
Validation records are 32 bytes long.
Bytes 2 and 3 determine the format
Format 7000:
| First | Last | Length | Field description |
|---|---|---|---|
| 0 | 1 | 2 | 2000 (tag-on) or 20f0 (tag-off) |
| 2 | 3 | 2 | 7000 |
| 4 | 5 | 2 | date + 1806 days = almost 5 years (some kind of expiry?), in days since 1900-01-01 |
| 6 | 7 | 2 | ff-filled |
| 8 | 11 | 4 | Entry timestamp |
| 12 | 13 | 2 | Entry station ID |
| 14 | 31 | 18 | ff-filled |
Format 8000:
| First | Last | Length | Field description |
|---|---|---|---|
| 0 | 1 | 2 | 2000 |
| 2 | 3 | 2 | 3000 |
| 4 | 5 | 2 | Some date in the future, in days since 1900-01-01 |
| 14 | 15 | 2 | Some date in the past, in days since 1900-01-01 |
BART station assignment
It looks like the numbers were first assigned on year 2000 map of BART.
See https://commons.wikimedia.org/wiki/File:Revised_BART_map.svg
It starts with Colma and follows Yellow line to Pittsburg
| Number | Station |
|---|---|
| 0x01 | Colma |
| 0x02 | Daly City |
| 0x03 | Balboa Park |
| 0x04 | Glen Park |
| 0x05 | 24st/Mission |
| 0x06 | 16st/Mission |
| 0x07 | Civic Center |
| 0x08 | Powell St. |
| 0x09 | Montgomerry |
| 0x0a | Embarcadero |
| 0x0b | West Oakland |
| 0x0c | 12st/Oakland city center |
| 0x0d | 19st/Oakland |
| 0x0e | MacArthur |
| 0x0f | Rockridge |
| 0x10 | Orinda |
| 0x11 | Lafayette |
| 0x12 | Walnut Creek |
| 0x13 | Pleasant Hill |
| 0x14 | Concord |
| 0x15 | North Concord/Martinez |
| 0x16 | Pittsburg/Bay Point |
0x10 and 0x16 are unconfirmed
Then it continues at branching point of orange/red line from yellow line (Ashby) and continues to Richmond
| Number | Station |
|---|---|
| 0x17 | Ashby |
| 0x18 | Downtown Berkeley |
| 0x19 | North Berkeley |
| 0x1a | El Cerrito Plaza |
| 0x1b | El Cerrito del Norte |
| 0x1c | Richmond |
Then it continues at branching point of orange/green line from yellow line (Lake Meritt) and continues to Fremont.
| Number | Station |
|---|---|
| 0x1d | Lake Meritt |
| 0x1e | Fruitvale |
| 0x1f | Coliseum |
| 0x20 | San Leandro |
| 0x21 | Bay Fair |
| 0x22 | Hayward |
| 0x23 | South Hayward |
| 0x24 | Union City |
| 0x25 | Fremont |
However our database doesn't match it on 0x20 and 0x21 - likely an error in database
Then it logically should continue with blue line to Dublin/Pleasanton
| Number | Station |
|---|---|
| 0x26 | Castro Valley |
| 0x27 | Dublin/Pleasanton |
However our database doesn't match it on 0x26 - likely an error in database Then it goes on to the other direction from Colma station following yellow line to SFO
| Number | Station |
|---|---|
| 0x28 | South San Francisco |
| 0x29 | San Bruno |
| 0x2a | San Francisco International airport |
Then it goes on to blue/red line branching:
| Number | Station |
|---|---|
| 0x2b | Millbrae |
Then it follows newer station added as they were constructed:
| Number | Station |
|---|---|
| 0x2c | West Dublin/Pleasanton (February 2011) |
| 0x2d | Oakland airport station (November 2014) |
| 0x2e | Warm Springs/South Fremont (March 2017) |
| 0x2f | Pittsburg Center (May 2018) |
| 0x30 | Antioch (May 2018) |
However 0x2e, 0x2f and 0x30 are unconfirmed
Single-trip
Single-trips are per-agency. Most buses give at most a paper receipt. BART, Caltrain and VTA use magnetic card for single trip. So far the only NFC single-ride ticket are Muni's and GGF's "Paper Clipper" on Mifare Ultralight. Its format is a mixture between Clipper and Cubic MFU structures.
General structure
| Page | Purpose |
|---|---|
| 0-2 | Manufacturer data |
| 3 | Serial-number, big endian |
| 4-5 | Header |
| 6-10 | Transaction 1 |
| 11-15 | Transaction 2 |
Header
All offsets are in bits, big-endian
| First | Length | Last | Value |
|---|---|---|---|
| 0 | 8 | 7 | Always 0x13 |
| 8 | 8 | 15 | Ticket type |
| 16 | 16 | 31 | ?? |
| 32 | 16 | 47 | Product code |
| 48 | 16 | 63 | Base/Expiry date, in days since 1990 |
Transaction
All offsets are in bits, big-endian
| First | Length | Last | Value |
|---|---|---|---|
| 0 | 7 | 6 | Transaction counter |
| 7 | 17 | 23 | Transaction type |
| 24 | 17 | 40 | Transaction time, in minutes before base day |
| 41 | 17 | 57 | Station ID |
| 58 | 10 | 67 | ??? |
| 68 | 5 | 73 | Agency ID |
| 74 | 6 | 79 | ??? |
| 80 | 4 | 83 | Balance sequence counter |
| 84 | 6 | 89 | Number of remaining trips |
| 90 | 10 | 99 | ??? |
| 100 | 10 | 109 | Transfer expiry timestamp |
| 110 | 18 | 127 | ??? |
| 128 | 32 | 159 | Hash |