Module swarm.swarm

Expand source code
import logging
from enum import IntEnum


class Sensor(IntEnum):
    """All Sensor types known by the ftSwarm"""
    UNDEFINED = -1
    DIGITAL = 0
    ANALOG = 1
    SWITCH = 2
    REEDSWITCH = 3
    LIGHTBARRIER = 4
    VOLTMETER = 5
    OHMMETER = 6
    THERMOMETER = 7
    LDR = 8
    TRAILSENSOR = 9
    COLORSENSOR = 10
    ULTRASONIC = 11
    BUTTON = 12


class Actor(IntEnum):
    """All Actor types known by the ftSwarm"""
    UNDEFINDED = -1
    XMOTOR = 0
    XMMOTOR = 1
    TRACTOR = 2
    ENCODER = 3
    LAMP = 4
    VALVE = 5
    COMPRESSOR = 6
    BUZZER = 7


class MotionType(IntEnum):
    """How to move a motor"""
    COAST = 0
    BRAKE = 1
    ON = 2


class Toggle(IntEnum):
    """Toggle states"""
    NOTOGGLE = 0
    TOGGLEUP = 1
    TOGGLEDOWN = 2


class Align(IntEnum):
    """Text alignment for display"""
    ALIGNLEFT = 0
    ALIGNCENTER = 1
    ALIGNRIGHT = 2


class Trigger(IntEnum):
    """Trigger events"""
    TRIGGERUP = 0
    TRIGGERDOWN = 1
    TRIGGERVALUE = 2
    TRIGGERI2CREAD = 3
    TRIGGERI2CWRITE = 4


class FtSwarmBase:
    """Base class for all ftSwarm implementations"""

    def __init__(self) -> None:
        self.logger = logging.getLogger("swarm-base")

    async def send(self, port_name: str, command: str, *args: str | int | float) -> int | str | None:
        pass


class FtSwarmIO:
    """
    Base class for all ftSwarm interfaces

    Don't use this class at all
    """

    def __init__(self, swarm: FtSwarmBase, port_name: str) -> None:
        self._port_name = port_name
        self._swarm = swarm

    async def post_init(self) -> None:
        pass

    async def get_port_name(self) -> str:
        return self._port_name

    async def set_value(self, value: str) -> None:
        self._swarm.logger.warning(f"Received unexpected write to {self._port_name}: {value}")


class FtSwarmActorShim(FtSwarmIO):
    """
    Shim class for all ftSwarm actors for type annotations

    Don't use this class at all
    """

    def get_port_name(self) -> str:
        pass


class FtSwarmInput(FtSwarmIO):
    """
    Base class for all ftSwarm inputs

    Don't use this class at all
    """

    def __init__(self, swarm: FtSwarmBase, name: str, normally_open: bool = True, hysteresis: float = 0):
        super().__init__(swarm, name)
        self._normallyOpen = normally_open
        self._value = 0
        self._hysteresis = hysteresis

    async def post_init(self) -> None:
        await self._swarm.send(self._port_name, "setSensorType", await self.get_sensor_type(), self._normallyOpen)
        await self._swarm.send(self._port_name, "subscribe", self._hysteresis)
        self._value = await self._swarm.send(self._port_name, "getValue")

    async def get_sensor_type(self) -> Sensor:
        return Sensor.UNDEFINED

    async def on_trigger(self, trigger_event: Trigger, actor: FtSwarmActorShim, value: int | None = None) -> None:
        # The last parameter is optional, so we need to check if it is None
        await self._swarm.send(self._port_name, "onTrigger", trigger_event, actor.get_port_name(), *([value] or []))

    async def set_value(self, str_value: str) -> None:
        self._value = int(str_value)


class FtSwarmDigitalInput(FtSwarmInput):
    """
    Digital input

    Maps to ports A1...A4 on all controller types
    """

    def __init__(self, swarm: FtSwarmBase, name: str) -> None:
        super().__init__(swarm, name, True, 0)

    async def get_sensor_type(self) -> Sensor:
        return Sensor.DIGITAL

    async def get_toggle(self) -> Toggle:
        return Toggle(await self._swarm.send(self._port_name, "getToggle"))

    async def get_state(self) -> bool:
        return self._value != 0

    async def is_pressed(self) -> bool:
        return await self.get_state()

    async def is_released(self) -> bool:
        return not (await self.get_state())

    async def has_toggled_up(self) -> bool:
        return (await self.get_toggle()) == Toggle.TOGGLEUP

    async def has_toggled_down(self) -> bool:
        return (await self.get_toggle()) == Toggle.TOGGLEDOWN


class FtSwarmSwitch(FtSwarmDigitalInput):
    """
    Mechanical switch
    Maps to ports A1...A4 on all controller types
    Wiring for fischertechnik switches: 1-3 is normally open, 1-2 is normally closed
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.SWITCH


class FtSwarmReedSwitch(FtSwarmDigitalInput):
    """
    Reed switch

    Maps to ports A1...A4 on all controller types
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.REEDSWITCH


class FtSwarmLightBarrier(FtSwarmDigitalInput):
    """
    Light barrier

    Maps to ports A1...A4 on all controller types
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.LIGHTBARRIER


class FtSwarmButton(FtSwarmDigitalInput):
    """
    Onboard button

    This input is only available on the ftSwarmControl
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.BUTTON


class FtSwarmAnalogInput(FtSwarmInput):
    """
    General analog input

    Maps to ports A1...A6 on the ftSwarm specifically
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.ANALOG

    async def get_value(self) -> int:
        return self._value


class FtSwarmVoltmeter(FtSwarmAnalogInput):
    """
    Voltmeter

    Maps to port A2 on the ftSwarm specifically
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.VOLTMETER

    async def get_voltage(self) -> int:
        return await self._swarm.send(self._port_name, "getVoltage")


