Skip to content

Commit

Permalink
Display SlimeVR Tracker Battery Life (#41)
Browse files Browse the repository at this point in the history
  • Loading branch information
NWBx01 committed Jun 5, 2023
1 parent 7097018 commit ce80726
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 7 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -11,12 +11,14 @@ compile_commands.json
CTestTestfile.cmake
_deps
CMakeUserPresets.json
vcpkg_installed/

### CMake Patch ###
# External projects
*-prefix/

### vscode ###
.vs
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
Expand All @@ -26,3 +28,4 @@ CMakeUserPresets.json

# Project-specific
build/*
out/
2 changes: 2 additions & 0 deletions src/IVRDevice.hpp
Expand Up @@ -63,6 +63,8 @@ namespace SlimeVRDriver {
virtual void PositionMessage(messages::Position& position) = 0;
virtual void StatusMessage(messages::TrackerStatus& status) = 0;

virtual void BatteryMessage(messages::Battery& battery) = 0;

~IVRDevice() = default;
};
};
40 changes: 33 additions & 7 deletions src/TrackerDevice.cpp
Expand Up @@ -79,6 +79,32 @@ void SlimeVRDriver::TrackerDevice::PositionMessage(messages::Position &position)
this->last_pose_ = pose;
}

void SlimeVRDriver::TrackerDevice::BatteryMessage(messages::Battery &battery)
{
if (this->device_index_ == vr::k_unTrackedDeviceIndexInvalid)
return;

// Get the properties handle
auto props = GetDriver()->GetProperties()->TrackedDeviceToPropertyContainer(this->device_index_);

vr::ETrackedPropertyError err;

// Set that the tracker reports battery level in case it has not already been set to true
// It's a given that the tracker supports reporting battery life because otherwise a BatteryMessage would not be received
if (vr::VRProperties()->GetBoolProperty(props, vr::Prop_DeviceProvidesBatteryStatus_Bool, &err) != true) {
vr::VRProperties()->SetBoolProperty(props, vr::Prop_DeviceProvidesBatteryStatus_Bool, true);
}

if (battery.is_charging()) {
vr::VRProperties()->SetBoolProperty(props, vr::Prop_DeviceIsCharging_Bool, true);
} else {
vr::VRProperties()->SetBoolProperty(props, vr::Prop_DeviceIsCharging_Bool, false);
}

// Set the battery Level; 0 = 0%, 1 = 100%
vr::VRProperties()->SetFloatProperty(props, vr::Prop_DeviceBatteryPercentage_Float, battery.battery_level());
}

void SlimeVRDriver::TrackerDevice::StatusMessage(messages::TrackerStatus &status)
{
auto pose = this->last_pose_;
Expand Down Expand Up @@ -141,15 +167,15 @@ vr::EVRInitError SlimeVRDriver::TrackerDevice::Activate(uint32_t unObjectId)
GetDriver()->GetProperties()->SetStringProperty(props, vr::Prop_RenderModelName_String, "{htc}/rendermodels/vr_tracker_vive_1_0");

// Set the icon
GetDriver()->GetProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceReady_String, "{slimevr}/icons/tracker_status_ready.b4bfb144.png");
GetDriver()->GetProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceReady_String, "{slimevr}/icons/tracker_status_ready.png");

GetDriver()->GetProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceOff_String, "{slimevr}/icons/tracker_status_off.png");
GetDriver()->GetProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceSearching_String, "{slimevr}/icons/tracker_status_ready.b4bfb144.png");
GetDriver()->GetProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceSearchingAlert_String, "{slimevr}/icons/tracker_status_ready_alert.b4bfb144.png");
GetDriver()->GetProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceReadyAlert_String, "{slimevr}/icons/tracker_status_ready_alert.b4bfb144.png");
GetDriver()->GetProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceNotReady_String, "{slimevr}/icons/tracker_status_off.png");
GetDriver()->GetProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceStandby_String, "{slimevr}/icons/tracker_status_standby.b4bfb144.png");
GetDriver()->GetProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceAlertLow_String, "{slimevr}/icons/tracker_status_ready_low.b4bfb144.png");
GetDriver()->GetProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceSearching_String, "{slimevr}/icons/tracker_status_ready.png");
GetDriver()->GetProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceSearchingAlert_String, "{slimevr}/icons/tracker_status_ready_alert.png");
GetDriver()->GetProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceReadyAlert_String, "{slimevr}/icons/tracker_status_ready_alert.png");
GetDriver()->GetProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceNotReady_String, "{slimevr}/icons/tracker_status_error.png");
GetDriver()->GetProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceStandby_String, "{slimevr}/icons/tracker_status_standby.png");
GetDriver()->GetProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceAlertLow_String, "{slimevr}/icons/tracker_status_ready_low.png");

// Automatically select vive tracker roles and set hints for games that need it (Beat Saber avatar mod, for example)
auto roleHint = getViveRoleHint(trackerRole);
Expand Down
2 changes: 2 additions & 0 deletions src/TrackerDevice.hpp
Expand Up @@ -22,6 +22,8 @@ namespace SlimeVRDriver {
TrackerDevice(std::string serial, int deviceId, TrackerRole trackerRole);
~TrackerDevice() = default;

virtual void BatteryMessage(messages::Battery &battery);

// Inherited via IVRDevice
virtual std::string GetSerial() override;
virtual void Update() override;
Expand Down
16 changes: 16 additions & 0 deletions src/VRDriver.cpp
Expand Up @@ -84,6 +84,12 @@ void SlimeVRDriver::VRDriver::RunFrame()
if (device != this->devices_by_id.end()) {
device->second->StatusMessage(status);
}
} else if (message->has_battery()) {
messages::Battery bat = message->battery();
auto device = this->devices_by_id.find(bat.tracker_id());
if (device != this->devices_by_id.end()) {
device->second->BatteryMessage(bat);
}
}
}

Expand Down Expand Up @@ -167,6 +173,16 @@ void SlimeVRDriver::VRDriver::RunFrame()
hmdPosition->set_qw((float) q.w);

sendBridgeMessage(*message, *this);

vr::ETrackedPropertyError err;
if (vr::VRProperties()->GetBoolProperty(vr::VRProperties()->TrackedDeviceToPropertyContainer(0), vr::Prop_DeviceProvidesBatteryStatus_Bool, &err) == true) {
messages::Battery* hmdBattery = google::protobuf::Arena::CreateMessage<messages::Battery>(&arena);
message->set_allocated_battery(hmdBattery);
hmdBattery->set_tracker_id(0);
hmdBattery->set_battery_level(vr::VRProperties()->GetFloatProperty(vr::VRProperties()->TrackedDeviceToPropertyContainer(0), vr::Prop_DeviceBatteryPercentage_Float, &err) * 100);
hmdBattery->set_is_charging(vr::VRProperties()->GetBoolProperty(vr::VRProperties()->TrackedDeviceToPropertyContainer(0), vr::Prop_DeviceIsCharging_Bool, &err));
sendBridgeMessage(*message, *this);
}
} else {
// If bridge not connected, assume we need to resend hmd tracker add message
sentHmdAddMessage = false;
Expand Down
7 changes: 7 additions & 0 deletions src/bridge/ProtobufMessages.proto
Expand Up @@ -103,11 +103,18 @@ message TrackerStatus {
optional Confidence confidence = 4;
}

message Battery {
int32 tracker_id = 1;
float battery_level = 2;
bool is_charging = 3;
}

message ProtobufMessage {
oneof message {
Position position = 1;
UserAction user_action = 2;
TrackerAdded tracker_added = 3;
TrackerStatus tracker_status = 4;
Battery battery = 5;
}
}

0 comments on commit ce80726

Please sign in to comment.