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 = 7Ancestors
- enum.IntEnum
- builtins.int
- enum.Enum
Class variables
var BUZZERvar COMPRESSORvar ENCODERvar LAMPvar TRACTORvar UNDEFINDEDvar VALVEvar XMMOTORvar 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 = 2Ancestors
- enum.IntEnum
- builtins.int
- enum.Enum
Class variables
var ALIGNCENTERvar ALIGNLEFTvar 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.UNDEFINDEDAncestors
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: passAncestors
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._valueAncestors
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: passSubclasses
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.BUTTONAncestors
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.BUZZERAncestors
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.COMPRESSORAncestors
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.TOGGLEDOWNAncestors
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.ENCODERAncestors
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.LDRAncestors
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.LIGHTBARRIERAncestors
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.REEDSWITCHAncestors
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.SWITCHAncestors
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.VALVEAncestors
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.XMMOTORAncestors
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 = 2Ancestors
- enum.IntEnum
- builtins.int
- enum.Enum
Class variables
var BRAKEvar COASTvar 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 = 12Ancestors
- enum.IntEnum
- builtins.int
- enum.Enum
Class variables
var ANALOGvar BUTTONvar COLORSENSORvar DIGITALvar LDRvar LIGHTBARRIERvar OHMMETERvar REEDSWITCHvar SWITCHvar THERMOMETERvar TRAILSENSORvar ULTRASONICvar UNDEFINEDvar 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 = 2Ancestors
- enum.IntEnum
- builtins.int
- enum.Enum
Class variables
var NOTOGGLEvar TOGGLEDOWNvar 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 = 4Ancestors
- enum.IntEnum
- builtins.int
- enum.Enum
Class variables
var TRIGGERDOWNvar TRIGGERI2CREADvar TRIGGERI2CWRITEvar TRIGGERUPvar TRIGGERVALUE