Skip to content

Commit

Permalink
Merge pull request #5 from bryce-seifert/organization
Browse files Browse the repository at this point in the history
Module Revamp (NDI source gathering, new actions, variables)
  • Loading branch information
josephdadams committed Mar 3, 2021
2 parents 4c75918 + 7e440f7 commit 81173ef
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 271 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules/
package-lock.json
package-lock.json
.DS_Store
21 changes: 11 additions & 10 deletions HELP.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
## Birddog Studio/Mini
This module connects to a Birddog Studio/Mini
<br/>
The module has an integrated database based on json which stores Ndi Sources to find them later
## BirdDog Studio NDI / Mini
This module allows you to control the BirdDog Studio NDI / Mini.

### Configuration
* Target IP: Type in the IP address of the device.
* Target Port: Type in the Port of the device.
* NDI Source Detection Mode: Enable or Disable NDI Source Detection
* NDI Source Detection Interval: Please do not change the Ndi Source Detection Time unless you know what you are doing
* Target IP: the IP address of the BirdDog device

### Available actions
* Change NDI Decode Source: In the Source drop down that custom is the one for which you can also manually set your own sources as Ndi Decode Source using the three entries "NDI Source Name", "NDI Source IP" and "NDI Source Port"
* Remove NDI Decode Source from DB
* Change Decode Source: allows you to change the decode source from a dropdown list of sources available to the BirdDog device
* Change Decode Source by IP: allows you to change to a custom NDI source using the Source Name, Source IP and Source Port
* Resfresh NDI Source List: refreshes the dropdown list of sources available to the BirdDog device. *Note: this does not search for new sources on the BirdDog itself, that must be done in the BirdDog web UI. It only refreshes any new sources once the BirdDog has found*

