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.samsungtv.internal;
15 import static org.openhab.binding.samsungtv.internal.SamsungTvBindingConstants.*;
17 import java.util.Optional;
18 import java.util.concurrent.ScheduledFuture;
19 import java.util.concurrent.TimeUnit;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.openhab.binding.samsungtv.internal.handler.SamsungTvHandler;
23 import org.openhab.binding.samsungtv.internal.service.RemoteControllerService;
24 import org.openhab.binding.samsungtv.internal.service.api.SamsungTvService;
25 import org.openhab.core.library.types.OnOffType;
26 import org.openhab.core.types.Command;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
31 * The {@link WolSend} is responsible for sending WOL packets and resending of commands
32 * Used by {@link SamsungTvHandler}
34 * @author Nick Waterton - Initial contribution
37 public class WolSend {
39 private static final int WOL_PACKET_RETRY_COUNT = 10;
40 private static final int WOL_SERVICE_CHECK_COUNT = 30;
42 private final Logger logger = LoggerFactory.getLogger(WolSend.class);
44 private String host = "";
47 String channel = POWER;
48 Command command = OnOffType.ON;
49 String macAddress = "";
50 private Optional<ScheduledFuture<?>> wolJob = Optional.empty();
51 SamsungTvHandler handler;
53 public WolSend(SamsungTvHandler handler) {
54 this.handler = handler;
58 * Send multiple WOL packets spaced with 100ms intervals and resend command
60 * @param channel Channel to resend command on
61 * @param command Command to resend
62 * @return boolean true/false if WOL job started
64 public boolean send(String channel, Command command) {
65 this.host = handler.host;
66 if (channel.equals(POWER) || channel.equals(ART_MODE)) {
67 if (OnOffType.ON.equals(command)) {
68 macAddress = handler.configuration.getMacAddress();
69 if (macAddress.isBlank()) {
70 logger.debug("{}: Cannot send WOL packet, MAC address invalid: {}", host, macAddress);
73 this.channel = channel;
74 this.command = command;
75 if (channel.equals(ART_MODE) && !handler.getArtModeSupported()) {
76 logger.debug("{}: artMode is not yet detected on this TV - sending WOL anyway", host);
87 private void startWoljob() {
88 wolJob.ifPresentOrElse(job -> {
89 if (job.isCancelled()) {
92 logger.debug("{}: WOL job already running", host);
101 wolJob = Optional.of(
102 handler.getScheduler().scheduleWithFixedDelay(this::wolCheckPeriodic, 0, 1000, TimeUnit.MILLISECONDS));
105 public synchronized void cancel() {
106 wolJob.ifPresent(job -> {
107 logger.debug("{}: cancelling WOL Job", host);
112 private void sendWOL() {
113 logger.debug("{}: Send WOL packet to {}", host, macAddress);
115 // send max 10 WOL packets with 100ms intervals
116 for (int i = 0; i < WOL_PACKET_RETRY_COUNT; i++) {
117 handler.getScheduler().schedule(() -> {
118 WakeOnLanUtility.sendWOLPacket(macAddress);
119 }, (i * 100), TimeUnit.MILLISECONDS);
123 private void sendCommand(RemoteControllerService service) {
124 // send command in 2 seconds to allow time for connection to re-establish
125 logger.debug("{}: resend command {} to channel {} in 2 seconds...", host, command, channel);
126 handler.getScheduler().schedule(() -> {
127 service.handleCommand(channel, command);
128 }, 2000, TimeUnit.MILLISECONDS);
131 private void wolCheckPeriodic() {
132 if (wolCount % 10 == 0) {
133 // resend WOL every 10 seconds
136 // after RemoteService up again to ensure state is properly set
137 Optional<SamsungTvService> service = handler.findServiceInstance(RemoteControllerService.SERVICE_NAME);
138 service.ifPresent(s -> {
139 logger.debug("{}: RemoteControllerService found after {} attempts", host, wolCount);
140 // do not resend command if artMode command as TV wakes up in artMode
141 if (!channel.equals(ART_MODE)) {
142 sendCommand((RemoteControllerService) s);
147 if (wolCount++ > WOL_SERVICE_CHECK_COUNT) {
148 logger.warn("{}: Service NOT found after {} attempts: stopping WOL attempts", host, wolCount);
150 handler.putOffline();