class FtSwarmOhmmeter(FtSwarmAnalogInput):
    """
    Ohmmeter

    Maps to ports A1...A6 on the ftSwarm specifically
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.OHMMETER

    async def get_resistance(self) -> int:
        return await self._swarm.send(self._port_name, "getResistance")


class FtSwarmThermometer(FtSwarmAnalogInput):
    """
    Thermometer based on 1.5kOhm NTC

    Maps to ports A1...A6 on the ftSwarm specifically
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.THERMOMETER

    async def get_celcius(self) -> int:
        return await self._swarm.send(self._port_name, "getCelcius")

    async def get_kelvin(self) -> int:
        return await self._swarm.send(self._port_name, "getKelvin")

    async def get_fahrenheit(self) -> int:
        return await self._swarm.send(self._port_name, "getFahrenheit")


class FtSwarmLDR(FtSwarmAnalogInput):
    """
    LDR

    Maps to ports A1...A6 on the ftSwarm specifically
    At FtSwarmControl you could use a LDR with a FtSwarmDigitalInput as well
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.LDR


class FtSwarmActor(FtSwarmIO):
    """
    Base class for all actors

    Don't use this class directly, use one of the derived classes instead
    """

    def __init__(self, swarm: FtSwarmBase, port_name: str, high_precision: bool = False) -> None:
        super().__init__(swarm, port_name)
        self._high_precision = high_precision

    async def post_init(self) -> None:
        await self._swarm.send(self._port_name, "setActorType", await self.get_actor_type(), self._high_precision)

    async def get_actor_type(self) -> Actor:
        return Actor.UNDEFINDED


class FtSwarmMotor(FtSwarmActor):
    """
    General motor class, use this class for (old) gray motors, mini motors, XS motors

    M1..M2 all contollers - keep power budget in mind!
    """

    async def get_actor_type(self) -> Actor:
        return Actor.XMOTOR

    async def set_speed(self, speed) -> None:
        await self._swarm.send(self._port_name, "setSpeed", speed)

    async def get_speed(self) -> int:
        return await self._swarm.send(self._port_name, "getSpeed")


class FtSwarmTractorMotor(FtSwarmMotor):
    """
    Tractor & XM motor

    M1..M2 all contollers - keep power budget in mind!
    """

    async def get_actor_type(self) -> Actor:
        return Actor.TRACTOR

    async def set_motion_type(self, motion_type) -> None:
        """
        Set motion type of motor
        FtSwarmTractor has different options for stopping motor:

        :return: None
        """
        await self._swarm.send(self._port_name, "setMotionType", motion_type)

    async def get_motion_type(self) -> MotionType:
        return MotionType(await self._swarm.send(self._port_name, "getMotionType"))

    async def coast(self) -> None:
        await self.set_motion_type(MotionType.COAST)

    async def brake(self) -> None:
        await self.set_motion_type(MotionType.BRAKE)

    async def run(self) -> None:
        await self.set_motion_type(MotionType.ON)


class FtSwarmXMMotor(FtSwarmTractorMotor):
    """
    XM motor

    M1...M2 all contollers - keep power budget in mind!
    """

    async def get_actor_type(self) -> Actor:
        return Actor.XMMOTOR


# TODO: implement encoder input
class FtSwarmEncoderMotor(FtSwarmTractorMotor):
    """
    Encoder motor

    M1...M2 all contollers - keep power budget in mind!
    """

    async def get_actor_type(self) -> Actor:
        return Actor.ENCODER


class FtSwarmLamp(FtSwarmActor):
    """
    Classic lamp or LED

    M1...M2 all contollers - keep power budget in mind!
    """

    async def get_actor_type(self) -> Actor:
        return Actor.LAMP

    async def on(self, power=255) -> None:
        await self._swarm.send(self._port_name, "setSpeed", power)

    async def off(self) -> None:
        await self._swarm.send(self._port_name, "setSpeed", 0)


class FtSwarmBinaryActor(FtSwarmActor):
    """
    Base class for all binary actors

    Don't use this class directly, use one of the derived classes instead
    """

    async def on(self) -> None:
        await self._swarm.send(self._port_name, "setSpeed", 255)

    async def off(self) -> None:
        await self._swarm.send(self._port_name, "setSpeed", 0)


class FtSwarmValve(FtSwarmBinaryActor):
    """
    Electromagnetic Valve

    M1...M2 all contollers - keep power budget in mind!
    """

    async def get_actor_type(self) -> Actor:
        return Actor.VALVE


class FtSwarmCompressor(FtSwarmBinaryActor):
    """
    Compressor

    M1...M2 all contollers - keep power budget in mind!
    """

    async def get_actor_type(self) -> Actor:
        return Actor.COMPRESSOR


class FtSwarmBuzzer(FtSwarmBinaryActor):
    """
    Buzzer

    M1...M2 all contollers - keep power budget in mind!
    """

    async def get_actor_type(self) -> Actor:
        return Actor.BUZZER


class FtSwarmServo(FtSwarmIO):
    """
    Servo

    ftSwarm only

    A servo has 150mA typically, higher values with load. Keep power budget in mind!
    """

    def __init__(self, swarm, port_name) -> None:
        super().__init__(swarm, port_name)
        self._position = 0
        self._offset = 0

    async def post_init(self) -> None:
        self._offset = self._swarm.send(self._port_name, "getOffset")
        self._position = self._swarm.send(self._port_name, "getPositon")

    async def get_position(self) -> int:
        return self._position

    async def set_position(self, position) -> None:
        self._position = position
        await self._swarm.send(self._port_name, "setPosition", position)

    async def get_offset(self) -> int:
        return self._offset

    async def set_offset(self, offset) -> None:
        self._offset = offset
        await self._swarm.send(self._port_name, "setOffset", offset)


class FtSwarmJoystick(FtSwarmIO):
    """
    Joystick

    ftSwarmControl only
    """

    def __init__(self, swarm, port_name, hysteresis) -> None:
        super().__init__(swarm, port_name)
        self._lr = 0
        self._fb = 0
        self._hysteresis = hysteresis

    async def post_init(self) -> None:
        await self._swarm.send(self._port_name, "subscribe", self._hysteresis)

    async def get_fb(self) -> int:
        return self._fb

    async def get_lr(self) -> int:
        return self._lr

    async def on_trigger_lr(self, trigger_event, actor, p1=None) -> None:
        await self._swarm.send(self._port_name, "onTriggerLR", trigger_event, actor, *(p1 or []))

    async def on_trigger_fb(self, trigger_event, actor, p1=None) -> None:
        await self._swarm.send(self._port_name, "onTriggerFB", trigger_event, actor, *(p1 or []))


class FtSwarmPixel(FtSwarmIO):
    """
    RGB LED

    ftSwarm only
    One LED takes up to 60mA, keep power budget in mind!
    """

    def __init__(self, swarm, port_name) -> None:
        super().__init__(swarm, port_name)
        self._brightness = 0
        self._color = 0

    async def post_init(self) -> None:
        self._brightness = await self._swarm.send(self._port_name, "getBrightness")
        self._color = await self._swarm.send(self._port_name, "getColor")

    async def get_brightness(self) -> int:
        """
        Get the brightness of the LED
        :return:  brightness 0..255
        """
        return self._brightness

    async def set_brightness(self, brightness) -> None:
        self._brightness = brightness
        await self._swarm.send(self._port_name, "setBrightness", brightness)

    async def get_color(self) -> int:
        return self._color

    async def set_color(self, color) -> None:
        # If color is a tuple, reformat it as hex
        if isinstance(color, tuple) or isinstance(color, list):
            color = (color[0] << 16) + (color[1] << 8) + color[2]
        self._color = color
        await self._swarm.send(self._port_name, "setColor", color)


class FtSwarmI2C(FtSwarmIO):
    """
    I2C slave with 4 registers
    """

    def __init__(self, swarm, port_name) -> None:
        super().__init__(swarm, port_name)
        self.__register = [0, 0, 0, 0, 0, 0, 0, 0]

    async def post_init(self) -> None:
        for i in range(8):
            self.__register[i] = await self._swarm.send(self._port_name, "getRegister", i)
        await self._swarm.send(self._port_name, "subscribe")

    async def get_register(self, reg) -> int:
        return self.__register[reg]

    async def set_register(self, reg, value) -> None:
        self.__register[reg] = value
        await self._swarm.send(self._port_name, "setRegister", reg, value)

    async def on_trigger(self, trigger_event, actor, p1) -> None:
        await self._swarm.send(self._port_name, "onTrigger", trigger_event, actor.get_port_name(), p1)

Classes

class Actor (value, names=None, *, module=None, qualname=None, type=None, start=1)

All Actor types known by the ftSwarm

Expand source code
class Actor(IntEnum):
    """All Actor types known by the ftSwarm"""
    UNDEFINDED = -1
    XMOTOR = 0
    XMMOTOR = 1
    TRACTOR = 2
    ENCODER = 3
    LAMP = 4
    VALVE = 5
    COMPRESSOR = 6
    BUZZER = 7

Ancestors

  • enum.IntEnum
  • builtins.int
  • enum.Enum

Class variables

var BUZZER
var COMPRESSOR
var ENCODER
var LAMP
var TRACTOR
var UNDEFINDED
var VALVE
var XMMOTOR
var XMOTOR
class Align (value, names=None, *, module=None, qualname=None, type=None, start=1)

Text alignment for display

Expand source code
class Align(IntEnum):
    """Text alignment for display"""
    ALIGNLEFT = 0
    ALIGNCENTER = 1
    ALIGNRIGHT = 2

Ancestors

  • enum.IntEnum
  • builtins.int
  • enum.Enum

Class variables

var ALIGNCENTER
var ALIGNLEFT
var ALIGNRIGHT
class FtSwarmActor (swarm: FtSwarmBase, port_name: str, high_precision: bool = False)

Base class for all actors

Don't use this class directly, use one of the derived classes instead

Expand source code
class FtSwarmActor(FtSwarmIO):
    """
    Base class for all actors

    Don't use this class directly, use one of the derived classes instead
    """

    def __init__(self, swarm: FtSwarmBase, port_name: str, high_precision: bool = False) -> None:
        super().__init__(swarm, port_name)
        self._high_precision = high_precision

    async def post_init(self) -> None:
        await self._swarm.send(self._port_name, "setActorType", await self.get_actor_type(), self._high_precision)

    async def get_actor_type(self) -> Actor:
        return Actor.UNDEFINDED

Ancestors

Subclasses

Methods

async def get_actor_type(self) ‑> Actor
Expand source code
async def get_actor_type(self) -> Actor:
    return Actor.UNDEFINDED
async def post_init(self) ‑> NoneType
Expand source code
async def post_init(self) -> None:
    await self._swarm.send(self._port_name, "setActorType", await self.get_actor_type(), self._high_precision)
class FtSwarmActorShim (swarm: FtSwarmBase, port_name: str)

Shim class for all ftSwarm actors for type annotations

Don't use this class at all

Expand source code
class FtSwarmActorShim(FtSwarmIO):
    """
    Shim class for all ftSwarm actors for type annotations

    Don't use this class at all
    """

    def get_port_name(self) -> str:
        pass

Ancestors

Methods

def get_port_name(self) ‑> str
Expand source code
def get_port_name(self) -> str:
    pass
class FtSwarmAnalogInput (swarm: FtSwarmBase, name: str, normally_open: bool = True, hysteresis: float = 0)

General analog input

Maps to ports A1…A6 on the ftSwarm specifically

Expand source code
class FtSwarmAnalogInput(FtSwarmInput):
    """
    General analog input

    Maps to ports A1...A6 on the ftSwarm specifically
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.ANALOG

    async def get_value(self) -> int:
        return self._value

