Cant get callback in MySensors from Openhab using MQTT Gateway

I have spent a week at this point trying to get a switch item in OpenHab to turn on an LED in a MySensor.

Overview
MySensors 1.5.4
OpenHab 1.8 running on RPi (Jessie)
MQTTGateway (MQTT broker/server)

Success
Gateway instantiates
MySensor registers to MQTT Gateway
OpenHab registers to MQTT Gateway
SketchName is posted to OpenHab
SketchVersion is posted to OpenHab
Message data is posted to OpenHab
OpenHab post response
Failure
MySensor incomingMessage never fires

Gateway Sketch

/**
 * The MySensors Arduino library handles the wireless radio link and protocol
 * between your home built sensors/actuators and HA controller of choice.
 * The sensors forms a self healing radio network with optional repeaters. Each
 * repeater and gateway builds a routing tables in EEPROM which keeps track of the
 * network topology allowing messages to be routed to nodes.
 *
 * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
 * Copyright (C) 2013-2015 Sensnology AB
 * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
 *
 * Documentation: http://www.mysensors.org
 * Support Forum: http://forum.mysensors.org
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 *******************************
 *
 * REVISION HISTORY
 * Version 1.0 - Created by Daniel Wiegert <daniel.wiegert@gmail.com>
 * 
 * DESCRIPTION
 * MyMQTT Broker Gateway 0.1b
 * Latest instructions found here:
 * http://www.mysensors.org/build/mqtt_gateway
 * http://www.mysensors.org/build/ethernet_gateway
 * 
 * Change below; TCP_IP, TCP_PORT, TCP_MAC
 * This will listen on your selected TCP_IP:TCP_PORT below, Please change TCP_MAC your liking also.
 * 1 -> NOTE: Keep first byte at x2, x6, xA or xE (replace x with any hex value) for using Local Ranges.
 * 2 You can use standard pin set-up as MySensors recommends or if you own a IBOARD you may change
 *	the radio-pins below if you hardware mod your iBoard. see [URL BELOW] for more details.
 *	http://forum.mysensors.org/topic/224/iboard-cheap-single-board-ethernet-arduino-with-radio/5
 *
 * Don't forget to look at the definitions in MyMQTT.h!
 *
 *	define TCPDUMP and connect serial interface if you have problems, please write on
 *	http://forum.mysensors.org/ and explain your problem, include serial output. Don't forget to
 *	turn on DEBUG in libraries\MySensors\MyConfig.h also.
 *
 *	MQTT_FIRST_SENSORID is for 'DHCP' server in MyMQTT. You may limit the ID's with FIRST and LAST definition.
 *	If you want your manually configured below 20 set MQTT_FIRST_SENSORID to 20.
 *	To disable: set MQTT_FIRST_SENSORID to 255.
 *
 *	MQTT_BROKER_PREFIX is the leading prefix for your nodes. This can be only one char if like.
 *
 *	MQTT_SEND_SUBSCRIPTION is if you want the MyMQTT to send a empty payload message to your nodes.
 *	This can be useful if you want to send latest state back to the MQTT client. Just check if incoming
 *	message has any length or not.
 *	Example: if (msg.type==V_LIGHT && strlen(msg.getString())>0) otherwise the code might do strange things.
 *
 * (*) Address-layout is : [MQTT_BROKER_PREFIX]/[NodeID]/[SensorID]/V_[SensorType]
 *	NodeID and SensorID is uint8 (0-255) number.
 *	Last segment is translation of the sensor type, look inside MyMQTT.cpp for the definitions.
 *	User can change this to their needs. We have also left some space for custom types.
 *
 * Special: (sensor 255 reserved for special commands)
 * You can receive a node sketch name with MyMQTT/20/255/V_Sketch_name (or version with _version)
 *
 * To-do:
 * Special commands : clear or set EEPROM Values, Send REBOOT and Receive reboot for MyMQTT itself.
 * Be able to send ACK so client returns the data being sent.
 * ... Please come with ideas!
 * What to do with publish messages.
 *
 * Test in more MQTT clients, So far tested in openhab and MyMQTT for Android (Not my creation)
 * - http://www.openhab.org/
 * - https://play.google.com/store/apps/details?id=at.tripwire.mqtt.client&hl=en
 * ... Please notify me if you use this broker with other software.
 * 
 *  How to set-up Openhab and MQTTGateway:
 * http://forum.mysensors.org/topic/303/mqtt-broker-gateway
 */

#include <DigitalIO.h>
#include <SPI.h>

#include <MySigningNone.h>
#include <MyTransportRFM69.h>
#include <MyTransportNRF24.h>
#include <MyHwATMega328.h>
#include <MySigningAtsha204Soft.h>
#include <MySigningAtsha204.h>

