/tcp-driver/src/main/java/be/abollaert/domotics/light/drivers/tcp/TCPClient.java
https://github.com/abollaert/smartlights · Java · 525 lines · 259 code · 102 blank · 164 comment · 21 complexity · 040e42279814f9768ad626b1e3fe1a0a MD5 · raw file
- package be.abollaert.domotics.light.drivers.tcp;
- import java.io.IOException;
- import java.io.InputStream;
- import java.net.InetAddress;
- import java.util.Date;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- import org.apache.commons.httpclient.HttpClient;
- import org.apache.commons.httpclient.HttpException;
- import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
- import org.apache.commons.httpclient.methods.PostMethod;
- import be.abollaert.domotics.light.api.ChannelState;
- import be.abollaert.domotics.light.api.DigitalInputChannelConfiguration;
- import be.abollaert.domotics.light.api.DigitalModule;
- import be.abollaert.domotics.light.api.DigitalModuleConfiguration;
- import be.abollaert.domotics.light.api.DimMoodElement;
- import be.abollaert.domotics.light.api.DimmerDirection;
- import be.abollaert.domotics.light.api.DimmerInputChannelConfiguration;
- import be.abollaert.domotics.light.api.DimmerModuleConfiguration;
- import be.abollaert.domotics.light.api.Mood;
- import be.abollaert.domotics.light.api.SwitchMoodElement;
- import be.abollaert.domotics.light.protocolbuffers.Api;
- import be.abollaert.domotics.light.protocolbuffers.Api.GetDigitalModuleConfigResponse;
- import be.abollaert.domotics.light.protocolbuffers.Api.MessageResponse;
- import com.google.protobuf.Message;
- /**
- * The TCP client class provides access to the API.
- *
- * @author alex
- */
- public final class TCPClient {
-
- /** The URI for the GetModules request. */
- private static final String URI_GET_MODULES = "/api/GetModules";
-
- /** URI for the GetDigitalChannelConfig request. */
- private static final String URI_GET_DIGITAL_CHANNEL_CONFIG = "/api/GetDigitalInputChannelConfig";
-
- /** URI for the SwitchOutput request. */
- private static final String URI_SWITCH_OUTPUT ="/api/SwitchOutput";
-
- /** The URI to get the output channels. */
- private static final String URI_GET_OUTPUT_CHANNELS = "/api/GetOutputChannels";
-
- /** The URL to set an input channel configuration. */
- private static final String URI_SET_DIGITAL_INPUT_CONFIG = "/api/SetDigitalInputChannelConfig";
-
- /** The URL to set a digital module configuration. */
- private static final String URI_SET_DIGITAL_MODULE_CONFIG = "/api/SetDigitalModuleConfig";
-
- /** THe URL for saving the configuration of a {@link DigitalModule}. */
- private static final String URI_SAVE_DIGITAL_MODULE_CONFIG = "/api/SaveModuleConfig";
-
- /** URI to get the digital module configuration. */
- private static final String URI_GET_DIGITAL_MODULE_CONFIG = "/api/GetDigitalModuleConfiguration";
-
- /** URI used to get dimmer input channel configuration. */
- private static final String URI_GET_DIMMER_INPUT_CHANNEL_CONFIG = "/api/GetDimmerInputChannelConfig";
-
- /** URI for saving a mood. */
- private static final String URI_SAVE_MOOD = "/api/SaveMood";
-
- /** The URI for dimming. */
- private static final String URI_DIM = "/api/Dim";
-
- /** URI to set the dimmer module config. */
- private static final String URI_SET_DIMMER_MODULE_CONFIG = "/api/SetDimmerModuleConfig";
-
- /** URI to set the dimmer input configuration. */
- private static final String URI_SET_DIMMER_INPUT_CONFIG = "/api/SetDimmerInputConfiguration";
-
- /** URI to get the switch requests. */
- private static final String URI_GET_SWITCH_EVENTS = "/api/GetSwitchEvents";
-
- /** URI for getting the output state of a digital channel. */
- private static final String URI_GET_DIGITAL_OUTPUT_STATE = "/api/GetDigitalOutputState";
-
- /** URI for getting the output state of a dimmer channel. */
- private static final String URI_GET_DIMMER_OUTPUT_STATE = "/api/GetDimmerOutputState";
-
- /** URI for getting all moods. */
- private static final String URI_GET_MOODS = "/api/GetMoods";
-
- private static final String URI_ACTIVATE_MOOD = "/api/ActivateMood";
-
- private static final String URI_REMOVE_MOOD = "/api/RemoveMood";
-
- private static final String URI_ALL_LIGHTS_OFF = "/api/AllLightsOff";
-
- /** The HTTP client. */
- private HttpClient httpClient;
-
- /** The event listener. */
- private EventListener eventListener;
-
- /** The server address. */
- private String serverAddress;
-
- /** The server port. */
- private int port;
-
- /** The http client lock. */
- private final Lock httpClientLock = new ReentrantLock();
-
- /**
- * Connects the client.
- *
- * @param serverAddress The server address.
- * @param port The port.
- *
- * @throws IOException If an IO error occurs during the connect.
- */
- public void connect(final String serverAddress, final int port, final InetAddress iface) throws IOException {
- this.serverAddress = serverAddress;
- this.port = port;
-
- this.httpClient = new HttpClient();
-
- this.eventListener = new EventListener();
- this.eventListener.start(iface);
- }
-
- /**
- * Disconnects the client.
- *
- * @throws IOException If an IO error occurs while disconnecting.
- */
- public void disconnect() throws IOException {
- this.eventListener.stop();
- this.eventListener = null;
-
- this.httpClient = null;
- }
-
- /**
- * Gets the modules from the server.
- *
- * @return The modules from the server.
- *
- * @throws IOException If an IO error occurs.
- */
- public final Api.GetModulesResponse getModules() throws IOException {
- return (Api.GetModulesResponse)this.execute(URI_GET_MODULES, null, Api.GetModulesResponse.newBuilder());
- }
-
- /**
- * Returns the digital channel config for the requested channel.
- *
- * @param moduleId The module ID.
- * @param channelNumber The channel number.
- *
- * @return The config.
- *
- * @throws IOException
- */
- public final Api.GetDigitalInputChannelConfigResponse getDigitalChannelConfiguration(final int moduleId, final int channelNumber) throws IOException {
- final Api.GetDigitalInputChannelConfig.Builder builder = Api.GetDigitalInputChannelConfig.newBuilder();
- builder.setModuleId(moduleId);
- builder.setChannelNumber(channelNumber);
-
- return (Api.GetDigitalInputChannelConfigResponse)this.execute(URI_GET_DIGITAL_CHANNEL_CONFIG, builder.build(), Api.GetDigitalInputChannelConfigResponse.newBuilder());
- }
-
- public final void switchOutput(final int moduleId, final int channelNumber, final ChannelState desiredState) throws IOException {
- final Api.SwitchOutput.Builder builder = Api.SwitchOutput.newBuilder();
- builder.setModuleId(moduleId);
- builder.setChannelNumber(channelNumber);
- builder.setRequiredState(desiredState == ChannelState.ON ? true : false);
-
- this.executeVoidMessage(URI_SWITCH_OUTPUT, builder.build());
- }
-
- /**
- * Returns the switch events for the given module ID and channel number.
- *
- * @param moduleId
- * @param channelNumber
- * @param startDate
- * @param endDate
- * @return
- * @throws IOException
- */
- public final Api.SwitchEventList getSwitchEvents(final int moduleId, final int channelNumber, final Date startDate, final Date endDate) throws IOException {
- final Api.GetSwitchEvents.Builder requestBuilder = Api.GetSwitchEvents.newBuilder();
-
- requestBuilder.setModuleId(moduleId);
- requestBuilder.setChannelNumber(channelNumber);
-
- if (startDate != null) {
- requestBuilder.setStartDate(startDate.getTime());
- }
-
- if (endDate != null) {
- requestBuilder.setEndDate(endDate.getTime());
- }
-
- return (Api.SwitchEventList)this.execute(URI_GET_SWITCH_EVENTS, requestBuilder.build(), Api.SwitchEventList.newBuilder());
- }
-
- /**
- * Dim the given channel.
- *
- * @param moduleId The module ID.
- * @param channelNumber The channel number.
- * @param percentage The percentage.
- *
- * @throws IOException If an IO error occurs during the action.
- */
- public final void dim(final int moduleId, final int channelNumber, final int percentage) throws IOException {
- final Api.Dim.Builder messageBuilder = Api.Dim.newBuilder();
- messageBuilder.setModuleId(moduleId);
- messageBuilder.setChannelNumber(channelNumber);
- messageBuilder.setPercentage(percentage);
-
- this.executeVoidMessage(URI_DIM, messageBuilder.build());
- }
-
- public final Api.GetOutputChannelsResponse getOutputChannels() throws IOException {
- try {
- return (Api.GetOutputChannelsResponse)this.execute(URI_GET_OUTPUT_CHANNELS, null, Api.GetOutputChannelsResponse.newBuilder());
- } catch (HttpException e) {
- throw new IOException("HTTP error while getting modules : [" + e.getMessage() + "]");
- }
- }
-
- /**
- * Set the configuration for a particular digital input channel.
- *
- * @param newConfiguration The new configuration.
- *
- * @return The response.
- *
- * @throws IOException If an IO error occurs during the set.
- */
- public final void setDigitalInputChannelConfiguration(final DigitalInputChannelConfiguration newConfiguration) throws IOException {
- final Api.DigitalInputChannelConfig.Builder configurationBuilder = Api.DigitalInputChannelConfig.newBuilder();
- configurationBuilder.setCurrentOutputState(false);
- configurationBuilder.setCurrentSwitchState(false);
- configurationBuilder.setDefaultState(newConfiguration.getDefaultState() == ChannelState.ON ? true : false);
- configurationBuilder.setMappedOutputChannel(newConfiguration.getMappedOutputChannel());
- configurationBuilder.setTimerInSec(newConfiguration.getTimerInSeconds());
-
- if (newConfiguration.getName() != null) {
- configurationBuilder.setName(newConfiguration.getName());
- }
-
- configurationBuilder.setEnableLogging(newConfiguration.isLoggingEnabled());
-
- final Api.SetDigitalInputConfig.Builder messageBuilder = Api.SetDigitalInputConfig.newBuilder();
- messageBuilder.setModuleId(newConfiguration.getModuleId());
- messageBuilder.setChannelNumber(newConfiguration.getChannelNumber());
- messageBuilder.setConfig(configurationBuilder);
-
- this.executeVoidMessage(URI_SET_DIGITAL_INPUT_CONFIG, messageBuilder.build());
- }
-
- /**
- * Sets the configuration for a dimmer module.
- *
- * @param newConfiguration The new configuration.
- *
- * @throws IOException If an IO error occurs while setting.
- */
- public final void setDimmerModuleConfiguration(final DimmerModuleConfiguration newConfiguration) throws IOException {
- final Api.DimmerModuleConfig.Builder configBuilder = Api.DimmerModuleConfig.newBuilder();
-
- configBuilder.setDimmerDelay(newConfiguration.getDimmerDelay());
- configBuilder.setDimmerThresholdInMs(newConfiguration.getDimmerThreshold());
- configBuilder.setSwitchThresholdInMs(newConfiguration.getSwitchThreshold());
-
- final Api.SetDimmerModuleConfig.Builder messageBuilder = Api.SetDimmerModuleConfig.newBuilder();
- messageBuilder.setConfiguration(configBuilder);
- messageBuilder.setModuleId(newConfiguration.getModuleId());
-
- this.executeVoidMessage(URI_SET_DIMMER_MODULE_CONFIG, messageBuilder.build());
- }
-
- /**
- * Sets the configuration for a dimmer input.
- *
- * @param newConfiguration The new configuration.
- *
- * @throws IOException If an IO error occurs while setting.
- */
- public final void setDimmerInputConfiguration(final int moduleId, final int channelNumber, final DimmerInputChannelConfiguration newConfiguration) throws IOException {
- final Api.DimmerInputChannelConfig.Builder configBuilder = Api.DimmerInputChannelConfig.newBuilder();
-
- configBuilder.setCurrentDimmerPercentage(0);
- configBuilder.setCurrentOutputState(false);
- configBuilder.setCurrentSwitchState(false);
- configBuilder.setDefaultDirection(newConfiguration.getDefaultDirection() == DimmerDirection.UP ? true : false);
- configBuilder.setDefaultPercentage(newConfiguration.getDefaultPercentage());
- configBuilder.setDefaultState(newConfiguration.getDefaultState() == ChannelState.ON ? true : false);
- configBuilder.setMappedOutputChannel(newConfiguration.getMappedOutputChannel());
- configBuilder.setTimerInSec(newConfiguration.getTimerInSeconds());
-
- if (newConfiguration.getName() != null) {
- configBuilder.setName(newConfiguration.getName());
- }
-
- configBuilder.setEnableLogging(newConfiguration.isLoggingEnabled());
-
- final Api.SetDimmerInputConfig.Builder messageBuilder = Api.SetDimmerInputConfig.newBuilder();
- messageBuilder.setConfig(configBuilder);
- messageBuilder.setModuleId(moduleId);
- messageBuilder.setChannelNumber(channelNumber);
-
- this.executeVoidMessage(URI_SET_DIMMER_INPUT_CONFIG, messageBuilder.build());
- }
-
- /**
- * Sets the new digital module configuration.
- *
- * @param newConfiguration The new configuration.
- *
- * @return The response.
- *
- * @throws IOException If an IO error occurs.
- */
- public final void setDigitalModuleConfiguration(final DigitalModuleConfiguration newConfiguration) throws IOException {
- final Api.DigitalModuleConfig.Builder configurationBuilder = Api.DigitalModuleConfig.newBuilder();
- configurationBuilder.setSwitchThresholdInMs(newConfiguration.getSwitchThreshold());
-
- final Api.SetDigitalModuleConfig.Builder messageBuilder = Api.SetDigitalModuleConfig.newBuilder();
- messageBuilder.setModuleId(newConfiguration.getModuleId());
- messageBuilder.setConfiguration(configurationBuilder);
-
- this.executeVoidMessage(URI_SET_DIGITAL_MODULE_CONFIG, messageBuilder.build());
- }
-
- /**
- * Saves a digital module configuration.
- *
- * @param moduleId The module ID.
- *
- * @return The response.
- *
- * @throws IOException If an IO error occurs.
- */
- public final void saveModuleConfiguration(final int moduleId) throws IOException {
- final Api.SaveDigitalModuleConfig.Builder messageBuilder = Api.SaveDigitalModuleConfig.newBuilder();
- messageBuilder.setModuleId(moduleId);
-
- this.executeVoidMessage(URI_SAVE_DIGITAL_MODULE_CONFIG, messageBuilder.build());
- }
-
- public final int saveMood(final Mood mood) throws IOException {
- final Api.Mood.Builder moodBuilder = Api.Mood.newBuilder();
- moodBuilder.setName(mood.getName());
- moodBuilder.setMoodId(mood.getId());
-
- for (final SwitchMoodElement switchElement : mood.getSwitchMoodElements()) {
- final Api.SwitchMoodElement.Builder elementBuilder = Api.SwitchMoodElement.newBuilder();
-
- elementBuilder.setModuleId(switchElement.getModuleId());
- elementBuilder.setChannelNumber(switchElement.getChannelNumber());
- elementBuilder.setRequestedState(switchElement.getRequestedState() == ChannelState.ON);
-
- moodBuilder.addSwitchElements(elementBuilder.build());
- }
-
- for (final DimMoodElement dimmerElement : mood.getDimMoodElements()) {
- final Api.DimmerMoodElement.Builder elementBuilder = Api.DimmerMoodElement.newBuilder();
-
- elementBuilder.setModuleId(dimmerElement.getModuleId());
- elementBuilder.setChannelNumber(dimmerElement.getChannelNumber());
- elementBuilder.setPercentage(dimmerElement.getTargetPercentage());
-
- moodBuilder.addDimmerElements(elementBuilder.build());
- }
-
- final Api.SaveMood.Builder requestBuilder = Api.SaveMood.newBuilder();
- requestBuilder.setMood(moodBuilder.build());
-
- return ((Api.SaveMoodResponse)this.execute(URI_SAVE_MOOD, requestBuilder.build(), Api.SaveMoodResponse.newBuilder())).getMoodId();
- }
-
- /**
- * REturns the configuration of a digital module.
- *
- * @param moduleId The ID of the module.
- *
- * @return The configuration.
- *
- * @throws IOException
- */
- public final Api.DigitalModuleConfig getDigitalModuleConfig(final int moduleId) throws IOException {
- final Api.GetDigitalModuleConfig.Builder messageBuilder = Api.GetDigitalModuleConfig.newBuilder();
- messageBuilder.setModuleId(moduleId);
-
- final GetDigitalModuleConfigResponse response = (Api.GetDigitalModuleConfigResponse)this.execute(URI_GET_DIGITAL_MODULE_CONFIG, messageBuilder.build(), Api.GetDigitalModuleConfigResponse.newBuilder());
- return response.getConfig();
- }
-
- /**
- * Returns the event listener.
- *
- * @return The event listener.
- */
- public final EventListener getEventListener() {
- return this.eventListener;
- }
-
- /**
- * Generates the URL for the given URI.
- *
- * @param uri The URI to generate an URL for.
- *
- * @return The URL to use.
- */
- private final String generateURL(final String uri) {
- return new StringBuilder("http://").append(this.serverAddress).append(":").append(this.port).append(uri).toString();
- }
-
- /**
- * Get the configuration of an input channel on a dimmer module.
- *
- * @param moduleId The ID of the module.
- * @param channelNumber The channel number.
- *
- * @return The configuration of the channel.
- *
- * @throws IOException If an IO error occurs.
- */
- public final Api.DimmerInputChannelConfig getDimmerInputChannelConfiguration(final int moduleId, final int channelNumber) throws IOException {
- final Api.GetDimmerInputChannelConfig.Builder requestMessageBuilder = Api.GetDimmerInputChannelConfig.newBuilder();
- requestMessageBuilder.setModuleId(moduleId);
- requestMessageBuilder.setChannelNumber(channelNumber);
-
- final Api.GetDimmerInputChannelConfigResponse response = (Api.GetDimmerInputChannelConfigResponse)this.execute(URI_GET_DIMMER_INPUT_CHANNEL_CONFIG, requestMessageBuilder.build(), Api.GetDimmerInputChannelConfigResponse.newBuilder());
- return response.getConfig();
- }
-
- public final Api.DigitalChannelOutputState getDigitalChannelOutputState(final int moduleId, final int channelNumber) throws IOException {
- final Api.GetOutputChannelState.Builder requestBuilder = Api.GetOutputChannelState.newBuilder();
- requestBuilder.setModuleId(moduleId);
- requestBuilder.setChannelNumber(channelNumber);
-
- return (Api.DigitalChannelOutputState)this.execute(URI_GET_DIGITAL_OUTPUT_STATE, requestBuilder.build(), Api.DigitalChannelOutputState.newBuilder());
- }
-
- public final Api.DimmerChannelOutputState getDimmerChannelOutputState(final int moduleId, final int channelNumber) throws IOException {
- final Api.GetOutputChannelState.Builder requestBuilder = Api.GetOutputChannelState.newBuilder();
- requestBuilder.setModuleId(moduleId);
- requestBuilder.setChannelNumber(channelNumber);
-
- return (Api.DimmerChannelOutputState)this.execute(URI_GET_DIMMER_OUTPUT_STATE, requestBuilder.build(), Api.DimmerChannelOutputState.newBuilder());
- }
-
- /**
- * Executes the given message against the given URI, and returns the reult message if any.
- *
- * @param uri The URI.
- * @param message The message.
- * @param responseBuilder The response builder.
- *
- * @return The response message.
- *
- * @throws IOException If an IO error occurs.
- */
- private final Message execute(final String uri, final Message message, final Message.Builder responseBuilder) throws IOException {
- PostMethod method = new PostMethod(this.generateURL(uri));
-
- try {
- this.httpClientLock.lock();
-
- if (message != null) {
- method.setRequestEntity(new ByteArrayRequestEntity(message.toByteArray()));
- }
-
- this.httpClient.executeMethod(method);
-
- final InputStream responseBodyStream = method.getResponseBodyAsStream();
-
- if (responseBodyStream != null) {
- responseBuilder.mergeFrom(responseBodyStream);
- }
-
- return responseBuilder.build();
- } finally {
- method.releaseConnection();
- this.httpClientLock.unlock();
- }
- }
-
- private final void executeVoidMessage(final String uri, final Message message) throws IOException {
- final Api.MessageResponse response = (Api.MessageResponse)this.execute(uri, message, MessageResponse.newBuilder());
-
- if (response.getType() == Api.MessageResponse.Type.ERROR) {
- throw new IOException(response.getMessage());
- }
- }
-
- public final Api.MoodList getAllMoods() throws IOException {
- return (Api.MoodList)this.execute(URI_GET_MOODS, null, Api.MoodList.newBuilder());
- }
-
- public final void activateMood(final int moodId) throws IOException {
- final Api.ActivateMood.Builder requestBuilder = Api.ActivateMood.newBuilder();
- requestBuilder.setMoodId(moodId);
-
- this.executeVoidMessage(URI_ACTIVATE_MOOD, requestBuilder.build());
- }
-
- public final void removeMood(final int moodId) throws IOException {
- final Api.RemoveMood.Builder requestBuilder = Api.RemoveMood.newBuilder();
- requestBuilder.setMoodId(moodId);
-
- this.executeVoidMessage(URI_REMOVE_MOOD, requestBuilder.build());
- }
-
- /**
- * Switch all lights off.
- *
- * @throws IOException If an IO error occurs.
- */
- public final void allLightsOff() throws IOException {
- this.executeVoidMessage(URI_ALL_LIGHTS_OFF, null);
- }
- }