-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathpacketstorage.cpp
148 lines (119 loc) · 4.27 KB
/
packetstorage.cpp
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
/*
nexus433
Copyright (C) 2018 aquaticus
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <chrono>
#include <ctime>
#include <map>
#include <iostream>
#include <iterator>
#include <unistd.h>
#include <inttypes.h>
#include "color.h"
#include "packetstorage.h"
#include "diag.h"
#include "packet.h"
uint32_t PacketStorage::m_SilentTimeoutSec = 90; //[secs]
void PacketStorage::Add(uint64_t raw)
{
Packet packet(raw);
// check packet. 0 is not valid.
if (!packet.IsValid())
{
DEBUG_PRINTF("DEBUG: Received invalid packet. %d\n", 0);
return;
}
// id + channel number
uint16_t id = packet.GetSenderId();
m_Lock.lock();
auto pos = m_Items.find(id);
if (pos == m_Items.end())
{
//not found
DEBUG_PRINTF("DEBUG: New transmitter 0x%02x\n", id);
DEBUG_PRINTF("DEBUG: New reading 0x%" PRIx64 " from transmitter 0x%02x\n", packet.GetRaw(), id);
packet.IncreaseFrameCounter();
StorageItem n(packet);
m_Items.insert(std::pair<uint16_t, StorageItem>(id, n));
}
else
{
//found
StorageItem& n = pos->second;
if (n.GetPacket().GetRaw() == packet.GetRaw())
{
n.GetPacket().IncreaseFrameCounter();
n.UpdateTimestamp();
#ifdef DEBUG_MORE
DEBUG_PRINTF("DEBUG: New frame #%d 0x%" PRIx64 " from transmitter 0x%02x\n", n.GetPacket().GetFrameCounter(), packet.GetRaw(), id);
#endif
}
else
{
DEBUG_PRINTF("DEBUG: New reading 0x%" PRIx64 " from transmitter 0x%02x\n", packet.GetRaw(), id);
n.NewPacket(packet);
}
}
m_Lock.unlock();
}
void PacketStorage::UpdateStatus(std::set<Packet>& NewReadings, std::set<uint16_t>& RemovedTransmitters,
std::set<uint16_t>& NewTransmitters)
{
auto now = std::chrono::system_clock::now();
Packet subst;
m_Lock.lock();
for (auto& i : m_Items)
{
auto &item = i.second;
uint32_t age = std::chrono::duration_cast<std::chrono::milliseconds>(now - item.GetTimestamp()).count();
// check if new station is available
if (item.IsNewTransmitter())
{
NewTransmitters.insert(item.GetPacket().GetSenderId());
item.ClearNewTransmitter();
DEBUG_PRINTF("DEBUG: UpdateStatus: New transmitter is available 0x%02x.\n", item.GetPacket().GetSenderId());
}
//if no new readings within 1 minute treat station as dead
if (age > GetSilentTimeoutSec()*1000)
{
DEBUG_PRINTF("DEBUG: Transmitter 0x%02x become silent.\n", i.first);
RemovedTransmitters.insert(i.first);
}
else if (age >= m_ReadingMaxAgeMs && item.GetPacket().GetRaw() != 0) // if reading comes after 1s from the last one is treated as a new reading
{
NewReadings.insert(item.GetPacket());
item.GetPacket().SetRaw(0); //set to invalid value. Next reading will update entry as new but won't indicate new sender
}
}
for (auto item : RemovedTransmitters)
{
DEBUG_PRINTF("DEBUG: Removing transmitter %02x from list of active stations\n", item);
m_Items.erase(item);
}
m_Lock.unlock();
}
std::list<uint16_t> PacketStorage::GetActiveTransmitters()
{
std::list<uint16_t> transmitters;
m_Lock.lock(); //iterator is const, so it should be thread safe but just in case
for (const auto& it : m_Items)
{
transmitters.push_back(it.first);
}
m_Lock.unlock();
return transmitters;
}
int PacketStorage::GetActiveTransmittersCount()
{
return m_Items.size();
}