#include <MySensor.h>
#include <MsTimer2.h>
#include <Ethernet.h>
#include "MyMQTT.h"

#include <EEPROM.h>

#define INCLUSION_MODE_TIME 1 // Number of minutes inclusion mode is enabled
#define INCLUSION_MODE_PIN  3 // Digital pin used for inclusion mode button

// * Use this for IBOARD modded to use standard MISO/MOSI/SCK, see note *1 above!
/*
#define RADIO_CE_PIN        3			// radio chip enable
#define RADIO_SPI_SS_PIN    8			// radio SPI serial select
#define RADIO_ERROR_LED_PIN A2  		// Error led pin
#define RADIO_RX_LED_PIN    A1  		// Receive led pin
#define RADIO_TX_LED_PIN    A0  		// the PCB, on board LED
*/

// * Use this for default configured pro mini / nano etc :
///*

#define RADIO_CE_PIN        5		// radio chip enable
#define RADIO_SPI_SS_PIN    6		// radio SPI serial select
#define RADIO_ERROR_LED_PIN 7		// Error led pin
#define RADIO_RX_LED_PIN    8		// Receive led pin
#define RADIO_TX_LED_PIN    9		// the PCB, on board LED*/

#define TCP_PORT 1883						// Set your MQTT Broker Listening port.
IPAddress TCP_IP ( 192, 168, 1, 83 );				// Configure your static ip-address here
byte TCP_MAC[] = { 0x02, 0xDE, 0xAD, 0x00, 0x00, 0x42 };	// Mac-address - You should change this! see note *2 above!

//////////////////////////////////////////////////////////////////

// NRFRF24L01 radio driver (set low transmit power by default) 
MyTransportNRF24 transport(RADIO_CE_PIN, RADIO_SPI_SS_PIN, RF24_PA_LEVEL_GW);  
//MyTransportRFM69 transport;

// Message signing driver (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h)
//MySigningNone signer;
//MySigningAtsha204Soft signer;
//MySigningAtsha204 signer;

// Hardware profile 
MyHwATMega328 hw;

// Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h)
MySensor gw(transport, hw /*, signer*/);


EthernetServer server = EthernetServer(TCP_PORT);
EthernetClient *currentClient = NULL;
MyMessage msg;
char convBuf[MAX_PAYLOAD*2+1];
char broker[] PROGMEM = MQTT_BROKER_PREFIX;
bool MQTTClientConnected = false;
uint8_t buffsize;
char buffer[MQTT_MAX_PACKET_SIZE];
volatile uint8_t countRx;
volatile uint8_t countTx;
volatile uint8_t countErr;


void writeEthernet(const char *writeBuffer, uint8_t *writeSize) {
#ifdef TCPDUMP
	Serial.print(">>");
	char buf[4];
	for (uint8_t a=0; a<*writeSize; a++) { sprintf(buf,"%02X ",(uint8_t)writeBuffer[a]);  Serial.print(buf); } Serial.println("");
#endif
	server.write((const uint8_t *)writeBuffer, *writeSize);
}


void processEthernetMessages() {
  char inputString[MQTT_MAX_PACKET_SIZE] = "";
  byte inputSize = 0;
  byte readCnt = 0;
  byte length = 0;

  EthernetClient client = server.available();
  if (client) {
    while (client.available()) {
      // Save the current client we are talking with
      currentClient = &client;
      byte inByte = client.read();
      readCnt++;

      if (inputSize < MQTT_MAX_PACKET_SIZE) {
        inputString[inputSize] = (char)inByte;
        inputSize++;
      }

      if (readCnt == 2) {
        length = (inByte & 127) * 1;
      }
      if (readCnt == (length+2)) {
        break;
      }
    }
#ifdef TCPDUMP
    Serial.print("<<");
    char buf[4];
    for (byte a=0; a<inputSize; a++) { sprintf(buf, "%02X ", (byte)inputString[a]); Serial.print(buf); } Serial.println();
#endif
    processMQTTMessage(inputString, inputSize);
    currentClient = NULL;
  }
}




void incomingMessage(const MyMessage &message) {
   rxBlink(1);
   sendMQTT(message);
} 



