Skip to content

Commit

Permalink
- Adds ability to generate config from CSV files
Browse files Browse the repository at this point in the history
- Fixes parsing issue when tones specified in string format
  • Loading branch information
Kevin Dolan committed Mar 28, 2022
1 parent 6ce3f21 commit 9c098a0
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 7 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ config/local*
build/*
*.wav
license.txt
config.csv

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
Expand Down
67 changes: 67 additions & 0 deletions bin/csvToConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
const config = require("config");
const log = require('../util/logger');
const csv = require('fast-csv');
const fs = require('fs');
const path = require('path');
const defaultConfig = require('../config/default.json');

const DEFAULT_DETECTOR = {
"name": "",
"tones": [],
"matchThreshold": 6,
"tolerancePercent": 0.02,
"notifications": {
"preRecording": {
"pushbullet": [],
"webhooks": [],
"externalCommands": [],
"emails": []
},
"postRecording": {
"pushbullet": [],
"webhooks": [],
"externalCommands": [],
"emails": []
}
}
}

async function csvToConfig({inputPath="./config/config.csv", outputPath="config-from-csv.json"}={}){
const rows = await getRecords({inputPath});
const config = Object.assign({}, defaultConfig);
config.detection.detectors = [];
rows.forEach(r => {
const detector = JSON.parse(JSON.stringify(DEFAULT_DETECTOR));
detector.name = r.name;
detector.tones.push(Number(r.tone1));
if(r.tone2)
detector.tones.push(Number(r.tone2));
if(r.preRecordingEmailList)
detector.notifications.preRecording.emails.push({
"to": r.preRecordingEmailList,
"subject": r.preRecordingEmailSubject.replace("{name}", r.name),
"text": "Tone Received %d"
})
if(r.postRecordingEmailList)
detector.notifications.postRecording.emails.push({
"to": r.postRecordingEmailList,
"subject": r.postRecordingEmailSubject.replace("{name}", r.name),
"text": "Tone Received %d"
});
config.detection.detectors.push(detector);
});
fs.writeFileSync(outputPath, JSON.stringify(config, null, 4));
}

async function getRecords({inputPath}){
return new Promise((resolve, reject) => {
const rows = [];
fs.createReadStream(path.resolve(__dirname, "../", inputPath))
.pipe(csv.parse({ headers: true }))
.on('error', error => reject(error))
.on('data', row => rows.push(row))
.on('end', rowCount => resolve(rows));
} )
}

module.exports = {csvToConfig};
6 changes: 5 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ setupProgram();
const {checkLicense} = require("./util/licence");

const {toneDetector} = require('./bin/toneDetector');
const {csvToConfig} = require('./bin/csvToConfig');
const {fdToneNotify} = require('./bin/fdToneNotify');
const {testNotifications} = require('./bin/testNotifications');
const log = require('./util/logger');
Expand All @@ -21,6 +22,7 @@ function setupProgram(){
'is monitored. When a multi tone is detected the result is logged to the console. Use this mode to determine the frequencies to monitor and ' +
'enter the results in the "tones" parameter for the corresponding department.')
.option('--test-notifications', 'Send test notifications')
.option('--csv-to-config', 'Send test notifications')
.option('--debug', 'Overrides FD_LOG_LEVEL environment var forcing the log level to debug')
.option('--silly', 'Overrides FD_LOG_LEVEL environment var forcing the log level to silly')
.option('--instance-name', 'Overrides NODE_APP_INSTANCE environment allowing different config files for different instances running' +
Expand All @@ -44,7 +46,9 @@ async function main(){
const options = program.opts();
populateSecretsEnvVar({secretsPath: options.secretsFile, forceSecretsFile: options.forceSecretsFile});

if(options.allToneDetector)
if(options.csvToConfig)
csvToConfig();
else if(options.allToneDetector)
toneDetector({webServer: options.webServer});
else if(options.testNotifications)
testNotifications();
Expand Down
24 changes: 19 additions & 5 deletions obj/ToneDetector.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ const {arrayAverage} = require("../util/util");

class ToneDetector{
constructor({tone, tolerancePercent, matchThreshold}) {
this.tone = tone;
const _tone = Number(tone);
if(isNaN(_tone)){
log.error(`The provided tone ${tone} is not a valid number.`);
throw new Error(`${tone} is not a valid number`);
}

this.tone = _tone;
this.tolerancePercent = tolerancePercent;
this.matchThreshold = matchThreshold;

Expand Down Expand Up @@ -46,7 +52,7 @@ class ToneDetector{

if(this.__isMatch(value)){
this._matches.push(value);
log[this.__matchLogLevel](chalk.yellow(`Detector ${this.tone}Hz ±${this.tolerancePercent * 100}% ` +
log[this.__matchLogLevel](chalk.yellow(`Detector ${this.tone}Hz ±${this.tolerancePercent * 100}% [${this.__lowerLimit}Hz - ${this.__upperLimit}Hz] ` +
`Matches @ ${value}Hz. Count ${this._matchCount}/${this.matchThreshold} `));
return {match: true, warn: false};
}
Expand All @@ -61,9 +67,17 @@ class ToneDetector{
}

__isMatch(value){
const upperLimit = this.tone + (this.tone * this.tolerancePercent);
const lowerLimit = this.tone - (this.tone * this.tolerancePercent);
return value >= lowerLimit && value <= upperLimit;
return value >= this.__lowerLimit && value <= this.__upperLimit;
}

get __lowerLimit(){
return this.tone - (this.tone * this.tolerancePercent);
}

get __upperLimit(){
const value = this.tone + (this.tone * this.tolerancePercent);
if(value > 5000)
console.log();
}

get __matchLogLevel(){
Expand Down
76 changes: 76 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"dotenv": "^8.2.0",
"expect": "^26.6.2",
"express": "^4.17.1",
"fast-csv": "^4.3.6",
"fluent-ffmpeg": "^2.1.2",
"form-data": "^3.0.0",
"helmet": "^3.23.3",
Expand Down
5 changes: 4 additions & 1 deletion test/obj/ToneDetector.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ describe("ToneDetector", function() {
});

it("should be able process values and progress through proper states", async function() {
const VALUES = [400, 1001, 1024, 985, 988, 985, 1004, 400, 400, 400, 988];
const VALUES = [0, 1001, 1024, 985, 988, 985, 1004, 400, 400, 400, 988];
const tolerance = DEFAULT_PARAMS.tone * DEFAULT_PARAMS.tolerancePercent ;
VALUES[0] = DEFAULT_PARAMS.tone - tolerance - 1;

const detector = new ToneDetector(DEFAULT_PARAMS);

expect(detector.state).equals(MATCH_STATES.WAITING);
Expand Down

0 comments on commit 9c098a0

Please sign in to comment.