Files
MuditaOS/module-cellular/Modem/ATCommon.cpp
2020-10-20 12:55:10 +02:00

121 lines
3.6 KiB
C++

// 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 <functional>
#include <log/log.hpp>
#include <string>
#include <ticks.hpp>
#include <vector>
using namespace at;
const std::string Chanel::OK = "OK";
const std::string Chanel::ERROR = "ERROR";
const std::string Chanel::NO_CARRIER = "NO CARRIER";
const std::string Chanel::BUSY = "BUSY";
const std::string Chanel::NO_ANSWER = "NO ANSWER";
// const std::string Chanel::CONNECT = "CONNECT";
// const std::string Chanel::RING = "RING";
// const std::string Chanel::NO_DIALTONE = "NO DIALTONE";
Result::Code Chanel::at_check(const std::vector<std::string> &arr)
{
if (arr.size()) {
for (auto el : arr) {
if (el.compare(0, OK.length(), OK) == 0) {
return Result::Code::OK;
}
else if (el.compare(0, ERROR.length(), ERROR) == 0) {
return Result::Code::ERROR;
}
}
}
return Result::Code::NONE;
}
void Chanel::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_ERROR("[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_ERROR("[AT]: >%s<, >%s<", cmd.c_str(), result.response.size() ? result.response.back().c_str() : "");
} break;
default:
LOG_DEBUG("[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
}
class Result Chanel::cmd(const std::string cmd, uint32_t timeout, size_t rxCount)
{
Result result;
blockedTaskHandle = xTaskGetCurrentTaskHandle();
cmd_init();
cmd_send(cmd);
uint32_t currentTime = cpp_freertos::Ticks::GetTicks();
uint32_t timeoutNeeded = ((timeout == UINT32_MAX) ? UINT32_MAX : currentTime + timeout);
uint32_t timeElapsed = currentTime;
while (1) {
if (timeoutNeeded != UINT32_MAX && timeElapsed >= timeoutNeeded) {
result.code = Result::Code::TIMEOUT;
break;
}
auto ret = ulTaskNotifyTake(pdTRUE, timeoutNeeded - timeElapsed);
timeElapsed = cpp_freertos::Ticks::GetTicks();
if (ret) {
std::vector<std::string> ret = cmd_receive();
result.response.insert(std::end(result.response), std::begin(ret), std::end(ret));
result.code = at_check(ret);
if (result.code != Result::Code::NONE) {
break;
}
if (rxCount != 0 && result.response.size() >= rxCount) {
result.code = Result::Code::TOKENS;
break;
}
}
}
blockedTaskHandle = nullptr;
cmd_post();
cmd_log(cmd, result, timeout);
return result;
}
auto Chanel::cmd(at::Cmd &at) -> Result
{
at.last.requested = cpp_freertos::Ticks::GetTicks();
Result result = this->cmd(at.cmd, at.timeout);
at.last.response = cpp_freertos::Ticks::GetTicks();
at.last.status = result.code;
return result;
}
auto Chanel::cmd(const at::AT at) -> Result
{
auto cmd = at::factory(at);
return this->cmd(cmd);
}