void setup()  
{ 
  Serial.print("Beginning setup");

  //Wipe eprom
  for (int i = 0 ; i < EEPROM.length() ; i++) {
    EEPROM.write(i, 0);
  }

  
  Ethernet.begin(TCP_MAC, TCP_IP);

  
  countRx = 0;
  countTx = 0;
  countErr = 0;

  // Setup led pins
  pinMode(RADIO_RX_LED_PIN, OUTPUT);
  pinMode(RADIO_TX_LED_PIN, OUTPUT);
  pinMode(RADIO_ERROR_LED_PIN, OUTPUT);
  digitalWrite(RADIO_RX_LED_PIN, LOW);
  digitalWrite(RADIO_TX_LED_PIN, LOW);
  digitalWrite(RADIO_ERROR_LED_PIN, LOW);

 
  // Set initial state of leds
  digitalWrite(RADIO_RX_LED_PIN, HIGH);
  digitalWrite(RADIO_TX_LED_PIN, HIGH);
  digitalWrite(RADIO_ERROR_LED_PIN, HIGH);


  // Add led timer interrupt
  MsTimer2::set(300, ledTimersInterrupt);
  MsTimer2::start();


  // give the Ethernet interface a second to initialize
  delay(1000);


  // Initialize gateway at maximum PA level, channel 70 and callback for write operations 
  gw.begin(incomingMessage, 0, true, 0);  

  // start listening for clients
  server.begin();
  
  Serial.println("Ok!");
}

void loop()
{
  gw.process();  
  
  processEthernetMessages();
}





inline MyMessage& build (MyMessage &msg, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type, bool enableAck) {
	msg.destination = destination;
	msg.sender = GATEWAY_ADDRESS;
	msg.sensor = sensor;
	msg.type = type;
	mSetCommand(msg,command);
	mSetRequestAck(msg,enableAck);
	mSetAck(msg,false);
	return msg;
}

char *getType(char *b, const char **index) {
	char *q = b;
	char *p = (char *)pgm_read_word(index);
	while (*q++ = pgm_read_byte(p++));
	*q=0;
	return b;
}

void processMQTTMessage(char *inputString, uint8_t inputPos) {
	char *str, *p;
	uint8_t i = 0;
	buffer[0]= 0;
	buffsize = 0;

	if ((uint8_t)inputString[0] >> 4 == MQTTCONNECT) {
		buffer[buffsize++] = MQTTCONNACK << 4;
		buffer[buffsize++] = 0x02;			// Remaining length
		buffer[buffsize++] = 0x00;			// Connection accepted
		buffer[buffsize++] = 0x00;			// Reserved
		MQTTClientConnected=true;			// We have connection!
	}
	if ((uint8_t)inputString[0] >> 4 == MQTTPINGREQ) {
		buffer[buffsize++] = MQTTPINGRESP << 4;
		buffer[buffsize++] = 0x00;
	}
	if ((uint8_t)inputString[0] >> 4 == MQTTSUBSCRIBE) {
		buffer[buffsize++] = MQTTSUBACK << 4;		// Just ack everything, we actually dont really care!
		buffer[buffsize++] = 0x03;			// Remaining length
		buffer[buffsize++] = (uint8_t)inputString[2];	// Message ID MSB
		buffer[buffsize++] = (uint8_t)inputString[3];	// Message ID LSB
		buffer[buffsize++] = MQTTQOS0;			// QOS level
	}
	if ((uint8_t)inputString[0] >> 4 == MQTTUNSUBSCRIBE) {
		buffer[buffsize++] = MQTTUNSUBACK << 4;
		buffer[buffsize++] = 0x02;			// Remaining length
		buffer[buffsize++] = (uint8_t)inputString[2];	// Message ID MSB
		buffer[buffsize++] = (uint8_t)inputString[3];	// Message ID LSB
	}
	if ((uint8_t)inputString[0] >> 4 == MQTTDISCONNECT) {
		MQTTClientConnected=false;			// We lost connection!
	}
	if (buffsize > 0) {
		writeEthernet(buffer,&buffsize);
	}

	// We publish everything we get, we dont care if its subscribed or not!
	if ((uint8_t)inputString[0] >> 4 == MQTTPUBLISH || (MQTT_SEND_SUBSCRIPTION && (uint8_t)inputString[0] >> 4 == MQTTSUBSCRIBE)) {
		buffer[0]= 0;
		buffsize = 0;
		// Cut out address and payload depending on message type.
		if ((uint8_t)inputString[0] >> 4 == MQTTSUBSCRIBE) {
			strncat(buffer,inputString+6,inputString[5]);
		} else {
			strncat(buffer,inputString+4,inputString[3]);
		}

#ifdef DEBUG
		Serial.println(buffer);
#endif
		// TODO: Check if we should send ack or not.
		for (str = strtok_r(buffer,"/",&p) ; str && i<4 ; str = strtok_r(NULL,"/",&p)) {
			if (i == 0) {
				if (strcmp_P(str,broker)!=0) {	//look for MQTT_BROKER_PREFIX
					return;			//Message not for us or malformatted!
				}
			} else if (i==1) {
				msg.destination = atoi(str);	//NodeID
			} else if (i==2) {
				msg.sensor = atoi(str);		//SensorID
			} else if (i==3) {
				char match=255;			//SensorType
#ifdef MQTT_TRANSLATE_TYPES				

				for (uint8_t j=0; strcpy_P(convBuf, (char*)pgm_read_word(&(vType[j]))) ; j++) {
					if (strcmp((char*)&str[2],convBuf)==0) { //Strip V_ and compare
						match=j;
						break;
					}
					if (j >= V_TOTAL)  break;
				}

#endif
                                if ( atoi(str)!=0 || str=="0" ) {
					match=atoi(str);
				}

				if (match==255) {
					match=V_UNKNOWN;
 				}
				msg.type = match;
			}
			i++;
		}						//Check if packge has payload
		if ((uint8_t)inputString[1] > (uint8_t)(inputString[3]+2) && !((uint8_t)inputString[0] >> 4 == MQTTSUBSCRIBE)) {
			strcpy(convBuf,inputString+(inputString[3]+4));
			msg.set(convBuf);			//Payload
		} else {
			msg.set("");				//No payload
		}
		txBlink(1);
		if (!gw.sendRoute(build(msg, msg.destination, msg.sensor, C_SET, msg.type, 0))) errBlink(1);

	}
}

