Ошибка компиляции: "cannot declare 'client' to be of abstract type 'Client'"
Я знаю, что это не мой исходный код, но я использую его для более крупного проекта, над которым сейчас работаю. Я продолжаю получать это сообщение об ошибке: «невозможно объявить «клиент» абстрактным типом «Клиент»». вот код:
// RoboSapienServer.cpp
// RobosapienServer — веб-включение RoboSapien
// Кевин Н. Хоу
// http://www.KevinHaw.com/RoboSapienServer.php
// Этот проект объединяет пример веб-сервера по умолчанию в дистрибутиве IDE и RoboSapienIR Карла Каслтона (http://home.mesastate.edu/~kcastlet) (http://playground.arduino.cc/Main/RoboSapienIR).
// Исходный код объединен из этих двух источников.
// Включить файлы
#include <Ethernet.h>
#include <string.h>
#include <WebServer.h>
////////////////////////////////////////////////// ////////////////
// Начать определения переменных, специфичных для веб-сервера
////////////////////////////////////////////////// ////////////////
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// KNH, 09.02.2010 - Смена IP-адреса для использования локальной подсети дома
//byte ip[] = { 10, 0, 0, 177 };
byte ip[] = { 192, 168, 1, 177 };
// Сервер для веб-запросов
EthernetServer server(80);
// Определяем имя поля в отправленной форме
#define SUBMIT_BUTTON_FIELDNAME "RSCmd"
// Строка для переменных HTTP-запроса
char pcHttpReqRsCmd[20] = {'\0'};
volatile int viRobsapienUrlCmd = -1; // Команда robosapien, отправленная по URL-адресу HTTP-запроса веб-страницы
////////////////////////////////////////////////// ////////////////
// Начать определение переменных, специфичных для Robosapien
////////////////////////////////////////////////// ////////////////
// Определены некоторые, но не все команды RS
#define RSTurnRight 0x80
#define RSRightArmUp 0x81
#define RSRightArmOut 0x82
#define RSTiltBodyRight 0x83
#define RSRightArmDown 0x84
#define RSRightArmIn 0x85
#define RSWalkForward 0x86
#define RSWalkBackward 0x87
#define RSTurnLeft 0x88
#define RSLeftArmUp 0x89
#define RSLeftArmOut 0x8A
#define RSTiltBodyLeft 0x8B
#define RSLeftArmDown 0x8C
#define RSLeftArmIn 0x8D
#define RSStop 0x8E
#define RSWakeUp 0xB1
#define RSBurp 0xC2
#define RSRightHandStrike 0xC0
#define RSNoOp 0xEF
// Подмножество дополнительных кодов, взятых с http://www.contrib.andrew.cmu.edu/~ebuehl/robosapien-lirc/ir_codes.htm
#define RSRightHandSweep 0xC1
#define RSRightHandStrike2 0xC3
#define RSHigh5 0xC4
#define RSFart 0xC7
#define RSLeftHandStrike 0xC8
#define RSLeftHandSweep 0xC9
#define RSWhistle 0xCA
#define RSRoar 0xCE
int IRIn = 2; // Мы будем использовать прерывание
int IROut = 3; // Откуда будет отправлена эхо-команда
boolean RSEcho = true; // Должны ли команды Arduino Echo RS
boolean RSUsed = true; // Была ли использована последняя команда
volatile int RSBit = 9; // Всего бит данных
volatile int RSCommand; // Однобайтовая команда из ИК
int bitTime = 516; // Битовое время (теоретически 833, но 516)
// работает на передачу и быстрее
int last; // Предыдущая команда из ИК
////////////////////////////////////////////////// ////////////////
// Начать специальный код Robosapien
////////////////////////////////////////////////// ////////////////
// Получаем понемногу.
// ПРИМЕЧАНИЕ. Не используется в приложении RoboServer.
void RSReadCommand() {
delayMicroseconds(833 + 208); // примерно 1 1/4 бита
int bit = digitalRead(IRIn);
if (RSBit == 9) { // Должно быть начало новой команды
RSCommand = 0;
RSBit = 0;
RSUsed = true;
}
if (RSBit < 8) {
RSCommand <<= 1;
RSCommand |= bit;
}
RSBit++;
if (RSBit == 9) RSUsed = false;
}
// отправляем все 8 бит
void RSSendCommand(int command) {
digitalWrite(IROut, LOW);
delayMicroseconds(8 * bitTime);
for (int i = 0; i < 8; i++) {
digitalWrite(IROut, HIGH);
delayMicroseconds(bitTime);
if ((command & 128) != 0) delayMicroseconds(3 * bitTime);
digitalWrite(IROut, LOW);
delayMicroseconds(bitTime);
command <<= 1;
}
digitalWrite(IROut, HIGH);
delay(250); // Даем 1/4 секунды до следующего
}
// Настраиваем функциональность RoboSpapien
void RSSetup()
{
pinMode(IRIn, INPUT);
pinMode(IROut, OUTPUT);
pinMode(10, OUTPUT);
digitalWrite(IROut, HIGH);
attachInterrupt(0, RSReadCommand, RISING);
last = RSNoOp;
// Сделать отрыжку робота, чтобы показать, что настройка завершена
RSSendCommand(RSBurp);
}
// Цикл для функциональности RoboSapien
// Функциональность только для записи - отправить команду с веб-страницы роботу, игнорируя любой ввод с удаленного
void RSLoop()
{
// Пришла ли новая команда с сервера?
if (viRobsapienUrlCmd != -1)
{
// Новая команда - отправляем ее роботу
Serial.print("Sending command to RoboSapien: ");
Serial.println(viRobsapienUrlCmd, HEX);
RSSendCommand(viRobsapienUrlCmd);
// Теперь очистить команду
viRobsapienUrlCmd = -1;
}
}
////////////////////////////////////////////////// ////////////////
// Запуск кода, специфичного для веб-сервера
////////////////////////////////////////////////// ////////////////
// Печатаем наш заголовок MIME и HTML в верхней части веб-страницы
void HtmlHeader(Client client)
{
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
client.println("<HTML>\n<HEAD>");
client.println(" <TITLE>Kevin's Arduino Webserver</TITLE>");//
// client.println("<META HTTP-EQUIV=\"обновить\" CONTENT=\"5\">");
client.println("</HEAD><BODY bgcolor=\"#9bbad6\">");
}
// Печать нижнего колонтитула в нижней части веб-страницы
void HtmlFooter(Client client)
{
client.println("</BODY></HTML>");
}
// Печать кнопки отправки с указанной меткой, обернутой в форму для указанной шестнадцатеричной команды
void SubmitButton(Client &client, char *pcLabel, int iCmd)
{
client.print("<form method=post action=\"/?");
client.print(iCmd, HEX);
client.print("\"><input type=submit value=\"");
client.print(pcLabel);
client.print("\" name=\"" SUBMIT_BUTTON_FIELDNAME "\">");
client.println("</form>");
}
// Разбираем заголовок HTTP-запроса посимвольно, ищем строковые переменные
void ParseHttpHeader(Client &client)
{
char c;
// Пропускаем, пока не наткнемся на вопросительный знак (первый)
while ((c = client.read()) != '?' && client.available())
{
// Отладка - печать данных
Serial.print(c);
}
// Мы здесь из-за вопросительного знака или у нас закончились данные?
if (client.available() > 2)
{
char pcUrlNum[3], *pc;
// У нас достаточно данных для шестнадцатеричного числа - читаем его
for (int i = 0; i < 2; i++)
{
// Чтение и сброс данных в порт отладки
Serial.print(c = pcUrlNum[i] = client.read());
}
// Нулевая завершающая строка
pcUrlNum[2] = '\0';
// Получить шестнадцатеричное число
viRobsapienUrlCmd = strtol(pcUrlNum, &pc, 0x10);
}
// Пропустить и удалить все оставшиеся данные
while (client.available())
{
// Отладка - печать данных
Serial.print(c = client.read());
}
}
// Настраиваем функциональность веб-сервера
void WebServerSetup()
{
Ethernet.begin(mac, ip);
server.begin();
}
// Цикл веб-сервера
void WebServerLoop()
{
Client client = server.available();
boolean bPendingHttpResponse = false; // Истинно, когда мы получили весь HTTP-запрос и нам нужно вывести веб-страницу
char c; // Для чтения в HTTP-запросе по одному символу за раз
if (client) {
// Цикл, пока есть соединение
while (client.connected()) {
// Есть ли у нас ожидающие данные (запрос HTTP)?
if (client.available()) {
// Указываем, что нам нужно ответить на HTTP-запрос, как только мы закончим его обработку
bPendingHttpResponse = true;
ParseHttpHeader(client);
}
else
{
// В клиентском сокете нет данных, ожидающих чтения. У нас есть ожидающий HTTP-запрос?
if (bPendingHttpResponse)
{
// Да, у нас есть ожидающий запрос. Снимите флажок, а затем отправьте веб-страницу клиенту.
bPendingHttpResponse = false;
// отправляем стандартный HTTP-заголовок ответа и HTML-заголовок
HtmlHeader(client);
// Выводим текстовый заголовок
client.println("<H1>Kevin's RoboSapien Webserver</H1>");
client.println("<table border cellspacing=0 cellpadding=5><tr>");
client.println("<td>");
// Создаем кнопки
SubmitButton(client, "WakeUp", RSWakeUp);
SubmitButton(client, "Roar", RSRoar);
SubmitButton(client, "Whistle", RSWhistle);
SubmitButton(client, "High5", RSHigh5);
client.println("<br>");
client.println("</td><td>");
SubmitButton(client, "LeftArmUp", RSLeftArmUp);
SubmitButton(client, "LeftArmIn", RSLeftArmIn);
SubmitButton(client, "LeftArmOut", RSLeftArmOut);
SubmitButton(client, "LeftArmDown", RSLeftArmDown);
SubmitButton(client, "LeftArmSweep", RSLeftHandSweep);
client.println("<br>");
client.println("</td><td>");
SubmitButton(client, "RightArmUp", RSRightArmUp);
SubmitButton(client, "RightArmIn", RSRightArmIn);
SubmitButton(client, "RightArmOut", RSRightArmOut);
SubmitButton(client, "RightArmDown", RSRightArmDown);
SubmitButton(client, "RightArmSweep", RSRightHandSweep);
client.println("<br>");
client.println("</td></tr></table>");
client.print("<br><br><br>URL Hex no: ");
client.print(viRobsapienUrlCmd, HEX);
client.println("<br />");
// отправить нижний колонтитул HTML
HtmlFooter(client);
// дать веб-браузеру время для получения данных
delay(1);
client.stop();
}
}
} // Конец пока(подключено)
}
}
////////////////////////////////////////////////// ////////////////
// начинаем точки входа arduino
////////////////////////////////////////////////// ////////////////
void setup()
{
// открываем последовательный порт на скорости 9600 бит/с:
Serial.begin(9600);
// Распечатать приветствие
Serial.println("Kevin's RobSapien Server");
RSSetup();
WebServerSetup();
}
void loop()
{
RSLoop();
WebServerLoop();
}
@JasonBreen, 👍2
2 ответа
Вы не можете напрямую использовать Клиент. Это просто абстрактный класс. Вы должны использовать один из классов, таких как EthernetClient или WiFiClient, который его реализует.
Клиент похож на оболочку класса. В нем говорится, что будут классы, которые действуют как клиенты и будут иметь эту базовую форму. Но у него нет никакого кода, только схема. Базовые классы, которые реализуют этот абстрактный класс, например EthernetClient или WiFiClient, на самом деле имеют код, который фактически БУДЕТ клиентом.
Я предполагаю, что проблема здесь:
void HtmlFooter(Client client) {
client.println("</BODY></HTML>");
}
(также функция HtmlHeader)
Когда вы вызываете эту функцию, вы создаете новый объект Client и копируете в него содержимое существующего объекта. Поскольку клиент является чисто виртуальным, вы не можете этого сделать. Вместо этого вы должны работать со ссылкой, как и в других функциях:
void HtmlFooter(Client &client) {
client.println("</BODY></HTML>");
}
- Ошибка: expected unqualified-id before 'if'
- Как получить HTTPS на Arduino?
- Ошибка компиляции кода для Arduino/Genuino Uno
- Ошибка : заблудиться '\' в программе
- Ошибка: invalid application of 'sizeof' to incomplete type 'int []' при попытке вычислить размер массива в библиотеке
- Клиент MQTT на Arduino + SIM900
- Arduino Ethernet Shield при использовании контактов Arduino Mega
- Ethernet nodemcu