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

[zoneminder] Add support for setting the server run state #14906

Merged
merged 4 commits into from Apr 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions bundles/org.openhab.binding.zoneminder/README.md
Expand Up @@ -77,6 +77,7 @@ The following configuration parameters are available on the Monitor thing:
| imageUrl | String | Image URL for monitor id specified by imageMonitorId. Channel is UNDEF if the monitor id is not set, or if an OFF command is sent to the imageMonitorId channel. |
| videoMonitorId | String | Monitor ID to use for selecting a video URL. Also, sending an OFF command to this channel will reset the monitor id and url to UNDEF. |
| videoUrl | String | Video URL for monitor id specified by videoMonitorId. Channel is UNDEF if the monitor id is not set, or if an OFF command is sent to the videoMonitorId channel. |
| runState | String | Set the run state for the ZoneMinder server |

### Monitor Thing

Expand Down Expand Up @@ -171,6 +172,7 @@ String ZmServer_ImageMonitorId "Image Monitor Id [%s]" { channel="zoneminder:ser
String ZmServer_ImageUrl "Image Url [%s]" { channel="zoneminder:server:server:imageUrl" }
String ZmServer_VideoMonitorId "Video Monitor Id [%s]" { channel="zm:server:server:videoMonitorId" }
String ZmServer_VideoUrl "Video Url [%s]" { channel="zoneminder:server:server:videoUrl" }
String ZmServer_RunState "Run State [%s]" { channel="zoneminder:server:server:runState" }

// Monitor
String ZM_Monitor1_Id "Monitor Id [%s]" { channel="zoneminder:monitor:1:id" }
Expand Down
Expand Up @@ -67,6 +67,7 @@ public class ZmBindingConstants {
public static final String DEFAULT_URL_PATH = "/zm";

// List of all channel ids
public static final String CHANNEL_RUN_STATE = "runState";
public static final String CHANNEL_IMAGE_MONITOR_ID = "imageMonitorId";
public static final String CHANNEL_VIDEO_MONITOR_ID = "videoMonitorId";
public static final String CHANNEL_ID = "id";
Expand Down
@@ -0,0 +1,55 @@
/**
* Copyright (c) 2010-2023 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.zoneminder.internal.dto;

import com.google.gson.annotations.SerializedName;

/**
* The {@link RunStateDTO} contains a run state.
*
* @author Mark Hilbush - Initial contribution
*/
public class RunStateDTO extends AbstractResponseDTO {

/**
* A run state
*/
@SerializedName("State")
public RunState runState;

public class RunState {
/**
* ID of run state, typically "1", "2", etc.
*/
@SerializedName("Id")
public String id;

/**
* Name of run state
*/
@SerializedName("Name")
public String name;

/**
* Definition of the run state
*/
@SerializedName("Definition")
public String definition;

/**
* "1" if run state is active; "0" if not active
*/
@SerializedName("IsActive")
public String isActive;
}
}
@@ -0,0 +1,31 @@
/**
* Copyright (c) 2010-2023 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.zoneminder.internal.dto;

import java.util.List;

import com.google.gson.annotations.SerializedName;

/**
* The {@link RunStatesDTO} contains the list of run states.
*
* @author Mark Hilbush - Initial contribution
*/
public class RunStatesDTO extends AbstractResponseDTO {

/**
* List of run states
*/
@SerializedName("states")
public List<RunStateDTO> runStatesList;
}
Expand Up @@ -16,6 +16,8 @@

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
Expand Down Expand Up @@ -48,6 +50,9 @@
import org.openhab.binding.zoneminder.internal.dto.MonitorStateDTO;
import org.openhab.binding.zoneminder.internal.dto.MonitorStatusDTO;
import org.openhab.binding.zoneminder.internal.dto.MonitorsDTO;
import org.openhab.binding.zoneminder.internal.dto.RunStateDTO;
import org.openhab.binding.zoneminder.internal.dto.RunStateDTO.RunState;
import org.openhab.binding.zoneminder.internal.dto.RunStatesDTO;
import org.openhab.binding.zoneminder.internal.dto.VersionDTO;
import org.openhab.core.io.net.http.HttpUtil;
import org.openhab.core.library.types.OnOffType;
Expand Down Expand Up @@ -186,6 +191,11 @@ public void handleCommand(ChannelUID channelUID, Command command) {
case CHANNEL_VIDEO_MONITOR_ID:
handleMonitorIdCommand(command, CHANNEL_VIDEO_MONITOR_ID, CHANNEL_VIDEO_URL, STREAM_VIDEO);
break;
case CHANNEL_RUN_STATE:
if (command instanceof StringType) {
changeRunState(command);
}
break;
}
}

Expand All @@ -204,6 +214,12 @@ private void handleMonitorIdCommand(Command command, String monitorIdChannelId,
}
}

