Skip to content

Instantly share code, notes, and snippets.

@SqyD
Last active Nov 23, 2022
Embed
What would you like to do?
mqtt-pi-pwn-fan

MQTT client to control a PWM fan from a raspberry pi

A simple python script to control a fan from Home Assistant.

Note: I have replaced this Raspberry based solution with an Wemos/ESPHome based one you can find here:

https://gist.github.com/SqyD/38d10391c2e21988406d2bdaec24f031

  • Installing dependencies on a stock Raspbian install:
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install python3-pip python3-dev python3-gpiozero 
sudo pip3 install paho-mqtt
  • Create the python script as /home/pi/mqtt_fan.py
  • Create a systemd service definition file as /lib/systemd/system/mqtt_fan.service
  • Set permissions:
sudo chmod 644 /lib/systemd/system/mqtt_fan.service
  • Enable and test the service:
sudo systemctl daemon-reload
sudo systemctl enable mqtt_fan.service
sudo systemctl start mqtt_fan.service
# Snippet to add to a Home Assistant configuration yaml file
mqtt:
fan:
- platform: mqtt
name: "My Fan"
command_topic: "homeassistant/test_fan/on/set"
state_topic: "homeassistant/test_fan/on/state"
speed_command_topic: "homeassistant/test_fan/speed/set"
speed_state_topic: "homeassistant/test_fan/speed/state"
payload_low_speed: "low"
payload_medium_speed: "medium"
payload_high_speed: "high"
speeds:
- low
- medium
- high
#!/usr/bin/python3
import paho.mqtt.client as mqtt
from gpiozero import PWMOutputDevice
# MQTT configuration
broker = '127.0.0.1'
device_id = 'test_fan'
on_topic = 'homeassistant/' + device_id + '/on/set'
on_state_topic = 'homeassistant/' + device_id + '/on/state'
speed_topic = 'homeassistant/' + device_id + '/speed/set'
speed_state_topic = 'homeassistant/' + device_id + '/speed/state'
# gpio settings
gpio_pin = 18
pwm_freq = 5000
speeds = {'low': 0.05, 'medium': 0.4, 'high': 1}
class PwmFan:
on_state = 'OFF'
pwm = PWMOutputDevice(gpio_pin,frequency=pwm_freq)
speed_state = 'high'
def switch(self, onoff):
if onoff == 'ON':
if self.on_state == 'OFF':
self.on_state = 'ON'
self.set_speed(self.speed_state)
elif onoff == 'OFF':
if self.on_state == 'ON':
self.on_state = 'OFF'
self.pwm.off()
def set_speed(self,speed):
if speed in speeds:
if self.on_state == 'ON':
self.pwm.value=speeds[speed]
self.speed_state = speed
fan = PwmFan()
def on_message(client, userdata, message):
payload = str(message.payload.decode("utf-8"))
topic = message.topic
if topic == on_topic:
print("ON/OF command received")
if (payload == 'ON') or (payload == 'OFF'):
print("turning " + payload)
fan.switch(payload)
client.publish(on_state_topic, payload)
if payload == 'ON':
client.publish(speed_state_topic, fan.speed_state)
elif message.topic == speed_topic:
if payload in speeds:
print('Setting speed to ' + payload)
fan.set_speed(payload)
if fan.on_state == 'ON':
client.publish(speed_state_topic, fan.speed_state)
# Send messages in a loop
client = mqtt.Client("myfan")
client.on_message = on_message
# If your homeassistant is protected by as password, uncomment this next line:
# client.username_pw_set('homeassistant','yourpasswordhere')
client.connect(broker)
client.subscribe(on_topic)
client.subscribe(speed_topic)
client.loop_forever()
[Unit]
Description=MQTT Fan
After=multi-user.target
[Service]
Type=idle
ExecStart=/usr/bin/python3 /home/pi/mqtt_fan.py
[Install]
WantedBy=multi-user.target
@ReliableBob
Copy link

Hi.
Thanks for the great code.
Please tell me how to properly connect the fan to the GPIO? It needs to be connected directly or through a transistor.
Please give me the connection diagram.
Thank.

@kvvoff
Copy link

kvvoff commented May 9, 2019

Thanks!

@kvvoff
Copy link

kvvoff commented May 10, 2019

How can I use authentication for the mqtt client?

@kvvoff
Copy link

