HELLO EVERYONE!!!!
After many struggles I have managed to get websockets working with mosquitto on my RPi 2 (Thanks element 14 for this baby).
I decided to start from scratch, so I wiped the SD card and reinstalled Raspbian. I honestly had given up on the idea of using websockets, but I couldn't find any recent tutorials that didn't include enabling websockets so I decided to give it one last shot. This particular install tutorial was helpful, although there are number of sites with similar information, it was most helpful when it came to adding in user access. It has some problems because it's not up-to-date with the latest package changes, so just follow my instructions. I just wanted to give them credit.
Alright. So here's how you get it working. You need to install a variety of packages but in the end you will be very happy.
Make sure your system is updated, it's always good to start with:
sudo apt-get update
The first thing you are going to want to do is install OpenSSL. mosquitto uses this to handle communications over websockets. Once this is installed you should also install cmake, if you don't already have it. You'll need this to build mosquitto and websockets.
sudo apt-get install openssl-dev sudo apt-get install cmake
Next, you want to install websockets. This is tricky because the most recent (1.4) is busted. See this discussion on stackoverflow for more info. The bottom line is that you need to use version 1.3 to make this work.
wget https://github.com/warmcat/libwebsockets/archive/v1.3-chrome37-firefox30.tar.gz tar xvzf v1.3-chrome37-firefox30.tar.gz cd v1.3-chrome37-firefox30 mkdir build cd build cmake .. make sudo make install
That should do it for libwebsockets. The folder name for your tar files usually takes on the filename, but if it doesn't, just ls into your source directory and you should find the actual name of the folder, just cd into that folder at line 03 and continue with the rest of the commands.
Now, we have to install a support package called uuid-dev to complete the mosquitto installation in the next step.
sudo apt-get install uuid-dev
The next step is to install mosquitto with websockets enabled. This, like libwebsockets, must be built from source.
wget http://mosquitto.org/files/source/mosquitto-1.4.tar.gz tar xvzf mosquitto-1.4.tar.gz cd mosquitto-1.4
At this point you have to edit the config.mk file. You will look for the line, "WITH_WEBSOCKETS:= no" and change it to read, "WITH_WEBSOCKETS:= yes". I like to use nano, but you can use vi or whatever. CTRL+W helps finding things quickly in nano.
nano config.mk
Alright, now it's time to build and install mosquitto!
make sudo make install
Hopefully everything is going smoothly up to this point. mosquitto has a configuration file that holds some basic information to keep the server running. The installation comes with an example configuration file that is well commented and we're going to copy this file over and use it to build our own. It's actually not necessary and you could simply create your own config file with the upcoming lines, but it might be helpful to read through the comments to get an idea what is possible.
sudo cp /etc/mosquitto/mosquitto.conf.example /etc/mosquitto/mosquitto.conf
Now open the new config file in your favorite text editor (nano for me) and you must add the following commands (please read on before doing this if you are unsure):
sudo /etc/mosquitto/mosquitto.conf listener 1883 listener 9001 protocol websockets password_file mosquitto.pwd
You may be wondering where to exactly to put this in your config file. When you open up the config file look for the area called "Default listener". That's where I put line 02, I changed it from "port 1883" to "listener 1883". This may not actually be necessary, I'm not sure, but it worked for me.
Line 03 and 04 will go under the section called, "Extra listeners". You should see a line that reads: "#listener". You can remove the hash (uncomment the line) and add in 9001. This means that mosquitto should listen on ports 1883 and 9001. The latter being the websockets port. A few paragraphs below the listener line where it reads, "Choose the protocol to use when listening.", you can add line 04. Just uncomment "#protocol mqtt" and change it to match line 04.
You can add in the password access line under the section that reads, "Default authentication and topic access control". Uncomment the line, "password_file" by removing the hash in front and type in line 05.
That's it for the config file. Just save the file and exit out of the text editor. Now create the user that will be allowed access to mosquitto. This will protect it from unauthorized access across the network. This is absolutely not necessary because mosquitto allows anonymous login, but it's always good to limit access. Make "username" your preferred name. You'll be prompted to enter a password, too.
sudo mosquitto_passwd -c mosquitto.pwd username
The next step is to create a link because websockets is actually installed in a different directory from where mosquitto expects to find it.
sudo ln -s /usr/local/lib/libwebsockets.so.4.0.0 /usr/lib/libwebsockets.so.4.0.0
There is another workaround for this, but I didn't try it this time around so I'm not sure if it truly, truly works. Back when you installed websockets, you could have use this cmake command in place of the one at line 06:
cmake .. -DOPENSSL_ROOT_DIR=/usr/bin/openssl
As I said, I didn't try it this time around, so I don't know if it really solves the problem, but I have tried it in past attempts and it seems like it corrected the issue.
We're almost there! The next step is to enable IPv6 on the Raspberry Pi. I was getting an annoying error whenever I ran mosquitto: "Warning: Address family not supported by protocol". Turns out it was because IPv6 was not enabled. It's way easy to correct this problem. First, turn IPv6 on, then go into your /etc/modules file and add the line "ipv6" to the end of the file. IPv6 will now be enabled at boot.
sudo modprobe ipv6 sudo nano /etc/modules
The last thing you need to install is Paho JavaScript client. This is the Javascript package you'll use to help you communicate with your mosquitto mqtt server over websockets.
wget http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt.javascript.git/plain/src/mqttws31.js sudo cp /var/www/mqttws31.js
Line 02 assumes that you have a webserver already installed. I followed this tutorial (this appears to be down right now but it's cached here) to get lighttpd/mysql/phpmyadmin running on my RPi2. I suggest you follow it, it works every time. Ignore the last part about making it work over TCP/IP. Oh, also note that you really don't need all of the extra PHP packages they suggest, just pick and choose the ones you require. Anyway, all I did was copy the Javascript library to the web server directory so we can call it in our HTML file.
Wow, that's it for installation. The next step is to create the test file. In order to do this, we're going to use Paho's test Javascript code. So go ahead and create an HTML file in your web directory:
sudo nano /var/www/mosquitto.html
Now you'll want to paste in the following and note where it says username to put the username you created earlier and the password, too.
<html>
<head>
<script src="mqttws31.js"></script>
<title>mqtt status</title>
</head>
<body>
<div id="status">connecting...</div>
</body>
<script>
// Create a client instance
client = new Paho.MQTT.Client('255.255.255.255', Number(9001), "clientId-"+ Math.random());
// set callback handlers
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;
// connect the client
client.connect({
onSuccess:onConnect,
userName: "username",
password: "password"
});
// called when the client connects
function onConnect() {
// Once a connection has been made, make a subscription and send a message.
var status = document.getElementById("status");
console.log("onConnect");
status.innerHTML = "onConnect";
client.subscribe("/World");
message = new Paho.MQTT.Message("Hello");
message.destinationName = "/World";
client.send(message);
}
// called when the client loses its connection
function onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
var status = document.getElementById("status");
console.log("onConnectionLost:"+responseObject.errorMessage);
status.innerHTML = "onConnectionLost:"+responseObject.errorMessage;
}
}
// called when a message arrives
function onMessageArrived(message) {
var status = document.getElementById("status");
console.log("onMessageArrived:"+message.payloadString);
status.innerHTML = "onMessageArrived:"+message.payloadString;
}
</script>
</html>
Take a look at line 17: Be sure to enter your RPi's network IP address. In my case, I am using the assigned internal router IP. You can find out your IP address using ifconfig. Also note that "clientId" can be anything you want and you don't need to generate a random number if you don't want to. I think this is mainly for logging purposes, it keeps track of who is connecting to mosquitto.
It's time to turn on mosquitto. If everything has been setup correctly, this should be flawless. I have run into some problems when I don't run this while in the /etc/mosquitto directory. I don't know why, but when I try to load it from a different directly, it has a problem running the password file.
cd /etc/mosquitto mosquitto -c /etc/mosquitto/mosquitto.conf
Now, go ahead and direct your web browser to the IP address you entered above along with the name of the HTML file. For example: http://255.255.255.255/mosquitto.html. You should see a "Hello" message appear. The script subscribes to /World and then sends "Hello". When mosquitto receives the message, it pushes that baby to all subscribers and it shows up in your browser.
Yes, this takes a lot of trial and error, but it does in fact work. The next step would be to configure mosquitto as a service that starts automatically but I'm having a little bit of trouble with the init.d files I've found online. I'll have to get back to everyone on that once I've sorted it out. This has really set me back a bit, but I'm glad it's all sorted out. I can finally move on with my project!
Top Comments