2 * Copyright (c) 2010-2023 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.magentatv.internal;
15 import static org.openhab.binding.magentatv.internal.MagentaTVBindingConstants.*;
17 import java.io.IOException;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.eclipse.jetty.client.HttpClient;
23 import org.openhab.binding.magentatv.internal.MagentaTVDeviceManager.MagentaTVDevice;
24 import org.openhab.binding.magentatv.internal.handler.MagentaTVHandler;
25 import org.openhab.binding.magentatv.internal.network.MagentaTVNetwork;
26 import org.openhab.binding.magentatv.internal.network.MagentaTVPoweroffListener;
27 import org.openhab.core.io.net.http.HttpClientFactory;
28 import org.openhab.core.net.HttpServiceUtil;
29 import org.openhab.core.net.NetworkAddressService;
30 import org.openhab.core.thing.Thing;
31 import org.openhab.core.thing.ThingTypeUID;
32 import org.openhab.core.thing.binding.BaseThingHandlerFactory;
33 import org.openhab.core.thing.binding.ThingHandler;
34 import org.openhab.core.thing.binding.ThingHandlerFactory;
35 import org.osgi.service.component.ComponentContext;
36 import org.osgi.service.component.annotations.Activate;
37 import org.osgi.service.component.annotations.Component;
38 import org.osgi.service.component.annotations.Reference;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
43 * The {@link MagentaTVHandlerFactory} is responsible for creating things and thing
46 * @author Markus Michels - Initial contribution
49 @Component(service = { ThingHandlerFactory.class, MagentaTVHandlerFactory.class }, configurationPid = "binding."
51 public class MagentaTVHandlerFactory extends BaseThingHandlerFactory {
52 private final Logger logger = LoggerFactory.getLogger(MagentaTVHandlerFactory.class);
54 private final MagentaTVNetwork network = new MagentaTVNetwork();
55 private final MagentaTVDeviceManager manager;
56 private final HttpClient httpClient;
57 private @Nullable MagentaTVPoweroffListener upnpListener;
58 private boolean servletInitialized = false;
61 * Activate the bundle: save properties
63 * @param componentContext
64 * @param configProperties set of properties from cfg (use same names as in
69 public MagentaTVHandlerFactory(@Reference NetworkAddressService networkAddressService,
70 @Reference HttpClientFactory httpClientFactory, @Reference MagentaTVDeviceManager manager,
71 ComponentContext componentContext, Map<String, String> configProperties) throws IOException {
72 super.activate(componentContext);
73 this.manager = manager;
74 this.httpClient = httpClientFactory.getCommonHttpClient();
76 logger.debug("Initialize network access");
77 System.setProperty("java.net.preferIPv4Stack", "true");
78 String lip = networkAddressService.getPrimaryIpv4HostAddress();
79 Integer port = HttpServiceUtil.getHttpServicePort(componentContext.getBundleContext());
83 network.initLocalNet(lip != null ? lip : "", port.toString());
84 upnpListener = new MagentaTVPoweroffListener(this, network.getLocalInterface());
85 } catch (MagentaTVException e) {
86 logger.warn("Initialization failed: {}", e.toString());
91 public boolean supportsThingType(ThingTypeUID thingTypeUID) {
92 return SUPPORTED_THING_TYPES.contains(thingTypeUID);
96 protected @Nullable ThingHandler createHandler(Thing thing) {
97 ThingTypeUID thingTypeUID = thing.getThingTypeUID();
99 if (upnpListener != null) {
100 upnpListener.start();
103 logger.debug("Create thing type {}", thing.getThingTypeUID().getAsString());
104 if (THING_TYPE_RECEIVER.equals(thingTypeUID)) {
105 return new MagentaTVHandler(manager, thing, network, httpClient);
111 public void setNotifyServletStatus(boolean newStatus) {
112 logger.debug("NotifyServlet started");
113 servletInitialized = newStatus;
116 public boolean getNotifyServletStatus() {
117 return servletInitialized;
121 * We received the pairing result (by the Notify servlet)
123 * @param notifyDeviceId The unique device id pairing was initiated for
124 * @param pairingCode Pairing code computed by the receiver
125 * @return true: thing handler was called, false: failed, e.g. unknown device
127 public boolean notifyPairingResult(String notifyDeviceId, String ipAddress, String pairingCode) {
129 logger.trace("PairingResult: Check {} devices for id {}, ipAddress {}", manager.numberOfDevices(),
130 notifyDeviceId, ipAddress);
131 MagentaTVDevice dev = manager.lookupDevice(ipAddress);
132 if ((dev != null) && (dev.thingHandler != null)) {
133 if (dev.deviceId.isEmpty()) {
134 logger.trace("deviceId {} assigned for ipAddress {}", notifyDeviceId, ipAddress);
135 dev.deviceId = notifyDeviceId;
137 if (dev.thingHandler != null) {
138 dev.thingHandler.onPairingResult(pairingCode);
143 logger.debug("Received pairingCode {} for unregistered device {}!", pairingCode, ipAddress);
144 } catch (MagentaTVException e) {
145 logger.debug("Unable to process pairing result for deviceID {}: {}", notifyDeviceId, e.toString());
151 * A programInfo or playStatus event was received from the receiver
153 * @param mrMac MR MAC address (used to map the device)
154 * @param jsonEvent Event data in JSON format
155 * @return true: thing handler was called, false: failed, e.g. unknown device
157 public boolean notifyMREvent(String mrMac, String jsonEvent) {
159 logger.trace("Received MR event from MAC {}, JSON={}", mrMac, jsonEvent);
160 MagentaTVDevice dev = manager.lookupDevice(mrMac);
161 if ((dev != null) && (dev.thingHandler != null)) {
162 dev.thingHandler.onMREvent(jsonEvent);
165 logger.debug("Received event for unregistered MR: MAC address {}, JSON={}", mrMac, jsonEvent);
166 } catch (RuntimeException e) {
167 logger.debug("Unable to process MR event! {} ({}), json={}", e.getMessage(), e.getClass(), jsonEvent);
173 * The PowerOff Listener got a byebye message. This comes in when the receiver
174 * was is going to suspend mode.
176 * @param ipAddress receiver IP
178 public void onPowerOff(String ipAddress) {
180 logger.debug("ByeBye message received for IP {}", ipAddress);
181 MagentaTVDevice dev = manager.lookupDevice(ipAddress);
182 if ((dev != null) && (dev.thingHandler != null)) {
183 dev.thingHandler.onPowerOff();
185 } catch (MagentaTVException e) {
186 logger.debug("Unable to process SSDP message for IP {} - {}", ipAddress, e.toString());