M17 mrefd and pyM17: Prototyping M17 reflector applications

I’ve added mrefd reflector support to pyM17, so now you can talk to existing M17-REF reflectors using Python.

Code and details after the break.

Here’s an example client, which has no error checking or network retries, but should demonstrate the concept.

There’s also an experimental bidirectional echolink bridge, which as of this writing also lacks error checking but will be improved when time permits.

The Docker w/svxlink is probably good to go, and can be used for testing and development.

I’m really enjoying this pattern of making small, reusable functions that do processing transformations. It’s not original, and I’m slowly hitting the limitations of my current design, but it’s still a lot of fun to whip together a brand new capability in a few seconds and expect it to work pretty well.

An example app, the salient parts of m17ref_client

c = m17ref_client_blocks(myrefmod,module,host,port)
tx_chain = [mic_audio, codec2enc, vox, m17frame, tobytes, c.sender()]
rx_chain = [c.receiver(), m17parse, payload2codec2, codec2dec, spkr_audio]
config = default_config(mode) #includes Codec2 vocoder
modular(config, [tx_chain, rx_chain])

An example function, vox

def vox(config,inq,outq):
    Watch for duplicate incoming q elements, and if there's more than
    a configurable threshold in a row, don't copy further duplicates

    This lets you use a microphone mute as a reverse PTT, among other things
    last = None
    repeat_count = 0
    while 1:
        x = inq.get()
        if x == last:
            repeat_count += 1
            repeat_count = 0
        last = x
        if repeat_count > config.vox.silence_threshold:
            continue #drop the element, since we're processing the same data which means it's silent audio