Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added configuration for OpenHAB #92

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ buildNumber.properties
*.iml
data
.idea
config/
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,24 @@ You can now control devices with your Amazon Echo by saying "Alexa, Turn on the

To view or remove devices that Alexa knows about, you can use the mobile app Menu / Settings / Connected Home, This is needed if you remove a device from the Amazon Echo Bridge.

## Running as a service

If you are running this on Linux with `systemd`, do the following:
1. Modify `echo-ha-bridge.service` by changing the name of the jar file to execute and location of the working directory
2. Copy `echo-ha-bridge.service` to `/lib/systemd/system/`
3. Run `sudo systemctl enable echo-ha-bridge.service`
4. Navigate to the location of `amazon-ha-bridge-*.jar` and create a file called `application.properties` with the following content:
```
upnp.response.port=50000
upnp.config.address=ip address of your machine
emulator.portbase=should be same as server.port
emulator.portcount=3
upnp.disable=false
server.port=port number you want the server to be listening on
logging.file=full path to the file where logs will be written to
```


## Build

In case you would like to internally configure your own build of the Amazon Echo Bridge, a few requisites are required.
Expand Down
13 changes: 13 additions & 0 deletions echo-ha-bridge.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[Unit]
Description=Amazon Echo HA Bridge
After=syslog.target

[Service]
Type=simple
PIDFile=/var/run/echo-ha-bridge/echo-ha-bridge.pid
WorkingDirectory=/opt/echo-ha-bridge/
ExecStart=/usr/bin/java -jar amazon-echo-bridge.jar & > /dev/null
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>com.armzilla.ha</groupId>
<artifactId>amazon-echo-bridge</artifactId>
<version>0.4.0</version>
<version>0.4.1</version>
<packaging>jar</packaging>

<name>Amazon Echo Bridge</name>
Expand Down
7 changes: 0 additions & 7 deletions src/main/java/com/armzilla/ha/SpringbootEntry.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
package com.armzilla.ha;

import org.apache.catalina.connector.Connector;
import org.apache.coyote.http11.Http11NioProtocol;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;

import java.io.IOException;

@SpringBootApplication
@EnableScheduling
Expand Down
6 changes: 0 additions & 6 deletions src/main/java/com/armzilla/ha/TomcatConnectorBean.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
package com.armzilla.ha;

