How To Use Meross Smart Devices As Cheap Offline IoT
When it comes to smart devices, Meross has been my choice for multiple projects due to their excellent construction and very competitive prices. The biggest problem with these devices, as with many other readily available smart devices is that any commands you send will go over the internet, to some remote server, only to come back to your local network. While there are benefits to using this approach, generally I think relying on a third-party server for your hardware device to function is not ideal. All security implications aside, if one day the company shutdowns or if there is some sort of network failure between you and the server, everything will stop working.
Disclaimer: This post contains affiliate links. As an Amazon Associate, I earn from qualifying purchases.
There are several advantages of using a local server with your smart devices, such as higher reliability as a result of fewer points of failure, complete control over the security of your smart home, and more flexibility. In my case, I used Home Assistant to control all the devices without the need for any additional external service.
Before getting started, there are a few topics that must be covered to understand what these smart devices are doing when they are used normally. Once that is clear, the method for replacing this with our local version will make more sense.
Note: When this article was originally published, all Meross devices needed to be connected via the cloud. There was no way to use them offline in any situation. However, they now offer some devices that support HomeKit, which is natively an offline protocol. Check them out here, anything labelled with HomeKit will work offline and if you use Home Assistant it can be used as a HomeKit controller for free.
Table of Contents
- What is MQTT?
- Setting up the MQTT server
- Getting Meross Devices to Work Offline
- Controlling Meross Devices from Home Assistant
- The Home Assistant Plugin
- Closing Thoughts
What is MQTT?
According to mqtt.org, "MQTT is a machine-to-machine (M2M)/"Internet of Things" connectivity protocol". In other words, it is a protocol designed to allow various devices that are scattered throughout a network to communicate with each other. The most significant advantage of MQTT over alternatives is that it is specifically designed to be lightweight and easy to scale between the most straightforward implementation up to the most complex.
The fundamental way this works is with a publish/subscribe system in which clients will subscribe to topics that other clients are publishing to while having its own set of topics that it is publishing messages to. The role of the server in MQTT is just to allow communication between clients. It does not have an active role in the messaging other than acting a delivery network between all the clients.
Normally each client will connect to the server using it's IP address (or domain name, if DNS is set up), a username, and a password. The client will authenticate providing it's client name as a token for the server to use as a representation of this connection. There are several other ways MQTT clients can authenticate with the server. In the case of these devices, no password will be used for authentication, relying instead on an SSL certificate to secure the connection. Unfortunately, there is minimal opportunity to configure the MQTT server since the technique shown here only works with these exacts settings. If you find a different way to set up the server that also works with the Meross devices, please comment with what you did!
Setting up the MQTT server
Typically the setup a server is relatively straight forward, and the default settings are more than enough to get started. Unfortunately, Meross devices seem to require very particular settings to connect to the server properly. Luckily I've managed to find the settings that will work with all of the machines I've tried so far.
Installing Mosquitto MQTT
The server I used is also one of the most popular message brokers that use MQTT, Eclipse Mosquitto. It supports so many different features, but we only need a basic installation to run these devices offline. Head over to mosquitto.org/download to download the latest version for your operating system. Under Linux, simply using the package manager should work well, but follow the instructions on the download page to get the latest information.
Creating a Certificate Authority (CA)
Meross devices require the MQTT server to support SSL. For whatever reason, they haven't locked them to their own server's root certificate, which is good for us because it means we can create our own. Start by getting shell access to the system that will be used as the MQTT server and then run the following commands:
openssl genrsa -des3 -out mqtt_ca.key
It will prompt you for a passphrase, which you should create to keep your SSL certificates safe. Just make sure to write this down!
Next, we will create a root certificate using the key we just created:
openssl req -x509 -new -nodes -key mqtt_ca.key -sha256 -days 1825 -out mqtt_ca.crt
That command will prompt you asking many questions, but the answer to them is not that important. Try to make the answers somewhat accurate because later if you are looking at these certificates, it will be useful if you can recognize it using the listed information. There should now be two files in your working directory, mqtt_ca.key and mqtt_ca.crt. These two files allow you to start issuing certificates as your own certificate authority just like the big companies do - the difference being that they have their root certificate (our mqtt_ca.pem) installed on almost every device in the world by default.
Since you aren't a big company doing this, we will need to install our root certificate onto the devices that are going to be connecting to the server. That's why later the configuration file has a spot to specify your CA certificate.
Creating SSL Certificates
Now that you have a CA setup, you can start issuing SSL certificates to be used by the server. The server must have a certificate that's tied to the CA we created because that's how the clients will verify they are connected to the right place. To generate the certificate for use with the server, first create a private key:
openssl genrsa -out mqtt.key 2048
Then we generate a Certificate Signing Request (CSR):
openssl req -new -key mqtt.key -out mqtt.csr
Once again, you will be getting all of the same questions as before, but now you can answer with whatever you want because this certificate will only identify this specific MQTT server. There is one question that you MUST answer correctly though: the Common Name. In the case of this guide put the IP of the system that will be running the Mosquitto server. If you don't put the IP as the common name, you will get SSL errors!
Now we are almost done, we just need to create the certificate file by running the following command that makes use of all the files we've created til now:
openssl x509 -req -in mqtt.csr -CA mqtt_ca.crt -CAkey mqtt_ca.key -CAcreateserial -out mqtt.crt -days 500 -sha256
Now you should have the following files: mqtt_ca.crt, mqtt.crt, mqtt.key. If all of these files exist you are ready to configure the Mosquitto server.
To configure Mosquitto, simply copy the following file and modify it to fit your setup:
port 8883 require_certificate false use_identity_as_username false allow_anonymous true capath /etc/mosquitto/certs # replace with your CA Root and server certificate and key paths cafile /etc/mosquitto/certs/mqtt_ca.crt certfile /etc/mosquitto/certs/mqtt.crt keyfile /etc/mosquitto/certs/mqtt.key tls_version tlsv1.2
I simply created a folder within the /etc/mosquitto directory called "certs", and I copied all three of the files created in the previous section using mv. The configuration file is relatively basic and should be located in /etc/mosquitto/mosquitto.conf under Debian based Linux. For other platforms check the Moquitto documentation for the location of this file, though it shouldn't be too different. Finally, run service mosquitto restart to reload the service and refresh the configuration.
That's it! The MQTT server is set up and ready to go. Now we just need to configure our devices to be able to connect to the server we just setup.
Getting Meross Devices to Work Offline
This part is the real challenge. Well, it would be if Meross-Powermon didn't exist. It is specially made to be used with the wall plug type devices, but it will work for any Meross device as long as you only use it to configure it. The tool is relatively straight forward to use, and the readme on the repository provides excellent instructions on how to use it. I was personally trying to use it on my Macbook, and I couldn't get it to work correctly in its default state (by using the WIFI commands).
If this happens to you as well, just connect your laptop directly to the WiFi network of the Meross device (it should be Meross_ followed by random letters and numbers) and run the setup commands as if the script had found it. Note that the monitor command may not work; this is fine as we will not be using this tool after the initial configuration.
Setting up devices using Meross-Powermon
Getting things set up with the tool is fairly straight forward. Download the repository, unzip the files to some location, and open up a terminal window to start running commands. Most of these commands need to be run as root so that the script can manage the WiFi adapter. In your terminal run the following as root:
./meross init --user USER --ssid SSID --password PASSWORD --interface IF
Replacing all of the parameters with your own. User is the system user that you want to own the config file, SSID and password and the credentials to the WiFi network, and interface is the name of the network interface that will be used to connect to the device's network.
Switch over to a regular terminal as the user you specified in the last command and run the following:
./meross init --server --port 8883 --ca-cert /path/to/cert/mqtt_ca.crt
Specify the IP address of the MQTT server and the path to the CA certificate we generated earlier. You might need to copy it over before this step. Once the command executes the config file will be created, and the only thing left to do is to add devices to it. Go back to the previous terminal and as root run:
Replace the name with whatever you want to call this device. Once you run this command, the "Meross_" WiFi network should no longer be visible, and you should see the device reset. With any luck, it should now be connected to the MQTT server. You can tell that it's connected to your network with the status light (if the device has one) or by going to the system running the Mosquitto server and checking the logs using:
service mosquitto status
If you see connections in the log, that means it's working! If not then try to read over the setup again ensuring every step is correct, and that the device can reach the IP address of the server (try connecting another MQTT client to it).
Once your device(s) are set up to connect to your WiFi network and MQTT server, that's it! Your Meross device is now connected to your MQTT server without needing any access to the internet. Now you have no way to control it, of course, and that's what we will cover in the next section.
Controlling Meross Devices from Home Assistant
Since MQTT devices communicate using a publish and subscription model, Home Assistant needs to know what topics to connect to be able to control them. Unfortunately, there is no way to do this out of the box. Luckily, I have created a plugin that will interface with Meross devices that are on a local MQTT server. The plugin makes use of the wonderful MerossIot library; however, I have made a fork of version 2.x.x of MerossIot, which will work better with this use case.
My fork can be found at github.com/woder/MerossIot. It uses an older version of the MerossIot library because newer versions have a focus on connecting to the official Meross servers, which is not what we are trying to do here. I have not tested the fork with every device Meross sells, but when they came out with the small USB humidifier, it was simple enough for me to modify the library to support it as well.
Once you download the repository, copy it to the system where you run Home Assistant. In my case, I run Home Assistant within a VM using the supervised install option. The specifics of this step will vary from setup to setup, but the idea is the same. Copy the forked MerossIot library to the python environment that Home Assistant is using. Then run python setup.py from the top-level directory within MerossIot. This will install the library to the virtual environment, allowing the Home Assistant plugin to access it.
The Home Assistant Plugin
Once the library is installed, the plugin can be downloaded from github.com/woder/meross_offline. The plugin allows for the config we generated within Meross-Powermon to be used in Home Assistant. Any devices you setup using Meross-Powermon will be in the config file that the plugin uses. The plugin will then add all of these devices to the entity registry, allowing them to be controlled through the UI. One thing to note about this plugin is that I'm very sure it has a lot of opportunities to be better - it's my first real attempt at writing a component and it was written with my specific needs at the time in mind. If you spot obvious improvements drop me a comment, I'll do my best to make it better!
Installing the Plugin
To install the Meross_Offline plugin simply download the repository from the github link and place all of the downloaded files into a folder located at [homeassistant_install_DIR]/custom_components/meross_offline. The plugin will now be installed as a custom component.
Configuring the Plugin
Unlike most Home Assistant components, Meross_Offline doesn't have any configuration under configuration.yaml because it uses the configuration file generated by Meross-Powermon, saving time while integrating the two. The plugin comes with a config.json file that contains an example setup that can be used as a reference. The only field that must be changed from how it is when it is first generated is the addition of a "friendly_name" field which is used by the plugin to determine what the device's entity name should be.
The config.json file is at the root of the git repository. Copy this file to the main Home Assistant directory and rename it "meross_config.json" which will allow the plugin to find it. Finally copy the devices section from the Meross-Powermon output to this config file, adding the "friendly_name" field in the same spot as in the example file.
Now you have Meross devices that can run entirely offline while also being integrated into Home Assistant! While I was trying to get this to work myself, I was very frustrated by how difficult it was to obtain any information about making these devices work offline. These devices are excellent because they are readily available while also being so much cheaper than more prominent brands. Still, the lack of offline capability is a deal-breaker for me - so after playing with it for long enough, I eventually managed to make it work. Since it was such an adventure, I thought I would try and make it easier for anyone else trying this out. Let me know in the comments if you did this! Did it work? Any major problems?