Java tutorial
/** * Copyright (c) 2016 Dishant Langayan * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Dishant Langayan */ package com.dishant.iot.smarthome.publisher; import java.util.HashMap; import java.util.Map; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.dishant.iot.smarthome.data.DataTransportListener; import com.dishant.iot.smarthome.sensors.SensorChangedListener; import com.dishant.iot.smarthome.data.DataTransport; import com.dishant.iot.smarthome.sensors.SensorService; import com.dishant.iot.smarthome.sensors.SensorService.NoSuchSensorOrActuatorException; import com.dishant.iot.smarthome.SmarthomeException; import com.dishant.iot.smarthome.data.mqtt.MqttDataTransport; import com.dishant.iot.smarthome.util.ValidationUtil; public class SmarthomePublisher implements DataTransportListener, SensorChangedListener { private static final Logger s_logger = LoggerFactory.getLogger(SmarthomePublisher.class); private static final String PUBLISH_TOPICPREFIX_PROP_NAME = "publish.topicPrefix"; private static final String PUBLISH_QOS_PROP_NAME = "publish.qos"; private static final String PUBLISH_RETAIN_PROP_NAME = "publish.retain"; private static final String MQTT_TIMEOUT_PROP_NAME = "mqtt.timeout"; private String m_topicPrefix = ""; private int m_qos = 0; private boolean m_retain = false; private long m_timeout = 0; private SensorService m_sensorService; private Map<String, Object> m_properties = new HashMap<String, Object>(); // Data transport service private DataTransport m_dataTransport; private JSONParser parser = new JSONParser(); public SmarthomePublisher() { } /** * Set the SmartHome Sensor Service * * @param sensorService */ public void setSmarthomeSensorService(SensorService sensorService) { m_sensorService = sensorService; } public void unsetSmarthomeSensorService(SensorService sensorService) { m_sensorService = null; } public void activate(Map<String, Object> properties) throws SmarthomeException { s_logger.info("Activating SmarthomePublisher..."); // Configuration m_properties = properties; // // Validate and set required properties for publishing try { m_topicPrefix = (String) m_properties.get(PUBLISH_TOPICPREFIX_PROP_NAME); ValidationUtil.notEmptyOrNull(m_topicPrefix, PUBLISH_TOPICPREFIX_PROP_NAME); m_qos = Integer.parseInt((String) m_properties.get(PUBLISH_QOS_PROP_NAME)); ValidationUtil.notNegative(m_qos, PUBLISH_QOS_PROP_NAME); if (m_properties.containsKey(PUBLISH_RETAIN_PROP_NAME)) m_retain = Boolean.parseBoolean((String) m_properties.get(PUBLISH_RETAIN_PROP_NAME)); m_timeout = Integer.parseInt((String) m_properties.get(MQTT_TIMEOUT_PROP_NAME)); ValidationUtil.notNegative(m_timeout, MQTT_TIMEOUT_PROP_NAME); } catch (Exception e) { s_logger.error("Invalid SmarthomePublisher configuration"); throw new SmarthomeException("Invalid SmarthomePublisher configuration", e); } // // Connect to remote mqtt broker try { s_logger.debug("Connecting to MQTT data transport..."); m_dataTransport = new MqttDataTransport(m_properties, this); m_dataTransport.connect(); } catch (Exception e) { throw new SmarthomeException("Connection to MQTT data transport failed", e); } // // Subscribe to receive update rejects from AWS-IoT thing String topic = m_topicPrefix + "update/rejected"; try { s_logger.info("Subscribing to topic: " + topic); m_dataTransport.subscribe(topic, 0); } catch (Exception e) { throw new SmarthomeException("Failed to subscribe to AWS-IoT thing update reject topic: " + topic, e); } s_logger.info("Activating SmarthomePublisher... Done"); } /** * Disconnect the publisher from the remote MQTT broker. */ public void deactivate() { s_logger.info("Deactivating SmarthomePublisher..."); try { if (m_dataTransport != null) m_dataTransport.disconnect(m_timeout); } catch (Exception e) { e.printStackTrace(); } s_logger.info("Deactivating SmarthomePublisher... Done"); } @Override public void sensorChanged(String sensorName, Object newValue) { if (m_dataTransport != null && !m_dataTransport.isConnected()) { s_logger.error("No connected data transport - enable auto reconnect to re-establish connection"); } // Publish topic String topic = m_topicPrefix + "update"; // Message payload String payload = "{\"state\": {\"reported\": {\"" + sensorName + "\": " + newValue.toString() + "}}}"; try { // Publish the message m_dataTransport.publish(topic, payload.getBytes(), m_qos, m_retain); s_logger.info("Published to {} message: {}", new Object[] { topic, payload }); } catch (Exception e) { s_logger.error("Cannot publish to topic: {} reason: {}", new Object[] { topic, e.getCause() }); } } @Override public void onConnectionEstablished() { s_logger.info("SmarthomePublisher connected to MQTT broker"); try { m_sensorService.setActuatorValue("light", "on"); } catch (NoSuchSensorOrActuatorException e) { e.printStackTrace(); } } @Override public void onDisconnecting() { s_logger.info("SmarthomePublisher disconnecting from MQTT broker"); } @Override public void onDisconnected() { s_logger.info("SmarthomePublisher disconnected"); try { m_sensorService.setActuatorValue("light", "off"); } catch (NoSuchSensorOrActuatorException e) { e.printStackTrace(); } } @Override public void onConnectionLost(Throwable cause) { s_logger.warn("Connection to MQTT broker lost!" + cause.getMessage()); } @Override public void onMessageArrived(String topic, byte[] payload, int qos, boolean retained) { if (!topic.startsWith(m_topicPrefix)) { return; } if (topic.equals(m_topicPrefix + "update/rejected")) { // Parse the JSON message payload try { JSONObject obj = (JSONObject) parser.parse(new String(payload)); String code = (String) obj.get("code"); String message = (String) obj.get("message"); String timestamp = (String) obj.get("timestamp"); String clientToken = (String) obj.get("clientToken"); s_logger.error("AWS IoT thing update rejected - code: {} message: {} timestamp: {} clientToken: {}", new Object[] { code, message, timestamp, clientToken }); } catch (ParseException e) { s_logger.error("Error while parse AWS IoT thing update rejected message", e); } } } @Override public void onMessageConfirmed(int messageId, String topic) { } }