velotrain


Namevelotrain JSON
Version 1.0.3 PyPI version JSON
download
home_pageNone
SummaryVelodrome transponder training timing
upload_time2025-07-23 01:59:47
maintainerNone
docs_urlNone
authorNone
requires_python>=3.11
licenseNone
keywords velodrome transponder timing
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # velotrain

velotrain reads raw transponder passing information from a set
of up to 9 measurement points, filters the messages according
to track configuration parameters and then emits valid timing
measurements as JSON-encoded objects to MQTT.


## Operation

The velodrome is divided into a closed loop of timing sectors
by measurement points at each of the interesting offsets, for example:

   - Finish line
   - 200m Start
   - Pursuit B
   - Pursuit A

A rider is considered to be in a 'run' if their speed over any
configured sector (eg Finish line to 200m start) is between
configured values (default: 30 km/h to 90 km/h).
Passings emitted for a rider in a run will include any available
lap, half-lap, quarter-lap, 100 m, and 50 m splits.
Rider passings slower or faster than the configured limits are
considered isolated, and will be reported without splits.

Where possible, valid raw passings received out of order will be
corrected and re-ordered before being emitted. In the case that
an isolated raw passing violates the configured track ordering and 
speed limits, it may be reported out of order.

For a Protime active/passive dual loop configuration, riders
will not be registered at all until they are moving faster than
about 30 km/h, no matter what software limits have been configured.


## Configuration

Track layout, system transponder ids and speed limits are configured
using a metarace jsonconfig entry with the section 'velotrain' and the
following keys:

   - authkey: (string) reset authorisation string, default: null
   - gate: (string) transponder ID for start gate, default: null
   - gatedelay: (string) trigger delay for start gate, default: '0.075' _[1]_
   - gatesrc: (string) channel start gate reports to eg 'C2', default: null
   - laplen: (float) lap length in metres, default: 250.0
   - maxspeed: (float) maximum sector speed in km/d, default: 90.0
   - minspeed: (float) minimum sector speed in km/h, default: 38.0
   - moto: (list) list of transponder IDs attached to motos, default: []
   - trig: (string) transponder ID of sync trigger messages, default: '255'
   - passlevel: (integer) minimum accepted passing level, default 40 _[2]_
   - uaddr: (string) UDP host listen address, default ''
   - uport: (integer) UDP host port, default: 2008
   - bcast: (string) broadcast address for timing LAN,
     default: '255.255.255.255'
   - basetopic: (string) base topic for telegraph interface,
     default: 'velotrain'
   - sync: (string) channel of synchronisation master unit, default: null
   - mingate: (float) minimum accepted speed in km/h over the
     start gate sector, default: 9.0
   - maxgate: (float) maximum accepted speed in km/h over the
     start gate sector, default: 22.5
   - dhi: (list) ['address', port] DHI port for Caprica scoreboard,
     default: null
   - dhiencoding: (string) text encoding for DHI messages, default: 'utf-8'
   - mpseq: (list) ordering of channels on the track,
     default: ['C1', 'C9', 'C4', 'C6', 'C3', 'C5', 'C7', 'C8', 'C2'] _[3]_
   - mps: (dict) mapping of channel IDs to measurement point configs,
     default: {} _[4]_

Configured measurement points divide the track into a closed loop of
timing sectors, with a set of splits at each measurement point.
Measurement point config entries have the following options, omitted keys
receive a default value:

   - name: (string) visible name of the measurement point,
     default: channel ID
   - ip: (string) IP address of connected Protime decoder,
     default: null _[4]_
   - offset: (float) distance in metres from finish line to measurement 
     point, default: null
   - half: (string) channel ID corresponding to a half lap before this unit,
     default: null
   - qtr: (string) channel ID corresponding to quarter lap before this unit,
     default: null
   - 200: (string) channel ID corresponding to 200 m before this unit,
     default: null
   - 100: (string) channel ID corresponding to 100 m before this unit,
     default: null
   - 50: (string) channel ID corresponding to 50 m before this unit,
     default: null

Notes:

   1. 0.075 seconds is LS transponder delay when triggered by
      start gate release
   2. Sets the 'level' option in all attached Protime decoder units
   3. Default channel ordering matches trackmeet, all configured units
      must appear once in this sequence, however the sequence may contain
      more channels than are configured.
   4. Measurement points require a non-null IP entry to be configured.
      For use with foreign timers, set the IP to be an empty string: ''.
      Refer to the sample velomon.json for an example setting