void sendMQTT(const MyMessage &inMsg) {
        MyMessage msg = inMsg;
	buffsize = 0;
	if (!MQTTClientConnected) return;			//We have no connections - return
	if (msg.isAck()) {
//		if (msg.sender==255 && mGetCommand(msg)==C_INTERNAL && msg.type==I_ID_REQUEST) {
// TODO: sending ACK request on id_response fucks node up. doesn't work.
// The idea was to confirm id and save to EEPROM_LATEST_NODE_ADDRESS.
//  }
	} else {
		// we have to check every message if its a newly assigned id or not.
		// Ack on I_ID_RESPONSE does not work, and checking on C_PRESENTATION isn't reliable.
		uint8_t newNodeID = gw.loadState(EEPROM_LATEST_NODE_ADDRESS)+1;
		if (newNodeID <= MQTT_FIRST_SENSORID) newNodeID = MQTT_FIRST_SENSORID;
		if (msg.sender==newNodeID) {
			gw.saveState(EEPROM_LATEST_NODE_ADDRESS,newNodeID);
		}
		if (mGetCommand(msg)==C_INTERNAL) {
			if (msg.type==I_CONFIG) {
				txBlink(1);
				if (!gw.sendRoute(build(msg, msg.sender, 255, C_INTERNAL, I_CONFIG, 0).set(MQTT_UNIT))) errBlink(1);
				return;
			} else if (msg.type==I_ID_REQUEST && msg.sender==255) {
				uint8_t newNodeID = gw.loadState(EEPROM_LATEST_NODE_ADDRESS)+1;
				if (newNodeID <= MQTT_FIRST_SENSORID) newNodeID = MQTT_FIRST_SENSORID;
				if (newNodeID >= MQTT_LAST_SENSORID) return; // Sorry no more id's left :(
				txBlink(1);
				if (!gw.sendRoute(build(msg, msg.sender, 255, C_INTERNAL, I_ID_RESPONSE, 0).set(newNodeID))) errBlink(1);
				return;
			}
		}
		if (mGetCommand(msg)!=C_PRESENTATION) {
			if (mGetCommand(msg)==C_INTERNAL) msg.type=msg.type+(S_FIRSTCUSTOM-10);	//Special message
			buffer[buffsize++] = MQTTPUBLISH << 4;	// 0:
			buffer[buffsize++] = 0x09;		// 1: Remaining length with no payload, we'll set this later to correct value, buffsize -2
			buffer[buffsize++] = 0x00;		// 2: Length MSB (Remaing length can never exceed ff,so MSB must be 0!)
			buffer[buffsize++] = 0x08;		// 3: Length LSB (ADDR), We'll set this later
			strcpy_P(buffer+4, broker);
			buffsize+=strlen_P(broker);
#ifdef MQTT_TRANSLATE_TYPES
			if (msg.type > V_TOTAL) msg.type=V_UNKNOWN;// If type > defined types set to unknown.
 			buffsize+=sprintf(&buffer[buffsize],"/%i/%i/V_%s",msg.sender,msg.sensor,getType(convBuf, &vType[msg.type]));
#else
			buffsize+=sprintf(&buffer[buffsize],"/%i/%i/%i",msg.sender,msg.sensor,msg.type);
#endif
			buffer[3]=buffsize-4;			// Set correct address length on byte 4.
#ifdef DEBUG
			Serial.println((char*)&buffer[4]);
#endif
			msg.getString(convBuf);
			for (uint8_t a=0; a<strlen(convBuf); a++) {// Payload
				buffer[buffsize++] = convBuf[a];
			}
			buffer[1]=buffsize-2;			// Set correct Remaining length on byte 2.
			writeEthernet(buffer,&buffsize);
		}
	}
}


