Skip to content

Commit

Permalink
Merge pull request #18 from Caleb-Wishart/integrate
Browse files Browse the repository at this point in the history
v2.1.0 - Authentication Support
  • Loading branch information
Caleb-Wishart authored Sep 10, 2023
2 parents 4da450b + f4ffe0e commit 7c97464
Show file tree
Hide file tree
Showing 8 changed files with 680 additions and 510 deletions.
20 changes: 12 additions & 8 deletions companion/HELP.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@

**Supported Actions**

* Start/Stop Record
* Start/Stop Streaming
* Change recording profile
* Change streaming profile
* Change Audio / Video input
* Rename file
* Rename file with current timestamp - YYYYMMDD_HHMM
* Rename file with variable
- Start/Stop Record
- Start/Stop Streaming
- Change recording profile
- Change streaming profile
- Change Audio / Video input
- Rename file
- Rename file with current timestamp - YYYYMMDD_HHMM
- Rename file with variable

Check out the [AJA HELO Support Page](https://www.aja.com/products/helo#support) for firmware updates and hardware support.

**Variables & Polling**

This module supports polling the HELO REST API, and saves the response to certain states. Polling can be set to various options.

**Authentication (Beta)**

In the event that your HELO has User Authentication enabled the module will attempt to authenticate with the given password.
11 changes: 5 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ class HeloInstance extends InstanceBase {

self.updateFeedbacks()

self.updateStatus(InstanceStatus.Connecting, 'Waiting for Config Confirmation')
await self.configUpdated(config)
}

Expand All @@ -63,16 +62,14 @@ class HeloInstance extends InstanceBase {
if (self.config.host && self.config.port) {
self.updateStatus(InstanceStatus.Connecting, 'Config Updated')
// update our connection in case host has changed
self.connection = new Helo(self.config)
self.connection = new Helo(self, self.config)

// Test to confirm connection
// Simply send a request to get the current media available
let result = await self.connection.sendRequest('action=get&paramid=eParamID_CurrentMediaAvailable')
if (result.status != 'success') {
self.updateStatus(
InstanceStatus.ConnectionFailure,
`Could not connect to Helo @ http://${self.config.host}:${self.config.port}`
)
self.log('error', 'Confirm connection Failure: ' + JSON.stringify(result))
self.updateStatus(InstanceStatus.ConnectionFailure, `Could not connect to Helo @ ${self.connection.baseUrl}`)
return
}

Expand All @@ -85,6 +82,8 @@ class HeloInstance extends InstanceBase {
self.updateActions()

self.updateStatus(InstanceStatus.Ok)
} else {
self.updateStatus(InstanceStatus.BadConfig, 'Missing required values')
}
}

Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "aja-helo",
"version": "2.0.2",
"version": "2.1.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
Expand All @@ -12,10 +12,10 @@
"url": "git+https://github.com/bitfocus/companion-module-aja-helo.git"
},
"dependencies": {
"@companion-module/base": "~1.0.2"
"@companion-module/base": "^1.4.1"
},
"prettier": "@companion-module/tools/.prettierrc.json",
"devDependencies": {
"@companion-module/tools": "^0.5.1"
"@companion-module/tools": "^1.3.2"
}
}
67 changes: 59 additions & 8 deletions src/Helo.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,71 @@
const { InstanceStatus } = require('@companion-module/base')

class Helo {
constructor(config) {
constructor(instance, config) {
this.instance = instance

const apiHost = config.host
const apiPort = config.port

this.baseUrl = `http://${apiHost}:${apiPort}/config?`
this.baseUrl = `http://${apiHost}:${apiPort}`

this.requestOptions = {
method: 'GET',
timeout: 10000,
}
this.auth_required = config.auth_required
this.auth_password = config.auth_password
this.session = null
}

async authenticate() {
let requestUrl = this.baseUrl + '/authenticator/login'

let requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
password_provided: this.auth_password,
}),
}

const response = await fetch(requestUrl, requestOptions)
let result = await response.json()

