Files
2026-06-17 14:00:51 +02:00

409 lines
14 KiB
JavaScript

var throttleSpeed = 0; // The speed of the train
var throttleForward = true; // The direction of the train
var locoPos = 100; // The position of the loco
// var locoPos = 700; // The position of the loco
// var locoPos = 830; // The position of the loco
// var locoPos = 982; // The position of the loco
// var locoPos = 765; // The position of the loco
// var locoPos = 707; // The position of the loco
var selectDivergedTrack = false; // Should the train go to crane track instead of harbour track?
var turnoutThrown = true; // Is the turnout thrown?
var diveringTrackAngle = 0; // The angle of crane track?
var turnoutPos = 0; // Where does the diverging track starts?
var carPos = 0; // Position of the car
var carIsFilled = false; // Is the car loaded with coal?
var craneX = 737; // Crane X position
var craneY = 540; // Crane Y position
var craneMinAngle = -160; // Minimum angle of the crane
var craneMaxAngle = 90; // Maximum angle of the crane
var craneAngle = craneMinAngle; // Current angle of crane
// var craneAngle = 59; // Current angle of crane
var commandedCraneAngle = -1; // Commanded angle of the crane
//var craneUpDown = -1; // Current crane arm up/down (up = 100, down = 0)
var craneUpDown = 100; // Current crane arm up/down (up = 100, down = 0)
var commandedCraneUpDown = 0; // Commanded crane arm up/down (up = 100, down = 0)
var craneBucketOpenClosed = -1; // Current crane bucket open/closed (open = 0, closed = 100)
var commandedCraneBucketOpenClosed = 0; // Commanded crane arm up/down (open = 0, closed = 100)
var craneBucketFilled = false; // Is the crane bucket filled?
var sensor1_active = false;
var sensor1_Pos = 30;
var sensor2_active = false;
var sensor2_Pos = 760;
var sensor3_active = false;
var sensor3_Pos = 914;
var locoLength = 450 * 0.3; // 0.3 is the scale factor
var carLength = 437 * 0.3; // 0.3 is the scale factor
// set the jmri global variable to null
var jmri = null;
$(document).ready(function() {
calculateDivergingTrackAngle();
jmri = $.JMRI({
open: function() {
jmri.getMemory("IM_7_1"); // Crane angle left - right, commanded position
jmri.getMemory("IM_7_2"); // Crane angle left - right, actual position
jmri.getMemory("IM_7_3"); // Crane bucket up - down, commanded position
jmri.getMemory("IM_7_4"); // Crane bucket up - down, actual position
jmri.getMemory("IM_7_5"); // Crane bucket closed - open, commanded position
jmri.getMemory("IM_7_6"); // Crane bucket closed - open, actual position
jmri.getTurnout("IT_7_1"); // Turnout
jmri.getSensor("IS_7_1"); // Sensor at turnout
jmri.getSensor("IS_7_2"); // Sensor at ship
jmri.getSensor("IS_7_3"); // Sensor at coal yard
// console.log("Throttle data: ");
// console.log("MyLoco throttle");
throttle = {"name": "MyLoco", "address": 21};
result = jmri.getThrottle(throttle);
},
memory: function(name, value, data) {
if (name == "IM_7_1") rotateCrane(value);
if (name == "IM_7_3") liftLowerCrane(value);
if (name == "IM_7_5") openCloseCraneBucket(value);
},
turnout: function(name, value, data) {
turnoutThrown = (value == 4);
if (turnoutThrown) {
turnout_1_1.setAttribute("visibility", "hidden");
turnout_1_2.setAttribute("visibility", "hidden");
turnout_2_1.setAttribute("visibility", "visible");
turnout_2_2.setAttribute("visibility", "visible");
} else {
turnout_1_1.setAttribute("visibility", "visible");
turnout_1_2.setAttribute("visibility", "visible");
turnout_2_1.setAttribute("visibility", "hidden");
turnout_2_2.setAttribute("visibility", "hidden");
}
},
throttle: function(throttle, data) {
if (typeof data.speed !== 'undefined') {
// console.log("Speed: ", data.speed);
if (data.speed >= 0) throttleSpeed = data.speed;
else throttleSpeed = 0;
}
if (typeof data.forward !== 'undefined') {
// console.log("Forward: ", data.forward);
throttleForward = data.forward;
}
// for (var key in data2) {
// console.log(key);
// }
},
// when the JMRI object receives a power update, call this
// function, regardless of source of update
power: function(state) {
power = state;
// console.log("Power: "+power);
/*
switch (power) {
case jmri.UNKNOWN:
$('#powerImg').prop('src', "/images/PowerGrey.png");
$('#powerImg').prop('alt', "Unknown");
$('#powerImg').prop('title', "Unknown");
break;
case jmri.POWER_ON:
$('#powerImg').prop('src', "/images/PowerGreen.png");
$('#powerImg').prop('alt', "Powered On");
$('#powerImg').prop('title', "Powered On");
break;
case jmri.POWER_OFF:
$('#powerImg').prop('src', "/images/PowerRed.png");
$('#powerImg').prop('alt', "Powered Off");
$('#powerImg').prop('title', "Powered Off");
break;
}
*/
}
});
// trigger the initial connection to the JMRI server; this
// method call ensures the jmri.open() method is called after
// a timeout to begin using fall back methods for monitoring
// items on the JMRI server even if a WebSocket connection
// cannot be established
jmri.connect();
// make it possible to click on the power button to turn track
// power on or off without using a javascript URI
// $('#powerImg').click(function(event) {
// jmri.setPower((power === jmri.POWER_ON) ? jmri.POWER_OFF : jmri.POWER_ON);
// });
});
function calculateDivergingTrackAngle()
{
var track = document.getElementById('DivergingCenterRail');
var x1 = parseFloat(track.getAttributeNS(null, 'x1'));
var y1 = parseFloat(track.getAttributeNS(null, 'y1'));
var x2 = parseFloat(track.getAttributeNS(null, 'x2'));
var y2 = parseFloat(track.getAttributeNS(null, 'y2'));
turnoutPos = x1;
var x = x2 - x1;
var y = y2 - y1;
diveringTrackAngle = Math.atan(y/x);
}
function moveLocoOrCar(item, pos)
{
var x = pos;
var y = 0;
var rotate = 0;
if (selectDivergedTrack && (pos > turnoutPos)) {
var posAfterTurnout = pos - turnoutPos;
rotate = diveringTrackAngle * 360 / 2 / Math.PI;
x = turnoutPos + posAfterTurnout * Math.cos(diveringTrackAngle);
y = posAfterTurnout * Math.sin(diveringTrackAngle);
}
var data = "translate("+x+","+(y+200)+") scale(0.3) rotate("+rotate+")";
item.setAttribute("transform", data);
}
function checkSensors()
{
var sensorTriggered = false;
sensorTriggered = (((locoPos-locoLength/2) <= sensor1_Pos) && ((locoPos+locoLength/2) >= sensor1_Pos));
sensorTriggered |= (((carPos-carLength/2) <= sensor1_Pos) && ((carPos+carLength/2) >= sensor1_Pos));
if (sensorTriggered) {
// Sensor 1 triggered
if (true || !sensor1_active) {
sensor1_active = true;
jmri.setSensor("IS_7_1", 2);
}
} else {
// Sensor 1 not triggered
if (true || sensor1_active) {
sensor1_active = false;
jmri.setSensor("IS_7_1", 4);
}
}
sensorTriggered = false;
if (!selectDivergedTrack) {
sensorTriggered = (((locoPos-locoLength/2) <= sensor2_Pos) && ((locoPos+locoLength/2) >= sensor2_Pos));
sensorTriggered |= (((carPos-carLength/2) <= sensor2_Pos) && ((carPos+carLength/2) >= sensor2_Pos));
}
if (sensorTriggered) {
// Sensor 2 triggered
if (true || !sensor2_active) {
sensor2_active = true;
jmri.setSensor("IS_7_2", 2);
}
} else {
// Sensor 2 not triggered
if (true || sensor2_active) {
sensor2_active = false;
jmri.setSensor("IS_7_2", 4);
}
}
sensorTriggered = false;
if (selectDivergedTrack) {
sensorTriggered = (((locoPos-locoLength/2) <= sensor3_Pos) && ((locoPos+locoLength/2) >= sensor3_Pos));
sensorTriggered |= (((carPos-carLength/2) <= sensor3_Pos) && ((carPos+carLength/2) >= sensor3_Pos));
}
if (sensorTriggered) {
// Sensor 3 triggered
if (true || !sensor3_active) {
sensor3_active = true;
jmri.setSensor("IS_7_3", 2);
}
} else {
// Sensor 3 not triggered
if (true || sensor3_active) {
sensor3_active = false;
jmri.setSensor("IS_7_3", 4);
}
}
}
window.setInterval(runTrain, 50);
function runTrain()
{
jmri.setSensor("IS_7_2", "ACTIVE");
if (throttleSpeed != 0)
{
if (carPos < turnoutPos) selectDivergedTrack = turnoutThrown;
var speed = throttleSpeed;
if (throttleForward) speed = -speed;
locoPos += speed*2;
carPos = locoPos + 150;
var loco = document.getElementById('LocoHandle');
moveLocoOrCar(loco, locoPos);
var car = document.getElementById('CarHandle');
moveLocoOrCar(car, carPos);
} else {
if ((carPos >= 591) && (carPos <= 858) && !selectDivergedTrack) {
// Unload car
carIsFilled = false;
var carLoad = document.getElementById('CarLoad');
carLoad.setAttribute("visibility", "hidden");
}
}
// Check the sensors
checkSensors();
// Check the crane
checkCrane();
}
function rotateCrane(value) {
commandedCraneAngle = (craneMaxAngle - craneMinAngle) * value / 100 + craneMinAngle;
if (commandedCraneAngle < craneMinAngle) commandedCraneAngle = craneMinAngle;
if (commandedCraneAngle > craneMaxAngle) commandedCraneAngle = craneMaxAngle;
}
function liftLowerCrane(value) {
commandedCraneUpDown = value;
if (commandedCraneUpDown < 0) commandedCraneUpDown = 0;
if (commandedCraneUpDown > 100) commandedCraneUpDown = 100;
}
function openCloseCraneBucket(value) {
commandedCraneBucketOpenClosed = value;
if (commandedCraneBucketOpenClosed < 2) commandedCraneBucketOpenClosed = 2;
if (commandedCraneBucketOpenClosed > 100) commandedCraneBucketOpenClosed = 100;
}
function checkLoadingOfCar()
{
// If here, the crane bucket is filled, but the bucket is opened to drop its coal
// Check if crane bucket is close to the track
if ((craneAngle < 0) || (craneAngle > 60)) return;
// Calculate where the crane bucket are relative to the track
// 857 = position of the car when the car is below the crane bucket and the crane arm is
// perpendicular to the track.
var cranePosRelativeToTrack = Math.sin((craneAngle-30) * 2 * Math.PI / 360) * 2 * 57 + 857;
if (selectDivergedTrack && (Math.abs(carPos - cranePosRelativeToTrack) < carLength/3)) {
carIsFilled = true;
var carLoad = document.getElementById('CarLoad');
carLoad.setAttribute("visibility", "visible");
}
}
function checkCrane()
{
var lastAngle = craneAngle;
if (craneUpDown >= 80) {
if (commandedCraneAngle < craneAngle) {
craneAngle -= 1;
if (craneAngle < commandedCraneAngle) craneAngle = commandedCraneAngle;
}
if (commandedCraneAngle > craneAngle) {
craneAngle += 1;
if (craneAngle > commandedCraneAngle) craneAngle = commandedCraneAngle;
}
}
if (craneAngle != lastAngle) {
var item = document.getElementById('CraneHandle');
var data = "translate("+craneX+","+(craneY)+") scale(0.3) rotate("+craneAngle+")";
item.setAttribute("transform", data);
anglePercent = (craneAngle - craneMinAngle) / (craneMaxAngle - craneMinAngle) * 100;
jmri.setMemory("IM_7_2", anglePercent);
}
var lastCraneUpDown = craneUpDown;
if (commandedCraneUpDown < craneUpDown) {
craneUpDown -= 1;
if (craneUpDown < commandedCraneUpDown) craneUpDown = commandedCraneUpDown;
}
if (commandedCraneUpDown > craneUpDown) {
craneUpDown += 1;
if (craneUpDown > commandedCraneUpDown) craneUpDown = commandedCraneUpDown;
}
if (craneUpDown != lastCraneUpDown) {
var item = document.getElementById('CraneUpDown');
var data = "translate(0,0) rotate("+((100-craneUpDown)*1.80)+")";
item.setAttribute("transform", data);
jmri.setMemory("IM_7_4", craneUpDown);
}
var lastCraneBucketOpenClosed = craneBucketOpenClosed;
if (commandedCraneBucketOpenClosed < craneBucketOpenClosed) {
craneBucketOpenClosed -= 1;
if (craneBucketOpenClosed < commandedCraneBucketOpenClosed) craneBucketOpenClosed = commandedCraneBucketOpenClosed;
if (craneBucketFilled && (craneBucketOpenClosed < 50)) {
checkLoadingOfCar();
craneBucketFilled = false;
}
}
if (commandedCraneBucketOpenClosed > craneBucketOpenClosed) {
craneBucketOpenClosed += 1;
if (craneBucketOpenClosed > commandedCraneBucketOpenClosed) craneBucketOpenClosed = commandedCraneBucketOpenClosed;
if (!craneBucketFilled && (craneBucketOpenClosed > 50) && (craneUpDown < 20) && (anglePercent >= 22) && (anglePercent <= 48)) {
craneBucketFilled = true;
}
}
if (craneBucketOpenClosed != lastCraneBucketOpenClosed) {
var item = document.getElementById('CraneBucket');
var data = "translate(0,0) rotate("+((100-craneBucketOpenClosed)*1.80)+")";
item.setAttribute("height", craneBucketOpenClosed);
if (!craneBucketFilled) item.setAttribute("fill", "#4F81BD");
else item.setAttribute("fill", "#948A54");
jmri.setMemory("IM_7_6", craneBucketOpenClosed);
}
}