void ledTimersInterrupt() {
  if(countRx && countRx != 255) {
    // switch led on
    digitalWrite(RADIO_RX_LED_PIN, LOW);
  } else if(!countRx) {
     // switching off
     digitalWrite(RADIO_RX_LED_PIN, HIGH);
   }
   if(countRx != 255) { countRx--; }

  if(countTx && countTx != 255) {
    // switch led on
    digitalWrite(RADIO_TX_LED_PIN, LOW);
  } else if(!countTx) {
     // switching off
     digitalWrite(RADIO_TX_LED_PIN, HIGH);
   }
   if(countTx != 255) { countTx--; }

  if(countErr && countErr != 255) {
    // switch led on
    digitalWrite(RADIO_ERROR_LED_PIN, LOW);
  } else if(!countErr) {
     // switching off
     digitalWrite(RADIO_ERROR_LED_PIN, HIGH);
   }
   if(countErr != 255) { countErr--; }

}

void rxBlink(uint8_t cnt) {
  if(countRx == 255) { countRx = cnt; }
}
void txBlink(uint8_t cnt) {
  if(countTx == 255) { countTx = cnt; }
}
void errBlink(uint8_t cnt) {
  if(countErr == 255) { countErr = cnt; }
}

Motion Sensor Sketch with Callback

/**
 * The MySensors Arduino library handles the wireless radio link and protocol
 * between your home built sensors/actuators and HA controller of choice.
 * The sensors forms a self healing radio network with optional repeaters. Each
 * repeater and gateway builds a routing tables in EEPROM which keeps track of the
 * network topology allowing messages to be routed to nodes.
 *
 * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
 * Copyright (C) 2013-2015 Sensnology AB
 * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
 *
 * Documentation: http://www.mysensors.org
 * Support Forum: http://forum.mysensors.org
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 *******************************
 *
 * REVISION HISTORY
 * Version 1.0 - Henrik Ekblad
 * 
 * DESCRIPTION
 * Motion Sensor example using HC-SR501 
 * http://www.mysensors.org/build/motion
 *
 */

#include <EEPROM.h>
#include <MySensor.h>  
#include <SPI.h>

unsigned long SLEEP_TIME = 30000; // Sleep time between reports (in milliseconds)
#define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
#define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
#define NODE_ID  2
#define CHILD_ID 2   // Id of the sensor child
#define LED_PIN  6

MySensor gw;

// Initialize motion message
MyMessage msg(CHILD_ID, V_LIGHT);

void setup()  
{  
  //Wipe eprom
  for (int i = 0 ; i < EEPROM.length() ; i++) {
    EEPROM.write(i, 0);
  }

  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  
  gw.begin(incomingMessage, NODE_ID, false);

  // Send the sketch version information to the gateway and Controller
  gw.sendSketchInfo("Motion Sensor", "1.0");

  pinMode(DIGITAL_INPUT_SENSOR, INPUT);      // sets the motion sensor digital pin as input
  // Register all sensors to gw (they will be created as child devices)
  gw.present(CHILD_ID, S_LIGHT);
  
}

void loop()     
{     
  // Read digital motion value
  boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; 
        
  Serial.println(tripped);
  gw.send(msg.set(tripped?"1":"0"));  // Send tripped value to gw 
 
  // Sleep until interrupt comes in on motion sensor. Send update every two minute. 
  gw.sleep(INTERRUPT,CHANGE, SLEEP_TIME);
}

void incomingMessage(const MyMessage &message)
{
     digitalWrite(LED_PIN, HIGH);
     Serial.println("message received");
}

OpenHab.cfg

mqtt:mysensor.url=tcp://192.168.1.83:1883
mqtt:mysensor.clientId=openhab

OpenHab MQTT.items

Switch MQTTTestSwitch  "MQTT Test Switch"  (gBasement)  {mqtt=">[mysensor:MyMQTT/2/2/V_LIGHT:command:ON:1],>[mysensor:MyMQTT/2/2/V_LIGHT:command:OFF:0],<[mysensor:MyMQTT/2/2/V_LIGHT:command:MAP(1on0off.map)]"}

OpenHab MQTT.log on startup