Ancestors

Subclasses

Methods

async def get_sensor_type(self) ‑> Sensor
Expand source code
async def get_sensor_type(self) -> Sensor:
    return Sensor.ANALOG
async def get_value(self) ‑> int
Expand source code
async def get_value(self) -> int:
    return self._value
class FtSwarmBase

Base class for all ftSwarm implementations

Expand source code
class FtSwarmBase:
    """Base class for all ftSwarm implementations"""

    def __init__(self) -> None:
        self.logger = logging.getLogger("swarm-base")

    async def send(self, port_name: str, command: str, *args: str | int | float) -> int | str | None:
        pass

Subclasses

Methods

async def send(self, port_name: str, command: str, *args: str | int | float) ‑> int | str | None
Expand source code
async def send(self, port_name: str, command: str, *args: str | int | float) -> int | str | None:
    pass
class FtSwarmBinaryActor (swarm: FtSwarmBase, port_name: str, high_precision: bool = False)

Base class for all binary actors

Don't use this class directly, use one of the derived classes instead

Expand source code
class FtSwarmBinaryActor(FtSwarmActor):
    """
    Base class for all binary actors

    Don't use this class directly, use one of the derived classes instead
    """

    async def on(self) -> None:
        await self._swarm.send(self._port_name, "setSpeed", 255)

    async def off(self) -> None:
        await self._swarm.send(self._port_name, "setSpeed", 0)