import org.apache.catalina.connector.Connector;
import org.apache.coyote.http11.Http11NioProtocol;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
* Created by arm on 9/12/15.
*/
Expand All @@ -37,7 +32,6 @@ public EmbeddedServletContainerFactory servletContainer() {

private Connector createConnector(int portNumber) {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
connector.setScheme("http");
connector.setPort(portNumber);
return connector;
Expand Down
1 change: 0 additions & 1 deletion src/main/java/com/armzilla/ha/dao/DeviceRepository.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.armzilla.ha.dao;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

Expand Down
16 changes: 11 additions & 5 deletions src/main/java/com/armzilla/ha/hue/HueMulator.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,20 @@ public HueMulator(){
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}

private Page<DeviceDescriptor> getDevices(HttpServletRequest request) {
int pageNumber = request.getLocalPort()-portBase;
Page<DeviceDescriptor> result = repository.findByDeviceType("switch", new PageRequest(pageNumber, 25));
log.info("Found " + result.getNumberOfElements() + " devices on port " + request.getLocalPort());

return result;
}


@RequestMapping(value = "/{userId}/lights", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity<Map<String, String>> getUpnpConfiguration(@PathVariable(value = "userId") String userId, HttpServletRequest request) {
log.info("hue lights list requested: " + userId + " from " + request.getRemoteAddr() + request.getLocalPort());
log.info("hue lights list requested: " + userId + " from " + request.getRemoteAddr() + ":" + request.getLocalPort());

int pageNumber = request.getLocalPort()-portBase;
Page<DeviceDescriptor> deviceList = repository.findByDeviceType("switch", new PageRequest(pageNumber, 25));
Page<DeviceDescriptor> deviceList = this.getDevices(request);
Map<String, String> deviceResponseMap = new HashMap<>();
for (DeviceDescriptor device : deviceList) {
deviceResponseMap.put(device.getId(), device.getName());
Expand All @@ -85,8 +92,7 @@ public ResponseEntity<String> postAPI(HttpServletRequest request) {
@RequestMapping(value = "/{userId}", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity<HueApiResponse> getApi(@PathVariable(value = "userId") String userId, HttpServletRequest request) {
log.info("hue api root requested: " + userId + " from " + request.getRemoteAddr());
int pageNumber = request.getLocalPort()-portBase;
Page<DeviceDescriptor> descriptorList = repository.findByDeviceType("switch", new PageRequest(pageNumber, 25));
Page<DeviceDescriptor> descriptorList = this.getDevices(request);
if (descriptorList == null) {
return new ResponseEntity<>(null, null, HttpStatus.NOT_FOUND);
}
Expand Down
61 changes: 51 additions & 10 deletions src/main/resources/static/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,20 +107,61 @@ angular.module('configurator', [])

$scope.bridge = bridgeService.state;
$scope.device = {id: "", name: "", type: "switch", onUrl: "", offUrl: ""};
$scope.vera = {base: "", port: "3480", id: ""};
$scope.hubs = {
vera: {
base: ""
, port: "3480"
, id: ""
, onUrl: "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1&DeviceNum={deviceId}"
, offUrl: "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=0&DeviceNum={deviceId}"
, user: ""
, pass: ""
}
, openhab: {
base: ""
, port: "8080"
, id: ""
, onUrl: "/CMD?{deviceId}=ON"
, offUrl: "/CMD?{deviceId}=OFF"
, user: ""
, pass: ""
}
}
// set default system to Vera
$scope.selectedHub = "vera";
$scope.system = $scope.hubs.vera;
bridgeService.device = $scope.device;

$scope.selectHub = function (hubName) {
console.log('Selecting hub', $scope.selectedHub)
if (hubName === "openhab") {
$scope.system = $scope.hubs.openhab;
}
else {
$scope.system = $scope.hubs.vera;
}
}

$scope.buildUrls = function () {
if ($scope.vera.base.indexOf("http") < 0) {
$scope.vera.base = "http://" + $scope.vera.base;
var base = ""
if ($scope.system.base.indexOf("http") < 0) {
base = "http://";
}
$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
+ "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=0&DeviceNum="
+ $scope.vera.id;
};
base += $scope.system.base;

var user = $scope.system.user.trim();
var pass = $scope.system.pass.trim();
var creds = "";
if (user.length > 0 && pass.length > 0) {
creds = encodeURIComponent(user) + ":" + encodeURIComponent(pass) + "@";
}

var index = base.indexOf("//") + 2;
base = base.slice(0, index) + creds + base.slice(index);

$scope.device.onUrl = base + ":" + $scope.system.port + $scope.system.onUrl.replace("{deviceId}", $scope.system.id);
$scope.device.offUrl = base + ":" + $scope.system.port + $scope.system.offUrl.replace("{deviceId}", $scope.system.id);
};

$scope.testUrl = function (url) {
window.open(url, "_blank");
Expand Down
47 changes: 36 additions & 11 deletions src/main/resources/static/configurator.html
Original file line number Diff line number Diff line change
Expand Up @@ -95,38 +95,63 @@ <h2 ng-show='bridge.error != ""'>ERROR</h2>
</div>

<div ng-controller="AddingController">
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
<div class="panel-heading"><h2 class="panel-title">Select Hub Type</h2></div>
<ul class="list-group">
<li class="list-group-item">
<label class="col-xs-12 col-sm-2 control-label" for="automationType">Automation Hub Type </label>

<select id="automationType" name="automationType" ng-model="selectedHub" ng-change="selectHub(selectedHub)">
<option value="vera">Vera</option>
<option value="openhab">OpenHAB</option>
</select>
</li>

</ul>
</div>
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
<div class="panel-heading"><h2 class="panel-title">Add a new device</h2></div>
<ul class="list-group">
<li class="list-group-item">
<p class="text-muted">You can generate on/off URLs by filling in a Vera server URL, port, and
<p class="text-muted">You can generate on/off URLs by filling in a hub server URL, port, and
device ID; or you can fill them out manually in the lower section.</p>

<form class="form-horizontal">
<div class="form-group">
<label class="col-xs-12 col-sm-2 control-label" for="vera-base">Vera Server URL </label>
<label class="col-xs-12 col-sm-2 control-label" for="hub-base">Hub Server URL </label>

<div class="col-xs-12 col-sm-10">
<input type="text" class="form-control" id="vera-base" ng-model="vera.base"
placeholder="Vera URL (e.g. http://192.168.1.100)">
<input type="text" class="form-control" id="hub-base" ng-model="system.base"
placeholder="Hub URL (e.g. http://192.168.1.100)">
</div>
</div>
<div class="form-group">
<label class="col-xs-2 col-sm-2 control-label" for="vera-port">Vera Request Port </label>
<label class="col-xs-2 col-sm-2 control-label" for="hub-port">Hub Request Port </label>

<div class="col-xs-10 col-sm-2">
<input type="text" class="form-control" id="vera-port" ng-model="vera.port"
placeholder="Vera Port (typically 3480)">
<input type="text" class="form-control" id="hub-port" ng-model="system.port"
placeholder="Hub Port (typically 3480)">
</div>

<label class="col-xs-2 col-sm-2 control-label" for="vera-id">Device ID </label>
<label class="col-xs-2 col-sm-2 control-label" for="hub-user">Username</label>
<div class="col-xs-10 col-sm-2">
<input type="text" class="form-control" id="hub-user" ng-model="system.user"
placeholder="Hub user (optional)">
</div>
<label class="col-xs-2 col-sm-2 control-label" for="hub-pass">Password</label>
<div class="col-xs-10 col-sm-2">
<input type="text" class="form-control" id="hub-pass" ng-model="system.pass"
placeholder="Hub pass (optional)">
</div>
</div>
<div class="form-group">
<label class="col-xs-2 col-sm-2 control-label" for="hub-id">Device ID </label>

<div class="col-xs-10 col-sm-2">
<input type="text" class="form-control" id="vera-id" ng-model="vera.id"
<input type="text" class="form-control" id="hub-id" ng-model="system.id"
placeholder="ID">
</div>
<button type="submit" ng-click="buildUrls()"
class="col-xs-offset-2 col-sm-offset-1 col-xs-4 col-sm-2 btn btn-success">
class="col-xs-offset-6 col-sm-offset-6 col-xs-4 col-sm-2 btn btn-success">
Generate URLs
</button>
</div>
Expand Down