]> git.basschouten.com Git - openhab-addons.git/blob
ebc3fd03271fbff148593e79762b1e30fc5352a5
[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.deutschebahn.internal;
14
15 import java.util.ArrayList;
16 import java.util.List;
17
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.openhab.binding.deutschebahn.internal.timetable.dto.TimetableStop;
21 import org.openhab.core.thing.Channel;
22 import org.openhab.core.thing.ChannelUID;
23 import org.openhab.core.thing.Thing;
24 import org.openhab.core.thing.ThingStatus;
25 import org.openhab.core.thing.ThingStatusDetail;
26 import org.openhab.core.thing.binding.BaseThingHandler;
27 import org.openhab.core.types.Command;
28 import org.openhab.core.types.State;
29 import org.openhab.core.types.UnDefType;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * Handler for a Train-Thing in DeutscheBahn Binding.
35  *
36  * Represents a Train that arrives / departs at the station selected by the DeutscheBahnTimetable-Bridge.
37  *
38  * @author Sönke Küper - Initial contribution
39  */
40 @NonNullByDefault
41 public class DeutscheBahnTrainHandler extends BaseThingHandler {
42
43     /**
44      * Wraps the Channel-UID with the configured {@link AttributeSelection}.
45      */
46     private final class ChannelWithConfig {
47
48         private final ChannelUID channelUid;
49         private final AttributeSelection attributeSelection;
50
51         /**
52          * Creates a new ChannelWithConfig.
53          * 
54          * @param channelUid The UID of the channel
55          * @param attributeSelection The attribute that provides the state that will be displayed.
56          */
57         public ChannelWithConfig( //
58                 final ChannelUID channelUid, //
59                 final AttributeSelection attributeSelection) {
60             this.channelUid = channelUid;
61             this.attributeSelection = attributeSelection;
62         }
63
64         /**
65          * Updates the value for the channel from given {@link TimetableStop}.
66          */
67         public void updateChannelValue(final TimetableStop stop) {
68             final State newState = this.determineState(stop);
69             if (newState != null) {
70                 DeutscheBahnTrainHandler.this.updateState(this.channelUid, newState);
71             } else {
72                 DeutscheBahnTrainHandler.this.updateState(this.channelUid, UnDefType.NULL);
73             }
74         }
75
76         @Nullable
77         private State determineState(final TimetableStop stop) {
78             return this.attributeSelection.getState(stop);
79         }
80
81         @Override
82         public String toString() {
83             return this.channelUid.toString();
84         }
85     }
86
87     private final Logger logger = LoggerFactory.getLogger(DeutscheBahnTrainHandler.class);
88     private final List<ChannelWithConfig> configuredChannels = new ArrayList<>();
89
90     /**
91      * Creates a new {@link DeutscheBahnTrainHandler}.
92      */
93     public DeutscheBahnTrainHandler(Thing thing) {
94         super(thing);
95     }
96
97     @Override
98     public void initialize() {
99         this.updateStatus(ThingStatus.UNKNOWN);
100
101         if (this.getBridge() == null) {
102             this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Please select bridge");
103             return;
104         }
105
106         this.createChannelMapping();
107         this.updateStatus(ThingStatus.ONLINE);
108     }
109
110     private void createChannelMapping() {
111         this.configuredChannels.clear();
112         for (Channel channel : this.getThing().getChannelsOfGroup("trip")) {
113             this.createTripChannelConfiguration(channel);
114         }
115         for (Channel channel : this.getThing().getChannelsOfGroup("arrival")) {
116             this.createEventChannelConfiguration(EventType.ARRIVAL, channel);
117         }
118         for (Channel channel : this.getThing().getChannelsOfGroup("departure")) {
119             this.createEventChannelConfiguration(EventType.DEPARTURE, channel);
120         }
121         this.logger.debug("Created {} configured channels for thing {}.", this.configuredChannels.size(),
122                 this.getThing().getUID());
123     }
124
125     /**
126      * Creates a {@link ChannelWithConfig} for a channel that represents an attribute of an
127      * {@link org.openhab.binding.deutschebahn.internal.timetable.dto.TripLabel}.
128      */
129     private void createTripChannelConfiguration(Channel channel) {
130         final ChannelUID channelUid = channel.getUID();
131         final String attributeName = getAttributeName(channelUid);
132         final TripLabelAttribute<?, ?> attribute = TripLabelAttribute.getByChannelName(attributeName);
133         if (attribute == null) {
134             this.logger.warn("Could not find trip attribute {} of channel: {} .", attribute, channelUid.getId());
135             return;
136         }
137         final ChannelWithConfig channelWithConfig = new ChannelWithConfig( //
138                 channelUid, //
139                 attribute);
140         this.configuredChannels.add(channelWithConfig);
141     }
142
143     /**
144      * Creates the {@link ChannelWithConfig} for a channel that represents an attribute of an
145      * {@link org.openhab.binding.deutschebahn.internal.timetable.dto.Event}.}
146      */
147     private void createEventChannelConfiguration(EventType eventType, Channel channel) {
148         final ChannelUID channelUid = channel.getUID();
149         final String attributeName = getAttributeName(channelUid);
150         final EventAttribute<?, ?> attribute = EventAttribute.getByChannelName(attributeName, eventType);
151         if (attribute == null) {
152             this.logger.warn("Could not find event attribute {} of channel: {} .", attribute, channelUid.getId());
153             return;
154         }
155         final ChannelWithConfig channelWithConfig = new ChannelWithConfig( //
156                 channelUid, //
157                 new EventAttributeSelection(eventType, attribute));
158         this.configuredChannels.add(channelWithConfig);
159     }
160
161     /**
162      * Strips the attribute name from the channel-UID.
163      */
164     private static String getAttributeName(ChannelUID channelUid) {
165         final String channelId = channelUid.getId();
166         int hashIndex = channelId.indexOf("#");
167         assert hashIndex > 0;
168         return channelId.substring(hashIndex + 1);
169     }
170
171     /**
172      * Does not handle any commands.
173      */
174     @Override
175     public void handleCommand(ChannelUID channelUID, Command command) {
176     }
177
178     /**
179      * Updates the value for the channels of this train from the given {@link TimetableStop}.
180      */
181     void updateChannels(TimetableStop stop) {
182         for (ChannelWithConfig channel : this.configuredChannels) {
183             channel.updateChannelValue(stop);
184         }
185     }
186 }