mirror of
https://github.com/daniviga/django-ram.git
synced 2025-08-04 13:17:50 +02:00
188 lines
4.3 KiB
JavaScript
188 lines
4.3 KiB
JavaScript
/* This is part of the DCC++ EX Project for model railroading and more.
|
|
For licence information, please see index.html.
|
|
For more information, see us at dcc-ex.com.
|
|
|
|
emulator.js
|
|
|
|
Allows the software to operate without a Command Station attached. This
|
|
file manages the correct response that a Command Station would provide.
|
|
*/
|
|
/**
|
|
* Utility function can be moved when we can import files
|
|
* @description Removes control characters "<", ">" and "\n"
|
|
* @param {string} packet
|
|
* @return {string}
|
|
*/
|
|
function removeControlCharacters(packet) {
|
|
return [...packet].filter(char => !["<", ">", "\n"].includes(char)).join("")
|
|
}
|
|
|
|
/**
|
|
* Utility function can be moved when we can import files
|
|
* @description Finds the first non-blank character after control characters are removed
|
|
* @param {string} packet
|
|
* @return {string}
|
|
*/
|
|
function extractPacketKey(packet) {
|
|
const cleanedPacket = [...removeControlCharacters(packet)]
|
|
return cleanedPacket.find(char => char !== " ");
|
|
}
|
|
|
|
class Emulator {
|
|
constructor({logger}) {
|
|
this.turnoutEmulator = new TurnoutEmulator()
|
|
this.logger = logger
|
|
}
|
|
|
|
/**
|
|
* @param {string} packet
|
|
*/
|
|
write(packet) {
|
|
if (packet === "<credits>") {
|
|
console.log("Credits")
|
|
return credits()
|
|
}
|
|
|
|
let packetKey = extractPacketKey(packet);
|
|
|
|
switch (packetKey) {
|
|
// Cab control
|
|
case ("t"):
|
|
this.logger('[RECEIVE] '+ this.#cabControlCommand(packet))
|
|
break;
|
|
|
|
// Track power off
|
|
case ('0') :
|
|
this.logger('[RECEIVE] '+ this.#powerOffCommand(packet));
|
|
break;
|
|
|
|
// Track power on
|
|
case ('1'):
|
|
this.logger('[RECEIVE] '+ this.#powerOnCommand(packet));
|
|
break;
|
|
|
|
// New cab functions
|
|
case ('F'):
|
|
this.logger('[RECEIVE] '+ this.#cabFunctionCommand(packet));
|
|
break;
|
|
|
|
// Legacy cab functions
|
|
case ('f'):
|
|
|
|
this.logger('[RECEIVE] '+ this.#cabFunctionCommand(packet, true));
|
|
break;
|
|
|
|
// Turnouts
|
|
case ('T'): //Not fully finished
|
|
this.logger('[RECEIVE] '+ this.#turnoutCommand(packet, this.turnoutEmulator))
|
|
break
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string} packet
|
|
* @return {string}
|
|
*/
|
|
#cabControlCommand(packet) {
|
|
const splitPacket = packet.split(" ");
|
|
return 'T 1 ' + splitPacket[3] + ' ' + splitPacket[4].substring(0, splitPacket[4].length - 2);
|
|
}
|
|
|
|
/**
|
|
* @param {string} packet
|
|
* @return {string}
|
|
*/
|
|
#powerOffCommand(packet) {
|
|
return 'p0';
|
|
}
|
|
|
|
/**
|
|
* @param {string} packet
|
|
* @return {string}
|
|
*/
|
|
#powerOnCommand(packet) {
|
|
return 'p1';
|
|
}
|
|
|
|
/**
|
|
* @param {string} packet
|
|
* @param {boolean} legacy
|
|
* @return number
|
|
*/
|
|
#cabFunctionCommand(packet, legacy = false) {
|
|
return NaN;
|
|
}
|
|
|
|
/**
|
|
* @param {string} packet
|
|
* @param {TurnoutEmulator} turnoutEmulator
|
|
* @return {string}
|
|
*/
|
|
#turnoutCommand(packet, turnoutEmulator = new TurnoutEmulator()) {
|
|
const splitPacket = removeControlCharacters(packet).split(" ");
|
|
|
|
if (splitPacket.length === 4) {
|
|
// Adds a Turnout
|
|
return turnoutEmulator.addTurnout(new Turnout(packet))
|
|
} else if (splitPacket.length === 2) {
|
|
// Removes a Turnout
|
|
return turnoutEmulator.removeTurnout(splitPacket[1])
|
|
} else if (splitPacket.length === 1) {
|
|
// Reads Turnouts
|
|
return turnoutEmulator.turnouts
|
|
}
|
|
}
|
|
}
|
|
|
|
class TurnoutEmulator {
|
|
/**
|
|
* @type {[]}
|
|
*/
|
|
#turnouts = []
|
|
|
|
/**
|
|
* @return {string|string[]}
|
|
*/
|
|
get turnouts() {
|
|
if (!this.#turnouts.length) {
|
|
return 'X'
|
|
}
|
|
|
|
return this.#turnouts.map(turnout => `H ${turnout.id} ${turnout.address} ${turnout.subaddress} ${turnout.thrown}`)
|
|
}
|
|
|
|
/**
|
|
* @param {*} turnout
|
|
* @return {string}
|
|
*/
|
|
addTurnout(turnout) {
|
|
this.#turnouts = [...this.#turnouts, turnout]
|
|
console.log(this.#turnouts);
|
|
return '<O>';
|
|
}
|
|
|
|
/**
|
|
* @param {string} turnoutId
|
|
* @return {string}
|
|
*/
|
|
removeTurnout(turnoutId) {
|
|
this.#turnouts = this.#turnouts.filter(turnout => turnout.id !== turnoutId);
|
|
console.log(this.#turnouts);
|
|
return 'O';
|
|
}
|
|
}
|
|
|
|
class Turnout {
|
|
constructor(packet) {
|
|
let [_key, id, address, subaddress] = removeControlCharacters(packet).split(" ");
|
|
|
|
this.id = id
|
|
this.address = address
|
|
this.subaddress = subaddress
|
|
this.thrown = 0
|
|
}
|
|
}
|