2016-07-25 22:39:53.851 [DEBUG] [.io.transport.mqtt.MqttService:123 ]- Starting MQTT Service...
2016-07-25 22:39:54.506 [INFO ] [.io.transport.mqtt.MqttService:108 ]- MQTT Service initialization completed.
2016-07-25 22:39:54.534 [INFO ] [o.i.t.m.i.MqttBrokerConnection:114 ]- Starting MQTT broker connection 'mysensor'
2016-07-25 22:39:54.613 [DEBUG] [o.i.t.m.i.MqttBrokerConnection:294 ]- Creating new client for 'tcp://192.168.1.83:1883' using id 'openhab' and file store '/tmp/mysensor'
2016-07-25 22:42:40.296 [DEBUG] [.b.mqtt.internal.MqttActivator:34  ]- MQTT binding has been started.
2016-07-25 22:42:41.142 [TRACE] [m.i.MqttGenericBindingProvider:52  ]- Starting to load MQTT config for item MQTTTestSketchName
2016-07-25 22:42:41.162 [DEBUG] [b.mqtt.internal.MqttItemConfig:72  ]- Loaded MQTT config for item 'MQTTTestSketchName' : 1 subscribers, 0 publishers
2016-07-25 22:42:41.176 [DEBUG] [o.i.t.m.i.MqttBrokerConnection:476 ]- Starting message consumer for broker 'mysensor' on topic 'MyMQTT/2/255/V_SKETCH_NAME'
2016-07-25 22:42:41.207 [TRACE] [m.i.MqttGenericBindingProvider:52  ]- Starting to load MQTT config for item MQTTTestSketchVersion
2016-07-25 22:42:41.225 [DEBUG] [b.mqtt.internal.MqttItemConfig:72  ]- Loaded MQTT config for item 'MQTTTestSketchVersion' : 1 subscribers, 0 publishers
2016-07-25 22:42:41.237 [DEBUG] [o.i.t.m.i.MqttBrokerConnection:476 ]- Starting message consumer for broker 'mysensor' on topic 'MyMQTT/2/255/V_SKETCH_VERSION'
2016-07-25 22:42:41.272 [TRACE] [m.i.MqttGenericBindingProvider:52  ]- Starting to load MQTT config for item MQTTTestSwitch
2016-07-25 22:42:41.301 [DEBUG] [b.mqtt.internal.MqttItemConfig:72  ]- Loaded MQTT config for item 'MQTTTestSwitch' : 1 subscribers, 2 publishers
2016-07-25 22:42:41.308 [DEBUG] [o.i.t.m.i.MqttBrokerConnection:476 ]- Starting message consumer for broker 'mysensor' on topic 'MyMQTT/2/2/V_LIGHT'
2016-07-25 22:42:53.947 [DEBUG] [.mqtt.internal.MqttItemBinding:44  ]- Publishing command ON to MyMQTT/2/2/V_LIGHT
2016-07-25 22:42:54.184 [DEBUG] [o.i.t.m.i.MqttBrokerConnection:437 ]- Publishing message 5 to topic 'MyMQTT/2/2/V_LIGHT'
2016-07-25 22:43:03.672 [DEBUG] [.mqtt.internal.MqttItemBinding:44  ]- Publishing command OFF to MyMQTT/2/2/V_LIGHT
2016-07-25 22:43:03.795 [DEBUG] [o.i.t.m.i.MqttBrokerConnection:437 ]- Publishing message 6 to topic 'MyMQTT/2/2/V_LIGHT'

OpenHab Events.log on MySensor startup

2016-07-25 23:42:22 - MQTTTestSketchName state updated to Motion Sensor
2016-07-25 23:42:22 - MQTTTestSketchVersion state updated to 1.0
2016-07-25 23:42:22 - MQTTTestSwitch received command ON

Do you want to read back the state of the switch with this part of your item definition?
Then it should be:

<[mysensor:MyMQTT/2/2/V_LIGHT:state:MAP(1on0off.map)

Thanks for your reply, but actually that piece works fine for me. When the MySensor sends a value of 1, that code uses the map file and changes the state of the button correctly to On and it displays correctly. But then when I manually slide the switch to Off, the log shows that it publishes Off but no command reaches MySensor.

Its these two that don’t work:
>[mysensor:MyMQTT/2/2/V_LIGHT:command:ON:1],>[mysensor:MyMQTT/2/2/V_LIGHT:command:OFF:0]

When reading the many pages on or near this topic it is obvious that many people use Mosquitto. Just for clarity, I am not. I am using MySensors Arduino-based MQTTGateway.

Do these messages reach your broker? You should be able to subscribe to the topic on your broker with another client and to see the messages received. There are various mqtt clients available for doing this on android, iphone, linux and windows. mosquitto_sub is one such client, that I tend to use.

Yes, but note I’m using mosquitto and don’t know the differences to your broker.

The only help I can give you is one of my working configs (mosquitto, esp8266):

Switch Alarm_LED_Green {mqtt=">[mosquitto:/esp8266two/gpio/2:command:ON:0],>[mosquitto:/esp8266two/gpio/2:command:OFF:1]"}

Result in MQTT.fx:

Thanks for your reply. No, I don’t see those messages. Whenever I subscribe to broker using phone on topic MyMQTT/#, I see posts from MySensor but not from OpenHab. Howerver, this may not be totally reliable since I also see evidence that connecting from the phone disconnects OpenHab. But it does seem to successfully reconnect and still I see no posts from Openhab on the broker.

Output from MQTT.log on phone connect

2016-07-25 22:52:05.754 [ERROR] [o.i.t.m.i.MqttBrokerConnection:536 ]- MQTT connection to broker was lost
org.eclipse.paho.client.mqttv3.MqttException: Connection lost
        at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:138) [mqtt-client-0.4.0.jar:na]
        at java.lang.Thread.run(Thread.java:745) [na:1.8.0_65]
Caused by: java.net.SocketException: Connection reset
        at java.net.SocketInputStream.read(SocketInputStream.java:209) ~[na:1.8.0_65]
        at java.net.SocketInputStream.read(SocketInputStream.java:141) ~[na:1.8.0_65]
        at java.net.SocketInputStream.read(SocketInputStream.java:223) ~[na:1.8.0_65]
        at java.io.DataInputStream.readByte(DataInputStream.java:265) ~[na:1.8.0_65]
        at org.eclipse.paho.client.mqttv3.internal.wire.MqttInputStream.readMqttWireMessage(MqttInputStream.java:56) ~[na:na]
        at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:100) [mqtt-client-0.4.0.jar:na]
        ... 1 common frames omitted
2016-07-25 22:52:05.769 [ERROR] [o.i.t.m.i.MqttBrokerConnection:540 ]- MQTT connection to 'mysensor' was lost: Connection lost : ReasonCode 32109 : Cau$
2016-07-25 22:52:05.778 [INFO ] [o.i.t.m.i.MqttBrokerConnection:547 ]- Starting connection helper to periodically try restore connection to broker 'mys$
2016-07-25 22:52:15.789 [INFO ] [o.i.t.m.i.MqttBrokerConnection:114 ]- Starting MQTT broker connection 'mysensor'

Make sure you are using a different client ID for each device that connects to the broker. If a client with the same name connects the broker will kick off the client already connected with the same name.

Fair enough. But I am pretty sure only OpenHab is using client id “openhab” as defined in openHab.cfg. Just checked and my phone was using “clientid” so I changed it to “phone” and will retry when I get home.

Ok, so I got some simple advice in the MySensors forum. Use the MQTTClientGateway and then use Mosquitto on RPi. 2 hours later everything is working like a charm.

Now that I went through all this I am going to post what I hope may help others trying to do the same thing that I was. Basically I just wanted a solid platform to connect MySensors to OpenHab. This is what I ended up with.

Controller

  • Raspberry Pi (Jessie)
  • Openhab 1.8
  • make sure you org.openhab.binding.mqtt-1.8.1.jar in your addons directory
  • 192.168.1.101

MQTT Broker

MQTT Client Gateway

MySensors RelayActuator

  • Arduino Nano clone
  • Addicore nRF24L01

MQTT Client on my iPhone

  • This is so useful for getting the messaging correct (both from OpenHab and Sensor)
  • MQTT Inspector 1.0 is the one i used

GatewayW5100MQTTClient sketch I didn’t change these lines but you need to note them. They form an important part of the message structure that your openhab items will need to subscribe to

// Set this nodes subscripe and publish topic prefix
#define MY_MQTT_PUBLISH_TOPIC_PREFIX "mygateway1-out"
#define MY_MQTT_SUBSCRIBE_TOPIC_PREFIX "mygateway1-in"

It is important to change the lines below so that the MySensors MQTT Client device is on your network and can communicate correctly. Use the same subnet as your other devices. You can get gateway information using ipconfig on windows…

// Enable MY_IP_ADDRESS here if you want a static ip address (no DHCP)
#define MY_IP_ADDRESS 192,168,1,87

// If using static ip you need to define Gateway and Subnet address as well
#define MY_IP_GATEWAY_ADDRESS 192,168,1,1
#define MY_IP_SUBNET_ADDRESS 255,255,255,0

Change these lines to point to your Mosquito MQTT Broker

