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

KNX Multicast without KNXD #152

Merged
merged 3 commits into from
Mar 16, 2020
Merged
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
52 changes: 15 additions & 37 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ function KNXPlatform(log, config, newAPI) {
* - GroupAddresses object
* - Devices Object
*/
globs.knxd = this.config.knxd;
globs.knxd_ip = this.config.knxd_ip;
globs.knxd_port = this.config.knxd_port || 6720;
globs.log = log;
Expand All @@ -78,6 +79,7 @@ function KNXPlatform(log, config, newAPI) {
globs.readRequests = {};

KNXAccess.setGlobs(globs); // init link for module;
knxmonitor.setGlobs(globs);
knxmonitor.startMonitor({
host : globs.knxd_ip,
port : globs.knxd_port
Expand Down Expand Up @@ -288,11 +290,7 @@ KNXPlatform.prototype.configure = function() {
if (that.config.AllowKillHomebridge===true) {
response.write(' <br><hr><br><a href="/kill">Kill homebridge</a> by throwing an Error. Use this to restart HomeBridge if you have it configured as a self-starting service ' + ' <BR>');
}
response.write(`<HR><BR>Available pages are <br>
<a href="/list">list devices</a> and <br>
<a href="/availservices">list available services</a><br>
<a href="/availcharacteristics">list available characteristics</a>
`);
response.write('<HR><BR>Available pages are <br><a href="/list">list devices</a> and <br><a href="/availservices">list available services</a><br><a href="/availcharacteristics">list available characteristics</a>');
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you convert all multi-line strings to single line strings? Some issue with your IDE?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ops, i think there was a plugin in my IDE over motivated ...

response.write('URL<BR><BR>' + request.url + '<BR>');
response.write(JSON.stringify(params) + '<BR>');
response.end('</BODY>');
Expand Down Expand Up @@ -343,11 +341,7 @@ KNXPlatform.prototype.configure = function() {
}

}
response.write(`<HR><BR>Available pages are <br>
<a href="/list">list devices</a> and <br>
<a href="/availservices">list available services</a><br>
<a href="/availcharacteristics">list available characteristics</a>
`);
response.write('<HR><BR>Available pages are <br><a href="/list">list devices</a> and <br><a href="/availservices">list available services</a><br><a href="/availcharacteristics">list available characteristics</a>');
response.write('URL<BR><BR>' + request.url + '<BR>');
response.write(JSON.stringify(params) + '<BR>');
response.end('</BODY>');
Expand All @@ -362,11 +356,7 @@ KNXPlatform.prototype.configure = function() {
response.write('<a href="/chardata?name='+ chr.displayName+'">' + chr.displayName + '</a><BR>');
}
}
response.write(`<HR><BR>Available pages are <br>
<a href="/list">list devices</a> and <br>
<a href="/availservices">list available services</a><br>
<a href="/availcharacteristics">list available characteristics</a>
`);
response.write('<HR><BR>Available pages are <br><a href="/list">list devices</a> and <br><a href="/availservices">list available services</a><br><a href="/availcharacteristics">list available characteristics</a>');
response.write('URL<BR><BR>' + request.url + '<BR>');
response.write(JSON.stringify(params) + '<BR>');
response.end('</BODY>');
Expand All @@ -379,8 +369,8 @@ KNXPlatform.prototype.configure = function() {
let service1 = globs.webdata.availableServices.Services[params.name];
let disp1 = globs.webdata.servData[params.name];
response.write('<H1>' + disp1.displayName +'</H1>');
response.write(`<H2>Mandatory characteristics</H2>`);
response.write(`<H4>Mandatory characteristics are created automatically by homebridge. If they are not connected to group addresses they are dysfunct although displayed in HomeKit apps.</H4>`);
response.write('<H2>Mandatory characteristics</H2>');
response.write('<H4>Mandatory characteristics are created automatically by homebridge. If they are not connected to group addresses they are dysfunct although displayed in HomeKit apps.</H4>');
for (let chrName in service1.characteristics) { // service1.characteristics is a numbered array !!!
if (service1.characteristics.hasOwnProperty(chrName)) {
//console.log('Searching for '+service1.characteristics[chrName].displayName);
Expand All @@ -390,8 +380,8 @@ KNXPlatform.prototype.configure = function() {
}

}
response.write(`<H2>Optional characteristics</H2>`);
response.write(`<H4>Optional characteristics are created if listed in configuration. Any other characteristic might also work, these are thought by Apple to work best with the service</H4>`);
response.write('<H2>Optional characteristics</H2>');
response.write('<H4>Optional characteristics are created if listed in configuration. Any other characteristic might also work, these are thought by Apple to work best with the service</H4>');
for (let chrName in service1.optionalCharacteristics) { // service1.characteristics is a numbered array !!!
if (service1.optionalCharacteristics.hasOwnProperty(chrName)) {
//console.log('Searching for '+service1.optionalCharacteristics[chrName].displayName);
Expand All @@ -404,11 +394,7 @@ KNXPlatform.prototype.configure = function() {
} else {
response.write('<H1>Error in URL</H1>');
}
response.write(`<HR><BR>Available pages are <br>
<a href="/list">list devices</a> and <br>
<a href="/availservices">list available services</a><br>
<a href="/availcharacteristics">list available characteristics</a>
`);
response.write('<HR><BR>Available pages are <br><a href="/list">list devices</a> and <br><a href="/availservices">list available services</a><br><a href="/availcharacteristics">list available characteristics</a>');
response.write('URL<BR><BR>' + request.url + '<BR>');
response.write(JSON.stringify(params) + '<BR>');
response.end('</BODY>');
Expand All @@ -421,8 +407,8 @@ KNXPlatform.prototype.configure = function() {
let disp1 = globs.webdata.charData[params.name];
let char1 = globs.webdata.availableCharacteristics[disp1.objectName];
response.write('<H1>' + disp1.displayName +'</H1>');
response.write(`<H2>Properties</H2>`);
response.write(`<H4>Properties define the behaviour of the characteristic</H4>`);
response.write('<H2>Properties</H2>');
response.write('<H4>Properties define the behaviour of the characteristic</H4>');
for (let prop in char1) { // service1.characteristics is a numbered array !!!
if (char1.hasOwnProperty(prop)) {
//console.log('Searching for '+service1.characteristics[chrName].displayName);
Expand All @@ -445,23 +431,15 @@ KNXPlatform.prototype.configure = function() {
response.write('<H1>Error in URL</H1>');
console.dir(globs.webdata.charData);
}
response.write(`<HR><BR>Available pages are <br>
<a href="/list">list devices</a> and <br>
<a href="/availservices">list available services</a><br>
<a href="/availcharacteristics">list available characteristics</a>
`);
response.write('<HR><BR>Available pages are <br><a href="/list">list devices</a> and <br><a href="/availservices">list available services</a><br><a href="/availcharacteristics">list available characteristics</a>');
response.write('URL<BR><BR>' + request.url + '<BR>');
response.write(JSON.stringify(params) + '<BR>');
response.end('</BODY>');
} else {
// any other URL
response.write('<HEAD><TITLE>Homebridge-KNX</TITLE></HEAD>');
response.write('<BODY>');
response.write(`<BR>Available pages are <br>
<a href="/list">list devices</a> and <br>
<a href="/availservices">list available services</a><br>
<a href="/availcharacteristics">list available characteristics</a>
`);
response.write('<BR>Available pages are <br><a href="/list">list devices</a> and <br><a href="/availservices">list available services</a><br><a href="/availcharacteristics">list available characteristics</a>');
response.write('<h1>URL<h1/><BR><BR>' + request.url + '<BR>');
response.write(JSON.stringify(params) + '<BR>');
response.end('</BODY>');
Expand All @@ -478,7 +456,7 @@ KNXPlatform.prototype.configure = function() {
}

// we're done, now issue the startup read requests to the bus
require('./lib/knxaccess.js').knxreadhash(globs.readRequests);
KNXAccess.knxreadhash(globs.readRequests);

};

Expand Down
3 changes: 2 additions & 1 deletion knx_config.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"knxd": false,
"knxd_ip": "192.168.178.212",
"knxd_port": 6720,
"AllowWebserver": true,
Expand Down Expand Up @@ -89,4 +90,4 @@
],
"GroupAddresses": []

}
}
2 changes: 2 additions & 0 deletions knx_config.json.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ homebridge-knx expects the following structure in the `knx_config.json`:

```
{
"knxd": true,
"knxd_ip": "192.168.1.1",
"knxd_port": 6720,
"AllowWebserver": true,
Expand All @@ -11,6 +12,7 @@ homebridge-knx expects the following structure in the `knx_config.json`:
]
}
```
`knxd` if true then knxd is used, if false than multicast routing is used
`192.168.1.1` has to be changed to your [knxd](https://github.com/knxd/knxd) installation, and `6720` to the port you are using (6720 is default).
`platform` and `name` have become obsolete.
`AllowWebserver`: if set to true, homebridge-knx will start a tiny webserver on port 18081 to allow the removal of devices from homebridge cache (and the running instance). Enable for debugging, disable for secure productive operation!
Expand Down
167 changes: 99 additions & 68 deletions lib/knxaccess.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

var globs;
var knx = require('knx');
var knxd = require('eibd');
var iterate = require('./iterate');
var allFunctions = {};
Expand All @@ -23,56 +24,75 @@ var allFunctions = {};
allFunctions.knxwrite = function(callback, groupAddress, dpt, value) {
//globs.info("DEBUG in knxwrite");
/** @type {eibd~Connection} */
var knxdConnection = new knxd.Connection();
//globs.info("DEBUG in knxwrite: created empty connection, trying to connect socket to " + globs.knxd_ip + ":" + globs.knxd_port);
knxdConnection.socketRemote({
host : globs.knxd_ip,
port : globs.knxd_port
}, function(err) {
if (err) {
// a fatal error occurred
console.error("FATAL: knxd or eibd not reachable: " + err);
throw new Error("Cannot reach knxd or eibd service, please check installation and configuration .json");
}
var dest = knxd.str2addr(groupAddress);
globs.debug("DEBUG knxwrite Address conversion, converted "+ groupAddress+ " to " + dest);
knxdConnection.openTGroup(dest, 1, function(err) {
if (err) {
globs.errorlog("[ERROR] knxwrite:openTGroup: " + err);
if (callback) {
try {
callback(err);
} catch (e) {
globs.log('Caught error '+ e + ' when calling homebridg callback.');
}
}
} else {
//globs.debug("DEBUG opened TGroup ");
var msg = knxd.createMessage('write', dpt, parseFloat(value));
knxdConnection.sendAPDU(msg, function(err) {
if (err) {
globs.errorlog("[ERROR] knxwrite:sendAPDU: " + err);
if (callback) {
try {
callback(err);
} catch (e) {
globs.log('Caught error '+ e + ' when calling homebridg callback.');
}
}
} else {
globs.debug("knxAccess.knxwrite: knx data sent: Value " + value + " for GA " + groupAddress);

if(!globs.knxd) {
var connection = knx.Connection({
handlers: {
connected: function() {
connection.write(groupAddress, parseFloat(value), dpt, function(err) {
if (callback) {
try {
callback();
} catch (e) {
globs.log('Caught error '+ e + ' when calling homebridg callback.');
}
}
}
});
});
}
}
});
} else {
var knxdConnection = new knxd.Connection();
//globs.info("DEBUG in knxwrite: created empty connection, trying to connect socket to " + globs.knxd_ip + ":" + globs.knxd_port);
knxdConnection.socketRemote({
host : globs.knxd_ip,
port : globs.knxd_port
}, function(err) {
if (err) {
// a fatal error occurred
console.error("FATAL: knxd or eibd not reachable: " + err);
throw new Error("Cannot reach knxd or eibd service, please check installation and configuration .json");
}
var dest = knxd.str2addr(groupAddress);
globs.debug("DEBUG knxwrite Address conversion, converted "+ groupAddress+ " to " + dest);
knxdConnection.openTGroup(dest, 1, function(err) {
if (err) {
globs.errorlog("[ERROR] knxwrite:openTGroup: " + err);
if (callback) {
try {
callback(err);
} catch (e) {
globs.log('Caught error '+ e + ' when calling homebridg callback.');
}
}
} else {
//globs.debug("DEBUG opened TGroup ");
var msg = knxd.createMessage('write', dpt, parseFloat(value));
knxdConnection.sendAPDU(msg, function(err) {
if (err) {
globs.errorlog("[ERROR] knxwrite:sendAPDU: " + err);
if (callback) {
try {
callback(err);
} catch (e) {
globs.log('Caught error '+ e + ' when calling homebridg callback.');
}
}
} else {
globs.debug("knxAccess.knxwrite: knx data sent: Value " + value + " for GA " + groupAddress);
if (callback) {
try {
callback();
} catch (e) {
globs.log('Caught error '+ e + ' when calling homebridg callback.');
}
}
}
});
}
});
});
});
}
};

allFunctions.setBooleanState = function(value, callback, gaddress, reverseflag) {
Expand Down Expand Up @@ -128,36 +148,47 @@ allFunctions.knxread = function(groupAddress) {
return null;
}
globs.debug("[knxdevice:knxread] preparing knx request for " + groupAddress);
var knxdConnection = new knxd.Connection();
//globs.info("DEBUG in knxread: created empty connection, trying to connect socket to " + globs.knxd_ip + ":" + globs.knxd_port);
knxdConnection.socketRemote({
host : globs.knxd_ip,
port : globs.knxd_port
}, function(err) {
if (err) {
throw {
name : "KNXD connection failed",
message : "The connection to the knx daemon failed. Check IP and Port."
};
}
var dest = knxd.str2addr(groupAddress);
// globs.info("DEBUG got dest="+dest);
knxdConnection.openTGroup(dest, 1, function(err) {

if(!globs.knxd) {
var connection = knx.Connection({
handlers: {
connected: function() {
connection.read(groupAddress);
}
}
});
} else {
var knxdConnection = new knxd.Connection();
//globs.info("DEBUG in knxread: created empty connection, trying to connect socket to " + globs.knxd_ip + ":" + globs.knxd_port);
knxdConnection.socketRemote({
host : globs.knxd_ip,
port : globs.knxd_port
}, function(err) {
if (err) {
globs.errorlog("[ERROR] knxread:openTGroup: " + err);
} else {
// globs.info("DEBUG knxread: opened TGroup ");
var msg = knxd.createMessage('read', 'DPT1', 0);
knxdConnection.sendAPDU(msg, function(err) {
if (err) {
globs.errorlog("[ERROR] knxread:sendAPDU: " + err);
} else {
globs.debug("[knxdevice:knxread] knx request sent for " + groupAddress);
}
});
throw {
name : "KNXD connection failed",
message : "The connection to the knx daemon failed. Check IP and Port."
};
}
var dest = knxd.str2addr(groupAddress);
// globs.info("DEBUG got dest="+dest);
knxdConnection.openTGroup(dest, 1, function(err) {
if (err) {
globs.errorlog("[ERROR] knxread:openTGroup: " + err);
} else {
// globs.info("DEBUG knxread: opened TGroup ");
var msg = knxd.createMessage('read', 'DPT1', 0);
knxdConnection.sendAPDU(msg, function(err) {
if (err) {
globs.errorlog("[ERROR] knxread:sendAPDU: " + err);
} else {
globs.debug("[knxdevice:knxread] knx request sent for " + groupAddress);
}
});
}
});
});
});
}
};

// issuing multiple read requests at once
Expand Down
Loading