1"""Base class for Blueberry controllers using Arduino board. 2 3This module uses pyserial library to communicate with Arduino UNO board. 4 5About Arduino code, please refer to the code of following Arduino project: 6Internal link 7""" 8 9import time 10from typing import Dict 11from mobly.signals import ControllerError 12import serial 13 14 15class ArduinoBase(object): 16 """Implements an Arduino base class. 17 18 Attributes: 19 config: A device configuration. 20 serial: serial object, a serial object which is used to communicate with 21 Arduino board. 22 """ 23 24 def __init__(self, config: Dict[str, str]): 25 """Initializes an Arduino base class.""" 26 self._verify_config(config) 27 self.config = config 28 self.serial = serial.Serial(config['arduino_port'], 9600) 29 self.serial.timeout = 30 30 # Buffer between calling serial.Serial() and serial.Serial.write(). 31 time.sleep(2) 32 33 def _verify_config(self, config): 34 """Checks the device config's required config parameters. 35 36 Args: 37 config: dict, Mobly controller config for ArduinoBass. The config should 38 include the key "arduino_port" whose value is a string representing 39 Arduino board name. e.g. /dev/ttyACM0. 40 """ 41 if 'arduino_port' not in config: 42 raise ControllerError('Please provide an Arduino board port for the' 43 ' ArduinoBase in Mobile Harness config') 44 45 def _send_string_to_arduino(self, tx_string): 46 """Sends a particular string to communicate with Arduino. 47 48 The method requires that Arduino code can read string which is received from 49 a python serial object and then send the same string to the serial object. 50 51 An example of Arduino code: 52 String kRxString = ""; 53 void setup() { 54 ... 55 } 56 void loop() { 57 if (Serial.available() > 0) { 58 kRxString = Serial.readString(); 59 ... 60 Serial.write(kRxString.c_str()); 61 } 62 } 63 64 Args: 65 tx_string: string, is used to be sent to Arduino port for making the 66 controlled device perform action. After Arduino receives the string, it 67 will send a response which is the same string. 68 69 Returns: 70 The time it takes for waiting a response, in seconds. 71 72 Raises: 73 ControllerError: raised if not received a response from Arduino. 74 """ 75 self.serial.write(str.encode(tx_string)) 76 start_time = time.time() 77 rx_string = self.serial.read_until(tx_string, len(tx_string)).decode() 78 if rx_string == tx_string: 79 return time.time() - start_time 80 raise ControllerError('Timed out after %ds waiting for the string "%s" from' 81 ' Arduino.' % (self.serial.timeout, tx_string)) 82