Compare commits

...

6 Commits

Author SHA1 Message Date
Admin
9c3d95f177 Finished implementing and testing state change and bug fixes from
testing

Fixes #44
Fixes #60
Fixes #61
Fixes #63
Fixes #66
Fixes #69
2016-03-21 16:37:13 -05:00
Admin
926a7f50dc Finished adding dim versus on, utf-8 and track state and return on api
calls.
2016-03-18 16:38:18 -05:00
Admin
ad820a68c9 Updated C/F setting. Started to implement UTF-8 2016-03-16 17:13:03 -05:00
Admin
73f0f766f7 Added more logging and updated nest controller version to fix issues
with range temp setting in nest.
2016-03-09 16:45:21 -06:00
Admin
113ce0ca59 Updated logging with new nest module. 2016-03-08 16:40:32 -06:00
bwssystems
a5860417c1 Update null numberoflogmessages 2016-02-27 12:56:42 -06:00
21 changed files with 353 additions and 211 deletions

View File

@@ -531,6 +531,30 @@ A response to a successful PUT request contains confirmation of the arguments pa
{"success":{"/lights/1/state/on":true}}, {"success":{"/lights/1/state/on":true}},
] ]
``` ```
### Update bridge internal light state
Allows the user to set the internal state of the light on and off, modify the brightness. This is not a HUE API call and is special to the bridge as it keeps track of the state changes to the light from the api. It is intended to allow you to sync the bridge state with your HA system state.
```
PUT http://host:port/api/<username>/lights/<id>/bridgeupdatestate
```
#### Body arguments
Name | Type | Description
-----|-------|-------------
on | bool | On/Off state of the light. On=true, Off=false. Optional
bri | uint8 | The brightness value to set the light to. Brightness is a scale from 1 (the minimum the light is capable of) to 254 (the maximum). Note: a brightness of 1 is not off. e.g. "brightness": 60 will set the light to a specific brightness. Optional
```
{
"on": true,
"bri": 200
}
```
#### Response
A response to a successful PUT request contains confirmation of the arguments passed in. Note: If the new value is too large to return in the response due to internal memory constraints then a value of "Updated." is returned.
```
[
{"success":{"/lights/1/state/bri":200}},
{"success":{"/lights/1/state/on":true}},
]
```
### Create user ### Create user
Emulates creating a new user. The link button state on the HA Bridge is always on for the purpose of responding to this request. No actual user is saved as this is for compatibility. Emulates creating a new user. The link button state on the HA Bridge is always on for the purpose of responding to this request. No actual user is saved as this is for compatibility.
``` ```

View File

@@ -5,7 +5,7 @@
<groupId>com.bwssystems.HABridge</groupId> <groupId>com.bwssystems.HABridge</groupId>
<artifactId>ha-bridge</artifactId> <artifactId>ha-bridge</artifactId>
<version>1.4.1</version> <version>1.4.2</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>HA Bridge</name> <name>HA Bridge</name>
@@ -43,7 +43,7 @@
<dependency> <dependency>
<groupId>com.github.bwssytems</groupId> <groupId>com.github.bwssytems</groupId>
<artifactId>nest-controller</artifactId> <artifactId>nest-controller</artifactId>
<version>1.0.5</version> <version>1.0.8</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>

View File

