Troubles getting external raspberry pi's GPIOs as mqtt switches to work

Hey all,

I’ve got some troubles getting some external raspberry pi gpio’s to work.
I’m an noob related to programming, so here’s what I’ve copy & pasted so far:

Client-Script:
#!/usr/bin/python
# -- coding: utf-8 --
# Import package
import paho.mqtt.client as mqtt
#add for output
import RPi.GPIO as GPIO

# Define Variables
MQTT_HOST = "192.168.X.X"
MQTT_PORT = 1883
MQTT_KEEPALIVE_INTERVAL = 45
MQTT_TOPIC1 = "pibox/oben/switch/1"
MQTT_TOPIC2 = "pibox/oben/switch/2"
MQTT_TOPIC3 = "pibox/oben/switch/3"
MQTT_TOPIC4 = "pibox/oben/switch/4"
MQTT_TOPIC5 = "pibox/oben/switch/5"
MQTT_TOPIC6 = "pibox/oben/switch/6"
MQTT_TOPIC7 = "pibox/oben/switch/7"
MQTT_TOPIC8 = "pibox/oben/switch/8"
#MQTT_TOPIC = [("pibox/oben/switch1",0),("pibox/oben/switch2",0),("pibox/oben/switch3",0),("pibox/oben/switch4",0),("pibox/oben/switch5",0),("pibox/oben/switch6",0),("pibox/oben/switch7",0),("pibox/oben/switch8",0)]
MQTT_TOPIC = client.subscribe("pibox/#",0)

# Define Ports
SWITCH1 = 17 # wPi: 0
SWITCH2 = 4 # wPi: 7
SWITCH3 = 27 # wPi: 2
SWITCH4 = 24 # wPi: 5
SWITCH5 = 5 # wPi: 21
SWITCH6 = 6 # wPi: 22
SWITCH7 = 13 # wPi: 23
SWITCH8 = 16 # wPi: 27

GPIO.setmode(GPIO.BCM)
GPIO.setup(SWITCH1, GPIO.OUT)
GPIO.setup(SWITCH2, GPIO.OUT)
GPIO.setup(SWITCH3, GPIO.OUT)
GPIO.setup(SWITCH4, GPIO.OUT)
GPIO.setup(SWITCH5, GPIO.OUT)
GPIO.setup(SWITCH6, GPIO.OUT)
GPIO.setup(SWITCH7, GPIO.OUT)
GPIO.setup(SWITCH8, GPIO.OUT)

try:
  # Define on connect event function
  # We shall subscribe to our Topic in this function
  def on_connect(self,mosq, obj, rc):
     mqttc.subscribe(MQTT_TOPIC)
     print("Connected on "+MQTT_HOST)
  # Define on_message event function. 
  # This function will be invoked every time,
  # a new message arrives for the subscribed topic 
  def on_message(mosq, obj, msg):
     
      if(msg.topic==MQTT_TOPIC1):
          print 'Switch 1 wird geschaltet!'
          SWITCH = SWITCH1
      if(msg.topic==MQTT_TOPIC2):
          print 'Switch 2 wird geschaltet!'
          SWITCH = SWITCH2
      if(msg.topic==MQTT_TOPIC3):
          print 'Switch 3 wird geschaltet!'
          SWITCH = SWITCH1
      if(msg.topic==MQTT_TOPIC4):
          print 'Switch 4 wird geschaltet!'
          SWITCH = SWITCH4
      if(msg.topic==MQTT_TOPIC5):
          print 'Switch 5 wird geschaltet!'
          SWITCH = SWITCH1
      if(msg.topic==MQTT_TOPIC6):
          print 'Switch 6 wird geschaltet!'
          SWITCH = SWITCH6
      if(msg.topic==MQTT_TOPIC1):
          print 'Switch 7 wird geschaltet!'
          SWITCH = SWITCH7
      if(msg.topic==MQTT_TOPIC8):
          print 'Switch 8 wird geschaltet!'
          SWITCH = SWITCH2
      
      if (msg.payload=='ON'):
           GPIO.output(SWITCH,True)
           print 'Switch '+SWITCH+' switches to ON'
           print "Topic: " + str(msg.topic)
           print "QoS: " + str(msg.qos)
      if (msg.payload=='OFF'):
           GPIO.output(SWITCH,False)
           print 'Switch '+SWITCH+' switches to OFF' 
           print "Topic: " + str(msg.topic)
           print "QoS: " + str(msg.qos)

  def on_subscribe(mosq, obj, mid, granted_qos):
          print("Subscribed to Topic: " + 
          MQTT_TOPIC + " with QoS: " + str(granted_qos))

    # Initiate MQTT Client
  mqttc = mqtt.Client()

    # Assign event callbacks
  mqttc.on_message = on_message
  mqttc.on_connect = on_connect
  mqttc.on_subscribe = on_subscribe

    # Connect with MQTT Broker
  mqttc.connect(MQTT_HOST, MQTT_PORT, MQTT_KEEPALIVE_INTERVAL)

    # Continue monitoring the incoming messages for subscribed topic
  mqttc.loop_forever()

