RTCM Channel Driver
The chan/voter channel driver is the interface between Asterisk and the RTCM/VOTER radio/repeater hardware interface. It allows receiver voting, simulcast transmitters, or just a plain repeater interface when used with the appropriate hardware.
This page will document configuring the channel driver, done through voter.conf, as well as some common issues and more obscure features that may not be widely known.
Basic Information On chan/voter Works
Each node has a number of potential "clients" associated with it. In the voter.conf file, each stanza (category) is named by the node number that the clients specified within the stanza are to be associated with. Each entry consists of an arbitrary (relatively meaningless, just included for easy identification purposes within this channel driver, and has nothing to do with its operation) identifier equated to a unique password. This password is programmed into the client. All clients must have unique passwords, as that is what is used by this channel driver to identify them.
Each channel instance (as opened by app_rpt as a main radio channel, e.g. rxchannel=Voter/1999 in rpt.conf) and is directly associated with the node that opened it.
Each client has a pair of circular buffers, one for mu-law audio data, and one for RSSI value. The allocated buffer length in all clients is determined by the "buflen" parameter, which is specified in the "global" stanza in the voter.conf file in milliseconds, and represented in the channel driver as number of samples (actual buffer length, which is 8 * milliseconds).
Every channel instance has a index ("drainindex"), indicating the next position within the physical buffer(s) where the audio will be taken from the buffers and presented to the Asterisk channel stream as VOICE frames. Therefore, there is an abstraction of a "buffer" that exists starting at drainindex and ending (modulo) at drainindex - 1, with length of buflen.
Buflen is selected so that there is enough time (delay) for any straggling packets to arrive before it is time to present the data to the Asterisk channel.
The idea is that the current audio being presented to Asterisk is from some time shortly in the past. Therefore, "Now" is the position in the abstracted buffer of 'bufdelay' (generally buflen - 160, you gotta at least leave room for an entire frame) and the data is being presented from the start of the abstracted buffer. As the physical buffer moves along, what was once "now" will eventually become far enough in the "past" to be presented to Asterisk (gosh, doesn't this sound like a scene from "Spaceballs"??.. I too always drink coffee while watching "Mr. Radar").
During the processing of an audio frame to be presented to Asterisk, all client's buffers that are associated with a channel instance (node) are examined by taking an average of the RSSI value for each sample in the associated time period (the first 160 samples of the abstracted buffer (which is the physical buffer from drainindex to drainindex + 159) and whichever one, if any that has the largest RSSI average greater then zero is selected as the audio source for that frame. The corresponding audio buffer's contents (in the corresponding offsets) are presented to Asterisk, then ALL the clients corresponding RSSI data is set to 0, ALL the clients corresponding audio is set to quiet (0x7f). The overwriting of the buffers after their use/examination is done so that the next time those positions in the physical buffer are examined, they will not contain any data that was not actually put there, since all client's buffers are significant regardless of whether they were populated or not. This allows for the true 'connectionless-ness' of this protocol implementation.
Less Known Facts/Features
The original intent was to change this driver to use signed linear internally, but after some thought, it was determined that it was prudent to continue using mulaw as the "standard" internal audio format (with the understanding of the slight degradation in dynamic range when using ADPCM resulting in doing so). This was done because existing external entities (such as the recording files and the streaming stuff) use mulaw as their transport, and changing all of that to signed linear would be cumbersome, inefficient and undesirable.
"Dynamic" client functionality
DON'T USE IT!!. It is intentionally NOT documented to encourage non-use of this feature. It is for demo purposes ONLY. The chan/voter driver will NOT properly perform reliably in a production environment if this option is used.
Redundant "Proxy" Mode
A "Redundant" (backup) server may be set up, so that if the "primary" server fails, clients can detect this failure, and connect to the designated "backup" (or "secondary") server.
Needless to say, since Internet connectivity is not by any means guaranteed to be consistent, it is possible for some clients to have working connectivity to the "primary" server and not others, even though the "primary" server is functional.
If this was to occur, actual voting and/or simulcast clients would have a "broken" system (being that all the clients need to be on the same server for any sort of functional operation).
To eliminate this possibility, functionality has been added so that a "secondary" server will "proxy" (forward) all of its VOTER packets to the "primary" (if the "primary" is on line), and the "primary" will generate all of the outbound VOTER packets, which (for clients "connected" to the "secondary" server) get sent to the "secondary" server to distribution to its clients.
This allows for a "unity" of all of the clients on a network, even though they may be connected to different servers.
In addition, it is assumed that "permanent linking" (at least of some sort) will be provided between the channel side of the chan/voter instances (presumably through a "perma-link" provided by app_rpt).
When the "secondary" is "proxying" (to the "primary") it does not provide direct connectivity to/from its locally-connected clients, thus allowing them to "connect" via the "primary" server instead. In "normal" mode, it works "normally".
The operation is performed by more-or-less "encapsulating" the VOTER packets received by the "secondary" server, and forwarding them on to the "primary" server, where they are "un-encapsulated" and appear to that serer to be coming from clients connected directly to it (and keeps track of which ones are connected in this manner, etc). When it needs to send VOTER packets to a client connected through the "secondary", it "encapsulates" them, and sends them to the "secondary", where they get "un-enacpsulated" and sent to their associated connected clients, based upon information in the "encapsulation".
If the "secondary" server loses (or does not make) connection to the "primary", it operates as normal, until such time as it can make the connection.
The server redundancy feature is local to each chan/voter instance.
For each chan_voter instance served by both the "primary" and "secondary" servers, the client list (parameters, etc) MUST be identical.
In addition, the following things must be added uniquely on each server:
- In the "primary" server, there needs to be a "primary connectivity" client specified for each "secondary" server for which it is "primary". Basically, this is a client that does NOTHING other then providing a means by which the "secondary" can determine whether the "primary" is on line.
- It is a standard chan/voter client, with nothing else specified other then its password. Again, although it is a "legitimate" client (technically), its only purpose MUST be to allow the secondary server to connect to it.
- The "primary" server also needs to have the following in all of its instances that require redundancy:
isprimary = y
- The "secondary" server needs to have the following in all of its instances that require redundancy:
primary = 184.108.40.206:667,mypswd
Where 220.127.116.11:667 is the IPADDDR:PORT of the "primary" server, and mypswd is the password of the "primary connectivity" client
Note: Master timing sources MUST be local to their associated server, and therefore, can not be operated in a redundant configuration. If a radio needs server redundancy, it CAN NOT be connected to a master timing source. Also, the master timing source MUST be associated with a chan/voter instance that DOES NOT have redundancy configured for it, even if a separate instance needs to be created just for this purpose.
Also, if non-GPS-based operation is all that is needed, just the use of redundancy within the clients is sufficient, and does not require any use of the server redundancy features.