]> git.basschouten.com Git - openhab-addons.git/blob
11197cb1588ded33c9ccddfd49ce22b8742b1785
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.lcn.internal.connection;
14
15 import java.io.IOException;
16 import java.net.InetSocketAddress;
17 import java.net.StandardSocketOptions;
18 import java.nio.channels.AsynchronousSocketChannel;
19 import java.nio.channels.CompletionHandler;
20 import java.util.Objects;
21
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.openhab.binding.lcn.internal.common.LcnException;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 /**
29  * This state is active during the socket creation, host name resolving and waiting for the TCP connection to become
30  * established.
31  *
32  * @author Fabian Wolter - Initial Contribution
33  */
34 @NonNullByDefault
35 public class ConnectionStateConnecting extends AbstractConnectionState {
36     private final Logger logger = LoggerFactory.getLogger(ConnectionStateConnecting.class);
37
38     public ConnectionStateConnecting(ConnectionStateMachine context) {
39         super(context);
40     }
41
42     @Override
43     public void startWorking() {
44         connection.clearRuntimeData();
45
46         logger.debug("Connecting to {}:{} ...", connection.getSettings().getAddress(),
47                 connection.getSettings().getPort());
48
49         try {
50             // Open Channel by using the system-wide default AynchronousChannelGroup.
51             // So, Threads are used or re-used on demand by the JVM.
52             AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();
53             // Do not wait until some buffer is filled, send PCK commands immediately
54             channel.setOption(StandardSocketOptions.TCP_NODELAY, true);
55             connection.setSocketChannel(channel);
56
57             InetSocketAddress address = new InetSocketAddress(connection.getSettings().getAddress(),
58                     connection.getSettings().getPort());
59
60             if (address.isUnresolved()) {
61                 throw new LcnException("Could not resolve hostname");
62             }
63
64             channel.connect(address, null, new CompletionHandler<@Nullable Void, @Nullable Void>() {
65                 @Override
66                 public void completed(@Nullable Void result, @Nullable Void attachment) {
67                     connection.readAndProcess();
68                     nextState(ConnectionStateSendUsername::new);
69                 }
70
71                 @Override
72                 public void failed(@Nullable Throwable e, @Nullable Void attachment) {
73                     handleConnectionFailure(e);
74                 }
75             });
76         } catch (IOException | LcnException e) {
77             handleConnectionFailure(e);
78         }
79     }
80
81     private void handleConnectionFailure(@Nullable Throwable e) {
82         String message = null;
83         if (e != null) {
84             logger.warn("Could not connect to {}:{}: {}", connection.getSettings().getAddress(),
85                     connection.getSettings().getPort(), e.getMessage());
86             message = e.getMessage();
87         }
88         connection.getCallback().onOffline(Objects.requireNonNullElse(message, ""));
89         handleConnectionFailed(e);
90     }
91
92     @Override
93     public void onPckMessageReceived(String data) {
94         // nothing
95     }
96 }