Ancestors

Subclasses

Methods

async def off(self) ‑> NoneType
Expand source code
async def off(self) -> None:
    await self._swarm.send(self._port_name, "setSpeed", 0)
async def on(self) ‑> NoneType
Expand source code
async def on(self) -> None:
    await self._swarm.send(self._port_name, "setSpeed", 255)
class FtSwarmButton (swarm: FtSwarmBase, name: str)

Onboard button

This input is only available on the ftSwarmControl

Expand source code
class FtSwarmButton(FtSwarmDigitalInput):
    """
    Onboard button

    This input is only available on the ftSwarmControl
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.BUTTON

Ancestors

Methods

async def get_sensor_type(self) ‑> Sensor
Expand source code
async def get_sensor_type(self) -> Sensor:
    return Sensor.BUTTON
class FtSwarmBuzzer (swarm: FtSwarmBase, port_name: str, high_precision: bool = False)

Buzzer

M1…M2 all contollers - keep power budget in mind!

Expand source code
class FtSwarmBuzzer(FtSwarmBinaryActor):
    """
    Buzzer

    M1...M2 all contollers - keep power budget in mind!
    """

    async def get_actor_type(self) -> Actor:
        return Actor.BUZZER

Ancestors

Methods

async def get_actor_type(self) ‑> Actor
Expand source code
async def get_actor_type(self) -> Actor:
    return Actor.BUZZER
class FtSwarmCompressor (swarm: FtSwarmBase, port_name: str, high_precision: bool = False)

Compressor

M1…M2 all contollers - keep power budget in mind!

Expand source code
class FtSwarmCompressor(FtSwarmBinaryActor):
    """
    Compressor

    M1...M2 all contollers - keep power budget in mind!
    """

    async def get_actor_type(self) -> Actor:
        return Actor.COMPRESSOR

Ancestors

Methods

async def get_actor_type(self) ‑> Actor
Expand source code
async def get_actor_type(self) -> Actor:
    return Actor.COMPRESSOR
class FtSwarmDigitalInput (swarm: FtSwarmBase, name: str)

Digital input

Maps to ports A1…A4 on all controller types

Expand source code
class FtSwarmDigitalInput(FtSwarmInput):
    """
    Digital input

    Maps to ports A1...A4 on all controller types
    """

    def __init__(self, swarm: FtSwarmBase, name: str) -> None:
        super().__init__(swarm, name, True, 0)

    async def get_sensor_type(self) -> Sensor:
        return Sensor.DIGITAL

    async def get_toggle(self) -> Toggle:
        return Toggle(await self._swarm.send(self._port_name, "getToggle"))

    async def get_state(self) -> bool:
        return self._value != 0

    async def is_pressed(self) -> bool:
        return await self.get_state()

    async def is_released(self) -> bool:
        return not (await self.get_state())

    async def has_toggled_up(self) -> bool:
        return (await self.get_toggle()) == Toggle.TOGGLEUP

    async def has_toggled_down(self) -> bool:
        return (await self.get_toggle()) == Toggle.TOGGLEDOWN

Ancestors

Subclasses

Methods

async def get_sensor_type(self) ‑> Sensor
Expand source code
async def get_sensor_type(self) -> Sensor:
    return Sensor.DIGITAL
async def get_state(self) ‑> bool
Expand source code
async def get_state(self) -> bool:
    return self._value != 0
async def get_toggle(self) ‑> Toggle
Expand source code
async def get_toggle(self) -> Toggle:
    return Toggle(await self._swarm.send(self._port_name, "getToggle"))
async def has_toggled_down(self) ‑> bool
Expand source code
async def has_toggled_down(self) -> bool:
    return (await self.get_toggle()) == Toggle.TOGGLEDOWN
async def has_toggled_up(self) ‑> bool
Expand source code
async def has_toggled_up(self) -> bool:
    return (await self.get_toggle()) == Toggle.TOGGLEUP
async def is_pressed(self) ‑> bool
Expand source code
async def is_pressed(self) -> bool:
    return await self.get_state()
async def is_released(self) ‑> bool
Expand source code
async def is_released(self) -> bool:
    return not (await self.get_state())
class FtSwarmEncoderMotor (swarm: FtSwarmBase, port_name: str, high_precision: bool = False)

Encoder motor

M1…M2 all contollers - keep power budget in mind!

Expand source code
class FtSwarmEncoderMotor(FtSwarmTractorMotor):
    """
    Encoder motor

    M1...M2 all contollers - keep power budget in mind!
    """

    async def get_actor_type(self) -> Actor:
        return Actor.ENCODER

Ancestors

Methods

async def get_actor_type(self) ‑> Actor
Expand source code
async def get_actor_type(self) -> Actor:
    return Actor.ENCODER

Inherited members

class FtSwarmI2C (swarm, port_name)

I2C slave with 4 registers

Expand source code
class FtSwarmI2C(FtSwarmIO):
    """
    I2C slave with 4 registers
    """

    def __init__(self, swarm, port_name) -> None:
        super().__init__(swarm, port_name)
        self.__register = [0, 0, 0, 0, 0, 0, 0, 0]

    async def post_init(self) -> None:
        for i in range(8):
            self.__register[i] = await self._swarm.send(self._port_name, "getRegister", i)
        await self._swarm.send(self._port_name, "subscribe")

    async def get_register(self, reg) -> int:
        return self.__register[reg]

    async def set_register(self, reg, value) -> None:
        self.__register[reg] = value
        await self._swarm.send(self._port_name, "setRegister", reg, value)

    async def on_trigger(self, trigger_event, actor, p1) -> None:
        await self._swarm.send(self._port_name, "onTrigger", trigger_event, actor.get_port_name(), p1)

Ancestors

Methods

async def get_register(self, reg) ‑> int
Expand source code
async def get_register(self, reg) -> int:
    return self.__register[reg]
async def on_trigger(self, trigger_event, actor, p1) ‑> NoneType
Expand source code
async def on_trigger(self, trigger_event, actor, p1) -> None:
    await self._swarm.send(self._port_name, "onTrigger", trigger_event, actor.get_port_name(), p1)
async def post_init(self) ‑> NoneType
Expand source code
async def post_init(self) -> None:
    for i in range(8):
        self.__register[i] = await self._swarm.send(self._port_name, "getRegister", i)
    await self._swarm.send(self._port_name, "subscribe")
async def set_register(self, reg, value) ‑> NoneType
Expand source code
async def set_register(self, reg, value) -> None:
    self.__register[reg] = value
    await self._swarm.send(self._port_name, "setRegister", reg, value)
class FtSwarmIO (swarm: FtSwarmBase, port_name: str)

Base class for all ftSwarm interfaces

Don't use this class at all

Expand source code
class FtSwarmIO:
    """
    Base class for all ftSwarm interfaces

    Don't use this class at all
    """

    def __init__(self, swarm: FtSwarmBase, port_name: str) -> None:
        self._port_name = port_name
        self._swarm = swarm

    async def post_init(self) -> None:
        pass

    async def get_port_name(self) -> str:
        return self._port_name

    async def set_value(self, value: str) -> None:
        self._swarm.logger.warning(f"Received unexpected write to {self._port_name}: {value}")

Subclasses

Methods

async def get_port_name(self) ‑> str
Expand source code
async def get_port_name(self) -> str:
    return self._port_name
async def post_init(self) ‑> NoneType
Expand source code
async def post_init(self) -> None:
    pass
async def set_value(self, value: str) ‑> NoneType
Expand source code
async def set_value(self, value: str) -> None:
    self._swarm.logger.warning(f"Received unexpected write to {self._port_name}: {value}")
class FtSwarmInput (swarm: FtSwarmBase, name: str, normally_open: bool = True, hysteresis: float = 0)

Base class for all ftSwarm inputs

Don't use this class at all

Expand source code
class FtSwarmInput(FtSwarmIO):
    """
    Base class for all ftSwarm inputs

    Don't use this class at all
    """

    def __init__(self, swarm: FtSwarmBase, name: str, normally_open: bool = True, hysteresis: float = 0):
        super().__init__(swarm, name)
        self._normallyOpen = normally_open
        self._value = 0
        self._hysteresis = hysteresis

    async def post_init(self) -> None:
        await self._swarm.send(self._port_name, "setSensorType", await self.get_sensor_type(), self._normallyOpen)
        await self._swarm.send(self._port_name, "subscribe", self._hysteresis)
        self._value = await self._swarm.send(self._port_name, "getValue")

    async def get_sensor_type(self) -> Sensor:
        return Sensor.UNDEFINED

    async def on_trigger(self, trigger_event: Trigger, actor: FtSwarmActorShim, value: int | None = None) -> None:
        # The last parameter is optional, so we need to check if it is None
        await self._swarm.send(self._port_name, "onTrigger", trigger_event, actor.get_port_name(), *([value] or []))

    async def set_value(self, str_value: str) -> None:
        self._value = int(str_value)

Ancestors

Subclasses

Methods

async def get_sensor_type(self) ‑> Sensor
Expand source code
async def get_sensor_type(self) -> Sensor:
    return Sensor.UNDEFINED
async def on_trigger(self, trigger_event: Trigger, actor: FtSwarmActorShim, value: int | None = None) ‑> NoneType
Expand source code
async def on_trigger(self, trigger_event: Trigger, actor: FtSwarmActorShim, value: int | None = None) -> None:
    # The last parameter is optional, so we need to check if it is None
    await self._swarm.send(self._port_name, "onTrigger", trigger_event, actor.get_port_name(), *([value] or []))
async def post_init(self) ‑> NoneType
Expand source code
async def post_init(self) -> None:
    await self._swarm.send(self._port_name, "setSensorType", await self.get_sensor_type(), self._normallyOpen)
    await self._swarm.send(self._port_name, "subscribe", self._hysteresis)
    self._value = await self._swarm.send(self._port_name, "getValue")
async def set_value(self, str_value: str) ‑> NoneType
Expand source code
async def set_value(self, str_value: str) -> None:
    self._value = int(str_value)
class FtSwarmJoystick (swarm, port_name, hysteresis)

Joystick

ftSwarmControl only

Expand source code
class FtSwarmJoystick(FtSwarmIO):
    """
    Joystick

    ftSwarmControl only
    """

    def __init__(self, swarm, port_name, hysteresis) -> None:
        super().__init__(swarm, port_name)
        self._lr = 0
        self._fb = 0
        self._hysteresis = hysteresis

    async def post_init(self) -> None:
        await self._swarm.send(self._port_name, "subscribe", self._hysteresis)

    async def get_fb(self) -> int:
        return self._fb

    async def get_lr(self) -> int:
        return self._lr

    async def on_trigger_lr(self, trigger_event, actor, p1=None) -> None:
        await self._swarm.send(self._port_name, "onTriggerLR", trigger_event, actor, *(p1 or []))

    async def on_trigger_fb(self, trigger_event, actor, p1=None) -> None:
        await self._swarm.send(self._port_name, "onTriggerFB", trigger_event, actor, *(p1 or []))

Ancestors

Methods

async def get_fb(self) ‑> int
Expand source code
async def get_fb(self) -> int:
    return self._fb
async def get_lr(self) ‑> int
Expand source code
async def get_lr(self) -> int:
    return self._lr
async def on_trigger_fb(self, trigger_event, actor, p1=None) ‑> NoneType
Expand source code
async def on_trigger_fb(self, trigger_event, actor, p1=None) -> None:
    await self._swarm.send(self._port_name, "onTriggerFB", trigger_event, actor, *(p1 or []))
async def on_trigger_lr(self, trigger_event, actor, p1=None) ‑> NoneType
Expand source code
async def on_trigger_lr(self, trigger_event, actor, p1=None) -> None:
    await self._swarm.send(self._port_name, "onTriggerLR", trigger_event, actor, *(p1 or []))
async def post_init(self) ‑> NoneType
Expand source code
async def post_init(self) -> None:
    await self._swarm.send(self._port_name, "subscribe", self._hysteresis)
class FtSwarmLDR (swarm: FtSwarmBase, name: str, normally_open: bool = True, hysteresis: float = 0)

LDR

Maps to ports A1…A6 on the ftSwarm specifically At FtSwarmControl you could use a LDR with a FtSwarmDigitalInput as well

Expand source code
class FtSwarmLDR(FtSwarmAnalogInput):
    """
    LDR

    Maps to ports A1...A6 on the ftSwarm specifically
    At FtSwarmControl you could use a LDR with a FtSwarmDigitalInput as well
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.LDR

