This new post finalized the User Node (an Android device). It will include the smart-house functionalities to that of the competition system. This way, any resident will be able to check the smart house information while connected to the WiFi and switch to Competition mode when leaving to gain some miles.
*In other words... I will make the Smart Competition button work
User's node - include MQTT Publisher Client
NOT CONNECTED EXAMPLES OF SUBSCRIBE RESPONSE
Smart competition Activity
Initial setup: Nexus 5 / Android / SmartCompetitionHome App v 3
Functionalities
It is a direct implementation of the MQTT Clients, thanks to the Paho library
MQTT Clients subscriber & publisher
I create both kind of clients in the app. To do so, the code needs:
- Client id
- url - local IP of the broker
- port - that of MQTT Service (or the one our broker is listening to) Default port = 1883
Both types of client (subscriber, with its callbacks and publisher) are implemented in the Paho libraries. Very great news
public static void createMQTTDefaultClients(){ String url = protocol + broker + ":" + port; clientId = "phone_"+action; try { //Publisher: //Create an instance of this class sampleClient = new MyCustomMqttClient(url, clientId, cleanSession, quietMode,userName,password); // Perform the requested action sampleClient.publish(pubTopic,qos,message.getBytes()); //Subscriber: //For the async clientId = "phone_"+action_async; sampleSubscriber = new SampleAsyncCallBack(url,clientId,cleanSession, quietMode,userName,password); sampleSubscriber.subscribe(subTopic,qos); } catch(Throwable me) { // Display full details of any exception that occurs System.out.println("reason "+((MqttException) me).getReasonCode()); System.out.println("msg "+me.getMessage()); System.out.println("loc "+me.getLocalizedMessage()); System.out.println("cause "+me.getCause()); System.out.println("excep "+me); me.printStackTrace(); } }
Subscriber
In order to create the subscriber, I instantiate the class SampleAsyncCallback (implementing MqttCallback). The subscription will be performed as a combination of the function subscribe() method (which starts and manages the process)and the waitForStateChange(). As a result, the code will navigate through all the connection steps:
- Normally - BEGIN, CONNECTED, SUBSCRIBED, DISCONNECT, DISCONNECTED
While the client is subscribed, the information will get to the phone as a callback, messageArrived(). This method is used to:
- Get new data of the topic
- Update the interface to include this new information
More details of this callback:
/** * @see MqttCallback#messageArrived(String, MqttMessage) */ public void messageArrived(String topic, MqttMessage message) throws MqttException { // Called when a message arrives from the server that matches any // subscription made by the client String time = new Timestamp(System.currentTimeMillis()).toString(); System.out.println("Time:\t" +time + " Topic:\t" + topic + " Message:\t" + new String(message.getPayload()) + " QoS:\t" + message.getQos()); if (topic.equals("sensors/door")){ //Change door values //MainActivity.doorState.setText(new String(message.getPayload())); SmartHomeActivity.readDoor = new String (message.getPayload()); receivedDoor = true; }else if (topic.equals("sensors/temperature")){ //Change temperature values //MainActivity.tempState.setText(new String(message.getPayload())); SmartHomeActivity.readTemp = new String (message.getPayload()); receivedTemp = true; }else if (topic.equals("sensors/pressure")){ //Change pressure values //MainActivity.pressState.setText(new String(message.getPayload())); SmartHomeActivity.readPress = new String (message.getPayload()); receivedPres = true; }else if (topic.equals("sensors/warning")){ //Change warning //MainActivity.warningState.setText(new String(message.getPayload())); SmartHomeActivity.readWarning = new String (message.getPayload()); receivedWar = true; }else if (topic.equals("sensors/altitude")){ SmartHomeActivity.readAlt = new String (message.getPayload()); }else{ //Change anything SmartHomeActivity.readTemp = ("?"); SmartHomeActivity.readWarning = ("?"); SmartHomeActivity.readDoor = ("?"); SmartHomeActivity.readPress = ("?"); } if (receivedDoor && receivedTemp && receivedPres ){ receivedDoor = false; receivedTemp = false; receivedPres = false; receivedWar = false; //Go to the next step of the connection SmartHomeActivity.subscribed = false; } }
At this point, I use the subscribe() function when pressing SUBSCRIBE button.
Publisher
I have been using it mainly for debugging purposes: I can check whether messages are received by the broker when the sensor data seems to be lagging.
NOTE: Clients id! Along this project, I have been creating a few different clients. It might be obvious, but sometimes it is not... I have been given them different ids. The broker will refuse any connection if there is already a client with that name
Not the best features
I wanted to refined this Smart home activity, since its missing both a nicer look and additional useful commands. Regarding this commands, I wan to point out that:
- The connection IP is hardcoded, which means that the user has no way of selecting a different device. Consequently, an extra field needs to be included for that purpose
- There is no alert when the connection fails.
- It is not automated - I have to press subscribe button every time a want to get new data
- There is the "Publish" option on the interface, which will actually create MQTT_Publisher and send the message to the broker. However, the Central Node only logs the result:
- With a bit more of coding, we can use the smart home application to control some actuators (if some are installed in the house)
All in all... it will get the job done but it is still not the most comfortable to deal with
Conclusion
This post closes the implementation of our User's Node. Now, we have the two main functions of the system:
- A distance tracker linked to the competition server
- An MQTT client which can be use to read data from Sensors Node
Top Comments