mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-22 01:20:36 +00:00
Added a optional webhook for harmony-activity changes
This commit is contained in:
139
src/main/java/com/bwssystems/HABridge/HttpRequestHelper.java
Normal file
139
src/main/java/com/bwssystems/HABridge/HttpRequestHelper.java
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
package com.bwssystems.HABridge;
|
||||||
|
|
||||||
|
import com.bwssystems.HABridge.api.NameValue;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.client.config.CookieSpecs;
|
||||||
|
import org.apache.http.client.config.RequestConfig;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.client.methods.HttpPut;
|
||||||
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
import org.apache.http.ssl.SSLContexts;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Helper-Class to Call HTTP- and HTTPS-URLs
|
||||||
|
*
|
||||||
|
* Created by CrEaK on 23.12.16 19:34.
|
||||||
|
*/
|
||||||
|
public enum HttpRequestHelper {
|
||||||
|
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(HttpRequestHelper.class);
|
||||||
|
|
||||||
|
|
||||||
|
private HttpClient httpClient;
|
||||||
|
private CloseableHttpClient httpclientSSL;
|
||||||
|
private SSLContext sslcontext;
|
||||||
|
private SSLConnectionSocketFactory sslsf;
|
||||||
|
private RequestConfig globalConfig;
|
||||||
|
|
||||||
|
HttpRequestHelper() {
|
||||||
|
this.httpClient = HttpClients.createDefault();
|
||||||
|
// Trust own CA and all self-signed certs
|
||||||
|
this.sslcontext = SSLContexts.createDefault();
|
||||||
|
// Allow TLSv1 protocol only
|
||||||
|
this.sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
|
||||||
|
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
|
||||||
|
this.globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();
|
||||||
|
this.httpclientSSL = HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultRequestConfig(globalConfig).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function executes the url from the device repository against the
|
||||||
|
// target as http or https as defined
|
||||||
|
public String doHttpRequest(String url, String httpVerb, String contentType, String body, NameValue[] headers) {
|
||||||
|
HttpUriRequest request = null;
|
||||||
|
String theContent = null;
|
||||||
|
URI theURI = null;
|
||||||
|
ContentType parsedContentType = null;
|
||||||
|
StringEntity requestBody = null;
|
||||||
|
if (contentType != null && contentType.length() > 0) {
|
||||||
|
parsedContentType = ContentType.parse(contentType);
|
||||||
|
if (body != null && body.length() > 0)
|
||||||
|
requestBody = new StringEntity(body, parsedContentType);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
theURI = new URI(url);
|
||||||
|
} catch (URISyntaxException e1) {
|
||||||
|
log.warn("Error creating URI http request: " + url + " with message: " + e1.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (HttpGet.METHOD_NAME.equalsIgnoreCase(httpVerb) || httpVerb == null) {
|
||||||
|
request = new HttpGet(theURI);
|
||||||
|
} else if (HttpPost.METHOD_NAME.equalsIgnoreCase(httpVerb)) {
|
||||||
|
HttpPost postRequest = new HttpPost(theURI);
|
||||||
|
if (requestBody != null)
|
||||||
|
postRequest.setEntity(requestBody);
|
||||||
|
request = postRequest;
|
||||||
|
} else if (HttpPut.METHOD_NAME.equalsIgnoreCase(httpVerb)) {
|
||||||
|
HttpPut putRequest = new HttpPut(theURI);
|
||||||
|
if (requestBody != null)
|
||||||
|
putRequest.setEntity(requestBody);
|
||||||
|
request = putRequest;
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
log.warn("Error creating outbound http request: IllegalArgumentException in log", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
log.debug("Making outbound call in doHttpRequest: " + request);
|
||||||
|
if (headers != null && headers.length > 0) {
|
||||||
|
for (int i = 0; i < headers.length; i++) {
|
||||||
|
request.setHeader(headers[i].getName(), headers[i].getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
HttpResponse response;
|
||||||
|
if (url.startsWith("https"))
|
||||||
|
response = httpclientSSL.execute(request);
|
||||||
|
else
|
||||||
|
response = httpClient.execute(request);
|
||||||
|
log.debug((httpVerb == null ? "GET" : httpVerb) + " execute on URL responded: "
|
||||||
|
+ response.getStatusLine().getStatusCode());
|
||||||
|
if (response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300) {
|
||||||
|
if (response.getEntity() != null) {
|
||||||
|
try {
|
||||||
|
theContent = EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8")); // read
|
||||||
|
// content
|
||||||
|
// for
|
||||||
|
// data
|
||||||
|
EntityUtils.consume(response.getEntity()); // close out
|
||||||
|
// inputstream
|
||||||
|
// ignore
|
||||||
|
// content
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug(
|
||||||
|
"Error ocurred in handling response entity after successful call, still responding success. "
|
||||||
|
+ e.getMessage(),
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (theContent == null)
|
||||||
|
theContent = "";
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.warn("Error calling out to HA gateway: IOException in log", e);
|
||||||
|
}
|
||||||
|
return theContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpClient getHttpClient() {
|
||||||
|
return httpClient;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package com.bwssystems.HABridge;
|
|||||||
public class NamedIP {
|
public class NamedIP {
|
||||||
private String name;
|
private String name;
|
||||||
private String ip;
|
private String ip;
|
||||||
|
private String webhook;
|
||||||
private String port;
|
private String port;
|
||||||
private String username;
|
private String username;
|
||||||
private String password;
|
private String password;
|
||||||
@@ -19,6 +20,12 @@ public class NamedIP {
|
|||||||
public void setIp(String ip) {
|
public void setIp(String ip) {
|
||||||
this.ip = ip;
|
this.ip = ip;
|
||||||
}
|
}
|
||||||
|
public String getWebhook() {
|
||||||
|
return webhook;
|
||||||
|
}
|
||||||
|
public void setWebhook(final String webhook) {
|
||||||
|
this.webhook = webhook;
|
||||||
|
}
|
||||||
public String getPort() {
|
public String getPort() {
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ package com.bwssystems.HABridge.hue;
|
|||||||
|
|
||||||
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
|
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
|
||||||
import com.bwssystems.HABridge.DeviceMapTypes;
|
import com.bwssystems.HABridge.DeviceMapTypes;
|
||||||
|
import com.bwssystems.HABridge.HttpRequestHelper;
|
||||||
import com.bwssystems.HABridge.api.CallItem;
|
import com.bwssystems.HABridge.api.CallItem;
|
||||||
import com.bwssystems.HABridge.api.CallItemDeserializer;
|
|
||||||
import com.bwssystems.HABridge.api.NameValue;
|
import com.bwssystems.HABridge.api.NameValue;
|
||||||
import com.bwssystems.HABridge.api.UserCreateRequest;
|
import com.bwssystems.HABridge.api.UserCreateRequest;
|
||||||
import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
||||||
@@ -34,7 +34,6 @@ import com.bwssystems.nest.controller.Nest;
|
|||||||
import com.bwssystems.util.JsonTransformer;
|
import com.bwssystems.util.JsonTransformer;
|
||||||
import com.bwssystems.util.UDPDatagramSender;
|
import com.bwssystems.util.UDPDatagramSender;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
|
|
||||||
import net.java.dev.eval.Expression;
|
import net.java.dev.eval.Expression;
|
||||||
|
|
||||||
@@ -43,22 +42,9 @@ import static spark.Spark.options;
|
|||||||
import static spark.Spark.post;
|
import static spark.Spark.post;
|
||||||
import static spark.Spark.put;
|
import static spark.Spark.put;
|
||||||
|
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.HttpStatus;
|
import org.apache.http.HttpStatus;
|
||||||
import org.apache.http.client.HttpClient;
|
|
||||||
import org.apache.http.client.config.CookieSpecs;
|
|
||||||
import org.apache.http.client.config.RequestConfig;
|
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
|
||||||
import org.apache.http.client.methods.HttpPut;
|
import org.apache.http.client.methods.HttpPut;
|
||||||
import org.apache.http.client.methods.HttpUriRequest;
|
|
||||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
|
||||||
import org.apache.http.entity.ContentType;
|
|
||||||
import org.apache.http.entity.StringEntity;
|
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
|
||||||
import org.apache.http.impl.client.HttpClients;
|
|
||||||
import org.apache.http.ssl.SSLContexts;
|
|
||||||
import org.apache.http.util.EntityUtils;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -69,9 +55,6 @@ import java.math.BigDecimal;
|
|||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -80,7 +63,6 @@ import java.util.Set;
|
|||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.xml.bind.DatatypeConverter;
|
import javax.xml.bind.DatatypeConverter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,11 +83,6 @@ public class HueMulator implements HueErrorStringSet {
|
|||||||
private Nest theNest;
|
private Nest theNest;
|
||||||
private HueHome myHueHome;
|
private HueHome myHueHome;
|
||||||
private MQTTHome mqttHome;
|
private MQTTHome mqttHome;
|
||||||
private HttpClient httpClient;
|
|
||||||
private CloseableHttpClient httpclientSSL;
|
|
||||||
private SSLContext sslcontext;
|
|
||||||
private SSLConnectionSocketFactory sslsf;
|
|
||||||
private RequestConfig globalConfig;
|
|
||||||
private BridgeSettingsDescriptor bridgeSettings;
|
private BridgeSettingsDescriptor bridgeSettings;
|
||||||
private UDPDatagramSender theUDPDatagramSender;
|
private UDPDatagramSender theUDPDatagramSender;
|
||||||
private byte[] sendData;
|
private byte[] sendData;
|
||||||
@@ -116,15 +93,6 @@ public class HueMulator implements HueErrorStringSet {
|
|||||||
public HueMulator(BridgeSettingsDescriptor theBridgeSettings, DeviceRepository aDeviceRepository,
|
public HueMulator(BridgeSettingsDescriptor theBridgeSettings, DeviceRepository aDeviceRepository,
|
||||||
HarmonyHome theHarmonyHome, NestHome aNestHome, HueHome aHueHome, MQTTHome aMqttHome,
|
HarmonyHome theHarmonyHome, NestHome aNestHome, HueHome aHueHome, MQTTHome aMqttHome,
|
||||||
UDPDatagramSender aUdpDatagramSender) {
|
UDPDatagramSender aUdpDatagramSender) {
|
||||||
httpClient = HttpClients.createDefault();
|
|
||||||
// Trust own CA and all self-signed certs
|
|
||||||
sslcontext = SSLContexts.createDefault();
|
|
||||||
// Allow TLSv1 protocol only
|
|
||||||
sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
|
|
||||||
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
|
|
||||||
globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();
|
|
||||||
httpclientSSL = HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultRequestConfig(globalConfig).build();
|
|
||||||
|
|
||||||
repository = aDeviceRepository;
|
repository = aDeviceRepository;
|
||||||
if (theBridgeSettings.isValidHarmony())
|
if (theBridgeSettings.isValidHarmony())
|
||||||
this.myHarmonyHome = theHarmonyHome;
|
this.myHarmonyHome = theHarmonyHome;
|
||||||
@@ -309,7 +277,7 @@ public class HueMulator implements HueErrorStringSet {
|
|||||||
if ((device.getMapType() != null && device.getMapType().equalsIgnoreCase("hueDevice"))) {
|
if ((device.getMapType() != null && device.getMapType().equalsIgnoreCase("hueDevice"))) {
|
||||||
HueDeviceIdentifier deviceId = new Gson().fromJson(device.getOnUrl(), HueDeviceIdentifier.class);
|
HueDeviceIdentifier deviceId = new Gson().fromJson(device.getOnUrl(), HueDeviceIdentifier.class);
|
||||||
if (myHueHome.getTheHUERegisteredUser() == null) {
|
if (myHueHome.getTheHUERegisteredUser() == null) {
|
||||||
hueUser = HueUtil.registerWithHue(httpClient, deviceId.getIpAddress(), device.getName(),
|
hueUser = HueUtil.registerWithHue(deviceId.getIpAddress(), device.getName(),
|
||||||
myHueHome.getTheHUERegisteredUser(), this);
|
myHueHome.getTheHUERegisteredUser(), this);
|
||||||
if (hueUser == null) {
|
if (hueUser == null) {
|
||||||
return errorString;
|
return errorString;
|
||||||
@@ -317,7 +285,7 @@ public class HueMulator implements HueErrorStringSet {
|
|||||||
myHueHome.setTheHUERegisteredUser(hueUser);
|
myHueHome.setTheHUERegisteredUser(hueUser);
|
||||||
}
|
}
|
||||||
// make call
|
// make call
|
||||||
responseString = doHttpRequest(
|
responseString = HttpRequestHelper.INSTANCE.doHttpRequest(
|
||||||
"http://" + deviceId.getIpAddress() + "/api/" + myHueHome.getTheHUERegisteredUser()
|
"http://" + deviceId.getIpAddress() + "/api/" + myHueHome.getTheHUERegisteredUser()
|
||||||
+ "/lights/" + deviceId.getDeviceId(),
|
+ "/lights/" + deviceId.getDeviceId(),
|
||||||
HttpGet.METHOD_NAME, device.getContentType(), null, null);
|
HttpGet.METHOD_NAME, device.getContentType(), null, null);
|
||||||
@@ -327,7 +295,7 @@ public class HueMulator implements HueErrorStringSet {
|
|||||||
} else
|
} else
|
||||||
if (responseString.contains("[{\"error\":") && responseString.contains("unauthorized user")) {
|
if (responseString.contains("[{\"error\":") && responseString.contains("unauthorized user")) {
|
||||||
myHueHome.setTheHUERegisteredUser(null);
|
myHueHome.setTheHUERegisteredUser(null);
|
||||||
hueUser = HueUtil.registerWithHue(httpClient, deviceId.getIpAddress(), device.getName(),
|
hueUser = HueUtil.registerWithHue(deviceId.getIpAddress(), device.getName(),
|
||||||
myHueHome.getTheHUERegisteredUser(), this);
|
myHueHome.getTheHUERegisteredUser(), this);
|
||||||
if (hueUser == null) {
|
if (hueUser == null) {
|
||||||
return errorString;
|
return errorString;
|
||||||
@@ -527,7 +495,7 @@ public class HueMulator implements HueErrorStringSet {
|
|||||||
if ((device.getMapType() != null && device.getMapType().equalsIgnoreCase("hueDevice"))) {
|
if ((device.getMapType() != null && device.getMapType().equalsIgnoreCase("hueDevice"))) {
|
||||||
HueDeviceIdentifier deviceId = new Gson().fromJson(device.getOnUrl(), HueDeviceIdentifier.class);
|
HueDeviceIdentifier deviceId = new Gson().fromJson(device.getOnUrl(), HueDeviceIdentifier.class);
|
||||||
if (myHueHome.getTheHUERegisteredUser() == null) {
|
if (myHueHome.getTheHUERegisteredUser() == null) {
|
||||||
hueUser = HueUtil.registerWithHue(httpClient, deviceId.getIpAddress(), device.getName(),
|
hueUser = HueUtil.registerWithHue(deviceId.getIpAddress(), device.getName(),
|
||||||
myHueHome.getTheHUERegisteredUser(), this);
|
myHueHome.getTheHUERegisteredUser(), this);
|
||||||
if (hueUser == null) {
|
if (hueUser == null) {
|
||||||
return errorString;
|
return errorString;
|
||||||
@@ -535,7 +503,7 @@ public class HueMulator implements HueErrorStringSet {
|
|||||||
myHueHome.setTheHUERegisteredUser(hueUser);
|
myHueHome.setTheHUERegisteredUser(hueUser);
|
||||||
}
|
}
|
||||||
// make call
|
// make call
|
||||||
responseString = doHttpRequest("http://" + deviceId.getIpAddress() + "/api/"
|
responseString = HttpRequestHelper.INSTANCE.doHttpRequest("http://" + deviceId.getIpAddress() + "/api/"
|
||||||
+ myHueHome.getTheHUERegisteredUser() + "/lights/" + deviceId.getDeviceId(),
|
+ myHueHome.getTheHUERegisteredUser() + "/lights/" + deviceId.getDeviceId(),
|
||||||
HttpGet.METHOD_NAME, device.getContentType(), null, null);
|
HttpGet.METHOD_NAME, device.getContentType(), null, null);
|
||||||
if (responseString == null) {
|
if (responseString == null) {
|
||||||
@@ -543,7 +511,7 @@ public class HueMulator implements HueErrorStringSet {
|
|||||||
lightResponse = DeviceResponse.createResponse(device);
|
lightResponse = DeviceResponse.createResponse(device);
|
||||||
} else if (responseString.contains("[{\"error\":") && responseString.contains("unauthorized user")) {
|
} else if (responseString.contains("[{\"error\":") && responseString.contains("unauthorized user")) {
|
||||||
myHueHome.setTheHUERegisteredUser(null);
|
myHueHome.setTheHUERegisteredUser(null);
|
||||||
hueUser = HueUtil.registerWithHue(httpClient, deviceId.getIpAddress(), device.getName(),
|
hueUser = HueUtil.registerWithHue(deviceId.getIpAddress(), device.getName(),
|
||||||
myHueHome.getTheHUERegisteredUser(), this);
|
myHueHome.getTheHUERegisteredUser(), this);
|
||||||
if (hueUser == null) {
|
if (hueUser == null) {
|
||||||
return errorString;
|
return errorString;
|
||||||
@@ -800,7 +768,7 @@ public class HueMulator implements HueErrorStringSet {
|
|||||||
|
|
||||||
HueDeviceIdentifier deviceId = new Gson().fromJson(callItems[i].getItem(), HueDeviceIdentifier.class);
|
HueDeviceIdentifier deviceId = new Gson().fromJson(callItems[i].getItem(), HueDeviceIdentifier.class);
|
||||||
if (myHueHome.getTheHUERegisteredUser() == null) {
|
if (myHueHome.getTheHUERegisteredUser() == null) {
|
||||||
hueUser = HueUtil.registerWithHue(httpClient, deviceId.getIpAddress(), device.getName(),
|
hueUser = HueUtil.registerWithHue(deviceId.getIpAddress(), device.getName(),
|
||||||
myHueHome.getTheHUERegisteredUser(), this);
|
myHueHome.getTheHUERegisteredUser(), this);
|
||||||
if (hueUser == null) {
|
if (hueUser == null) {
|
||||||
return errorString;
|
return errorString;
|
||||||
@@ -817,7 +785,7 @@ public class HueMulator implements HueErrorStringSet {
|
|||||||
theDelay = callItems[i].getDelay();
|
theDelay = callItems[i].getDelay();
|
||||||
else
|
else
|
||||||
theDelay = bridgeSettings.getButtonsleep();
|
theDelay = bridgeSettings.getButtonsleep();
|
||||||
responseString = doHttpRequest(
|
responseString = HttpRequestHelper.INSTANCE.doHttpRequest(
|
||||||
"http://" + deviceId.getIpAddress() + "/api/" + myHueHome.getTheHUERegisteredUser()
|
"http://" + deviceId.getIpAddress() + "/api/" + myHueHome.getTheHUERegisteredUser()
|
||||||
+ "/lights/" + deviceId.getDeviceId() + "/state",
|
+ "/lights/" + deviceId.getDeviceId() + "/state",
|
||||||
HttpPut.METHOD_NAME, device.getContentType(), request.body(), null);
|
HttpPut.METHOD_NAME, device.getContentType(), request.body(), null);
|
||||||
@@ -832,7 +800,7 @@ public class HueMulator implements HueErrorStringSet {
|
|||||||
} else if (responseString.contains("[{\"error\":")) {
|
} else if (responseString.contains("[{\"error\":")) {
|
||||||
if(responseString.contains("unauthorized user")) {
|
if(responseString.contains("unauthorized user")) {
|
||||||
myHueHome.setTheHUERegisteredUser(null);
|
myHueHome.setTheHUERegisteredUser(null);
|
||||||
hueUser = HueUtil.registerWithHue(httpClient, deviceId.getIpAddress(), device.getName(),
|
hueUser = HueUtil.registerWithHue(deviceId.getIpAddress(), device.getName(),
|
||||||
myHueHome.getTheHUERegisteredUser(), this);
|
myHueHome.getTheHUERegisteredUser(), this);
|
||||||
if (hueUser == null) {
|
if (hueUser == null) {
|
||||||
return errorString;
|
return errorString;
|
||||||
@@ -1132,7 +1100,7 @@ public class HueMulator implements HueErrorStringSet {
|
|||||||
calculateIntensity(state, theStateChanges, stateHasBri, stateHasBriInc),
|
calculateIntensity(state, theStateChanges, stateHasBri, stateHasBriInc),
|
||||||
false);
|
false);
|
||||||
// make call
|
// make call
|
||||||
if (doHttpRequest(anUrl, device.getHttpVerb(), device.getContentType(), body,
|
if (HttpRequestHelper.INSTANCE.doHttpRequest(anUrl, device.getHttpVerb(), device.getContentType(), body,
|
||||||
theHeaders) == null) {
|
theHeaders) == null) {
|
||||||
log.warn("Error on calling url to change device state: " + anUrl);
|
log.warn("Error on calling url to change device state: " + anUrl);
|
||||||
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||||
@@ -1239,84 +1207,6 @@ public class HueMulator implements HueErrorStringSet {
|
|||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function executes the url from the device repository against the
|
|
||||||
// target as http or https as defined
|
|
||||||
protected String doHttpRequest(String url, String httpVerb, String contentType, String body, NameValue[] headers) {
|
|
||||||
HttpUriRequest request = null;
|
|
||||||
String theContent = null;
|
|
||||||
URI theURI = null;
|
|
||||||
ContentType parsedContentType = null;
|
|
||||||
StringEntity requestBody = null;
|
|
||||||
if (contentType != null && contentType.length() > 0) {
|
|
||||||
parsedContentType = ContentType.parse(contentType);
|
|
||||||
if (body != null && body.length() > 0)
|
|
||||||
requestBody = new StringEntity(body, parsedContentType);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
theURI = new URI(url);
|
|
||||||
} catch (URISyntaxException e1) {
|
|
||||||
log.warn("Error creating URI http request: " + url + " with message: " + e1.getMessage());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (HttpGet.METHOD_NAME.equalsIgnoreCase(httpVerb) || httpVerb == null) {
|
|
||||||
request = new HttpGet(theURI);
|
|
||||||
} else if (HttpPost.METHOD_NAME.equalsIgnoreCase(httpVerb)) {
|
|
||||||
HttpPost postRequest = new HttpPost(theURI);
|
|
||||||
if (requestBody != null)
|
|
||||||
postRequest.setEntity(requestBody);
|
|
||||||
request = postRequest;
|
|
||||||
} else if (HttpPut.METHOD_NAME.equalsIgnoreCase(httpVerb)) {
|
|
||||||
HttpPut putRequest = new HttpPut(theURI);
|
|
||||||
if (requestBody != null)
|
|
||||||
putRequest.setEntity(requestBody);
|
|
||||||
request = putRequest;
|
|
||||||
}
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
log.warn("Error creating outbound http request: IllegalArgumentException in log", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
log.debug("Making outbound call in doHttpRequest: " + request);
|
|
||||||
if (headers != null && headers.length > 0) {
|
|
||||||
for (int i = 0; i < headers.length; i++) {
|
|
||||||
request.setHeader(headers[i].getName(), headers[i].getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
HttpResponse response;
|
|
||||||
if (url.startsWith("https"))
|
|
||||||
response = httpclientSSL.execute(request);
|
|
||||||
else
|
|
||||||
response = httpClient.execute(request);
|
|
||||||
log.debug((httpVerb == null ? "GET" : httpVerb) + " execute on URL responded: "
|
|
||||||
+ response.getStatusLine().getStatusCode());
|
|
||||||
if (response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300) {
|
|
||||||
if (response.getEntity() != null) {
|
|
||||||
try {
|
|
||||||
theContent = EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8")); // read
|
|
||||||
// content
|
|
||||||
// for
|
|
||||||
// data
|
|
||||||
EntityUtils.consume(response.getEntity()); // close out
|
|
||||||
// inputstream
|
|
||||||
// ignore
|
|
||||||
// content
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.debug(
|
|
||||||
"Error ocurred in handling response entity after successful call, still responding success. "
|
|
||||||
+ e.getMessage(),
|
|
||||||
e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (theContent == null)
|
|
||||||
theContent = "";
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.warn("Error calling out to HA gateway: IOException in log", e);
|
|
||||||
}
|
|
||||||
return theContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String doExecRequest(String anItem, int intensity, String lightId) {
|
private String doExecRequest(String anItem, int intensity, String lightId) {
|
||||||
log.debug("Executing request: " + anItem);
|
log.debug("Executing request: " + anItem);
|
||||||
String responseString = null;
|
String responseString = null;
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import static java.lang.String.format;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import com.bwssystems.HABridge.HttpRequestHelper;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -18,7 +20,13 @@ import net.whistlingfish.harmony.HarmonyClientModule;
|
|||||||
import net.whistlingfish.harmony.config.Activity;
|
import net.whistlingfish.harmony.config.Activity;
|
||||||
import net.whistlingfish.harmony.protocol.OAReplyProvider;
|
import net.whistlingfish.harmony.protocol.OAReplyProvider;
|
||||||
|
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
|
||||||
public class HarmonyServer {
|
public class HarmonyServer {
|
||||||
|
|
||||||
|
private static final String ACTIVIY_ID = "${activity.id}";
|
||||||
|
private static final String ACTIVIY_LABEL = "${activity.label}";
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private HarmonyClient harmonyClient;
|
private HarmonyClient harmonyClient;
|
||||||
|
|
||||||
@@ -37,16 +45,22 @@ public class HarmonyServer {
|
|||||||
isDevMode = false;
|
isDevMode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HarmonyServer setup(BridgeSettingsDescriptor bridgeSettings, Boolean harmonyDevMode, NamedIP theHarmonyAddress) throws Exception {
|
public static HarmonyServer setup(
|
||||||
if(!bridgeSettings.isValidHarmony() && harmonyDevMode) {
|
BridgeSettingsDescriptor bridgeSettings,
|
||||||
|
Boolean harmonyDevMode,
|
||||||
|
NamedIP theHarmonyAddress
|
||||||
|
) throws Exception {
|
||||||
|
if (!bridgeSettings.isValidHarmony() && harmonyDevMode) {
|
||||||
return new HarmonyServer(theHarmonyAddress);
|
return new HarmonyServer(theHarmonyAddress);
|
||||||
}
|
}
|
||||||
Injector injector = null;
|
Injector injector = null;
|
||||||
if(!harmonyDevMode)
|
if (!harmonyDevMode) {
|
||||||
injector = Guice.createInjector(new HarmonyClientModule());
|
injector = Guice.createInjector(new HarmonyClientModule());
|
||||||
|
}
|
||||||
HarmonyServer mainObject = new HarmonyServer(theHarmonyAddress);
|
HarmonyServer mainObject = new HarmonyServer(theHarmonyAddress);
|
||||||
if(!harmonyDevMode)
|
if (!harmonyDevMode) {
|
||||||
injector.injectMembers(mainObject);
|
injector.injectMembers(mainObject);
|
||||||
|
}
|
||||||
mainObject.execute(bridgeSettings, harmonyDevMode);
|
mainObject.execute(bridgeSettings, harmonyDevMode);
|
||||||
return mainObject;
|
return mainObject;
|
||||||
}
|
}
|
||||||
@@ -55,23 +69,36 @@ public class HarmonyServer {
|
|||||||
Boolean noopCalls = Boolean.parseBoolean(System.getProperty("noop.calls", "false"));
|
Boolean noopCalls = Boolean.parseBoolean(System.getProperty("noop.calls", "false"));
|
||||||
isDevMode = harmonyDevMode;
|
isDevMode = harmonyDevMode;
|
||||||
String modeString = "";
|
String modeString = "";
|
||||||
if(dummyProvider != null)
|
if (dummyProvider != null) {
|
||||||
log.debug("something is very wrong as dummyProvider is not null...");
|
log.debug("something is very wrong as dummyProvider is not null...");
|
||||||
if(isDevMode)
|
}
|
||||||
|
if (isDevMode) {
|
||||||
modeString = " (development mode)";
|
modeString = " (development mode)";
|
||||||
else if(noopCalls)
|
} else if (noopCalls) {
|
||||||
modeString = " (no op calls to harmony)";
|
modeString = " (no op calls to harmony)";
|
||||||
|
}
|
||||||
log.info("setup initiated " + modeString + "....");
|
log.info("setup initiated " + modeString + "....");
|
||||||
if(isDevMode)
|
if (isDevMode) {
|
||||||
{
|
|
||||||
harmonyClient = null;
|
harmonyClient = null;
|
||||||
devResponse = new DevModeResponse();
|
devResponse = new DevModeResponse();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
devResponse = null;
|
devResponse = null;
|
||||||
harmonyClient.addListener(new ActivityChangeListener() {
|
harmonyClient.addListener(new ActivityChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void activityStarted(Activity activity) {
|
public void activityStarted(Activity activity) {
|
||||||
|
String webhook = myNameAndIP.getWebhook();
|
||||||
|
try {
|
||||||
|
// Replacing variables
|
||||||
|
webhook = webhook.replace(ACTIVIY_ID, activity.getId().toString());
|
||||||
|
webhook = webhook.replace(ACTIVIY_LABEL, URLEncoder.encode(activity.getLabel(), "UTF-8"));
|
||||||
|
|
||||||
|
log.info(format("calling webhook: %s", webhook));
|
||||||
|
|
||||||
|
// Calling webhook
|
||||||
|
HttpRequestHelper.INSTANCE.doHttpRequest(webhook, HttpGet.METHOD_NAME, null, null, null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("could not call webhook: " + webhook, e);
|
||||||
|
}
|
||||||
log.info(format("activity changed: [%d] %s", activity.getId(), activity.getLabel()));
|
log.info(format("activity changed: [%d] %s", activity.getId(), activity.getLabel()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ package com.bwssystems.hue;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
import com.bwssystems.HABridge.HttpRequestHelper;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.client.HttpClient;
|
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.impl.client.HttpClients;
|
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -17,7 +17,6 @@ import com.google.gson.Gson;
|
|||||||
|
|
||||||
public class HueInfo implements HueErrorStringSet {
|
public class HueInfo implements HueErrorStringSet {
|
||||||
private static final Logger log = LoggerFactory.getLogger(HueInfo.class);
|
private static final Logger log = LoggerFactory.getLogger(HueInfo.class);
|
||||||
private HttpClient httpClient;
|
|
||||||
private NamedIP hueAddress;
|
private NamedIP hueAddress;
|
||||||
private String theUser;
|
private String theUser;
|
||||||
private HueHome theHueHome;
|
private HueHome theHueHome;
|
||||||
@@ -25,7 +24,6 @@ public class HueInfo implements HueErrorStringSet {
|
|||||||
|
|
||||||
public HueInfo(NamedIP addressName, HueHome aHueHome) {
|
public HueInfo(NamedIP addressName, HueHome aHueHome) {
|
||||||
super();
|
super();
|
||||||
httpClient = HttpClients.createDefault();
|
|
||||||
hueAddress = addressName;
|
hueAddress = addressName;
|
||||||
theUser = "habridge";
|
theUser = "habridge";
|
||||||
theHueHome = aHueHome;
|
theHueHome = aHueHome;
|
||||||
@@ -50,7 +48,7 @@ public class HueInfo implements HueErrorStringSet {
|
|||||||
log.debug("GET HueApiResponse - data: " + theData);
|
log.debug("GET HueApiResponse - data: " + theData);
|
||||||
if(theData.contains("[{\"error\":")) {
|
if(theData.contains("[{\"error\":")) {
|
||||||
if(theData.contains("unauthorized user")) {
|
if(theData.contains("unauthorized user")) {
|
||||||
theUser = HueUtil.registerWithHue(httpClient, hueAddress.getIp(), hueAddress.getName(), theHueHome.getTheHUERegisteredUser(), this);
|
theUser = HueUtil.registerWithHue(hueAddress.getIp(), hueAddress.getName(), theHueHome.getTheHUERegisteredUser(), this);
|
||||||
if(theUser == null) {
|
if(theUser == null) {
|
||||||
log.warn("Register to Hue for " + hueAddress.getName() + " returned error: " + errorString);
|
log.warn("Register to Hue for " + hueAddress.getName() + " returned error: " + errorString);
|
||||||
return null;
|
return null;
|
||||||
@@ -84,7 +82,7 @@ public class HueInfo implements HueErrorStringSet {
|
|||||||
log.debug("calling GET on URL: " + url);
|
log.debug("calling GET on URL: " + url);
|
||||||
HttpGet httpGet = new HttpGet(url);
|
HttpGet httpGet = new HttpGet(url);
|
||||||
try {
|
try {
|
||||||
HttpResponse response = httpClient.execute(httpGet);
|
HttpResponse response = HttpRequestHelper.INSTANCE.getHttpClient().execute(httpGet);
|
||||||
log.debug("GET on URL responded: " + response.getStatusLine().getStatusCode());
|
log.debug("GET on URL responded: " + response.getStatusLine().getStatusCode());
|
||||||
if(response.getStatusLine().getStatusCode() == 200){
|
if(response.getStatusLine().getStatusCode() == 200){
|
||||||
theContent = EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8")); //read content for data
|
theContent = EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8")); //read content for data
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ package com.bwssystems.hue;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import com.bwssystems.HABridge.HttpRequestHelper;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.client.HttpClient;
|
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpPost;
|
||||||
import org.apache.http.entity.ContentType;
|
import org.apache.http.entity.ContentType;
|
||||||
import org.apache.http.entity.StringEntity;
|
import org.apache.http.entity.StringEntity;
|
||||||
@@ -19,7 +19,7 @@ public class HueUtil {
|
|||||||
private static final Logger log = LoggerFactory.getLogger(HueUtil.class);
|
private static final Logger log = LoggerFactory.getLogger(HueUtil.class);
|
||||||
public static final String HUE_REQUEST = "/api";
|
public static final String HUE_REQUEST = "/api";
|
||||||
|
|
||||||
public static final String registerWithHue(HttpClient anHttpClient, String ipAddress, String aName, String theUser, HueErrorStringSet errorStringSet) {
|
public static final String registerWithHue(String ipAddress, String aName, String theUser, HueErrorStringSet errorStringSet) {
|
||||||
UserCreateRequest theLogin = new UserCreateRequest();
|
UserCreateRequest theLogin = new UserCreateRequest();
|
||||||
theLogin.setDevicetype("HABridge#MyMachine");
|
theLogin.setDevicetype("HABridge#MyMachine");
|
||||||
HttpPost postRequest = new HttpPost("http://" + ipAddress + HUE_REQUEST);
|
HttpPost postRequest = new HttpPost("http://" + ipAddress + HUE_REQUEST);
|
||||||
@@ -28,7 +28,7 @@ public class HueUtil {
|
|||||||
HttpResponse response = null;
|
HttpResponse response = null;
|
||||||
postRequest.setEntity(requestBody);
|
postRequest.setEntity(requestBody);
|
||||||
try {
|
try {
|
||||||
response = anHttpClient.execute(postRequest);
|
response = HttpRequestHelper.INSTANCE.getHttpClient().execute(postRequest);
|
||||||
log.debug("POST execute on URL responded: " + response.getStatusLine().getStatusCode());
|
log.debug("POST execute on URL responded: " + response.getStatusLine().getStatusCode());
|
||||||
if(response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300){
|
if(response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300){
|
||||||
String theBody = EntityUtils.toString(response.getEntity());
|
String theBody = EntityUtils.toString(response.getEntity());
|
||||||
|
|||||||
@@ -654,18 +654,21 @@ app.controller('SystemController', function ($scope, $location, $http, $window,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
$scope.addHarmonytoSettings = function (newharmonyname, newharmonyip) {
|
$scope.addHarmonytoSettings = function (newharmonyname, newharmonyip, newharmonywebhook) {
|
||||||
if($scope.bridge.settings.harmonyaddress == null) {
|
if($scope.bridge.settings.harmonyaddress == null) {
|
||||||
$scope.bridge.settings.harmonyaddress = { devices: [] };
|
$scope.bridge.settings.harmonyaddress = { devices: [] };
|
||||||
}
|
}
|
||||||
var newharmony = {name: newharmonyname, ip: newharmonyip }
|
var newharmony = {name: newharmonyname, ip: newharmonyip , webhook: newharmonywebhook }
|
||||||
$scope.bridge.settings.harmonyaddress.devices.push(newharmony);
|
$scope.bridge.settings.harmonyaddress.devices.push(newharmony);
|
||||||
$scope.newharmonyname = null;
|
$scope.newharmonyname = null;
|
||||||
$scope.newharmonyip = null;
|
$scope.newharmonyip = null;
|
||||||
|
$scope.newharmonywebhook = null;
|
||||||
};
|
};
|
||||||
$scope.removeHarmonytoSettings = function (harmonyname, harmonyip) {
|
$scope.removeHarmonytoSettings = function (harmonyname, harmonyip, harmonywebhook) {
|
||||||
for(var i = $scope.bridge.settings.harmonyaddress.devices.length - 1; i >= 0; i--) {
|
for(var i = $scope.bridge.settings.harmonyaddress.devices.length - 1; i >= 0; i--) {
|
||||||
if($scope.bridge.settings.harmonyaddress.devices[i].name === harmonyname && $scope.bridge.settings.harmonyaddress.devices[i].ip === harmonyip) {
|
if($scope.bridge.settings.harmonyaddress.devices[i].name === harmonyname
|
||||||
|
&& $scope.bridge.settings.harmonyaddress.devices[i].ip === harmonyip
|
||||||
|
&& $scope.bridge.settings.harmonyaddress.devices[i].webhook === harmonywebhook) {
|
||||||
$scope.bridge.settings.harmonyaddress.devices.splice(i, 1);
|
$scope.bridge.settings.harmonyaddress.devices.splice(i, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,14 +139,16 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>IP</th>
|
<th>IP</th>
|
||||||
|
<th>Webhook</th>
|
||||||
<th>Manage</th>
|
<th>Manage</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tr ng-repeat="harmony in bridge.settings.harmonyaddress.devices">
|
<tr ng-repeat="harmony in bridge.settings.harmonyaddress.devices">
|
||||||
<td>{{harmony.name}}</td>
|
<td>{{harmony.name}}</td>
|
||||||
<td>{{harmony.ip}}</td>
|
<td>{{harmony.ip}}</td>
|
||||||
|
<td>{{harmony.webhook}}</td>
|
||||||
<td><button class="btn btn-danger" type="submit"
|
<td><button class="btn btn-danger" type="submit"
|
||||||
ng-click="removeHarmonytoSettings(harmony.name, harmony.ip)">Del</button></td>
|
ng-click="removeHarmonytoSettings(harmony.name, harmony.ip, harmony.webhook)">Del</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><input id="bridge-settings-next-harmony-name"
|
<td><input id="bridge-settings-next-harmony-name"
|
||||||
@@ -155,8 +157,11 @@
|
|||||||
<td><input id="bridge-settings-next-harmony-ip"
|
<td><input id="bridge-settings-next-harmony-ip"
|
||||||
class="form-control" type="text" ng-model="newharmonyip"
|
class="form-control" type="text" ng-model="newharmonyip"
|
||||||
placeholder="192.168.1.3"></td>
|
placeholder="192.168.1.3"></td>
|
||||||
|
<td><input id="bridge-settings-next-harmony-webhook"
|
||||||
|
class="form-control" type="text" ng-model="newharmonywebhook"
|
||||||
|
placeholder="http://hook?a=${activity.label}"></td>
|
||||||
<td><button class="btn btn-success" type="submit"
|
<td><button class="btn btn-success" type="submit"
|
||||||
ng-click="addHarmonytoSettings(newharmonyname, newharmonyip)">Add</button></td>
|
ng-click="addHarmonytoSettings(newharmonyname, newharmonyip, newharmonywebhook)">Add</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table></td>
|
</table></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user