Я должен настроить дистанционное управление приложением MCU.
В поле MCU основан на ATMEGA 1284P.MCU комплектуется модемом GPRS на основе модуля SIM808.
MCU устанавливает соединение TCPIP с удаленным СЕРВЕРОМ по своему IP-адресу и порту.На стороне MCU все основано на официальной заметке SIM900_TCPIP_Application_V1.02, и я сравнил реализацию с https://vsblogs.wordpress.com/2013/11/28/tcp-connection-over-gprs-using-sim900-and-at-commands/ и https://www.electronicwings.com/pic/pic18f4550-interface-with-sim900a-gprs и https://www.cooking -hacks.com / Документация / Tutorials / gprs-gsm-quadband-module-arduino-raspberry-pi-tutorial-sim-900 # введение
Соединение с СЕРВЕРОМ происходит регулярно, строка JSON от клиента к серверу отправляется правильнои приложение GUI на стороне сервера получает JSON и корректно обновляет интерфейс GUI, как и ожидалось.Таким образом, удаленный мониторинг работает отлично, непрерывно и навсегда (до тех пор, пока СЕРВЕР не будет остановлен).
В GUI APP написано Qt C ++.Код MCU записывается в AVRstudio C.
Когда приложение Qt, действительно сервер, пытается отправить обратно JSON, в MCU я получаю строку в буфер UART;если я проверю это, это как ожидалось, но модем GPRS входит в своего рода бесконечный цикл.Модем GPRS никогда не освобождает управление, никогда не принимает никакую другую команду AT.Поэтому я не могу отправить любой другой JSON и обновить удаленный монитор.Единственный выход - это сброс модема и отмена сеанса TCPIP.
После сброса снова можно отправить все требуемые JSON, но при первой же попытке отправить JSON из приложения Qt вMCU модем блокируется и не принимает никаких других AT-команд.
Я должен сбросить его.
Наконец невозможно, чтобы СЕРВЕР отправил JSON клиенту.Он получает правильно, но не отвечает, когда хочет ответить.
Вот как мы читаем / записываем данные из приложения (сторона SERVER)
#include "communicationhandler.h"
#include <QTcpSocket>
#include <QJsonDocument>
#include <QJsonObject>
#include <QtDebug>
CommunicationHandler::CommunicationHandler(QObject *parent)
: QObject(parent)
{
init();
}
void CommunicationHandler::init()
{
tcpServer = new QTcpServer(this);
}
bool CommunicationHandler::startServer(int port)
{
if (tcpServer->isListening())
return true;
if (port <= 0)
{
return false;
}
if (tcpServer->listen(QHostAddress::AnyIPv4, port))
{
connect(tcpServer, &QTcpServer::newConnection,
this, &CommunicationHandler::onNewConnection);
return true;
}
return false;
}
bool CommunicationHandler::stopServer()
{
if (!tcpServer->isListening())
return true;
tcpServer->close();
return true;
}
bool CommunicationHandler::isServerListening()
{
return tcpServer->isListening();
}
void CommunicationHandler::onNewConnection()
{
connectionSocket = tcpServer->nextPendingConnection();
connect(connectionSocket, &QTcpSocket::readyRead, this, &CommunicationHandler::onData);
}
void CommunicationHandler::onData()
{
QTcpSocket* socket = (QTcpSocket*)sender();
if (socket)
{
QByteArray data = socket->readAll();
jsonData += data;
qDebug() << jsonData;
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData);
if (!jsonDoc.isEmpty())
{
emit jsonReceived(jsonDoc);
dataToBeSent = jsonData;
jsonData.clear();
}
}
}
void CommunicationHandler::sendParameterData(const QByteArray& data)
{
QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
if (!jsonDoc.isEmpty())
{
QJsonDocument fullJsonDoc = QJsonDocument::fromJson(dataToBeSent);
if (!fullJsonDoc.isEmpty())
{
//"{\"buzzer\":\"y\",\"deltaRpm\":50,\"door\":11,\"function\":\"a\",\"ins\":{\"l1\":120,\"l2\":100,\"l3\":80,\"l4\":20},\"powerMode\":\"b\",\"pressure\":35,\"reactTime\":12,\"rel\":{\"l1\":220,\"l2\":180,\"l3\":45,\"l4\":0},\"rpm\":2800,\"service\":127,\"test\":\"y\"}"
QVariantMap map = jsonDoc.toVariant().toMap();
QVariantMap fullMap = fullJsonDoc.toVariant().toMap();
fullMap["buzzer"] = map.value("buzzer");
fullMap["deltaRpm"] = map.value("deltaRpm");
fullMap["door"] = map.value("door");
fullMap["function"] = map.value("function");
fullMap["ins"] = map.value("ins");
fullMap["powerMode"] = map.value("powerMode");
fullMap["pressure"] = map.value("pressure");
fullMap["reactTime"] = map.value("reactTime");
fullMap["rel"] = map.value("rel");
fullMap["rpm"] = map.value("rpm");
fullMap["service"] = map.value("service");
fullMap["test"] = map.value("test");
QJsonDocument doc = QJsonDocument::fromVariant(fullMap);
QByteArray jsonData = doc.toJson(QJsonDocument::Compact);
sendData(jsonData);
}
}
}
void CommunicationHandler::sendData(const QByteArray& data)
{
if (connectionSocket!=nullptr)
{
qDebug() << "Sending Data to Device: " << data;
QByteArray dataToBeSent = data;
dataToBeSent.append('\r');
connectionSocket->write(dataToBeSent);
connectionSocket->flush();
}
}
ПочемуAPP на стороне сервера, когда отправляет JSON клиенту блокирует модем GPRS?Есть ли какое-либо рукопожатие на стороне сервера, прежде чем отправлять JSON в MCU?
Как уровень TCPIP на стороне сервера сообщает, что он готов принять строку для отправки клиенту?На стороне MCU после AT + CIPSEND уровень TCPIP выпускает приглашение>, и только после этого приглашения можно отправить JSON.Когда передача успешно завершена (получена СЕРВЕРОМ), уровень TCPIP выпускает сообщение SEND OK, действительно OK для отправки нового JSON. Ничего подобного на стороне СЕРВЕРА?
Я не нашел никакого полезного объяснения того, как и когда СЕРВЕР может отправить JSON обратно в MCU.Сразу после получения JSON от MCU и без какой-либо заботы о каких-либо запросах от уровня TCPIP?
Если на стороне MCU ATMEGA я достаточно опытен, мои возможности с кодом сервера ограничены.
Конечно, я могу опубликовать код C о MCU, но он довольно сложный и не требует немедленного чтения, потому что управление модемом GPRS и всеми AT-командами выполняется параллельно со всем другим процессом, который управляет подключенными устройствами.,Таким образом, процессы делятся на этапы, и каждый этап выполняется только после окончания обратного отсчета.В любом случае, если нужно, я отправлю.
Я думаю, что проблема на стороне СЕРВЕРА, а не на стороне MCU.
Спасибо за любую помощь.
С уважением.Mario