This is the most useful thing you can send, and it needs no code at all.
MateFan knows one machine out of the box. Every other Huawei laptop measures itself on first start, which takes two minutes and is loud. If you send in the result, the next person with your model never has to sit through it.
- Start MateFan. If it does not know your machine, the wizard runs on its own. If it does, use Measure this machine again … in the main window.
- Let the measurement finish.
- Press Copy as JSON on the result page.
- Open an issue with the Device profile template and paste it in.
No pull request needed. An issue is enough — the numbers go into
src/MateFan.Core/profiles.json from there.
ProfileCatalogTests validates every catalogue entry, so an impossible profile fails CI rather
than reaching a user. DeviceProfile.TryValidate is the authority; these are its limits:
| Field | Range |
|---|---|
fanCount |
1 to 4 |
minRpm, maxRpm |
500 to 20000 rpm |
maxRpm - minRpm |
at least 500 rpm — anything narrower is not worth controlling |
cpuSensorIndex |
0 to 7 |
The wizard already produces values inside these bounds. If yours does not, something went wrong in the measurement and the profile should not be submitted — say so in the issue instead.
You need the .NET 10 SDK and Windows. There is no cross-platform build: MateFan talks to
root\wmi, which only exists here.
dotnet build matefan.slnx
dotnet test tests/MateFan.TestsThe test suite is deliberately hardware-free — no WMI, no schtasks, no Process.Start. That is
what lets it run on a CI runner, and it means you can run it on any Windows machine, Huawei or not.
dotnet run --project src/MateFan.AppAs administrator. root\wmi is unreachable otherwise, and the app will tell you so and exit.
.editorconfigapplies. Your editor should pick it up automatically.- Comments and identifiers are English, throughout, including in tests.
- The interface takes its text from
src/MateFan.App/Resources/Strings.resx(English, the neutral resource) andStrings.de.resx(German). A new string goes into both files, orLocalizationTestsfails the build. That is on purpose: a half-translated release should break CI, not surface in front of a user. - Keys without a placeholder get a property on
Stringsso XAML can reach them through{x:Static}. Keys with a{0}deliberately get none — they are reachable only throughStrings.Format, which cannot forget the arguments.
Any code path that sets a fan speed must put the fans back on automatic on every way out — success, cancellation, firmware refusal, exception, all of them.
CalibrationRunner is the pattern to copy: its whole run sits in a try/finally, and the
finally calls RestoreAutomatic() for every fan it touched. A cancelled measurement leaves the
machine exactly as it found it. Hold new code to the same standard, and add the test that proves
it — CalibrationRunnerTests cancels mid-run precisely so the guarantee cannot be satisfied by
accident.
These are settled decisions, not gaps waiting for a contribution:
- Manufacturers other than Huawei. MateFan drives the fans through a Huawei firmware interface. Supporting another vendor means a different protocol and a different project.
- Switching language at runtime. The language is fixed at start, from the system.
- Automatic updates. Releases are downloaded by hand.
- Separate curves per fan. One curve drives all fans.
- Controlling by sensors other than the CPU temperature.
If you disagree with one of these, open an issue and make the case before writing the code — it is a shame to write a feature that gets declined on principle.