// MQTT broker ip address or url. Define one or the other. 
//#define MY_CONTROLLER_URL_ADDRESS "m20.cloudmqtt.com"
#define MY_CONTROLLER_IP_ADDRESS 192, 168, 1, 101

// The MQTT broker port to to open 
#define MY_PORT 1883  

openhab.cfg I probably should have called the broker mosquitto instead of mysensor but just note that this is the alias openhab will use to talk to the broker and can be anything you choose

# URL to the MQTT broker, e.g. tcp://localhost:1883 or ssl://localhost:8883
mqtt:mysensor.url=tcp://192.168.1.101:1883  

# Optional. Client id (max 23 chars) to use when connecting to the broker.
# If not provided a default one is generated.
mqtt:mysensor.clientId=openhab

1closed0open.map this is in opt/openhab/configurations/transform

1=closed
0=open

mqtt.items
before each message is a symbol. < means openhab is subscribing to this topic. As such topics need to be prefixed with the values in your gateway. If you left the default use mygateway1-out prefix. I am not including the code I use to publish to the Garage Door item. > means openhab is publishing to this item. The default prefix here is mygateway1-in. Now the good news here is once everything gets connected and starts sending messages, you can use a MQTT client to watch for specifc messages by subscribing to both mygateway1-out/# and mygateway1-in/#. This is how i dialed in the values you see in my mqtt.items file.

String Garage_Door  "Garage Door [%s]"           (gGarage, Windows)   {mqtt="<[mysensor:mygateway1-out/101/3/1/0/16:state:MAP(1closed0open.map)]"}

Switch MQTTTestSwitch  "MQTT Test Switch"  (gBasement)  {mqtt=">[mysensor:mygateway1-in/2/2/0/0/2:command:ON:1],>[mysensor:mygateway1-in/2/2/0/0/2:command:OFF:0]"}

Modified RelayActuator Sketch from MySensors 2.0 examples

/**
 * The MySensors Arduino library handles the wireless radio link and protocol
 * between your home built sensors/actuators and HA controller of choice.
 * The sensors forms a self healing radio network with optional repeaters. Each
 * repeater and gateway builds a routing tables in EEPROM which keeps track of the
 * network topology allowing messages to be routed to nodes.
 *
 * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
 * Copyright (C) 2013-2015 Sensnology AB
 * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
 *
 * Documentation: http://www.mysensors.org
 * Support Forum: http://forum.mysensors.org
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 *******************************
 *
 * REVISION HISTORY
 * Version 1.0 - Henrik Ekblad
 * 
 * DESCRIPTION
 * Example sketch showing how to control physical relays. 
 * This example will remember relay state after power failure.
 * http://www.mysensors.org/build/relay
 */ 

// Enable debug prints to serial monitor
#define MY_DEBUG 

// Enable and select radio type attached
#define MY_RADIO_NRF24
//#define MY_RADIO_RFM69

// Enable repeater functionality for this node
// #define MY_REPEATER_FEATURE

#include <SPI.h>
#include <MySensors.h>

#define RELAY_1  3  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
#define NUMBER_OF_RELAYS 1 // Total number of attached relays
#define RELAY_ON 1  // GPIO value to write to turn on attached relay
#define RELAY_OFF 0 // GPIO value to write to turn off attached relay
#define LED_PIN 6

void before() { 

}

void setup() {
    // Then set relay pins in output mode
    pinMode(LED_PIN, OUTPUT);   
    // Set relay to last known state (using eeprom storage) 
    digitalWrite(LED_PIN, LOW);
}

void presentation()  
{   
  // Send the sketch version information to the gateway and Controller
  sendSketchInfo("Relay", "1.0");

    // Register all sensors to gw (they will be created as child devices)
    present(2, S_LIGHT);
  
}


void loop() 
{
  
}

void receive(const MyMessage &message) {
  Serial.print("V_LIGHT=");
  Serial.print(V_LIGHT);
  Serial.print("got message of type ");
  Serial.println(message.type);
  // We only expect one type of message from controller. But we better check anyway.
  if (message.type==V_LIGHT) {
     // Change relay state
     digitalWrite(LED_PIN, message.getBool()?RELAY_ON:RELAY_OFF);
     // Store state in eeprom
     saveState(message.sensor, message.getBool());
     // Write some debug info
     Serial.print("Incoming change for sensor:");
     Serial.print(message.sensor);
     Serial.print(", New status: ");
     Serial.println(message.getBool());
   } 
}

One other thing to note is that the type of item can affect how it reacts to values. For example, originally my Garage Door item was of type contact and i kept getting messages in my openhab.log that said it could not set state because new value was NULL. I switched it to string and it worked.

1 Like