@@ -40,12 +40,14 @@ public class BridgeSettings extends BackupHandler {
String addressString = null; String addressString = null;
String theVeraAddress = null; String theVeraAddress = null;
String theHarmonyAddress = null; String theHarmonyAddress = null;
String configFileProperty = System.getProperty("config.file"); String configFileProperty = System.getProperty("config.file");
if(configFileProperty == null) { if(configFileProperty == null) {
Path filePath = Paths.get(Configuration.CONFIG_FILE); Path filePath = Paths.get(Configuration.CONFIG_FILE);
if(Files.exists(filePath) && Files.isReadable(filePath)) if(Files.exists(filePath) && Files.isReadable(filePath))
configFileProperty = Configuration.CONFIG_FILE; configFileProperty = Configuration.CONFIG_FILE;
} }
if(configFileProperty != null) if(configFileProperty != null)
{ {
log.info("reading from config file: " + configFileProperty); log.info("reading from config file: " + configFileProperty);
@@ -56,6 +58,7 @@ public class BridgeSettings extends BackupHandler {
{ {
log.info("reading from system properties"); log.info("reading from system properties");
theBridgeSettings.setNumberoflogmessages(Configuration.NUMBER_OF_LOG_MESSAGES); theBridgeSettings.setNumberoflogmessages(Configuration.NUMBER_OF_LOG_MESSAGES);
theBridgeSettings.setFarenheit(true);
theBridgeSettings.setConfigfile(Configuration.CONFIG_FILE); theBridgeSettings.setConfigfile(Configuration.CONFIG_FILE);
theBridgeSettings.setServerPort(System.getProperty("server.port", Configuration.DEFAULT_WEB_PORT)); theBridgeSettings.setServerPort(System.getProperty("server.port", Configuration.DEFAULT_WEB_PORT));
theBridgeSettings.setUpnpConfigAddress(System.getProperty("upnp.config.address")); theBridgeSettings.setUpnpConfigAddress(System.getProperty("upnp.config.address"));
@@ -142,6 +145,9 @@ public class BridgeSettings extends BackupHandler {
if(theBridgeSettings.getUpnpDeviceDb() == null) if(theBridgeSettings.getUpnpDeviceDb() == null)
theBridgeSettings.setUpnpDeviceDb(Configuration.DEVICE_DB_DIRECTORY); theBridgeSettings.setUpnpDeviceDb(Configuration.DEVICE_DB_DIRECTORY);
if(theBridgeSettings.getNumberoflogmessages() == null)
theBridgeSettings.setNumberoflogmessages(Configuration.NUMBER_OF_LOG_MESSAGES);
if(theBridgeSettings.getButtonsleep() <= 0) if(theBridgeSettings.getButtonsleep() <= 0)
theBridgeSettings.setButtonsleep(Integer.parseInt(Configuration.DEFAULT_BUTTON_SLEEP)); theBridgeSettings.setButtonsleep(Integer.parseInt(Configuration.DEFAULT_BUTTON_SLEEP));
@@ -179,6 +185,8 @@ public class BridgeSettings extends BackupHandler {
theBridgeSettings.setVeraconfigured(aBridgeSettings.isValidVera()); theBridgeSettings.setVeraconfigured(aBridgeSettings.isValidVera());
theBridgeSettings.setHarmonyconfigured(aBridgeSettings.isValidHarmony()); theBridgeSettings.setHarmonyconfigured(aBridgeSettings.isValidHarmony());
theBridgeSettings.setNestConfigured(aBridgeSettings.isValidNest()); theBridgeSettings.setNestConfigured(aBridgeSettings.isValidNest());
theBridgeSettings.setNumberoflogmessages(aBridgeSettings.getNumberoflogmessages());
theBridgeSettings.setFarenheit(aBridgeSettings.isFarenheit());
} }
public void save(BridgeSettingsDescriptor newBridgeSettings) { public void save(BridgeSettingsDescriptor newBridgeSettings) {

View File

@@ -19,6 +19,7 @@ public class BridgeSettingsDescriptor {
private boolean veraconfigured; private boolean veraconfigured;
private boolean harmonyconfigured; private boolean harmonyconfigured;
private boolean nestconfigured; private boolean nestconfigured;
private boolean farenheit;
private String configfile; private String configfile;
private Integer numberoflogmessages; private Integer numberoflogmessages;
@@ -29,6 +30,7 @@ public class BridgeSettingsDescriptor {
this.nestconfigured = false; this.nestconfigured = false;
this.veraconfigured = false; this.veraconfigured = false;
this.harmonyconfigured = false; this.harmonyconfigured = false;
this.farenheit = true;
} }
public String getUpnpConfigAddress() { public String getUpnpConfigAddress() {
return upnpconfigaddress; return upnpconfigaddress;
@@ -144,8 +146,14 @@ public class BridgeSettingsDescriptor {
public void setNumberoflogmessages(Integer numberoflogmessages) { public void setNumberoflogmessages(Integer numberoflogmessages) {
this.numberoflogmessages = numberoflogmessages; this.numberoflogmessages = numberoflogmessages;
} }
public boolean isFarenheit() {
return farenheit;
}
public void setFarenheit(boolean farenheit) {
this.farenheit = farenheit;
}
public Boolean isValidVera() { public Boolean isValidVera() {
if(this.getVeraAddress() == null) if(this.getVeraAddress() == null || this.getVeraAddress().getDevices().size() <= 0)
return false; return false;
List<NamedIP> devicesList = this.getVeraAddress().getDevices(); List<NamedIP> devicesList = this.getVeraAddress().getDevices();
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS)) if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))

View File

@@ -92,7 +92,7 @@ public class SystemControl {
// http://ip_address:port/system/logmgmt/loggers gets the logger info for the bridge // http://ip_address:port/system/logmgmt/loggers gets the logger info for the bridge
get (SYSTEM_CONTEXT + "/logmgmt/loggers/:all", "application/json", (request, response) -> { get (SYSTEM_CONTEXT + "/logmgmt/loggers/:all", "application/json", (request, response) -> {
log.info("Get loggers info with showAll argument: " + request.params(":all")); log.debug("Get loggers info with showAll argument: " + request.params(":all"));
Boolean showAll = false; Boolean showAll = false;
if(request.params(":all").equals("true")) if(request.params(":all").equals("true"))
showAll = true; showAll = true;
@@ -113,6 +113,7 @@ public class SystemControl {
}); });
// http://ip_address:port/system/logmgmt/update which changes logging parameters for the process // http://ip_address:port/system/logmgmt/update which changes logging parameters for the process
put(SYSTEM_CONTEXT + "/logmgmt/update", "application/json", (request, response) -> { put(SYSTEM_CONTEXT + "/logmgmt/update", "application/json", (request, response) -> {
log.debug("update loggers: " + request.body());
response.status(200); response.status(200);
LoggerInfo updateLoggers[]; LoggerInfo updateLoggers[];
updateLoggers = new Gson().fromJson(request.body(), LoggerInfo[].class); updateLoggers = new Gson().fromJson(request.body(), LoggerInfo[].class);
@@ -239,7 +240,7 @@ public class SystemControl {
} }
else else
log.warn("No filename given for restore backup."); log.warn("No filename given for restore backup.");
return null; return bridgeSettings.getBridgeSettingsDescriptor();
}, new JsonTransformer()); }, new JsonTransformer());
} }

View File

@@ -1,5 +1,7 @@
package com.bwssystems.HABridge.api.hue; package com.bwssystems.HABridge.api.hue;
import com.bwssystems.HABridge.dao.DeviceDescriptor;
/** /**
* Created by arm on 4/14/15. * Created by arm on 4/14/15.
*/ */
@@ -68,18 +70,18 @@ public class DeviceResponse {
this.swversion = swversion; this.swversion = swversion;
} }
public static DeviceResponse createResponse(String name, String id){ public static DeviceResponse createResponse(DeviceDescriptor device){
DeviceState deviceState = new DeviceState(); DeviceState deviceState = new DeviceState();
DeviceResponse response = new DeviceResponse(); DeviceResponse response = new DeviceResponse();
response.setState(deviceState); response.setState(deviceState);
deviceState.setOn(false); deviceState.setOn(device.getDeviceState());
deviceState.setReachable(true); deviceState.setReachable(true);
deviceState.setEffect("none"); deviceState.setEffect("none");
deviceState.setAlert("none"); deviceState.setAlert("none");
deviceState.setBri(254); deviceState.setBri(device.getDeviceSetValue());
response.setName(name); response.setName(device.getName());
response.setUniqueid(id); response.setUniqueid(device.getId());
response.setManufacturername("Philips"); response.setManufacturername("Philips");
response.setType("Dimmable light"); response.setType("Dimmable light");
response.setModelid("LWB004"); response.setModelid("LWB004");

View File

@@ -6,7 +6,7 @@ package com.bwssystems.HABridge.api.hue;
*/ */
public class DeviceState { public class DeviceState {
private boolean on; private boolean on;
private int bri = 255; private int bri = 0;
private String effect; private String effect;
private String alert; private String alert;
private boolean reachable; private boolean reachable;

View File

@@ -1,21 +1,55 @@
package com.bwssystems.HABridge.dao; package com.bwssystems.HABridge.dao;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/* /*
* Object to handle the device configuration * Object to handle the device configuration
*/ */
public class DeviceDescriptor{ public class DeviceDescriptor{
private String id; @SerializedName("id")
@Expose
private String id;
@SerializedName("name")
@Expose
private String name; private String name;
@SerializedName("mapId")
@Expose
private String mapId; private String mapId;
@SerializedName("mapType")
@Expose
private String mapType; private String mapType;
@SerializedName("deviceType")
@Expose
private String deviceType; private String deviceType;
@SerializedName("targetDevice")
@Expose
private String targetDevice; private String targetDevice;
@SerializedName("offUrl")
@Expose
private String offUrl; private String offUrl;
@SerializedName("dimUrl")
@Expose
private String dimUrl;
@SerializedName("onUrl")
@Expose
private String onUrl; private String onUrl;
@SerializedName("httpVerb")
@Expose
private String httpVerb; private String httpVerb;
@SerializedName("contentType")
@Expose
private String contentType; private String contentType;
@SerializedName("contentBody")
@Expose
private String contentBody; private String contentBody;
@SerializedName("contentBodyOff")
@Expose
private String contentBodyOff; private String contentBodyOff;
private boolean deviceState;
private int deviceSetValue;
public String getName() { public String getName() {
return name; return name;
} }
@@ -64,7 +98,15 @@ public class DeviceDescriptor{
this.offUrl = offUrl; this.offUrl = offUrl;
} }
public String getOnUrl() { public String getDimUrl() {
return dimUrl;
}
public void setDimUrl(String dimUrl) {
this.dimUrl = dimUrl;
}
public String getOnUrl() {
return onUrl; return onUrl;
} }
@@ -111,6 +153,22 @@ public class DeviceDescriptor{
public void setContentBodyOff(String contentBodyOff) { public void setContentBodyOff(String contentBodyOff) {
this.contentBodyOff = contentBodyOff; this.contentBodyOff = contentBodyOff;
} }
public boolean getDeviceState() {
return deviceState;
}
public void setDeviceState(boolean deviceState) {
this.deviceState = deviceState;
}
public int getDeviceSetValue() {
return deviceSetValue;
}
public void setDeviceSetValue(int deviceSetValue) {
this.deviceSetValue = deviceSetValue;
}
} }

View File

@@ -2,7 +2,6 @@ package com.bwssystems.HABridge.dao;
import java.io.IOException; import java.io.IOException;
import java.io.StringReader;
import java.nio.file.FileSystems; import java.nio.file.FileSystems;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
@@ -18,22 +17,27 @@ import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.dao.DeviceDescriptor; import com.bwssystems.HABridge.dao.DeviceDescriptor;
import com.bwssystems.util.BackupHandler; import com.bwssystems.util.BackupHandler;
import com.bwssystems.util.JsonTransformer; import com.bwssystems.util.JsonTransformer;
import com.google.gson.stream.JsonReader; import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.List; import java.util.List;
import java.util.ListIterator;
/* /*
* This is an in memory list to manage the configured devices and saves the list as a JSON string to a file for later * This is an in memory list to manage the configured devices and saves the list as a JSON string to a file for later
* loading. * loading.
*/ */
public class DeviceRepository extends BackupHandler { public class DeviceRepository extends BackupHandler {
Map<String, DeviceDescriptor> devices; private Map<String, DeviceDescriptor> devices;
Path repositoryPath; private Path repositoryPath;
final Random random = new Random(); private Gson gson;
final Logger log = LoggerFactory.getLogger(DeviceRepository.class); final private Random random = new Random();
private Logger log = LoggerFactory.getLogger(DeviceRepository.class);
public DeviceRepository(String deviceDb) { public DeviceRepository(String deviceDb) {
super(); super();
gson =
new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();
repositoryPath = null; repositoryPath = null;
repositoryPath = Paths.get(deviceDb); repositoryPath = Paths.get(deviceDb);
setupParams(repositoryPath, ".bk", "device.db-"); setupParams(repositoryPath, ".bk", "device.db-");
@@ -50,15 +54,11 @@ public class DeviceRepository extends BackupHandler {
if(jsonContent != null) if(jsonContent != null)
{ {
List<DeviceDescriptor> list = readJsonStream(jsonContent); DeviceDescriptor list[] = gson.fromJson(jsonContent, DeviceDescriptor[].class);
ListIterator<DeviceDescriptor> theIterator = list.listIterator(); for(int i = 0; i < list.length; i++) {
DeviceDescriptor theDevice = null; put(list[i].getId(), list[i]);
while (theIterator.hasNext()) {
theDevice = theIterator.next();
put(theDevice.getId(), theDevice);
} }
} }
} }
public List<DeviceDescriptor> findAll() { public List<DeviceDescriptor> findAll() {
@@ -82,15 +82,14 @@ public class DeviceRepository extends BackupHandler {
public void save(DeviceDescriptor[] descriptors) { public void save(DeviceDescriptor[] descriptors) {
String theNames = ""; String theNames = "";
for(int i = 0; i < descriptors.length; i++) { for(int i = 0; i < descriptors.length; i++) {
if(descriptors[i].getId() != null) if(descriptors[i].getId() != null && descriptors[i].getId().length() > 0)
devices.remove(descriptors[i].getId()); devices.remove(descriptors[i].getId());
else else
descriptors[i].setId(String.valueOf(random.nextInt(Integer.MAX_VALUE))); descriptors[i].setId(String.valueOf(random.nextInt(Integer.MAX_VALUE)));
put(descriptors[i].getId(), descriptors[i]); put(descriptors[i].getId(), descriptors[i]);
theNames = theNames + " " + descriptors[i].getName() + ", "; theNames = theNames + " " + descriptors[i].getName() + ", ";
} }
JsonTransformer aRenderer = new JsonTransformer(); String jsonValue = gson.toJson(findAll());
String jsonValue = aRenderer.render(findAll());
repositoryWriter(jsonValue, repositoryPath); repositoryWriter(jsonValue, repositoryPath);
log.debug("Save device(s): " + theNames); log.debug("Save device(s): " + theNames);
} }
@@ -153,82 +152,4 @@ public class DeviceRepository extends BackupHandler {
return content; return content;
} }
}
private List<DeviceDescriptor> readJsonStream(String context) {
JsonReader reader = new JsonReader(new StringReader(context));
List<DeviceDescriptor> theDescriptors = null;
try {
theDescriptors = readDescriptorArray(reader);
} catch (IOException e) {
log.error("Error reading json array: " + context + " message: " + e.getMessage(), e);
} finally {
try {
reader.close();
} catch (IOException e) {
log.error("Error closing json reader: " + context + " message: " + e.getMessage(), e);
}
}
return theDescriptors;
}
public List<DeviceDescriptor> readDescriptorArray(JsonReader reader) throws IOException {
List<DeviceDescriptor> descriptors = new ArrayList<DeviceDescriptor>();
reader.beginArray();
while (reader.hasNext()) {
descriptors.add(readDescriptor(reader));
}
reader.endArray();
return descriptors;
}
public DeviceDescriptor readDescriptor(JsonReader reader) throws IOException {
DeviceDescriptor deviceEntry = new DeviceDescriptor();
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
if (name.equals("id")) {
deviceEntry.setId(reader.nextString());
log.debug("Read a Device - device json id: " + deviceEntry.getId());
} else if (name.equals("name")) {
deviceEntry.setName(reader.nextString());
log.debug("Read a Device - device json name: " + deviceEntry.getName());
} else if (name.equals("mapType")) {
deviceEntry.setMapType(reader.nextString());
log.debug("Read a Device - device json name: " + deviceEntry.getMapType());
} else if (name.equals("mapId")) {
deviceEntry.setMapId(reader.nextString());
log.debug("Read a Device - device json name: " + deviceEntry.getMapId());
} else if (name.equals("deviceType")) {
deviceEntry.setDeviceType(reader.nextString());
log.debug("Read a Device - device json type:" + deviceEntry.getDeviceType());
} else if (name.equals("targetDevice")) {
deviceEntry.setTargetDevice(reader.nextString());
log.debug("Read a Device - device json type:" + deviceEntry.getTargetDevice());
} else if (name.equals("offUrl")) {
deviceEntry.setOffUrl(reader.nextString());
log.debug("Read a Device - device json off URL:" + deviceEntry.getOffUrl());
} else if (name.equals("onUrl")) {
deviceEntry.setOnUrl(reader.nextString());
log.debug("Read a Device - device json on URL:" + deviceEntry.getOnUrl());
} else if (name.equals("httpVerb")) {
deviceEntry.setHttpVerb(reader.nextString());
log.debug("Read a Device - device json httpVerb:" + deviceEntry.getHttpVerb());
} else if (name.equals("contentType")) {
deviceEntry.setContentType(reader.nextString());
log.debug("Read a Device - device json contentType:" + deviceEntry.getContentType());
} else if (name.equals("contentBody")) {
deviceEntry.setContentBody(reader.nextString());
log.debug("Read a Device - device json contentBody:" + deviceEntry.getContentBody());
} else if (name.equals("contentBodyOff")) {
deviceEntry.setContentBodyOff(reader.nextString());
log.debug("Read a Device - device json contentBodyOff:" + deviceEntry.getContentBodyOff());
} else {
reader.skipValue();
}
}
reader.endObject();
return deviceEntry;
}
}

View File

@@ -115,35 +115,24 @@ public class DeviceResource {
put (API_CONTEXT + "/:id", "application/json", (request, response) -> { put (API_CONTEXT + "/:id", "application/json", (request, response) -> {
log.debug("Edit a Device - request body: " + request.body()); log.debug("Edit a Device - request body: " + request.body());
DeviceDescriptor device = new Gson().fromJson(request.body(), DeviceDescriptor.class); DeviceDescriptor device = new Gson().fromJson(request.body(), DeviceDescriptor.class);
DeviceDescriptor deviceEntry = deviceRepository.findOne(request.params(":id")); if(deviceRepository.findOne(request.params(":id")) == null){
if(deviceEntry == null){ log.debug("Could not save an edited device, Device Id not found: " + request.params(":id"));
log.debug("Could not save an edited Device Id: " + request.params(":id"));
response.status(HttpStatus.SC_BAD_REQUEST); response.status(HttpStatus.SC_BAD_REQUEST);
return new ErrorMessage("Could not save an edited Device Id: " + request.params(":id") + " "); return new ErrorMessage("Could not save an edited device, Device Id not found: " + request.params(":id") + " ");
} }
else else
{ {
log.debug("Saving an edited Device: " + deviceEntry.getName()); log.debug("Saving an edited Device: " + device.getName());
deviceEntry.setName(device.getName());
if (device.getDeviceType() != null) if (device.getDeviceType() != null)
deviceEntry.setDeviceType(device.getDeviceType()); device.setDeviceType(device.getDeviceType());
deviceEntry.setMapId(device.getMapId());
deviceEntry.setMapType(device.getMapType());
deviceEntry.setTargetDevice(device.getTargetDevice());
deviceEntry.setOnUrl(device.getOnUrl());
deviceEntry.setOffUrl(device.getOffUrl());
deviceEntry.setHttpVerb(device.getHttpVerb());
deviceEntry.setContentType(device.getContentType());
deviceEntry.setContentBody(device.getContentBody());
deviceEntry.setContentBodyOff(device.getContentBodyOff());
DeviceDescriptor[] theDevices = new DeviceDescriptor[1]; DeviceDescriptor[] theDevices = new DeviceDescriptor[1];
theDevices[0] = deviceEntry; theDevices[0] = device;
deviceRepository.save(theDevices); deviceRepository.save(theDevices);
response.status(HttpStatus.SC_OK); response.status(HttpStatus.SC_OK);
} }
return deviceEntry; return device;
}, new JsonTransformer()); }, new JsonTransformer());
get (API_CONTEXT, "application/json", (request, response) -> { get (API_CONTEXT, "application/json", (request, response) -> {

View File

@@ -101,7 +101,7 @@ public class HueMulator {
List<DeviceDescriptor> deviceList = repository.findAll(); List<DeviceDescriptor> deviceList = repository.findAll();
Map<String, DeviceResponse> deviceResponseMap = new HashMap<>(); Map<String, DeviceResponse> deviceResponseMap = new HashMap<>();
for (DeviceDescriptor device : deviceList) { for (DeviceDescriptor device : deviceList) {
DeviceResponse deviceResponse = DeviceResponse.createResponse(device.getName(), device.getId()); DeviceResponse deviceResponse = DeviceResponse.createResponse(device);
deviceResponseMap.put(device.getId(), deviceResponse); deviceResponseMap.put(device.getId(), deviceResponse);
} }
response.type("application/json; charset=utf-8"); response.type("application/json; charset=utf-8");
@@ -225,7 +225,7 @@ public class HueMulator {
Map<String, DeviceResponse> deviceList = new HashMap<>(); Map<String, DeviceResponse> deviceList = new HashMap<>();
descriptorList.forEach(descriptor -> { descriptorList.forEach(descriptor -> {
DeviceResponse deviceResponse = DeviceResponse.createResponse(descriptor.getName(), descriptor.getId()); DeviceResponse deviceResponse = DeviceResponse.createResponse(descriptor);
deviceList.put(descriptor.getId(), deviceResponse); deviceList.put(descriptor.getId(), deviceResponse);
} }
); );
@@ -249,13 +249,68 @@ public class HueMulator {
} else { } else {
log.debug("found device named: " + device.getName()); log.debug("found device named: " + device.getName());
} }
DeviceResponse lightResponse = DeviceResponse.createResponse(device.getName(), device.getId()); DeviceResponse lightResponse = DeviceResponse.createResponse(device);
response.type("application/json; charset=utf-8"); response.type("application/json; charset=utf-8");
response.status(HttpStatus.SC_OK); response.status(HttpStatus.SC_OK);
return lightResponse; return lightResponse;
}, new JsonTransformer()); }, new JsonTransformer());
// http://ip_address:port/api/:userid/lights/:id/bridgeupdatestate CORS request
options(HUE_CONTEXT + "/:userid/lights/:id/bridgeupdatestate", "application/json", (request, response) -> {
response.status(HttpStatus.SC_OK);
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
response.header("Access-Control-Allow-Methods", "GET, POST, PUT");
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
response.header("Content-Type", "text/html; charset=utf-8");
return "";
});
// http://ip_address:port/api/{userId}/lights/{lightId}/bridgeupdatestate uses json object to update the internal bridge lights state.
// THIS IS NOT A HUE API CALL... It is for state management if so desired.
put(HUE_CONTEXT + "/:userid/lights/:id/bridgeupdatestate", "application/json", (request, response) -> {
String userId = request.params(":userid");
String lightId = request.params(":id");
String responseString = null;
DeviceState state = null;
log.debug("Update state requested: " + userId + " from " + request.ip() + " body: " + request.body());
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
response.type("application/json; charset=utf-8");
response.status(HttpStatus.SC_OK);
try {
state = mapper.readValue(request.body(), DeviceState.class);
} catch (IOException e) {
log.warn("Object mapper barfed on input of body.", e);
responseString = "[{\"error\":{\"type\": 2, \"address\": \"/lights/" + lightId + "\",\"description\": \"Object mapper barfed on input of body.\"}}]";
return responseString;
}
DeviceDescriptor device = repository.findOne(lightId);
if (device == null) {
log.warn("Could not find device: " + lightId + " for hue state change request: " + userId + " from " + request.ip() + " body: " + request.body());
responseString = "[{\"error\":{\"type\": 3, \"address\": \"/lights/" + lightId + "\",\"description\": \"Could not find device\", \"resource\": \"/lights/" + lightId + "\"}}]";
return responseString;
}
responseString = "[{\"success\":{\"/lights/" + lightId + "/state/on\":";
if(request.body().contains("bri"))
{
responseString = responseString + "true}},{\"success\":{\"/lights/" + lightId + "/state/bri\":" + state.getBri() + "}}]";
}
else
{
if (state.isOn()) {
responseString = responseString + "true}}]";
state.setBri(255);
} else if (request.body().contains("false")) {
responseString = responseString + "false}}]";
state.setBri(0);
}
}
device.setDeviceSetValue(state.getBri());
device.setDeviceState(state.isOn());
return responseString;
});
// http://ip_address:port/api/:userid/lights/:id/state CORS request // http://ip_address:port/api/:userid/lights/:id/state CORS request
options(HUE_CONTEXT + "/:userid/lights/:id/state", "application/json", (request, response) -> { options(HUE_CONTEXT + "/:userid/lights/:id/state", "application/json", (request, response) -> {
response.status(HttpStatus.SC_OK); response.status(HttpStatus.SC_OK);
@@ -296,28 +351,34 @@ public class HueMulator {
return responseString; return responseString;
} }
if (state.isOn()) { responseString = "[{\"success\":{\"/lights/" + lightId + "/state/on\":";
responseString = "[{\"success\":{\"/lights/" + lightId + "/state/on\":true}}";
url = device.getOnUrl();
} else if (request.body().contains("false")) {
responseString = "[{\"success\":{\"/lights/" + lightId + "/state/on\":false}}";
url = device.getOffUrl();
}
if(request.body().contains("bri")) if(request.body().contains("bri"))
{ {
if(url == null) url = device.getDimUrl();
{
url = device.getOnUrl();
responseString = "[";
}
else
responseString = responseString + ",";
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/bri\":" + state.getBri() + "}}]"; if(url == null || url.length() == 0)
url = device.getOnUrl();
responseString = responseString + "true}},{\"success\":{\"/lights/" + lightId + "/state/bri\":" + state.getBri() + "}}]";
} }
else else
responseString = responseString + "]"; {
if (state.isOn()) {
responseString = responseString + "true}}]";
url = device.getOnUrl();
state.setBri(255);
} else if (request.body().contains("false")) {
responseString = responseString + "false}}]";
url = device.getOffUrl();
state.setBri(0);
}
}
if (url == null) {
log.warn("Could not find url: " + lightId + " for hue state change request: " + userId + " from " + request.ip() + " body: " + request.body());
responseString = "[{\"error\":{\"type\": 3, \"address\": \"/lights/" + lightId + "\",\"description\": \"Could not find url\", \"resource\": \"/lights/" + lightId + "\"}}]";
return responseString;
}
if(device.getDeviceType().toLowerCase().contains("activity") || (device.getMapType() != null && device.getMapType().equalsIgnoreCase("harmonyActivity"))) if(device.getDeviceType().toLowerCase().contains("activity") || (device.getMapType() != null && device.getMapType().equalsIgnoreCase("harmonyActivity")))
{ {
@@ -337,7 +398,6 @@ public class HueMulator {
else { else {
log.warn("Should not get here, no harmony configured"); log.warn("Should not get here, no harmony configured");
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + "\",\"description\": \"Should not get here, no harmony configured\", \"parameter\": \"/lights/" + lightId + "state\"}}]"; responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + "\",\"description\": \"Should not get here, no harmony configured\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
} }
} }
else if(device.getDeviceType().toLowerCase().contains("button") || (device.getMapType() != null && device.getMapType().equalsIgnoreCase("harmonyButton"))) else if(device.getDeviceType().toLowerCase().contains("button") || (device.getMapType() != null && device.getMapType().equalsIgnoreCase("harmonyButton")))
@@ -395,7 +455,10 @@ public class HueMulator {
NestInstruction thermoSetting = new Gson().fromJson(url, NestInstruction.class); NestInstruction thermoSetting = new Gson().fromJson(url, NestInstruction.class);
if(thermoSetting.getControl().equalsIgnoreCase("temp")) { if(thermoSetting.getControl().equalsIgnoreCase("temp")) {
if(request.body().contains("bri")) { if(request.body().contains("bri")) {
thermoSetting.setTemp(String.valueOf((Double.parseDouble(replaceIntensityValue(thermoSetting.getTemp(), state.getBri())) - 32.0)/1.8)); if(bridgeSettings.isFarenheit())
thermoSetting.setTemp(String.valueOf((Double.parseDouble(replaceIntensityValue(thermoSetting.getTemp(), state.getBri())) - 32.0)/1.8));
else
thermoSetting.setTemp(String.valueOf(Double.parseDouble(replaceIntensityValue(thermoSetting.getTemp(), state.getBri()))));
log.debug("Setting thermostat: " + thermoSetting.getName() + " to " + thermoSetting.getTemp() + "C"); log.debug("Setting thermostat: " + thermoSetting.getName() + " to " + thermoSetting.getTemp() + "C");
theNest.getThermostat(thermoSetting.getName()).setTargetTemperature(Float.parseFloat(thermoSetting.getTemp())); theNest.getThermostat(thermoSetting.getName()).setTargetTemperature(Float.parseFloat(thermoSetting.getTemp()));
} }
@@ -453,7 +516,11 @@ public class HueMulator {
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + "\",\"description\": \"Error on calling url to change device state\", \"parameter\": \"/lights/" + lightId + "state\"}}]"; responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + "\",\"description\": \"Error on calling url to change device state\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
} }
} }
if(!responseString.contains("[{\"error\":")) {
device.setDeviceSetValue(state.getBri());
device.setDeviceState(state.isOn());
}
return responseString; return responseString;
}); });
} }

View File

@@ -1,5 +1,7 @@
package com.bwssystems.NestBridge; package com.bwssystems.NestBridge;
import java.io.UnsupportedEncodingException;
public class NestItem { public class NestItem {
private String name; private String name;
private String id; private String id;
@@ -9,7 +11,14 @@ public class NestItem {
return name; return name;
} }
public void setName(String name) { public void setName(String name) {
this.name = name; byte ptext[];
String theLabel = new String(name);
try {
ptext = theLabel.getBytes("ISO-8859-1");
this.name = new String(ptext, "UTF-8");
} catch (UnsupportedEncodingException e) {
this.name = theLabel;
}
} }
public String getId() { public String getId() {
return id; return id;

View File

@@ -1,5 +1,7 @@
package com.bwssystems.harmony; package com.bwssystems.harmony;
import java.io.UnsupportedEncodingException;
import net.whistlingfish.harmony.config.Activity; import net.whistlingfish.harmony.config.Activity;
public class HarmonyActivity { public class HarmonyActivity {
@@ -15,6 +17,14 @@ public class HarmonyActivity {
return activity; return activity;
} }
public void setActivity(Activity activity) { public void setActivity(Activity activity) {
byte ptext[];
String theLabel = activity.getLabel();
try {
ptext = theLabel.getBytes("ISO-8859-1");
activity.setLabel(new String(ptext, "UTF-8"));
} catch (UnsupportedEncodingException e) {
activity.setLabel(theLabel);
}
this.activity = activity; this.activity = activity;
} }

View File

@@ -1,5 +1,7 @@
package com.bwssystems.harmony; package com.bwssystems.harmony;
import java.io.UnsupportedEncodingException;
import net.whistlingfish.harmony.config.Device; import net.whistlingfish.harmony.config.Device;
public class HarmonyDevice { public class HarmonyDevice {
@@ -9,6 +11,14 @@ public class HarmonyDevice {
return device; return device;
} }
public void setDevice(Device device) { public void setDevice(Device device) {
byte ptext[];
String theLabel = device.getLabel();
try {
ptext = theLabel.getBytes("ISO-8859-1");
device.setLabel(new String(ptext, "UTF-8"));
} catch (UnsupportedEncodingException e) {
device.setLabel(theLabel);
}
this.device = device; this.device = device;
} }
public String getHub() { public String getHub() {

View File

@@ -1,6 +1,7 @@
package com.bwssystems.vera; package com.bwssystems.vera;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap; import java.util.HashMap;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Map; import java.util.Map;
@@ -101,7 +102,7 @@ public class VeraInfo {
HttpResponse response = httpClient.execute(httpGet); HttpResponse response = httpClient.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()); //read content for data theContent = EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8")); //read content for data
EntityUtils.consume(response.getEntity()); //close out inputstream ignore content EntityUtils.consume(response.getEntity()); //close out inputstream ignore content
} }
} catch (IOException e) { } catch (IOException e) {

View File

@@ -47,27 +47,25 @@ app.service('bridgeService', function ($http, $window, ngToast) {
this.state = {base: window.location.origin + "/api/devices", bridgelocation: window.location.origin, systemsbase: window.location.origin + "/system", huebase: window.location.origin + "/api", configs: [], backups: [], devices: [], device: [], type: "", settings: [], myToastMsg: [], logMsgs: [], loggerInfo: [], olddevicename: "", logShowAll: false, isInControl: false, showVera: false, showHarmony: false, showNest: false, habridgeversion: ""}; this.state = {base: window.location.origin + "/api/devices", bridgelocation: window.location.origin, systemsbase: window.location.origin + "/system", huebase: window.location.origin + "/api", configs: [], backups: [], devices: [], device: [], type: "", settings: [], myToastMsg: [], logMsgs: [], loggerInfo: [], olddevicename: "", logShowAll: false, isInControl: false, showVera: false, showHarmony: false, showNest: false, habridgeversion: ""};
this.displayWarn = function(errorTitle, error) { this.displayWarn = function(errorTitle, error) {
if(error == null || typeof(error) != 'undefined') { var toastContent = errorTitle;
error = {status: 200, statusText: "OK", data: []}; if(error != null && typeof(error) != 'undefined')
error.data = {message: "success"}; toastContent = toastContent + " " + error.data.message + " with status: " + error.statusText + " - " + error.status;
}
ngToast.create({ ngToast.create({
className: "warning", className: "warning",
dismissButton: true, dismissButton: true,
dismissOnTimeout: false, dismissOnTimeout: false,
content: errorTitle + error.data.message + " with status: " + error.statusText + " - " + error.status}); content: toastContent});
}; };
this.displayError = function(errorTitle, error) { this.displayError = function(errorTitle, error) {
if(error == null || typeof(error) != 'undefined') { var toastContent = errorTitle;
error = {status: 200, statusText: "OK", data: []}; if(error != null && typeof(error) != 'undefined')
error.data = {message: "success"}; toastContent = toastContent + " " + error.data.message + " with status: " + error.statusText + " - " + error.status;
}
ngToast.create({ ngToast.create({
className: "danger", className: "danger",
dismissButton: true, dismissButton: true,
dismissOnTimeout: false, dismissOnTimeout: false,
content: errorTitle + error.data.message + " with status: " + error.statusText + " - " + error.status}); content: toastContent});
}; };
this.displayErrorMessage = function(errorTitle, errorMessage) { this.displayErrorMessage = function(errorTitle, errorMessage) {
@@ -101,6 +99,7 @@ app.service('bridgeService', function ($http, $window, ngToast) {
self.state.device.mapId = null; self.state.device.mapId = null;
self.state.device.name = ""; self.state.device.name = "";
self.state.device.onUrl = ""; self.state.device.onUrl = "";
self.state.device.dimUrl = "";
self.state.device.deviceType = "custom"; self.state.device.deviceType = "custom";
self.state.device.targetDevice = null; self.state.device.targetDevice = null;
self.state.device.offUrl = ""; self.state.device.offUrl = "";
@@ -108,7 +107,7 @@ app.service('bridgeService', function ($http, $window, ngToast) {
self.state.device.contentType = null; self.state.device.contentType = null;
self.state.device.contentBody = null; self.state.device.contentBody = null;
self.state.device.contentBodyOff = null; self.state.device.contentBodyOff = null;
self.state.bridge.olddevicename = ""; self.state.olddevicename = "";
}; };
this.getHABridgeVersion = function () { this.getHABridgeVersion = function () {
@@ -303,27 +302,16 @@ app.service('bridgeService', function ($http, $window, ngToast) {
); );
}; };
this.addDevice = function (device) { this.addDevice = function (aDevice) {
var device = {};
angular.extend(device, aDevice );
if(device.httpVerb != null && device.httpVerb != "") if(device.httpVerb != null && device.httpVerb != "")
device.deviceType = "custom"; device.deviceType = "custom";
if(device.targetDevice == null || device.targetDevice == "") if(device.targetDevice == null || device.targetDevice == "")
device.targetDevice = "Encapsulated"; device.targetDevice = "Encapsulated";
if (device.id) { if (device.id) {
var putUrl = this.state.base + "/" + device.id; var putUrl = this.state.base + "/" + device.id;
return $http.put(putUrl, { return $http.put(putUrl, device).then(
id: device.id,
name: device.name,
mapId: device.mapId,
mapType: device.mapType,
deviceType: device.deviceType,
targetDevice: device.targetDevice,
onUrl: device.onUrl,
offUrl: device.offUrl,
httpVerb: device.httpVerb,
contentType: device.contentType,
contentBody: device.contentBody,
contentBodyOff: device.contentBodyOff
}).then(
function (response) { function (response) {
}, },
function (error) { function (error) {
@@ -333,19 +321,7 @@ app.service('bridgeService', function ($http, $window, ngToast) {
} else { } else {
if(device.deviceType == null || device.deviceType == "") if(device.deviceType == null || device.deviceType == "")
device.deviceType = "custom"; device.deviceType = "custom";
return $http.post(this.state.base, { return $http.post(this.state.base, device).then(
name: device.name,
mapId: device.mapId,
mapType: device.mapType,
deviceType: device.deviceType,
targetDevice: device.targetDevice,
onUrl: device.onUrl,
offUrl: device.offUrl,
httpVerb: device.httpVerb,
contentType: device.contentType,
contentBody: device.contentBody,
contentBodyOff: device.contentBodyOff
}).then(
function (response) { function (response) {
}, },
function (error) { function (error) {
@@ -474,6 +450,7 @@ app.service('bridgeService', function ($http, $window, ngToast) {
filename: afilename filename: afilename
}).then( }).then(
function (response) { function (response) {
self.state.settings = response.data;
self.viewConfigs(); self.viewConfigs();
self.viewDevices(); self.viewDevices();
}, },
@@ -523,11 +500,11 @@ app.service('bridgeService', function ($http, $window, ngToast) {
var msgDescription = "unknown"; var msgDescription = "unknown";
var testUrl = this.state.huebase + "/test/lights/" + device.id + "/state"; var testUrl = this.state.huebase + "/test/lights/" + device.id + "/state";
var testBody = "{\"on\":"; var testBody = "{\"on\":";
if(type == "on") { if(type == "off") {
testBody = testBody + "true"; testBody = testBody + "false";
} }
else { else {
testBody = testBody + "false"; testBody = testBody + "true";
} }
if(value) { if(value) {
testBody = testBody + ",\"bri\":" + value; testBody = testBody + ",\"bri\":" + value;
@@ -683,12 +660,15 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
$scope.imgBkUrl = "glyphicon glyphicon-plus"; $scope.imgBkUrl = "glyphicon glyphicon-plus";
$scope.testUrl = function (device, type) { $scope.testUrl = function (device, type) {
var dialogNeeded = false; var dialogNeeded = false;
if((type == "on" && (bridgeService.aContainsB(device.onUrl, "${intensity..byte}") || if((type == "on" && (bridgeService.aContainsB(device.onUrl, "${intensity.byte}") ||
bridgeService.aContainsB(device.onUrl, "${intensity.percent}") || bridgeService.aContainsB(device.onUrl, "${intensity.percent}") ||
bridgeService.aContainsB(device.onUrl, "${intensity.math("))) || bridgeService.aContainsB(device.onUrl, "${intensity.math("))) ||
(type == "off" && (bridgeService.aContainsB(device.offUrl, "${intensity..byte}") || (type == "off" && (bridgeService.aContainsB(device.offUrl, "${intensity.byte}") ||
bridgeService.aContainsB(device.offUrl, "${intensity.percent}") || bridgeService.aContainsB(device.offUrl, "${intensity.percent}") ||
bridgeService.aContainsB(device.offUrl, "${intensity.math(")))) { bridgeService.aContainsB(device.offUrl, "${intensity.math("))) ||
(type == "dim" && (bridgeService.aContainsB(device.dimUrl, "${intensity.byte}") ||
bridgeService.aContainsB(device.dimUrl, "${intensity.percent}") ||
bridgeService.aContainsB(device.dimUrl, "${intensity.math(")))) {
$scope.bridge.device = device; $scope.bridge.device = device;
$scope.bridge.type = type; $scope.bridge.type = type;
ngDialog.open({ ngDialog.open({
@@ -786,27 +766,32 @@ app.controller('VeraController', function ($scope, $location, $http, bridgeServi
}; };
$scope.buildDeviceUrls = function (veradevice, dim_control) { $scope.buildDeviceUrls = function (veradevice, dim_control) {
bridgeService.clearDevice();
$scope.device.deviceType = "switch"; $scope.device.deviceType = "switch";
$scope.device.name = veradevice.name; $scope.device.name = veradevice.name;
$scope.device.targetDevice = veradevice.veraname; $scope.device.targetDevice = veradevice.veraname;
$scope.device.mapType = "veraDevice"; $scope.device.mapType = "veraDevice";
$scope.device.mapId = veradevice.id; $scope.device.mapId = veradevice.id;
if(dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0) if(dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0)
$scope.device.onUrl = "http://" + veradevice.veraaddress + ":" + $scope.vera.port $scope.device.dimUrl = "http://" + veradevice.veraaddress + ":" + $scope.vera.port
+ "/data_request?id=action&output_format=json&DeviceNum=" + "/data_request?id=action&output_format=json&DeviceNum="
+ veradevice.id + veradevice.id
+ "&serviceId=urn:upnp-org:serviceId:Dimming1&action=SetLoadLevelTarget&newLoadlevelTarget=" + "&serviceId=urn:upnp-org:serviceId:Dimming1&action=SetLoadLevelTarget&newLoadlevelTarget="
+ dim_control; + dim_control;
else else
$scope.device.onUrl = "http://" + veradevice.veraaddress + ":" + $scope.vera.port $scope.device.dimUrl = "http://" + veradevice.veraaddress + ":" + $scope.vera.port
+ "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1&DeviceNum=" + "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1&DeviceNum="
+ veradevice.id; + veradevice.id;
$scope.device.onUrl = "http://" + veradevice.veraaddress + ":" + $scope.vera.port
+ "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1&DeviceNum="
+ veradevice.id;
$scope.device.offUrl = "http://" + veradevice.veraaddress + ":" + $scope.vera.port $scope.device.offUrl = "http://" + veradevice.veraaddress + ":" + $scope.vera.port
+ "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=0&DeviceNum=" + "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=0&DeviceNum="
+ veradevice.id; + veradevice.id;
}; };
$scope.buildSceneUrls = function (verascene) { $scope.buildSceneUrls = function (verascene) {
bridgeService.clearDevice();
$scope.device.deviceType = "scene"; $scope.device.deviceType = "scene";
$scope.device.name = verascene.name; $scope.device.name = verascene.name;
$scope.device.targetDevice = verascene.veraname; $scope.device.targetDevice = verascene.veraname;
@@ -831,6 +816,7 @@ app.controller('VeraController', function ($scope, $location, $http, bridgeServi
bridgeService.viewVeraScenes(); bridgeService.viewVeraScenes();
}, },
function (error) { function (error) {
bridgeService.displayWarn("Error adding device: " + $scope.device.name, error)
} }
); );
@@ -910,6 +896,7 @@ app.controller('HarmonyController', function ($scope, $location, $http, bridgeSe
}; };
$scope.buildActivityUrls = function (harmonyactivity) { $scope.buildActivityUrls = function (harmonyactivity) {
bridgeService.clearDevice();
$scope.device.deviceType = "activity"; $scope.device.deviceType = "activity";
$scope.device.targetDevice = harmonyactivity.hub; $scope.device.targetDevice = harmonyactivity.hub;
$scope.device.name = harmonyactivity.activity.label; $scope.device.name = harmonyactivity.activity.label;
@@ -920,6 +907,7 @@ app.controller('HarmonyController', function ($scope, $location, $http, bridgeSe
}; };
$scope.buildButtonUrls = function (harmonydevice, onbutton, offbutton) { $scope.buildButtonUrls = function (harmonydevice, onbutton, offbutton) {
bridgeService.clearDevice();
var currentOn = $scope.device.onUrl; var currentOn = $scope.device.onUrl;
var currentOff = $scope.device.offUrl; var currentOff = $scope.device.offUrl;
var actionOn = angular.fromJson(onbutton); var actionOn = angular.fromJson(onbutton);
@@ -984,6 +972,7 @@ app.controller('NestController', function ($scope, $location, $http, bridgeServi
}; };
$scope.buildNestHomeUrls = function (nestitem) { $scope.buildNestHomeUrls = function (nestitem) {
bridgeService.clearDevice();
$scope.device.deviceType = "home"; $scope.device.deviceType = "home";
$scope.device.name = nestitem.name; $scope.device.name = nestitem.name;
$scope.device.targetDevice = nestitem.name; $scope.device.targetDevice = nestitem.name;
@@ -994,16 +983,18 @@ app.controller('NestController', function ($scope, $location, $http, bridgeServi
}; };
$scope.buildNestTempUrls = function (nestitem) { $scope.buildNestTempUrls = function (nestitem) {
bridgeService.clearDevice();
$scope.device.deviceType = "thermo"; $scope.device.deviceType = "thermo";
$scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Temperature"; $scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Temperature";
$scope.device.targetDevice = nestitem.location; $scope.device.targetDevice = nestitem.location;
$scope.device.mapType = "nestThermoSet"; $scope.device.mapType = "nestThermoSet";
$scope.device.mapId = nestitem.id + "-SetTemp"; $scope.device.mapId = nestitem.id + "-SetTemp";
$scope.device.onUrl = "{\"name\":\"" + nestitem.id + "\",\"control\":\"temp\",\"temp\":\"${intensity.percent}\"}"; $scope.device.dimUrl = "{\"name\":\"" + nestitem.id + "\",\"control\":\"temp\",\"temp\":\"${intensity.percent}\"}";
$scope.device.offUrl = "{\"name\":\"" + nestitem.id + "\",\"control\":\"temp\",\"temp\":\"${intensity.percent}\"}"; $scope.device.offUrl = "{\"name\":\"" + nestitem.id + "\",\"control\":\"off\"}";
}; };
$scope.buildNestHeatUrls = function (nestitem) { $scope.buildNestHeatUrls = function (nestitem) {
bridgeService.clearDevice();
$scope.device.deviceType = "thermo"; $scope.device.deviceType = "thermo";
$scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Heat"; $scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Heat";
$scope.device.targetDevice = nestitem.location; $scope.device.targetDevice = nestitem.location;
@@ -1014,6 +1005,7 @@ app.controller('NestController', function ($scope, $location, $http, bridgeServi
}; };
$scope.buildNestCoolUrls = function (nestitem) { $scope.buildNestCoolUrls = function (nestitem) {
bridgeService.clearDevice();
$scope.device.deviceType = "thermo"; $scope.device.deviceType = "thermo";
$scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Cool"; $scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Cool";
$scope.device.targetDevice = nestitem.location; $scope.device.targetDevice = nestitem.location;
@@ -1024,6 +1016,7 @@ app.controller('NestController', function ($scope, $location, $http, bridgeServi
}; };
$scope.buildNestRangeUrls = function (nestitem) { $scope.buildNestRangeUrls = function (nestitem) {
bridgeService.clearDevice();
$scope.device.deviceType = "thermo"; $scope.device.deviceType = "thermo";
$scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Range"; $scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Range";
$scope.device.targetDevice = nestitem.location; $scope.device.targetDevice = nestitem.location;
@@ -1034,6 +1027,7 @@ app.controller('NestController', function ($scope, $location, $http, bridgeServi
}; };
$scope.buildNestOffUrls = function (nestitem) { $scope.buildNestOffUrls = function (nestitem) {
bridgeService.clearDevice();
$scope.device.deviceType = "thermo"; $scope.device.deviceType = "thermo";
$scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Thermostat"; $scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Thermostat";
$scope.device.targetDevice = nestitem.location; $scope.device.targetDevice = nestitem.location;
@@ -1044,6 +1038,7 @@ app.controller('NestController', function ($scope, $location, $http, bridgeServi
}; };
$scope.buildNestFanUrls = function (nestitem) { $scope.buildNestFanUrls = function (nestitem) {
bridgeService.clearDevice();
$scope.device.deviceType = "thermo"; $scope.device.deviceType = "thermo";
$scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Fan"; $scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Fan";
$scope.device.targetDevice = nestitem.location; $scope.device.targetDevice = nestitem.location;
@@ -1090,7 +1085,7 @@ app.controller('EditController', function ($scope, $location, $http, bridgeServi
$scope.device_dim_control = ""; $scope.device_dim_control = "";
$scope.bulk = { devices: [] }; $scope.bulk = { devices: [] };
var veraList = angular.fromJson($scope.bridge.settings.veraaddress); var veraList = angular.fromJson($scope.bridge.settings.veraaddress);
if(veraList != null) if(veraList != null && veraList.devices.length > 0)
$scope.vera = {base: "http://" + veraList.devices[0].ip, port: "3480", id: ""}; $scope.vera = {base: "http://" + veraList.devices[0].ip, port: "3480", id: ""};
else else
$scope.vera = {base: "http://", port: "3480", id: ""}; $scope.vera = {base: "http://", port: "3480", id: ""};
@@ -1102,32 +1097,31 @@ app.controller('EditController', function ($scope, $location, $http, bridgeServi
}; };
$scope.buildUrlsUsingDevice = function (dim_control) { $scope.buildUrlsUsingDevice = function (dim_control) {
if ($scope.vera.base.indexOf("http") < 0) { bridgeService.clearDevice();
$scope.vera.base = "http://" + $scope.vera.base;
}
$scope.device.deviceType = "switch"; $scope.device.deviceType = "switch";
$scope.device.targetDevice = "Encapsulated"; $scope.device.targetDevice = "Encapsulated";
$scope.device.mapType = "veraDevice"; $scope.device.mapType = "veraDevice";
$scope.device.mapId = $scope.vera.id; $scope.device.mapId = $scope.vera.id;
if(dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0) if(dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0)
$scope.device.onUrl = $scope.vera.base + ":" + $scope.vera.port $scope.device.dimUrl = $scope.vera.base + ":" + $scope.vera.port
+ "/data_request?id=action&output_format=json&DeviceNum=" + "/data_request?id=action&output_format=json&DeviceNum="
+ $scope.vera.id + $scope.vera.id
+ "&serviceId=urn:upnp-org:serviceId:Dimming1&action=SetLoadLevelTarget&newLoadlevelTarget=" + "&serviceId=urn:upnp-org:serviceId:Dimming1&action=SetLoadLevelTarget&newLoadlevelTarget="
+ dim_control; + dim_control;
else else
$scope.device.onUrl = $scope.vera.base + ":" + $scope.vera.port $scope.device.dimUrl = $scope.vera.base + ":" + $scope.vera.port
+ "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1&DeviceNum=" + "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1&DeviceNum="
+ $scope.vera.id; + $scope.vera.id;
$scope.device.onUrl = $scope.vera.base + ":" + $scope.vera.port
+ "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1&DeviceNum="
+ $scope.vera.id;
$scope.device.offUrl = $scope.vera.base + ":" + $scope.vera.port $scope.device.offUrl = $scope.vera.base + ":" + $scope.vera.port
+ "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=0&DeviceNum=" + "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=0&DeviceNum="
+ $scope.vera.id; + $scope.vera.id;
}; };
$scope.buildUrlsUsingScene = function () { $scope.buildUrlsUsingScene = function () {
if ($scope.vera.base.indexOf("http") < 0) { bridgeService.clearDevice();
$scope.vera.base = "http://" + $scope.vera.base;
}
$scope.device.deviceType = "scene"; $scope.device.deviceType = "scene";
$scope.device.targetDevice = "Encapsulated"; $scope.device.targetDevice = "Encapsulated";
$scope.device.mapType = "veraScene"; $scope.device.mapType = "veraScene";

View File

@@ -36,6 +36,8 @@
<p> <p>
<button class="btn btn-info" type="submit" <button class="btn btn-info" type="submit"
ng-click="testUrl(device, 'on')">Test ON</button> ng-click="testUrl(device, 'on')">Test ON</button>
<button class="btn btn-info" type="submit"
ng-click="testUrl(device, 'dim')">Test Dim</button>
<button class="btn btn-info" type="submit" <button class="btn btn-info" type="submit"
ng-click="testUrl(device, 'off')">Test OFF</button> ng-click="testUrl(device, 'off')">Test OFF</button>
<button class="btn btn-warning" type="submit" <button class="btn btn-warning" type="submit"

View File

@@ -83,6 +83,17 @@
</div> </div>
</div> </div>
</div> </div>
<div class="form-group">
<div class="row">
<label class="col-xs-12 col-sm-2 control-label" for="device-dim-url">Dim
URL </label>
<div class="col-xs-8 col-sm-7">
<textarea rows="3" class="form-control" id="device-dim-url"
ng-model="device.dimUrl" placeholder="URL to dim device"></textarea>
</div>
</div>
</div>
<div class="form-group"> <div class="form-group">
<div class="row"> <div class="row">
<label class="col-xs-12 col-sm-2 control-label" <label class="col-xs-12 col-sm-2 control-label"

View File

@@ -107,6 +107,17 @@
Clear Device</button> Clear Device</button>
</div> </div>
</div> </div>
<div class="form-group">
<div class="row">
<label class="col-xs-12 col-sm-2 control-label" for="device-dim-url">Dim
URL </label>
<div class="col-xs-8 col-sm-7">
<textarea rows="3" class="form-control" id="device-dim-url"
ng-model="device.dimUrl" placeholder="URL to dim device"></textarea>
</div>
</div>
</div>
<div class="form-group"> <div class="form-group">
<div class="row"> <div class="row">
<label class="col-xs-12 col-sm-2 control-label" <label class="col-xs-12 col-sm-2 control-label"

View File

@@ -173,6 +173,11 @@
<td><input type="checkbox" ng-model="bridge.settings.traceupnp" <td><input type="checkbox" ng-model="bridge.settings.traceupnp"
ng-true-value=true ng-false-value=false> {{bridge.settings.traceupnp}}</td> ng-true-value=true ng-false-value=false> {{bridge.settings.traceupnp}}</td>
</tr> </tr>
<tr>
<td>Nest Temp Farenheit</td>
<td><input type="checkbox" ng-model="bridge.settings.farenheit"
ng-true-value=true ng-false-value=false> {{bridge.settings.farenheit}}</td>
</tr>
</table> </table>
</form> </form>
</div> </div>

View File

@@ -130,6 +130,17 @@
<button class="btn btn-danger" ng-click="clearDevice()"> <button class="btn btn-danger" ng-click="clearDevice()">
Clear Device</button> Clear Device</button>
</div> </div>
<div class="form-group">
<div class="row">
<label class="col-xs-12 col-sm-2 control-label" for="device-dim-url">Dim
URL </label>
<div class="col-xs-8 col-sm-7">
<textarea rows="3" class="form-control" id="device-dim-url"
ng-model="device.dimUrl" placeholder="URL to dim device"></textarea>
</div>
</div>
</div>
<div class="form-group"> <div class="form-group">
<div class="row"> <div class="row">
<label class="col-xs-12 col-sm-2 control-label" <label class="col-xs-12 col-sm-2 control-label"