Skip to content
View in the app

A better way to browse. Learn more.

Unraid

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

[Support] SasaKaranovic - OpenFan Controller

Featured Replies

For your containers you aren't using the usual appdata subfolder?

  • Replies 99
  • Views 11.8k
  • Created
  • Last Reply

Top Posters In This Topic

Most Popular Posts

  • For anyone interested in this great project, i created an updated 3d printable case. This remix allows the installation of the fancontroller in a 2.5" SATA SSD slot. https://makerworld.com/en/models

  • SasaKaranovic
    SasaKaranovic

    New version should be live now. Main improvement should be that now you are able to specify multiple disks temperatures to be used for determining fan curve profile. This should hopefully make a life

  • JayBee_Unraid
    JayBee_Unraid

    That was it! I just needed to switch it to host. Thanks for figuring that out. No, that address is the one used my unRaid server, you can see it in the screenshot. No problem with the port either. It

Posted Images

On 1/18/2025 at 7:24 PM, Gingersnap155 said:

Ok so I switch to using a JSON and adjusted the docker run command accordingly. Now it works fine.  It’s possible I messed up something with my docker run command with a typo and that was the problem. Either way it works perfectly fine now. And I can even edit it in notepad++ and save and it will adjust on the fly. 

What exactly did you change? I am having the same 'error parsing json file/error: expecting value' issues as other. I have swapped some stuff .json  and .yaml stuff around, but I have no experiance with anything beyond very basic stuff with dockers, so I really have almost no idea what to do. Very frustrating. The controller seems to be working fine, but i cant figuure out the service.

3 hours ago, anon0276 said:

What exactly did you change? I am having the same 'error parsing json file/error: expecting value' issues as other. I have swapped some stuff .json  and .yaml stuff around, but I have no experiance with anything beyond very basic stuff with dockers, so I really have almost no idea what to do. Very frustrating. The controller seems to be working fine, but i cant figuure out the service.

The latest image version for the docker isn't up to date at all, I guess the dev forgot to update it from his own source code. It means yaml support isn't present at all in the docker, so no matter what it won't work.

To make a json it's simple, just create an yaml file then use a yaml to json converter, then change the docker installation to replace every reference of the yaml file by the json file.

Alternatively you can get a sample json file from here and modify it the way you want.

Also both documentation and samples are incorrect, as fans are counted from 0 not 1, you need to change that if you want it to control the proper fan.

Edited by JayBee_Unraid

That worked, thankyou very much.

Now, when no profile is assigned to a fan, it starts. when I add a profile to any fan, I get this error:

 

