Welcome to mirror list, hosted at ThFree Co, Russian Federation.

reporter.cpp « tracking - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 35b59c65ae9c7fb97e72bb321f0fb9f04d7c951d (plain)
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
#include "reporter.hpp"

#include "platform/location.hpp"
#include "platform/socket.hpp"

#include "base/logging.hpp"
#include "base/timer.hpp"

#include "std/target_os.hpp"

namespace
{
double constexpr kRequiredHorizontalAccuracy = 10.0;
double constexpr kMinDelaySeconds = 1.0;
double constexpr kReconnectDelaySeconds = 60.0;
size_t constexpr kRealTimeBufferSize = 60;
} // namespace

namespace tracking
{
// static
// Apple and Android applications use different keys for settings.ini.
// Keys saved for existing users, so can' fix it easy, need migration.
// Use this hack until change to special traffic key.
#if defined(OMIM_OS_IPHONE)
const char Reporter::kEnableTrackingKey[] = "StatisticsEnabled";
#elif defined(OMIM_OS_ANDROID)
const char Reporter::kEnableTrackingKey[] = "AllowStat";
#else
const char Reporter::kEnableTrackingKey[] = "AllowStat";
#endif

// static
milliseconds const Reporter::kPushDelayMs = milliseconds(10000);

Reporter::Reporter(unique_ptr<platform::Socket> socket, string const & host, uint16_t port,
                   milliseconds pushDelay)
  : m_realtimeSender(move(socket), host, port, false)
  , m_pushDelay(pushDelay)
  , m_points(kRealTimeBufferSize)
  , m_thread([this] { Run(); })
{
}

Reporter::~Reporter()
{
  {
    lock_guard<mutex> lg(m_mutex);
    m_isFinished = true;
  }
  m_cv.notify_one();
  m_thread.join();
}

void Reporter::AddLocation(location::GpsInfo const & info)
{
  lock_guard<mutex> lg(m_mutex);

  if (info.m_horizontalAccuracy > kRequiredHorizontalAccuracy)
    return;

  if (info.m_timestamp < m_lastGpsTime + kMinDelaySeconds)
    return;

  m_lastGpsTime = info.m_timestamp;
  m_input.push_back(DataPoint(info.m_timestamp, ms::LatLon(info.m_latitude, info.m_longitude)));
}

void Reporter::Run()
{
  LOG(LINFO, ("Tracking Reporter started"));

  unique_lock<mutex> lock(m_mutex);

  while (!m_isFinished)
  {
    auto const startTime = steady_clock::now();

    // Fetch input.
    m_points.insert(m_points.end(), m_input.begin(), m_input.end());
    m_input.clear();

    lock.unlock();
    if (m_points.empty() && m_idleFn)
    {
      m_idleFn();
    }
    else
    {
      if (SendPoints())
        m_points.clear();
    }
    lock.lock();

    auto const passedMs = duration_cast<milliseconds>(steady_clock::now() - startTime);
    if (passedMs < m_pushDelay)
      m_cv.wait_for(lock, m_pushDelay - passedMs, [this]{return m_isFinished;});
  }

  LOG(LINFO, ("Tracking Reporter finished"));
}

bool Reporter::SendPoints()
{
  if (m_points.empty())
    return true;

  if (m_wasConnected)
    m_wasConnected = m_realtimeSender.Send(m_points);

  if (m_wasConnected)
    return true;

  double const currentTime = my::Timer::LocalTime();
  if (currentTime < m_lastConnectionAttempt + kReconnectDelaySeconds)
    return false;

  m_lastConnectionAttempt = currentTime;

  m_wasConnected = m_realtimeSender.Reconnect();
  if (!m_wasConnected)
    return false;

  m_wasConnected = m_realtimeSender.Send(m_points);
  return m_wasConnected;
}
}  // namespace tracking