Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reading fan tables from a configuration file #44

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
11 changes: 10 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach",
"port": 9229,
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "pwa-node"
},
{
"name": "Debug Main Process",
"type": "node",
Expand All @@ -10,7 +19,7 @@
"windows": {
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd"
},
"runtimeArgs": ["./dist/tuxedo-control-center"],
"runtimeArgs": ["./dist/tuxedo-control-center", "--debug"],

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this just for executions in VSCode or for release as well?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--debug is only passed when you run the Debug Main Process target from vscode. It would possible to pass to a release build as well. I'm not sure how to avoid that though.

It opens the dev tools / inspector immediately as the application launches which I found useful, especially for placing breakpoints and stepping through things.

"program": "${workspaceRoot}/src/e-app/main.ts",
"outFiles": [
"${workspaceRoot}/dist/tuxedo-control-center/e-app/e-app/main.js"
Expand Down
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,21 @@ tuxedo-control-center

sudo apt install -y git gcc g++ make nodejs
```
2. Clone & install libraries

2. Install `tuxedo-cc-wmi` (can be obtained from the respositories [here](https://www.tuxedocomputers.com/en/Infos/Help-and-Support/Instructions/Add-TUXEDO-Computers-software-package-sources.tuxedo#)).
This package provides a driver at `/dev/tuxedo_cc_wmi`. The control center can run without this but will not be functional.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a dependency list to add it to?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand the question. I just thought I would mention that if you are building the control center from source then you need to install the driver separately. Previously there was no mention of that in the README.


3. Clone & install libraries
```
git clone https://github.com/tuxedocomputers/tuxedo-control-center.git`
git clone https://github.com/tuxedocomputers/tuxedo-control-center.git

cd tuxedo-control-center

npm install
```
**Note:** Do ***not*** continue with `npm audit fix`. Known to cause various issues.

3. Install service file that points to development build path (or use installed service from packaged version)
4. Install service file that points to development build path (or use installed service from packaged version)

Manual instructions:
1. Copy `tccd.service` and `tccd-sleep.service` (from src/dist-data) to `/etc/systemd/system/`
Expand All @@ -58,6 +62,7 @@ tuxedo-control-center
| build | Build all apps service/electron/angular |
| start | Normal start of electron app after build |
| start-watch | Start GUI with automatic reload on changes to angular directory |
| start-service | Start the tccd daemon |
| test-common | Test common files (jasmine) |
| gen-lang | Generate base for translation (`ng-app/assets/locale/lang.xlf`) |
| pack-prod -- all \| deb \| rpm | Build and package for chosen target(s) |
Expand All @@ -66,7 +71,10 @@ tuxedo-control-center
| inc-version-major | Major version increase (updates package.json files) |

### Debugging
Debugging of electron main and render process is configured for vscode in .vscode/launch.json
Debugging of electron main and render process is configured for vscode in `.vscode/launch.json`.
Note that the application must be rebuilt each time a change is made. Usually `npm run build-ng` is sufficient.

To debug the service, run `npm run debug-service` the launch the `Attach` target in `.vscode/launch.json`.

## Screenshots
### English
Expand Down
4 changes: 4 additions & 0 deletions build-src/after_install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ cp ${DIST_DATA}/tuxedo-control-center-tray.desktop /etc/skel/.config/autostart/t
cp ${DIST_DATA}/de.tuxedocomputers.tcc.policy /usr/share/polkit-1/actions/de.tuxedocomputers.tcc.policy || true
cp ${DIST_DATA}/com.tuxedocomputers.tccd.conf /usr/share/dbus-1/system.d/com.tuxedocomputers.tccd.conf || true

# Copy settings
mkdir -p /etc/tcc
cp ${DIST_DATA}/fantables.json /etc/tcc/fantables || true

# Copy and enable services
cp ${DIST_DATA}/tccd.service /etc/systemd/system/tccd.service || true
cp ${DIST_DATA}/tccd-sleep.service /etc/systemd/system/tccd-sleep.service || true
Expand Down
22 changes: 0 additions & 22 deletions build-src/fan_table_format.ts

This file was deleted.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
"build-electron": "tsc -p ./src/e-app",
"build-service": "tsc -p ./src/service-app && cp ./src/package.json ./dist/tuxedo-control-center/service-app/package.json && run-s bundle-service",
"bundle-service": "pkg --target node10-linux-x64 --output ./dist/tuxedo-control-center/data/service/tccd ./dist/tuxedo-control-center/service-app/package.json",
"start-service": "sudo NODE_PATH=\"./dist/tuxedo-control-center/data/service:${NODE_PATH}\" node ./dist/tuxedo-control-center/service-app/service-app/main.js --start",
"debug-service": "sudo NODE_PATH=\"./dist/tuxedo-control-center/data/service:${NODE_PATH}\" node --inspect-brk ./dist/tuxedo-control-center/service-app/service-app/main.js --start",
"build-native": "node-gyp configure && node-gyp rebuild",
"copy-files": "run-s copy-package-json copy-dist-files copy-native",
"copy-native": "mkdir -p ./dist/tuxedo-control-center/service-app/native-lib && cp ./build/Release/TuxedoWMIAPI.node ./dist/tuxedo-control-center/data/service",
Expand Down
75 changes: 69 additions & 6 deletions src/common/classes/ConfigHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ import * as path from 'path';
import { ITccSettings, defaultSettings } from '../models/TccSettings';
import { ITccProfile, defaultProfiles, defaultCustomProfile, defaultCustomProfileXP1508UHD } from '../models/TccProfile';
import { ITccAutosave, defaultAutosave } from '../models/TccAutosave';
import { ITccFanProfile, defaultFanProfiles } from '../models/TccFanTable';
import { ITccFanProfile } from '../models/TccFanTable';

export class ConfigHandler {
public settingsFileMod: number;
public profileFileMod: number;
public autosaveFileMod: number;
public fantablesFileMod: number;

private fanTables: ITccFanProfile[];

private loadedCustomProfiles: ITccProfile[];
private loadedSettings: ITccSettings;

Expand All @@ -38,6 +40,8 @@ export class ConfigHandler {
this.profileFileMod = 0o644;
this.autosaveFileMod = 0o644;
this.fantablesFileMod = 0o644;

this.fanTables = this.readFanTables();
}

get pathSettings() { return this._pathSettings; }
Expand Down Expand Up @@ -73,12 +77,67 @@ export class ConfigHandler {
this.writeConfig<ITccAutosave>(autosave, filePath, { mode: this.autosaveFileMod });
}

private createFanProfile(name: string, rows): ITccFanProfile {
return {
name: name,
tableCPU: rows.map(row => ({"temp": row[0], "speed": row[1]})),
tableGPU: rows.map(row => ({"temp": row[0], "speed": row[2]}))
}
}

readFanTables(filePath: string = this.pathFanTables): ITccFanProfile[] {
return this.readConfig<ITccFanProfile[]>(filePath);
const lines = fs.readFileSync(filePath, 'utf-8').split('\n');
let currentProfile = null;
let currentRows = [];
let profiles = [];
const blankLineRegex = /^\s*(#.*)?$/
const sectionLineRegex = /^\s*\[([^\]]+)\]\s*(#.*)?$/
const rowLineRegex = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(#.*)?$/
let match
for(const [i, line] of lines.entries()) {
if(blankLineRegex.test(line)) {
continue;
} else if((match = rowLineRegex.exec(line)) !== null) {
if(currentProfile === null) {
throw Error(`syntax error on line ${i+1} reading fan profiles from "${filePath}"`);
}
currentRows.push([parseInt(match[1]), parseInt(match[2]), parseInt(match[3])]);
} else if((match = sectionLineRegex.exec(line)) !== null) {
if(currentProfile !== null) {
profiles.push(this.createFanProfile(currentProfile, currentRows));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if currentRows is null?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currentRows should never be null but could be an empty list.
are you saying that empty profiles should be discarded? For example

[MyProfile]

[MyOtherProfile]
0,0,0

only MyOtherProfile should be created?

currentRows = [];
}
currentProfile = match[1];
} else {
throw Error(`syntax error on line ${i+1} reading fan profiles from "${filePath}"`);
}
}
if(currentProfile !== null) {
profiles.push(this.createFanProfile(currentProfile, currentRows));
}
return profiles;
}

writeFanTables(fanTables: ITccFanProfile[], filePath: string = this.pathFanTables) {
this.writeConfig<ITccFanProfile[]>(fanTables, filePath, { mode: this.fantablesFileMod });
let lines = [];
for(var profile of fanTables) {
lines.push(`[${profile.name}]`)
if(profile.tableCPU.length !== profile.tableGPU.length) {
throw Error("invalid fan profile. CPU and GPU table length mismatch");
}
for(var i = 0; i < profile.tableCPU.length; i++) {
let cpu_entry = profile.tableCPU[i];
let gpu_entry = profile.tableGPU[i];
if(cpu_entry.temp !== gpu_entry.temp) {
throw Error("invalid fan profile. Temperatures don't match");
}
lines.push(`${cpu_entry.temp},${cpu_entry.speed},${gpu_entry.speed}`)
}
lines.push('');
}
this.fanTables = fanTables;
let data = lines.join('\n');
this.writeFile(data, filePath, { mode: this.fantablesFileMod });
}

public readConfig<T>(filename: string): T {
Expand All @@ -93,7 +152,10 @@ export class ConfigHandler {
}

public writeConfig<T>(config: T, filePath: string, writeFileOptions): void {
const fileData = JSON.stringify(config);
this.writeFile(JSON.stringify(config), filePath, writeFileOptions);
}

private writeFile(fileData: string, filePath: string, writeFileOptions): void {
try {
if (!fs.existsSync(path.dirname(filePath))) {
fs.mkdirSync(path.dirname(filePath), { mode: 0o755, recursive: true });
Expand Down Expand Up @@ -150,7 +212,8 @@ export class ConfigHandler {
}
}

public getDefaultFanProfiles(): ITccFanProfile[] {
return this.copyConfig<ITccFanProfile[]>(defaultFanProfiles);
public getFanProfiles(): ITccFanProfile[] {
return this.copyConfig<ITccFanProfile[]>(this.fanTables);
}

}
Loading