Using XMPP with Raspberry Pi GPIO

Hi again. Though I have probably successfully created an XMPP server in the Terminal (with Prosody), are there any example of XMPP scripts using RPi GPIOs for Home Assistant? Been searching for XMPP, but still haven’t got a clear idea to integrate it with GPIO and Home Assistant (I know it’s avaliable as one of the Integrations).

It seems like the XMPP integration can only send messages, not receive.
I guess you could write a Python script that would relay XMPP messages to MQTT and set up your automations in Home Assistant using the MQTT trigger.

Well, so far I found this video if to show that XMPP can be used as home automation in Raspberry Pi, but no tips in how to create it

https://www.youtube.com/watch?v=od2aXGTpCEA

If the Python script has a relation with MQTT (to relay XMPP messages), does that mean the analyzer will take into account of the MQTT part too if I used network protocol analyzer on the XMPP one? I’m trying to compare IoT protocols separately which includes XMPP and MQTT (sorry bad english).

XMPP is an instant messaging protocol. As far as I know, it’s not widely used for home automation.
I thought you wanted to be able to trigger some actions by chatting to a bot. If this is supposed to be communication between autonomous devices in your local network, I’d just go with MQTT.

I’m not sure what you mean. I would write the script so that it would listen for messages on XMPP and send them to a MQTT topic and vice versa.
This means that if you listened to all XMPP messages, you’d see the input from the user sent via XMPP and responses from Home Assistant (if any) relayed from MQTT to XMPP by your script.
If you listened to all MQTT messages, you’d see input from the user relayed by your script from XMPP to MQTT and direct MQTT responses from Home Assistant (if any).

Maybe you should tell us what you want to use this for (e.g. I want to be able to control my lights from my mobile phone). There might be better solutions to your problem than XMPP. This look a bit like an XY problem.

If you just wanted to compare XMPP to MQTT, then I’d say MQTT support in Home Assistant is very good and XMPP support in HA is basically non-existent (the XMPP integration can only send messages / notifications to people).

I’d use NodeRed to take the messages from XMPP and translate them to MQTT if the intention is to be able to trigger things from chatting to a bot.

1 Like

I thought you wanted to be able to trigger some actions by chatting to a bot. If this is supposed to be communication between autonomous devices in your local network, I’d just go with MQTT.

Yeah, this’d be my intention, though as usual, it’ll also include things like sensors or such.

Maybe you should tell us what you want to use this for (e.g. I want to be able to control my lights from my mobile phone). There might be better solutions to your problem than XMPP. This look a bit like an XY problem.

Well, I’m assigned with a project to compare the performances of several smart home IoT protocols, XMPP and MQTT are among them. So I was thinking about making an XMPP one being purely XMPP, and before I make it, I tried to make sure if using MQTT to relay XMPP messages would not get MQTT involved in what’s supposed to be the XMPP performance part, as I already did an MQTT configuration one before.

XMPP is designed primarily as an instant chat protocol, MQTT is designed primarily as a messaging protocol. Both can be used to carry IoT messages, but MQTT is more supported by libraries and software, and is designed to have less overhead than XMPP which is why it is largely preferred.

Yeah I know, but my project assignment requires using both to compare.

OK - well on a default install of NodeRed on a Raspberry Pi:

bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)

You will have access to nodes for XMPP and Nodes for GPIO, this is going to be least complicated way of being able to receive an XMPP message and then do something with the GPIO based on the message contents.

Presumably you already set up an XMPP server, if you haven’t - I recommend OpenFire. DO NOT put the server on the Pi though.

OK, so far I’ve created this in Node-RED (a further change from the previous one), but I’d show you one for a GPIO relay, and one for a sensor.
image

The XMPP node is the “node-red-node-xmpp” you install right? I’d want to know where to add the XMPP and MQTT nodes after.

Yes.

