OpenHAB Controller, MQTT Broker and Gateway all in one machine.


  • Hardware Contributor

    Good evening guys, please inform me if my method/thinking is incorrect on the following confusion.

    At the moment what i have setup is a OpenHAB Controller running on a raspberry pi which is also running a MQTT Broker (Mosquitto). This is all working nice and smoothly. I also have a file called MQTTController.cpp installed, this is acting as a Gateway for the sensor nodes to communicated to the controller through. This is also working perfectly, however because it is a very basic C++ Program, its not utilizing any TCP/IP methods and just using the standard RF24 Library to use their nRF24L01 radios and therefor it is limited to 6 radios at any one time. I need more 😞

    So, i'm now trying to find a software solution (Gateway program) to install onto the Pi in place of my current MQTTController program so i can use more than 6 radios. I have looked all through the Raspberry repo from mysensors and i can't find a gateway file/program that talks through Mosquitto/MQTT.


  • Hardware Contributor

    Am i being a silly fool and thinking that the gateway needs to connect to the controller through MQTT when actually a 'MQTT Gateway' on here is a gateway that is connected to the controller via a nRF24L01 module with the sketch holding the MQTT program itself.

    Because i have Mosquitto running on the RaspberryPi that the controller is running on, could i just now install the raspberryPi gateway files, direct it to Mosquitto and then the sensors will communicate with the gateway program (on the same Pi), the gateway then sends it onto a Mosquitto/MQTT topic which OpenHAB then reads and publishes as it needs to?


  • Hardware Contributor

    Also, could someone confirm to me what role the NodeJsController.js has within the Pi please. From reading the documentation regarding this on your github tree, i have come to the conclusion that the NodeJsController.js is playing the same role as my current Mosquitto(MQTT) and MQTTController.cpp file together (receiving the data, sending it to OpenHAB). While that would be some what a step in the right direction, it would get me no father and actually just limit me to using arduino nodes since it would only be taking data from RF modules, where as having a MQTT Broker/protocol on board it would mean that i could connect different types of protocols all the way through my home automation. Please correct me if i'm in correct.


  • Mod

    @samuel235 There are a few different setups possible to communicate with a MySensors network (a bunch of MySensors nodes):

    • MQTT ethernet gateway running on Arduino (works as MQTT client, included with MySensors) -- ethernet connection to Mosquitto -- OpenHab
    • MQTT ethernet gateway running on Arduino (works as MQTT broker, included with MySensors master branch, which is being phased-out) -- MQTT ethernet connection to OpenHab
    • Serial gateway running on Arduino -- serial connection to Raspberry Pi running a MySensors serial protocol to MQTT converter (my Perl script) -- Mosquitto -- OpenHab
    • Ethernet gateway running on Arduino -- ethernet connection to Raspberry Pi running a MySensors serial protocol to MQTT converter (my Perl script) -- Mosquitto -- OpenHab
    • MySensors Raspberry port running on Raspberry Pi directly connected to nRF24 radio -- <some missing MQTT conversion> -- Mosquitto -- OpenHab

    It seems like you are pursuing the latest option which, to my knowing, is missing an MQTT adapter.
    I personally don't have experience running MySensors directly on RPi, so I cannot help you with that.
    Better take the safe, best tested route and go for option 1. This configuration default for MySensors, so you won't have to take care of maintenance and have the benefit of a large support community.

    So, in short: Go for option 1, build a standalone Ethernet gateway (e.g. using an ESP8266) running an MQTT client and connect that to the MQTT broker.


  • Hardware Contributor

    Right, okay. If I'm honest, one of the reasons i wanted it to be using it on its own system is to get it off of the internal wifi/ethernet network. I suppose you're correct in advising to use option one. And i more than likely will do. Do you know if you can run this on a Arduino Mega without any code changes compared to running it on a nano? Even though i will end up working on this method today, i would like to just put the code of my MQTTController.cpp here for you to see if you would like to develop something for the last option (the one i was originally looking for). It seems pretty straight forward for even the likes of me, who is not a coder/developer/programmer. I have been working with it for a couple of weeks now and it seems pretty standard and simple. It starts the network, listens for data, reads the message, splits the message into separate topics, sends the topics out to mosquitto, mosquitto then takes the data and which topic it was on and passes it to OpenHAB (I think).

    #include <RF24/RF24.h>
    #include <RF24Network/RF24Network.h>
    #include <mosquittopp.h>
    #include <iostream>
    #include <ctime>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    // Constants that identify nodes
    const uint16_t pi_node = 0;
    const uint16_t sensor_node1 = 1;
    const uint16_t action_node1 = 2;
    const uint16_t sensor_node2 = 3;
    const uint16_t action_node2 = 4;
    
    const char* action_channel1 = "home/bedroom/light";
    const char* action_channel2 = "home/bedroom/";
    
    // CE Pin, CSN Pin, SPI Speed
    RF24 radio(RPI_BPLUS_GPIO_J8_15,RPI_BPLUS_GPIO_J8_24, BCM2835_SPI_SPEED_8MHZ);
    RF24Network network(radio);
    
    // Time between checking for packets (in ms)
    const unsigned long interval = 1000;
    
    // Structure of our messages
    struct message_action {
    	bool state;
    };
    
    struct message_sensor {
    	float temperature;
    	float humidity;
    	bool motion;
    	bool lightswitch;
    };
    
    // Mosquitto class
     class MyMosquitto : public mosquittopp::mosquittopp {
    	public:
    		MyMosquitto() : mosquittopp::mosquittopp ("PiBrain") { MyMosquitto::lib_init(); }
    		
    		virtual void on_connect (int rc) { printf("Connected to Mosquitto\n"); }
    		
    		virtual void on_disconnect () { printf("Disconnected\n"); }
    		
    		virtual void on_message(const struct mosquitto_message* mosqmessage) {
    			// Message received on a channel we subscribe to
    			printf("Message found on channel %s: %s\n", mosqmessage->topic, mosqmessage->payload);
    			
    			// Create message to send via RF24
    			message_action actionmessage;
    			if (strcmp((char*)mosqmessage->payload, "0") == 0) {
    				actionmessage = (message_action){ false };
    			} else if (strcmp((char*)mosqmessage->payload, "1") == 0) {
    				actionmessage = (message_action){ true };
    			} else {
    				printf("Unknown message: %s\n", mosqmessage->payload); 
    				return;
    			}
    			// Determine target node based on channel
    			uint16_t target_node;
    			if (strcmp(mosqmessage->topic, action_channel1) == 0) {
    				target_node = action_node1;
    			} else if (strcmp(mosqmessage->topic, action_channel2) == 0) {
    				target_node = action_node2;
    			}
    			
    			printf("Sending instructions to node %i\n", target_node);
    			
    			// Send message on RF24 network
    			RF24NetworkHeader header(target_node);
    			header.type = '2';
    			if (network.write(header, &actionmessage, sizeof(actionmessage))) {
    				printf("Message sent\n"); 
    			} else {
    				printf("Could not send message\n"); 
    			}
    		}
     };
     
     MyMosquitto mosq;
    
    int main(int argc, char** argv)
    {
    	// Initialize all radio related modules
    	radio.begin();
    	delay(5);
    	network.begin(90, pi_node);
    	
    	// Print some radio details (for debug purposes)
    	radio.printDetails();
    	
    	network.update();
    	
    	mosq.connect("127.0.0.1");
    	mosq.subscribe(0, action_channel1);
    	mosq.subscribe(0, action_channel2);
    	
    	while (true) {
    		// Get the latest network info
    		network.update();
    		printf(".\n");
    		// Enter this loop if there is data available to be read,
    		// and continue it as long as there is more data to read
    		while ( network.available() ) {
    			RF24NetworkHeader header;
    			message_sensor sensormessage;
    			// Have a peek at the data to see the header type
    			network.peek(header);
    			// We can only handle type 1 sensor nodes for now
    			if (header.type == '1') {
    				// Read the message
    				network.read(header, &sensormessage, sizeof(sensormessage));
    				// Print it out in case someone's watching
    				printf("Data received from node %i\n", header.from_node);
    				char buffer [50];
    				switch (header.from_node) {
    					case sensor_node1:
    						sprintf (buffer, "mosquitto_pub -t home/bedroom/temperature -m \"%f\"", sensormessage.temperature);
    						printf (buffer, "mosquitto_pub -t home/bedroom/temperature -m \"%f\"", sensormessage.temperature);
    						system(buffer);
    						sprintf (buffer, "mosquitto_pub -t home/bedroom/humidity -m \"%f\"", sensormessage.humidity);
    						printf (buffer, "mosquitto_pub -t home/bedroom/humidity -m \"%f\"", sensormessage.humidity);
    						system(buffer);
    						sprintf (buffer, "mosquitto_pub -t home/bedroom/motion -m \"%i\"", sensormessage.motion ? 1 : 0);
    						printf (buffer, "mosquitto_pub -t home/bedroom/motion -m \"%i\"", sensormessage.motion ? 1 : 0);
    						system(buffer);
    						sprintf (buffer, "mosquitto_pub -t home/bedroom/lightswitch -m \"%i\"", sensormessage.lightswitch ? 1 : 0);
    						printf (buffer, "mosquitto_pub -t home/bedroom/lightswitch -m \"%i\"", sensormessage.lightswitch ? 1 : 0);
    						system(buffer);
    						break;
    					case sensor_node2:
    						sprintf (buffer, "mosquitto_pub -t home/office/temperature -m \"%f\"", sensormessage.temperature);
    						printf (buffer, "mosquitto_pub -t home/office/temperature -m \"%f\"", sensormessage.temperature);
    						system(buffer);
    						// read other sensor data from node 2 here
    						break;
    					// add as many case statements as you have nodes
    					default:
    						printf("Unknown node %i\n", header.from_node);
    						break;
    				}
    			} else {
    				// This is not a type we recognize
    				network.read(header, &sensormessage, sizeof(sensormessage));
    				printf("Unknown message received from node %i\n", header.from_node);
    			}
    		}
    		
    		// Check for messages on our subscribed channels
    		mosq.loop();
    		
    		delay(interval);
    	}
    	
    	mosq.unsubscribe(0, action_channel1);
    	mosq.unsubscribe(0, action_channel2);
    
    	// last thing we do before we end things
    	return 0;
    }
    

  • Mod

    @samuel235 said:

    to get it off of the internal wifi/ethernet network

    There's always option 3 -- serial connection between ARduino and RPi. This is also very well supported!

    run this on a Arduino Mega

    I guess it will, but again, no experience with this setup (and hey, a Uno/Nano has enough power and only costs a few $$$ at Ali's)

    i would like to just put the code of my MQTTController.cpp here for you to see if you would like to develop something for the last option

    Sorry, no time 😉


  • Hardware Contributor

    @Yveaux said:

    Sorry, no time 😉

    I wasn't asking you to develop something for me. I was just letting you know the code that is working at the moment as a MQTT communicator.

    Would you prefer me to use your script and go for the serial one or would you rather me go for the more supported route? What stage is your script at, completely finished or making minor alterations every now and then to keep up to date with new mysensor releases?


  • Mod

    @samuel235 said:

    use your script and go for the serial one or would you rather me go for the more supported route?

    Go for the 'official' MySensors route. My script works fine with an ethernet connection, but I haven't tested it with serial.

    The script only requires modifications when the serial protocol changes, but this still hapens every now and then (e.g. new sensor types are added)


  • Hardware Contributor

    @Yveaux Okay, i shall do that route then. Does using a Mysensors route mean that i can only use sensors that are in the github, or can i create my own without having to modify the gateway in anyway?


  • Mod

    @samuel235 Creating you own sensors (whether using code from the Github/library repository or rolling your own) should not require modifying the gateway


  • Hardware Contributor

    @Yveaux Absolutely fantastic. I will get to work on that today and will be back to update this thread a little later on during my progress for others to realize they can follow the route i am when they firstly just wanted one machine.


Log in to reply
 

Suggested Topics

  • 1
  • 10
  • 1
  • 2
  • 2
  • 5

27
Online

11.2k
Users

11.1k
Topics

112.5k
Posts