Yippe i was not lazy
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
bin/*
|
||||
25526
lib/nlohmann/json.hpp
Normal file
25526
lib/nlohmann/json.hpp
Normal file
File diff suppressed because it is too large
Load Diff
278
status.cpp
Normal file
278
status.cpp
Normal file
@@ -0,0 +1,278 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <filesystem>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <poll.h>
|
||||
#include <nlohmann/json.hpp> // include with: sudo apt install nlohmann-json3-dev
|
||||
|
||||
using json = nlohmann::json;
|
||||
using namespace std;
|
||||
|
||||
// Utility to execute shell commands and capture output
|
||||
string execCmd(const string &cmd){
|
||||
array<char,128> buffer;
|
||||
string result;
|
||||
FILE* pipe=popen(cmd.c_str(),"r");
|
||||
if(!pipe)return "";
|
||||
while(fgets(buffer.data(),buffer.size(),pipe)!=nullptr)result+=buffer.data();
|
||||
pclose(pipe);
|
||||
if(!result.empty()&&result.back()=='\n')result.pop_back();
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----- Module functions -----
|
||||
string getBattery(){
|
||||
string percent=execCmd("cat /sys/class/power_supply/BAT*/capacity 2>/dev/null");
|
||||
string status=execCmd("cat /sys/class/power_supply/BAT*/status 2>/dev/null");
|
||||
string energyNow=execCmd("cat /sys/class/power_supply/BAT*/energy_now 2>/dev/null");
|
||||
string powerNow=execCmd("cat /sys/class/power_supply/BAT*/power_now 2>/dev/null");
|
||||
string energyFull=execCmd("cat /sys/class/power_supply/BAT*/energy_full 2>/dev/null");
|
||||
|
||||
int val=percent.empty()?0:stoi(percent);
|
||||
string icon;
|
||||
if(status=="Charging")icon="";
|
||||
else if(val>90)icon="";
|
||||
else if(val>70)icon="";
|
||||
else if(val>50)icon="";
|
||||
else if(val>30)icon="";
|
||||
else icon="";
|
||||
|
||||
string timeLeft;
|
||||
if(!energyNow.empty()&&!powerNow.empty()){
|
||||
double eNow=stod(energyNow);
|
||||
double pNow=stod(powerNow);
|
||||
double eFull=energyFull.empty()?eNow:eNow+1000;
|
||||
if(pNow>0){
|
||||
double hours=0;
|
||||
if(status=="Charging")hours=(eFull-eNow)/pNow;
|
||||
else if(status=="Discharging")hours=eNow/pNow;
|
||||
int h=(int)hours;
|
||||
int m=(int)((hours-h)*60);
|
||||
stringstream tss;
|
||||
tss<<" ("<<h<<"h "<<m<<"m"<<(status=="Charging"?" until full":" left")<<")";
|
||||
timeLeft=tss.str();
|
||||
}
|
||||
}
|
||||
|
||||
return " "+icon+" "+percent+"% "+status+timeLeft+" ";
|
||||
}
|
||||
|
||||
string getPowerMode(){
|
||||
string mode=execCmd("powerprofilesctl get 2>/dev/null");
|
||||
if(mode=="performance")return " Performance ";
|
||||
if(mode=="balanced")return " Balanced ";
|
||||
if(mode=="power-saver")return " Power Saver ";
|
||||
return " Unknown ";
|
||||
}
|
||||
|
||||
string getSound(){
|
||||
string vol=execCmd("pamixer --get-volume 2>/dev/null");
|
||||
string mute=execCmd("pamixer --get-mute 2>/dev/null");
|
||||
string icon=(mute=="true")?" ":" ";
|
||||
return icon+" "+(vol.empty()?"0":vol)+"% ";
|
||||
}
|
||||
|
||||
string getMic(){
|
||||
string vol=execCmd("pamixer --default-source --get-volume 2>/dev/null");
|
||||
string mute=execCmd("pamixer --default-source --get-mute 2>/dev/null");
|
||||
string icon=(mute=="true")?" ":" ";
|
||||
return icon+" "+(vol.empty()?"0":vol)+"% ";
|
||||
}
|
||||
|
||||
string getDunst(){
|
||||
string status=execCmd("dunstctl is-paused 2>/dev/null");
|
||||
return (status=="true")?" Off ":" On ";
|
||||
}
|
||||
|
||||
string getBrightness(){
|
||||
namespace fs = std::filesystem;
|
||||
string path;
|
||||
for(const auto& dir: fs::directory_iterator("/sys/class/backlight/")){
|
||||
path = dir.path();
|
||||
break;
|
||||
}
|
||||
if(path.empty()) return " 🌞 N/A ";
|
||||
|
||||
string cur = execCmd("cat "+path+"/brightness");
|
||||
string max = execCmd("cat "+path+"/max_brightness");
|
||||
|
||||
if(cur.empty() || max.empty()) return " 🌞 N/A ";
|
||||
|
||||
double perc = stod(cur) / stod(max) * 100.0;
|
||||
|
||||
string icon = (perc > 75) ? "" : (perc > 50) ? "" : (perc > 25) ? "" : "";
|
||||
|
||||
stringstream ss;
|
||||
ss << " " << icon << " " << fixed << setprecision(0) << perc << "% ";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
double getCpuUsage() {
|
||||
static long long lastTotal=0, lastIdle=0;
|
||||
|
||||
std::ifstream file("/proc/stat");
|
||||
std::string line;
|
||||
getline(file,line); // first line: "cpu …"
|
||||
std::istringstream ss(line);
|
||||
std::string cpu;
|
||||
long long user, nice, system, idle, iowait, irq, softirq, steal;
|
||||
ss >> cpu >> user >> nice >> system >> idle >> iowait >> irq >> softirq >> steal;
|
||||
long long idleTime = idle + iowait;
|
||||
long long total = user+nice+system+idle+iowait+irq+softirq+steal;
|
||||
|
||||
long long diffIdle = idleTime - lastIdle;
|
||||
long long diffTotal = total - lastTotal;
|
||||
|
||||
lastIdle = idleTime;
|
||||
lastTotal = total;
|
||||
|
||||
if(diffTotal==0)return 0.0;
|
||||
return (double)(diffTotal - diffIdle) / diffTotal * 100.0;
|
||||
}
|
||||
|
||||
string getCPU(){
|
||||
string temp=execCmd("sensors | grep 'Package id 0:' | awk '{print $4}' | tr -d '+'");
|
||||
double usage = getCpuUsage(); //execCmd("mpstat 1 1 | awk '/all/ {print 100-$12}'");
|
||||
stringstream ss;
|
||||
ss<<" "<<fixed<<setprecision(1)<<usage<<"% "<<(temp.empty()?"N/A":temp)<<" ";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
string getRAM(){
|
||||
ifstream meminfo("/proc/meminfo");
|
||||
long total=0,free=0,avail=0;
|
||||
string key;
|
||||
long val;
|
||||
string unit;
|
||||
while(meminfo>>key>>val>>unit){
|
||||
if(key=="MemTotal:")total=val;
|
||||
if(key=="MemAvailable:")avail=val;
|
||||
}
|
||||
long used=total-avail;
|
||||
double usedGB=used/1024.0/1024.0;
|
||||
double totalGB=total/1024.0/1024.0;
|
||||
string icon=" ";
|
||||
stringstream ss;
|
||||
ss<<icon<<" "<<fixed<<setprecision(2)<<usedGB<<"/"<<setprecision(1)<<totalGB<<"GiB ";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
string getNetwork(){
|
||||
string wifi=execCmd("iwgetid -r 2>/dev/null");
|
||||
string eth=execCmd("ip link show | grep 'state UP' | grep eth | awk '{print $2}' | tr -d ':'");
|
||||
|
||||
string ip=execCmd("hostname -I | awk '{print $1}'");
|
||||
string out;
|
||||
|
||||
if(!wifi.empty()){
|
||||
string strength=execCmd("awk 'NR==3 {print int($3)}' /proc/net/wireless 2>/dev/null");
|
||||
out+=" "+wifi;
|
||||
if(!strength.empty())out+=" ("+strength+"%)";
|
||||
if(!ip.empty())out+=" "+ip;
|
||||
}else out+=" Wi-Fi Off";
|
||||
|
||||
if(!eth.empty()){
|
||||
if(!out.empty())out+=" | ";
|
||||
out+=" "+eth;
|
||||
if(!ip.empty())out+=" "+ip;
|
||||
}else{
|
||||
if(out.find("Wi-Fi Off")==string::npos){
|
||||
// only show 'no eth' if not both off
|
||||
out+=" | No ETH";
|
||||
}
|
||||
}
|
||||
|
||||
if(out.find("")==string::npos&&out.find("")==string::npos)
|
||||
out=" Offline";
|
||||
|
||||
return " "+out+" ";
|
||||
}
|
||||
|
||||
|
||||
string getStorage(){
|
||||
string df=execCmd("df -h /home/ | awk 'NR==2 {print $3\"/\"$2}'");
|
||||
return " "+df+" ";
|
||||
}
|
||||
|
||||
string getDateTime(){
|
||||
time_t t=time(nullptr);
|
||||
tm* now=localtime(&t);
|
||||
stringstream ss;
|
||||
const char* days[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
|
||||
ss<<" "<<days[now->tm_wday]<<" "<<put_time(now,"%d %b %Y")<<" "<<put_time(now,"%H:%M:%S ");
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// ----- JSON Output -----
|
||||
json makeBlock(const string&id,const string&text,const string&color,const string&bg){
|
||||
json j;
|
||||
j["name"]=id;
|
||||
j["full_text"]=text;
|
||||
j["color"]=color;
|
||||
j["background"]=bg;
|
||||
j["separator"]=false;
|
||||
j["separator_block_width"]=0;
|
||||
return j;
|
||||
}
|
||||
|
||||
// ----- Main -----
|
||||
int main(){
|
||||
ios::sync_with_stdio(false);
|
||||
cout<<"{\"version\":1,\"click_events\":true}"<<endl; // i3bar header
|
||||
cout<<"["<<endl; // Start infinite array
|
||||
|
||||
bool first=true;
|
||||
|
||||
while(true){
|
||||
vector<json> blocks; // TEXT | BACK
|
||||
blocks.push_back(makeBlock("battery",getBattery(),"#cdd6f4","#000000")); //313244
|
||||
blocks.push_back(makeBlock("power",getPowerMode(),"#f9e2af","#000000")); //45475a
|
||||
blocks.push_back(makeBlock("sound",getSound(),"#a6e3a1","#000000")); //313244
|
||||
// blocks.push_back(makeBlock("mic",getMic(),"#f38ba8","#000000")); //313244
|
||||
// blocks.push_back(makeBlock("dunst",getDunst(),"#b4befe","#313244"));
|
||||
blocks.push_back(makeBlock("brightness", getBrightness(), "#f38ba8", "#000000")); //313244
|
||||
blocks.push_back(makeBlock("cpu",getCPU(),"#89b4fa","#000000")); //45475a
|
||||
blocks.push_back(makeBlock("ram",getRAM(),"#fab387","#000000")); //313244
|
||||
blocks.push_back(makeBlock("net",getNetwork(),"#94e2d5","#000000")); //45475a
|
||||
blocks.push_back(makeBlock("storage",getStorage(),"#f5c2e7","#000000")); //313244
|
||||
blocks.push_back(makeBlock("clock",getDateTime(),"#f2cdcd","#000000")); //45475a
|
||||
|
||||
if(!first)cout<<","<<endl;
|
||||
first=false;
|
||||
cout<<blocks<<endl;
|
||||
cout.flush();
|
||||
|
||||
// ---- Handle click events properly ----
|
||||
struct pollfd fds[1];
|
||||
fds[0].fd=STDIN_FILENO;
|
||||
fds[0].events=POLLIN;
|
||||
int ret=poll(fds,1,50);
|
||||
if(ret>0 && (fds[0].revents&POLLIN)){
|
||||
string line;
|
||||
if(getline(cin,line)){
|
||||
try{
|
||||
json click=json::parse(line);
|
||||
string name=click.value("name","");
|
||||
if(name=="power")system("~/Projects/C+++/statusBar/scripts/toggle_performance.sh &");
|
||||
// else if(name=="dunst")system("~/Projects/C+++/statusBar/scripts/toggle_dunst.sh &");
|
||||
else if(name=="mic")system("~/Projects/C+++/statusBar/scripts/toggle_mic.sh &");
|
||||
else if(name=="sound")system("~/Projects/C+++/statusBar/scripts/toggle_sound.sh &");
|
||||
else if(name=="net")system("alacritty -e nmtui &");
|
||||
}catch(...){
|
||||
// ignore malformed input
|
||||
}
|
||||
}
|
||||
}
|
||||
this_thread::sleep_for(chrono::milliseconds(500));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user