In both cases you would have the XMPP or MQTT node as an input (probably) and then after whatever action has been performed with GPIO or whatever, you would probably want to output a confirmation message.

For example if you have a switch in Home Assistant that publishes a desired state to a command topic on MQTT, after you have turned on or off the GPIO, you would normally want to publish the state of the GPIO back to MQTT on the state topic, so that Home Assistant updates it’s state. If you don’t do that - then Home Assistant will turn the switch on, and after a second or so, because it hasn’t received a state update to acknowledge that the switch was turned on, Home Assistant will assume the command failed, and turn the switch back off, in it’s state database and on the UI (it won’t actually send the off command to MQTT).

I have not personally done anything in NodeRed with XMPP, nor do I have any XMPP server anymore - the point of that went away when Google Talk was killed off. So if you want any help with XMPP in Node Red, you are going to have better luck (possibly) looking on YouTube for other people who have already done it.

I’ve been looking on YouTube (more obscure results, harder to get what I’m looking for) or other places before, I asked when I hit a dead end. For the node part (I know you said you haven’t done it), you mean the XMPP node connected to the switch along with event_state (such as Light) or such? And if MQTT is an input, it’ll be connected to the switch part too? And OpenFire is the one that sends the XMPP message within the node I guess (but not put the server on Pi?).

So, anyone else got other ideas?

XMPP IN linked to a function node so you can parse the message and do something with it - eg:

var parts = msg.payload.split(" ");
msg.onoff = "";
switch (parts[0].toLowerCase()) {
case "switch":
  msg.action = "turn";
  break;
case "turn":
  msg.action = "turn";
  break;
case "activate":
  msg.action = "turn";
  msg.onoff = "on";
  break;
case "deactivate":
  msg.action = "turn";
  msg.onoff = "off";
  break;
default:
  return null;
}
if (msg.onoff == "") {
  msg.onoff = parts[1].toLowerCase();
}
msg.device = parts[2].toLowerCase();
return msg;

From that point you will know if you want to turn on or off a device based on the content of the XMPP message, then you can use a switch node to change where the flow goes based on whether msg.onoff is on or off.

So if the message was something like turn on GPIO2 then msg.action is turn, msg.onoff is on and the device msg.device is gpio2

That’s the basics of it.
As far as I know the only way to send that back to Home Assistant though would be on MQTT so you would need to publish something back like:

topic: picontrol/state/gpio2
payload: on

And have the MQTT switch in Home Assistant with something like:

switch:
  - platform: mqtt
    name: GPIO2 Control
    state_topic: picontrol/state/gpio2
    command_topic: picontrol/control/gpio2

You would then have an MQTT IN ( topic: picontrol/control/+ ) node in the same flow and to get the device information you would do something like this in a function node:

var parts = msg.topic.split("/");
msg.device = parts[parts.length-1].toLowerCase();
msg.onoff = ((msg.payload.toLowerCase() == "on" or msg.payload == 1) ? "on" : "off");
return msg;

This can now be fed in to exactly the same switch node input as the XMPP messages.

Once you have turned on or off the GPIO then you would post the message back to Home Assistant via MQTT - so something like this in a function node:

msg.topic = "picontrol/state/" + msg.device;
msg.payload = msg.onoff;
return msg;

Feed that directly in to the MQTT OUT node, leaving all the settings to set by msg

OK thanks for the further help, though I wonder where do you get to know more about building this. Is the node built like this (for an on/off)? Where did I got wrong here?

Does this only use 1 switch (and is only about msg.onoff)? And does the switch lead into call service node which I use the existing GPIO entity? And does picontrol/control/+ is written as such where + means generally?

And where is the

topic: picontrol/state/gpio2
payload: on

part located? On the mqtt section in configuration.yaml (the configuration wasn’t valid that way for mine)?

I have questions…

  1. Why are using Home Assistant to do anything with Pi’s GPIO pins? There are GPIO nodes in Node Red, if you are doing it with Home Assistant, then I’m not sure what the point of the XMPP is?

  2. picontrol/control/+ the + means some other word can appear here. We use this so all the GPIO switches are using the same topic.

