Skip to content
Open
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
33 changes: 33 additions & 0 deletions src/controller/controller.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,39 @@ describe("Controller Class", () => {
}).toThrow();
});

it("Scan Min Overhead Percent", () => {
const plc = new Controller();
expect(plc.scan_min_overhead_percent).toBe(20);

plc.scan_min_overhead_percent = 40;
expect(plc.scan_min_overhead_percent).not.toBe(20);
expect(plc.scan_min_overhead_percent).toBe(40);

expect(() => {
plc.scan_min_overhead_percent = null;
}).toThrow();

expect(() => {
plc.scan_min_overhead_percent = undefined;
}).toThrow();

expect(() => {
plc.scan_min_overhead_percent = "hello";
}).toThrow();
});

it("Scan Read Only", () => {
const plc = new Controller();
expect(plc.scan_read_only).toBeFalsy();

plc.scan_read_only = true;
expect(plc.scan_read_only).toBeTruthy();


plc.scan_read_only = false;
expect(plc.scan_read_only).toBeFalsy();
});

it("Scanning", () => {
const plc = new Controller();
expect(plc.scanning).toBeFalsy();
Expand Down
107 changes: 90 additions & 17 deletions src/controller/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ class Controller extends ENIP {
},
subs: new TagGroup(compare),
scanning: false,
scan_rate: 200 //ms
scan_rate: 200, //ms
scan_min_overhead_percent: 0.2,
scan_read_only: false
};

this.workers = {
Expand Down Expand Up @@ -64,6 +66,47 @@ class Controller extends ENIP {
this.state.scan_rate = Math.trunc(rate);
}

/**
* Returns the Scan Min Overhead Percent for the Scan method
*
* @memberof Controller
* @returns {number} percent
*/
get scan_min_overhead_percent() {
return this.state.scan_min_overhead_percent * 100;
}

/**
* Sets the Scan Min Overhead Percent for the Scan method
*
* @memberof Controller
*/
set scan_min_overhead_percent(percent) {
if (typeof percent !== "number") throw new Error("scan_min_overhead_percent must be of Type <number>");
if (percent < 1 | percent > 99) throw new Error("scan_min_overhead_percent must be >=1 and <=99 ");
this.state.scan_min_overhead_percent = percent / 100;
}

/**
* Returns the status of the Scan Read Only property
*
* @memberof Controller
* @returns {boolean} percent
*/
get scan_read_only() {
return this.state.scan_read_only;
}

/**
* Sets the status of the Scan Read Only property
*
* @memberof Controller
*/
set scan_read_only(readOnly) {
if (typeof readOnly !== "boolean") throw new Error("scan_min_overhead_percent must be of Type <boolean>");
this.state.scan_read_only = readOnly;
}

/**
* Get the status of Scan Group
*
Expand Down Expand Up @@ -396,15 +439,42 @@ class Controller extends ENIP {
this.state.subs.add(tag);
}

/**
* Removes Tag from Subscription Group
*
* @param {Tagany} tag
* @memberof Controller
*/
unsubscribe(tag) {
this.state.subs.remove(tag);
}

/**
* Queries Tag in Subscription Group
*
* @param {Tagany} tag
* @memberof Controller
*/
isSubscribed(tag) {
return this.state.subs.contains(tag);
}

/**
* Begin Scanning Subscription Group
*
* @memberof Controller
*/
async scan() {
async scan(readOnly = false) {
this.state.scanning = true;

this.state.scan_read_only = readOnly;

let startTime = 0;
let elapsedTime = 0;

while (this.state.scanning) {
startTime = Date.now();

await this.workers.group
.schedule(this._readTagGroup.bind(this), [this.state.subs], {
priority: 10,
Expand All @@ -417,21 +487,24 @@ class Controller extends ENIP {
throw e;
}
});

await this.workers.group
.schedule(this._writeTagGroup.bind(this), [this.state.subs], {
priority: 10,
timestamp: new Date()
})
.catch(e => {
if (e.message) {
throw new Error(`<SCAN_GROUP>\n ${e.message}`);
} else {
throw e;
}
});

await delay(this.state.scan_rate);

if(!this.state.scan_read_only){
await this.workers.group
.schedule(this._writeTagGroup.bind(this), [this.state.subs], {
priority: 10,
timestamp: new Date()
})
.catch(e => {
if (e.message) {
throw new Error(`<SCAN_GROUP>\n ${e.message}`);
} else {
throw e;
}
});
}

elapsedTime = Date.now() - startTime;
await delay(Math.max(this.state.scan_rate - elapsedTime, elapsedTime / (1 - this.state.scan_min_overhead_percent) * (this.state.scan_min_overhead_percent)));
}
}

Expand Down
11 changes: 11 additions & 0 deletions src/tag-group/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@ class TagGroup extends EventEmitter {
if (this.state.tags[tag.instance_id]) delete this.state.tags[tag.instance_id];
}

/**
* Queries Tag Group for Tag
*
* @param {Tag} tag - Tag to be Queried in Group
* @memberof TagGroup
*/
contains(tag) {
if(this.state.tags[tag.instance_id]) return true;
return false;
}

/**
* Iterable, Allows user to Iterate of each Tag in Group
*
Expand Down
18 changes: 18 additions & 0 deletions src/tag-group/tag-group.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,22 @@ describe("Tag Class", () => {
expect(group.generateWriteMessageRequests()).toMatchSnapshot();
});
});

describe("Add, Remove, Query Tag Methods", () => {
it("Adds, Removes, Queries Tags", () => {
const tag = new Tag("tag", "prog", Types.DINT);

const group = new TagGroup();

expect(group.contains(tag)).toBeFalsy();

group.add(tag);

expect(group.contains(tag)).toBeTruthy();

group.remove(tag);

expect(group.contains(tag)).toBeFalsy();
});
});
});