except KeyboardInterrupt:  
    # here you put any code you want to run before the program   
    # exits when you press CTRL+C
    GPIO.cleanup()  
#finally:  
    #GPIO.cleanup() # this ensures a clean exit

configuration.yaml
# External MQTT Switches
- platform: mqtt
name: “Switch 1”
state_topic: “pibox/oben/switch/1/state”
command_topic: “pibox/oben/switch/1/” #set"
availability_topic: “pibox/oben/switch/1/available”
payload_on: “ON”
payload_off: “OFF”
state_on: “ON”
state_off: “OFF”
optimistic: false
qos: 0
retain: true

      - platform: mqtt
        name: "Switch 2"
        state_topic: "pibox/oben/switch/2/state"
        command_topic: "pibox/oben/switch/2/set"
        availability_topic: "pibox/oben/switch/2/available"
        payload_on: "ON"
        payload_off: "OFF"
        state_on: "ON"
        state_off: "OFF"
        optimistic: false
        qos: 0
        retain: true
        etc..

And this is what it looks like:

Home Assistant Dashboard:

  • new user, so just one picture :open_mouth:

Entities tab:
00

I think this issue get’s caused by my lack of knowledge related to mqtt and his topics :confused:

Using this code just works like a charm:

  • new user, so just one picture.

    /dev-mqtt
    topic: pibox/oben/switch/8
    payload: ON

Any clue how to solve this issue?

Many thanks in advance!

If this is a seperate Pi to the one you are running HA on, save yourself some pain and use this:

All configured with yaml.

If it’s on the same Pi as HA you may not be able to use the GPIO port if HA doesn’t like sharing. It’s just a guess, I’m not sure about this.

2 Likes

Also this code may assist you, I’ve not used it but have heard it works:

#!/usr/bin/python

import RPi.GPIO as GPIO
import logging
import paho.mqtt.publish as publish
from time import sleep
from systemd.journal import JournalHandler

log = logging.getLogger('mqtt_alarm')
log.addHandler(JournalHandler())
log.setLevel(logging.INFO)

MQTT_HOST = "10.0.0.100"
MQTT_TOPIC_PREFIX = "home/alarm/"
MQTT_CLIENT_ID = "pi_slave1"
MQTT_PAYLOADS = {
  0: "off",
  1: "on",
}

# Dictionary of GPIO PIN to mqtt topic
PIN_MAP = {
  14: "smoke_comms",
  15: "smoke_lounge",
  17: "smoke_hall",
  18: "smoke_rumpus",
  27: "pir_wardrobe",
  22: "pir_ensuite",
  23: "pir_mstr_bedrm",
  24: "pir_lounge",
  10: "pir_dining",
  9: "pir_deck_side",
  25: "pir_deck_front",
  11: "pir_hall",
  8: "pir_study",
  7: "pir_laundry",
  5: "pir_washline",
  6: "pir_bathroom",
  12: "pir_spr_bedrm",
  13: "pir_entry",
  19: "pir_drive",
  16: "pir_rumpus",
  26: "pir_wkshop",
  20: "doorbell",
  21: "rfid_vald",
  4: "mailbox",
}

GPIO.setmode(GPIO.BCM)

def state_change_hadler(channel):
  state = GPIO.input(channel)

  if state:
    log.info("Rising edge detected on {}".format(channel))
  else:
    log.info("Falling edge detected on {}".format(channel))

  publish_event(channel, state)

def publish_event(pin, state):
  topic = MQTT_TOPIC_PREFIX + PIN_MAP[pin]
  payload = MQTT_PAYLOADS[state]

  publish.single(topic, payload, hostname=MQTT_HOST, retain=True, qos=2)

  log.info("Published event, topic={}, payload={}, hostname={}".format(topic, payload, MQTT_HOST))

for pin, name in PIN_MAP.items():
  GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  GPIO.add_event_detect(pin, GPIO.BOTH, callback=state_change_hadler, bouncetime=100)

  state = GPIO.input(pin)

  log.info("Mapped pin {:0>2d} to {}".format(pin, name))
  log.info("... state {}".format(state))

  publish_event(pin, state)

try:
  while True:
    sleep(60)
except KeyboardInterrupt:
  log.info("Stopping...")
finally:
  GPIO.cleanup()
2 Likes

Hey Tom,

thanks for your very quick reply !!

I gave it a try:

Server: config.yaml