## Telegraph (MQTT) Interface

The topics below are relative to the configured basetopic (default:
'velotrain'), from the perspective of the velotrain process. For
all JSON encoded objects, invalid or unavailable properties will be
reported as null.


### passing (publish)

Issue filtered and accepted passing records. Passing records
are JSON encoded objects with the following properties:

   - index : (integer) index of the passing record (reset to 0 each day)
   - date: (string) Date of the passing formatted YYYY-MM-DD
   - time: (string) Time of day of the passing formatted HH:MM:SS.dcm
   - mpid: (integer) Measurement point ID 0 - 9
   - refid: (string) Transponder ID or system passing ID 'gate', 'moto'
     or 'marker'
   - env: (list) [temperature, humidity, pressure] where each value
     is a float value in units degrees Celsius, %rh, and hPa respectively
   - moto: (string) Proximity to moto in seconds if drafted
   - elap: (string) Elapsed time since last start gate or start of run
     formatted HH:MM:SS.dc
   - lap: (string) Time for the last full lap to the measurement point
   - half: (string) Time for the last half lap to the measurement point
   - qtr: (string) Time for the last quarter lap to the measurement point
   - 200: (string) Time for the last 200m to the measurement point
   - 100: (string) Time for the last 100m to the measurement point
   - 50: (string) Time for the last 50m to the measurement point
   - text: (string) Name of measurement point, or user-supplied text
     for markers

Example: A moto passing over the 100m split at about 4:18pm

	Topic:		velotrain/passing
	Payload:	{"index": 108, "date": "2022-07-06",
			 "time": "16:18:32.300", "mpid": 5,
			 "refid": "moto", "env": [16.3, 55.0, 1015.0],
			 "moto": "0.00", "elap": "2:10.51",
			 "lap": "22.95", "half": null, "qtr": null,
			 "200": "18.32", "100": "9.07", "50": "4.52",
			 "text": "100m Split"}

### rawpass (publish)

Issue raw, unprocessed passing records as received from decoders. Raw
passing records are JSON encoded objects with the following properties:

   - date: (string) Date of the raw passing formatted YYYY-MM-DD
   - time: (string) Time of day of the passing formatted HH:MM:SS.dc
   - rcv: (string) Time of day passing was received by host system,
     formatted HH:MM:SS.dcm
   - mpid: (integer) Measurement point ID 0 - 9
   - refid: (string) Raw transponder ID
   - env: (list) [temperature, humidity, pressure] where each value
     is a float value in units degrees Celsius, %rh, and hPa respectively
   - name: (string) Name of measurement point
   - info: (string) Extra information provided by decoder

Example: The raw passing that might have generated the above moto passing

	Topic:		velotrain/rawpass
	Payload:	{"date": "2022-07-06", "env": [16.3, 55.0, 1015.0],
			 "refid": "125328", "mpid": 5,
			 "name": "100m Split", "time": "16:18:32.303",
			 "rcv": "16:18:32.459"}

### status (publish)

Issue system and measurement point status records at the top of each
minute. Status records are JSON encoded objects with the following properties:

   - date: (string) Date of the status record formatted YYYY-MM-DD
   - time: (string) Time of day status was issued formatted HH:MM:SS.dc
   - offset: (string) Rough offset of system clock to UTC
   - count: (integer) Count of passing records
   - env: (list) [temperature, humidity, pressure] where each value
     is a float value in units degrees Celsius, %rh, and hPa respectively
   - gate: (string) Time of day of last gate trigger HH:MM:SS.dc
   - battery: (list) List of transponder refids that have reported a low
     battery warning since the last system reset
   - info: (string) Status info, one of: 'running', 'resetting',
     'error', 'offline' _[1]_
   - units: (list) List of JSON encoded objects, each containing a measurement
     point status:
       - mpid: (integer) Measurement point ID
       - name: (string) Measurement point name
       - noise: (integer) Interference noise value 0 - 100. Values under
         40 indicate normal operation. Larger values indicate interference.
       - offset: (string) Unit clock offset from system time in seconds
         formatted as [-]s.dcm

Notes:

   1. Status info strings:
       - running: Normal operation
       - resetting: System reset in progress
       - offline: velotrain was shutdown (date and time fields
         indicate when shutdown ocurred)
       - error: Network connection lost, server status temporarily
         unavailable

