2 * Copyright (c) 2010-2024 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.ipcamera.internal;
15 import static org.openhab.binding.ipcamera.internal.IpCameraBindingConstants.*;
17 import java.util.ArrayList;
18 import java.util.List;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.ipcamera.internal.ReolinkState.GetAbilityResponse;
23 import org.openhab.binding.ipcamera.internal.ReolinkState.GetAiStateResponse;
24 import org.openhab.binding.ipcamera.internal.handler.IpCameraHandler;
25 import org.openhab.core.library.types.OnOffType;
26 import org.openhab.core.library.types.PercentType;
27 import org.openhab.core.library.types.StringType;
28 import org.openhab.core.thing.ChannelUID;
29 import org.openhab.core.types.Command;
30 import org.openhab.core.types.RefreshType;
31 import org.openhab.core.types.UnDefType;
33 import com.google.gson.Gson;
34 import com.google.gson.JsonParseException;
36 import io.netty.channel.ChannelDuplexHandler;
37 import io.netty.channel.ChannelHandlerContext;
38 import io.netty.util.ReferenceCountUtil;
41 * The {@link ReolinkHandler} is responsible for handling commands, which are
42 * sent to one of the channels.
44 * @author Matthew Skinner - Initial contribution
48 public class ReolinkHandler extends ChannelDuplexHandler {
49 protected final Gson gson = new Gson();
50 private IpCameraHandler ipCameraHandler;
51 private String requestUrl = "Empty";
53 public ReolinkHandler(IpCameraHandler thingHandler) {
54 ipCameraHandler = thingHandler;
57 public void setURL(String url) {
61 // This handles the incoming http replies back from the camera.
63 public void channelRead(@Nullable ChannelHandlerContext ctx, @Nullable Object msg) throws Exception {
64 if (msg == null || ctx == null) {
68 String content = msg.toString();
69 ipCameraHandler.logger.trace("HTTP Result from {} contains \t:{}:", requestUrl, content);
70 int afterCommand = requestUrl.indexOf("&");
72 if (afterCommand < 0) {
73 cutDownURL = requestUrl;
75 cutDownURL = requestUrl.substring(0, afterCommand);
77 switch (cutDownURL) {// Use a cutdown URL as we can not use variables in a switch()
78 case "/api.cgi?cmd=Login":
79 ipCameraHandler.reolinkAuth = "&token=" + Helper.searchString(content, "\"name\" : \"");
80 if (ipCameraHandler.reolinkAuth.length() > 7) {
81 ipCameraHandler.logger.debug("Your Reolink camera gave a login:{}",
82 ipCameraHandler.reolinkAuth);
83 ipCameraHandler.snapshotUri = "/cgi-bin/api.cgi?cmd=Snap&channel="
84 + ipCameraHandler.cameraConfig.getNvrChannel() + "&rs=openHAB"
85 + ipCameraHandler.reolinkAuth;
86 // admin user in case username in config is a restricted user account. This may cause channels
87 // to be removed due to restricted user, causing missing channels to be falsely reported as a
89 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=GetAbility" + ipCameraHandler.reolinkAuth,
90 "[{ \"cmd\":\"GetAbility\", \"param\":{ \"User\":{ \"userName\":\"admin\" }}}]");
92 ipCameraHandler.logger.info("Your Reolink camera gave a bad login response:{}", content);
95 case "/api.cgi?cmd=GetAbility": // Used to check what channels the camera supports
96 List<org.openhab.core.thing.Channel> removeChannels = new ArrayList<>();
97 org.openhab.core.thing.Channel channel = null;
99 GetAbilityResponse[] getAbilityResponse = gson.fromJson(content, GetAbilityResponse[].class);
100 if (getAbilityResponse == null) {
103 if (getAbilityResponse[0].value == null || getAbilityResponse[0].value.ability == null) {
104 ipCameraHandler.logger.warn("The GetAbilityResponse could not be parsed: {}",
105 getAbilityResponse[0].error.detail);
108 ipCameraHandler.reolinkScheduleVersion = getAbilityResponse[0].value.ability.scheduleVersion.ver;
109 if (getAbilityResponse[0].value.ability.supportFtpEnable == null
110 || getAbilityResponse[0].value.ability.supportFtpEnable.permit == 0) {
111 ipCameraHandler.logger.debug("Camera has no Enable FTP support.");
112 channel = ipCameraHandler.getThing().getChannel(CHANNEL_ENABLE_FTP);
113 if (channel != null) {
114 removeChannels.add(channel);
117 if (getAbilityResponse[0].value.ability.supportRecordEnable == null
118 || getAbilityResponse[0].value.ability.supportRecordEnable.permit == 0) {
119 ipCameraHandler.logger.debug("Camera has no enable recording support.");
120 channel = ipCameraHandler.getThing().getChannel(CHANNEL_ENABLE_RECORDINGS);
121 if (channel != null) {
122 removeChannels.add(channel);
125 if (getAbilityResponse[0].value.ability.abilityChn[0].supportAiDogCat == null
126 || getAbilityResponse[0].value.ability.abilityChn[0].supportAiDogCat.permit == 0) {
127 ipCameraHandler.logger.debug("Camera has no AiDogCat support.");
128 channel = ipCameraHandler.getThing().getChannel(CHANNEL_ANIMAL_ALARM);
129 if (channel != null) {
130 removeChannels.add(channel);
133 if (getAbilityResponse[0].value.ability.abilityChn[0].supportAiPeople == null
134 || getAbilityResponse[0].value.ability.abilityChn[0].supportAiPeople.permit == 0) {
135 ipCameraHandler.logger.debug("Camera has no AiPeople support.");
136 channel = ipCameraHandler.getThing().getChannel(CHANNEL_HUMAN_ALARM);
137 if (channel != null) {
138 removeChannels.add(channel);
141 if (getAbilityResponse[0].value.ability.abilityChn[0].supportAiVehicle == null
142 || getAbilityResponse[0].value.ability.abilityChn[0].supportAiVehicle.permit == 0) {
143 ipCameraHandler.logger.debug("Camera has no AiVehicle support.");
144 channel = ipCameraHandler.getThing().getChannel(CHANNEL_CAR_ALARM);
145 if (channel != null) {
146 removeChannels.add(channel);
149 if (getAbilityResponse[0].value.ability.supportEmailEnable == null
150 || getAbilityResponse[0].value.ability.supportEmailEnable.permit == 0) {
151 ipCameraHandler.logger.debug("Camera has no EmailEnable support.");
152 channel = ipCameraHandler.getThing().getChannel(CHANNEL_ENABLE_EMAIL);
153 if (channel != null) {
154 removeChannels.add(channel);
157 if (getAbilityResponse[0].value.ability.push == null
158 || getAbilityResponse[0].value.ability.push.permit == 0) {
159 ipCameraHandler.logger.debug("Camera has no Push support.");
160 channel = ipCameraHandler.getThing().getChannel(CHANNEL_ENABLE_PUSH);
161 if (channel != null) {
162 removeChannels.add(channel);
165 if (getAbilityResponse[0].value.ability.supportAudioAlarm == null
166 || getAbilityResponse[0].value.ability.supportAudioAlarm.permit == 0) {
167 ipCameraHandler.logger.debug("Camera has no AudioAlarm support.");
168 channel = ipCameraHandler.getThing().getChannel(CHANNEL_AUDIO_ALARM);
169 if (channel != null) {
170 removeChannels.add(channel);
173 if (getAbilityResponse[0].value.ability.supportAudioAlarmEnable == null
174 || getAbilityResponse[0].value.ability.supportAudioAlarmEnable.permit == 0) {
175 ipCameraHandler.logger.debug("Camera has no AudioAlarm support.");
176 channel = ipCameraHandler.getThing().getChannel(CHANNEL_THRESHOLD_AUDIO_ALARM);
177 if (channel != null) {
178 removeChannels.add(channel);
180 channel = ipCameraHandler.getThing().getChannel(CHANNEL_ENABLE_AUDIO_ALARM);
181 if (channel != null) {
182 removeChannels.add(channel);
185 if (getAbilityResponse[0].value.ability.abilityChn[0].supportAiFace == null
186 || getAbilityResponse[0].value.ability.abilityChn[0].supportAiFace.permit == 0) {
187 ipCameraHandler.logger.debug("Camera has no AiFace support.");
188 channel = ipCameraHandler.getThing().getChannel(CHANNEL_FACE_DETECTED);
189 if (channel != null) {
190 removeChannels.add(channel);
193 } catch (JsonParseException e) {
194 ipCameraHandler.logger.warn("API command GetAbility may not be supported by the camera");
196 if (channel != null) {
197 ipCameraHandler.removeChannels(removeChannels);
200 case "/api.cgi?cmd=GetAiState":
201 ipCameraHandler.setChannelState(CHANNEL_LAST_EVENT_DATA, new StringType(content));
203 GetAiStateResponse[] aiResponse = gson.fromJson(content, GetAiStateResponse[].class);
204 if (aiResponse == null) {
207 if (aiResponse[0].value == null) {
208 ipCameraHandler.logger.debug("The GetAiStateResponse could not be parsed: {}",
209 aiResponse[0].error.detail);
212 if (aiResponse[0].value.dogCat.alarmState == 1) {
213 ipCameraHandler.setChannelState(CHANNEL_ANIMAL_ALARM, OnOffType.ON);
215 ipCameraHandler.setChannelState(CHANNEL_ANIMAL_ALARM, OnOffType.OFF);
217 if (aiResponse[0].value.face.alarmState == 1) {
218 ipCameraHandler.setChannelState(CHANNEL_FACE_DETECTED, OnOffType.ON);
220 ipCameraHandler.setChannelState(CHANNEL_FACE_DETECTED, OnOffType.OFF);
222 if (aiResponse[0].value.people.alarmState == 1) {
223 ipCameraHandler.setChannelState(CHANNEL_HUMAN_ALARM, OnOffType.ON);
225 ipCameraHandler.setChannelState(CHANNEL_HUMAN_ALARM, OnOffType.OFF);
227 if (aiResponse[0].value.vehicle.alarmState == 1) {
228 ipCameraHandler.setChannelState(CHANNEL_CAR_ALARM, OnOffType.ON);
230 ipCameraHandler.setChannelState(CHANNEL_CAR_ALARM, OnOffType.OFF);
232 } catch (JsonParseException e) {
233 ipCameraHandler.logger.debug("API GetAiState is not supported by the camera.");
236 case "/api.cgi?cmd=GetAudioAlarm":
237 case "/api.cgi?cmd=GetAudioAlarmV20":
238 if (content.contains("\"enable\" : 1")) {
239 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON);
241 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.OFF);
244 case "/api.cgi?cmd=GetIrLights":
245 if (content.contains("\"state\" : 0")) {
246 ipCameraHandler.setChannelState(CHANNEL_AUTO_LED, OnOffType.OFF);
248 ipCameraHandler.setChannelState(CHANNEL_AUTO_LED, OnOffType.ON);
251 case "/api.cgi?cmd=GetMdAlarm":
252 if (content.contains("00000")) {
253 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.OFF);
255 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.ON);
258 case "/api.cgi?cmd=GetMdState":
259 if (content.contains("\"state\" : 0")) {
260 ipCameraHandler.setChannelState(CHANNEL_MOTION_ALARM, OnOffType.OFF);
262 ipCameraHandler.setChannelState(CHANNEL_MOTION_ALARM, OnOffType.ON);
265 case "/api.cgi?cmd=GetEmail":
266 case "/api.cgi?cmd=GetEmailV20":
267 if (content.contains("\"enable\" : 0")) {
268 ipCameraHandler.setChannelState(CHANNEL_MOTION_ALARM, OnOffType.OFF);
270 ipCameraHandler.setChannelState(CHANNEL_MOTION_ALARM, OnOffType.ON);
273 case "/api.cgi?cmd=GetPush":
274 case "/api.cgi?cmd=GetPushV20":
275 if (content.contains("\"enable\" : 0")) {
276 ipCameraHandler.setChannelState(CHANNEL_MOTION_ALARM, OnOffType.OFF);
278 ipCameraHandler.setChannelState(CHANNEL_MOTION_ALARM, OnOffType.ON);
281 case "/api.cgi?cmd=GetWhiteLed":
282 if (content.contains("\"state\" : 0")) {
283 ipCameraHandler.setChannelState(CHANNEL_WHITE_LED, OnOffType.OFF);
285 ipCameraHandler.setChannelState(CHANNEL_WHITE_LED, OnOffType.ON);
288 case "/cgi-bin/api.cgi?cmd=Snap":
291 if (!cutDownURL.contains("cmd=Set")) {// ignore the responses from all Setxxxxx commands
292 ipCameraHandler.logger.warn(
293 "URL {} is not handled currently by the binding, please report this message",
298 ReferenceCountUtil.release(msg);
302 // This handles the commands that come from the openHAB event bus.
303 public void handleCommand(ChannelUID channelUID, Command command) {
304 if (command instanceof RefreshType) {
305 switch (channelUID.getId()) {
306 case CHANNEL_ENABLE_MOTION_ALARM:
307 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=GetMdAlarm" + ipCameraHandler.reolinkAuth,
308 "[{\"cmd\": \"GetMdAlarm\", \"action\": 1,\"param\": {\"channel\": "
309 + ipCameraHandler.cameraConfig.getNvrChannel() + "}}]");
311 case CHANNEL_ENABLE_AUDIO_ALARM:
312 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=GetAudioAlarmV20" + ipCameraHandler.reolinkAuth,
313 "[{ \"cmd\":\"GetAudioAlarmV20\", \"action\":1, \"param\":{ \"channel\": 0}}]");
315 case CHANNEL_AUTO_LED:
316 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=GetIrLights" + ipCameraHandler.reolinkAuth,
317 "[{ \"cmd\":\"GetIrLights\"}]");
319 case CHANNEL_AUTO_WHITE_LED:
320 case CHANNEL_WHITE_LED:
321 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=GetWhiteLed" + ipCameraHandler.reolinkAuth,
322 "[{\"cmd\": \"GetWhiteLed\",\"action\": 0,\"param\": {\"channel\": "
323 + ipCameraHandler.cameraConfig.getNvrChannel() + "}}]");
325 case CHANNEL_ENABLE_EMAIL:
326 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=GetEmailV20" + ipCameraHandler.reolinkAuth,
327 "[{ \"cmd\":\"GetEmailV20\"}]");
329 case CHANNEL_ENABLE_PUSH:
330 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=GetPushV20" + ipCameraHandler.reolinkAuth,
331 "[{ \"cmd\":\"GetPush\"}]");
335 } // end of "REFRESH"
336 switch (channelUID.getId()) {
337 case CHANNEL_ACTIVATE_ALARM_OUTPUT: // cameras built in siren
338 if (OnOffType.ON.equals(command)) {
339 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=AudioAlarmPlay" + ipCameraHandler.reolinkAuth,
340 "[{\"cmd\": \"AudioAlarmPlay\", \"param\": {\"alarm_mode\": \"manul\", \"manual_switch\": 1, \"channel\": "
341 + ipCameraHandler.cameraConfig.getNvrChannel() + " }}]");
343 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=AudioAlarmPlay" + ipCameraHandler.reolinkAuth,
344 "[{\"cmd\": \"AudioAlarmPlay\", \"param\": {\"alarm_mode\": \"manul\", \"manual_switch\": 0, \"channel\": "
345 + ipCameraHandler.cameraConfig.getNvrChannel() + " }}]");
348 case CHANNEL_AUTO_LED:
349 if (OnOffType.ON.equals(command)) {
350 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetIrLights" + ipCameraHandler.reolinkAuth,
351 "[{\"cmd\": \"SetIrLights\",\"action\": 0,\"param\": {\"IrLights\": {\"channel\": "
352 + ipCameraHandler.cameraConfig.getNvrChannel() + ",\"state\": \"Auto\"}}}]");
354 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetIrLights" + ipCameraHandler.reolinkAuth,
355 "[{\"cmd\": \"SetIrLights\",\"action\": 0,\"param\": {\"IrLights\": {\"channel\": "
356 + ipCameraHandler.cameraConfig.getNvrChannel() + ",\"state\": \"Off\"}}}]");
359 case CHANNEL_AUTO_WHITE_LED:
360 if (OnOffType.ON.equals(command)) {
361 ipCameraHandler.setChannelState(CHANNEL_WHITE_LED, UnDefType.UNDEF);
362 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetWhiteLed" + ipCameraHandler.reolinkAuth,
363 "[{\"cmd\":\"SetWhiteLed\",\"param\":{\"WhiteLed\":{\"channel\": "
364 + ipCameraHandler.cameraConfig.getNvrChannel() + ", \"mode\": 1}}}]");
366 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetWhiteLed" + ipCameraHandler.reolinkAuth,
367 "[{\"cmd\":\"SetWhiteLed\",\"param\":{\"WhiteLed\":{\"channel\": "
368 + ipCameraHandler.cameraConfig.getNvrChannel() + ", \"mode\": 0}}}]");
371 case CHANNEL_ENABLE_AUDIO_ALARM:
372 if (OnOffType.ON.equals(command)) {
373 if (ipCameraHandler.reolinkScheduleVersion == 1) {
374 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetAudioAlarmV20" + ipCameraHandler.reolinkAuth,
375 "[{\"cmd\":\"SetAudioAlarmV20\",\"param\":{\"Audio\" : {\"enable\" : 1}}}]");
377 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetAudioAlarm" + ipCameraHandler.reolinkAuth,
378 "[{\"cmd\": \" SetAudioAlarm\",\"param\": {\"Audio\": {\"schedule\": {\"enable\": 1,\"table\": \"111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\"}}}}]");
381 if (ipCameraHandler.reolinkScheduleVersion == 1) {
382 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetAudioAlarmV20" + ipCameraHandler.reolinkAuth,
383 "[{\"cmd\":\"SetAudioAlarmV20\",\"param\":{\"Audio\" : {\"enable\" : 0}}}]");
386 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetAudioAlarm" + ipCameraHandler.reolinkAuth,
387 "[{\"cmd\": \" SetAudioAlarm\",\"param\": {\"Audio\": {\"schedule\": {\"enable\": 0,\"table\": \"111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\"}}}}]");
391 case CHANNEL_ENABLE_FTP:
392 if (OnOffType.ON.equals(command)) {
393 if (ipCameraHandler.reolinkScheduleVersion == 1) {
394 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetFtpV20" + ipCameraHandler.reolinkAuth,
395 "[{\"cmd\":\"SetFtpV20\",\"param\":{\"Ftp\" : {\"enable\" : 1}}}]");
398 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetFtp" + ipCameraHandler.reolinkAuth,
399 "[{\"cmd\":\"SetFtp\",\"param\":{\"Ftp\" : {\"schedule\" : {\"enable\" : 1}}}}]");
402 if (ipCameraHandler.reolinkScheduleVersion == 1) {
403 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetFtpV20" + ipCameraHandler.reolinkAuth,
404 "[{\"cmd\":\"SetFtpV20\",\"param\":{\"Ftp\" : {\"enable\" : 0}}}]");
406 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetFtp" + ipCameraHandler.reolinkAuth,
407 "[{\"cmd\":\"SetFtp\",\"param\":{\"Ftp\" : {\"schedule\" : {\"enable\" : 0}}}}]");
411 case CHANNEL_ENABLE_EMAIL:
412 if (OnOffType.ON.equals(command)) {
413 if (ipCameraHandler.reolinkScheduleVersion == 1) {
414 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetEmailV20" + ipCameraHandler.reolinkAuth,
415 "[{\"cmd\":\"SetEmailV20\",\"param\":{\"Email\" : {\"enable\" : 1}}}]");
417 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetEmail" + ipCameraHandler.reolinkAuth,
418 "[{\"cmd\":\"SetEmail\",\"param\":{\"Email\" : {\"schedule\" : {\"enable\" : 1}}}}]");
421 if (ipCameraHandler.reolinkScheduleVersion == 1) {
422 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetEmailV20" + ipCameraHandler.reolinkAuth,
423 "[{\"cmd\":\"SetEmailV20\",\"param\":{\"Email\" : {\"enable\" : 0}}}]");
425 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetEmail" + ipCameraHandler.reolinkAuth,
426 "[{\"cmd\":\"SetEmail\",\"param\":{\"Email\" : {\"schedule\" : {\"enable\" : 0}}}}]");
430 case CHANNEL_ENABLE_PUSH:
431 if (OnOffType.ON.equals(command)) {
432 if (ipCameraHandler.reolinkScheduleVersion == 1) {
433 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetPushV20" + ipCameraHandler.reolinkAuth,
434 "[{\"cmd\":\"SetPushV20\",\"param\":{\"Push\":{\"enable\":1}}}]");
436 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetPush" + ipCameraHandler.reolinkAuth,
437 "[{\"cmd\":\"SetPush\",\"param\":{\"Push\" : {\"schedule\" : {\"enable\" : 1}}}}]");
440 if (ipCameraHandler.reolinkScheduleVersion == 1) {
441 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetPushV20" + ipCameraHandler.reolinkAuth,
442 "[{\"cmd\":\"SetPushV20\",\"param\":{\"Push\":{\"enable\":0}}}]");
444 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetPush" + ipCameraHandler.reolinkAuth,
445 "[{\"cmd\":\"SetPush\",\"param\":{\"Push\" : {\"schedule\" : {\"enable\" : 0}}}}]");
449 case CHANNEL_ENABLE_LED:
450 ipCameraHandler.setChannelState(CHANNEL_AUTO_LED, OnOffType.OFF);
451 if (OnOffType.OFF.equals(command) || PercentType.ZERO.equals(command)) {
452 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetIrLights" + ipCameraHandler.reolinkAuth,
453 "[{\"cmd\": \"SetIrLights\",\"action\": 0,\"param\": {\"IrLights\": {\"channel\": "
454 + ipCameraHandler.cameraConfig.getNvrChannel() + ",\"state\": \"Off\"}}}]");
455 } else if (OnOffType.ON.equals(command) || command instanceof PercentType percentCommand) {
456 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetIrLights" + ipCameraHandler.reolinkAuth,
457 "[{\"cmd\": \"SetIrLights\",\"action\": 0,\"param\": {\"IrLights\": {\"channel\": "
458 + ipCameraHandler.cameraConfig.getNvrChannel() + ",\"state\": \"On\"}}}]");
460 ipCameraHandler.logger.warn("Unsupported command sent to enableLED channel");
462 case CHANNEL_ENABLE_MOTION_ALARM:
463 if (OnOffType.ON.equals(command)) {
464 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetMdAlarm" + ipCameraHandler.reolinkAuth);
466 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetMdAlarm" + ipCameraHandler.reolinkAuth);
469 case CHANNEL_ENABLE_RECORDINGS:
470 if (OnOffType.ON.equals(command)) {
471 if (ipCameraHandler.reolinkScheduleVersion == 1) {
472 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetRecV20" + ipCameraHandler.reolinkAuth,
473 "[{\"cmd\":\"SetRecV20\",\"param\":{\"Rec\":{\"enable\":1}}}]");
476 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetRec" + ipCameraHandler.reolinkAuth,
477 "[{\"cmd\":\"SetRec\",\"param\":{\"Rec\" : {\"channel\" : "
478 + ipCameraHandler.cameraConfig.getNvrChannel()
479 + ",\"schedule\" : {\"enable\" : 1}}}}]");
482 if (ipCameraHandler.reolinkScheduleVersion == 1) {
483 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetRecV20" + ipCameraHandler.reolinkAuth,
484 "[{\"cmd\":\"SetRecV20\",\"param\":{\"Rec\":{\"enable\":0}}}]");
487 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetRec" + ipCameraHandler.reolinkAuth,
488 "[{\"cmd\":\"SetRec\",\"param\":{\"Rec\" : {\"channel\" : "
489 + ipCameraHandler.cameraConfig.getNvrChannel()
490 + ",\"schedule\" : {\"enable\" : 0}}}}]");
494 case CHANNEL_WHITE_LED:
495 ipCameraHandler.setChannelState(CHANNEL_AUTO_WHITE_LED, OnOffType.OFF);
496 if (OnOffType.OFF.equals(command) || PercentType.ZERO.equals(command)) {
497 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetWhiteLed" + ipCameraHandler.reolinkAuth,
498 "[{\"cmd\": \"SetWhiteLed\",\"param\": {\"WhiteLed\": {\"state\": 0,\"channel\": "
499 + ipCameraHandler.cameraConfig.getNvrChannel() + ",\"mode\": 0}}}]");
500 } else if (OnOffType.ON.equals(command)) {
501 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetWhiteLed" + ipCameraHandler.reolinkAuth,
502 "[{\"cmd\": \"SetWhiteLed\",\"param\": {\"WhiteLed\": {\"state\": 1,\"channel\": "
503 + ipCameraHandler.cameraConfig.getNvrChannel() + ",\"mode\": 2}}}]");
504 } else if (command instanceof PercentType percentCommand) {
505 int value = percentCommand.toBigDecimal().intValue();
506 ipCameraHandler.sendHttpPOST("/api.cgi?cmd=SetWhiteLed" + ipCameraHandler.reolinkAuth,
507 "[{\"cmd\": \"SetWhiteLed\",\"param\": {\"WhiteLed\": {\"state\": 1,\"channel\": "
508 + ipCameraHandler.cameraConfig.getNvrChannel() + ",\"mode\": 2,\"bright\": " + value
514 // If a camera does not need to poll a request as often as snapshots, it can be
515 // added here. Binding steps through the list.
516 public List<String> getLowPriorityRequests() {