~aleteoryx/muditaos

ref: 7d4452f90c40b1b5d3f673f321484c6f418bbea2 muditaos/module-cellular/Modem/ATCommon.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
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ATCommon.hpp"
#include <at/Cmd.hpp>
#include "time/ScopedTime.hpp"
#include <functional>
#include <log/log.hpp>
#include <string>
#include <ticks.hpp>
#include <vector>
#include <inttypes.h> // for PRIu32
#include <Utils.hpp>
#include "ATStream.hpp"
#include <at/ATFactory.hpp>

using namespace at;

const std::string Channel::OK         = "OK";
const std::string Channel::ERROR      = "ERROR";
const std::string Channel::NO_CARRIER = "NO CARRIER";
const std::string Channel::BUSY       = "BUSY";
const std::string Channel::NO_ANSWER  = "NO ANSWER";
const std::string Channel::CME_ERROR  = "+CME ERROR:";
const std::string Channel::CMS_ERROR  = "+CMS ERROR:";
// const std::string Channel::CONNECT = "CONNECT";
// const std::string Channel::RING = "RING";
// const std::string Channel::NO_DIALTONE = "NO DIALTONE";

void Channel::cmd_log(std::string cmd, const Result &result, uint32_t timeout)
{
    cmd.erase(std::remove(cmd.begin(), cmd.end(), '\r'), cmd.end());
    cmd.erase(std::remove(cmd.begin(), cmd.end(), '\n'), cmd.end());
    switch (result.code) {
    case Result::Code::TIMEOUT: {
        LOG_INFO("[AT]: >%s<, timeout %" PRIu32
                 " - please check the value with Quectel_EC25&EC21_AT_Commands_Manual_V1.3.pdf",
                 cmd.c_str(),
                 timeout);
    } break;
    case Result::Code::ERROR: {
        LOG_INFO("[AT]: >%s<, >%s<", cmd.c_str(), result.response.size() ? result.response.back().c_str() : "");
    } break;
    default:
        LOG_INFO("[AT]: >%s<, >%s<", cmd.c_str(), result.response.size() ? result.response.back().c_str() : "");
        break;
    }
#if DEBUG_MODEM_OUTPUT_RESPONSE
    for (auto s : result.response) {
        LOG_DEBUG("[AT] > %s", s.c_str());
    }
#endif
}

std::string Channel::formatCommand(const std::string &cmd) const
{
    bool isTerminatorValid = std::find(validTerm.begin(), validTerm.end(), cmd.back()) != validTerm.end();
    if (isTerminatorValid) {
        return cmd;
    }
    return cmd + cmdSeparator;
}

Result Channel::cmd(const std::string &cmd, std::chrono::milliseconds timeout, size_t rxCount)
{
    Result result;
    blockedTaskHandle = xTaskGetCurrentTaskHandle();

    cmd_init();
    std::string cmdFixed = formatCommand(cmd);

    cmd_send(cmdFixed);

    uint32_t currentTime   = cpp_freertos::Ticks::GetTicks();
    uint32_t timeoutNeeded = ((timeout.count() == UINT32_MAX) ? UINT32_MAX : currentTime + timeout.count());
    uint32_t timeElapsed   = currentTime;

    ATStream atStream(rxCount);

    while (true) {
        if (timeoutNeeded != UINT32_MAX && timeElapsed >= timeoutNeeded) {
            result.code = Result::Code::TIMEOUT;
            break;
        }

        auto taskUnlocked = ulTaskNotifyTake(pdTRUE, timeoutNeeded - timeElapsed);
        timeElapsed       = cpp_freertos::Ticks::GetTicks();

        if (taskUnlocked) {
            atStream.write(cmd_receive());

            if (atStream.isReady()) {
                result = atStream.getResult();
                break;
            }
        }
    }

    blockedTaskHandle = nullptr;
    cmd_post();
    cmd_log(cmdFixed, result, timeout.count());

    return result;
}

auto Channel::cmd(const at::Cmd &at) -> Result
{
    auto time = utils::time::Scoped("Time to run at command" + at.getCmd());
    return cmd(at.getCmd(), at.getTimeout());
}

auto Channel::cmd(const at::AT &at) -> Result
{
    auto cmd  = at::factory(at);
    auto time = utils::time::Scoped("Time to run at command" + cmd.getCmd());
    return this->cmd(cmd);
}