kvvoff commented May 10, 2019

and when i start mqtt_fan.py :
gpiozero.exc.PinPWMUnsupported: PWM is not supported on pin GPIO18

@ReliableBob
Copy link

ReliableBob commented May 10, 2019

How can I use authentication for the mqtt client?

# If your homeassistant is protected by as password, uncomment this next line:
# client.username_pw_set('homeassistant','yourpasswordhere')

@ReliableBob
Copy link

and when i start mqtt_fan.py :
gpiozero.exc.PinPWMUnsupported: PWM is not supported on pin GPIO18

GPIO18 and there is a PWM

@kvvoff
Copy link

kvvoff commented May 10, 2019

@ReliableBob
how could I not notice! Inattentive :) thanks. But I don’t understand why I get a error on pin18

@kvvoff
Copy link

kvvoff commented May 10, 2019

@ReliableBob
root@osmc:/home/osmc/mqtt# sudo python3 mqtt_fan.py /usr/local/lib/python3.5/dist-packages/gpiozero/devices.py:279: PinFactoryFallba ck: Falling back from rpigpio: No module named 'RPi' 'Falling back from %s: %s' % (name, str(e)))) /usr/local/lib/python3.5/dist-packages/gpiozero/devices.py:279: PinFactoryFallba ck: Falling back from rpio: No module named 'RPIO' 'Falling back from %s: %s' % (name, str(e)))) /usr/local/lib/python3.5/dist-packages/gpiozero/devices.py:279: PinFactoryFallba ck: Falling back from pigpio: No module named 'pigpio' 'Falling back from %s: %s' % (name, str(e)))) Traceback (most recent call last): File "mqtt_fan.py", line 19, in <module> class PwmFan: File "mqtt_fan.py", line 21, in PwmFan pwm = PWMOutputDevice(gpio_pin,frequency=pwm_freq) File "/usr/local/lib/python3.5/dist-packages/gpiozero/devices.py", line 124, i n __call__ self = super(GPIOMeta, cls).__call__(*args, **kwargs) File "/usr/local/lib/python3.5/dist-packages/gpiozero/output_devices.py", line 418, in __init__ self.pin.frequency = frequency File "/usr/local/lib/python3.5/dist-packages/gpiozero/pins/__init__.py", line 358, in <lambda> lambda self, value: self._set_frequency(value), File "/usr/local/lib/python3.5/dist-packages/gpiozero/pins/__init__.py", line 354, in _set_frequency raise PinPWMUnsupported("PWM is not supported on pin %r" % self) gpiozero.exc.PinPWMUnsupported: PWM is not supported on pin GPIO18

@ReliableBob
Copy link

Strange things ... I did everything according to the instructions and it works for me without errors ...
Raspberry pi 3 B +

@kvvoff
Copy link

kvvoff commented May 10, 2019

@ReliableBob
Really. But I have OSMС on pi2, not raspbian, can be because of this. And I did not manage to install python3-gpiozero via apt, I installed via pip. I will try on another system for the purity of the experiment.

@kvvoff
Copy link

kvvoff commented May 11, 2019

I needed a "wheel" setup for latest osmс

apt-get update
apt-get install python3-pip python3-dev gcc
apt-get install python3-setuptools
pip3 install wheel
pip3 install gpiozero

its working for me on my osmc, raspberry pi 2 model b

@SqyD
Copy link
Author

SqyD commented May 22, 2019

Please tell me how to properly connect the fan to the GPIO? It needs to be connected directly or through a transistor.
I used a cheap hardware PWM to 10V board since my ventilation unit has a 0-10V input. I don't have a diagram and my setup is likely different then yours. My ventilation unit has a 12V output and a 0-10V input. I used the PWM to 0-10V board to convert the GPIO PWM output to the variable voltage. I hope this clarifies things.

@ReliableBob
Copy link

Да, спасибо. Я всё понял.

Please tell me how to properly connect the fan to the GPIO? It needs to be connected directly or through a transistor.
I used a cheap hardware PWM to 10V board since my ventilation unit has a 0-10V input. I don't have a diagram and my setup is likely different then yours. My ventilation unit has a 12V output and a 0-10V input. I used the PWM to 0-10V board to convert the GPIO PWM output to the variable voltage. I hope this clarifies things.

Yes thank you. I got it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment