Skip to content

PyLib in Your Own Applications

The ahoi PyLib is a python library intended to be used in your own applications. This tutorial will show you the basic concepts and functions.

Note

The PyLib has to be installed on every device, on which your PyLib-based programs run.

Modem Wrapper Class

The PyLib contains a helpful wrapper class Modem that allows easy access and control of an ahoi modem via Python. It is included via

from ahoi.modem.modem import Modem

You create an instance of type Modem

myModem = Modem()
as virtual representation of a modem that you want to communicate with.

Connecting to a Modem

You connect to a modem via a serial port or TCP connection

myModem.connect("connection")
where "connection" is either

  • the name of a serial device (e.g., /dev/ttyUSB0 or COM1) or
  • the IP address (and port number) of a serial forwarder with prefix "tcp@" (e.g., "tcp@192.168.1.50:2464")

To close the connection to a modem, use

myModem.close()

Sending a Data Packet

To let the modem send a data packet on the acoustic channel, use

myModem.send(src, dst, type, payload=bytearray(), status=None, dsn=None)

Todo

Do we actually use "src"?

Parameter Description
src ID of the source modem (8 bits). Typical the id the modem which send the packet.
dst ID of the modem which should receive the packet or 255 for broadcasting
payload data to send
status bit field of status flags
dsn sequence number, when 'None' its automatic handled

Refer to the ahoi Packet Format for details.

Example:

myModem.send(dst=0xFF, payload=bytearray(8), status=0, dsn=10)

Receiving a Data Packet

Reception of data and command packets is realized by registering packet handler callback methods for a Modem instance. Upon packet reception, the callback methods are called and the received packet is handed over to the callback methods as parameter.

Callback Methods

Callback methods have the following signature:

def rxCallback(pkt):
    ...
They are installed (registered) and removed (deregistered) for an instance of type Modem with name myModem via

myModem.addRxCallback(rxCallback)
myModem.removeRxCallback(rxCallback)

The registration of multiple callback methods (with unique names) is supported. Note that for each received packet, all of the installed callback methods are called.

Starting Reception

Reception must be activated for a modem by calling the method receive() in either blocking (thread = False) or non-blocking (thread = True) mode.

myModem.receive(thread)

In blocking mode, the method receive() runs in an endless loop and only returns, if the connection to the modem is interrupted. In non-blocking mode, the method receive() starts a thread, which takes care of reception, and returns directly afterwards. The thread is automatically exited, when the connection to the modem is closed or interrupted.

Modem Configuration

To interact with a modem other than sending and receiving acoustic data packets, individual wrapper methods are available. Examples are to query the firmware version or get/set a modem ID. We kindly refer you to modem.py for a complete list of available methods.

Distance Measurements / Ranging

The ahoi modem supports distance measurements (also called ranging) by means of two-way time-of-flight (TWR) estimation (between any pair of modems). A distance measurement is initiated by sending a data packet with R-flag (cf. ahoi Packet Format) from one modem to another modem or as a broadcast. As such, you can trigger a distance measurement from PyLib via status = 2 when sending a data packet.

When the distance measurement is complete, the sending modem will forward the received ACK to the host. This ACK contains half the cumulated time-of-flight of the data packet and the ACK and can be processed by a packet handler. Note that you can filter out ACKs with ranging information by its packet type 0x7F and a non-zero payload length.

The payload can be converted to the distance by the following calculation:

SPEED_OF_SOUND = 1500  # in meters per second

def rxCallback(pkt):
    # check if we have received a ranging ack
    if pkt.header.type == 0x7F and pkt.header.length > 0:
        tof = 0
        for i in range(0,4):
            tof = tof * 256 + pkt.payload[i]
        print("distance: %6.1f" % (tof * 1e-6 * SPEED_OF_SOUND))

    ...

Underwater Speed of Sound

The value for the speed of sound depends on the medium and temperature. Look up the value in a table, or measure the value on your own.

If a modem receives a data packet with R-flag, it responds with a ranging request, if and only if the field dst of the received packet

  • equals the receiver's ID or
  • is the broadcast address.

Using the broadcast address in the dst field of such a packet may, hence, trigger multiple simultaneous ACKs from different receiving modems. This is undesired, because the sender cannot receive overlapping ACKs. For this particular purpose, the ahoi modem supports delayed ACKs: By configuring a different (and large enough) delay for each modem in a network, multiple ACKs with distance information can be collected by sending a single data packet with R-flag. To configure such a delay for an instance myModem of type Modem, use

myModem.rangeDelay(delay)
where delay is an integer value in milliseconds.

Effect of Ranging Delay

  • The ranging delay is only effective for ACKs sent in response to a packet with R-flag. Regular ACKs (A-flag only) will always be sent immediately.
  • The ranging delay is purged (subtracted) from the time-of-flight contained in a ranging ACK automatically.

Firmware Installation (Experimental)

Serial Port Only

The firmware update is only supported via a direct serial port communication. An update over ethernet is currently not possible.

PyLib supports firmware installation and updating through the external program "stm32flash", which is also used in the MoSh Firmware Installation. A firmware installation via PyLib is done with the following command:

myModem.program(img='ahoi.hex', empty)
Set the parameter empty to

  • True, if the modem is empty (i.e., no previous firmware has been installed) or
  • False, if the modem contains a previous firmware version and shall be updated.