Skip to content

Commit

Permalink
Added multiple RS485 comm port capabilities to njsPC.
Browse files Browse the repository at this point in the history
  • Loading branch information
rstrouse committed Mar 19, 2022
1 parent 4007b1c commit 3d3cc5e
Show file tree
Hide file tree
Showing 10 changed files with 447 additions and 550 deletions.
2 changes: 1 addition & 1 deletion app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export async function initAsync() {
try {
await config.init();
await logger.init();
await conn.init();
await conn.initAsync();
await sys.init();
await state.init();
await webApp.init();
Expand Down
14 changes: 14 additions & 0 deletions config/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,20 @@ class Config {

}
}
public removeSection(section: string) {
let c = this._cfg;
if (section.indexOf('.') !== -1) {
let arr = section.split('.');
for (let i = 0; i < arr.length - 1; i++) {
if (typeof c[arr[i]] === 'undefined')
c[arr[i]] = {};
c = c[arr[i]];
}
section = arr[arr.length - 1];
}
if(typeof c[section] !== 'undefined') delete c[section];
this.update();
}
public setSection(section: string, val) {
let c = this._cfg;
if (section.indexOf('.') !== -1) {
Expand Down
6 changes: 4 additions & 2 deletions controller/Equipment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ interface IPoolSystem {

export class PoolSystem implements IPoolSystem {
public _hasChanged: boolean = false;
public isReady: boolean = false;
constructor() {
this.cfgPath = path.posix.join(process.cwd(), '/data/poolConfig.json');
}
Expand Down Expand Up @@ -142,6 +143,7 @@ export class PoolSystem implements IPoolSystem {
}
else
this.initNixieController();
this.isReady = true;
}
public init() {
let cfg = this.loadConfigFile(this.cfgPath, {});
Expand Down Expand Up @@ -202,15 +204,15 @@ export class PoolSystem implements IPoolSystem {
}

public resetSystem() {
conn.pause();
conn.pauseAll();
this.resetData();
state.resetData();
this.data.controllerType === 'unknown';
state.equipment.controllerType = ControllerType.Unknown;
this.controllerType = ControllerType.Unknown;
state.status = 0;
this.board = BoardFactory.fromControllerType(ControllerType.Unknown, this);
setTimeout(function () { state.status = 0; conn.resume(); }, 0);
setTimeout(function () { state.status = 0; conn.resumeAll(); }, 0);
}
public get controllerType(): ControllerType { return this.data.controllerType as ControllerType; }
public set controllerType(val: ControllerType) {
Expand Down
6 changes: 1 addition & 5 deletions controller/boards/AquaLinkBoard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,7 @@ class AquaLinkConfigQueue extends ConfigQueue {
protected queueItems(cat: number, items: number[] = [0]) { }
public queueChanges() {
this.reset();
if (conn.mockPort) {
logger.info(`Skipping configuration request from OCP because MockPort enabled.`);
} else {
logger.info(`Requesting ${sys.controllerType} configuration`);
}
logger.info(`Requesting ${sys.controllerType} configuration`);
if (this.remainingItems > 0) {
var self = this;
setTimeout(() => { self.processNext(); }, 50);
Expand Down
6 changes: 3 additions & 3 deletions controller/boards/IntelliCenterBoard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -669,14 +669,14 @@ class IntelliCenterConfigQueue extends ConfigQueue {
response: Response.create({ dest:-1, action: 30, payload: [this.curr.category, itm], callback: () => { self.processNext(out); } })
});
logger.verbose(`Requesting config for: ${ConfigCategories[this.curr.category]} - Item: ${itm}`);
setTimeout(conn.queueSendMessage, 50, out);
setTimeout(() => { conn.queueSendMessage(out) }, 50);
} else {
// Now that we are done check the configuration a final time. If we have anything outstanding
// it will get picked up.
state.status = 1;
this.curr = null;
this._processing = false;
if (this._failed) setTimeout(function () { sys.checkConfiguration(); }, 100);
if (this._failed) setTimeout(() => { sys.checkConfiguration(); }, 100);
logger.info(`Configuration Complete`);
sys.board.heaters.updateHeaterServices();
state.cleanupState();
Expand Down Expand Up @@ -815,7 +815,7 @@ class IntelliCenterConfigQueue extends ConfigQueue {
}
this.maybeQueueItems(curr.systemState, ver.systemState, ConfigCategories.systemState, [0]);
logger.info(`Queued ${this.remainingItems} configuration items`);
if (this.remainingItems > 0) setTimeout(function () { self.processNext(); }, 50);
if (this.remainingItems > 0) setTimeout(() => { self.processNext(); }, 50);
else {
this._processing = false;
if (this._newRequest) {
Expand Down
896 changes: 400 additions & 496 deletions controller/comms/Comms.ts

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions controller/comms/messages/Messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export class Message {
// Fields
private static _messageId: number = 0;
public static get nextMessageId(): number { return this._messageId < 80000 ? ++this._messageId : this._messageId = 0; }

public portId = 0; // This will be the target or source port for the message. If this is from or to an Aux RS485 port the value will be > 0.
public timestamp: Date = new Date();
public direction: Direction = Direction.In;
public protocol: Protocol = Protocol.Unknown;
Expand Down Expand Up @@ -186,15 +186,16 @@ export class Inbound extends Message {
public responseFor: number[] = [];
public isProcessed: boolean = false;
public collisions: number = 0;
public rewinds: number = 0;
// Private methods
private isValidChecksum(): boolean {
if (this.protocol === Protocol.Chlorinator || this.protocol === Protocol.AquaLink) return this.checksum % 256 === this.chkLo;
return (this.chkHi * 256) + this.chkLo === this.checksum;
}
public toLog() {
if (this.responseFor.length > 0)
return `{"id":${this.id},"valid":${this.isValid},"dir":"${this.direction}","proto":"${this.protocol}","for":${JSON.stringify(this.responseFor)},"pkt":[${JSON.stringify(this.padding)},${JSON.stringify(this.preamble)},${JSON.stringify(this.header)},${JSON.stringify(this.payload)},${JSON.stringify(this.term)}],"ts": "${Timestamp.toISOLocal(this.timestamp)}"}`;
return `{"id":${this.id},"valid":${this.isValid},"dir":"${this.direction}","proto":"${this.protocol}","pkt":[${JSON.stringify(this.padding)},${JSON.stringify(this.preamble)},${JSON.stringify(this.header)},${JSON.stringify(this.payload)},${JSON.stringify(this.term)}],"ts": "${Timestamp.toISOLocal(this.timestamp)}"}`;
return `{"port:${this.portId || 0} id":${this.id},"valid":${this.isValid},"dir":"${ this.direction } ","proto":"${ this.protocol } ","for":${JSON.stringify(this.responseFor)},"pkt":[${JSON.stringify(this.padding)},${JSON.stringify(this.preamble)},${JSON.stringify(this.header)},${JSON.stringify(this.payload)},${JSON.stringify(this.term)}],"ts": "${ Timestamp.toISOLocal(this.timestamp) } "}`;
return `{"port: ${this.portId || 0} id":${this.id},"valid":${this.isValid},"dir":"${this.direction}","proto":"${this.protocol}","pkt":[${JSON.stringify(this.padding)},${JSON.stringify(this.preamble)},${JSON.stringify(this.header)},${JSON.stringify(this.payload)},${JSON.stringify(this.term)}],"ts": "${Timestamp.toISOLocal(this.timestamp)}"}`;
}
private testChlorHeader(bytes: number[], ndx: number): boolean {
// if packets have 16,2 (eg status=16,2,29) in them and they come as partial packets, they would have
Expand Down Expand Up @@ -247,6 +248,7 @@ export class Inbound extends Message {
this.isValid = true;

this.collisions++;
this.rewinds++;
logger.info(`rewinding message collision ${this.collisions} ${ndx} ${bytes.length} ${JSON.stringify(buff)}`);
this.readPacket(buff);
return ndx;
Expand Down Expand Up @@ -327,6 +329,7 @@ export class Inbound extends Message {
this.preamble = [];
this.header = [];
this.collisions++;
this.rewinds++;
return ndxHeader + 1;
}
break;
Expand Down
1 change: 1 addition & 0 deletions defaultConfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"controller": {
"comms": {
"portId": 0,
"enabled": true,
"rs485Port": "/dev/ttyUSB0",
"mockPort": false,
Expand Down
36 changes: 0 additions & 36 deletions web/Server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -618,42 +618,6 @@ export class HttpServer extends ProtoServer {
self._sockets = await self.sockServer.fetchSockets();
});
sock.on('echo', (msg) => { sock.emit('echo', msg); });
/* sock.on('receivePacketRaw', function (incomingPacket: any[]) {
//var str = 'Add packet(s) to incoming buffer: ';
logger.silly('User request (replay.html) to RECEIVE packet: %s', JSON.stringify(incomingPacket));
for (var i = 0; i < incomingPacket.length; i++) {
conn.buffer.pushIn(Buffer.from(incomingPacket[i]));
// str += JSON.stringify(incomingPacket[i]) + ' ';
}
//logger.info(str);
});
sock.on('replayPackets', function (inboundPkts: number[][]) {
// used for replay
logger.debug(`Received replayPackets: ${inboundPkts}`);
inboundPkts.forEach(inbound => {
conn.buffer.pushIn(Buffer.from([].concat.apply([], inbound)));
// conn.queueInboundMessage([].concat.apply([], inbound));
});
});
sock.on('sendPackets', function (bytesToProcessArr: number[][]) {
// takes an input of bytes (src/dest/action/payload) and sends
if (!bytesToProcessArr.length) return;
logger.silly('User request (replay.html) to SEND packet: %s', JSON.stringify(bytesToProcessArr));
do {
let bytesToProcess: number[] = bytesToProcessArr.shift();
// todo: logic for chlor packets
let out = Outbound.create({
source: bytesToProcess.shift(),
dest: bytesToProcess.shift(),
action: bytesToProcess.shift(),
payload: bytesToProcess.splice(1, bytesToProcess[0])
});
conn.queueSendMessage(out);
} while (bytesToProcessArr.length > 0);
}); */
sock.on('sendOutboundMessage', (mdata) => {
let msg: Outbound = Outbound.create({});
Object.assign(msg, mdata);
Expand Down
21 changes: 17 additions & 4 deletions web/services/config/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,16 @@ export class ConfigRoute {
return res.status(200).send(opts);
});
app.get('/config/options/rs485', (req, res) => {
let opts = {
port: config.getSection('controller.comms', { enabled: false, netConnect: false }),
stats: conn.buffer.counter
};
let opts = { ports: [] }
let cfg = config.getSection('controller');
for (let section in cfg) {
if (section.startsWith('comms')) {
let cport = extend(true, { enabled: false, netConnect: false }, cfg[section]);
let port = conn.findPortById(cport.portId || 0);
if (typeof port !== 'undefined') cport.stats = port.stats;
opts.ports.push(cport);
}
}
return res.status(200).send(opts);
});
app.get('/config/options/circuits', async (req, res, next) => {
Expand Down Expand Up @@ -756,6 +762,13 @@ export class ConfigRoute {
}
catch (err) { next(err); }
});
app.delete('/app/rs485Port', async (req, res, next) => {
try {
let port = await conn.deleteAuxPort(req.body);
return res.status(200).send(port);
}
catch (err) { next(err); }
});
app.get('/app/config/startPacketCapture', (req, res) => {
startPacketCapture(true);
return res.status(200).send('OK');
Expand Down

0 comments on commit 3d3cc5e

Please sign in to comment.