diff --git a/lora-codec-browan/pom.xml b/lora-codec-browan/pom.xml new file mode 100644 index 0000000000..17c96b2b6a --- /dev/null +++ b/lora-codec-browan/pom.xml @@ -0,0 +1,114 @@ + + + + 4.0.0 + + c8y.example + c8y-examples + ${revision}${changelist} + + lora-codec-browan + lora-codec-browan + http://maven.apache.org + + 2.3.3.RELEASE + lora-codec-browan + lora.Application + + + + + com.nsn.cumulocity.clients-java + microservice-dependencies + ${revision}${changelist} + pom + import + + + + + + com.nsn.cumulocity.clients-java + lpwan-custom-codec + ${c8y.version} + + + com.nsn.cumulocity.model + device-capability-model + ${c8y.version} + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot-dependencies.version} + + ${main.class} + + + + + repackage + + + + + + com.nsn.cumulocity.clients-java + microservice-package-maven-plugin + ${c8y.version} + + + package + package + + package + + + ${microservice.name} + ${microservice.name} + UTF-8 + + 92m + 172m + + + + + + + + + + + cumulocity + default + http://download.cumulocity.com/maven/repository + + + + + public + http://download.cumulocity.com/maven/repository + + + diff --git a/lora-codec-browan/src/main/configuration/cumulocity.json b/lora-codec-browan/src/main/configuration/cumulocity.json new file mode 100644 index 0000000000..294b88af07 --- /dev/null +++ b/lora-codec-browan/src/main/configuration/cumulocity.json @@ -0,0 +1,13 @@ +{ + "apiVersion":"1", + "version":"@project.version@", + "contextPath": "lora-codec-browan", + "provider": { + "name":"Software AG" + }, + "isolation":"MULTI_TENANT", + "requiredRoles": [ + "ROLE_INVENTORY_ADMIN", + "ROLE_INVENTORY_READ" + ] +} \ No newline at end of file diff --git a/lora-codec-browan/src/main/java/lora/Application.java b/lora-codec-browan/src/main/java/lora/Application.java new file mode 100644 index 0000000000..c8e5079ff1 --- /dev/null +++ b/lora-codec-browan/src/main/java/lora/Application.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2012-2020 Cumulocity GmbH + * Copyright (c) 2022 Software AG, Darmstadt, Germany and/or Software AG USA Inc., Reston, VA, USA, + * and/or its subsidiaries and/or its affiliates and/or their licensors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lora; + +import com.cumulocity.microservice.lpwan.codec.annotation.CodecMicroserviceApplication; +import org.springframework.boot.SpringApplication; + +@CodecMicroserviceApplication +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} \ No newline at end of file diff --git a/lora-codec-browan/src/main/java/lora/codec/browan/BrowanCodec.java b/lora-codec-browan/src/main/java/lora/codec/browan/BrowanCodec.java new file mode 100644 index 0000000000..a5af402bdd --- /dev/null +++ b/lora-codec-browan/src/main/java/lora/codec/browan/BrowanCodec.java @@ -0,0 +1,25 @@ +package lora.codec.browan; + +import java.util.Collections; +import java.util.Set; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +import org.springframework.stereotype.Component; + +import com.cumulocity.microservice.lpwan.codec.Codec; +import com.cumulocity.microservice.lpwan.codec.model.DeviceInfo; + +@Component +public class BrowanCodec implements Codec { + + @Override + public @NotNull @NotEmpty Set supportsDevices() { + + DeviceInfo airQualitySensor = new DeviceInfo("Browan", "TBHV110"); + return Collections.singleton(airQualitySensor); + } + + +} diff --git a/lora-codec-browan/src/main/java/lora/codec/browan/decoder/BrowanDecoder.java b/lora-codec-browan/src/main/java/lora/codec/browan/decoder/BrowanDecoder.java new file mode 100644 index 0000000000..4dbf26c929 --- /dev/null +++ b/lora-codec-browan/src/main/java/lora/codec/browan/decoder/BrowanDecoder.java @@ -0,0 +1,81 @@ +package lora.codec.browan.decoder; + +import java.math.BigDecimal; +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.Map; + +import org.joda.time.DateTime; +import org.springframework.stereotype.Component; + +import com.cumulocity.microservice.customdecoders.api.exception.DecoderServiceException; +import com.cumulocity.microservice.customdecoders.api.model.DecoderResult; +import com.cumulocity.microservice.customdecoders.api.model.MeasurementDto; +import com.cumulocity.microservice.customdecoders.api.model.MeasurementValueDto; +import com.cumulocity.microservice.customdecoders.api.service.DecoderService; +import com.cumulocity.microservice.lpwan.codec.decoder.model.LpwanDecoderInputData; +import com.cumulocity.model.event.CumulocitySeverities; +import com.cumulocity.model.idtype.GId; +import com.cumulocity.rest.representation.alarm.AlarmRepresentation; +import com.cumulocity.rest.representation.inventory.ManagedObjects; +import com.google.common.io.BaseEncoding; + +@Component +public class BrowanDecoder implements DecoderService { + + @Override + public DecoderResult decode(String inputData, GId deviceId, Map args) throws DecoderServiceException { + LpwanDecoderInputData decoderInput = new LpwanDecoderInputData(inputData, deviceId, args); + ByteBuffer buffer = ByteBuffer.wrap(BaseEncoding.base16().decode(inputData.toUpperCase())); + DecoderResult result = new DecoderResult(); + + if(decoderInput.getFport() == 103) { + buffer.get(); + buffer.get(); + int pcbTemperature = Byte.toUnsignedInt(buffer.get()) - 32; + result.addMeasurement(measurement(decoderInput, "pcb_Temperature", "T", pcbTemperature, "C")); + int humidity = Byte.toUnsignedInt(buffer.get()); + result.addMeasurement(measurement(decoderInput, "c8y_Humidity", "H", humidity, "%")); + int co2 = Short.toUnsignedInt(Short.reverseBytes(buffer.getShort())); + result.addMeasurement(measurement(decoderInput, "CO2", "C", co2, "ppm")); + int voc = Short.toUnsignedInt(Short.reverseBytes(buffer.getShort())); + result.addMeasurement(measurement(decoderInput, "VOC", "V", voc, "ppm")); + int iaq = Short.toUnsignedInt(Short.reverseBytes(buffer.getShort())); + result.addMeasurement(measurement(decoderInput, "IAQ", "Q", iaq, "Q")); + int envTemperature = Byte.toUnsignedInt(buffer.get()) - 32; + result.addMeasurement(measurement(decoderInput, "c8y_Temperature", "T", envTemperature, "C")); + + if(iaq > 100) { + result.addAlarm(alarm(deviceId, "AirQualityWarning", CumulocitySeverities.WARNING, + String.format("Air quality indicator > 100. Actual value: %d. Please open window", iaq)), true); + } + } else { + result.addAlarm(alarm(deviceId, "DecoderError", CumulocitySeverities.CRITICAL, String.format("Unknown port: %s", decoderInput.getFport())), true); + } + + return result; + } + + private AlarmRepresentation alarm(GId deviceId, String alarmType, CumulocitySeverities severity, String alarmText) { + AlarmRepresentation alarm = new AlarmRepresentation(); + alarm.setSource(ManagedObjects.asManagedObject(deviceId)); + alarm.setType(alarmType); + alarm.setSeverity(severity.name()); + alarm.setText(alarmText); + alarm.setDateTime(DateTime.now()); + return alarm; + } + + private MeasurementDto measurement(LpwanDecoderInputData decoderInput, String fragmentName, String seriesName, long v, String unit) { + MeasurementDto m = new MeasurementDto(); + m.setType(fragmentName); + m.setSeries(fragmentName); + MeasurementValueDto value = new MeasurementValueDto(); + value.setSeriesName(seriesName); + value.setValue(BigDecimal.valueOf(v)); + value.setUnit(unit); + m.setValues(Collections.singletonList(value)); + m.setTime(new DateTime(decoderInput.getUpdateTime() != null?decoderInput.getUpdateTime() : System.currentTimeMillis())); + return m; + } +} diff --git a/lora-codec-browan/src/main/java/lora/codec/browan/encoder/BrowanEncoder.java b/lora-codec-browan/src/main/java/lora/codec/browan/encoder/BrowanEncoder.java new file mode 100644 index 0000000000..0628b3c73f --- /dev/null +++ b/lora-codec-browan/src/main/java/lora/codec/browan/encoder/BrowanEncoder.java @@ -0,0 +1,22 @@ +package lora.codec.browan.encoder; + +import org.springframework.stereotype.Component; + +import com.cumulocity.microservice.customencoders.api.exception.EncoderServiceException; +import com.cumulocity.microservice.customencoders.api.model.EncoderInputData; +import com.cumulocity.microservice.customencoders.api.model.EncoderResult; +import com.cumulocity.microservice.customencoders.api.service.EncoderService; +import com.cumulocity.microservice.lpwan.codec.encoder.model.LpwanEncoderResult; + +@Component +public class BrowanEncoder implements EncoderService { + + @Override + public EncoderResult encode(EncoderInputData arg0) throws EncoderServiceException { + LpwanEncoderResult encoderResult = new LpwanEncoderResult(); + encoderResult.setSuccess(false); + encoderResult.setMessage("Encoding Payload Failed"); + return encoderResult; + } + +} diff --git a/lora-codec-browan/src/main/resources/application.properties b/lora-codec-browan/src/main/resources/application.properties new file mode 100644 index 0000000000..b1497bff21 --- /dev/null +++ b/lora-codec-browan/src/main/resources/application.properties @@ -0,0 +1,18 @@ +# +# Copyright (c) 2012-2020 Cumulocity GmbH +# Copyright (c) 2022 Software AG, Darmstadt, Germany and/or Software AG USA Inc., Reston, VA, USA, +# and/or its subsidiaries and/or its affiliates and/or their licensors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +application.name=lora-codec-browan \ No newline at end of file diff --git a/lora-codec-browan/src/main/resources/logback-spring.xml b/lora-codec-browan/src/main/resources/logback-spring.xml new file mode 100644 index 0000000000..e0ad568c38 --- /dev/null +++ b/lora-codec-browan/src/main/resources/logback-spring.xml @@ -0,0 +1,53 @@ + + + + + + + + + ${LOG_FILE} + + + ${LOG_FILE}.%d{yyyy-MM-dd}.log + + + 30 + 1GB + + + ${FILE_LOG_PATTERN} + + + + + + + + + + + + + + + + \ No newline at end of file