Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ authors = ["Your Name <you@example.com>"]
publish = false

[dependencies]
trunk-recorder-plugin = "0.3.0"
trunk-recorder-plugin = "0.4.0"
# The settings form is drawn from your config structs' JSON Schema. Keep the
# major version the SDK uses (1).
schemars = "1"
Expand Down
28 changes: 21 additions & 7 deletions docs/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ uploaders and archivers.
"path": "county/2026/9/30/101-1790771550_857587500",
"system": 0,
"call": {
"call_num": 412, "short_name": "county", "talkgroup": 101,
"call_num": 412, "short_name": "county", "site": "county", "talkgroup": 101,
"talkgroup_tag": "Fire Dispatch", "talkgroup_description": "", "talkgroup_group": "Fire", "talkgroup_group_tag": "Fire Dispatch",
"freq": 857587500, "start_time": 1790771550, "stop_time": 1790771554, "call_length": 4,
"emergency": 0, "encrypted": 0, "priority": 0, "phase2_tdma": 0, "tdma_slot": 0, "audio_type": "digital",
Expand Down Expand Up @@ -64,6 +64,12 @@ uploaders and archivers.
Only recorded calls conclude. Calls the recorder skipped (encrypted, no free
recorder, an unknown talkgroup when those aren't recorded) have no files.

A system can have several sites, each a control channel the recorder follows.
A call heard on more than one is one call, saved once from the site that heard
it best: `short_name` is the system, and **`site`** is the site the call was
kept from (a system of one site: its short name; none for a conventional
channel's call).

## `call.start` and `call.end`

A call started, or ended. Unlike `call.concluded`, these cover calls that
Expand All @@ -73,7 +79,7 @@ it was recorded, come later in `call.concluded`.
```json
{
"type": "call.start",
"id": 412, "system": 0, "short_name": "county",
"id": 412, "system": 0, "short_name": "county", "site": "county",
"talkgroup": 101, "talkgroup_tag": "Fire Dispatch",
"freq_hz": 857587500, "tdma_slot": null,
"analog": false, "encrypted": false, "emergency": false,
Expand All @@ -85,7 +91,10 @@ it was recorded, come later in `call.concluded`.
```

- **`id`** is unique while the recorder runs. It's the same number as
`call_num` in the concluded call.
`call_num` in the concluded call, except for a call heard on several sites:
it starts and ends once, as its first site's copy (`site`), and the copy
that concludes may be another site's, with another number. Match those by
system, talkgroup and time if you need to.
- **`recording`**: `false` means the call isn't recorded, and **`reason`**
says why: `encrypted`, `unknown_tg` (not in the talkgroup list, and unknown
talkgroups aren't recorded), `no_recorder` (all in use) or `no_source` (no
Expand All @@ -99,7 +108,7 @@ it was recorded, come later in `call.concluded`.
A radio did something on the control channel.

```json
{ "type": "unit", "system": 0, "short_name": "county", "kind": "affiliation", "unit": 1116707, "talkgroup": 101, "time": 1790771551.4 }
{ "type": "unit", "system": 0, "short_name": "county", "site": "county", "kind": "affiliation", "unit": 1116707, "talkgroup": 101, "time": 1790771551.4 }
```

`kind` is one of:
Expand Down Expand Up @@ -128,19 +137,24 @@ little-endian, base64-encoded. `chunk.samples()` decodes it.

Chunks of one call come in order. Chunks of different calls are interleaved.
Use `call_id` to tell them apart, and `call.start` / `call.end` (subscribe to
them too) to know when a call's audio begins and ends.
them too) to know when a call's audio begins and ends. A call heard on several
sites plays from whichever site's copy has it at the moment, so a chunk can
carry the `call_id` of a copy that had no `call.start`: it is the call of the
same system and talkgroup that did.

This topic is busy. Hand the audio to your own thread straight away.

## `status`

Every system's state, every 5 seconds.
Every system's state, every 5 seconds: an entry for each site, so a system of
several sites has several, with the same `index` and `short_name` and its own
`site_name`.

```json
{
"type": "status", "time": 1790771560.0,
"systems": [
{ "index": 0, "short_name": "county", "control_channel_hz": 851012500, "decode_rate": 38.5, "active_calls": 3, "recording": 2 }
{ "index": 0, "short_name": "county", "site_name": "county", "control_channel_hz": 851012500, "decode_rate": 38.5, "active_calls": 3, "recording": 2 }
]
}
```
Expand Down
6 changes: 5 additions & 1 deletion docs/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ There are two kinds of settings:
- **`Config`**: settings for the plugin as a whole, like a server URL.
- **`SystemConfig`**: settings the form repeats for each system being
recorded, like an API key per system. Many services give each system its own
key, so uploaders need this.
key, so uploaders need this. A system's sites share them; for a service that
knows a site as a system of its own, add a list of sites with what differs
(the [Broadcastify](https://github.com/TrunkRecorder/trunk-plugin-broadcastify)
and [OpenMHz](https://github.com/TrunkRecorder/trunk-plugin-openmhz) plugins'
**Sites of their own**) and pick by the call's `site`.

Use `NoConfig` for either if you don't need it.

Expand Down
3 changes: 2 additions & 1 deletion docs/uploading.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ complete example, about 250 lines with its tests. Read it alongside.
## 1. Settings

Services usually give each system its own key, so the key goes in
`SystemConfig`. The server goes in `Config`, with the real service as the
`SystemConfig` (a system's sites share it; see [Settings](settings.md) for a
site a service knows on its own). The server goes in `Config`, with the real service as the
default:

```rust
Expand Down
Loading