Example: Status update

	Topic:		velotrain/status
	Payload:	{"date": "2022-07-07", "time": "23:04:00.15",
			 "offset": "0.211", "env": [13.1, 62.0, 1013.0],
			 "count": 123, "gate": null, "battery": ["123876"],
			 "info": "running",
			 "units": [
			  {"mpid": 1, "name": "Finish",
			   "noise": 20, "offset": "0.000"},
			  {"mpid": 2, "name": "Pursuit A",
			   "noise": 32, "offset": "0.025"},
			  {"mpid": 3, "name": "Pursuit B",
			   "noise": 15, "offset": "0.005"},
			  {"mpid": 4, "name": "200m Start",
			   "noise": 32, "offset": "0.005"},
			  {"mpid": 5, "name": "100m Split",
			   "noise": 14, "offset": "-0.008"},
			  {"mpid": 6, "name": "50m Split",
			   "noise": 27, "offset": "0.064"},
			  {"mpid": 8, "name": "150m Split",
			   "noise": 18, "offset": "-0.020"}
			 ]}


### request (subscribe)

Receive requests for replay of passing records to the nominated serial,
filtered according to the JSON encoded request object:

   - serial (string) optional request serial, appended to replay topic
   - index (list) optional [first, last] limit response to include
     passings from index first to index last.
   - time (list) optional [starttime, endtime] limit response to
     passings between starttime and endtime strings formatted HH:MM:SS.dc
   - mpid (list) optional [mpid, ...] include only the nominated
     mpids in replay
   - refid (list) optional [refid, ...] include only nominated
     transponder ids in response
   - marker (list) optional [marker, ...] include only passings
     following the nominated marker strings

Example: Request all passings, publish to default topic

	Topic:		velotrain/request
	Payload:	b''
	
	Reply topic:	velotrain/replay
	Payload:	[{"index":0, ...}, {"index":1, ...}, ...]

Request a replay of passing 254 to 'xxfd'

	Topic:		velotrain/request
	Payload:	{"serial": "xxfd", "index": 254}
	
	Reply topic:	velotrain/replay/xxfd
	Payload:	[{"index": 254, ... }]

Replay passings from transponder '123456' and start gate after midday
before index 10000 and that occur following manual markers 'one' and 'two'

	Topic:		velotrain/request
	Payload:	{"refid": ["123456", "gate"],
			 "time": ["12:00:00", null],
			 "index": [null, 10000],
			 "marker": ["one", "two"]}
	
	Reply topic:	velotrain/replay
	Payload:	[{"index":12, "text":"one","mpid":0, ...}, ...]


### replay[/serial] (publish)

Issues a JSON encoded list of passing objects, filtered according
to a provided request.


### marker (subscribe)

Insert the provided utf-8 encoded unicode payload as a manual marker
passing. If the supplied payload is empty, 'marker' is used.

Example: Insert an emoticon '🤷' (U+1F937) at the current time of day

	Topic:		velotrain/marker
	Payload:	b'\xf0\x9f\xa4\xb7'
	
	Reply topic:	velotrain/passing
	Payload:	{"index": 143, "date": "2022-07-06",
			 "time": "12:09:13.33", "mpid": 0,
			 "refid": "marker", "env": null, "moto": null,
			 "elap": null, "lap": null, "half": null,
			 "qtr": null, "200": null, "100": null,
			 "50": null, "text": "\ud83e\udd37"}

### reset (subscribe)

Start a reset process, authorised by the provided utf-8 encoded 
authkey (config option 'authkey'). For a Tag Heuer Protime decoder network,
this process may take up to three minutes to complete. For systems
with foreign timers, this request will just clear passing records.

Example: Request reset process using authkey 'qwertyuiop'

	Topic:		velotrain/reset
	Payload:	b'qwertyuiop'


### timer (subscribe)

Receive raw passing data from a foreign timing device. Foreign timing
records are utf-8 encoded unicode strings in the format:

	INDEX;SOURCE;CHANNEL;REFID;TOD

Where the fields are as follows:

   - INDEX: ignored
   - SOURCE: measurement point id as a metarace timing channel
     eg: 'C1', 'C2', 'C3', ... 'C9'
   - CHANNEL: ignored
   - REFID: transponder ID eg '123456'
   - TOD: time of day of passing as string eg: '1:23.456', 'now', '12:34:56.789'

Note: velotrain expects each attached decoder to be triggered from a
reference clock at the top of each minute, and to report a passing with
refid matching config option 'trig' (default: '255').
For systems that maintain synchronisation via a
different mechanism, a fake top of minute trigger can be sent
with the channel of the configured sync source (config key 'sync')
at any time using the trig refid and a TOD of '0'.

