Параметры strcat выдают ошибки указателя в моем приложении tcp server/parser
Я пытаюсь использовать плату Arduino Uno WiFi Rev2 для интеграции отдельных данных. Я буду использовать набор микросхем NINA WiFi и связанные библиотеки для запуска сервера, который будет периодически запрашивать и получать клиентскую информацию, размещенную на нескольких типах устройств, которые будут работать одновременно; таким образом, он в значительной степени разделен на 2 раздела: 1.) Управляйте клиентскими соединениями и их символьными массивами 2.) Анализ информации и соответствующий ответ с точки зрения контроля
Это то, что у меня есть на данный момент, и то, что я собирал на днях:
#include <stdlib.h>
#include <SPI.h>
#include <WiFiNINA.h>
char ssid[] = "***"; // Дом -- SSID сети (имя)
char pass[] = "***"; // Дом -- пароль SSID (WPA2-PSK)
#define MAX_CLIENTS 5
#define MAX_LINE_LEN 50
char inputs[MAX_CLIENTS][MAX_LINE_LEN] = {0}; // Создаем двумерный массив
client/received data
int msg_array[] = {0,0};
int net_status = WL_IDLE_STATUS; // Состояние радио Wi-Fi
WiFiServer server(80); // Создаем серверный объект на порту WiFi
// сервер, который будет использоваться для
// отвечаем на команды
WiFiClient *clients[MAX_CLIENTS] = {NULL}; // Создаем клиентские объекты
// ограничен размером
// МАКСИМАЛЬНОЕ_КЛИЕНТОВ
byte mac[] = {0xDE,0xAD,0xBE,0xEF,0xFE,0xED}; // физический MAC-адрес Arduino
byte ip[] = {192,168,9,25}; // IP этого контроллера
byte gateway[] = {192,168,0,1}; // Адрес маршрутизатора (интернет)
byte subnet[] = {255,255,0,0}; // Маска подсети
unsigned long wd_Dside, wd_Cside = millis(); // Собираем текущий tstamp
unsigned long wd_Delap, wd_Celap = 0; // Создаем прошедшее время
//прилавок
void setup(){
pinMode(4, OUTPUT); // вывод, выбранный для управления D SIDE
pinMode(5, OUTPUT); // вывод, выбранный для управления C SIDE
//включаем последовательную печать данных
Serial.begin(9600);
while (!Serial){
Serial.println("No serial.");
}
Serial.println("Serial.begin was initiated.");
if (WiFi.status() == WL_NO_SHIELD) { // проверяем модуль WiFi:
Serial.println("Wi-Fi: Communication with NINA has failed!");
// здесь ничего не делаем
while (true);
}
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
Serial.println("Please upgrade the firmware");
}
while (net_status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Подключиться к сети WPA/WPA2:
net_status = WiFi.begin(ssid, pass); // Попытка присоединиться к этому SSID
// ждем 5 секунд соединения:
delay(5000);
listNetworks();
server.begin(); // Запускаем Wi-Fi сервер
Serial.print("Server started on ");
Serial.println(WiFi.localIP());
}
}
void loop() {
delay(5);
WiFiClient newClient = server.available(); // начинаем слушать
// клиентские сообщения
if (newClient) {
Serial.println("New client discovered."); // Можно использовать как
// ACK/рукопожатие
// хост на стороне клиента
for (int i=0; i<MAX_CLIENTS; i++) {
if (clients[i] == NULL) {
clients[i] = new WiFiClient(newClient);
break;
}
}
}
for (int i=0; i<MAX_CLIENTS; i++){ // Проверяем клиент на наличие данных
if (clients[i] != NULL && clients[i]->available()){
// Если данные не мусор и данные доступны..
char newChar = clients[i]->read();
// Чтение данных
if (newChar == 'x') {
// Проверяем символ завершения для разделения
// Теперь проанализируем с помощью strtok, чтобы получить параметризацию
char delimiters[] = ",";
char* valIndex;
valIndex = strtok(inputs[i], delimiters);
for (int j=0; j < 2; j++){
// Расширение позже до наибольшего ожидаемого количества символов
msg_array[j] = atoi(valIndex);
Serial.print(msg_array[j]);
valIndex = strtok(NULL, delimiters);
}
switch(msg_array[0]) {
// Определяем тип полученного сообщения (символ 0 анализируется как
// Тип сообщения)
case '3':
// Проверить строку на наличие команд клиента, чтобы включить или выключить стороны.
if(msg_array[1] == '1')
// Тип сообщения 3, Инструкция 1: включить сторону D
{
digitalWrite(4, HIGH);
// Установить вывод 4 в высокий уровень
Serial.println("Dside started.");
wd_Delap = 0;
// Сбросить значение сторожевого таймера истекшего времени для стороны D.
wd_Dside = millis();
// Последний тактовый импульс от клиентского устройства на стороне D.
}
if(msg_array[1] == '2')
// Тип сообщения 3, Инструкция 2: ВЫКЛЮЧИТЕ сторону D
{
digitalWrite(4, LOW);
// Установить на выводе 4 низкий уровень
Serial.println("Dside stopped");
wd_Delap = 0;
// Сбросить значение сторожевого таймера истекшего времени для стороны D.
wd_Dside = millis();
// Последний тактовый импульс от клиентского устройства на стороне D.
}
if(msg_array[1] == '3')
// Тип сообщения 3, Инструкция 3: включить сторону C
{
digitalWrite(5, HIGH);
// Установить вывод 5 в высокий уровень
Serial.println("C side started.");
wd_Celap = 0;
// Сброс значения времени сторожевого таймера истекшего времени для стороны C.
wd_Cside = millis();
// Последний тактовый импульс от клиентского устройства на стороне C.
}
if(msg_array[1] == '4')
// Тип сообщения 3, Инструкция 4: Выключите сторону C
{
digitalWrite(5, LOW);
// Установить на выводе 5 низкий уровень
Serial.println("C side stopped.");
wd_Celap = 0;
// Сброс значения времени сторожевого таймера истекшего времени для стороны C.
wd_Cside = millis();
// Последний тактовый импульс от клиентского устройства на стороне C.
}
break;
case '6':
// Проверяем строку на наличие другого типа сообщения TBD
break;
default:
Serial.println("Default break. Received crap.");
break;
}
inputs[i][0] = '\0';
// Очистить этот элемент массива для следующего сообщения
// клиенты[i]->stop();
// По умолчанию завершаем сеанс клиента, просто ждем открытия нового TCP
// удалить клиентов[i];
// Удалить данные клиентского элемента
// клиенты[i] = NULL;
// Сброс в NULL
}
else {
if (strlen(inputs[i]) > MAX_LINE_LEN) {
// Первая проверка на соответствие размеру
Serial.println("Max line length exceeded from client.");
inputs[i][0] = '0';
// Очистить этот элемент массива для следующего сообщения
}
else {
**strcat(inputs[i], newChar);**
// Добавляем символ в полученную строку
}
Serial.println();
Serial.println(newChar);
}
}
// Обновить сторожевые таймеры
wd_Delap += (millis()-wd_Dside);
wd_Celap += (millis()-wd_Cside);
if (wd_Delap>=60000)
{
Serial.print("Elapsed time on watchdog, D side: ");
Serial.println(wd_Delap);
Serial.print("Last message received: ");
Serial.println(wd_Dside);
digitalWrite(4, LOW); // устанавливаем на выводе 4 низкий уровень
Serial.println("D side didn't hear from a client in 60s;
defaulting to OFF.");
}
if (wd_Celap>=60000)
{
Serial.print("Elapsed time on watchdog, C side: ");
Serial.println(wd_Celap);
Serial.print("Last message recieved: ");
Serial.println(wd_Cside);
digitalWrite(5, LOW); // устанавливаем на выводе 5 низкий уровень
Serial.println("C side didn't hear from a client in 60s;
defaulting to OFF.");
}
}
}
Ранее у меня это компилировалось и запускалось, хотя и с проблемами, которые я намеревался итеративно устранять. Теперь он не будет компилироваться из-за следующей ошибки:
arduino:302:37: ошибка: неверное преобразование из 'char' в 'const char*' [-fpermissive]
strcat(inputs[i], newChar); // Добавляем символ в полученную строку
.. который я попытался выделить жирным шрифтом выше в последнем предложении else. Я понимаю, что для этих параметров требуются указатели, но похоже, что некоторые другие функции, такие как strtok и strlen, которые также запрашивают указатели, работают нормально в моем коде.
Есть ли какие-либо предложения или альтернативы strcat() относительно того, как я могу заставить это работать? Я в основном придерживался массивов символов вместо объявления объектов String. Я также, очевидно, довольно ржавый в C (++), так как я не работал с ним активно какое-то время.
Спасибо
@user8585939, 👍0
1 ответ
Лучший ответ:
strcat
— это функция для объединения строк. Он ожидает массив символов в качестве второго параметра. У вас есть только один символ newChar
для добавления к вашей строке.
size_t l = strlen(inputs[i]);
inputs[i][l] = newChar;
inputs[i][l + 1] = 0;
Примечание. Было бы лучше отслеживать длину input
, а затем использовать strlen
. strlen
перебирает массив, пока не завершится нулем.
- Строка JSON для Arduino WiFi версии 2
- Как подключиться к Arduino с помощью WiFi?
- Как подключить Wi-Fi Shield ESP-12E-ESP8266-UART-WIFI-Wireless-Shield к Arduino
- Как сделать повторитель Wi-Fi на Arduino?
- Как подключить ESP8266 с помощью адаптера ESP-01 к Arduino Uno?
- Почему эта программа на C++ не может прочитать Serial.write() моего arduino?
- Как установить связь между веб-камерой и Arduino UNO и получать прямую трансляцию на мобильном телефоне с помощью ESP8266?
- Как запустить TCP-сервер сокетов на Arduino Uno WiFi?
Спасибо. Я думаю, это сработает. Вопрос, нужна ли третья строчка? Разве это не добавило бы символ «0» в конце, или вы говорите, что это символ для завершения, который, как я думал, был «\ 0», @user8585939
следующий
strlen
не будет работать без завершающего нуля. ascii-код '\0' равен 0. некоторые используют NULL, который тоже равен 0, @Juraj