private void changeRunState(Command command) {
logger.debug("Bridge: Change run state to {}", command);
executeGet(buildUrl(String.format("/api/states/change/%s.json",
URLEncoder.encode(command.toString(), Charset.defaultCharset()))));
}

@Override
public Collection<Class<? extends ThingHandlerService>> getServices() {
return Collections.singleton(MonitorDiscoveryService.class);
Expand Down Expand Up @@ -332,6 +348,7 @@ private synchronized List<Monitor> getMonitors() {
m.setLastEvent(getLastEvent(m.getId()));
}
}
updateRunStates();
}
} catch (JsonSyntaxException e) {
logger.debug("Bridge: JsonSyntaxException: {}", e.getMessage(), e);
Expand Down Expand Up @@ -390,6 +407,32 @@ private void extractEventCounts(Monitor monitor, MonitorItemDTO monitorItemDTO)
return null;
}

private void updateRunStates() {
if (!zmAuth.isAuthorized() || !isLinked(CHANNEL_RUN_STATE)) {
return;
}
try {
String response = executeGet(buildUrl("/api/states.json"));
RunStatesDTO runStates = GSON.fromJson(response, RunStatesDTO.class);
if (runStates != null) {
List<StateOption> options = new ArrayList<>();
for (RunStateDTO runState : runStates.runStatesList) {
RunState state = runState.runState;
logger.debug("Found runstate: id={}, name={}, desc={}, isActive={}", state.id, state.name,
state.definition, state.isActive);
options.add(new StateOption(state.name, state.name));
if ("1".equals(state.isActive)) {
updateState(CHANNEL_RUN_STATE, new StringType(state.name));
}
}
stateDescriptionProvider.setStateOptions(new ChannelUID(getThing().getUID(), CHANNEL_RUN_STATE),
options);
}
} catch (JsonSyntaxException e) {
logger.debug("Bridge: JsonSyntaxException: {}", e.getMessage(), e);
}
}

private @Nullable VersionDTO getVersion() {
if (!zmAuth.isAuthorized()) {
return null;
Expand Down
Expand Up @@ -99,6 +99,8 @@ channel-type.zoneminder.image.label = Image
channel-type.zoneminder.image.description = A single snapshot image
channel-type.zoneminder.name.label = Name
channel-type.zoneminder.name.description = Monitor name
channel-type.zoneminder.runState.label = Run State
channel-type.zoneminder.runState.description = The currently executing run state
channel-type.zoneminder.state.label = State
channel-type.zoneminder.state.description = Current monitor state
channel-type.zoneminder.state.state.option.UNKNOWN = UNKNOWN
Expand Down
Expand Up @@ -7,6 +7,7 @@
<bridge-type id="server">
<label>ZoneMinder Server</label>
<description>Represents a ZoneMinder server</description>

<channels>
<channel id="imageMonitorId" typeId="id">
<label>Image Monitor Id</label>
Expand All @@ -22,7 +23,13 @@
<channel id="videoUrl" typeId="url">
<label>Video URL</label>
</channel>
<channel id="runState" typeId="runState"/>
</channels>

<properties>
<property name="thingTypeVersion">1</property>
</properties>

<config-description-ref uri="thing-type:zoneminder:server"/>
</bridge-type>

Expand Down Expand Up @@ -216,5 +223,11 @@
<description>Length of the event in seconds</description>
<state readOnly="true" pattern="%.2f %unit%"></state>
</channel-type>
<channel-type id="runState">
<item-type>String</item-type>
<label>Run State</label>
<description>The currently executing run state</description>
<state readOnly="false" pattern="%s"></state>
</channel-type>

</thing:thing-descriptions>
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<update:update-descriptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:update="https://openhab.org/schemas/update-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/update-description/v1.0.0 https://openhab.org/schemas/update-description-1.0.0.xsd">

<thing-type uid="zoneminder:server">

<instruction-set targetVersion="1">
<add-channel id="runState">
<type>zoneminder:runState</type>
</add-channel>
</instruction-set>

</thing-type>

</update:update-descriptions>