Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[luftdateninfo] Add internal sensor support #10643

Merged
merged 7 commits into from
May 13, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions bundles/org.openhab.binding.luftdateninfo/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# LuftdatenInfo Binding

<img align="right" src="./doc/logo-rund.png"/>

Binding for the Sensor Community [luftdaten.info](https://luftdaten.info/). The community provides instructions to build sensors on your own and they can be integrated into the database.
With this binding you can integrate your sensor, a sensor nearby or even any sensors you want into openHAB.

Expand All @@ -21,10 +19,21 @@ There's no auto discovery. See Thing configuration how to setup a Sensor.

## Thing Configuration

Choose either a local IP address of your personal owned sonsor _or_ a sensor id of an external one.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Choose either a local IP address of your personal owned sonsor _or_ a sensor id of an external one.
Choose either a local IP address of your personal owned sensor _or_ a sensor id of an external one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


| Parameter | Description |
|-----------------|----------------------------------------------------------------------|
| ipAddress | Local IP address of your personal owned sensor |
| sensorid | Sensor ID obtained from https://deutschland.maps.sensor.community/ |

### Local Sensor

Please check in your browser if you can access your sensor with your local IP address.

![Luftdaten.info Logo](doc/local-sensor.png)

### External Sensor

Perform the following steps to get the appropriate Sensor ID

* Go to to [luftdaten.info map](https://deutschland.maps.sensor.community/)
Expand Down Expand Up @@ -69,9 +78,9 @@ Perform the following steps to get the appropriate Sensor ID
luftdaten.things

```
Thing luftdateninfo:particulate:pm_sensor "PM Sensor" [ sensorid=28842]
Thing luftdateninfo:conditions:cond_sensor "Condition Sensor" [ sensorid=28843]
Thing luftdateninfo:noise:noise_sensor "Noise Sensor" [ sensorid=39745]
Thing luftdateninfo:particulate:pm_sensor "PM Sensor" [ ipAddress=192.168.178.50 ]
Thing luftdateninfo:conditions:cond_sensor "Condition Sensor" [ sensorid=28843 ]
Thing luftdateninfo:noise:noise_sensor "Noise Sensor" [ sensorid=39745 ]
```

### Items
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package org.openhab.binding.luftdateninfo.internal;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.luftdateninfo.internal.utils.Constants;

/**
* The {@link LuftdatenInfoConfiguration} class contains fields mapping thing configuration parameters.
Expand All @@ -22,5 +23,7 @@
@NonNullByDefault
public class LuftdatenInfoConfiguration {

public int sensorid = -1;
public int sensorid = Constants.UNDEF;

public String ipAddress = Constants.EMPTY;
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,9 @@ public LuftdatenInfoHandlerFactory(final @Reference HttpClientFactory httpClient

@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
if (thingTypeUID.equals(LuftdatenInfoBindingConstants.THING_TYPE_PARTICULATE)
return (thingTypeUID.equals(LuftdatenInfoBindingConstants.THING_TYPE_PARTICULATE)
|| thingTypeUID.equals(LuftdatenInfoBindingConstants.THING_TYPE_CONDITIONS)
|| thingTypeUID.equals(LuftdatenInfoBindingConstants.THING_TYPE_NOISE)) {
return true;
} else {
return false;
}
|| thingTypeUID.equals(LuftdatenInfoBindingConstants.THING_TYPE_NOISE));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
package org.openhab.binding.luftdateninfo.internal.handler;

import java.time.LocalDateTime;
import java.util.Optional;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.luftdateninfo.internal.LuftdatenInfoConfiguration;
import org.openhab.binding.luftdateninfo.internal.utils.Constants;
import org.openhab.binding.luftdateninfo.internal.utils.DateTimeUtils;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
Expand Down Expand Up @@ -48,9 +50,12 @@ public abstract class BaseSensorHandler extends BaseThingHandler {
protected ThingStatus myThingStatus = ThingStatus.UNKNOWN;
protected UpdateStatus lastUpdateStatus = UpdateStatus.UNKNOWN;
protected @Nullable ScheduledFuture<?> refreshJob;
private Optional<String> sensorUrl = Optional.empty();
private boolean firstUpdate = true;

public enum ConfigStatus {
OK,
INTERNAL_SENSOR_OK,
EXTERNAL_SENSOR_OK,
IS_NULL,
SENSOR_IS_NULL,
SENSOR_ID_NEGATIVE,
Expand Down Expand Up @@ -88,14 +93,15 @@ public void handleCommand(ChannelUID channelUID, Command command) {

@Override
public void initialize() {
firstUpdate = true;
lifecycleStatus = LifecycleStatus.INITIALIZING;
scheduler.execute(this::startUp);
}

private void startUp() {
config = getConfigAs(LuftdatenInfoConfiguration.class);
configStatus = checkConfig(config);
if (configStatus == ConfigStatus.OK) {
if (configStatus == ConfigStatus.INTERNAL_SENSOR_OK || configStatus == ConfigStatus.EXTERNAL_SENSOR_OK) {
// start getting values
dataUpdate();
} else {
Expand Down Expand Up @@ -135,10 +141,16 @@ public void dispose() {
*/
private ConfigStatus checkConfig(@Nullable LuftdatenInfoConfiguration c) {
if (c != null) {
if (c.sensorid >= 0) {
return ConfigStatus.OK;
if (c.ipAddress != null && !Constants.EMPTY.equals(c.ipAddress)) {
sensorUrl = Optional.of("http://" + c.ipAddress + "/data.json");
return ConfigStatus.INTERNAL_SENSOR_OK;
} else {
return ConfigStatus.SENSOR_ID_NEGATIVE;
if (c.sensorid >= 0) {
sensorUrl = Optional.of("http://data.sensor.community/airrohr/v1/sensor/" + c.sensorid + "/");
return ConfigStatus.EXTERNAL_SENSOR_OK;
} else {
return ConfigStatus.SENSOR_ID_NEGATIVE;
}
}
} else {
return ConfigStatus.IS_NULL;
Expand All @@ -150,11 +162,21 @@ public LifecycleStatus getLifecycleStatus() {
}

protected void dataUpdate() {
HTTPHandler.getHandler().request(config.sensorid, this);
if (sensorUrl.isPresent()) {
HTTPHandler.getHandler().request(sensorUrl.get(), this);
}
}

public void onResponse(String data) {
lastUpdateStatus = updateChannels(data);
if (firstUpdate) {
logger.debug("{} delivers {}", sensorUrl.get(), data);
firstUpdate = false;
}
if (configStatus == ConfigStatus.INTERNAL_SENSOR_OK) {
lastUpdateStatus = updateChannels("[" + data + "]");
} else {
lastUpdateStatus = updateChannels(data);
}
statusUpdate(lastUpdateStatus, EMPTY);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
package org.openhab.binding.luftdateninfo.internal.handler;

import static org.openhab.binding.luftdateninfo.internal.LuftdatenInfoBindingConstants.*;
import static org.openhab.binding.luftdateninfo.internal.handler.HTTPHandler.*;
import static org.openhab.binding.luftdateninfo.internal.utils.Constants.*;
import static org.openhab.core.library.unit.MetricPrefix.HECTO;

import java.util.List;

Expand All @@ -38,11 +39,10 @@
*/
@NonNullByDefault
public class ConditionHandler extends BaseSensorHandler {

protected QuantityType<Temperature> temperatureCache = QuantityType.valueOf(-1, SIUnits.CELSIUS);
protected QuantityType<Dimensionless> humidityCache = QuantityType.valueOf(-1, Units.PERCENT);
protected QuantityType<Pressure> pressureCache = QuantityType.valueOf(-1, SIUnits.PASCAL);
protected QuantityType<Pressure> pressureSeaCache = QuantityType.valueOf(-1, SIUnits.PASCAL);
protected QuantityType<Pressure> pressureCache = QuantityType.valueOf(-1, HECTO(SIUnits.PASCAL));
protected QuantityType<Pressure> pressureSeaCache = QuantityType.valueOf(-1, HECTO(SIUnits.PASCAL));

public ConditionHandler(Thing thing) {
super(thing);
Expand All @@ -55,18 +55,22 @@ public UpdateStatus updateChannels(@Nullable String json) {
if (valueList != null) {
if (HTTPHandler.getHandler().isCondition(valueList)) {
valueList.forEach(v -> {
if (v.getValueType().equals(TEMPERATURE)) {
if (v.getValueType().endsWith(TEMPERATURE)) {
temperatureCache = QuantityType.valueOf(NumberUtils.round(v.getValue(), 1),
SIUnits.CELSIUS);
updateState(TEMPERATURE_CHANNEL, temperatureCache);
} else if (v.getValueType().equals(HUMIDITY)) {
} else if (v.getValueType().endsWith(HUMIDITY)) {
humidityCache = QuantityType.valueOf(NumberUtils.round(v.getValue(), 1), Units.PERCENT);
updateState(HUMIDITY_CHANNEL, humidityCache);
} else if (v.getValueType().equals(PRESSURE)) {
pressureCache = QuantityType.valueOf(NumberUtils.round(v.getValue(), 1), SIUnits.PASCAL);
} else if (v.getValueType().endsWith(PRESSURE)) {
pressureCache = QuantityType.valueOf(
NumberUtils.round(NumberUtils.convert(v.getValue()) / 100, 1),
HECTO(SIUnits.PASCAL));
updateState(PRESSURE_CHANNEL, pressureCache);
} else if (v.getValueType().equals(PRESSURE_SEALEVEL)) {
pressureSeaCache = QuantityType.valueOf(NumberUtils.round(v.getValue(), 1), SIUnits.PASCAL);
} else if (v.getValueType().endsWith(PRESSURE_SEALEVEL)) {
pressureSeaCache = QuantityType.valueOf(
NumberUtils.round(NumberUtils.convert(v.getValue()) / 100, 1),
HECTO(SIUnits.PASCAL));
updateState(PRESSURE_SEA_CHANNEL, pressureSeaCache);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
*/
package org.openhab.binding.luftdateninfo.internal.handler;

import static org.openhab.binding.luftdateninfo.internal.utils.Constants.*;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
Expand Down Expand Up @@ -42,19 +44,6 @@ public class HTTPHandler {
private static final Gson GSON = new Gson();
private static final HTTPHandler HTTP_HANDLER = new HTTPHandler();

public static final String P1 = "P1";
public static final String P2 = "P2";

public static final String TEMPERATURE = "temperature";
public static final String HUMIDITY = "humidity";
public static final String PRESSURE = "pressure";
public static final String PRESSURE_SEALEVEL = "pressure_at_sealevel";

public static final String NOISE_EQ = "noise_LAeq";
public static final String NOISE_MIN = "noise_LA_min";
public static final String NOISE_MAX = "noise_LA_max";

private static String sensorUrl = "http://data.sensor.community/airrohr/v1/sensor/";
private static @Nullable HttpClient commonHttpClient;

public static void init(HttpClient httpClient) {
Expand All @@ -65,12 +54,11 @@ public static HTTPHandler getHandler() {
return HTTP_HANDLER;
}

public synchronized void request(int sensorId, BaseSensorHandler callback) {
public synchronized void request(String url, BaseSensorHandler callback) {
HttpClient localClient = commonHttpClient;
if (localClient == null) {
logger.warn("HTTP Client not initialized");
} else {
String url = sensorUrl + sensorId + "/";
Request req = localClient.newRequest(url);
req.timeout(15, TimeUnit.SECONDS).send(new BufferingResponseListener() {
@NonNullByDefault({})
Expand Down Expand Up @@ -142,24 +130,24 @@ public boolean isParticulate(@Nullable List<SensorDataValue> valueList) {
if (valueList == null) {
return false;
}
return valueList.stream().map(v -> v.getValueType()).filter(t -> t.equals(P1) || t.equals(P2)).findAny()
return valueList.stream().map(v -> v.getValueType()).filter(t -> t.endsWith(P1) || t.endsWith(P2)).findAny()
.isPresent();
}

public boolean isCondition(@Nullable List<SensorDataValue> valueList) {
if (valueList == null) {
return false;
}
return valueList.stream().map(v -> v.getValueType()).filter(
t -> t.equals(TEMPERATURE) || t.equals(HUMIDITY) || t.equals(PRESSURE) || t.equals(PRESSURE_SEALEVEL))
.findAny().isPresent();
return valueList.stream().map(v -> v.getValueType()).filter(t -> t.equals(TEMPERATURE) || t.endsWith(HUMIDITY)
|| t.endsWith(PRESSURE) || t.endsWith(PRESSURE_SEALEVEL)).findAny().isPresent();
}

public boolean isNoise(@Nullable List<SensorDataValue> valueList) {
if (valueList == null) {
return false;
}
return valueList.stream().map(v -> v.getValueType())
.filter(t -> t.equals(NOISE_EQ) || t.equals(NOISE_MAX) || t.equals(NOISE_MIN)).findAny().isPresent();
.filter(t -> t.endsWith(NOISE_EQ) || t.endsWith(NOISE_MAX) || t.endsWith(NOISE_MIN)).findAny()
.isPresent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
package org.openhab.binding.luftdateninfo.internal.handler;

import static org.openhab.binding.luftdateninfo.internal.LuftdatenInfoBindingConstants.*;
import static org.openhab.binding.luftdateninfo.internal.handler.HTTPHandler.*;
import static org.openhab.binding.luftdateninfo.internal.utils.Constants.*;

import java.util.List;

Expand Down Expand Up @@ -50,13 +50,13 @@ public UpdateStatus updateChannels(@Nullable String json) {
if (valueList != null) {
if (HTTPHandler.getHandler().isNoise(valueList)) {
valueList.forEach(v -> {
if (v.getValueType().equals(NOISE_EQ)) {
if (v.getValueType().endsWith(NOISE_EQ)) {
noiseEQCache = QuantityType.valueOf(NumberUtils.round(v.getValue(), 1), Units.DECIBEL);
updateState(NOISE_EQ_CHANNEL, noiseEQCache);
} else if (v.getValueType().equals(NOISE_MIN)) {
} else if (v.getValueType().endsWith(NOISE_MIN)) {
noiseMinCache = QuantityType.valueOf(NumberUtils.round(v.getValue(), 1), Units.DECIBEL);
updateState(NOISE_MIN_CHANNEL, noiseMinCache);
} else if (v.getValueType().equals(NOISE_MAX)) {
} else if (v.getValueType().endsWith(NOISE_MAX)) {
noiseMaxCache = QuantityType.valueOf(NumberUtils.round(v.getValue(), 1), Units.DECIBEL);
updateState(NOISE_MAX_CHANNEL, noiseMaxCache);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
package org.openhab.binding.luftdateninfo.internal.handler;

import static org.openhab.binding.luftdateninfo.internal.LuftdatenInfoBindingConstants.*;
import static org.openhab.binding.luftdateninfo.internal.handler.HTTPHandler.*;
import static org.openhab.binding.luftdateninfo.internal.utils.Constants.*;

import java.util.List;

Expand Down Expand Up @@ -49,11 +49,11 @@ public UpdateStatus updateChannels(@Nullable String json) {
if (valueList != null) {
if (HTTPHandler.getHandler().isParticulate(valueList)) {
valueList.forEach(v -> {
if (v.getValueType().equals(P1)) {
if (v.getValueType().endsWith(P1)) {
pm100Cache = QuantityType.valueOf(NumberUtils.round(v.getValue(), 1),
Units.MICROGRAM_PER_CUBICMETRE);
updateState(PM100_CHANNEL, pm100Cache);
} else if (v.getValueType().equals(P2)) {
} else if (v.getValueType().endsWith(P2)) {
pm25Cache = QuantityType.valueOf(NumberUtils.round(v.getValue(), 1),
Units.MICROGRAM_PER_CUBICMETRE);
updateState(PM25_CHANNEL, pm25Cache);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.luftdateninfo.internal.utils;

import org.eclipse.jdt.annotation.NonNullByDefault;

/**
* The {@link Constants} Constants used in this binding
*
* @author Bernd Weymann - Initial contribution
*/
@NonNullByDefault
public class Constants {
public static final String EMPTY = "";
public static final String P1 = "P1";
public static final String P2 = "P2";

public static final String TEMPERATURE = "temperature";
public static final String HUMIDITY = "humidity";
public static final String PRESSURE = "pressure";
public static final String PRESSURE_SEALEVEL = "pressure_at_sealevel";

public static final String NOISE_EQ = "noise_LAeq";
public static final String NOISE_MIN = "noise_LA_min";
public static final String NOISE_MAX = "noise_LA_max";
public static final int UNDEF = -1;
}
Loading