~aleteoryx/muditaos

ref: 9ba4d8cea949692768b4cbb0042fad7999362faa muditaos/module-cellular/modem/ATURCStream.cpp -rw-r--r-- 4.3 KiB
9ba4d8ce — Lukasz Mastalerz [BH-1838] Relaxation plays in the background for certain song lengths 2 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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ATURCStream.hpp"
#include "ATCommon.hpp"

#include <module-os/RTOSWrapper/include/ticks.hpp>
#include <cstring>

namespace at
{

    /**
     * Look for first possible urc begin \r\n+
     * remove everything in front(should not happen but possible communication errors)
     * @return true if have urc begin to process
     */
    bool ATURCStream::search()
    {
        if (!urcBeginFound) {
            auto pos = atBuffer.find(urcStart);
            if (pos == std::string::npos) {
                atBuffer = {};
                return false;
            }

            urcBeginFound = true;

            atBuffer.erase(0, pos);
            return true;
        }
        return true;
    }

    /**
     * check that quotation mark is open or close in current buffer
     * to wait for next chunk or if closed and urc is closed by \r\n ad to ready urc list
     * @return true if found urc line
     */
    bool ATURCStream::checkQuotation()
    {
        if (!openQuotationMark) {
            auto posDelimiter = atBuffer.find(at::delimiter, posMark + 1);
            if (posDelimiter != std::string::npos) {
                auto posMark2 = atBuffer.find("\"", posMark + 1);
                if ((posMark2 != std::string::npos) && (posDelimiter > posMark2)) {
                    posMark           = posMark2;
                    openQuotationMark = !openQuotationMark;
                    return false;
                }

                urcList.push_back(atBuffer.substr(0, posDelimiter + std::strlen(at::delimiter)));
                atBuffer.erase(0, posDelimiter + std::strlen(at::delimiter));
                lookForNextURC = true;
                return true;
            }
        }
        return false;
    }

    /**
     * Check for next quotation and urc, in general could look like
     * \r\n+URC: "literal \r\n...."\r\n\r\n+URC: "param",4,4\r\n ...
     * or
     * \r\nURC... \r\n
     * @return true if found and we could look for next URCin buffer
     */
    bool ATURCStream::lookForNext()
    {
        lookForNextURC    = false;
        openQuotationMark = false;
        posMark           = 0; /// start from \r\n(+) from search
        do {
            if (checkQuotation())
                break;

            openQuotationMark = !openQuotationMark;
            posMark           = atBuffer.find("\"", posMark + 1);
        } while (posMark != std::string::npos);

        return lookForNextURC;
    }
    /**
     * try to find URC in current buffer,
     * found results could be get by getURCList
     */
    void ATURCStream::tryParse()
    {

        while (search()) {

            if (!lookForNext()) {
                urcBeginFound = false;
                break;
            }
        }
    }

    /**
     * This function reset buffer in case it is too big or too old.
     * it is dictated only by the possibility related to transmission errors.
     */
    void ATURCStream::fuse()
    {
        /**
         * multiple frame have around hundreds char, so they should be delayed only by
         * transmission time and for one URC should be (from experiment) around 1ms
         * if frame delay is too long, there is a possibility that we have some transmission
         * errors, eg.frames
         * [1ms]Frame1: \r\n+URC: param,"long string .....
         * [2ms]Frame2: error .... and some part without end of quotation mark  ... \r\n
         * [100ms] Frame3:\r\n+NextURC:ABC\r\n
         *
         * In case checking only data we omit NextURC, because we could also get URC which look like
         * \r\n+URC: param,"\r\n+NextURC:ABC\r\n"\r\n
         */

        if (atBuffer.empty())
            return;

        constexpr auto maxTimeout = 5;
        constexpr auto maxSize    = 2048;
        uint32_t timeoutNeeded    = lastWriteTime + maxTimeout;
        uint32_t timeElapsed      = cpp_freertos::Ticks::GetTicks();
        if ((timeElapsed >= timeoutNeeded) || (atBuffer.length() > maxSize)) {
            LOG_ERROR("AT URC Stream timeout ");
            atBuffer = {};
        }
    }

    bool ATURCStream::write(const std::string &buffer)
    {
        fuse();
        lastWriteTime = cpp_freertos::Ticks::GetTicks();
        atBuffer += buffer;
        tryParse();
        return true;
    }

} // namespace at