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