#include <types_internal.h>
#include <context_mgr.h>
#include "place_recognition.h"
+#include "user_places/user_places.h"
ctx::place_recognition_provider *ctx::place_recognition_provider::__instance = NULL;
-ctx::place_recognition_provider::place_recognition_provider()
-{
- engine.start();
-}
-
-ctx::place_recognition_provider::~place_recognition_provider()
-{
- engine.stop();
-}
-
ctx::context_provider_iface *ctx::place_recognition_provider::create(void *data)
{
IF_FAIL_RETURN(!__instance, __instance);
namespace ctx {
class place_recognition_provider : public context_provider_iface {
+
public:
static context_provider_iface *create(void *data);
static void destroy(void *data);
static place_recognition_provider *__instance;
UserPlaces engine;
- place_recognition_provider();
- ~place_recognition_provider();
+ place_recognition_provider() : engine(PLACE_RECOG_HIGH_ACCURACY_MODE) {}
+ ~place_recognition_provider() {}
}; /* class place_recognition_provider */
#define __CONTEXT_PLACE_RECOGNITION_TYPES__
// Context Items
-#define PLACE_SUBJ_RECOGNITION "place/pattern/personal_poi"
+#define PLACE_SUBJ_RECOGNITION "place/pattern/personal_poi"
-#define PLACE_PRIV_RECOGNITION "location"
+#define PLACE_PRIV_RECOGNITION "location"
// Database
#define VISIT_TABLE "place_status_user_place_visit"
PLACE_CATEG_ID_OTHER = 3
} place_categ_id_e;
+typedef enum {
+ PLACE_RECOG_HIGH_ACCURACY_MODE = 0,
+ PLACE_RECOG_LOW_POWER_MODE = 1
+} place_recog_mode_e;
+
#endif
namespace ctx {
class DebugUtils {
+
public:
static std::string human_readable_date_time(time_t timestamp, std::string format, size_t size, bool utc = false);
+
}; /* class DebugUtils */
} /* namespace ctx */
namespace ctx {
class ILocationListener {
+
public:
virtual ~ILocationListener() {};
virtual void on_new_location(location_event_s location) = 0;
} \
}
-
void ctx::LocationLogger::location_service_state_changed_cb(location_service_state_e state, void *user_data)
{
ctx::LocationLogger* location_logger_p = (ctx::LocationLogger *)user_data;
} timer_purpose_e;
class LocationLogger : public timer_listener_iface, public IVisitListener {
+
public:
LocationLogger(ILocationListener *listener_ = nullptr,
bool test_mode_ = false);
* Class for Mahalanobis distance computation.
*/
class MahalModel {
+
private:
std::vector<num_t> mean;
std::vector<num_t> sigma; // represents square matrix row-wise
* Piecewise linear function. Used for approximation.
*/
class PiecewiseLin {
+
private:
std::vector<num_t> xs; // nodes
std::vector<num_t> vs; // values in nodes
#include "../place_recognition_types.h"
#include "db_mgr.h"
-int ctx::UserPlaces::start()
+ctx::UserPlaces::UserPlaces(place_recog_mode_e energy_mode)
+ : visit_detector(nullptr)
{
- running = true;
time_t now = std::time(nullptr);
- visit_detector = new(std::nothrow) VisitDetector(now);
+ visit_detector = new(std::nothrow) VisitDetector(now, energy_mode);
if (visit_detector == nullptr) {
_E("Cannot initialize visit_detector");
- return ERR_OUT_OF_MEMORY;
+ return;
}
- return ERR_NONE;
}
-int ctx::UserPlaces::stop()
+ctx::UserPlaces::~UserPlaces()
{
- running = false;
+ if (places_detector_timer_id >= 0) {
+ timer_manager::remove(places_detector_timer_id);
+ _D("PlacesDetector timer removed");
+ }
- if (visit_detector == nullptr) {
- _E("No visit_detector to destroy");
- } else {
+ if (visit_detector) {
delete visit_detector;
}
- return ERR_NONE;
}
-bool ctx::UserPlaces::is_running()
+void ctx::UserPlaces::set_mode(place_recog_mode_e energy_mode)
{
- return running;
+ if (visit_detector) {
+ visit_detector->set_mode(energy_mode);
+ }
}
namespace ctx {
class UserPlaces {
+
private:
- bool running;
VisitDetector *visit_detector;
int places_detector_timer_id;
public:
- UserPlaces() : running(false) {}
- ~UserPlaces() {};
+ UserPlaces(place_recog_mode_e energy_mode = PLACE_RECOG_HIGH_ACCURACY_MODE);
+ ~UserPlaces();
- int start();
- int stop();
- bool is_running();
+ void set_mode(place_recog_mode_e energy_mode);
}; /* class UserPlaces */
#define __CONTEXT_PLACE_STATUS_USER_PLACES_PARAMS_H__
/*
- * WiFi scanning frequency (in minutes).
+ * WiFi scanning frequency (in minutes) in PLACE_RECOG_HIGH_ACCURACY_MODE.
*/
-#define WIFI_LOGGER_INTERVAL_MINUTES 3
+#define WIFI_LOGGER_INTERVAL_MINUTES_HIGH_ACCURACY 3
/*
- * Time window taken into consideration (in seconds).
+ * WiFi scanning frequency (in minutes) in PLACE_RECOG_LOW_POWER_MODE.
*/
-#define VISIT_DETECTOR_PERIOD_SECONDS 360
+#define WIFI_LOGGER_INTERVAL_MINUTES_LOW_POWER 60
+
+/*
+ * Time window taken into consideration (in seconds) in PLACE_RECOG_HIGH_ACCURACY_MODE.
+ */
+#define VISIT_DETECTOR_PERIOD_SECONDS_HIGH_ACCURACY 360
+
+/*
+ * Time window taken into consideration (in seconds) in PLACE_RECOG_LOW_POWER_MODE.
+ */
+#define VISIT_DETECTOR_PERIOD_SECONDS_LOW_POWER 3600
/*
* Overlap threshold between two sets of mac addresses (overlap
* visit categorizer class
*/
class VisitCateger {
+
private:
const static int MINUTES_IN_WEEK = 60 * 24 * 7;
const static std::map<int, MahalModel> models;
VISIT_COLUMN_CATEG_WORK " REAL, "\
VISIT_COLUMN_CATEG_OTHER " REAL"
-ctx::VisitDetector::VisitDetector(time_t t_start_scan, bool test_mode_)
+ctx::VisitDetector::VisitDetector(time_t t_start_scan, place_recog_mode_e energy_mode, bool test_mode_)
: test_mode(test_mode_)
, location_logger(this, test_mode_)
- , wifi_logger(this, test_mode_)
- , current_interval(t_start_scan, t_start_scan + VISIT_DETECTOR_PERIOD_SECONDS)
+ , wifi_logger(this, energy_mode, test_mode_)
+ , current_interval(t_start_scan, t_start_scan + VISIT_DETECTOR_PERIOD_SECONDS_HIGH_ACCURACY)
+ , stable_counter(0)
+ , tolerance(VISIT_DETECTOR_TOLERANCE_DEPTH)
+ , entrance_to_place(false)
+ , period_seconds(VISIT_DETECTOR_PERIOD_SECONDS_HIGH_ACCURACY)
+ , entrance_time(0)
+ , departure_time(0)
{
+ set_period(energy_mode);
+ current_interval = interval_s(t_start_scan, t_start_scan + period_seconds);
current_logger = std::make_shared<mac_events>();
stay_macs = std::make_shared<mac_set_t>();
- history_frames.push_back(std::make_shared<frame_s>(interval_s(0, VISIT_DETECTOR_PERIOD_SECONDS))); // prehistoric period
- entrance_to_place = false;
- stable_counter = 0;
- tolerance = VISIT_DETECTOR_TOLERANCE_DEPTH;
- departure_time = 0; // prehistoric time
if (test_mode) {
detected_visits = std::make_shared<ctx::visits_t>();
void ctx::VisitDetector::shift_current_interval()
{
- current_interval.end += VISIT_DETECTOR_PERIOD_SECONDS;
- current_interval.start += VISIT_DETECTOR_PERIOD_SECONDS;
+ current_interval.end += period_seconds;
+ current_interval.start += period_seconds;
}
void ctx::VisitDetector::detect_entrance_or_departure(std::shared_ptr<ctx::frame_s> frame)
void ctx::VisitDetector::detect_entrance(std::shared_ptr<ctx::frame_s> current_frame)
{
- if (current_frame->mac_counts.empty()) { // empty frame
+ if (current_frame->mac_counts.empty() || history_frames.empty()) {
history_reset(current_frame);
return;
}
if (stable_counter == 0) {
- std::shared_ptr<frame_s> oldest_history_frame = history_frames[0];
+ std::shared_ptr<frame_s> oldest_history_frame = history_frames[0];
stay_macs = mac_set_from_mac_counts(oldest_history_frame->mac_counts);
}
location_event.log();
locations.push_back(location_event);
};
+
+void ctx::VisitDetector::set_period(place_recog_mode_e energy_mode)
+{
+ switch (energy_mode) {
+ case PLACE_RECOG_LOW_POWER_MODE:
+ period_seconds = VISIT_DETECTOR_PERIOD_SECONDS_LOW_POWER;
+ break;
+ case PLACE_RECOG_HIGH_ACCURACY_MODE:
+ period_seconds = VISIT_DETECTOR_PERIOD_SECONDS_HIGH_ACCURACY;
+ break;
+ default:
+ _E("Incorrect energy mode");
+ }
+}
+
+void ctx::VisitDetector::set_mode(place_recog_mode_e energy_mode)
+{
+ _D("");
+ set_period(energy_mode);
+ wifi_logger.set_mode(energy_mode);
+}
namespace ctx {
class VisitDetector : public IWifiListener, ILocationListener {
+
private:
bool test_mode;
std::shared_ptr<visits_t> detected_visits; // only used in test mode
int stable_counter;
int tolerance;
bool entrance_to_place;
+ int period_seconds;
// fields that are used only in case of entrance detection
std::shared_ptr<mac_set_t> rep_macs; // mac that represent the current place
void json_put_visit_categ(json &data, const char* key, const categs_t &categs, int categ_type);
void json_put_visit_categs(json &data, const categs_t &categs);
int db_insert_visit(visit_s visit);
+ void set_period(place_recog_mode_e mode);
public:
- VisitDetector(time_t _t_start_scan, bool test_mode_ = false);
+ VisitDetector(time_t t_start_scan, place_recog_mode_e energy_mode = PLACE_RECOG_HIGH_ACCURACY_MODE, bool test_mode_ = false);
~VisitDetector();
interval_s get_current_interval();
void on_wifi_scan(mac_event_s event);
void process_current_logger();
std::shared_ptr<visits_t> get_visits(); // only used in test mode
void on_new_location(location_event_s location);
+ void set_mode(place_recog_mode_e energy_mode);
}; /* class VisitDetector */
namespace ctx {
class IVisitListener {
+
public:
virtual ~IVisitListener() {};
virtual void on_visit_start() = 0;
namespace ctx {
class IWifiListener {
+
public:
virtual ~IWifiListener() {};
virtual void on_wifi_scan(ctx::mac_event_s e) = 0;
} \
}
-
int ctx::WifiLogger::create_table()
{
bool ret = db_manager::create_table(0, WIFI_TABLE_NAME, WIFI_CREATE_TABLE_COLUMNS, NULL, NULL);
return 0;
}
-ctx::WifiLogger::WifiLogger(IWifiListener * listener_, bool test_mode_, int interval_minutes_)
+ctx::WifiLogger::WifiLogger(IWifiListener * listener_, place_recog_mode_e energy_mode, bool test_mode_)
: test_mode(test_mode_)
, listener(listener_)
, last_scan_time(time_t(0))
, last_timer_callback_time(time_t(0))
, timer_on(false)
- , interval_minutes(interval_minutes_)
+ , interval_minutes(WIFI_LOGGER_INTERVAL_MINUTES_HIGH_ACCURACY)
, during_visit(false)
, started(false)
, running(false)
{
_D("CONSTRUCTOR");
-
- if (interval_minutes <= 0) {
- _E("interval_minutes should be greater than zero");
- }
-
if (test_mode) return;
+ set_interval(energy_mode);
+
if (WIFI_LOGGER_DATABASE) {
create_table();
}
during_visit = false;
last_scans_pool.clear();
}
+
+void ctx::WifiLogger::set_interval(place_recog_mode_e energy_mode)
+{
+ switch (energy_mode) {
+ case PLACE_RECOG_LOW_POWER_MODE:
+ interval_minutes = WIFI_LOGGER_INTERVAL_MINUTES_LOW_POWER;
+ break;
+ case PLACE_RECOG_HIGH_ACCURACY_MODE:
+ interval_minutes = WIFI_LOGGER_INTERVAL_MINUTES_HIGH_ACCURACY;
+ break;
+ default:
+ _E("Incorrect energy mode");
+ }
+}
+
+void ctx::WifiLogger::timer_restart()
+{
+ timer_manager::remove(timer_id);
+ timer_start(interval_minutes);
+}
+
+void ctx::WifiLogger::set_mode(place_recog_mode_e energy_mode)
+{
+ _D("");
+ set_interval(energy_mode);
+ if (WIFI_LOGGER_ACTIVE_SCANNING && timer_on) {
+ timer_restart();
+ }
+}
namespace ctx {
class WifiLogger : public timer_listener_iface, public IVisitListener {
+
public:
WifiLogger(IWifiListener * listener_ = nullptr,
- bool test_mode_ = false,
- int interval_minutes = WIFI_LOGGER_INTERVAL_MINUTES);
+ place_recog_mode_e mode = PLACE_RECOG_HIGH_ACCURACY_MODE,
+ bool test_mode_ = false);
~WifiLogger();
void start_logging();
void stop_logging();
+ void set_mode(place_recog_mode_e energy_mode);
/* INPUT */
void on_visit_start();
void _start_logging();
void _stop_logging();
+ void set_interval(place_recog_mode_e energy_mode);
bool check_timer_id(int id);
bool check_timer_time(time_t now);
static const char* wifi_error_str(int error);
void timer_start(time_t minutes);
+ void timer_restart();
}; /* class WifiLogger */