if (result.login == 'success') {
let cookies = response.headers.getSetCookie()
if (cookies.length == 1) {
this.session = cookies[0]
this.instance.log('info', 'auth: Successful Authentication')
} else {
this.instance.log('error', 'auth: Bad Cookies: ' + JSON.stringify(cookies))
}
} else {
this.session = null
this.instance.updateStatus(InstanceStatus.ConnectionFailure, 'Failed to authenticate with password')
}
}
async sendRequest(cmd) {
let requestUrl = this.baseUrl + cmd
let requestUrl = this.baseUrl + '/config?' + cmd
let requestOptions = {
method: 'GET',
}

if (this.auth_required) {
if (this.session === null) {
await this.authenticate()
}
requestOptions['headers'] = { cookie: this.session }
}

try {
const response = await fetch(requestUrl, this.requestOptions)
let response = await fetch(requestUrl, requestOptions)
if (response.status == 404 && this.auth_required) {
// in the case of a 404 with auth required most likely case is session expiry
// reauthenticate and try again
await this.authenticate()
response = await fetch(requestUrl, requestOptions)
}
if (!response.ok) {
this.instance.log('error', 'api call: bad response from device: ' + JSON.stringify(response))
return {
status: 'failed',
response: 'Device returned a bad response: ' + response.statusText,
Expand All @@ -26,6 +76,7 @@ class Helo {
response: await response.json(),
}
} catch (err) {
this.instance.log('error', 'api call: An error occured: ' + JSON.stringify(err))
return {
status: 'failed',
response: String(err),
Expand Down
46 changes: 23 additions & 23 deletions src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ module.exports = {
let self = this // required to have referenec to outer `this`
let actions = {}

const sendCommand = (cmd) => {
const sendCommand = async (cmd) => {
let self = this
let prefix = 'action=set&paramid=eParamID_'
if (cmd !== undefined) {
try {
const result = self.connection.sendRequest(prefix + cmd)
self.log('debug', 'Command result: ' + JSON.stringify(result))
const result = await self.connection.sendRequest(prefix + cmd)
self.log('debug', 'action call: Command result: ' + JSON.stringify(result))

if (result.status === 'success') {
self.updateStatus(InstanceStatus.Ok)
} else {
self.updateStatus(InstanceStatus.ConnectionFailure, 'Failed to connect to device')
self.updateStatus(InstanceStatus.ConnectionFailure, 'Failed to connect to device: ' + result.response)
}
} catch (error) {
let errorText = String(error)
Expand All @@ -26,7 +26,7 @@ module.exports = {
} else if (errorText.match('ETIMEDOUT') || errorText.match('ENOTFOUND')) {
self.log('error', 'Connection to streamer has timed out...')
} else {
self.log('error', 'An error has occurred when connecting to streamer...')
self.log('error', 'An error has occurred when connecting to streamer: ' + errorText)
}
}
}
Expand All @@ -51,7 +51,7 @@ module.exports = {
],
callback: async (event) => {
let cmd = event.options.command
sendCommand(cmd)
await sendCommand(cmd)
},
}

Expand All @@ -66,7 +66,7 @@ module.exports = {
} else {
cmd += '2'
}
sendCommand(cmd)
await sendCommand(cmd)
},
}

Expand All @@ -81,7 +81,7 @@ module.exports = {
} else {
cmd += '4'
}
sendCommand(cmd)
await sendCommand(cmd)
},
}

Expand All @@ -104,7 +104,7 @@ module.exports = {
],
callback: async (event) => {
let cmd = event.options.input
sendCommand(cmd)
await sendCommand(cmd)
},
}

Expand All @@ -128,7 +128,7 @@ module.exports = {
],
callback: async (event) => {
let cmd = event.options.input
sendCommand(cmd)
await sendCommand(cmd)
},
}

Expand All @@ -151,7 +151,7 @@ module.exports = {
],
callback: async (event) => {
let cmd = event.options.level
sendCommand(cmd)
await sendCommand(cmd)
},
}

Expand All @@ -174,7 +174,7 @@ module.exports = {
],
callback: async (event) => {
let cmd = 'DelayAudioMs&value=' + event.options.audioDelay
sendCommand(cmd)
await sendCommand(cmd)
},
}

Expand All @@ -183,7 +183,7 @@ module.exports = {
options: [],
callback: async (event) => {
let cmd = 'AVMute&value=1'
sendCommand(cmd)
await sendCommand(cmd)
},
}

Expand All @@ -192,7 +192,7 @@ module.exports = {
options: [],
callback: async (event) => {
let cmd = 'AVMute&value=0'
sendCommand(cmd)
await sendCommand(cmd)
},
}

Expand Down Expand Up @@ -233,7 +233,7 @@ module.exports = {
],
callback: async (event) => {
let cmd = event.options.profileType + event.options.profileNum
sendCommand(cmd)
await sendCommand(cmd)
},
}
}
Expand All @@ -250,7 +250,7 @@ module.exports = {
],
callback: async (event) => {
let cmd = 'FilenamePrefix&value=' + event.options.fileName
sendCommand(cmd)
await sendCommand(cmd)
},
}

Expand All @@ -270,7 +270,7 @@ module.exports = {
callback: async (event) => {
let cmd = 'FilenamePrefix&value='
cmd += await self.parseVariablesInString(event.options.name)
sendCommand(cmd)
await sendCommand(cmd)
},
}

Expand All @@ -280,7 +280,7 @@ module.exports = {
callback: async (event) => {
let timeStamp = self.renameTimestamp()
let cmd = 'FilenamePrefix&value=' + timeStamp
sendCommand(cmd)
await sendCommand(cmd)
},
}

Expand Down Expand Up @@ -309,7 +309,7 @@ module.exports = {
],
callback: async (event) => {
let cmd = 'LayoutSelector&value=' + event.options.layout
sendCommand(cmd)
await sendCommand(cmd)
},
}

Expand Down Expand Up @@ -348,8 +348,8 @@ module.exports = {
},
],
callback: async (event) => {
sendCommand('LayoutSelector&value=' + event.options.layout)
//sendCommand('LayoutCommand&value=' + event.options.action);
await sendCommand('LayoutSelector&value=' + event.options.layout)
//await sendCommand('LayoutCommand&value=' + event.options.action);
setTimeout(function () {
sendCommand('LayoutCommand&value=' + event.options.action)
}, 20)
Expand All @@ -361,15 +361,15 @@ module.exports = {
options: [],
callback: async (event) => {
let cmd = 'LayoutCommand&value=1'
sendCommand(cmd)
await sendCommand(cmd)
},
}

/*actionsArr.storeSelectedLayout = {
label: 'Store Selected Layout',
callback: function (action, bank) {
let cmd = 'LayoutCommand&value=2';
sendCommand(cmd);
await sendCommand(cmd);
}
};*/
}
Expand Down
Loading

0 comments on commit 7c97464

Please sign in to comment.