Example: Insert a passing for transponder '123456' on mpid 3 at the current time

	Topic:		velotrain/timer
	Payload:	b';C3;;123456;now'
	
	Reply topic:	velotrain/rawpass
	Payload:	{"date": "2022-07-06", "env": null,
			 "refid": "123456", "mpid": 3, "name": "Pursuit B",
			 "time": "12:23:35.879", "rcv": "12:23:35.879"}

Fake a top-of-minute message to mpid 1, using the default trig:

	Topic:		velotrain/timer
	Payload:	b';C1;;255;0'

	Reply topic:	velotrain/rawpass
	Payload:	{"date": "2022-07-06", "env": null,
			 "refid": "255", "mpid": 1, "name": "Finish",
			 "time": "00:00:00.000", "rcv": "12:25:06.090"}

Insert a passing for transponder '123456' on mpid 4, 10.2345 seconds after 2 pm:

	Topic:		velotrain/timer
	Payload:	b';C4;;123456;14:00:10.2345'

	Reply topic:	velotrain/rawpass
	Payload:	{"date": "2022-07-06", "env": null,
			 "refid": "123456", "mpid": 4, "name": "200m Start",
			 "time": "14:00:10.234", "rcv": "12:27:38.988"}


### resetunit (subscribe)

Attempt to stop, start and re-synchronise the single measurement
point unit specified in the message body. Note that the synchronisation
master may not be re-started this way.

Example: Reset unit "C4"

	Topic:		velotrain/resetunit
	Payload:	b'C4'


## Requirements

   - metarace (>= 2.1.14)
   - ypmeteo


## Installation

	$ pip3 install velotrain

