mirror of
https://github.com/torlando-tech/pyxis.git
synced 2026-08-24 11:39:49 +00:00
217 lines
8.1 KiB
C++
217 lines
8.1 KiB
C++
#include "LocationShareControlModel.h"
|
|
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
|
|
namespace UI {
|
|
namespace LXMF {
|
|
|
|
LocationShareControlModel::LocationShareControlModel()
|
|
: peer_{}, status_(LocationShareControlStatus::OFF),
|
|
error_(LocationShareControlError::NONE),
|
|
duration_(LocationShareDuration::MINUTES_15),
|
|
cadence_(LocationShareCadence::MINUTE_1),
|
|
precision_(LocationSharePrecision::EXACT), expiresAtMillis_(0),
|
|
hasPeer_(false), confirmationPending_(false) {}
|
|
|
|
bool LocationShareControlModel::openForPeer(const uint8_t* peer,
|
|
std::size_t peerSize) {
|
|
applyOff();
|
|
hasPeer_ = false;
|
|
std::memset(peer_, 0, sizeof(peer_));
|
|
if (peer == NULL || peerSize != sizeof(peer_)) {
|
|
error_ = LocationShareControlError::INVALID;
|
|
return false;
|
|
}
|
|
std::memcpy(peer_, peer, sizeof(peer_));
|
|
hasPeer_ = true;
|
|
return true;
|
|
}
|
|
|
|
bool LocationShareControlModel::selectDuration(LocationShareDuration duration) {
|
|
switch (duration) {
|
|
case LocationShareDuration::MINUTES_15:
|
|
case LocationShareDuration::HOUR_1:
|
|
case LocationShareDuration::HOURS_4:
|
|
duration_ = duration;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool LocationShareControlModel::selectCadence(LocationShareCadence cadence) {
|
|
switch (cadence) {
|
|
case LocationShareCadence::MINUTE_1:
|
|
case LocationShareCadence::MINUTES_5:
|
|
case LocationShareCadence::MINUTES_15:
|
|
cadence_ = cadence;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool LocationShareControlModel::selectPrecision(LocationSharePrecision precision) {
|
|
switch (precision) {
|
|
case LocationSharePrecision::EXACT:
|
|
case LocationSharePrecision::METERS_100:
|
|
case LocationSharePrecision::KILOMETER_1:
|
|
case LocationSharePrecision::KILOMETERS_10:
|
|
precision_ = precision;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool LocationShareControlModel::requestConfirmation() {
|
|
if (!hasPeer_) {
|
|
applyError(LocationShareControlError::INVALID);
|
|
return false;
|
|
}
|
|
error_ = LocationShareControlError::NONE;
|
|
confirmationPending_ = true;
|
|
return true;
|
|
}
|
|
|
|
void LocationShareControlModel::applyOff() {
|
|
status_ = LocationShareControlStatus::OFF;
|
|
error_ = LocationShareControlError::NONE;
|
|
expiresAtMillis_ = 0;
|
|
confirmationPending_ = false;
|
|
}
|
|
|
|
void LocationShareControlModel::applyActive(uint64_t expiresAtMillis,
|
|
uint32_t cadenceMillisValue,
|
|
bool hasApproximationValue,
|
|
int32_t approximationMetersValue) {
|
|
status_ = LocationShareControlStatus::ACTIVE;
|
|
error_ = LocationShareControlError::NONE;
|
|
expiresAtMillis_ = expiresAtMillis;
|
|
confirmationPending_ = false;
|
|
if (cadenceMillisValue == 60000U) cadence_ = LocationShareCadence::MINUTE_1;
|
|
else if (cadenceMillisValue == 300000U) cadence_ = LocationShareCadence::MINUTES_5;
|
|
else if (cadenceMillisValue == 900000U) cadence_ = LocationShareCadence::MINUTES_15;
|
|
if (!hasApproximationValue) precision_ = LocationSharePrecision::EXACT;
|
|
else if (approximationMetersValue == 100) precision_ = LocationSharePrecision::METERS_100;
|
|
else if (approximationMetersValue == 1000) precision_ = LocationSharePrecision::KILOMETER_1;
|
|
else if (approximationMetersValue == 10000) precision_ = LocationSharePrecision::KILOMETERS_10;
|
|
}
|
|
|
|
void LocationShareControlModel::markStopping() {
|
|
status_ = LocationShareControlStatus::STOPPING;
|
|
error_ = LocationShareControlError::NONE;
|
|
confirmationPending_ = false;
|
|
}
|
|
|
|
void LocationShareControlModel::applyError(LocationShareControlError error) {
|
|
if (status_ != LocationShareControlStatus::ACTIVE) {
|
|
status_ = LocationShareControlStatus::OFF;
|
|
}
|
|
error_ = error;
|
|
confirmationPending_ = false;
|
|
}
|
|
|
|
uint64_t LocationShareControlModel::durationMillis() const {
|
|
switch (duration_) {
|
|
case LocationShareDuration::MINUTES_15: return 15ULL * 60ULL * 1000ULL;
|
|
case LocationShareDuration::HOUR_1: return 60ULL * 60ULL * 1000ULL;
|
|
case LocationShareDuration::HOURS_4: return 4ULL * 60ULL * 60ULL * 1000ULL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
uint32_t LocationShareControlModel::cadenceMillis() const {
|
|
switch (cadence_) {
|
|
case LocationShareCadence::MINUTE_1: return 60000U;
|
|
case LocationShareCadence::MINUTES_5: return 300000U;
|
|
case LocationShareCadence::MINUTES_15: return 900000U;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool LocationShareControlModel::hasApproximation() const {
|
|
return precision_ != LocationSharePrecision::EXACT;
|
|
}
|
|
|
|
int32_t LocationShareControlModel::approximationMeters() const {
|
|
switch (precision_) {
|
|
case LocationSharePrecision::EXACT: return 0;
|
|
case LocationSharePrecision::METERS_100: return 100;
|
|
case LocationSharePrecision::KILOMETER_1: return 1000;
|
|
case LocationSharePrecision::KILOMETERS_10: return 10000;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
const char* LocationShareControlModel::durationText(LocationShareDuration duration) {
|
|
switch (duration) {
|
|
case LocationShareDuration::MINUTES_15: return "15 min";
|
|
case LocationShareDuration::HOUR_1: return "1 hour";
|
|
case LocationShareDuration::HOURS_4: return "4 hours";
|
|
}
|
|
return "invalid";
|
|
}
|
|
|
|
const char* LocationShareControlModel::cadenceText(uint32_t cadenceMillisValue) {
|
|
if (cadenceMillisValue == 60000U) return "1 min";
|
|
if (cadenceMillisValue == 300000U) return "5 min";
|
|
if (cadenceMillisValue == 900000U) return "15 min";
|
|
return "invalid";
|
|
}
|
|
|
|
const char* LocationShareControlModel::precisionText(bool hasApproximationValue,
|
|
int32_t meters) {
|
|
if (!hasApproximationValue) return "Exact";
|
|
if (meters == 100) return "100 m";
|
|
if (meters == 1000) return "1 km";
|
|
if (meters == 10000) return "10 km";
|
|
return "invalid";
|
|
}
|
|
|
|
bool LocationShareControlModel::formatConfirmation(char* output,
|
|
std::size_t capacity) const {
|
|
if (output == NULL || capacity == 0 || !hasPeer_) return false;
|
|
char peerHex[33];
|
|
for (std::size_t i = 0; i < sizeof(peer_); ++i) {
|
|
std::snprintf(peerHex + i * 2, 3, "%02x", peer_[i]);
|
|
}
|
|
const int written = std::snprintf(
|
|
output, capacity, "Share with %s?\nDuration: %s\nCadence: %s\nPrecision: %s",
|
|
peerHex, durationText(duration_), cadenceText(cadenceMillis()),
|
|
precisionText(hasApproximation(), approximationMeters()));
|
|
return written >= 0 && static_cast<std::size_t>(written) < capacity;
|
|
}
|
|
|
|
bool LocationShareControlModel::formatState(char* output,
|
|
std::size_t capacity) const {
|
|
if (output == NULL || capacity == 0) return false;
|
|
const char* statusText = status_ == LocationShareControlStatus::ACTIVE
|
|
? "ACTIVE" : status_ == LocationShareControlStatus::STOPPING
|
|
? "STOPPING" : "OFF";
|
|
const int written = std::snprintf(
|
|
output, capacity, "%s\nExpiry: %llu\nCadence: %s\nPrecision: %s",
|
|
statusText, static_cast<unsigned long long>(expiresAtMillis_),
|
|
cadenceText(cadenceMillis()),
|
|
precisionText(hasApproximation(), approximationMeters()));
|
|
return written >= 0 && static_cast<std::size_t>(written) < capacity;
|
|
}
|
|
|
|
const char* LocationShareControlModel::errorText() const {
|
|
switch (error_) {
|
|
case LocationShareControlError::NONE: return "";
|
|
case LocationShareControlError::CLOCK_UNAVAILABLE:
|
|
return "System clock unavailable. Get GPS/network time, then retry.";
|
|
case LocationShareControlError::STORAGE_FAILURE:
|
|
return "Location storage failure. Check filesystem and retry.";
|
|
case LocationShareControlError::CAPACITY:
|
|
return "Sharing capacity reached. Stop another peer and retry.";
|
|
case LocationShareControlError::BUSY:
|
|
return "Location sharing busy. Wait for pending delivery and retry.";
|
|
case LocationShareControlError::INVALID:
|
|
return "Peer or sharing selection invalid; sharing remains off.";
|
|
}
|
|
return "Invalid location sharing state.";
|
|
}
|
|
|
|
} // namespace LXMF
|
|
} // namespace UI
|