mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-27 07:41:39 +01:00
[netatmo] Fix Live Picture not always available (#16679)
* Adressing issue on live picture Signed-off-by: gael@lhopital.org <gael@lhopital.org> Signed-off-by: root <gael@lhopital.org> Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
parent
a8f8ccb24e
commit
d84a4b1154
@ -528,7 +528,7 @@ Warnings:
|
|||||||
| status | monitoring | Switch | Read-write | State of the camera (video surveillance on/off) |
|
| status | monitoring | Switch | Read-write | State of the camera (video surveillance on/off) |
|
||||||
| status | sd-card | String | Read-only | State of the SD card |
|
| status | sd-card | String | Read-only | State of the SD card |
|
||||||
| status | alim | String | Read-only | State of the power connector |
|
| status | alim | String | Read-only | State of the power connector |
|
||||||
| live | picture | Image | Read-only | Camera Live Snapshot |
|
| live | picture (**) | Image | Read-only | Camera Live Snapshot |
|
||||||
| live | local-picture-url | String | Read-only | Local Url of the live snapshot for this camera |
|
| live | local-picture-url | String | Read-only | Local Url of the live snapshot for this camera |
|
||||||
| live | vpn-picture-url | String | Read-only | Url of the live snapshot for this camera through Netatmo VPN. |
|
| live | vpn-picture-url | String | Read-only | Url of the live snapshot for this camera through Netatmo VPN. |
|
||||||
| live | local-stream-url (*) | String | Read-only | Local Url of the live stream for this camera (accessible if openhab server and camera are located on the same lan. |
|
| live | local-stream-url (*) | String | Read-only | Local Url of the live stream for this camera (accessible if openhab server and camera are located on the same lan. |
|
||||||
@ -547,6 +547,7 @@ Warnings:
|
|||||||
| last-event | person-id | String | Read-only | Id of the person the event is about (if any) |
|
| last-event | person-id | String | Read-only | Id of the person the event is about (if any) |
|
||||||
|
|
||||||
(*) This channel is configurable : low, poor, high.
|
(*) This channel is configurable : low, poor, high.
|
||||||
|
(**) This channel handles the REFRESH command for on demand update.
|
||||||
|
|
||||||
**Supported channels for the Presence Camera thing:**
|
**Supported channels for the Presence Camera thing:**
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ public class WebhookEvent extends Event {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable String getPersonId() {
|
public @Nullable String getPersonId() {
|
||||||
return persons.size() > 0 ? persons.keySet().iterator().next() : null;
|
return persons.isEmpty() ? null : persons.keySet().iterator().next();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -40,6 +40,7 @@ import org.openhab.core.config.core.Configuration;
|
|||||||
import org.openhab.core.library.types.OnOffType;
|
import org.openhab.core.library.types.OnOffType;
|
||||||
import org.openhab.core.thing.ChannelUID;
|
import org.openhab.core.thing.ChannelUID;
|
||||||
import org.openhab.core.types.Command;
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.RefreshType;
|
||||||
import org.openhab.core.types.State;
|
import org.openhab.core.types.State;
|
||||||
import org.openhab.core.types.StateOption;
|
import org.openhab.core.types.StateOption;
|
||||||
import org.openhab.core.types.UnDefType;
|
import org.openhab.core.types.UnDefType;
|
||||||
@ -141,6 +142,9 @@ public class CameraCapability extends HomeSecurityThingCapability {
|
|||||||
public void handleCommand(String channelName, Command command) {
|
public void handleCommand(String channelName, Command command) {
|
||||||
if (command instanceof OnOffType && CHANNEL_MONITORING.equals(channelName)) {
|
if (command instanceof OnOffType && CHANNEL_MONITORING.equals(channelName)) {
|
||||||
getSecurityCapability().ifPresent(cap -> cap.changeStatus(localUrl, OnOffType.ON.equals(command)));
|
getSecurityCapability().ifPresent(cap -> cap.changeStatus(localUrl, OnOffType.ON.equals(command)));
|
||||||
|
} else if (command instanceof RefreshType && CHANNEL_LIVEPICTURE.equals(channelName)) {
|
||||||
|
handler.updateState(GROUP_CAM_LIVE, CHANNEL_LIVEPICTURE,
|
||||||
|
toRawType(cameraHelper.getLivePictureURL(localUrl != null, true)));
|
||||||
} else {
|
} else {
|
||||||
super.handleCommand(channelName, command);
|
super.handleCommand(channelName, command);
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ import org.openhab.core.types.UnDefType;
|
|||||||
public class CameraChannelHelper extends ChannelHelper {
|
public class CameraChannelHelper extends ChannelHelper {
|
||||||
private static final String QUALITY_CONF_ENTRY = "quality";
|
private static final String QUALITY_CONF_ENTRY = "quality";
|
||||||
private static final String LIVE_PICTURE = "/live/snapshot_720.jpg";
|
private static final String LIVE_PICTURE = "/live/snapshot_720.jpg";
|
||||||
private boolean isLocal;
|
|
||||||
private @Nullable String vpnUrl;
|
private @Nullable String vpnUrl;
|
||||||
private @Nullable String localUrl;
|
private @Nullable String localUrl;
|
||||||
|
|
||||||
@ -44,56 +44,66 @@ public class CameraChannelHelper extends ChannelHelper {
|
|||||||
super(providedGroups);
|
super(providedGroups);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUrls(String vpnUrl, @Nullable String localUrl) {
|
public void setUrls(@Nullable String vpnUrl, @Nullable String localUrl) {
|
||||||
this.localUrl = localUrl;
|
this.localUrl = localUrl;
|
||||||
this.vpnUrl = vpnUrl;
|
this.vpnUrl = vpnUrl;
|
||||||
this.isLocal = localUrl != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable String getLocalURL() {
|
|
||||||
return localUrl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected @Nullable State internalGetProperty(String channelId, NAThing naThing, Configuration config) {
|
protected @Nullable State internalGetProperty(String channelId, NAThing naThing, Configuration config) {
|
||||||
if (naThing instanceof HomeStatusModule camera) {
|
if (naThing instanceof HomeStatusModule camera) {
|
||||||
boolean isMonitoring = OnOffType.ON.equals(camera.getMonitoring());
|
return switch (channelId) {
|
||||||
switch (channelId) {
|
case CHANNEL_MONITORING -> camera.getMonitoring();
|
||||||
case CHANNEL_MONITORING:
|
case CHANNEL_SD_CARD -> toStringType(camera.getSdStatus());
|
||||||
return camera.getMonitoring();
|
case CHANNEL_ALIM_STATUS -> toStringType(camera.getAlimStatus());
|
||||||
case CHANNEL_SD_CARD:
|
default -> liveChannels(channelId, (String) config.get(QUALITY_CONF_ENTRY), camera,
|
||||||
return toStringType(camera.getSdStatus());
|
OnOffType.ON.equals(camera.getMonitoring()), localUrl != null);
|
||||||
case CHANNEL_ALIM_STATUS:
|
};
|
||||||
return toStringType(camera.getAlimStatus());
|
|
||||||
case CHANNEL_LIVEPICTURE_VPN_URL:
|
|
||||||
return toStringType(getLivePictureURL(false, isMonitoring));
|
|
||||||
case CHANNEL_LIVEPICTURE_LOCAL_URL:
|
|
||||||
return toStringType(getLivePictureURL(true, isMonitoring));
|
|
||||||
case CHANNEL_LIVEPICTURE:
|
|
||||||
return toRawType(getLivePictureURL(isLocal, isMonitoring));
|
|
||||||
case CHANNEL_LIVESTREAM_VPN_URL:
|
|
||||||
return getLiveStreamURL(false, (String) config.get(QUALITY_CONF_ENTRY), isMonitoring);
|
|
||||||
case CHANNEL_LIVESTREAM_LOCAL_URL:
|
|
||||||
return getLiveStreamURL(true, (String) config.get(QUALITY_CONF_ENTRY), isMonitoring);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private @Nullable String getLivePictureURL(boolean local, boolean isMonitoring) {
|
public @Nullable String getLivePictureURL(boolean local, boolean isMonitoring) {
|
||||||
String url = local ? localUrl : vpnUrl;
|
String url = getUrl(local);
|
||||||
if (!isMonitoring || (local && !isLocal) || url == null) {
|
if (!isMonitoring || url == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return "%s%s".formatted(url, LIVE_PICTURE);
|
return "%s%s".formatted(url, LIVE_PICTURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private @Nullable State liveChannels(String channelId, String qualityConf, HomeStatusModule camera,
|
||||||
|
boolean isMonitoring, boolean isLocal) {
|
||||||
|
if (vpnUrl == null) {
|
||||||
|
setUrls(camera.getVpnUrl(), localUrl);
|
||||||
|
}
|
||||||
|
return switch (channelId) {
|
||||||
|
case CHANNEL_LIVESTREAM_LOCAL_URL ->
|
||||||
|
isLocal ? getLiveStreamURL(true, qualityConf, isMonitoring) : UnDefType.NULL;
|
||||||
|
case CHANNEL_LIVEPICTURE_LOCAL_URL ->
|
||||||
|
isLocal ? toStringType(getLivePictureURL(true, isMonitoring)) : UnDefType.NULL;
|
||||||
|
case CHANNEL_LIVESTREAM_VPN_URL -> getLiveStreamURL(false, qualityConf, isMonitoring);
|
||||||
|
case CHANNEL_LIVEPICTURE_VPN_URL -> toStringType(getLivePictureURL(false, isMonitoring));
|
||||||
|
case CHANNEL_LIVEPICTURE -> {
|
||||||
|
State result = toRawType(getLivePictureURL(isLocal, isMonitoring));
|
||||||
|
if (UnDefType.NULL.equals(result) && isLocal) {// If local read is unsuccessfull, try the VPN version
|
||||||
|
result = toRawType(getLivePictureURL(false, isMonitoring));
|
||||||
|
}
|
||||||
|
yield result;
|
||||||
|
}
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private @Nullable String getUrl(boolean local) {
|
||||||
|
return local ? localUrl : vpnUrl;
|
||||||
|
}
|
||||||
|
|
||||||
private State getLiveStreamURL(boolean local, @Nullable String configQual, boolean isMonitoring) {
|
private State getLiveStreamURL(boolean local, @Nullable String configQual, boolean isMonitoring) {
|
||||||
String url = local ? localUrl : vpnUrl;
|
String url = getUrl(local);
|
||||||
if (!isMonitoring || (local && !isLocal) || url == null) {
|
if (!isMonitoring || url == null) {
|
||||||
return UnDefType.NULL;
|
return UnDefType.NULL;
|
||||||
}
|
}
|
||||||
String finalQual = configQual != null ? configQual : "poor";
|
String finalQual = configQual != null ? configQual : "poor";
|
||||||
return toStringType("%s/live/%s", url, local ? "files/%s/index.m3u8".formatted(finalQual) : "index.m3u8");
|
return toStringType("%s/live/%sindex.m3u8", url, local ? "files/%s/".formatted(finalQual) : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ import org.openhab.core.types.UnDefType;
|
|||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class ChannelTypeUtils {
|
public class ChannelTypeUtils {
|
||||||
|
private static final int DEFAULT_TIMEOUT_MS = 30000;
|
||||||
|
|
||||||
public static @Nullable QuantityType<?> commandToQuantity(Command command, MeasureClass measureClass) {
|
public static @Nullable QuantityType<?> commandToQuantity(Command command, MeasureClass measureClass) {
|
||||||
Measure measureDef = measureClass.measureDefinition;
|
Measure measureDef = measureClass.measureDefinition;
|
||||||
@ -90,7 +91,8 @@ public class ChannelTypeUtils {
|
|||||||
|
|
||||||
public static State toRawType(@Nullable String pictureUrl) {
|
public static State toRawType(@Nullable String pictureUrl) {
|
||||||
if (pictureUrl != null) {
|
if (pictureUrl != null) {
|
||||||
RawType picture = HttpUtil.downloadImage(pictureUrl);
|
// Retrieving local picture can be quite long then extend the timeout.
|
||||||
|
RawType picture = HttpUtil.downloadImage(pictureUrl, DEFAULT_TIMEOUT_MS);
|
||||||
if (picture != null) {
|
if (picture != null) {
|
||||||
return picture;
|
return picture;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user