### Available variables
* Decode Source: displays the source currently being decoded
* Current Mode: displays the current mode (encode or decode) of the device
* Video Format: displays the resolution selected when for encoding (only applies when decive is in encode mode)
84 changes: 25 additions & 59 deletions actions.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
exports.getActions = function() {
return {
changeNdiSource: {
label: 'Change NDI Decode Source',
changeNDISource: {
label: 'Change Decode Source',
options: [{
type: 'dropdown',
label: 'Source',
id: 'source',
default: 'custom',
choices: this.ndi.getSourceDropdown()
},
{
choices: this.api.sourcelist
}
]
},
changeNDISourceIP: {
label: 'Change Decode Source by IP',
options: [{
type: 'textinput',
label: 'NDI Source Name',
id: 'ndiSource',
Expand All @@ -32,69 +35,32 @@ exports.getActions = function() {
regex: this.REGEX_PORT,
min: 1,
max: 65535,
default: 8080,
default: 5961,
}
]
},
removeNdiSource: {
label: 'Remove NDI Decode Source from DB',
options: [{
type: 'dropdown',
label: 'Source',
id: 'source',
default: 'custom',
choices: this.ndi.getSourceDropdown()
}, ]
}
resfreshNDISourceList: {
label: 'Resfresh NDI Source List',
},
};
};

exports.executeAction = function(action) {
if (action.action === 'changeNdiSource') {
if (action.options.source == 'custom') {
if (action.options.ndiSource && action.options.ndiSourceIp && action.options.ndiSourcePort) {
this.api.setNdiDecodeSource(action.options.ndiSourceIp, action.options.ndiSourcePort, action.options.ndiSource);
if (action.action === 'changeNDISource') {
if (action.options.source !=undefined) {
var urlAddressSplit = this.api.sourcelist[action.options.source].split(':');
var name = action.options.source;
this.api.setNDIDecodeSource(urlAddressSplit[0], urlAddressSplit[1], name);
} else {
this.log('error', 'The Ndi decoding source could not be changed!!! <h4>Check Action Config!!!</h4>');
this.log('error', 'Unable to find the configured NDI source. Please check the NDI source info in the action configuration');
}
} else if (action.action === 'changeNDISourceIP') {
if (action.options.ndiSource && action.options.ndiSourceIp && action.options.ndiSourcePort) {
this.api.setNDIDecodeSource(action.options.ndiSourceIp, action.options.ndiSourcePort, action.options.ndiSource);
} else {
if (action.options.source) {
(async () => {
var sourceSize = await this.ndi.getDb().get('source').filter({
name: action.options.source
}).size().value();
if (sourceSize > 0) {
var sourceDb = await this.ndi.getDb().get('source').filter({
name: action.options.source
}).value();
var urlAddressSplit = sourceDb[0].urlAddress.split(':');

this.api.setNdiDecodeSource(urlAddressSplit[0], urlAddressSplit[1], sourceDb[0].name);
} else {
this.log('error', 'The Ndi decoding source could not be changed!!! <h4>Check Action Config!!!</h4>');
}
})();
} else {
this.log('error', 'The Ndi decoding source could not be changed!!! <h4>Check Action Config!!!</h4>');
}
}
} else if (action.action === 'removeNdiSource') {
if (action.options.source) {
(async () => {
var sourceSize = await this.ndi.getDb().get('source').filter({
name: action.options.source
}).size().value();
if (sourceSize > 0) {
await this.ndi.getDb().get('source').remove({
name: action.options.source
}).write();
this.log('info', `Remove NDI Decode Source: ${action.options.source}!!!`);
} else {
this.log('error', 'The Ndi decoding source could not be removed!!! <h4>Check Action Config!!!</h4>');
}
})();
} else {
this.log('error', 'The Ndi decoding source could not be removed!!! <h4>Check Action Config!!!</h4>');
this.log('error', 'Unable to find the configured NDI source. Please check the NDI source info in the action configuration');
}
} else if (action.action === 'resfreshNDISourceList') {
this.api.getSourceList();
}
};
104 changes: 78 additions & 26 deletions birddogapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class instance_api {
this.instance = instance;
this.device = {
ip: this.instance.config.deviceIp,
port: this.instance.config.devicePort,
port: 8080,
deviceName: '',
source: '',
encsettings: {
Expand All @@ -31,115 +31,165 @@ class instance_api {
videoouts: '',
vidinsel: '',
},
source: ''
};
}

aboutDevice() {
const url = `http://${this.instance.config.deviceIp}:${this.instance.config.devicePort}/about`;
const url = `http://${this.instance.config.deviceIp}:8080/about`;
const options = {
json: true
};
got.get(url, options)
.then(res => {
if (res.body.MyHostName) {
this.device.deviceName = res.body.MyHostName;
this.instance.log('info', `Connected to ${this.device.deviceName}`);
this.instance.status(this.instance.STATUS_OK);
}
})
.catch(err => {
console.log(err);
this.instance.log('warn', 'Please check the device status or the ip and port of the device');
this.instance.log('error', `Unable to connect to ${this.device.deviceName}. Please check the device IP address in the config settings`);
this.instance.status(this.instance.STATUS_ERROR,'Error');
});
return this.device;
}

getSourceList() {
const url = `http://${this.instance.config.deviceIp}:8080/List`;
const options = {
json: true
};
got.get(url, options)
.then(res => {
if (!res.body) {
this.instance.log('warn', `Unable to retreive available sources for ${this.device.deviceName}`);
return;
}
this.sourcelist = [];
for (const [key, value] of Object.entries(res.body)) {
const NDIName = key;
const NDIIP = value;
this.sourcelist[NDIName] = NDIIP;
this.sourcelist.push({ id: NDIName, label: NDIName});
}
this.instance.system.emit('instance_actions', this.instance.id, this.instance.getActions.bind(this.instance)());
})
.catch(err => {
this.instance.log('error', `Unable to connect to ${this.device.deviceName}. Please check the device IP address in the config settings`);
this.instance.status(this.instance.STATUS_ERROR);
});
return this.sourcelist;
}

getEncSettings() {
const url = `http://${this.instance.config.deviceIp}:${this.instance.config.devicePort}/enc-settings`;
const url = `http://${this.instance.config.deviceIp}:8080/enc-settings`;
const options = {
json: true
};
got.get(url, options)
.then(res => {
if (!res.body) {
this.instance.log('warn', 'Retrieving the encoding settings failed!');
this.instance.log('warn', `Unable to retreive the encoding settings for ${this.device.deviceName}`);
return;
}
this.device.encsettings = JSON.stringify(res.body);
})
.catch(err => {
this.instance.log('warn', 'Please check the device status or the ip and port of the device');
this.instance.log('error', `Unable to connect to ${this.device.deviceName}. Please check the device IP address in the config settings`);
this.instance.status(this.instance.STATUS_ERROR);
});
return this.device.encsettings;
}

getDecSettings() {
const url = `http://${this.instance.config.deviceIp}:${this.instance.config.devicePort}/dec-settings`;
const url = `http://${this.instance.config.deviceIp}:8080/dec-settings`;
const options = {
json: true
};
got.get(url, options)
.then(res => {
if (!res.body) {
this.instance.log('warn', 'Retrieving the decoding settings failed!');
this.instance.log('warn', `Unable to retreive the decoding settings for ${this.device.deviceName}`);
return;
}
this.device.decsettings = JSON.stringify(res.body);
this.instance.log('warn', this.device.decsettings);
})
.catch(err => {
this.instance.log('warn', 'Please check the device status or the ip and port of the device');
this.instance.log('error', `Unable to connect to ${this.device.deviceName}. Please check the device IP address in the config settings`);
this.instance.status(this.instance.STATUS_ERROR);
});
return this.device.decsettings;
}

getAVSettings() {
const url = `http://${this.instance.config.deviceIp}:${this.instance.config.devicePort}/av-settings`;
const url = `http://${this.instance.config.deviceIp}:8080/av-settings`;
const options = {
json: true
};
got.get(url, options)
.then(res => {
if (!res.body) {
this.instance.log('warn', 'Retrieving the AV settings failed!');
this.instance.log('warn', `Unable to retreive AV settings for ${this.device.deviceName}`);
return;
}
this.device.avsettings = JSON.stringify(res.body);
this.decodeMode = 'Updating';
if (res.body.videoout === 'videooutd') {
this.decodeMode = 'Decode'
} else {
this.decodeMode = 'Encode'
}
this.instance.setVariable('current_mode', this.decodeMode);
this.videoFormat = 'Updating';
if (res.body.videoin !='AUTO') {
this.videoFormat = res.body.videoin;
} else {
this.videoFormat = 'Auto'
}
this.instance.setVariable('video_format', this.videoFormat);
})
.catch(err => {
this.instance.log('warn', 'Please check the device status or the ip and port of the device');
this.instance.log('error', `Unable to connect to ${this.device.deviceName}. Please check the device IP address in the config settings`);
this.instance.status(this.instance.STATUS_ERROR);
});
return this.device.avsettings;
}

getAktiveSource() {
const url = `http://${this.instance.config.deviceIp}:${this.instance.config.devicePort}/connectTo`;
getActiveSource() {
const url = `http://${this.instance.config.deviceIp}:8080/connectTo`;
const options = {
json: true
};
got.get(url, options)
.then(res => {
if (!res.body) {
this.instance.log('warn', 'Retrieving the NDI decoding source failed!');
this.instance.log('warn', `Unable to retreive the NDI decode source for ${this.device.deviceName}`);
return;
} else if (res.body.sourceName) {
this.device.currentSource = res.body.sourceName;
}
this.device.source = JSON.stringify(res.body);
this.instance.setVariable('decode_source', this.device.currentSource);
})
.catch(err => {
this.instance.log('warn', 'Please check the device status or the ip and port of the device');
this.instance.log('error', `Unable to connect to ${this.device.deviceName}. Please check the device IP address in the config settings`);
this.instance.status(this.instance.STATUS_ERROR);
});
return this.device.source;
return this.device.currentSource;
}

getDevice() {
return this.device;
}

setNdiDecodeSource(ip, port, sourceName) {
setNDIDecodeSource(ip, port, sourceName) {
if (!ip || !port || !sourceName) {
this.instance.log('warn', `The Ndi decoding source could not be changed!!`);
this.instance.log('warn', `Unable to change NDI decode source for ${this.device.deviceName}`);
return false;
}

const url = `http://${this.instance.config.deviceIp}:${this.instance.config.devicePort}/connectTo`;
const url = `http://${this.instance.config.deviceIp}:8080/connectTo`;
const sourceNameSplit = sourceName.split(" ");
const sourceJson = {
connectToIp: ip,
Expand All @@ -155,19 +205,21 @@ class instance_api {
got.post(url, options)
.then(res => {
if (!res.body) {
this.instance.log('warn', `The Ndi decoding source could not be changed to: ${sourceName} on Devicce: ${this.device.devicenName}`);
this.instance.log('warn', `Unable to change NDI decode source to ${sourceName} on ${this.device.deviceName}`);
return;
}
if (JSON.stringify(res.body) == JSON.stringify(sourceJson)) {
this.device.source = sourceName;

this.instance.log('info', `Change NDI Decode Source to: ${this.device.source} on Device: ${this.device.deviceName}!!!`);
this.instance.log('info', `Changed NDI decode source to ${this.device.source} on ${this.device.deviceName}`);
this.getActiveSource();
} else {
this.instance.log('warn', `The Ndi decoding source could not be changed to: ${sourceName} on Devicce: ${this.device.devicenName}`);
this.instance.log('warn', `Unable to change NDI decode source to ${sourceName} on ${this.device.deviceName}`);
}
})
.catch(err => {
this.instance.log('warn', 'Please check the device status or the ip and port of the device');
this.instance.log('error', `Unable to connect to ${this.device.deviceName}. Please check the device IP address in the config settings`);
this.instance.status(this.instance.STATUS_ERROR);
});

}
Expand Down
Loading

0 comments on commit 81173ef

Please sign in to comment.