Ignore this bit:

topic: picontrol/state/gpio2
payload: on

Because I gave you the actual code you need to use at the bottom of my post:

msg.topic = "picontrol/state/" + msg.device;
msg.payload = msg.onoff;
return msg;

And I gave you the code you need in configuration.yaml:

switch:
  - platform: mqtt
    name: GPIO2 Control
    state_topic: picontrol/state/gpio2
    command_topic: picontrol/control/gpio2

So the part of using Home Assistant to do with GPIO pins is just wrong then, how about this node configuration then? (the GPIO node is said to only accept 0 or 1 input)

What’s the 2nd output of the xmpp node? Also are the MQTT nodes connected to the xmpp one or each other (input and output)?

Right so in that case swap the switch node probably wants to acting on msg.device then instead, so that the message is routed to the right GPIO node. The code in the XMPP and MQTT functions would be changed slightly to something like this:

XMPP Node:

var parts = msg.payload.split(" ");
msg.onoff = "";
switch (parts[0].toLowerCase()) {
case "switch":
  break;
case "turn":
  break;
case "activate":
  msg.onoff = 1;
  msg.device = parts[1].toLowerCase();
  break;
case "deactivate":
  msg.onoff = 0;
  msg.device = parts[1].toLowerCase();
  break;
default:
  return null;
}
if (msg.onoff == "") {
  msg.onoff = parts[1].toLowerCase();
  msg.onoff = (msg.onoff == "on" ? 1 : 0);
  msg.device = parts[2].toLowerCase();
}
return msg;

and the MQTT function:

var parts = msg.topic.split("/");
msg.device = parts[parts.length-1].toLowerCase();
msg.onoff = (msg.payload.toLowerCase() == "on" ? 1 : 0);
return msg;

Both the XMPP function and the MQTT function would then link to the switch node, but also to another function node to prepare the MQTT out message:

var topic = "picontrol/state/" + msg.device;
var payload = (msg.onoff ? "on" : "off");
msg = {};
msg.topic = topic;
msg.payload = payload;
return msg;

Feed that in to the MQTT out node.

Remember to figure out what is going on and that things are working as they should, drop the debug node in there, set it to complete msg object, instead of the default of just showing msg.payload. And wire any node you need to know what is happening at that part of the flow - to the debug node.

So far the node is structured like this, what should be changed again? (and what’s the 2nd link on XMPP in):

For this flow, what should be filled on the “Buddy” section of the XMPP node? And what’s filled on the Buddy will be added as contact or such in applications like Spark IM to chat with?

So many things wrong here…

The MQTT In Function wants it’s output linked to the inputs of the Switch AND the MQTT Out Function.
The XMPP Function wants it’s output linked to the Switch Node AND the MQTT Out function.
Right now you have the XMPP Out Function leading in to the Output of the MQTT In Function which is impossible, and the IN of the Switch and the IN of the MQTT Out function linked together, which again is impossible.

Next you should have a GPIO node linked to EACH output of the Switch Node, since you said you can’t use msg to tell the GPIO node which GPIO to control, you have to enter it in to the node itself, so you need one for each switch output.

You don’t yet have the MQTT nodes connected to an actual MQTT server, or if you do then it isn’t working. You don’t yet have the XMPP node connected to an actual server either.

The GPIO out node is “not available” probably because Home Assistant is connected to the GPIO ports - judging by a previous post you showed.

I have never used XMPP in Node Red, I have no idea how to set up the node, or what information you get from it. You would be best advised to read the documentation on it.

The Buddy field is the id of the buddy or room you want to receive messages from.

Incoming messages will appear as msg.payload on the first output, while msg.topic will contain who it is from.

The second output will show the presence and status of a user in msg.payload. Again msg.topic will hold the user.