Lernapparat

Fischertechnik TXT Proxy

May 24, 2019

And now for something completely different: In order to access the Fischertechnik Robotics TXT's camera functions under Wine, one needs to cope with the camera port being opened slowly. We provide a small Python proxy to solve this.

So the ROBOPro software that came with the robotics construction kit works under Wine. However it seems to be a problem to use the camera function. Happily, someone on the great ftcommunity forum had already debugged the problem, which seems to be that the software tries to open a connection to a port (65001) before the Robotics TXT has listens. The other port that is used is 65000.

To work around this, it is suggested (e.g. in the first link) to use a proxy that delays connecting to 65001, but I didn't actually find one in those threads. So here is my Python 3 version, heavily based on a proxy example on StackOverflow. Note that I use a WLAN connection, I don't know if this works as well with USB or Bluetooth.

#!/usr/bin/python3
import asyncio
import sys
from functools import partial

async def pipe(reader, writer):
    try:
        while not reader.at_eof():
            writer.write(await reader.read(2048))
    finally:
        writer.close()

async def handle_client(local_reader, local_writer, port=65000, remote_ip=None):
    try:
        print("local connect on", port)
        if port == 65001:
            print("sleeping")
            await asyncio.sleep(1)
            print("done sleeping")
        remote_reader, remote_writer = await asyncio.open_connection(
            remote_ip, port)
        print("remote connected", port)
        pipe1 = pipe(local_reader, remote_writer)
        pipe2 = pipe(remote_reader, local_writer)
        await asyncio.gather(pipe1, pipe2)
    finally:
        local_writer.close()
        print("disconnected", port)

async def serve(port=65000, remote_ip=None):
    server = await asyncio.start_server(
        partial(handle_client, port=port, remote_ip=remote_ip), '127.0.0.1', port)

    addr = server.sockets[0].getsockname()
    print(f'Forwarding {port} on {addr} to {remote_ip}')

    async with server:
        await server.serve_forever()

if len(sys.argv) > 1:
    remote_ip = sys.argv[1]
else:
    remote_ip = '192.168.0.49' # very subjective default

loop = asyncio.get_event_loop()
loop.create_task(serve(remote_ip=remote_ip))
loop.create_task(serve(remote_ip=remote_ip, port=65001))
loop.run_forever()

Copy is to a file, e.g. ./robotxt_port_forwarder.py <IP of your TXT> and set the localhost (127.0.0.1) address in the ROBOPro software.

Have fun! As always, your feedback at tv@lernapparat.de is very welcome!