Ancestors

Methods

async def get_sensor_type(self) ‑> Sensor
Expand source code
async def get_sensor_type(self) -> Sensor:
    return Sensor.LDR
class FtSwarmLamp (swarm: FtSwarmBase, port_name: str, high_precision: bool = False)

Classic lamp or LED

M1…M2 all contollers - keep power budget in mind!

Expand source code
class FtSwarmLamp(FtSwarmActor):
    """
    Classic lamp or LED

    M1...M2 all contollers - keep power budget in mind!
    """

    async def get_actor_type(self) -> Actor:
        return Actor.LAMP

    async def on(self, power=255) -> None:
        await self._swarm.send(self._port_name, "setSpeed", power)

    async def off(self) -> None:
        await self._swarm.send(self._port_name, "setSpeed", 0)

Ancestors

Methods

async def get_actor_type(self) ‑> Actor
Expand source code
async def get_actor_type(self) -> Actor:
    return Actor.LAMP
async def off(self) ‑> NoneType
Expand source code
async def off(self) -> None:
    await self._swarm.send(self._port_name, "setSpeed", 0)
async def on(self, power=255) ‑> NoneType
Expand source code
async def on(self, power=255) -> None:
    await self._swarm.send(self._port_name, "setSpeed", power)
class FtSwarmLightBarrier (swarm: FtSwarmBase, name: str)