pr 27 2025 13:54:18.599 pid:7 start.py                  58 DEBUG Setting fan OpenFAN/Fan/1 to 50% PWM based on sensor temperature of 24°C
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/urllib3/connection.py", line 198, in _new_conn
    sock = connection.create_connection(
  File "/usr/local/lib/python3.10/dist-packages/urllib3/util/connection.py", line 85, in create_connection
    raise err
  File "/usr/local/lib/python3.10/dist-packages/urllib3/util/connection.py", line 73, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/urllib3/connectionpool.py", line 793, in urlopen
    response = self._make_request(
  File "/usr/local/lib/python3.10/dist-packages/urllib3/connectionpool.py", line 496, in _make_request
    conn.request(
  File "/usr/local/lib/python3.10/dist-packages/urllib3/connection.py", line 400, in request
    self.endheaders()
  File "/usr/lib/python3.10/http/client.py", line 1278, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.10/http/client.py", line 1038, in _send_output
    self.send(msg)
  File "/usr/lib/python3.10/http/client.py", line 976, in send
    self.connect()
  File "/usr/local/lib/python3.10/dist-packages/urllib3/connection.py", line 238, in connect
    self.sock = self._new_conn()
  File "/usr/local/lib/python3.10/dist-packages/urllib3/connection.py", line 213, in _new_conn
    raise NewConnectionError(
urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x15291b8ead10>: Failed to establish a new connection: [Errno 111] Connection refused

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/requests/adapters.py", line 667, in send
    resp = conn.urlopen(
  File "/usr/local/lib/python3.10/dist-packages/urllib3/connectionpool.py", line 847, in urlopen
    retries = retries.increment(
  File "/usr/local/lib/python3.10/dist-packages/urllib3/util/retry.py", line 515, in increment
    raise MaxRetryError(_pool, url, reason) from reason  # type: ignore[arg-type]
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='192.168.xx.xx', port=3000): Max retries exceeded with url: /api/v0/fan/1/set?value=50 (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x15291b8ead10>: Failed to establish a new connection: [Errno 111] Connection refused'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/mnt/OpenFanService/start.py", line 138, in <module>
    main(None, None, None, None, None)
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
  File "/mnt/OpenFanService/start.py", line 135, in main
    OpenFan.run_forever(live_reload=arg_live_reload)
  File "/mnt/OpenFanService/start.py", line 103, in run_forever
    self.update_fan_controls()
  File "/mnt/OpenFanService/start.py", line 37, in update_fan_controls
    self.update_fan(fan)
  File "/mnt/OpenFanService/start.py", line 59, in update_fan
    return self.openfan_client.set_fan_pwm(fanData['Identifier'], fan_value)
  File "/mnt/OpenFanService/openfan_client.py", line 39, in set_fan_pwm
    r = requests.get(f'{self.api_url}/fan/{fan}/set?value={pwm}', verify=False, timeout=(0.5, 1))
  File "/usr/local/lib/python3.10/dist-packages/requests/api.py", line 73, in get
    return request("get", url, params=params, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/requests/api.py", line 59, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/requests/sessions.py", line 589, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.10/dist-packages/requests/sessions.py", line 703, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/requests/adapters.py", line 700, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='192.168.xx.xx', port=3000): Max retries exceeded with url: /api/v0/fan/1/set?value=50 (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x15291b8ead10>: Failed to establish a new connection: [Errno 111] Connection refused'))

 

 

2 hours ago, anon0276 said:

That worked, thankyou very much.

Now, when no profile is assigned to a fan, it starts. when I add a profile to any fan, I get this error:

 

pr 27 2025 13:54:18.599 pid:7 start.py                  58 DEBUG Setting fan OpenFAN/Fan/1 to 50% PWM based on sensor temperature of 24°C
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/urllib3/connection.py", line 198, in _new_conn
    sock = connection.create_connection(
  File "/usr/local/lib/python3.10/dist-packages/urllib3/util/connection.py", line 85, in create_connection
    raise err
  File "/usr/local/lib/python3.10/dist-packages/urllib3/util/connection.py", line 73, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/urllib3/connectionpool.py", line 793, in urlopen
    response = self._make_request(
  File "/usr/local/lib/python3.10/dist-packages/urllib3/connectionpool.py", line 496, in _make_request
    conn.request(
  File "/usr/local/lib/python3.10/dist-packages/urllib3/connection.py", line 400, in request
    self.endheaders()
  File "/usr/lib/python3.10/http/client.py", line 1278, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.10/http/client.py", line 1038, in _send_output
    self.send(msg)
  File "/usr/lib/python3.10/http/client.py", line 976, in send
    self.connect()
  File "/usr/local/lib/python3.10/dist-packages/urllib3/connection.py", line 238, in connect
    self.sock = self._new_conn()
  File "/usr/local/lib/python3.10/dist-packages/urllib3/connection.py", line 213, in _new_conn
    raise NewConnectionError(
urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x15291b8ead10>: Failed to establish a new connection: [Errno 111] Connection refused

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/requests/adapters.py", line 667, in send
    resp = conn.urlopen(
  File "/usr/local/lib/python3.10/dist-packages/urllib3/connectionpool.py", line 847, in urlopen
    retries = retries.increment(
  File "/usr/local/lib/python3.10/dist-packages/urllib3/util/retry.py", line 515, in increment
    raise MaxRetryError(_pool, url, reason) from reason  # type: ignore[arg-type]
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='192.168.xx.xx', port=3000): Max retries exceeded with url: /api/v0/fan/1/set?value=50 (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x15291b8ead10>: Failed to establish a new connection: [Errno 111] Connection refused'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/mnt/OpenFanService/start.py", line 138, in <module>
    main(None, None, None, None, None)
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
  File "/mnt/OpenFanService/start.py", line 135, in main
    OpenFan.run_forever(live_reload=arg_live_reload)
  File "/mnt/OpenFanService/start.py", line 103, in run_forever
    self.update_fan_controls()
  File "/mnt/OpenFanService/start.py", line 37, in update_fan_controls
    self.update_fan(fan)
  File "/mnt/OpenFanService/start.py", line 59, in update_fan
    return self.openfan_client.set_fan_pwm(fanData['Identifier'], fan_value)
  File "/mnt/OpenFanService/openfan_client.py", line 39, in set_fan_pwm
    r = requests.get(f'{self.api_url}/fan/{fan}/set?value={pwm}', verify=False, timeout=(0.5, 1))
  File "/usr/local/lib/python3.10/dist-packages/requests/api.py", line 73, in get
    return request("get", url, params=params, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/requests/api.py", line 59, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/requests/sessions.py", line 589, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.10/dist-packages/requests/sessions.py", line 703, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/requests/adapters.py", line 700, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='192.168.xx.xx', port=3000): Max retries exceeded with url: /api/v0/fan/1/set?value=50 (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x15291b8ead10>: Failed to establish a new connection: [Errno 111] Connection refused'))

 

 

please share the content of your json, add it to your comment as a code snippet.

  • 2 weeks later...

I've been searching for a supported PWM controller for Unraid. While my Asus ROG Maximus Hero X sensors are working, it appears I cannot get the PWM fan controls to function.

 

I wanted to buy the OpenFan controller, but it appears to be now unavailable for purchase. It says "due to tariffs" but it seems that should just be a cost / pricing issue. I'm ok to pay more, but that's not given as an option.

 

So my questions are:

 

1. Does anyone know if the hardware can still be sourced?

2. If not, can anyone recommend an alternative?

 

Thanks.

  • Author
On 5/7/2025 at 5:54 PM, RandoUser said:

1. Does anyone know if the hardware can still be sourced?

2. If not, can anyone recommend an alternative?

 

Hey @RandoUser

The OpenFAN Controller is available and shipping world-wide. There is only a temporary pause for US due to tariffs.
Reason is that for a couple of weeks now couriers are literally either rejecting or putting on hold any new parcels going to the US. Since Monday I've been informed that parcels can be shipped to US but we need to pre-pay 165% import duty.
To me this seems absolutely ridiculous especially because I also believe that tariffs won't last forever...

However if you really need one ASAP and don't mind paying the import duty, please reach out to me and we can arrange shipping.
Again, I would advise maybe waiting a week or two and hopefully thing will improve by then...
Unfortunately this is out of my hands and also there is no guarantee that by the time package reaches US customs there won't be new rules affecting it.

  • Author
On 4/27/2025 at 9:56 AM, anon0276 said:

That worked, thankyou very much.

Now, when no profile is assigned to a fan, it starts. when I add a profile to any fan, I get this error:

 

Hey @anon0276

 

Please make sure your docker containers can talk to each other and that you have the correct IP address for OpenFAN Controller Web API.
From the error log it shows that you have specified that OpenFAN Controller server is at `192.168.xx.xx` which is incorrect no possible.
You need to replace this with the actual IP of the server (where docker container is running).

2 hours ago, SasaKaranovic said:

 

Hey @RandoUser

The OpenFAN Controller is available and shipping world-wide. There is only a temporary pause for US due to tariffs.
Reason is that for a couple of weeks now couriers are literally either rejecting or putting on hold any new parcels going to the US. Since Monday I've been informed that parcels can be shipped to US but we need to pre-pay 165% import duty.
To me this seems absolutely ridiculous especially because I also believe that tariffs won't last forever...

However if you really need one ASAP and don't mind paying the import duty, please reach out to me and we can arrange shipping.
Again, I would advise maybe waiting a week or two and hopefully thing will improve by then...
Unfortunately this is out of my hands and also there is no guarantee that by the time package reaches US customs there won't be new rules affecting it.

Thanks for the quick response. I'm with you that the whole tariffs thing is absolutely ridiculous. I'll follow your suggestion to wait a couple of weeks to see what the couriers are doing.

  • 2 weeks later...

@SasaKaranovic Can you please read my previous messages and check the issues I mentioned?

  • 2 weeks later...
  • Author
On 5/21/2025 at 1:55 AM, JayBee_Unraid said:

@SasaKaranovic Can you please read my previous messages and check the issues I mentioned?

Sorry I missed your previous message. There is a new version of the docker image, please check it out and see if it resolves the issue or feel free to email me if you need any help or have suggestions. :)

Edited by SasaKaranovic

  • Author

New version should be live now. Main improvement should be that now you are able to specify multiple disks temperatures to be used for determining fan curve profile. This should hopefully make a life a bit easier for people who have single fan cooling multiple disks. :)

I have also started a change log file to keep track of changes.

## 2025-05-31

- Adding support for multiple temperature sensors. Temperature source TempSource can now be a list of sensors.

- Adding option to specify how TempSource list should be evaluated. Default is max which finds temperature sensor with the highest temperature and uses it's value for for applying the fan curve. It is possible to explicitly request min as the eval function. Although using min is probably a really bad idea, but it's there if you need it.

- If not specified, default fan curve will be linear

- If no temperature source TempSource) is specified in fan profile, and error will be raised instead of current silent behaviour.

- If temperature sensor does not exist, temperature of -1 will be returned (previously it would return 0). Now it is easy to differentiate between missing sensor/disk -1) and a spun-down disk 0). If you use LN2 for cooling and this causes issues for you, let me know.

On 6/1/2025 at 1:37 PM, SasaKaranovic said:

New version should be live now. Main improvement should be that now you are able to specify multiple disks temperatures to be used for determining fan curve profile. This should hopefully make a life a bit easier for people who have single fan cooling multiple disks. :)

I have also started a change log file to keep track of changes.

## 2025-05-31

- Adding support for multiple temperature sensors. Temperature source TempSource can now be a list of sensors.

- Adding option to specify how TempSource list should be evaluated. Default is max which finds temperature sensor with the highest temperature and uses it's value for for applying the fan curve. It is possible to explicitly request min as the eval function. Although using min is probably a really bad idea, but it's there if you need it.

- If not specified, default fan curve will be linear

- If no temperature source TempSource) is specified in fan profile, and error will be raised instead of current silent behaviour.

- If temperature sensor does not exist, temperature of -1 will be returned (previously it would return 0). Now it is easy to differentiate between missing sensor/disk -1) and a spun-down disk 0). If you use LN2 for cooling and this causes issues for you, let me know.

Thanks a lot for the update, that is massively better and more useful now 🍻

And yeah the YAML file does work now.

UPDATE: This was solved here: https://forums.unraid.net/topic/155377-support-sasakaranovic-openfan-controller/page/3/#findComment-1559891

After some errors on my part getting the OpenFanUnraidService to communicate with the OpenFanController, as I was using port 3000 instead of 3210, I got the communication between them working.

However, I noticed that not matter the FanProfiles Points or whether I used RPM or PWM (yes, I set UsePWM to true) the fan speed did not change.

image.png

I decided to shutdown the OpenFanUnraidService and test the API, so I just used curl and first got the status, which show Fan 1 (only fan connected since I'm testing) at 951.

image.png

So I set the fan speed to 100% PWM
image.png

The fan physically didn't do anything, so I got the status again, and the fan is shown still running around ~950 RPM

image.png

Odd... so I decided to test with profiles. First I created two new profiles PWM50 and PWM100.

image.png

Then ran status, set PWM100 and ran status again, that worked!

image.png

Reverted back to PWM50

image.png

Now tried again to set the fan 1 PWM and it again failed! It is receiving and setting the PWM but no change.

image.png

@SasaKaranovic any ideas?

Edited by PeterDB

  • Author

Hey @PeterDB

There are a couple of things that don't make a lot of sense in those images/steps, so let's start from scratch and maybe let's clarify how this should work if you are using OpenFAN Controller on Unraid.

There are essentially two parts that you need to setup.

  • OpenFAN Controller - This is a "gateway" for any application on the system/network to talk with the OpenFAN Controller using WebAPI.

  • OpenFAN Unraid Service - This service will read disk temperatures and based on your fan profile definition, make an API call to update fan speeds.

First part is; you setup the OpenFAN Controller WebAPI docker image.

That's it.

(Don't create custom profiles or anything else because you will use OpenFAN Unraid Service to do everything else for you.)

Second part is; you setup OpenFAN Unraid Service docker image.

Create your fan profiles and assign them to fans and run the service.

Now the OpenFAN Unraid Service will manage your fans and their speed based on your fan profiles definition and disk temperatures.

There is no need (and will not have any effect) to manually make API calls to set fan speed because they will almost immediately get overwritten by a regular API call that OpenFAN Unraid Service makes.

Also note that OpenFAN Controller and OpenFAN Unraid Service are aware that machines prefer indexes that start at 0 and that humans usually prefer indexes that start at 1. So under the hood, they both massage the messaging to keep both happy. :)

I'm pretty sure this is not the case, but just saying it for future reference; You can NOT control 3-pin or 2-pin fans with OpenFAN Controller. In order to measure RPM and control the fan speed, you will need 4-pin (PWM) fans.

Also I noticed you are looking at the logs of OpenFAN Controller, but I think you should be more interested in the logs from OpenFAN Unraid Service.

p.s. If you are posting logs or config files, it's a lot better (or at least I think it is) if you attach the text output rather than screenshots. Text will scale nicely on all devices, it's easier to read, you can search it, copy&paste etc.

UPDATE: This was resolved here: https://forums.unraid.net/topic/155377-support-sasakaranovic-openfan-controller/page/3/#findComment-1559891

Hi @SasaKaranovic

I do have a 4pin PWM Noctua NF-P12 connected to FAN1

image.png

and I also have the Unraid Community OpenFanController docker and OpenFanUnraidService installed and running

image.png

For OpenFanController I left the port at default 3210 and changed nothing:

image.png

I am able to access OpenFanController docker and it is able to able to manually control FAN1, here it is spun up to 100% PWM with around ~1700 RPM

image.png

Here is FAN1 at 50% PWM with around ~940 RPM

image.png

The OpenFanUnraidService is also set up and running with this docker configuration

image.png

And the fan_profiles.yaml is in /mnt/user/appdata/openfanservice/

image.png

With this simple configuration looking only as the cache_nvme and disk1 temps , set with a linear curve and top temperature set to 30 and 100% PWM. The fan_profiles.yaml was built over the included https://github.com/SasaKaranovic/OpenFanUnraidService/blob/master/src/sample_profile.yaml

image.png

Right now that cache_nvme drive is hitting 39C, and according to the fan_profiles.yaml FAN1 should be at 100% PWM

image.png

As seen earlier in the earlier screenshot, 100% PWN is ~1700 RPM, but it's only at ~940 RPM

image.png

This is why I started to check the logs and API calls. I can see from the OpenFanUnraidService that the profile is being created and FAN1 is being set to 100% PWM and also that the cache_nvme drive temperature is seen at 40C.

image.png

From the OpenFanController logs, I can also see that it is receiving the API call and setting FAN1 to 100%. However, the fan is not adjusting the RPM.

image.png

Now, you are right, my earlier API calls, had 1 instead of 0 as the selected FAN (I blame that I being up to 3am and emailing you, plus my wife's alarming then going off at 7am again).

image.png

and when I do use 0 instead of 1, it does spin up to 100% PWM

image.png

However, how come the fan_profiles.yaml doesn't do this, when it sees that the cache_nvme drive is 40C and the highest point is set to 30,100 (30C 100% PWM)?

I tried make the fan_profiles.yaml even more simple and just set 0,100 and only lookg at cache_nvme...

image.png

but that still didn't make any change

image.png

I changed again to using RPM..

image.png

The OpenFanUnraidService is sending it

image.png

And OpenFanController is receiving it

image.png

But that also didn't make any change to the RPM

image.png

So back again to the quesiton, if the dockers are set up and the API calls are received, how come there is no change?

Updating with the logs:

logs.zip

Edited by PeterDB

@SasaKaranovic I found the error! It's the sample_profile.yaml!

I went through the logs and saw that OpenFanUnraidService is making the API call to the wrong fan; fan 1 instead of fan 0! The reason being is that the sample_profile.yaml that I copied from https://github.com/SasaKaranovic/OpenFanUnraidService/blob/master/src/sample_profile.yaml it has FAN1 with the identifier OpenFAN/Fan/1 not OpenFAN/Fan/0.

Once I made the change, it is now working!

image.png

image.png

image.png

Edited by PeterDB

  • 2 weeks later...

I have an odd issue. I have three drive cages. Each cage has the same fan in it. These PWM fans are capable of 4500rpm. When I am running the openfan docker I can manually adjust the PWM percentage of each fan and watch the RPM increase. When running the openfan unraid service docker the FAN#4 in my config wants to set itself to about 1500 RPM. I can see in the logs as the drive temp increases the unraid service docker continues to increase the commanded pwm percentage up to 90% but the fan stays around 1500rpm. The other fans seem to work fine. I did not find a reason for this behavior in the YAML config.

Unraid Version: 7.1.2

fan_profiles.yaml

Edited by K1ng0011

6 minutes ago, K1ng0011 said:

I have an odd issue. I have three drive cages. Each cage has the same fan in it. These PWM fans are capable of 4500rpm. When I am running the openfan docker I can manually adjust the PWM percentage of each fan and watch the RPM increase. When running the openfan unraid service docker the FAN#4 in my config wants to set itself to about 1500 RPM. I can see in the logs as the drive temp increases the unraid service docker continues to increase the commanded pwm percentage up to 90% but the fan stays around 1500rpm. The other fans seem to work fine. I did not find a reason for this behavior in the YAML config.

Unraid Version: 7.1.2

fan_profiles.yaml

Hi @K1ng0011

I think you have the same issue as me, the sample profiles yaml is not correct and Saša is aware of this.

Update your yaml so that the identifier starts at OpenFAN/Fan/0 not OpenFAN/Fan/1, and update the others too so it's 0 to 9 not 1 to 10.

Now test

Edited by PeterDB

Perfect its fixed now my fans are being controlled via the unraid service docker I created. I also noticed the following issue below. I know I am just nit picking but the spelling is off. Also I find it odd that in the actual docker for the open fan controller that the max fan speed is 3000 rpm. Maybe there is a reason that I am not aware of but some fans like mine are capable of more than 3000rpm.

Fix the "Crate new profile"

image.png

3 minutes ago, K1ng0011 said:

Perfect its fixed now my fans are being controlled via the unraid service docker I created. I also noticed the following issue below. I know I am just nit picking but the spelling is off. Also I find it odd that in the actual docker for the open fan controller that the max fan speed is 3000 rpm. Maybe there is a reason that I am not aware of but some fans like mine are capable of more than 3000rpm.

Fix the "Crate new profile"

image.png

hahahah @SasaKaranovic one more minor thing to fix.

@K1ng0011 99.1% of consumer fans, except Phantek T56's and some other models, can do more than 2000 RPM. Yes, there are model that do more, but the usage is niche and you wouldn't be able to sit next to the rack either because of the noise at those speeds. Maybe this something Sasa can fix, but there is no feedback mechanism from fans to report up what their max RPM is (at least that I know of).

  • Author

Thank you for helping out with the typo everyone.

The documentation and GitHub repo have been updated.

@PeterDB @K1ng0011 Fans maximum RPM is mostly arbitrary and from my research most consumer PC fans are around 2-3K RPM.
The fans don't report their RPM. However you could run the fan at 100% PWM and then record the maximum RPM. Obviously there are issues with this approach. Mainly you would have to spin-up the fans to the maximum, for at least a couple of seconds, every time the app/controller starts... this would be very annoying (to me). I think it's much easier to edit a text file and change "2000" to "4000" and you are good to go. That's one of the beauties of open-source. :)

Strangely, I bought a 6000 RPM fan and when either trying to manually set the fan to 100% PWM or MadMax (which should do the same), the 6000 RPM fan will just keep spinning up to about 4800 RPM then slow to about 2000 RPM then spin up again. It just does this repeatedly. It's Fan #3 in the log. The fan is a Delta model (https://www.delta-fan.com/qfr1212ghe.html). It is 12V 2.7A. Just wondering if the controller board can't sustain that amperage.

Logs:

Jun 28 2025 17:19:56.560 pid:7 webserver.py 145 INFO Request:STATUS

Jun 28 2025 17:19:56.560 pid:7 FanCommander.py 24 DEBUG CMD:0 Data: None

Jun 28 2025 17:19:56.560 pid:7 FanCommander.py 25 DEBUG Sending >00

Jun 28 2025 17:19:56.562 pid:7 FanCommander.py 31 DEBUG [0002537527][I][HCOMM] >00

Jun 28 2025 17:19:56.562 pid:7 FanCommander.py 31 DEBUG [0002537527][D][HCOMM] host_comm_tick: Start character found (Len=2)

Jun 28 2025 17:19:56.562 pid:7 FanCommander.py 31 DEBUG [0002537527][D][HCOMM] host_comm_parse_package

Jun 28 2025 17:19:56.562 pid:7 FanCommander.py 31 DEBUG [0002537527][D][HCOMM] A=00 H:0x00

Jun 28 2025 17:19:56.562 pid:7 FanCommander.py 31 DEBUG [0002537527][D][HCOMM] CMD_FAN_ALL_GET_RPM

Jun 28 2025 17:19:56.562 pid:7 FanCommander.py 31 DEBUG <00|00:080B;01:07FD;02:059F;03:09AD;04:05B4;05:0000;06:0000;07:0000;08:0000;09:0000;

Jun 28 2025 17:19:56.562 pid:7 FanCommander.py 33 DEBUG Response: '<00|00:080B;01:07FD;02:059F;03:09AD;04:05B4;05:0000;06:0000;07:0000;08:0000;09:0000;'

Jun 28 2025 17:19:56.562 pid:7 FanCommander.py 46 DEBUG {0: 2059, 1: 2045, 2: 1439, 3: 2477, 4: 1460, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0}

Jun 28 2025 17:20:00.561 pid:7 webserver.py 145 INFO Request:STATUS

Jun 28 2025 17:20:00.561 pid:7 FanCommander.py 24 DEBUG CMD:0 Data: None

Jun 28 2025 17:20:00.561 pid:7 FanCommander.py 25 DEBUG Sending >00

Jun 28 2025 17:20:00.563 pid:7 FanCommander.py 31 DEBUG [0002541529][I][HCOMM] >00

Jun 28 2025 17:20:00.563 pid:7 FanCommander.py 31 DEBUG [0002541529][D][HCOMM] host_comm_tick: Start character found (Len=2)

Jun 28 2025 17:20:00.563 pid:7 FanCommander.py 31 DEBUG [0002541529][D][HCOMM] host_comm_parse_package

Jun 28 2025 17:20:00.563 pid:7 FanCommander.py 31 DEBUG [0002541529][D][HCOMM] A=00 H:0x00

Jun 28 2025 17:20:00.563 pid:7 FanCommander.py 31 DEBUG [0002541529][D][HCOMM] CMD_FAN_ALL_GET_RPM

Jun 28 2025 17:20:00.563 pid:7 FanCommander.py 31 DEBUG <00|00:0804;01:07FD;02:0597;03:102B;04:05B0;05:0000;06:0000;07:0000;08:0000;09:0000;

Jun 28 2025 17:20:00.564 pid:7 FanCommander.py 33 DEBUG Response: '<00|00:0804;01:07FD;02:0597;03:102B;04:05B0;05:0000;06:0000;07:0000;08:0000;09:0000;'

Jun 28 2025 17:20:00.564 pid:7 FanCommander.py 46 DEBUG {0: 2052, 1: 2045, 2: 1431, 3: 4139, 4: 1456, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0}

  • Author
On 6/28/2025 at 1:23 PM, RandoUser said:

Strangely, I bought a 6000 RPM fan and when either trying to manually set the fan to 100% PWM or MadMax (which should do the same), the 6000 RPM fan will just keep spinning up to about 4800 RPM then slow to about 2000 RPM then spin up again. It just does this repeatedly. It's Fan #3 in the log. The fan is a Delta model (https://www.delta-fan.com/qfr1212ghe.html). It is 12V 2.7A. Just wondering if the controller board can't sustain that amperage.

Hey @RandoUser

The OpenFan Controller has a resetable fuse for each fan that trips around 1.1A (per fan). This is obviously for safety reasons. So your fan will not be able to draw the 2.7A without tripping the fuse.
If you like to live dangerously, you can short/replace the fuse, but please make sure you know what you are doing and not doing it just for fun.
I strongly advise against this, instead I would recommend getting a more common (less insane?) PC fan that is less likely to melt your power cables and/or damage your PC! :)

On 6/28/2025 at 7:23 PM, RandoUser said:

Strangely, I bought a 6000 RPM fan and when either trying to manually set the fan to 100% PWM or MadMax (which should do the same), the 6000 RPM fan will just keep spinning up to about 4800 RPM then slow to about 2000 RPM then spin up again. It just does this repeatedly. It's Fan #3 in the log. The fan is a Delta model (https://www.delta-fan.com/qfr1212ghe.html). It is 12V 2.7A. Just wondering if the controller board can't sustain that amperage.

Logs:

Jun 28 2025 17:19:56.560 pid:7 webserver.py 145 INFO Request:STATUS

Jun 28 2025 17:19:56.560 pid:7 FanCommander.py 24 DEBUG CMD:0 Data: None

Jun 28 2025 17:19:56.560 pid:7 FanCommander.py 25 DEBUG Sending >00

Jun 28 2025 17:19:56.562 pid:7 FanCommander.py 31 DEBUG [0002537527][I][HCOMM] >00

Jun 28 2025 17:19:56.562 pid:7 FanCommander.py 31 DEBUG [0002537527][D][HCOMM] host_comm_tick: Start character found (Len=2)

Jun 28 2025 17:19:56.562 pid:7 FanCommander.py 31 DEBUG [0002537527][D][HCOMM] host_comm_parse_package

Jun 28 2025 17:19:56.562 pid:7 FanCommander.py 31 DEBUG [0002537527][D][HCOMM] A=00 H:0x00

Jun 28 2025 17:19:56.562 pid:7 FanCommander.py 31 DEBUG [0002537527][D][HCOMM] CMD_FAN_ALL_GET_RPM

Jun 28 2025 17:19:56.562 pid:7 FanCommander.py 31 DEBUG <00|00:080B;01:07FD;02:059F;03:09AD;04:05B4;05:0000;06:0000;07:0000;08:0000;09:0000;

Jun 28 2025 17:19:56.562 pid:7 FanCommander.py 33 DEBUG Response: '<00|00:080B;01:07FD;02:059F;03:09AD;04:05B4;05:0000;06:0000;07:0000;08:0000;09:0000;'

Jun 28 2025 17:19:56.562 pid:7 FanCommander.py 46 DEBUG {0: 2059, 1: 2045, 2: 1439, 3: 2477, 4: 1460, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0}

Jun 28 2025 17:20:00.561 pid:7 webserver.py 145 INFO Request:STATUS

Jun 28 2025 17:20:00.561 pid:7 FanCommander.py 24 DEBUG CMD:0 Data: None

Jun 28 2025 17:20:00.561 pid:7 FanCommander.py 25 DEBUG Sending >00

Jun 28 2025 17:20:00.563 pid:7 FanCommander.py 31 DEBUG [0002541529][I][HCOMM] >00

Jun 28 2025 17:20:00.563 pid:7 FanCommander.py 31 DEBUG [0002541529][D][HCOMM] host_comm_tick: Start character found (Len=2)

Jun 28 2025 17:20:00.563 pid:7 FanCommander.py 31 DEBUG [0002541529][D][HCOMM] host_comm_parse_package

Jun 28 2025 17:20:00.563 pid:7 FanCommander.py 31 DEBUG [0002541529][D][HCOMM] A=00 H:0x00

Jun 28 2025 17:20:00.563 pid:7 FanCommander.py 31 DEBUG [0002541529][D][HCOMM] CMD_FAN_ALL_GET_RPM

Jun 28 2025 17:20:00.563 pid:7 FanCommander.py 31 DEBUG <00|00:0804;01:07FD;02:0597;03:102B;04:05B0;05:0000;06:0000;07:0000;08:0000;09:0000;

Jun 28 2025 17:20:00.564 pid:7 FanCommander.py 33 DEBUG Response: '<00|00:0804;01:07FD;02:0597;03:102B;04:05B0;05:0000;06:0000;07:0000;08:0000;09:0000;'

Jun 28 2025 17:20:00.564 pid:7 FanCommander.py 46 DEBUG {0: 2052, 1: 2045, 2: 1431, 3: 4139, 4: 1456, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0}

I gotta ask @RandoUser 10 fans at 2.7A. that's 27A on the 12V rail, which power supply are you using? I know my Corsair HX1200 can handle max 100A and on multi rails 40A, but 27A for fans is a lot.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.