~aleteoryx/muditaos

ref: master muditaos/module-cellular/modem/ATParser.cpp -rw-r--r-- 3.8 KiB
2cd0e472 — Lefucjusz [BH-000] Update Harmony 2.10.0 changelog 2 months 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
126
127
128
129
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/blob/master/LICENSE.md

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

using namespace std::chrono_literals;

ATParser::ATParser(bsp::Cellular *cellular) : Channel{new uint8_t[at::defaultReceiveBufferSize]}, cellular(cellular)
{
    assert(cellular != nullptr);

    responseBuffer = xMessageBufferCreate(at::defaultMessageBufferSize);
}

/// plz see 12.7 summary of urc in documentation
std::vector<ATParser::Urc> ATParser::parseUrc()
{
    size_t maxPos = 0, pos = 0;

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

    std::vector<ATParser::Urc> resp;
    resp.reserve(vals.size() + 1);
    cpp_freertos::LockGuard lock(mutex);

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

    if (urcBuffer.find("+QIND: \"FOTA\"") != std::string::npos) {
        resp.push_back(ATParser::Urc::Fota);
        return resp;
    }

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

    return resp;
}

at::Result ATParser::processNewData(sys::Service *service, const bsp::cellular::CellularResult &cellularResult)
{
    at::Result result;

    {
        cpp_freertos::LockGuard lock(mutex);
        urcBuffer.append(cellularResult.getDataAsString());
    }

    auto ret = parseUrc();

    if (awaitingResponseFlag.state()) {
        if (!xMessageBufferSend(responseBuffer,
                                cellularResult.getSerialized().get(),
                                cellularResult.getSerializedSize(),
                                pdMS_TO_TICKS(at::defaultBufferTimeoutMs.count()))) {
            LOG_DEBUG("[AT] Message buffer full!");
            result.code = at::Result::Code::FULL_MSG_BUFFER;
        }
    }
    else if (!ret.empty()) {
        if (ret.size() == 1 && ret[0] == ATParser::Urc::Fota) {
            LOG_DEBUG("Parsing FOTA");
            cpp_freertos::LockGuard lock(mutex);
            urcBuffer.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) {
            auto msg = std::make_shared<cellular::PowerUpProcedureCompleteNotification>();
            service->bus.sendMulticast(std::move(msg), sys::BusChannel::ServiceCellularNotifications);
            urcs.clear();

            cpp_freertos::LockGuard lock(mutex);
            urcBuffer.erase();
        }
    }
    else {
        result.code = at::Result::Code::DATA_NOT_USED;
    }

    return result;
}

void ATParser::cmdInit()
{
    cpp_freertos::LockGuard lock(mutex);
    urcBuffer.erase();
}

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

size_t ATParser::cmdReceive(std::uint8_t *buffer, std::chrono::milliseconds timeout = 0ms)
{
    return xMessageBufferReceive(responseBuffer, buffer, 256, pdMS_TO_TICKS(timeout.count()));
}

void ATParser::cmdPost()
{
    cpp_freertos::LockGuard lock(mutex);
    urcBuffer.erase();
    xMessageBufferReset(responseBuffer);
}