To use as a systemd service, edit the provided unit file
and copy to /etc/systemd/system, then enable with:

	# systemctl enable velotrain
	# systemctl start velotrain

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "velotrain",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.11",
    "maintainer_email": null,
    "keywords": "velodrome, transponder, timing",
    "author": null,
    "author_email": "Nathan Fraser <ndf-zz@6-v.org>",
    "download_url": "https://files.pythonhosted.org/packages/d3/d2/7d4157b28b5ddaef88234868c877c06154d58c50cccb905345d9c28dc72d/velotrain-1.0.3.tar.gz",
    "platform": null,
    "description": "# velotrain\n\nvelotrain reads raw transponder passing information from a set\nof up to 9 measurement points, filters the messages according\nto track configuration parameters and then emits valid timing\nmeasurements as JSON-encoded objects to MQTT.\n\n\n## Operation\n\nThe velodrome is divided into a closed loop of timing sectors\nby measurement points at each of the interesting offsets, for example:\n\n   - Finish line\n   - 200m Start\n   - Pursuit B\n   - Pursuit A\n\nA rider is considered to be in a 'run' if their speed over any\nconfigured sector (eg Finish line to 200m start) is between\nconfigured values (default: 30 km/h to 90 km/h).\nPassings emitted for a rider in a run will include any available\nlap, half-lap, quarter-lap, 100 m, and 50 m splits.\nRider passings slower or faster than the configured limits are\nconsidered isolated, and will be reported without splits.\n\nWhere possible, valid raw passings received out of order will be\ncorrected and re-ordered before being emitted. In the case that\nan isolated raw passing violates the configured track ordering and \nspeed limits, it may be reported out of order.\n\nFor a Protime active/passive dual loop configuration, riders\nwill not be registered at all until they are moving faster than\nabout 30 km/h, no matter what software limits have been configured.\n\n\n## Configuration\n\nTrack layout, system transponder ids and speed limits are configured\nusing a metarace jsonconfig entry with the section 'velotrain' and the\nfollowing keys:\n\n   - authkey: (string) reset authorisation string, default: null\n   - gate: (string) transponder ID for start gate, default: null\n   - gatedelay: (string) trigger delay for start gate, default: '0.075' _[1]_\n   - gatesrc: (string) channel start gate reports to eg 'C2', default: null\n   - laplen: (float) lap length in metres, default: 250.0\n   - maxspeed: (float) maximum sector speed in km/d, default: 90.0\n   - minspeed: (float) minimum sector speed in km/h, default: 38.0\n   - moto: (list) list of transponder IDs attached to motos, default: []\n   - trig: (string) transponder ID of sync trigger messages, default: '255'\n   - passlevel: (integer) minimum accepted passing level, default 40 _[2]_\n   - uaddr: (string) UDP host listen address, default ''\n   - uport: (integer) UDP host port, default: 2008\n   - bcast: (string) broadcast address for timing LAN,\n     default: '255.255.255.255'\n   - basetopic: (string) base topic for telegraph interface,\n     default: 'velotrain'\n   - sync: (string) channel of synchronisation master unit, default: null\n   - mingate: (float) minimum accepted speed in km/h over the\n     start gate sector, default: 9.0\n   - maxgate: (float) maximum accepted speed in km/h over the\n     start gate sector, default: 22.5\n   - dhi: (list) ['address', port] DHI port for Caprica scoreboard,\n     default: null\n   - dhiencoding: (string) text encoding for DHI messages, default: 'utf-8'\n   - mpseq: (list) ordering of channels on the track,\n     default: ['C1', 'C9', 'C4', 'C6', 'C3', 'C5', 'C7', 'C8', 'C2'] _[3]_\n   - mps: (dict) mapping of channel IDs to measurement point configs,\n     default: {} _[4]_\n\nConfigured measurement points divide the track into a closed loop of\ntiming sectors, with a set of splits at each measurement point.\nMeasurement point config entries have the following options, omitted keys\nreceive a default value:\n\n   - name: (string) visible name of the measurement point,\n     default: channel ID\n   - ip: (string) IP address of connected Protime decoder,\n     default: null _[4]_\n   - offset: (float) distance in metres from finish line to measurement \n     point, default: null\n   - half: (string) channel ID corresponding to a half lap before this unit,\n     default: null\n   - qtr: (string) channel ID corresponding to quarter lap before this unit,\n     default: null\n   - 200: (string) channel ID corresponding to 200 m before this unit,\n     default: null\n   - 100: (string) channel ID corresponding to 100 m before this unit,\n     default: null\n   - 50: (string) channel ID corresponding to 50 m before this unit,\n     default: null\n\nNotes:\n\n   1. 0.075 seconds is LS transponder delay when triggered by\n      start gate release\n   2. Sets the 'level' option in all attached Protime decoder units\n   3. Default channel ordering matches trackmeet, all configured units\n      must appear once in this sequence, however the sequence may contain\n      more channels than are configured.\n   4. Measurement points require a non-null IP entry to be configured.\n      For use with foreign timers, set the IP to be an empty string: ''.\n      Refer to the sample velomon.json for an example setting\n\n\n## Telegraph (MQTT) Interface\n\nThe topics below are relative to the configured basetopic (default:\n'velotrain'), from the perspective of the velotrain process. For\nall JSON encoded objects, invalid or unavailable properties will be\nreported as null.\n\n\n### passing (publish)\n\nIssue filtered and accepted passing records. Passing records\nare JSON encoded objects with the following properties:\n\n   - index : (integer) index of the passing record (reset to 0 each day)\n   - date: (string) Date of the passing formatted YYYY-MM-DD\n   - time: (string) Time of day of the passing formatted HH:MM:SS.dcm\n   - mpid: (integer) Measurement point ID 0 - 9\n   - refid: (string) Transponder ID or system passing ID 'gate', 'moto'\n     or 'marker'\n   - env: (list) [temperature, humidity, pressure] where each value\n     is a float value in units degrees Celsius, %rh, and hPa respectively\n   - moto: (string) Proximity to moto in seconds if drafted\n   - elap: (string) Elapsed time since last start gate or start of run\n     formatted HH:MM:SS.dc\n   - lap: (string) Time for the last full lap to the measurement point\n   - half: (string) Time for the last half lap to the measurement point\n   - qtr: (string) Time for the last quarter lap to the measurement point\n   - 200: (string) Time for the last 200m to the measurement point\n   - 100: (string) Time for the last 100m to the measurement point\n   - 50: (string) Time for the last 50m to the measurement point\n   - text: (string) Name of measurement point, or user-supplied text\n     for markers\n\nExample: A moto passing over the 100m split at about 4:18pm\n\n\tTopic:\t\tvelotrain/passing\n\tPayload:\t{\"index\": 108, \"date\": \"2022-07-06\",\n\t\t\t \"time\": \"16:18:32.300\", \"mpid\": 5,\n\t\t\t \"refid\": \"moto\", \"env\": [16.3, 55.0, 1015.0],\n\t\t\t \"moto\": \"0.00\", \"elap\": \"2:10.51\",\n\t\t\t \"lap\": \"22.95\", \"half\": null, \"qtr\": null,\n\t\t\t \"200\": \"18.32\", \"100\": \"9.07\", \"50\": \"4.52\",\n\t\t\t \"text\": \"100m Split\"}\n\n### rawpass (publish)\n\nIssue raw, unprocessed passing records as received from decoders. Raw\npassing records are JSON encoded objects with the following properties:\n\n   - date: (string) Date of the raw passing formatted YYYY-MM-DD\n   - time: (string) Time of day of the passing formatted HH:MM:SS.dc\n   - rcv: (string) Time of day passing was received by host system,\n     formatted HH:MM:SS.dcm\n   - mpid: (integer) Measurement point ID 0 - 9\n   - refid: (string) Raw transponder ID\n   - env: (list) [temperature, humidity, pressure] where each value\n     is a float value in units degrees Celsius, %rh, and hPa respectively\n   - name: (string) Name of measurement point\n   - info: (string) Extra information provided by decoder\n\nExample: The raw passing that might have generated the above moto passing\n\n\tTopic:\t\tvelotrain/rawpass\n\tPayload:\t{\"date\": \"2022-07-06\", \"env\": [16.3, 55.0, 1015.0],\n\t\t\t \"refid\": \"125328\", \"mpid\": 5,\n\t\t\t \"name\": \"100m Split\", \"time\": \"16:18:32.303\",\n\t\t\t \"rcv\": \"16:18:32.459\"}\n\n### status (publish)\n\nIssue system and measurement point status records at the top of each\nminute. Status records are JSON encoded objects with the following properties:\n\n   - date: (string) Date of the status record formatted YYYY-MM-DD\n   - time: (string) Time of day status was issued formatted HH:MM:SS.dc\n   - offset: (string) Rough offset of system clock to UTC\n   - count: (integer) Count of passing records\n   - env: (list) [temperature, humidity, pressure] where each value\n     is a float value in units degrees Celsius, %rh, and hPa respectively\n   - gate: (string) Time of day of last gate trigger HH:MM:SS.dc\n   - battery: (list) List of transponder refids that have reported a low\n     battery warning since the last system reset\n   - info: (string) Status info, one of: 'running', 'resetting',\n     'error', 'offline' _[1]_\n   - units: (list) List of JSON encoded objects, each containing a measurement\n     point status:\n       - mpid: (integer) Measurement point ID\n       - name: (string) Measurement point name\n       - noise: (integer) Interference noise value 0 - 100. Values under\n         40 indicate normal operation. Larger values indicate interference.\n       - offset: (string) Unit clock offset from system time in seconds\n         formatted as [-]s.dcm\n\nNotes:\n\n   1. Status info strings:\n       - running: Normal operation\n       - resetting: System reset in progress\n       - offline: velotrain was shutdown (date and time fields\n         indicate when shutdown ocurred)\n       - error: Network connection lost, server status temporarily\n         unavailable\n\nExample: Status update\n\n\tTopic:\t\tvelotrain/status\n\tPayload:\t{\"date\": \"2022-07-07\", \"time\": \"23:04:00.15\",\n\t\t\t \"offset\": \"0.211\", \"env\": [13.1, 62.0, 1013.0],\n\t\t\t \"count\": 123, \"gate\": null, \"battery\": [\"123876\"],\n\t\t\t \"info\": \"running\",\n\t\t\t \"units\": [\n\t\t\t  {\"mpid\": 1, \"name\": \"Finish\",\n\t\t\t   \"noise\": 20, \"offset\": \"0.000\"},\n\t\t\t  {\"mpid\": 2, \"name\": \"Pursuit A\",\n\t\t\t   \"noise\": 32, \"offset\": \"0.025\"},\n\t\t\t  {\"mpid\": 3, \"name\": \"Pursuit B\",\n\t\t\t   \"noise\": 15, \"offset\": \"0.005\"},\n\t\t\t  {\"mpid\": 4, \"name\": \"200m Start\",\n\t\t\t   \"noise\": 32, \"offset\": \"0.005\"},\n\t\t\t  {\"mpid\": 5, \"name\": \"100m Split\",\n\t\t\t   \"noise\": 14, \"offset\": \"-0.008\"},\n\t\t\t  {\"mpid\": 6, \"name\": \"50m Split\",\n\t\t\t   \"noise\": 27, \"offset\": \"0.064\"},\n\t\t\t  {\"mpid\": 8, \"name\": \"150m Split\",\n\t\t\t   \"noise\": 18, \"offset\": \"-0.020\"}\n\t\t\t ]}\n\n\n### request (subscribe)\n\nReceive requests for replay of passing records to the nominated serial,\nfiltered according to the JSON encoded request object:\n\n   - serial (string) optional request serial, appended to replay topic\n   - index (list) optional [first, last] limit response to include\n     passings from index first to index last.\n   - time (list) optional [starttime, endtime] limit response to\n     passings between starttime and endtime strings formatted HH:MM:SS.dc\n   - mpid (list) optional [mpid, ...] include only the nominated\n     mpids in replay\n   - refid (list) optional [refid, ...] include only nominated\n     transponder ids in response\n   - marker (list) optional [marker, ...] include only passings\n     following the nominated marker strings\n\nExample: Request all passings, publish to default topic\n\n\tTopic:\t\tvelotrain/request\n\tPayload:\tb''\n\t\n\tReply topic:\tvelotrain/replay\n\tPayload:\t[{\"index\":0, ...}, {\"index\":1, ...}, ...]\n\nRequest a replay of passing 254 to 'xxfd'\n\n\tTopic:\t\tvelotrain/request\n\tPayload:\t{\"serial\": \"xxfd\", \"index\": 254}\n\t\n\tReply topic:\tvelotrain/replay/xxfd\n\tPayload:\t[{\"index\": 254, ... }]\n\nReplay passings from transponder '123456' and start gate after midday\nbefore index 10000 and that occur following manual markers 'one' and 'two'\n\n\tTopic:\t\tvelotrain/request\n\tPayload:\t{\"refid\": [\"123456\", \"gate\"],\n\t\t\t \"time\": [\"12:00:00\", null],\n\t\t\t \"index\": [null, 10000],\n\t\t\t \"marker\": [\"one\", \"two\"]}\n\t\n\tReply topic:\tvelotrain/replay\n\tPayload:\t[{\"index\":12, \"text\":\"one\",\"mpid\":0, ...}, ...]\n\n\n### replay[/serial] (publish)\n\nIssues a JSON encoded list of passing objects, filtered according\nto a provided request.\n\n\n### marker (subscribe)\n\nInsert the provided utf-8 encoded unicode payload as a manual marker\npassing. If the supplied payload is empty, 'marker' is used.\n\nExample: Insert an emoticon '\ud83e\udd37' (U+1F937) at the current time of day\n\n\tTopic:\t\tvelotrain/marker\n\tPayload:\tb'\\xf0\\x9f\\xa4\\xb7'\n\t\n\tReply topic:\tvelotrain/passing\n\tPayload:\t{\"index\": 143, \"date\": \"2022-07-06\",\n\t\t\t \"time\": \"12:09:13.33\", \"mpid\": 0,\n\t\t\t \"refid\": \"marker\", \"env\": null, \"moto\": null,\n\t\t\t \"elap\": null, \"lap\": null, \"half\": null,\n\t\t\t \"qtr\": null, \"200\": null, \"100\": null,\n\t\t\t \"50\": null, \"text\": \"\\ud83e\\udd37\"}\n\n### reset (subscribe)\n\nStart a reset process, authorised by the provided utf-8 encoded \nauthkey (config option 'authkey'). For a Tag Heuer Protime decoder network,\nthis process may take up to three minutes to complete. For systems\nwith foreign timers, this request will just clear passing records.\n\nExample: Request reset process using authkey 'qwertyuiop'\n\n\tTopic:\t\tvelotrain/reset\n\tPayload:\tb'qwertyuiop'\n\n\n### timer (subscribe)\n\nReceive raw passing data from a foreign timing device. Foreign timing\nrecords are utf-8 encoded unicode strings in the format:\n\n\tINDEX;SOURCE;CHANNEL;REFID;TOD\n\nWhere the fields are as follows:\n\n   - INDEX: ignored\n   - SOURCE: measurement point id as a metarace timing channel\n     eg: 'C1', 'C2', 'C3', ... 'C9'\n   - CHANNEL: ignored\n   - REFID: transponder ID eg '123456'\n   - TOD: time of day of passing as string eg: '1:23.456', 'now', '12:34:56.789'\n\nNote: velotrain expects each attached decoder to be triggered from a\nreference clock at the top of each minute, and to report a passing with\nrefid matching config option 'trig' (default: '255').\nFor systems that maintain synchronisation via a\ndifferent mechanism, a fake top of minute trigger can be sent\nwith the channel of the configured sync source (config key 'sync')\nat any time using the trig refid and a TOD of '0'.\n\nExample: Insert a passing for transponder '123456' on mpid 3 at the current time\n\n\tTopic:\t\tvelotrain/timer\n\tPayload:\tb';C3;;123456;now'\n\t\n\tReply topic:\tvelotrain/rawpass\n\tPayload:\t{\"date\": \"2022-07-06\", \"env\": null,\n\t\t\t \"refid\": \"123456\", \"mpid\": 3, \"name\": \"Pursuit B\",\n\t\t\t \"time\": \"12:23:35.879\", \"rcv\": \"12:23:35.879\"}\n\nFake a top-of-minute message to mpid 1, using the default trig:\n\n\tTopic:\t\tvelotrain/timer\n\tPayload:\tb';C1;;255;0'\n\n\tReply topic:\tvelotrain/rawpass\n\tPayload:\t{\"date\": \"2022-07-06\", \"env\": null,\n\t\t\t \"refid\": \"255\", \"mpid\": 1, \"name\": \"Finish\",\n\t\t\t \"time\": \"00:00:00.000\", \"rcv\": \"12:25:06.090\"}\n\nInsert a passing for transponder '123456' on mpid 4, 10.2345 seconds after 2 pm:\n\n\tTopic:\t\tvelotrain/timer\n\tPayload:\tb';C4;;123456;14:00:10.2345'\n\n\tReply topic:\tvelotrain/rawpass\n\tPayload:\t{\"date\": \"2022-07-06\", \"env\": null,\n\t\t\t \"refid\": \"123456\", \"mpid\": 4, \"name\": \"200m Start\",\n\t\t\t \"time\": \"14:00:10.234\", \"rcv\": \"12:27:38.988\"}\n\n\n### resetunit (subscribe)\n\nAttempt to stop, start and re-synchronise the single measurement\npoint unit specified in the message body. Note that the synchronisation\nmaster may not be re-started this way.\n\nExample: Reset unit \"C4\"\n\n\tTopic:\t\tvelotrain/resetunit\n\tPayload:\tb'C4'\n\n\n## Requirements\n\n   - metarace (>= 2.1.14)\n   - ypmeteo\n\n\n## Installation\n\n\t$ pip3 install velotrain\n\nTo use as a systemd service, edit the provided unit file\nand copy to /etc/systemd/system, then enable with:\n\n\t# systemctl enable velotrain\n\t# systemctl start velotrain\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Velodrome transponder training timing",
    "version": "1.0.3",
    "project_urls": {
        "homepage": "https://github.com/ndf-zz/velotrain",
        "repository": "https://github.com/ndf-zz/velotrain"
    },
    "split_keywords": [
        "velodrome",
        " transponder",
        " timing"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "117d006a417866a0e1971fe656e6938e5e3336e99f5cb5d2e598090ca22f8ad3",
                "md5": "3afb294ce636912a353fade338e47c87",
                "sha256": "f506cf5c6af973dc6c2027746b4471954d9347da98ea5f4761707ffa6755ddef"
            },
            "downloads": -1,
            "filename": "velotrain-1.0.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "3afb294ce636912a353fade338e47c87",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.11",
            "size": 24499,
            "upload_time": "2025-07-23T01:59:45",
            "upload_time_iso_8601": "2025-07-23T01:59:45.566756Z",
            "url": "https://files.pythonhosted.org/packages/11/7d/006a417866a0e1971fe656e6938e5e3336e99f5cb5d2e598090ca22f8ad3/velotrain-1.0.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "d3d27d4157b28b5ddaef88234868c877c06154d58c50cccb905345d9c28dc72d",
                "md5": "f2ecaff7b4cb6823bf3df16b11f475cd",
                "sha256": "ef8b8adf06ca79158c2e291074d67266d1903dc9a089432cb23630aebefdd0a2"
            },
            "downloads": -1,
            "filename": "velotrain-1.0.3.tar.gz",
            "has_sig": false,
            "md5_digest": "f2ecaff7b4cb6823bf3df16b11f475cd",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.11",
            "size": 24338,
            "upload_time": "2025-07-23T01:59:47",
            "upload_time_iso_8601": "2025-07-23T01:59:47.068040Z",
            "url": "https://files.pythonhosted.org/packages/d3/d2/7d4157b28b5ddaef88234868c877c06154d58c50cccb905345d9c28dc72d/velotrain-1.0.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-23 01:59:47",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "ndf-zz",
    "github_project": "velotrain",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "velotrain"
}
        
Elapsed time: 0.53181s