Files
gnome-shell-extension-freon/extension.js
Marcel Metz d73f450fd4 Made sensors output parsing more robust.
Instead of searching for static literals in the sensors output use the
actual labels of the sensor features. For now all temperature sensors
are returned in the same order as reported by the sensors command. To
hide or relabel a sensor it is now possible to configure the sensors.conf
accordingly. Custom sensors.conf configurations are preserved and don't
lead to a parse error.

Should fix upsteam:
Issue #21
Issue #22
Issue #23
Issue #27
Issue #28
Issue #29
Issue #30
Issue #31
Issue #33
Issue #34
Issue #35
Issue #36
Issue #37
Issue #39
2012-12-25 12:52:02 +01:00

266 lines
9.1 KiB
JavaScript

const St = imports.gi.St;
const Lang = imports.lang;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Main = imports.ui.main;
const GLib = imports.gi.GLib;
const Util = imports.misc.util;
const Mainloop = imports.mainloop;
function CpuTemperature() {
this._init.apply(this, arguments);
}
CpuTemperature.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
_init: function(){
PanelMenu.SystemStatusButton.prototype._init.call(this, 'temperature');
this.statusLabel = new St.Label({
text: "--",
style_class: "temperature-label"
});
// destroy all previously created children, and add our statusLabel
this.actor.get_children().forEach(function(c) {
c.destroy()
});
this.actor.add_actor(this.statusLabel);
this.sensorsPath = this._detectSensors();
this.command=["xdg-open", "http://github.com/xtranophilist/gnome-shell-extension-cpu-temperature/issues/"];
if(this.sensorsPath){
this.title='Error';
this.content='Run sensors-detect as root. If it doesn\'t help, click here to report with your sensors output!';
}
else{
this.title='Warning';
this.content='Please install lm_sensors. If it doesn\'t help, click here to report with your sensors output!';
}
this._update_temp();
//update every 15 seconds
event = GLib.timeout_add_seconds(0, 15, Lang.bind(this, function () {
this._update_temp();
return true;
}));
},
_detectSensors: function(){
//detect if sensors is installed
let ret = GLib.spawn_command_line_sync("which sensors");
if ( (ret[0]) && (ret[3] == 0) ) {//if yes
return ret[1].toString().split("\n", 1)[0];//find the path of the sensors
}
return null;
},
_update_temp: function() {
let items = new Array();
let tempInfo=null;
if (this.sensorsPath){
let sensors_output = GLib.spawn_command_line_sync(this.sensorsPath);//get the output of the sensors command
if(sensors_output[0]) tempInfo = this._findTemperatureFromSensorsOutput(sensors_output[1].toString());//get temperature from sensors
if (tempInfo){
var s=0, n=0;//sum and count
for (let sensor in tempInfo){
s+=tempInfo[sensor]['temp'];
n++;
items.push(tempInfo[sensor]['label']+': '+this._formatTemp(tempInfo[sensor]['temp']));
}
if (n!=0){//if temperature is detected
this.title=this._formatTemp(s/n);//set title as average
}
}
}
//if we don't have the temperature yet, use some known files
if(!tempInfo){
tempInfo = this._findTemperatureFromFiles();
if(tempInfo.temp){
this.title=this._formatTemp(tempInfo.temp);
items.push('Current Temperature : '+this._formatTemp(tempInfo.temp));
if (tempInfo.crit)
items.push('Critical Temperature : '+this._formatTemp(tempInfo.crit));
}
}
this.statusLabel.set_text(this.title);
this.menu.box.get_children().forEach(function(c) {
c.destroy()
});
let section = new PopupMenu.PopupMenuSection("Temperature");
if (items.length>0){
let item;
for each (let itemText in items){
item = new PopupMenu.PopupMenuItem("");
item.addActor(new St.Label({
text:itemText,
style_class: "sm-label"
}));
section.addMenuItem(item);
}
}else{
let command=this.command;
let item = new PopupMenu.PopupMenuItem("");
item.addActor(new St.Label({
text:this.content,
style_class: "sm-label"
}));
item.connect('activate',function() {
Util.spawn(command);
});
section.addMenuItem(item);
}
this.menu.addMenuItem(section);
},
_findTemperatureFromFiles: function(){
let info = new Array();
let temp_files = [
//hwmon for new 2.6.39, 3.x linux kernels
'/sys/class/hwmon/hwmon0/temp1_input',
'/sys/devices/platform/coretemp.0/temp1_input',
'/sys/bus/acpi/devices/LNXTHERM\:00/thermal_zone/temp',
'/sys/devices/virtual/thermal/thermal_zone0/temp',
'/sys/bus/acpi/drivers/ATK0110/ATK0110:00/hwmon/hwmon0/temp1_input',
//old kernels with proc fs
'/proc/acpi/thermal_zone/THM0/temperature',
'/proc/acpi/thermal_zone/THRM/temperature',
'/proc/acpi/thermal_zone/THR0/temperature',
'/proc/acpi/thermal_zone/TZ0/temperature',
//Debian Sid/Experimental on AMD-64
'/sys/class/hwmon/hwmon0/device/temp1_input'];
for each (let file in temp_files){
if(GLib.file_test(file,1<<4)){
//let f = Gio.file_new_for_path(file);
//f.read_async(0, null, function(source, result) {debug(source.read_finish(result).read())});
let temperature = GLib.file_get_contents(file);
if(temperature[0]) {
info['temp']= parseInt(temperature[1])/1000;
}
}
break;
}
let crit_files = ['/sys/devices/platform/coretemp.0/temp1_crit',
'/sys/bus/acpi/drivers/ATK0110/ATK0110:00/hwmon/hwmon0/temp1_crit',
//hwmon for new 2.6.39, 3.0 linux kernels
'/sys/class/hwmon/hwmon0/temp1_crit',
//Debian Sid/Experimental on AMD-64
'/sys/class/hwmon/hwmon0/device/temp1_crit'];
for each (let file in crit_files){
if(GLib.file_test(file,1<<4)){
let temperature = GLib.file_get_contents(file);
if(temperature[0]) {
info['crit']= parseInt(temperature[1])/1000;
}
}
}
return info;
},
_findTemperatureFromSensorsOutput: function(txt){
let sensors_output=txt.split("\n");
let feature_label=undefined;
let feature_value=undefined;
let s= new Array();
let n=0,c=0;
let f;
//iterate through each lines
for(let i = 0; i < sensors_output.length; i++) {
// ignore chipset driver name and 'Adapter:' line for now
i+=2;
// get every feature of the chip
while(sensors_output[i]){
// if it is not a continutation of a feature line
if(sensors_output[i].indexOf(' ') != 0){
let feature = this._parseSensorsTemperatureLine(feature_label, feature_value);
if (feature) {
s[n++] = feature;
feature = undefined;
}
[feature_label, feature_value]=sensors_output[i].split(':');
}
else{
feature_value += sensors_output[i];
}
i++;
}
}
let feature = this._parseSensorsTemperatureLine(feature_label, feature_value);
if (feature) {
s[n++] = feature;
feature = undefined;
}
return s;
},
_parseSensorsTemperatureLine: function(label, value) {
let s = undefined;
if(label != undefined && value != undefined) {
let curValue = value.trim().split(' ')[0];
// does the current value look like a temperature unit (°C)?
if(curValue.indexOf("C", curValue.length - "C".length) !== -1){
s = new Array();
s['label'] = label.trim();
s['temp'] = parseFloat(curValue.split(' ')[0]);
s['high'] = this._getHigh(value);
s['crit'] = this._getCrit(value);
s['hyst'] = this._getHyst(value);
}
}
return s;
},
_getHigh: function(t){
let r;
return (r=/high=\+(\d{1,3}.\d)/.exec(t))?parseFloat(r[1]):null;
},
_getCrit: function(t){
let r;
return (r=/crit=\+(\d{1,3}.\d)/.exec(t))?parseFloat(r[1]):null;
},
_getHyst: function(t){
let r;
return (r=/hyst=\+(\d{1,3}.\d)/.exec(t))?parseFloat(r[1]):null;
},
_toFahrenheit: function(c){
return ((9/5)*c+32).toFixed(1);
},
_formatTemp: function(t) {
//uncomment the next line to display temperature in Fahrenheit
//return this._toFahrenheit(t).toString()+"\u1d3cF";
return (Math.round(t*10)/10).toFixed(1).toString()+"\u1d3cC";
}
}
//for debugging
function debug(a){
global.log(a);
Util.spawn(['echo',a]);
}
function init() {
//do nothing
}
let indicator;
let event=null;
function enable() {
indicator = new CpuTemperature();
Main.panel.addToStatusArea('temperature', indicator);
}
function disable() {
indicator.destroy();
Mainloop.source_remove(event);
indicator = null;
}