TCPIP-связь между клиентом на ATMEGA 1284P и сервером на Win10 - PullRequest
0 голосов
/ 17 мая 2019

Я должен настроить дистанционное управление приложением 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

...