First commit
This commit is contained in:
112
simulator/modules/sbot_interface/boards/arduino.py
Normal file
112
simulator/modules/sbot_interface/boards/arduino.py
Normal file
@@ -0,0 +1,112 @@
|
||||
"""
|
||||
A simulator for the SR Arduino board.
|
||||
|
||||
Provides a message parser that simulates the behavior of an Arduino board.
|
||||
|
||||
Based on the Arduino v2.0 firmware.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from sbot_interface.devices.arduino_devices import BasePin, GPIOPinMode, UltrasonicSensor
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Arduino:
|
||||
"""
|
||||
A simulator for the SR Arduino board.
|
||||
|
||||
:param pins: A list of simulated devices connected to the Arduino board.
|
||||
The list is indexed by the pin number and EmptyPin is used for
|
||||
unconnected pins.
|
||||
:param asset_tag: The asset tag to report for the Arduino board.
|
||||
:param software_version: The software version to report for the Arduino board.
|
||||
"""
|
||||
|
||||
def __init__(self, pins: list[BasePin], asset_tag: str, software_version: str = '2'):
|
||||
self.pins = pins
|
||||
self.asset_tag = asset_tag
|
||||
self.software_version = software_version
|
||||
|
||||
def handle_command(self, command: str) -> str:
|
||||
"""
|
||||
Process a command string and return the response.
|
||||
|
||||
Executes the appropriate action on any specified pins automatically.
|
||||
|
||||
:param command: The command string to process.
|
||||
:return: The response to the command.
|
||||
"""
|
||||
if command[0] == 'a': # analog read
|
||||
pin_number = self._convert_pin_number(command, 1)
|
||||
if pin_number == -1:
|
||||
return '0'
|
||||
return str(self.pins[pin_number].get_analog())
|
||||
elif command[0] == 'r': # digital read
|
||||
pin_number = self._convert_pin_number(command, 1)
|
||||
if pin_number == -1:
|
||||
return 'l'
|
||||
return 'h' if self.pins[pin_number].get_digital() else 'l'
|
||||
elif command[0] == 'l': # digital write low
|
||||
pin_number = self._convert_pin_number(command, 1)
|
||||
if pin_number != -1:
|
||||
self.pins[pin_number].set_digital(False)
|
||||
return ''
|
||||
elif command[0] == 'h': # digital write high
|
||||
pin_number = self._convert_pin_number(command, 1)
|
||||
if pin_number != -1:
|
||||
self.pins[pin_number].set_digital(True)
|
||||
return ''
|
||||
elif command[0] == 'i': # set pin mode to input
|
||||
pin_number = self._convert_pin_number(command, 1)
|
||||
if pin_number != -1:
|
||||
self.pins[pin_number].set_mode(GPIOPinMode.INPUT)
|
||||
return ''
|
||||
elif command[0] == 'o': # set pin mode to output
|
||||
pin_number = self._convert_pin_number(command, 1)
|
||||
if pin_number != -1:
|
||||
self.pins[pin_number].set_mode(GPIOPinMode.OUTPUT)
|
||||
return ''
|
||||
elif command[0] == 'p': # set pin mode to input pullup
|
||||
pin_number = self._convert_pin_number(command, 1)
|
||||
if pin_number != -1:
|
||||
self.pins[pin_number].set_mode(GPIOPinMode.INPUT_PULLUP)
|
||||
return ''
|
||||
elif command[0] == 'u': # ultrasonic measurement
|
||||
pulse_pin = self._convert_pin_number(command, 1)
|
||||
echo_pin = self._convert_pin_number(command, 2)
|
||||
|
||||
if pulse_pin == -1 or echo_pin == -1:
|
||||
return '0'
|
||||
|
||||
ultrasound_sensor = self.pins[echo_pin]
|
||||
if isinstance(ultrasound_sensor, UltrasonicSensor):
|
||||
return str(ultrasound_sensor.get_distance())
|
||||
else:
|
||||
return '0'
|
||||
elif command[0] == 'v': # software version
|
||||
return f"SRduino:{self.software_version}"
|
||||
else:
|
||||
# A problem here: we do not know how to handle the command!
|
||||
# Just ignore this for now.
|
||||
return ''
|
||||
|
||||
def _convert_pin_number(self, command: str, index: int) -> int:
|
||||
if len(command) < index + 1:
|
||||
LOGGER.warning(f'Incomplete arduino command: {command}')
|
||||
return -1
|
||||
|
||||
pin_str = command[index]
|
||||
try:
|
||||
pin_number = ord(pin_str) - ord('a')
|
||||
except ValueError:
|
||||
LOGGER.warning(f'Invalid pin number in command: {command}')
|
||||
return -1
|
||||
|
||||
if 0 < pin_number < len(self.pins):
|
||||
return pin_number
|
||||
else:
|
||||
LOGGER.warning(f'Invalid pin number in command: {command}')
|
||||
return -1
|
||||
Reference in New Issue
Block a user