~aleteoryx/muditaos

ref: 1f7d47183133e84f05babb8626d6d032421d97e7 muditaos/module-services/service-cellular/CellularCall.cpp -rw-r--r-- 5.3 KiB
1f7d4718 — alek [EGD-4429] Fix gui issues in application call 5 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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "service-cellular/CellularCall.hpp"

#include <CalllogRecord.hpp>
#include <PhoneNumber.hpp>
#include <Utils.hpp>
#include <log/log.hpp>
#include <time/time_conversion.hpp>

#include <cinttypes>
#include <optional>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>

namespace ModemCall
{
    ModemCall::ModemCall(const std::string str)
    {
        const std::string prefix = "+CLCC: ";
        std::string callEntry    = str;

        // Check for a valid prefix
        if (callEntry.rfind(prefix, 0) != 0) {

            throw std::runtime_error("No valid prefix");
        }
        else {
            // remove the prefix
            callEntry.erase(0, prefix.length());
        }

        std::vector<std::string> tokens = utils::split(callEntry, ",");

        auto numberOfTokens = tokens.size();
        if (numberOfTokens != 7 && numberOfTokens != 8) {
            throw std::runtime_error("Wrong number of tokens" + std::to_string(numberOfTokens));
        }

        idx           = std::stoul(tokens[0]);
        auto conv_val = std::stoul(tokens[1]);
        auto tmp_dir  = magic_enum::enum_cast<CallDir>(conv_val);
        if (tmp_dir.has_value()) {
            dir = tmp_dir.value();
        }
        else {
            throw std::runtime_error("dir value out of range CallDir enum - " + tokens[1]);
        }

        conv_val       = std::stoul(tokens[2]);
        auto tmp_state = magic_enum::enum_cast<CallState>(conv_val);
        if (tmp_state.has_value()) {
            state = tmp_state.value();
        }
        else {
            throw std::runtime_error("state value out of range CallState enum - " + tokens[2]);
        }

        conv_val      = std::stoul(tokens[3]);
        auto tmp_mode = magic_enum::enum_cast<CallMode>(conv_val);
        if (tmp_mode.has_value()) {
            mode = tmp_mode.value();
        }
        else {
            throw std::runtime_error("mode value out of range CallMode enum - " + tokens[3]);
        }

        isConferenceCall = static_cast<bool>(std::stoul(tokens[4]));
        phoneNumber      = tokens[5];

        try {
            conv_val = std::stoul(tokens[6]);
        }
        catch (const std::logic_error &) {
            conv_val = 0;
        }
        type = conv_val;

        if (numberOfTokens == 8) {
            phoneBookName = tokens[7];
        }
    }

    std::ostream &operator<<(std::ostream &out, const ModemCall &call)
    {
        out << " <idx> " << call.idx << " <dir> " << static_cast<uint32_t>(call.dir) << " <stat> "
            << static_cast<uint32_t>(call.state) << " <mode> " << static_cast<uint32_t>(call.mode) << " <mpty> "
            << static_cast<uint32_t>(call.isConferenceCall) << " <number> " << call.phoneNumber << " <type> "
            << static_cast<uint32_t>(call.type);

        if (!call.phoneBookName.empty()) {
            out << " <alpha> " << call.phoneBookName;
        }

        return out;
    }
} // namespace ModemCall

namespace CellularCall
{
    bool CellularCall::startCall(const utils::PhoneNumber::View &number, const CallType type)
    {
        if (isValid()) {
            LOG_ERROR("call already set");
            return false;
        }

        clear();
        CalllogRecord callRec;
        callRec.type        = type;
        callRec.date        = utils::time::Timestamp().getTime();
        callRec.name        = number.getFormatted(); // temporary set name to entered number
        callRec.phoneNumber = number;
        call                = startCallAction ? startCallAction(callRec) : CalllogRecord();
        if (!call.isValid()) {
            LOG_ERROR("startCallAction failed");
            clear();
            return false;
        }

        return true;
    }

    bool CellularCall::setActive()
    {
        if (isValid()) {
            startActiveTime = utils::time::Timestamp();
            isActiveCall    = true;
            return true;
        }
        return false;
    }

    bool CellularCall::endCall(Forced forced)
    {
        if (!isValid()) {
            LOG_ERROR("Trying to update invalid call");
            return false;
        }

        if (isActiveCall) {
            auto endTime  = utils::time::Timestamp();
            call.duration = (endTime - startActiveTime).get();
        }
        else {
            auto callType = call.type;
            switch (callType) {
            case CallType::CT_INCOMING: {
                if (forced == Forced::True) {
                    setType(CallType::CT_REJECTED);
                }
                else {
                    setType(CallType::CT_MISSED);
                    markUnread();
                }
            } break;

            case CallType::CT_OUTGOING: {
                // do nothing
            } break;

            default:
                LOG_ERROR("Not a valid call type %u", static_cast<int>(callType));
                return false;
            }
        }

        if (!(endCallAction && endCallAction(call))) {
            LOG_ERROR("CalllogUpdate failed, id %" PRIu32, call.ID);
            return false;
        }

        // Calllog entry was updated, ongoingCall can be cleared
        clear();

        return true;
    }
} // namespace CellularCall