mqtt:
  host: localhost
  port: 1883
  user: ""
  password: ""
  topic_prefix: pibox/switch

gpio_modules:
  - name: raspberrypi
    module: raspberrypi

digital_outputs:
  - name: '1'
    module: raspberrypi
    pin: 17
    on_payload: "ON"
    off_payload: "OFF"
  - name: '2'
    module: raspberrypi
    pin: 4
    on_payload: "ON"
    off_payload: "OFF"
    etc ...

HA: config.yaml

# External MQTT Switches
  - platform: mqtt
    name: "Switch 1"
    state_topic: "pibox/switch/output/output/1/state"
    command_topic: "pibox/switch/output/output/1/set"
    availability_topic: "pibox/switch/output/output/1/available"
    payload_on: "ON"
    payload_off: "OFF"
    state_on: "ON"
    state_off: "OFF"
    optimistic: false
    qos: 0
    retain: true

  - platform: mqtt
    name: "Switch 2"
    state_topic: "pibox/switch/output/2/state"
    command_topic: "pibox/switch/output/2/set"
    availability_topic: "pibox/switch/output/2/available"
    payload_on: "ON"
    payload_off: "OFF"
    state_on: "ON"
    state_off: "OFF"
    optimistic: false
    qos: 0
    retain: true
    etc...

Still the same issue:

Sending the Payload “ON” / “OFF” to the topics (ex. pibox/switch/output/1/set) manually still works :confused:

Do you see any errors in your mqtt broker log?

What broker are you using?

Could you expand on your set up, are you using hassio?

1 Like

Mmh and yeah, sorry about that! :confused:
So, here’s the setup:

Raspberry Pi 3B - hass.io

  • MQTT Integration

Raspberry Pi 2 - raspbian jessie (latest)

  • MQTT Broker
  • MQTT Server Script
    -> Both on same WiFi

=> Still works like a charm if i’m sending the mqtt messages directly using the /dev-mqtt - tab.

That’s the server script’s response:

MQTT client: Received PUBLISH (d0, q0, r0, m0), 'pibox/switch/output/1/set', ...  (2 bytes)
Received message on topic u'pibox/switch/output/1/set': 'ON'
Set 'raspberrypi' output '1' to True
MQTT client: Sending PUBLISH (d0, q0, r0, m26), 'pibox/switch/output/1', ... (2 bytes)

Mosquitto Status:

