]> git.basschouten.com Git - openhab-addons.git/blob
ca7652edb8aa2d8b2254cf4f22cce338159ddf03
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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.minecraft.internal.handler;
14
15 import org.openhab.binding.minecraft.internal.MinecraftBindingConstants;
16 import org.openhab.binding.minecraft.internal.config.PlayerConfig;
17 import org.openhab.binding.minecraft.internal.message.OHMessage;
18 import org.openhab.binding.minecraft.internal.message.data.PlayerData;
19 import org.openhab.binding.minecraft.internal.message.data.commands.PlayerCommandData;
20 import org.openhab.core.library.types.DecimalType;
21 import org.openhab.core.library.types.OnOffType;
22 import org.openhab.core.library.types.PointType;
23 import org.openhab.core.library.types.StringType;
24 import org.openhab.core.thing.Bridge;
25 import org.openhab.core.thing.ChannelUID;
26 import org.openhab.core.thing.Thing;
27 import org.openhab.core.thing.ThingStatus;
28 import org.openhab.core.thing.ThingStatusDetail;
29 import org.openhab.core.thing.binding.BaseThingHandler;
30 import org.openhab.core.thing.binding.ThingHandler;
31 import org.openhab.core.types.Command;
32 import org.openhab.core.types.State;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 import com.google.gson.Gson;
37 import com.google.gson.GsonBuilder;
38 import com.google.gson.JsonElement;
39
40 import rx.Observable;
41 import rx.Subscription;
42
43 /**
44  * The {@link MinecraftPlayerHandler} is responsible for handling commands, which are
45  * sent to one of the channels.
46  *
47  * @author Mattias Markehed - Initial contribution
48  */
49 public class MinecraftPlayerHandler extends BaseThingHandler {
50
51     private Logger logger = LoggerFactory.getLogger(MinecraftPlayerHandler.class);
52
53     private Subscription playerSubscription;
54     private MinecraftServerHandler bridgeHandler;
55     private PlayerConfig config;
56     private Gson gson = new GsonBuilder().create();
57
58     public MinecraftPlayerHandler(Thing thing) {
59         super(thing);
60     }
61
62     @Override
63     public void initialize() {
64         this.bridgeHandler = getBridgeHandler();
65         this.config = getThing().getConfiguration().as(PlayerConfig.class);
66
67         if (bridgeHandler == null || getThing().getBridgeUID() == null) {
68             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No bridge configured");
69
70             return;
71         }
72
73         updateStatus(ThingStatus.ONLINE);
74         hookupListeners(bridgeHandler);
75     }
76
77     @Override
78     public void dispose() {
79         super.dispose();
80         if (!playerSubscription.isUnsubscribed()) {
81             playerSubscription.unsubscribe();
82         }
83     }
84
85     private void hookupListeners(MinecraftServerHandler bridgeHandler) {
86         playerSubscription = bridgeHandler.getPlayerRx().doOnNext(players -> {
87             boolean playerOnline = false;
88             for (PlayerData player : players) {
89                 if (config.getName().equals(player.getName())) {
90                     playerOnline = true;
91                     break;
92                 }
93             }
94             State onlineState = playerOnline ? OnOffType.ON : OnOffType.OFF;
95             updateState(MinecraftBindingConstants.CHANNEL_PLAYER_ONLINE, onlineState);
96         }).flatMap(players -> Observable.from(players)).filter(player -> config.getName().equals(player.getName()))
97                 .subscribe(player -> updatePlayerState(player));
98     }
99
100     /**
101      * Updates the state of player
102      *
103      * @param player the player to update
104      */
105     private void updatePlayerState(PlayerData player) {
106         State playerLevel = new DecimalType(player.getLevel());
107         State playerLevelPercentage = new DecimalType(player.getExperience());
108         State playerTotalExperience = new DecimalType(player.getTotalExperience());
109         State playerHealth = new DecimalType(player.getHealth());
110         State playerWalkSpeed = new DecimalType(player.getWalkSpeed());
111         DecimalType longitude = new DecimalType(player.getLocation().getX());
112         DecimalType latitude = new DecimalType(player.getLocation().getY());
113         DecimalType altitude = new DecimalType(player.getLocation().getY());
114         State playerLocation = new PointType(latitude, longitude, altitude);
115         State playerGameMode = new StringType(player.getGameMode());
116
117         updateState(MinecraftBindingConstants.CHANNEL_PLAYER_LEVEL_PERCENTAGE, playerLevelPercentage);
118         updateState(MinecraftBindingConstants.CHANNEL_PLAYER_TOTAL_EXPERIENCE, playerTotalExperience);
119         updateState(MinecraftBindingConstants.CHANNEL_PLAYER_LEVEL, playerLevel);
120         updateState(MinecraftBindingConstants.CHANNEL_PLAYER_HEALTH, playerHealth);
121         updateState(MinecraftBindingConstants.CHANNEL_PLAYER_WALK_SPEED, playerWalkSpeed);
122         updateState(MinecraftBindingConstants.CHANNEL_PLAYER_LOCATION, playerLocation);
123         updateState(MinecraftBindingConstants.CHANNEL_PLAYER_GAME_MODE, playerGameMode);
124     }
125
126     private String getPlayerName() {
127         return config.getName();
128     }
129
130     private synchronized MinecraftServerHandler getBridgeHandler() {
131         Bridge bridge = getBridge();
132         if (bridge == null) {
133             logger.debug("Required bridge not defined for device {}.", getThing().getUID());
134             return null;
135         } else {
136             return getBridgeHandler(bridge);
137         }
138     }
139
140     private synchronized MinecraftServerHandler getBridgeHandler(Bridge bridge) {
141         MinecraftServerHandler bridgeHandler = null;
142
143         ThingHandler handler = bridge.getHandler();
144         if (handler instanceof MinecraftServerHandler) {
145             bridgeHandler = (MinecraftServerHandler) handler;
146         } else {
147             logger.debug("No available bridge handler found yet. Bridge: {} .", bridge.getUID());
148             bridgeHandler = null;
149         }
150         return bridgeHandler;
151     }
152
153     @Override
154     public void updateState(String channelID, State state) {
155         ChannelUID channelUID = new ChannelUID(this.getThing().getUID(), channelID);
156         updateState(channelUID, state);
157     }
158
159     /**
160      * Send a player command to server.
161      *
162      * @param type the type of command to send
163      * @param playerName the name of the player to target
164      * @param value the related to command
165      */
166     private void sendPlayerCommand(String type, String playerName, String value) {
167         PlayerCommandData playerCommand = new PlayerCommandData(type, playerName, value);
168         JsonElement serializedCommand = gson.toJsonTree(playerCommand);
169         logger.debug("Command: {}", serializedCommand);
170         bridgeHandler.sendMessage(new OHMessage(OHMessage.MESSAGE_TYPE_PLAYER_COMMANDS, serializedCommand));
171     }
172
173     @Override
174     public void handleCommand(ChannelUID channelUID, Command command) {
175         switch (channelUID.getId()) {
176             case MinecraftBindingConstants.CHANNEL_PLAYER_HEALTH:
177                 sendPlayerCommand(PlayerCommandData.COMMAND_PLAYER_HEALTH, getPlayerName(), command.toString());
178                 break;
179             case MinecraftBindingConstants.CHANNEL_PLAYER_LEVEL:
180                 sendPlayerCommand(PlayerCommandData.COMMAND_PLAYER_LEVEL, getPlayerName(), command.toString());
181                 break;
182             case MinecraftBindingConstants.CHANNEL_PLAYER_WALK_SPEED:
183                 sendPlayerCommand(PlayerCommandData.COMMAND_PLAYER_WALK_SPEED, getPlayerName(), command.toString());
184                 break;
185             case MinecraftBindingConstants.CHANNEL_PLAYER_GAME_MODE:
186                 sendPlayerCommand(PlayerCommandData.COMMAND_PLAYER_GAME_MODE, getPlayerName(), command.toString());
187                 break;
188             case MinecraftBindingConstants.CHANNEL_PLAYER_LOCATION:
189                 sendPlayerCommand(PlayerCommandData.COMMAND_PLAYER_LOCATION, getPlayerName(), command.toString());
190                 break;
191             default:
192                 break;
193         }
194     }
195 }