Skip to content

Commit

Permalink
Merge pull request kikolobo#9 from mzbik/master
Browse files Browse the repository at this point in the history
Corrects parsing of xml file
  • Loading branch information
kikolobo authored Mar 8, 2022
2 parents b86548d + ac8d978 commit 1a1899e
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 102 deletions.
142 changes: 91 additions & 51 deletions LutronXML_Parsin_Tool/DbXParser.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@ <h1>Homebridge-Homeworks Configuration Generator</h1>
JSON Text will be created automatically below after loading the XML file.<br>Copy & Paste text to the JSON settings in HomeBridge. Replace the whole platform block that belongs to the Homeworks integration.
<hr>

<div id="errors"> </div>
<div id="output"> </div>
<script type="text/javascript">
console.log("Here....");
</script>
</body>

</html>
<script type='text/javascript' src='https://code.jquery.com/jquery-3.5.1.min.js'></script>
<script type='text/javascript' src="https://cdn.rawgit.com/abdmob/x2js/master/xml2json.js"></script>

<script type="text/javascript">

Expand All @@ -56,14 +59,13 @@ <h1>Homebridge-Homeworks Configuration Generator</h1>

function parseXML(text)
{
var txt = text.split("/>");
var out = "";
var i = 0;
var currentArea = "";
var fixtureName = ""
var integID = "";
var FriendlyName = "";
var includeAreaName = document.getElementById("includeAreaName").checked;
var xmlText = $.parseXML(text)

var x2js = new X2JS();
var data = x2js.xml2json(xmlText);

var parsed = walkDBJson( data );

var configObject = {
"host": document.getElementById("host").value,
"apiPort": document.getElementById("port").value,
Expand All @@ -74,57 +76,95 @@ <h1>Homebridge-Homeworks Configuration Generator</h1>
"platform": "Homeworks",
};

var deviceObjects = new Array();
var integrationIDs = new Array();
var duplicateFlag = false;
configObject.devices = parsed;
document.getElementById("output").innerHTML = sanitizeHTML(JSON.stringify(configObject,undefined, 4));
}


for (i = 0; i < txt.length ;i++) {
if (txt[i] !== "") {
if (txt[i].includes("Area Name") === true) {
var tag = txt[i].split("\"");
currentArea = tag[1];
}
if (txt[i].includes("Output Name=") === true) {
var tag = txt[i].split("\"");

fixtureName = tag[1].trim();
integID = tag[5].trim();


if (integrationIDs.filter(integrationId => integrationId === integID).length > 0) {
duplicateFlag = true;
}

if (includeAreaName === true) {
FriendlyName = currentArea + " " + fixtureName;
} else {
FriendlyName = fixtureName;
}

out += currentArea + " = " + fixtureName + " [" + integID + "] " + " > " + FriendlyName + "\n";

var device = {"name": FriendlyName,
"integrationID": integID,
"isDimmable": true};
function noteError(txt) {
document.getElementById("errors").innerHTML = "<p style='color:red'>" + txt + "</p>";
}

integrationIDs.push(integID);
deviceObjects.push(device)
}
// Lutron's XML schema is not public so this is a best-guess. Also
// note that XML->JSON conversion is pretty wacko.
//
// The parsed XML is an object with field:
// Project object
//
// The Project object has (among others) field:
// Areas.Area Area or Area[]
//
// The Area object has (among others) fields:
// _Name string
// Outputs Output or Output[]
// Areas Area or Area[]
//
// The Output object has (among others) fields:
// _Name string
// _IntegrationID string
// _OutputType string
//
function walkDBJson(node) {
if (node.Project === undefined) {
noteError("Unable to parse: missing 'Project' field");
return [];
}

return walkAreas(node.Project.Areas.Area);
}

function walkAreas(areas) {
// Areas is either a single area or an array
if (areas instanceof Array) {
var deviceList = [];
for(var area of areas) {
deviceList = deviceList.concat(walkArea(area));
}
return deviceList;
}


configObject.devices = deviceObjects;
if (duplicateFlag === false) {
document.getElementById("output").innerHTML = sanitizeHTML(JSON.stringify(configObject,undefined, 4));
} else {
document.getElementById("output").innerHTML = "<p style='color:red'>ERROR: Multiple accessories are using the same Lutron IntegrationID. A unique ID is required.</br> Please edit your XML document to remove redundant devices.</p>";

return walkArea( areas);
}

function walkArea(area) {
var deviceList = [];
if (area.Outputs !== '') {
var x = walkOutputs(area.Outputs.Output, area._Name);
deviceList = deviceList.concat(x);
}
if (area.Areas !== '') {
var x = walkAreas(area.Areas.Area);
deviceList = deviceList.concat(x);
}
return deviceList;
}

function walkOutputs(outputs, name) {
if (outputs instanceof Array) {
var deviceList = [];
for (output of outputs) {
deviceList.push( walkOutput( output, name));
}
return deviceList;
}

return walkOutput(outputs, name);
}

function walkOutput(output, name) {
var deviceName = output._Name;
if (document.getElementById("includeAreaName").checked) {
deviceName = name + " " + output._Name;
}
var device = { "name": deviceName,
"integrationID": output._IntegrationID,
"outputType": output._OutputType,
"isDimmable": true};

return device;
}

function sanitizeHTML(text) {

function sanitizeHTML(text) {
var element = document.createElement('div');
element.innerText = text;
return element.innerHTML;
Expand Down
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,25 @@ https://github.com/kikolobo/homebridge-lutron-homeworks/tree/master/LutronXML_Pa
More info on the extraction process here:
https://www.lutron.com/TechnicalDocumentLibrary/HWQS_XML_Extraction_FAQ.pdf

## WebStorm/IntelliJ Setup


Start at the root of where this plugin will be installed
* ```git clone https://github.com/nfarina/homebridge.git```

This installs a local homebridge for testing
* ```cd homebridge```
* ```npm install```
* ```npm install homebridge-config-ui-x ```
* ```npm build```
* ```mkdir config```
* ```cd config```
* Create a default ```config.json``` in the current directory. See homebridge docs for details
* ```cd ..\..```
* ```git clone https://github.com/XXX/homebridge-lutron-homeworks.git```
* ```npm install```
* ```npm build```
* Start Webstorm and open the ```homebridge-lutron-homeworks``` directory as a project
* Create a run/debug configuration that looks like: ![img_1.png](img_1.png)

You're good to go!
11 changes: 11 additions & 0 deletions config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@
"items": {
"type": "object",
"properties": {
"deviceType": {
"type": "string",
"title": "Device Type",
"oneOf":
[
{ "title": "Light", "enum": ["light"] },
{ "title": "Shade", "enum": ["shade"] }
],
"required": true,
"placeholder": "light"
},
"name": {
"type": "string",
"title": "Light Name",
Expand Down
Binary file added img_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"private": false,
"displayName": "Homeworks",
"name": "homebridge-homeworks",
"name": "homebridge-lutron-homeworks",
"version": "0.0.2",
"description": "Homeworks Plugin for HomeBridge",
"license": "Apache-2.0",
Expand Down
5 changes: 5 additions & 0 deletions src/Schemas/device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ export interface ConfigDevice {
*/
integrationID: string;

/**
* Type of device
*/
deviceType: string;

/**
* Gets or sets a value that determines whether is dimmable
*/
Expand Down
Loading

0 comments on commit 1a1899e

Please sign in to comment.