service mosquitto status
● mosquitto.service - LSB: mosquitto MQTT v3.1 message broker
   Loaded: loaded (/etc/init.d/mosquitto)
   Active: active (running) since Di 2018-11-13 16:27:09 CET; 18min ago
  Process: 15910 ExecStop=/etc/init.d/mosquitto stop (code=exited, status=0/SUCCESS)
  Process: 15958 ExecStart=/etc/init.d/mosquitto start (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/mosquitto.service
           └─15963 /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf

Mosquitto Log:

1542100884: Saving in-memory database to /var/lib/mosquitto/mosquitto.db.
1542102685: Saving in-memory database to /var/lib/mosquitto/mosquitto.db.
1542104486: Saving in-memory database to /var/lib/mosquitto/mosquitto.db.
1542106287: Saving in-memory database to /var/lib/mosquitto/mosquitto.db.
1542108088: Saving in-memory database to /var/lib/mosquitto/mosquitto.db.
1542109889: Saving in-memory database to /var/lib/mosquitto/mosquitto.db.
1542111690: Saving in-memory database to /var/lib/mosquitto/mosquitto.db.
1542113491: Saving in-memory database to /var/lib/mosquitto/mosquitto.db.
1542114215: New connection from 192.168.X.X on port 1883.
1542114215: New client connected from 192.168.X.X as T<ELMeZ8cJ27bx5XEubm^R5N5<J6>tjR77nDl?<FYwM2vC[3?D$
1542115292: Saving in-memory database to /var/lib/mosquitto/mosquitto.db.
1542116498: Socket error on client uGonp7UoIWxPR^n?QHBrbNnJ[FA[ABhvJ^\AUq8oOp6rUdqfm:_VXE`s[rU]t4JE, disco$
1542116507: New connection from ::1 on port 1883.
1542116507: New client connected from ::1 as Kh4wx@DH?QKuTfxcj_GH<:enG>U?R_wmO2k>3oV28aw\>g70=>89HmwOlTNEs$
1542117093: Saving in-memory database to /var/lib/mosquitto/mosquitto.db.
1542117958: New connection from ::1 on port 1883.
1542117958: New client connected from ::1 as pi-mqtt-gpio-e0ec1afe8b74758cff5fbf591d89f55a6f042a31 (c0, k6$
1542118073: Socket error on client Kh4wx@DH?QKuTfxcj_GH<:enG>U?R_wmO2k>3oV28aw\>g70=>89HmwOlTNEs=s9, disco$
1542118075: New connection from 192.168.X.X on port 1883.
1542118075: New client connected from 192.168.X.X as xUG2<nmDF\`UJgUGvMQ52?UnSc:NpmWpJobVTWjZ:A6D0K[vil$
1542118076: Socket error on client pi-mqtt-gpio-e0ec1afe8b74758cff5fbf591d89f55a6f042a31, disconnecting.
1542118081: New connection from ::1 on port 1883.
1542118081: New client connected from ::1 as pi-mqtt-gpio-e0ec1afe8b74758cff5fbf591d89f55a6f042a31 (c0, k6$
1542118300: New connection from ::1 on port 1883.
1542118300: New client connected from ::1 as pi-mqtt-gpio-e0ec1afe8b74758cff5fbf591d89f55a6f042a31 (c0, k6$
1542118486: New connection from 192.168.X.X on port 1883.
1542118486: New client connected from 192.168.X.X as bC6vj`WtqNxaiJNI>AtjX;7JV\4eO]58`tnQKL<3j;eKV:TTKP$
1542118894: Saving in-memory database to /var/lib/mosquitto/mosquitto.db.
1542119081: New connection from 192.168.X.X on port 1883.
1542119081: New client connected from 192.168.X.X as Mt@h8LlbHHm^RIr^iwI;s>mS8QQOdXM8CMaKjDnr\bG52@c[wl$
1542120695: Saving in-memory database to /var/lib/mosquitto/mosquitto.db.
1542122117: New connection from 192.168.X.X on port 1883.
1542122117: New client connected from 192.168.X.X as 4jevmrQwDb9n4AXCp2sVBD (c1, k60).
1542122117: New connection from 192.168.X.X on port 1883.
1542122117: New client connected from 192.168.X.X as tq[U<P>hrU]uU8GSdnKf@WP]KYtW7;fklH7hX5GRZu>6mUIXKT$
1542122496: Saving in-memory database to /var/lib/mosquitto/mosquitto.db.
1542122803: mosquitto version 1.3.4 terminating
1542122803: Saving in-memory database to /var/lib/mosquitto/mosquitto.db.

-> Socket errors may appear because of some home assistant config changes (deleted MQTT integration, reboot, added it again, reboot and so on …)

I don’t want to get you off track but want to make sure you saw these.


1 Like

Hey RobDYI,

thanks for your feedback!
Thing is, the GPIOs which I wan’t to use are the one of the pi2.
So, it’s not about switching the internal GPIO’s. That just works fine :stuck_out_tongue:

Setup is like this:

Pi3 (hass.io)
Pi2 (MQTT Broker, MQTT Server/Client(GPIO-expose-Scipt))

Best regards

From what I can see, none of your scripts send a message on startup to indicate that they are available, so the simplest thing would be to remove the availability topic from the HA configuration.

Alternatively, you could change the scripts to send a message on startup and set a will message.

1 Like

That’s it, thank you very much !!!

1 Like

I know I’m a bit late, but yes, HA thinks the switches are unavailable because the availability_topic in HA’s config.yaml should be “pibox/switch/status”. The alternative solution is indeed just to remove the availability_topic config line entirely to disable that functionality.

The default availability payloads are incompatible by default, so if you want to use that functionality then you’d also have to change the pi-mqtt-gpio config to output different status payloads. I’m not sure whether you can assign two different payloads to payload_not_available on HA at the moment (because pi-mqtt-gpio has three states), so you’d need to change the pi-mqtt-gpio config’s mqtt section to include:

mqtt:
  ...
  status_payload_running: online
  status_payload_stopped: offline
  status_payload_dead: offline

Hi Flyte, hope you don’t mind me replying to this topic with a different problem, but its very close to my difficulties, BTW pi-mqtt-gpio has cured my delay problems,and all inputs and outputs work fine, brilliant!. But first, and I haven’t tried this yet, are you saying that if I run pi-mqtt-gpio on the same pi running HA that it cant use the GPIO’s? or is it OK if I don’t use rpi-gpio in the HA configs?

Anyway my current problem is that I cant see how to setup several of the same sensor (DS18B20) using your sensor_modules and sensor_inputs. I can get one sensor to work fine. Could you supply a config I could look at with 2 or more ds1820b sensors in?

Thanks in advance for any help.

See the warning at the bottom of this page.

Note that a pin managed by Home Assistant is expected to be exclusive to Home Assistant.

But I guess if you’re not using the HA GPIO integration it should be ok.

Excellent, that’s what I was hoping! Thanks for the quick answer.

Have you any ideas re the pi-mqtt-gpio config for multiple similar sensors?