~aleteoryx/muditaos

ref: 25a5d90f4e12ee5d33f4202170f18b59e16a9564 muditaos/module-services/service-cellular/SMSParser.cpp -rw-r--r-- 3.3 KiB
25a5d90f — rrandomsky [CP-2156] Fixed no response when editing a contact to have the same number as another 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
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "SMSParser.hpp"

#include <log/log.hpp>
#include <ucs2/UCS2.hpp>

#include <algorithm>
#include <ctime>
#include <map>
#include <sstream>
#include <unordered_map>
#include <vector>

namespace SMSParser
{
    namespace
    {
        static constexpr auto SMSReadMsgName        = "QCMGR";
        static constexpr auto SingleMessageLength   = 5;
        static constexpr auto MultipleMessageLength = 8;

        std::unordered_map<std::uint16_t, std::map<std::uint8_t, std::string>> concatenatedMessage;
        std::string message;
        UTF8 number;
    } // namespace

    bool parse(const std::string *smsData)
    {
        bool parsed = false;

        if (smsData[0].find(SMSReadMsgName) == std::string::npos) {
            return parsed;
        }

        std::istringstream ss(smsData[0]);
        std::string token;
        std::vector<std::string> tokens;
        while (std::getline(ss, token, ',')) {
            tokens.push_back(token);
        }
        /*
         * tokens:
         * [0] - +QCMGR
         * [1] - sender number
         * [2] - none
         * [3] - date YY/MM/DD
         * [4] - hour HH/MM/SS/timezone
         * concatenaded messages
         * [5] - unique concatenated message id (range: 0-65535)
         * [6] - current message number
         * [7] - total messages count
         */
        tokens[1].erase(std::remove(tokens[1].begin(), tokens[1].end(), '\"'), tokens[1].end());
        number = UCS2(tokens[1]).toUTF8();

        // parse date
        tokens[3].erase(std::remove(tokens[3].begin(), tokens[3].end(), '\"'), tokens[3].end());

        if (tokens.size() == SingleMessageLength) {
            LOG_DEBUG("Single message");
            message = smsData[1];
            parsed  = true;
        }
        else if (tokens.size() == MultipleMessageLength) {
            std::uint32_t smsId   = 0;
            std::uint32_t current = 0;
            std::uint32_t total   = 0;
            try {
                smsId   = std::stoi(tokens[5]);
                current = std::stoi(tokens[6]);
                total   = std::stoi(tokens[7]);
            }
            catch (const std::exception &e) {
                LOG_ERROR("Parse SMS error %s", e.what());
                parsed = false;
                return parsed;
            }
            concatenatedMessage[smsId][current] = smsData[1];
            auto receivedConcatenatedMessages   = concatenatedMessage[smsId].size();
            LOG_DEBUG("Concatenated message uid: %" PRIu32 " rcv: %zu [%" PRIu32 "/%" PRIu32 "]",
                      smsId,
                      receivedConcatenatedMessages,
                      current,
                      total);
            if (receivedConcatenatedMessages == total) {
                message.clear();
                for (const auto &[_, smsMessageCat] : concatenatedMessage[smsId]) {
                    message += smsMessageCat;
                }
                concatenatedMessage.erase(smsId);
                parsed = true;
            }
        }
        return parsed;
    }

    UTF8 getNumber()
    {
        return number;
    }

    std::string getMessage()
    {
        return message;
    }

    time_t getTime()
    {
        return std::time(nullptr);
    }

} // namespace SMSParser