Использование StringStream в скетче Arduino

Я узнал о StringStream потоке сегодня на работе.

#include <iostream>
#include <sstream>
#include <stdio.h>
#include <string.h>

using namespace std;

char* getSql() {
    float outdoorTempInC = 15;
    int outoorHumidity = 23;
    float indorTempinC = 20;
    int humidity = 22;
    int val = 400; // soil sensor reading
    int avgVal = 38; // avaerage of 10 values of soils sensor
    char statusMsg[50] = {"Hello World"} ;
    std::stringstream sqlQuery;
    sqlQuery  << "INSERT INTO arduinoSensorData.sensorLog (out_temperature,  " 
        << "out_humidity,  drwngRoom_temperature, drwngRoom_humidity, "
        << "pot1_soilMoisture, pot1_avg_SoilMoisture, wateringPot1) VALUES ('" 
        << outdoorTempInC << "', '" << outoorHumidity << "', '" << indorTempinC
        << "', '" << humidity << "', '" << val << "', '" << avgVal << "', '"
        << statusMsg << "');";

    char *mychar = new char[sqlQuery.str().length() + 1];
    strcpy(mychar, sqlQuery.str().c_str());
    return mychar;
}

string getSqlStream() {
    float outdoorTempInC = 15;
    int outoorHumidity = 23;
    float indorTempinC = 20;
    int humidity = 22;
    int val = 400; // soil sensor reading
    int avgVal = 38; // avaerage of 10 values of soils sensor
    char statusMsg[50] = {"Hello World"} ;
    std::stringstream sqlQuery;
    sqlQuery  << "INSERT INTO arduinoSensorData.sensorLog (out_temperature,  " 
        << "out_humidity,  drwngRoom_temperature, drwngRoom_humidity, "
        << "pot1_soilMoisture, pot1_avg_SoilMoisture, wateringPot1) VALUES ('" 
        << outdoorTempInC << "', '" << outoorHumidity << "', '" << indorTempinC
        << "', '" << humidity << "', '" << val << "', '" << avgVal << "', '"
        << statusMsg << "');";
    return sqlQuery.str();
}

int main() {
    string sql = getSqlStream();
    cout << getSql() << "\n";
    cout << sql.c_str() << "\n";
    return  0;
}

Я был очень счастлив, пока не обнаружил, что не могу использовать StringStream в Arduino, поэтому я порылся в Интернете и наткнулся на это.

Поэтому, если я попытаюсь использовать приведенную выше связанную строку gist, как я использовал в своем примере кода, я получу эту ошибку:

error: no match for 'operator<<' (operand types are 'StringStream' and 'const char [60]')
     sqlQuery  << "INSERT INTO arduinoSensorData.sensorLog (out_temperature,  " 
               ^
webServer_Displaying_everything_v01:24: error: 'outdoorTempInC' was not declared in this scope
         << outdoorTempInC << "', '" << outoorHumidity << "', '" << indorTempinC
            ^
webServer_Displaying_everything_v01:24: error: 'outoorHumidity' was not declared in this scope
         << outdoorTempInC << "', '" << outoorHumidity << "', '" << indorTempinC
                                        ^
webServer_Displaying_everything_v01:24: error: 'indorTempinC' was not declared in this scope
         << outdoorTempInC << "', '" << outoorHumidity << "', '" << indorTempinC
                                                                    ^
webServer_Displaying_everything_v01:25: error: 'humidity' was not declared in this scope
         << "', '" << humidity << "', '" << val << "', '" << avgVal << "', '"
                      ^
webServer_Displaying_everything_v01:25: error: 'val' was not declared in this scope
         << "', '" << humidity << "', '" << val << "', '" << avgVal << "', '"
                                            ^
webServer_Displaying_everything_v01:25: error: 'avgVal' was not declared in this scope
         << "', '" << humidity << "', '" << val << "', '" << avgVal << "', '"
                                                             ^
webServer_Displaying_everything_v01:28: error: 'class StringStream' has no member named 'str'
     char *mychar = new char[sqlQuery.str().length() + 1];
                                      ^
webServer_Displaying_everything_v01:29: error: 'class StringStream' has no member named 'str'
     strcpy(mychar, sqlQuery.str().c_str());

Или я делаю это совершенно неправильно? Мне кажется, что я все еще не могу использовать его так, как я сделал в примере. Пожалуйста, помогите.

, 👍0

Обсуждение

Этот класс не является “потоком” в смысле C++, это "Поток" в смысле Arduino, т. Е. Он предоставляет интерфейс, аналогичный "Последовательному". Вы можете, например, добавить к нему "print()` и" println ()"., @Edgar Bonet

@EdgarBonet итак, в таком случае, как я могу использовать метод "SqlQuery" для хранения переменной в arduino без необходимости использовать " print ()", "println" или "sprintf"?, @Ciasto piekarz

Вся цель этого "строкового потока" состоит в том, чтобы позволить вам ввести в него "print ()" и " println ()"., @Edgar Bonet

Ссылка на StringStream-это "#include<sstream>", который в значительной степени является потоком в смысле C++, а не в смысле Arduino. ОП хочет использовать std C++ в Arduino. Ответ заключается в использовании цепочек инструментов GNU, используемых (и установленных вместе с) средой разработки Arduino, но без препроцессора ino. Нет никакого класса StringStream. Класс является ostringstream, и его цель состоит в том, чтобы предоставить методы добавления с помощью << оператор. Println никогда не используется. \n, \r\n или предпочтительно std::endl используется для завершения строки, а sprintf может использоваться или не использоваться в методах ostringstream., @Douglas Daseeco


