Skip to content

Commit 7aa90bc

Browse files
authored
Merge pull request #397 from cjakeman/webserver-time
Webserver API/TIME http://www.elvastower.com/forums/index.php?/topic/34945-web-server/
2 parents f765a08 + cfd55a6 commit 7aa90bc

File tree

11 files changed

+745
-4
lines changed

11 files changed

+745
-4
lines changed
1.63 MB
Loading

Source/Documentation/Manual/software-platform.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ Some of these sample pages repeat data from the in-game panels to provide a more
128128

129129
.. image:: images/web-page-both.png
130130

131+
- The time page shows the simulation time as a digital clock and links to 3 versions of an analogue clock.
132+
133+
.. image:: images/web-page-clock.png
134+
135+
131136
The sample pages can be found in the ``Content\Web`` subfolder of the OR
132137
program folder and the web server defaults to ``Content\Web\index.html``.
133138

@@ -170,6 +175,10 @@ Note: To avoid overloading the simulator, please keep API calls to once or twice
170175
- | Retrieves information rendered on the Track Monitor, such as speed,
171176
| acceleration, grade, and upcoming hazards.
172177
- | ``Orts.Simulation.Physics .Train.TrainInfo``
178+
* - | GET
179+
- | ``/API/TIME``
180+
- | Retrieves just the simulation time in seconds since midnight.
181+
- | ``Orts.Viewer3D.WebServices .WebServer.ORTSApiController .ApiTime``
173182
* - | GET
174183
- | ``/API/CABCONTROLS``
175184
- | Retrieves an array of the cab controls for the player localhost