Light barrier

Maps to ports A1…A4 on all controller types

Expand source code
class FtSwarmLightBarrier(FtSwarmDigitalInput):
    """
    Light barrier

    Maps to ports A1...A4 on all controller types
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.LIGHTBARRIER

Ancestors

Methods

async def get_sensor_type(self) ‑> Sensor
Expand source code
async def get_sensor_type(self) -> Sensor:
    return Sensor.LIGHTBARRIER
class FtSwarmMotor (swarm: FtSwarmBase, port_name: str, high_precision: bool = False)

General motor class, use this class for (old) gray motors, mini motors, XS motors

M1..M2 all contollers - keep power budget in mind!

Expand source code
class FtSwarmMotor(FtSwarmActor):
    """
    General motor class, use this class for (old) gray motors, mini motors, XS motors

    M1..M2 all contollers - keep power budget in mind!
    """

    async def get_actor_type(self) -> Actor:
        return Actor.XMOTOR

    async def set_speed(self, speed) -> None:
        await self._swarm.send(self._port_name, "setSpeed", speed)

    async def get_speed(self) -> int:
        return await self._swarm.send(self._port_name, "getSpeed")

Ancestors

Subclasses

Methods

async def get_actor_type(self) ‑> Actor
Expand source code
async def get_actor_type(self) -> Actor:
    return Actor.XMOTOR
async def get_speed(self) ‑> int
Expand source code
async def get_speed(self) -> int:
    return await self._swarm.send(self._port_name, "getSpeed")
async def set_speed(self, speed) ‑> NoneType
Expand source code
async def set_speed(self, speed) -> None:
    await self._swarm.send(self._port_name, "setSpeed", speed)
class FtSwarmOhmmeter (swarm: FtSwarmBase, name: str, normally_open: bool = True, hysteresis: float = 0)

Ohmmeter

Maps to ports A1…A6 on the ftSwarm specifically

Expand source code
class FtSwarmOhmmeter(FtSwarmAnalogInput):
    """
    Ohmmeter

    Maps to ports A1...A6 on the ftSwarm specifically
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.OHMMETER

    async def get_resistance(self) -> int:
        return await self._swarm.send(self._port_name, "getResistance")

Ancestors

Methods

async def get_resistance(self) ‑> int
Expand source code
async def get_resistance(self) -> int:
    return await self._swarm.send(self._port_name, "getResistance")
async def get_sensor_type(self) ‑> Sensor
Expand source code
async def get_sensor_type(self) -> Sensor:
    return Sensor.OHMMETER
class FtSwarmPixel (swarm, port_name)

RGB LED

ftSwarm only One LED takes up to 60mA, keep power budget in mind!

Expand source code
class FtSwarmPixel(FtSwarmIO):
    """
    RGB LED

    ftSwarm only
    One LED takes up to 60mA, keep power budget in mind!
    """

    def __init__(self, swarm, port_name) -> None:
        super().__init__(swarm, port_name)
        self._brightness = 0
        self._color = 0

    async def post_init(self) -> None:
        self._brightness = await self._swarm.send(self._port_name, "getBrightness")
        self._color = await self._swarm.send(self._port_name, "getColor")

    async def get_brightness(self) -> int:
        """
        Get the brightness of the LED
        :return:  brightness 0..255
        """
        return self._brightness

    async def set_brightness(self, brightness) -> None:
        self._brightness = brightness
        await self._swarm.send(self._port_name, "setBrightness", brightness)

    async def get_color(self) -> int:
        return self._color

    async def set_color(self, color) -> None:
        # If color is a tuple, reformat it as hex
        if isinstance(color, tuple) or isinstance(color, list):
            color = (color[0] << 16) + (color[1] << 8) + color[2]
        self._color = color
        await self._swarm.send(self._port_name, "setColor", color)

Ancestors

Methods

async def get_brightness(self) ‑> int

Get the brightness of the LED :return: brightness 0..255