2 ответа


Лучший ответ:

3

Прямой ответ

Программа на C++ и кросс-компиляция в Arduino Yún. Язык скетчей Arduino представляет собой тонкий слой поверх C++, но пространство имен std:: не является легким в той степени, в какой это необходимо для того, чтобы вместить то, что вы цените из стандартной библиотеки C++, в объем памяти небольшой встроенной платы процессора. Смотрите среду Arduino Yun C++? Мост + Кросс-Компилятор.

Серьезное программирование на Arduino

Если вы хотите открыть дверь элегантности C++ на небольших встроенных процессорных платах, таких как более простые ардуино, вам нужно будет выйти за рамки языка скетчей Arduino. Возможно, вам будет и интересно, и полезно научиться перекрестной компиляции и связыванию с помощью набора инструментов GNU, предназначенного для процессора Atmel, который у вас на борту.

Этот более профессиональный подход не для слабонервных, но он делается постоянно. Мы делаем это здесь, в лабораториях TranSeed, каждый день.

Для начала вам не нужно загружать или устанавливать что-либо, кроме программного обеспечения Arduino. Набор инструментов, предназначенный для архитектуры AVR Atmel (используется несколькими платами Arduino), находится в подкаталоге в домашнем каталоге Arduino IDE. Набор инструментов, предназначенный для архитектуры SAM Atmel для Arduino Due, помещается в подкаталог вашего домашнего каталога при настройке IDE для загрузки скетчей в Due.

Возвращаясь к вопросу в этом контексте C++

Как только вы научитесь компилировать и связывать с помощью g++ из цепочки инструментов GNU1 и использовать инструменты загрузки2 вашей программы через USB-порт, вы сможете создать класс шаблонов, чтобы получить элегантность, доступную в C++, например, перегрузку оператора, которая вам нравится.

Проблема с попыткой использовать библиотеку C++ со встроенными целями заключается в том, что система распределения и другие зависимости, вероятно, исчерпают большую часть, если не всю память вашей программы. Класс ostringstream из библиотеки C++ со всеми включенными в него зависимостями не является чрезвычайно скудным.

Подход, который потребляет очень мало памяти и не требует циклов динамического выделения ЦП, заключается в создании шаблона C++, который обертывает статический массив. Размер его буфера может быть одним из параметров шаблона.

Затем вы можете перегрузить оператор << класса, используя эти примеры в качестве руководства. Вы получаете свою элегантность и резко снижаете требования к вычислительным ресурсам.


[1] Как перекрестная компиляция, так и перекрестные ссылки выполняются с помощью g++ (gcc для файлов Aruino и Atmel C в библиотеке). Для плат Arduino, использующих процессоры Atmel на базе AVR, используйте цепочку инструментов AVR GNU. Для Due, в котором используются процессоры Atmel на базе SAM, используйте цепочку инструментов SAM5X GNU.

[2] Программа bossac используется для загрузки в Due. Программа avrdude используется для загрузки в Mega 2560.

,

ну, у меня нет Arduino Yun, но я скорее собирался купить [Arduino Yun Shield][1], я бы предположил , что это не должно иметь значения, поправьте меня, если я ошибаюсь, пожалуйста ! [1]: https://www.arduino.cc/en/Main/ArduinoYunShield, @Ciasto piekarz

Yun board != Yun shield, @Douglas Daseeco

Спасибо Дуглас, лучший ответ, который я принял, однако я был бы признателен, если бы в вашем ответе вы могли связать текст "перекрестная компиляция", "ссылка с помощью инструмента GNU" и "установка, предназначенная для процессора Atmel", например, в Интернете. Это положит начало процессу обучения. Однако я бы воздержался от прямого перехода на более высокую ступень., @Ciasto piekarz

Этот ответ почти точно соответствует тому пути, по которому мы идем здесь, в лаборатории, и он работает очень хорошо. Большинство серьезных встраиваемых программистов используют микроэмаки для разработки. Мы пытались использовать пространство имен std:: в скетчах для контейнеров и строк, но преимущество перехода на g++ и файл makefile стало очевидным в первую неделю написания реальных программ. Описанный здесь способ работает уже три года и утрояет скорость нашего развития., @Douglas Daseeco


1

Это не имеет ничего общего с перекрестной компиляцией или связыванием с помощью инструмента GNU. Потоки ввода-вывода действительно присутствуют в Arduino, но попытка включить их приводит к слишком большому двоичному файлу. Это просто не укладывается в память чипа.

Существует несколько решений этой проблемы. Один из них заключается в использовании библиотеки под названием ard-потоки. Другой вариант-использовать облегченную, упрощенную версию stringstream, которой достаточно для компиляции вашего кода.

#include <string>

namespace ard
{
    struct ostringstream
    {
        ostringstream() = default;
        ostringstream(std::string arg) : s(std::move(arg)) {}

        const std::string& str() const {
            return s;
        }

        // Arithmetic types: int, float, ...
        template <class T>
        auto operator<<(T arg) -> decltype(std::to_string(arg), *this) {
            s.append(std::to_string(arg));
            return *this;
        }

        // String types: std::string, const char*
        template <class T>
        auto operator<<(const T& arg) -> decltype(std::string().append(arg), *this) {
            s.append(arg);
            return *this;
        }

        // Single char: 'a', '\n', ...
        ostringstream& operator<<(char arg) {
            s.append(1, arg);
            return *this;
        }

    private:
        std::string s;
    };
}

Теперь просто замените std::stringstream на ard::ostringstream, и он будет работать так, как ожидалось.

,