~aleteoryx/muditaos

ref: 7d4452f90c40b1b5d3f673f321484c6f418bbea2 muditaos/module-cellular/Modem/ATParser.cpp -rw-r--r-- 3.6 KiB
7d4452f9 — Bartosz Cichocki [EGD-6052] Add idle BT device disconnect 4 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ATParser.hpp"
#include <service-fota/FotaServiceAPI.hpp>
#include "bsp/cellular/bsp_cellular.hpp"
#include <service-cellular/CellularMessage.hpp>
#include "ticks.hpp"
#include <Utils.hpp>
#include <utility>
#include <vector>

ATParser::ATParser(bsp::Cellular *cellular) : cellular(cellular)
{
    isInitialized = true;
}

/// plz see 12.7 summary of urc in documentation
std::vector<ATParser::Urc> ATParser::ParseURC()
{

    std::vector<ATParser::Urc> resp;
    size_t maxPos = 0, pos = 0;

    cpp_freertos::LockGuard lock(mutex);

    std::vector<std::pair<std::string, ATParser::Urc>> vals = {
        {"RDY", ATParser::Urc::MeInitializationSuccessful},
        {"+CFUN: 1", ATParser::Urc::FullFuncionalityAvailable},
    };

    for (const auto &el : vals) {
        pos = responseBuffer.find(el.first);
        if (pos != std::string::npos) {
            resp.push_back(el.second);
            maxPos = std::max(pos + el.first.length(), maxPos);
            LOG_DEBUG("%s", ("[URC]: " + el.first).c_str());
        }
    }

    if (responseBuffer.find("+QIND: \"FOTA\"") != std::string::npos) {
        LOG_DEBUG("%s", responseBuffer.c_str());
        resp.push_back(ATParser::Urc::Fota);
        return resp;
    }

    // manage string buffer
    if (maxPos == 0) {}
    else if (responseBuffer.size() >= maxPos) {
        responseBuffer.erase();
    }
    else {
        responseBuffer = responseBuffer.substr(maxPos);
    }

    return resp;
}

int ATParser::ProcessNewData(sys::Service *service)
{
    char rawBuffer[256] = {0};

    LOG_DEBUG("Receiving data from ProcessNewData");
    auto length = cellular->Read(rawBuffer, sizeof(rawBuffer));

    {
        cpp_freertos::LockGuard lock(mutex);
        responseBuffer.append(reinterpret_cast<char *>(rawBuffer), length);
        LOG_DEBUG("Appending %d bytes to responseBuffer[%u]: %s",
                  static_cast<int>(length),
                  static_cast<unsigned int>(responseBuffer.size()),
                  utils::removeNewLines(responseBuffer).c_str());
    }

    auto ret = ParseURC();
    if (blockedTaskHandle) {
        xTaskNotifyGive(blockedTaskHandle);
    }
    else if (ret.size()) {
        if (ret.size() == 1 && ret[0] == ATParser::Urc::Fota) {
            std::string fotaData(responseBuffer);
            LOG_DEBUG("parsing FOTA:\"%s\"", fotaData.c_str());
            FotaService::API::sendRawProgress(service, fotaData);
            responseBuffer.erase();
        }
        else {
            urcs.insert(std::end(urcs), std::begin(ret), std::end(ret));
        }
        // GSM modem is considered as operational when it outputs URCs specified below:
        // 1) RDY
        // 2) +CFUN: 1
        if (urcs.size() == 2) {
            cpp_freertos::LockGuard lock(mutex);
            auto msg = std::make_shared<CellularPowerUpProcedureCompleteNotification>();
            service->bus.sendMulticast(msg, sys::BusChannel::ServiceCellularNotifications);
            LOG_DEBUG("[!!!] Fucking away data");
            responseBuffer.erase();
            urcs.clear();
        }
    }
    return 1;
}

void ATParser::cmd_init()
{
    cpp_freertos::LockGuard lock(mutex);
    responseBuffer.erase();
}

void ATParser::cmd_send(std::string cmd)
{
    cellular->Write(const_cast<char *>(cmd.c_str()), cmd.size());
}

std::string ATParser::cmd_receive()
{
    cpp_freertos::LockGuard lock(mutex);
    return responseBuffer;
}

void ATParser::cmd_post()
{
    cpp_freertos::LockGuard lock(mutex);
    responseBuffer.erase(); // TODO:M.P is it okay to flush buffer here ?
}