Source/RunActivity/RunActivity.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,9 @@
356356
<Content Include="Viewer3D\WebServices\Web\index.css" />
357357
<Content Include="Viewer3D\WebServices\Web\index.html" />
358358
<Content Include="Viewer3D\WebServices\Web\or_logo.png" />
359+
<Content Include="Viewer3D\WebServices\Web\Time\index.css" />
360+
<Content Include="Viewer3D\WebServices\Web\Time\index.html" />
361+
<Content Include="Viewer3D\WebServices\Web\Time\index.js" />
359362
<Content Include="Viewer3D\WebServices\Web\TrackMonitorTrainDriving\index.css" />
360363
<Content Include="Viewer3D\WebServices\Web\TrackMonitorTrainDriving\index.html" />
361364
<Content Include="Viewer3D\WebServices\Web\TrackMonitorTrainDriving\index.js" />
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
<!doctype html>
2+
<!-- Based on https://www.programmersought.com/article/31327047900/ -->
3+
<html lang="en">
4+
<head>
5+
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
6+
<style>
7+
canvas{
8+
display: block;
9+
margin: auto;
10+
border: 1px solid #CCC;
11+
}
12+
</style>
13+
<title>Flat Clock</title>
14+
</head>
15+
<body onload="setInterval (ApiTime, 500)">
16+
<canvas id="canvas" >Your browser does not support canvas</canvas>
17+
</body>
18+
<script>
19+
20+
var canvas = document.getElementById("canvas");
21+
var ctx = canvas.getContext("2d");
22+
var width = 1000;
23+
var height = 500;
24+
var cx = width / 2; // Canvas center x
25+
var cy = height / 2; // Canvas center y
26+
27+
var size = 200; // table size
28+
29+
canvas.width = width;
30+
canvas.height = height;
31+
32+
//draw();
33+
34+
function draw(hours, mins, secs){
35+
// // Time class
36+
// var date = new Date();
37+
// // When getting
38+
// var hours = date.getHours();
39+
// // Get points
40+
// var min = date.getMinutes();
41+
// // Get seconds
42+
// var sec = date.getSeconds();
43+
// outer ring
44+
drawOuter();
45+
// time
46+
drawText();
47+
// scale
48+
drawScale();
49+
// hour hand
50+
drawHour(hours, mins);
51+
// minute hand
52+
drawMid(mins, secs);
53+
// second hand
54+
drawSec(secs);
55+
}
56+
57+
// Draw the outer circle of the watch
58+
function drawOuter(){
59+
// outermost circle
60+
ctx.arc(cx, cy, size + 30, 0, Math.PI * 2);
61+
ctx.fillStyle = "#000033";
62+
ctx.fill();
63+
ctx.beginPath();
64+
65+
// inner circle
66+
ctx.arc(cx, cy, size, 0, Math.PI * 2);
67+
ctx.fillStyle = "white";
68+
ctx.fill();
69+
ctx.beginPath();
70+
71+
// middle origin
72+
ctx.arc(cx, cy, 10, 0, Math.PI * 2);
73+
ctx.fillStyle = "#000033";
74+
ctx.fill();
75+
ctx.beginPath();
76+
}
77+
78+
// Painting
79+
function drawText(){
80+
var radian = 0, x = 0, y = 0;
81+
var angle = -60; // start drawing from 1 point, the angle between 1 and 2 is 30 degrees
82+
for(var i = 0 ; i < 12 ; i++){
83+
radian = angle * Math.PI / 180;
84+
x = Math.cos(radian) * (size - 50) + cx;
85+
y = Math.sin(radian) * (size - 50) + cy;
86+
ctx.textAlign = "center"; // text is centered horizontally
87+
ctx.textBaseline = "middle"; // The text is centered vertically
88+
ctx.font = "45px Arial";
89+
ctx.fillText(i + 1, x, y);
90+
ctx.beginPath();
91+
angle += 30;
92+
}
93+
}
94+
95+
// draw scale
96+
function drawScale(){
97+
var radian = 0, x = 0, y = 0;
98+
var s = 15;
99+
var lineWidth = 0;
100+
for(var angle = 0 ; angle <= 360 ; angle += 6){
101+
radian = angle * Math.PI / 180;
102+
103+
// draw long scale
104+
if(angle % 30 == 0){
105+
s = 20;
106+
lineWidth = 3;
107+
}
108+
// draw short
109+
else{
110+
s = 15;
111+
lineWidth = 1;
112+
}
113+
114+
// The starting point of the scale is size-s
115+
x = Math.cos(radian) * (size - s) + cx;
116+
y = Math.sin(radian) * (size - s) + cy;
117+
ctx.moveTo(x, y);
118+
119+
// End of scale
120+
for(var j = 0 ; j < s ; j++){
121+
x += Math.cos(radian);
122+
y += Math.sin(radian);
123+
}
124+
ctx.lineTo(x, y);
125+
126+
// Set the scale width
127+
ctx.lineWidth = lineWidth;
128+
ctx.stroke();
129+
ctx.beginPath();
130+
}
131+
}
132+
133+
// Draw the hour hand, hour time, min minutes
134+
function drawHour(hour, min){
135+
// hour * angle between hours-90 degrees (default points to 3 o'clock, 3*30=90) + (percentage of the hour that the minute has passed)
136+
var angle = (hour * 30 - 90) + (30 * (min / 60));
137+
// The angle is converted to radians, and the parameters of cos sin are all radians
138+
var radian = angle * Math.PI / 180;
139+
// length
140+
var s = 100;
141+
ctx.beginPath();
142+
ctx.moveTo(cx, cy);
143+
ctx.lineTo(Math.cos(radian) * s + cx, Math.sin(radian) * s + cy);
144+
ctx.lineWidth = 10;
145+
ctx.stroke();
146+
}
147+
148+
// draw minute hand
149+
function drawMid(min, src){
150+
// 0 defaults to the 3 o'clock position, the angle between the minute and the minute is 6 degrees, to subtract 15 minutes * 6 degrees, point the minute to 12 o'clock
151+
// (6 * (src / 60)) = seconds have passed, the percentage of this minute * 6 degrees
152+
var angle = (min * 6 - 15 * 6) + (6 * (src / 60));
153+
// The angle is converted to radians, and the parameters of cos sin are all radians
154+
var radian = angle * Math.PI / 180;
155+
var s = 180; // length
156+
ctx.beginPath();
157+
ctx.moveTo(cx, cy);
158+
ctx.lineTo(Math.cos(radian) * s + cx, Math.sin(radian) * s + cy);
159+
ctx.lineWidth = 5;
160+
ctx.stroke();
161+
}
162+
163+
// draw seconds
164+
function drawSec(src){
165+
var angle = src * 6-15 * 6; // 0 defaults to the 3 o'clock position, the angle between the minute and the minute is 6 degrees, to subtract 15 minutes * 6 degrees, point the minute to 12 o'clock
166+
var radian = angle * Math.PI / 180;
167+
var s = 160; // second hand 1 length
168+
var s1 = 50; // second hand 2 length
169+
170+
// second hand
171+
ctx.beginPath();
172+
ctx.moveTo(cx, cy);
173+
ctx.lineTo(Math.cos(radian) * s + cx, Math.sin(radian) * s + cy);
174+
ctx.lineWidth = 1;
175+
ctx.stroke();
176+
177+
// second hand red dot
178+
ctx.beginPath();
179+
ctx.arc(Math.cos(radian) * s + cx, Math.sin(radian) * s + cy, 5, 0, Math.PI * 2);
180+
ctx.fillStyle = "red";
181+
ctx.fill();
182+
183+
// Reverse (short) second hand
184+
angle = (src * 6-15 * 6) + 180; // +180 degrees, opposite to the second hand
185+
radian = angle * Math.PI / 180;
186+
ctx.beginPath();
187+
ctx.moveTo(cx, cy);
188+
ctx.lineTo(Math.cos(radian) * s1 + cx, Math.sin(radian) * s1 + cy);
189+
ctx.lineWidth = 3;
190+
ctx.stroke();
191+
}
192+
193+
let hr = new XMLHttpRequest;
194+
let httpCodeSuccess = 200;
195+
let xmlHttpRequestCodeDone = 4;
196+
197+
function ApiTime() {
198+
// "/API/TIME" /API is a prefix hard-coded into the WebServer class
199+
hr.open("GET", "/API/TIME", true);
200+
hr.send();
201+
hr.onreadystatechange = function () {
202+
if (this.readyState == xmlHttpRequestCodeDone && this.status == httpCodeSuccess) {
203+
let vso = JSON.parse(hr.responseText);
204+
if (vso != null) // Can happen using IEv11
205+
{
206+
let value = vso;
207+
let daysInteger = Math.floor(value / (60 * 60 * 24));
208+
let daysFraction = value - daysInteger * (60 * 60 * 24);
209+
let hoursInteger = Math.floor(daysFraction / (60 * 60));
210+
let hoursFraction = value - hoursInteger * (60 * 60);
211+
let minutesInteger = Math.floor(hoursFraction / 60);
212+
let minutesFraction = hoursFraction - (minutesInteger * 60);
213+
let secondsInteger = Math.floor(minutesFraction);
214+
215+
draw(hoursInteger, minutesInteger, secondsInteger);
216+
}
217+
}
218+
}
219+
}
220+
</script>
221+
</html>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
table {
2+
margin: auto;
3+
padding: 10px;
4+
font-family: Consolas;
5+
font-size: 48px;
6+
background-color: rgb(31, 31, 31);
7+
color: white;
8+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<!DOCTYPE HTML>
2+
<!--
3+
COPYRIGHT 2009, 2010, 2011, 2012, 2013, 2014 by the Open Rails project.
4+
5+
This file is part of Open Rails.
6+
7+
Open Rails is free software: you can redistribute it and/or modify
8+
it under the terms of the GNU General Public License as published by
9+
the Free Software Foundation, either version 3 of the License, or
10+
(at your option) any later version.
11+
12+
Open Rails is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
GNU General Public License for more details.
16+
17+
You should have received a copy of the GNU General Public License
18+
along with Open Rails. If not, see <http://www.gnu.org/licenses/>.
19+
-->
20+
<html>
21+
<head>
22+
<title>OPEN RAILS - Sample API</title>
23+
<meta charset="utf-8" />
24+
<meta name="viewport" content="width=device-width, initial-scale=1"><!-- adds zooming for mobiles -->
25+
<link rel="shortcut icon" type="image/png" href="/or_logo.png"><!-- This icon appears in the page's tab and its bookmark. -->
26+
<link rel="stylesheet" type="text/css" href="/index.css"><!-- share styles with home page -->
27+
<link href="index.css" rel="stylesheet" type="text/css">
28+
<script src="index.js"></script>
29+
</head>
30+
31+
<body onload="setInterval (ApiTime, 500)">
32+
<div id="menu"><a href="/">Back to Menu</a></div>
33+
<br>
34+
<h2>Open Rails Web Server - Simulation Time</h2>
35+
<h3>Seconds since midnight</h3>
36+
<div id="time"></div>
37+
<table>
38+
<tr>
39+
<td id="hours"></td><td>:</td>
40+
<td id="minutes"></td><td>:</td>
41+
<td id="seconds"></td><td>.</td>
42+
<td id="centiseconds"></td>
43+
</tr>
44+
</table>
45+
<ul>
46+
<li><a href="flat_clock.html">Flat Clock</a></li>
47+
<li><a href="shadow_clock.html">Shadow Clock</a></li>
48+
<li><a href="smooth_clock.html">Smooth Clock</a></li>
49+
</ul>
50+
</body>
51+
</html>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// COPYRIGHT 2009, 2010, 2011, 2012, 2013, 2014 by the Open Rails project.
2+
//
3+
// This file is part of Open Rails.
4+
//
5+
// Open Rails is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// Open Rails is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU General Public License
16+
// along with Open Rails. If not, see <http://www.gnu.org/licenses/>.
17+
//
18+
// Based on original work by Dan Reynolds 2017-12-21
19+
20+
// Using XMLHttpRequest rather than fetch() as:
21+
// 1. it is more widely supported (e.g. Internet Explorer and various tablets)
22+
// 2. It doesn't hide some returning error codes
23+
// 3. We don't need the ability to chain promises that fetch() offers.
24+
25+
let hr = new XMLHttpRequest;
26+
let httpCodeSuccess = 200;
27+
let xmlHttpRequestCodeDone = 4;
28+
29+
function ApiTime() {
30+
// "/API/TIME" /API is a prefix hard-coded into the WebServer class
31+
hr.open("GET", "/API/TIME", true);
32+
hr.send();
33+
hr.onreadystatechange = function () {
34+
if (this.readyState == xmlHttpRequestCodeDone && this.status == httpCodeSuccess) {
35+
let vso = JSON.parse(hr.responseText);
36+
if (vso != null) // Can happen using IEv11
37+
{
38+
let secondsSinceMidnight = vso;
39+
let daysInteger = Math.floor(secondsSinceMidnight / (60 * 60 * 24));
40+
let daysFraction = secondsSinceMidnight - daysInteger * (60 * 60 * 24);
41+
let hoursInteger = Math.floor(daysFraction / (60 * 60));
42+
let hoursFraction = daysFraction - hoursInteger * (60 * 60);
43+
let minutesInteger = Math.floor(hoursFraction / 60);
44+
let minutesFraction = hoursFraction - (minutesInteger * 60);
45+
let secondsInteger = Math.floor(minutesFraction);
46+
let secondsFraction = minutesFraction - secondsInteger;
47+
let centisecondsInteger = Math.floor(secondsFraction * 100);
48+
49+
time.innerHTML = secondsSinceMidnight.toFixed(2);
50+
51+
hours.innerHTML = ((hoursInteger < 10) ? "0" : "") + hoursInteger;
52+
minutes.innerHTML = ((minutesInteger < 10) ? "0" : "") + minutesInteger;
53+
seconds.innerHTML = ((secondsInteger < 10) ? "0" : "") + secondsInteger;
54+
centiseconds.innerHTML = ((centisecondsInteger < 10) ? "0" : "") + centisecondsInteger;
55+
}
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)