Expand source code
async def get_brightness(self) -> int:
    """
    Get the brightness of the LED
    :return:  brightness 0..255
    """
    return self._brightness
async def get_color(self) ‑> int
Expand source code
async def get_color(self) -> int:
    return self._color
async def post_init(self) ‑> NoneType
Expand source code
async def post_init(self) -> None:
    self._brightness = await self._swarm.send(self._port_name, "getBrightness")
    self._color = await self._swarm.send(self._port_name, "getColor")
async def set_brightness(self, brightness) ‑> NoneType
Expand source code
async def set_brightness(self, brightness) -> None:
    self._brightness = brightness
    await self._swarm.send(self._port_name, "setBrightness", brightness)
async def set_color(self, color) ‑> NoneType
Expand source code
async def set_color(self, color) -> None:
    # If color is a tuple, reformat it as hex
    if isinstance(color, tuple) or isinstance(color, list):
        color = (color[0] << 16) + (color[1] << 8) + color[2]
    self._color = color
    await self._swarm.send(self._port_name, "setColor", color)
class FtSwarmReedSwitch (swarm: FtSwarmBase, name: str)

Reed switch

Maps to ports A1…A4 on all controller types

Expand source code
class FtSwarmReedSwitch(FtSwarmDigitalInput):
    """
    Reed switch

    Maps to ports A1...A4 on all controller types
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.REEDSWITCH

Ancestors

Methods

async def get_sensor_type(self) ‑> Sensor
Expand source code
async def get_sensor_type(self) -> Sensor:
    return Sensor.REEDSWITCH
class FtSwarmServo (swarm, port_name)

Servo

ftSwarm only

A servo has 150mA typically, higher values with load. Keep power budget in mind!

Expand source code
class FtSwarmServo(FtSwarmIO):
    """
    Servo

    ftSwarm only

    A servo has 150mA typically, higher values with load. Keep power budget in mind!
    """

    def __init__(self, swarm, port_name) -> None:
        super().__init__(swarm, port_name)
        self._position = 0
        self._offset = 0

    async def post_init(self) -> None:
        self._offset = self._swarm.send(self._port_name, "getOffset")
        self._position = self._swarm.send(self._port_name, "getPositon")

    async def get_position(self) -> int:
        return self._position

    async def set_position(self, position) -> None:
        self._position = position
        await self._swarm.send(self._port_name, "setPosition", position)

    async def get_offset(self) -> int:
        return self._offset

    async def set_offset(self, offset) -> None:
        self._offset = offset
        await self._swarm.send(self._port_name, "setOffset", offset)

Ancestors

Methods

async def get_offset(self) ‑> int
Expand source code
async def get_offset(self) -> int:
    return self._offset
async def get_position(self) ‑> int
Expand source code
async def get_position(self) -> int:
    return self._position
async def post_init(self) ‑> NoneType
Expand source code
async def post_init(self) -> None:
    self._offset = self._swarm.send(self._port_name, "getOffset")
    self._position = self._swarm.send(self._port_name, "getPositon")
async def set_offset(self, offset) ‑> NoneType
Expand source code
async def set_offset(self, offset) -> None:
    self._offset = offset
    await self._swarm.send(self._port_name, "setOffset", offset)
async def set_position(self, position) ‑> NoneType
Expand source code
async def set_position(self, position) -> None:
    self._position = position
    await self._swarm.send(self._port_name, "setPosition", position)
class FtSwarmSwitch (swarm: FtSwarmBase, name: str)

Mechanical switch Maps to ports A1…A4 on all controller types Wiring for fischertechnik switches: 1-3 is normally open, 1-2 is normally closed

Expand source code
class FtSwarmSwitch(FtSwarmDigitalInput):
    """
    Mechanical switch
    Maps to ports A1...A4 on all controller types
    Wiring for fischertechnik switches: 1-3 is normally open, 1-2 is normally closed
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.SWITCH

Ancestors

Methods

async def get_sensor_type(self) ‑> Sensor
Expand source code
async def get_sensor_type(self) -> Sensor:
    return Sensor.SWITCH
class FtSwarmThermometer (swarm: FtSwarmBase, name: str, normally_open: bool = True, hysteresis: float = 0)

Thermometer based on 1.5kOhm NTC

Maps to ports A1…A6 on the ftSwarm specifically

