Para dispositivos embebidos, hemos incluido un ejemplo que se ejecuta en el controlador ClearCore I/O. Otros dispositivos deberían ser similares.

Objetivo:

Este ejemplo demuestra cómo enviar una solicitud al Burro y leer la respuesta resultante. También utiliza las funciones splitString y ParseResponse que se pueden encontrar en otra parte.

Descripción:

Este ejemplo enviará una cadena por TTL al Burro solicitando el estado de la estación y esperará una respuesta. Luego analizará esa respuesta para ver si el Burro se ha detenido en una estación y encenderá una luz si es así. También tiene impresiones de depuración informativas que se envían por la conexión serial USB-B del ClearCore. Los errores se imprimen pero, de lo contrario, se ignoran y no se manejan.

Requisitos:

  • Una conexión serial TTL entre COM-1 y el robot Burro.
  • Un robot Burro con la API de Burro
Example_station_status_checker.ino
#define ARDUINOJSON_ENABLE_STD_STRING 1
#undef max
#undef min
#include <sstream>
#include <string>
#include <vector>
#include "ClearCore.h"

// Implementación estándar de splitString.
std::vector<std::string> splitString(std::string str, char delimiter = ',')
{
    std::vector<std::string> splitVect;
    std::stringstream ss(str);
    std::string substr;

    while (ss.good())
    {
        getline(ss, substr, delimiter);
        splitVect.emplace_back(std::move(substr));
    }
    return splitVect;
}

/**
 * @brief Toma una cadena formateada como respuesta y devuelve el mensaje original, el
 * timestamp, cualquier error y/o los valores devueltos por el backend, si los hay.
 * Ejemplo: "%?STTN=1 2_\r" devolvería std::vector<std::string> {"?STTN", "1 0"} donde 1
 * es el nanosegundo desde el epoch y 0 es el estado de la estación }
 *
 * @param[in]  response_string  La cadena de respuesta formateada, devuelta por la API
 *
 * @return Un std::vector<std::string> con el mensaje original y la respuesta a ese mensaje
 * con los delimitadores eliminados.
 */
std::vector<std::string> ParseResponse(std::string response_string){
    // La cadena de respuesta se divide alrededor de un solo signo igual '='. Nunca habrá más de un (1) signo igual
    // en una cadena de respuesta.
    std::vector<std::string> split_response = splitString(response_string.substr(1), '=');

    // El guion bajo '_' indica el final de una respuesta. Estará en la segunda posición del vector junto con el
    // timestamp y los valores devueltos. Elimina cualquier carácter después de él.
    int loc = split_response[1].find('_');
    split_response[1] = split_response[1].substr(0, loc);

    // Elimina el porcentaje inicial '%' que indica una respuesta. Aquí se puede realizar lógica para verificar que
    // el mensaje esté correctamente formateado.
    std::string s = split_response[1];

    // Determina si hay un error en la respuesta.
    if (s.find("#ERR") != std::string::npos)
    {
        std::string err_string = split_response[0] + " had error: " + s;
        split_response[1] = err_string;
        split_response[0] = "API Returned an error.";
        return split_response;
    }

    // Devuelve el vector para saber qué respuesta corresponde a qué comando original.
    return split_response;
}

// Selecciona la velocidad de baudios para que coincida con el dispositivo objetivo.
#define baudRateSerialPort 115200
#define baudRateInputPort  115200
// Especifica qué interfaz serial usar como salida.
#define SerialPort ConnectorUsb
// Especifica qué interfaz serial usar como entrada.
#define InputPort ConnectorCOM1
// Contenedor para el byte a leer
int16_t input;
int main() {
    // Configura la comunicación serial para imprimir la entrada serial.
    SerialPort.Mode(Connector::USB_CDC);
    SerialPort.Speed(baudRateSerialPort);
    SerialPort.PortOpen();

    // Configura la comunicación por el puerto COM para comunicarte con Burro.
    InputPort.Mode(Connector::TTL);
    InputPort.Speed(baudRateInputPort);
    InputPort.Parity(SerialBase::PARITY_N);
    InputPort.StopBits(1);
    InputPort.FlowControl(false);
    InputPort.PortOpen();
    while (!InputPort) {
        continue;
    }

    while (true) {
        // Envía la solicitud de la información que deseas, en este caso el estado de la estación
        InputPort.Send("?STTN_\r");
        Delay_ms(100);

        // Crea una cadena y lee el primer carácter
        std::string response = "";
        input = InputPort.CharGet();

        // Mientras haya bytes para leer, léelos y añádelos a nuestra cadena de respuesta
        while (input != -1) {
          response += (char)input;
          input = InputPort.CharGet();
        }

        // Si se leyó una cadena, analízala y realiza la lógica.
        if (response != "") {
            // Muestra la cadena recibida. Principalmente para depuración, si no tienes un monitor
            // conectado por USB-B, comenta esto.
            SerialPort.Send("Received:");
            SerialPort.SendLine((" " + response).c_str());
            // Analiza la respuesta para comenzar a realizar la lógica. El comando enviado está en la posición 0
            // del vector.
            std::vector<std::string> parsed_response = ParseResponse(response);
            if ( parsed_response[0] == "?STTN") {
              // El parser tiene la respuesta de la API al request en la posición 1 del vector.
              // Divide esto en espacios para obtener el timestamp y los argumentos devueltos. ?STTN solo debería
              // devolver un argumento junto al timestamp. Será 0 si no está en una estación y 1 si está detenido
              // en una estación.
              std::vector<std::string> split_station_response = splitString(parsed_response[1], ' ');
              if (split_station_response[1] == "1"){
                // Haz lo que quieras si estás detenido en una estación. Yo imprimo por USB-B y
                // enciendo el LED incorporado en la placa ClearCore.
                SerialPort.Send("Stopped for station at time");
                SerialPort.SendLine((" " + split_station_response[0]).c_str());
                ConnectorLed.State(true);
                Delay_ms(100);
                ConnectorLed.State(false);
                Delay_ms(100);
              }
            }
        }
        else {
            SerialPort.SendLine("No recibido");
        }
        // Espera un segundo y repite...
        Delay_ms(1000);
    }
}