Skip to content

Commit

Permalink
fix: throw outdated events
Browse files Browse the repository at this point in the history
  • Loading branch information
std-microblock committed Oct 5, 2024
1 parent fb938d9 commit 0278e4a
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 21 deletions.
6 changes: 4 additions & 2 deletions cli/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@ int main(int argc, char **argv) {
.wakeupActions = wakeupActionsSet,
.suspendProcesses = suspendProcesses,
.wakeLog = wakeLog,
.disableDevices = disableDevices};
.disableDevices = disableDevices,
.sleepAfterLidCloseSeconds = 40};
} else {
goodnight::Logger::info("Using default config...");
config = {.keepSleep = true,
Expand All @@ -184,7 +185,8 @@ int main(int argc, char **argv) {
},
.suspendProcesses = false,
.wakeLog = true,
.disableDevices = false};
.disableDevices = false,
.sleepAfterLidCloseSeconds = 40};
}

// Output the config as a human readable string
Expand Down
6 changes: 3 additions & 3 deletions gui/gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ struct SavedConfig {
goodnight::Daemon::Config::WakeupActions::Other);
}
}
config.sleepAfterLidCloseSeconds = 40;
return config;
}

Expand Down Expand Up @@ -209,9 +210,8 @@ struct SavedConfig {

struct UIData {
int daemonEnabled; // 0 = disabled, 1 = enabled
goodnight::Daemon::Config config{
.wakeLog = true,
};
goodnight::Daemon::Config config{.wakeLog = true,
.sleepAfterLidCloseSeconds = 40};
std::vector<std::string> wakeupActions;
bool english = false;
bool runOnStartup = false;
Expand Down
7 changes: 6 additions & 1 deletion include/goodnight/goodnight.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ struct PowerListener {
void addListener(std::function<void(Events)> listener);

~PowerListener();
void emitEvent(Events event);

private:
void emitEvent(Events event);
bool started = false;
std::vector<std::function<void(Events)>> listeners;

Expand Down Expand Up @@ -173,6 +173,7 @@ struct Daemon {

bool wakeLog = false;
bool disableDevices = false;
int sleepAfterLidCloseSeconds = 0;
};
using expected = std::expected<void, std::string>;
expected updateConfig(const Config &config);
Expand All @@ -192,6 +193,9 @@ struct Daemon {
std::unique_ptr<PowerListener> powerListenerDisableDevices = nullptr;
std::unique_ptr<DeviceManager> deviceManager = nullptr;

std::unique_ptr<PowerListener> powerListenerSleepAfterLidCloseSeconds =
nullptr;

Config::WakeupActions
ToWakeupAction(PowerListener::ExitModernStandbyEvent::Reason reason) {
if (reason == PowerListener::ExitModernStandbyEvent::Reason::Mouse) {
Expand Down Expand Up @@ -224,5 +228,6 @@ struct Daemon {
expected updateSuspendProcesses(const Config &new_config);
expected updateWakeLog(const Config &new_config);
expected updateDisableDevices(const Config &new_config);
expected updateSleepAfterLidCloseSeconds(const Config &new_config);
};
} // namespace goodnight
92 changes: 77 additions & 15 deletions src/goodnight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

#include <algorithm>
#include <array>
#include <chrono>
#include <expected>
#include <filesystem>
#include <format>
#include <iostream>
#include <map>
#include <memory>
#include <mutex>
#include <optional>
#include <print>
Expand Down Expand Up @@ -145,21 +147,23 @@ std::expected<void, std::string> PowerListener::start() {
auto eventRecordId =
std::stoul(extractStr("<EventRecordID>", "</EventRecordID>"));
auto eventId = std::stoul(extractStr("<EventID>", "</EventID>"));
auto eventTime = extractStr("<TimeCreated SystemTime='", "' />");

// parse the event time
std::chrono::system_clock::time_point timePoint;
{
std::tm tm = {};
std::istringstream ss(eventTime);
ss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S.%f");
timePoint =
std::chrono::system_clock::from_time_t(std::mktime(&tm));
}

// time till now
auto timeTillNow = std::chrono::system_clock::now() - timePoint;
if (timeTillNow > std::chrono::seconds(3)) {
auto eventTime = extractStr("<TimeCreated SystemTime='", "'");

time_t time;
std::tm tm = {};
std::istringstream ss(eventTime);
ss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S.%f");
time = std::mktime(&tm);
auto nowTime = std::chrono::system_clock::now();
auto timezone = std::chrono::current_zone();

auto localTime = timezone->to_local(nowTime);
auto timeTillNow =
localTime.time_since_epoch().count() / 1000 / 10000 -
std::chrono::seconds(time).count() -
timezone->get_info(nowTime).offset.count() * 2;

if (timeTillNow > 1000) {
Logger::info("Event {}(EventId-{}) is too old, skip", eventRecordId,
eventId);
continue;
Expand Down Expand Up @@ -255,6 +259,9 @@ std::expected<void, std::string> Daemon::updateConfig(const Config &config) {
if (auto res = updateDisableDevices(config); !res) {
return res;
}
if (auto res = updateSleepAfterLidCloseSeconds(config); !res) {
return res;
}
this->config = config;
return {};
}
Expand Down Expand Up @@ -907,6 +914,61 @@ bool isAdministrator() {
CloseHandle(hToken);
return elevation.TokenIsElevated;
}
Daemon::expected
Daemon::updateSleepAfterLidCloseSeconds(const Config &new_config) {
if (new_config.sleepAfterLidCloseSeconds) {
if (!config.sleepAfterLidCloseSeconds) {
powerListenerSleepAfterLidCloseSeconds =
std::make_unique<PowerListener>();
auto lastLidCloseTime = std::make_shared<int64_t>(0);
powerListenerSleepAfterLidCloseSeconds->addListener([=,
this](auto event) {
if (auto *lidEvent = std::get_if<PowerListener::LidEvent>(&event)) {
if (lidEvent->closed) {
auto now =
std::chrono::system_clock::now().time_since_epoch().count();
*lastLidCloseTime = now;
Logger::info("Lid closed, sleep after {} seconds",
config.sleepAfterLidCloseSeconds);
std::this_thread::sleep_for(
std::chrono::seconds(config.sleepAfterLidCloseSeconds));
if (*lastLidCloseTime != now) {
Logger::info("Lid closed, but opened before sleep, skip sleep");
}
StandbyManager::displayOff();

// emit sleep event
PowerListener::EnterModernStandbyEvent enterEvent;
enterEvent.reason = 15;
enterEvent.BatteryRemainingCapacityOnEnter = 0;
enterEvent.BatteryFullChargeCapacityOnEnter = 0;

auto emitFor = [&](auto &listener) {
if (listener)
listener->emitEvent(enterEvent);
};

emitFor(powerListenerKeepSleep);
emitFor(powerListenerSuspendProcesses);
emitFor(powerListenerDisableDevices);
std::this_thread::sleep_for(std::chrono::seconds(20));

StandbyManager::sleep();
} else {
*lastLidCloseTime = 0;
}
}
});

if (auto res = powerListenerSleepAfterLidCloseSeconds->start(); !res) {
return res;
}
}
} else {
powerListenerSleepAfterLidCloseSeconds = nullptr;
}
return {};
}
} // namespace goodnight

bool goodnight::startMessageLoop() {
Expand Down

0 comments on commit 0278e4a

Please sign in to comment.