Expand source code
class FtSwarmThermometer(FtSwarmAnalogInput):
    """
    Thermometer based on 1.5kOhm NTC

    Maps to ports A1...A6 on the ftSwarm specifically
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.THERMOMETER

    async def get_celcius(self) -> int:
        return await self._swarm.send(self._port_name, "getCelcius")

    async def get_kelvin(self) -> int:
        return await self._swarm.send(self._port_name, "getKelvin")

    async def get_fahrenheit(self) -> int:
        return await self._swarm.send(self._port_name, "getFahrenheit")

Ancestors

Methods

async def get_celcius(self) ‑> int
Expand source code
async def get_celcius(self) -> int:
    return await self._swarm.send(self._port_name, "getCelcius")
async def get_fahrenheit(self) ‑> int
Expand source code
async def get_fahrenheit(self) -> int:
    return await self._swarm.send(self._port_name, "getFahrenheit")
async def get_kelvin(self) ‑> int
Expand source code
async def get_kelvin(self) -> int:
    return await self._swarm.send(self._port_name, "getKelvin")
async def get_sensor_type(self) ‑> Sensor
Expand source code
async def get_sensor_type(self) -> Sensor:
    return Sensor.THERMOMETER
class FtSwarmTractorMotor (swarm: FtSwarmBase, port_name: str, high_precision: bool = False)

Tractor & XM motor

M1..M2 all contollers - keep power budget in mind!

Expand source code
class FtSwarmTractorMotor(FtSwarmMotor):
    """
    Tractor & XM motor

    M1..M2 all contollers - keep power budget in mind!
    """

    async def get_actor_type(self) -> Actor:
        return Actor.TRACTOR

    async def set_motion_type(self, motion_type) -> None:
        """
        Set motion type of motor
        FtSwarmTractor has different options for stopping motor:

        :return: None
        """
        await self._swarm.send(self._port_name, "setMotionType", motion_type)

    async def get_motion_type(self) -> MotionType:
        return MotionType(await self._swarm.send(self._port_name, "getMotionType"))

    async def coast(self) -> None:
        await self.set_motion_type(MotionType.COAST)

    async def brake(self) -> None:
        await self.set_motion_type(MotionType.BRAKE)

    async def run(self) -> None:
        await self.set_motion_type(MotionType.ON)

Ancestors

Subclasses

Methods

async def brake(self) ‑> NoneType
Expand source code
async def brake(self) -> None:
    await self.set_motion_type(MotionType.BRAKE)
async def coast(self) ‑> NoneType
Expand source code
async def coast(self) -> None:
    await self.set_motion_type(MotionType.COAST)
async def get_actor_type(self) ‑> Actor
Expand source code
async def get_actor_type(self) -> Actor:
    return Actor.TRACTOR
async def get_motion_type(self) ‑> MotionType
Expand source code
async def get_motion_type(self) -> MotionType:
    return MotionType(await self._swarm.send(self._port_name, "getMotionType"))
async def run(self) ‑> NoneType
Expand source code
async def run(self) -> None:
    await self.set_motion_type(MotionType.ON)
async def set_motion_type(self, motion_type) ‑> NoneType

Set motion type of motor FtSwarmTractor has different options for stopping motor:

:return: None

Expand source code
async def set_motion_type(self, motion_type) -> None:
    """
    Set motion type of motor
    FtSwarmTractor has different options for stopping motor:

    :return: None
    """
    await self._swarm.send(self._port_name, "setMotionType", motion_type)
class FtSwarmValve (swarm: FtSwarmBase, port_name: str, high_precision: bool = False)

Electromagnetic Valve

M1…M2 all contollers - keep power budget in mind!

Expand source code
class FtSwarmValve(FtSwarmBinaryActor):
    """
    Electromagnetic Valve

    M1...M2 all contollers - keep power budget in mind!
    """

    async def get_actor_type(self) -> Actor:
        return Actor.VALVE

Ancestors

Methods

async def get_actor_type(self) ‑> Actor
Expand source code
async def get_actor_type(self) -> Actor:
    return Actor.VALVE
class FtSwarmVoltmeter (swarm: FtSwarmBase, name: str, normally_open: bool = True, hysteresis: float = 0)

Voltmeter

Maps to port A2 on the ftSwarm specifically

Expand source code
class FtSwarmVoltmeter(FtSwarmAnalogInput):
    """
    Voltmeter

    Maps to port A2 on the ftSwarm specifically
    """

    async def get_sensor_type(self) -> Sensor:
        return Sensor.VOLTMETER

    async def get_voltage(self) -> int:
        return await self._swarm.send(self._port_name, "getVoltage")

Ancestors

Methods

async def get_sensor_type(self) ‑> Sensor
Expand source code
async def get_sensor_type(self) -> Sensor:
    return Sensor.VOLTMETER
async def get_voltage(self) ‑> int
Expand source code
async def get_voltage(self) -> int:
    return await self._swarm.send(self._port_name, "getVoltage")
class FtSwarmXMMotor (swarm: FtSwarmBase, port_name: str, high_precision: bool = False)

XM motor

M1…M2 all contollers - keep power budget in mind!

Expand source code
class FtSwarmXMMotor(FtSwarmTractorMotor):
    """
    XM motor

    M1...M2 all contollers - keep power budget in mind!
    """

    async def get_actor_type(self) -> Actor:
        return Actor.XMMOTOR

Ancestors

Methods

async def get_actor_type(self) ‑> Actor
Expand source code
async def get_actor_type(self) -> Actor:
    return Actor.XMMOTOR

Inherited members

class MotionType (value, names=None, *, module=None, qualname=None, type=None, start=1)

How to move a motor

Expand source code
class MotionType(IntEnum):
    """How to move a motor"""
    COAST = 0
    BRAKE = 1
    ON = 2

Ancestors

  • enum.IntEnum
  • builtins.int
  • enum.Enum

Class variables

var BRAKE
var COAST
var ON
class Sensor (value, names=None, *, module=None, qualname=None, type=None, start=1)

All Sensor types known by the ftSwarm

Expand source code
class Sensor(IntEnum):
    """All Sensor types known by the ftSwarm"""
    UNDEFINED = -1
    DIGITAL = 0
    ANALOG = 1
    SWITCH = 2
    REEDSWITCH = 3
    LIGHTBARRIER = 4
    VOLTMETER = 5
    OHMMETER = 6
    THERMOMETER = 7
    LDR = 8
    TRAILSENSOR = 9
    COLORSENSOR = 10
    ULTRASONIC = 11
    BUTTON = 12

Ancestors

  • enum.IntEnum
  • builtins.int
  • enum.Enum

Class variables

var ANALOG
var BUTTON
var COLORSENSOR
var DIGITAL
var LDR
var LIGHTBARRIER
var OHMMETER
var REEDSWITCH
var SWITCH
var THERMOMETER
var TRAILSENSOR
var ULTRASONIC
var UNDEFINED
var VOLTMETER
class Toggle (value, names=None, *, module=None, qualname=None, type=None, start=1)

Toggle states

Expand source code
class Toggle(IntEnum):
    """Toggle states"""
    NOTOGGLE = 0
    TOGGLEUP = 1
    TOGGLEDOWN = 2

Ancestors

  • enum.IntEnum
  • builtins.int
  • enum.Enum

Class variables

var NOTOGGLE
var TOGGLEDOWN
var TOGGLEUP
class Trigger (value, names=None, *, module=None, qualname=None, type=None, start=1)

Trigger events

Expand source code
class Trigger(IntEnum):
    """Trigger events"""
    TRIGGERUP = 0
    TRIGGERDOWN = 1
    TRIGGERVALUE = 2
    TRIGGERI2CREAD = 3
    TRIGGERI2CWRITE = 4

Ancestors

  • enum.IntEnum
  • builtins.int
  • enum.Enum

Class variables

var TRIGGERDOWN
var TRIGGERI2CREAD
var TRIGGERI2CWRITE
var TRIGGERUP
var TRIGGERVALUE