@PUT @Path("device/{deviceId}/policy") public Response updatePolicy( @PathParam("deviceId") String deviceId, @QueryParam("protocol") String protocol, @FormParam("policy") String policy) { String protocolString = protocol.toUpperCase(); if (log.isDebugEnabled()) { log.debug( "Sending request to update-policy of device [" + deviceId + "] via " + protocolString); } try { if (!APIUtil.getDeviceAccessAuthorizationService() .isUserAuthorized( new DeviceIdentifier(deviceId, VirtualFireAlarmConstants.DEVICE_TYPE), DeviceGroupConstants.Permissions.DEFAULT_MANAGE_POLICIES_PERMISSIONS)) { return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build(); } PrivateKey serverPrivateKey = VirtualFirealarmSecurityManager.getServerPrivateKey(); String actualMessage = VirtualFireAlarmConstants.POLICY_CONTEXT + ":" + policy; String encryptedMsg = VirtualFireAlarmServiceUtils.prepareSecurePayLoad(actualMessage, serverPrivateKey); Map<String, String> dynamicProperties = new HashMap<>(); switch (protocolString) { case XMPP_PROTOCOL: dynamicProperties.put( VirtualFireAlarmConstants.JID_PROPERTY_KEY, deviceId + "@" + XmppConfig.getInstance().getServerName()); dynamicProperties.put(VirtualFireAlarmConstants.SUBJECT_PROPERTY_KEY, "POLICTY-REQUEST"); dynamicProperties.put( VirtualFireAlarmConstants.MESSAGE_TYPE_PROPERTY_KEY, VirtualFireAlarmConstants.CHAT_PROPERTY_KEY); APIUtil.getOutputEventAdapterService() .publish( VirtualFireAlarmConstants.XMPP_ADAPTER_NAME, dynamicProperties, encryptedMsg); break; default: String publishTopic = APIUtil.getTenantDomainOftheUser() + "/" + VirtualFireAlarmConstants.DEVICE_TYPE + "/" + deviceId; dynamicProperties.put(VirtualFireAlarmConstants.ADAPTER_TOPIC_PROPERTY, publishTopic); APIUtil.getOutputEventAdapterService() .publish( VirtualFireAlarmConstants.MQTT_ADAPTER_NAME, dynamicProperties, encryptedMsg); break; } return Response.ok().build(); } catch (DeviceAccessAuthorizationException e) { log.error(e.getErrorMessage(), e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } catch (VirtualFireAlarmException e) { log.error(e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } }
/** * {@inheritDoc} VirtualFirealarm device-type specific implementation to publish data to the * device. This method calls the {@link #publishToQueue(String, MqttMessage)} method of the * "MQTTTransportHandler" class. */ @Override public void publishDeviceData(String... publishData) throws TransportHandlerException { if (publishData.length != 4) { String errorMsg = "Incorrect number of arguments received to SEND-MQTT Message. " + "Need to be [owner, deviceId, resource{BULB/TEMP}, state{ON/OFF or null}]"; log.error(errorMsg); throw new TransportHandlerException(errorMsg); } String deviceOwner = publishData[0]; String deviceId = publishData[1]; String resource = publishData[2]; String state = publishData[3]; MqttMessage pushMessage = new MqttMessage(); String publishTopic = "wso2/" + VirtualFireAlarmConstants.DEVICE_TYPE + "/" + deviceId; try { PublicKey devicePublicKey = VirtualFireAlarmServiceUtils.getDevicePublicKey(deviceId); PrivateKey serverPrivateKey = SecurityManager.getServerPrivateKey(); String actualMessage = resource + ":" + state; String encryptedMsg = VirtualFireAlarmServiceUtils.prepareSecurePayLoad( actualMessage, devicePublicKey, serverPrivateKey); pushMessage.setPayload(encryptedMsg.getBytes(StandardCharsets.UTF_8)); pushMessage.setQos(DEFAULT_MQTT_QUALITY_OF_SERVICE); pushMessage.setRetained(false); publishToQueue(publishTopic, pushMessage); } catch (VirtualFireAlarmException e) { String errorMsg = "Preparing Secure payload failed for device - [" + deviceId + "] of owner - " + "[" + deviceOwner + "]."; log.error(errorMsg); throw new TransportHandlerException(errorMsg, e); } }
/** * {@inheritDoc} VirtualFirealarm device-type specific implementation to process incoming * messages. This is the specific method signature of the overloaded "processIncomingMessage" * method that gets called from the messageArrived() callback of the "MQTTTransportHandler". */ @Override public void processIncomingMessage(MqttMessage mqttMessage, String... messageParams) { if (messageParams.length != 0) { // owner and the deviceId are extracted from the MQTT topic to which the message was received. // <Topic> = [ServerName/Owner/DeviceType/DeviceId/"publisher"] String topic = messageParams[0]; String[] topicParams = topic.split("/"); String deviceId = topicParams[2]; if (log.isDebugEnabled()) { log.debug("Received MQTT message for: [DEVICE.ID-" + deviceId + "]"); } String actualMessage; try { // the hash-code of the deviceId is used as the alias for device certificates during SCEP // enrollment. // hence, the same is used here to fetch the device-specific-certificate from the key store. PublicKey clientPublicKey = VirtualFireAlarmServiceUtils.getDevicePublicKey(deviceId); PrivateKey serverPrivateKey = SecurityManager.getServerPrivateKey(); // the MQTT-messages from VirtualFireAlarm devices are in the form {"Msg":<MESSAGE>, // "Sig":<SIGNATURE>} actualMessage = VirtualFireAlarmServiceUtils.extractMessageFromPayload( mqttMessage.toString(), serverPrivateKey, clientPublicKey); if (log.isDebugEnabled()) { log.debug("MQTT: Received Message [" + actualMessage + "] topic: [" + topic + "]"); } if (actualMessage.contains("PUBLISHER")) { float temperature = Float.parseFloat(actualMessage.split(":")[2]); try { PrivilegedCarbonContext.startTenantFlow(); PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); DeviceManagementProviderService deviceManagementProviderService = (DeviceManagementProviderService) ctx.getOSGiService(DeviceManagementProviderService.class, null); if (deviceManagementProviderService != null) { DeviceIdentifier identifier = new DeviceIdentifier(deviceId, VirtualFireAlarmConstants.DEVICE_TYPE); Device device = deviceManagementProviderService.getDevice(identifier); if (device != null) { String owner = device.getEnrolmentInfo().getOwner(); ctx.setTenantDomain(MultitenantUtils.getTenantDomain(owner), true); ctx.setUsername(owner); if (!VirtualFireAlarmServiceUtils.publishToDAS(deviceId, temperature)) { log.error("MQTT Subscriber: Publishing data to DAS failed."); } } } } catch (DeviceManagementException e) { log.error( "Failed to retreive the device managment service for device type " + VirtualFireAlarmConstants.DEVICE_TYPE, e); } finally { PrivilegedCarbonContext.endTenantFlow(); } if (log.isDebugEnabled()) { log.debug("MQTT Subscriber: Published data to DAS successfully."); } } else if (actualMessage.contains("TEMPERATURE")) { String temperatureValue = actualMessage.split(":")[1]; } } catch (VirtualFireAlarmException e) { String errorMsg = "CertificateManagementService failure oo Signature-Verification/Decryption was unsuccessful."; log.error(errorMsg, e); } } else { String errorMsg = "MQTT message [" + mqttMessage.toString() + "] was received without the topic information."; log.warn(errorMsg); } }
@POST @Path("device/{deviceId}/buzz") public Response switchBuzzer( @PathParam("deviceId") String deviceId, @FormParam("state") String state) { if (state == null || state.isEmpty()) { log.error("State is not defined for the buzzer operation"); return Response.status(Response.Status.BAD_REQUEST).build(); } String switchToState = state.toUpperCase(); if (!switchToState.equals(VirtualFireAlarmConstants.STATE_ON) && !switchToState.equals(VirtualFireAlarmConstants.STATE_OFF)) { log.error("The requested state change shoud be either - 'ON' or 'OFF'"); return Response.status(Response.Status.BAD_REQUEST).build(); } try { if (!APIUtil.getDeviceAccessAuthorizationService() .isUserAuthorized( new DeviceIdentifier(deviceId, VirtualFireAlarmConstants.DEVICE_TYPE), DeviceGroupConstants.Permissions.DEFAULT_OPERATOR_PERMISSIONS)) { return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build(); } String resource = VirtualFireAlarmConstants.BULB_CONTEXT.replace("/", ""); PrivateKey serverPrivateKey = VirtualFirealarmSecurityManager.getServerPrivateKey(); String actualMessage = resource + ":" + switchToState; String encryptedMsg = VirtualFireAlarmServiceUtils.prepareSecurePayLoad(actualMessage, serverPrivateKey); String publishTopic = APIUtil.getTenantDomainOftheUser() + "/" + VirtualFireAlarmConstants.DEVICE_TYPE + "/" + deviceId; Operation commandOp = new CommandOperation(); commandOp.setCode("buzz"); commandOp.setType(Operation.Type.COMMAND); commandOp.setEnabled(true); commandOp.setPayLoad(encryptedMsg); Properties props = new Properties(); props.setProperty(VirtualFireAlarmConstants.MQTT_ADAPTER_TOPIC_PROPERTY_NAME, publishTopic); props.setProperty( VirtualFireAlarmConstants.CLIENT_JID_PROPERTY_KEY, deviceId + "@" + XmppConfig.getInstance().getServerName()); props.setProperty(VirtualFireAlarmConstants.SUBJECT_PROPERTY_KEY, "CONTROL-REQUEST"); props.setProperty( VirtualFireAlarmConstants.MESSAGE_TYPE_PROPERTY_KEY, VirtualFireAlarmConstants.CHAT_PROPERTY_KEY); commandOp.setProperties(props); List<DeviceIdentifier> deviceIdentifiers = new ArrayList<>(); deviceIdentifiers.add(new DeviceIdentifier(deviceId, VirtualFireAlarmConstants.DEVICE_TYPE)); APIUtil.getDeviceManagementService() .addOperation(VirtualFireAlarmConstants.DEVICE_TYPE, commandOp, deviceIdentifiers); return Response.ok().build(); } catch (DeviceAccessAuthorizationException e) { log.error(e.getErrorMessage(), e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } catch (VirtualFireAlarmException e) { String errorMsg = "Preparing Secure payload failed for device - [" + deviceId + "]"; log.error(errorMsg); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } catch (OperationManagementException e) { String msg = "Error occurred while executing command operation upon ringing the buzzer"; log.error(msg, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } }