396 lines
15 KiB
Plaintext
396 lines
15 KiB
Plaintext
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta name="generator"
|
|
content="HTML Tidy for HTML5 for Apple macOS version 5.8.0">
|
|
<title>JMRI JSON Servlet</title>
|
|
<!--#include virtual="/help/en/parts/Style.shtml" -->
|
|
|
|
<style type="text/css">
|
|
table#jsonResponses {
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
table#jsonResponses td {
|
|
border: 1px solid gray;
|
|
width: 33%;
|
|
}
|
|
|
|
table.data {
|
|
margin: initial;
|
|
margin-left: 2em;
|
|
}
|
|
|
|
code {
|
|
white-space: normal;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<!--#include virtual="/help/en/parts/Header.shtml" -->
|
|
|
|
<div id="mBody">
|
|
<!--#include virtual="Sidebar.shtml" -->
|
|
|
|
<div id="mainContent">
|
|
<h1>JMRI JSON Servlet</h1>
|
|
|
|
<p>
|
|
The JMRI <a href="https://en.wikipedia.org/wiki/JSON">JSON</a>
|
|
Servlet provides a RESTful API and a <a
|
|
href="https://en.wikipedia.org/wiki/WebSocket">WebSocket</a> API
|
|
for accessing and editing user defined objects in JMRI. This
|
|
document describes how to enable the JMRI JSON servlet and provides
|
|
some examples of use.
|
|
</p>
|
|
|
|
<p>
|
|
<strong>Note</strong> the JMRI JSON protocol is documented in <a
|
|
href="https://www.jmri.org/JavaDoc/doc/jmri/server/json/package-summary.html">JMRI
|
|
API Documentation</a>.
|
|
</p>
|
|
|
|
<h2 id="jmri_json_servlet">JMRI JSON Servlet</h2>
|
|
|
|
<p>
|
|
An overview of how Web Server operates using JSON between JMRI and
|
|
the web browser, using web.servlet.panel as an example, can be found
|
|
on <a href="PanelServlet.shtml#example">PanelServlet Help page</a>.
|
|
</p>
|
|
|
|
<h2>Setting up the JSON Servlet</h2>
|
|
|
|
<p>The JMRI JSON Servlet is a feature that is part of the Web
|
|
Server. To use this service:</p>
|
|
|
|
<ol>
|
|
<li>Ensure the web server's port is unique:
|
|
<ul>
|
|
<li>Open the Preferences dialog</li>
|
|
|
|
<li>Click <strong>Web Server</strong> on the left side
|
|
</li>
|
|
|
|
<li>Ensure the port number is unique (for example 12080).
|
|
Other ports are used by WiThrottle, JSON Server, etc.</li>
|
|
|
|
<li>Click Save</li>
|
|
</ul>
|
|
</li>
|
|
|
|
<li>Click <strong>Actions</strong> and <strong>Start
|
|
Web Server</strong> to ensure the web server is running (<strong>Tools
|
|
⇒ Servers ⇒ Start JRMI Web Server</strong> in PanelPro).
|
|
</li>
|
|
|
|
<li>If you want the Web Server to run each time you start JMRI:
|
|
<ul>
|
|
<li>Open the JMRI <strong>Preferences</strong> dialog
|
|
</li>
|
|
|
|
<li>Select <strong>Start Up</strong> in the left column
|
|
</li>
|
|
|
|
<li>Click <strong>Add ▾</strong></li>
|
|
|
|
<li>Select <strong>Perform action...</strong></li>
|
|
|
|
<li>Select <strong>Start Web Server</strong></li>
|
|
|
|
<li>Click <strong>OK</strong></li>
|
|
</ul>
|
|
</li>
|
|
</ol>
|
|
|
|
<h2>Paths</h2>
|
|
|
|
<p>The servlet responds to the following paths:</p>
|
|
|
|
<dl>
|
|
<dt>/json</dt>
|
|
|
|
<dd>
|
|
Depending on protocol:
|
|
<dl>
|
|
<dt>HTTP</dt>
|
|
|
|
<dd>Open a JSON WebSocket console that allows experimentation
|
|
with JSON sockets.</dd>
|
|
|
|
<dt>WS</dt>
|
|
|
|
<dd>Open a JSON WebSocket.</dd>
|
|
</dl>
|
|
</dd>
|
|
|
|
<dt>
|
|
/json/<em>type</em>
|
|
</dt>
|
|
|
|
<dd>
|
|
Using the HTTP protocol:
|
|
<dl>
|
|
<dt>GET</dt>
|
|
|
|
<dd>
|
|
request a list of objects of <em>type</em>
|
|
</dd>
|
|
|
|
<dt>PUT</dt>
|
|
|
|
<dd>
|
|
add an object of <em>type</em>
|
|
</dd>
|
|
</dl>
|
|
A JSON array of valid types for your JMRI installation is available
|
|
by using the <em>type</em> "
|
|
<code>
|
|
<a href="/json/type">type</a>
|
|
</code>
|
|
" (with JMRI Web Server running). You can also see the list using
|
|
the Tables menu on the JMRI Web Server Home page. "
|
|
<code>
|
|
<a href="/tables/type">/tables/type</a>
|
|
</code>
|
|
" See the <a
|
|
href="https://www.jmri.org/JavaDoc/doc/jmri/server/json/package-summary.html">protocol
|
|
documentation</a> for more details.
|
|
</dd>
|
|
|
|
<dt>
|
|
/json/<em>type</em>/<em>name</em>
|
|
</dt>
|
|
|
|
<dd>
|
|
Using the HTTP protocol:
|
|
<dl>
|
|
<dt>GET</dt>
|
|
|
|
<dd>
|
|
request the object of <em>type</em> with name <em>name</em>
|
|
</dd>
|
|
|
|
<dt>POST</dt>
|
|
|
|
<dd>
|
|
modify the object of <em>type</em> with name <em>name</em>
|
|
</dd>
|
|
|
|
<dt>DELETE</dt>
|
|
|
|
<dd>
|
|
remove the object of <em>type</em> with name <em>name</em>
|
|
</dd>
|
|
</dl>
|
|
</dd>
|
|
</dl>
|
|
|
|
<h2 id="jmri_json_server">JMRI JSON Server</h2>
|
|
|
|
<p>The JMRI JSON server is functionally identical to the JSON
|
|
WebSocket interface, but running over a standard network socket.</p>
|
|
|
|
<h2 id="jquery_jmri">jquery.jmri.js</h2>
|
|
|
|
<p>
|
|
<a
|
|
href="https://github.com/JMRI/JMRI/blob/master/web/js/jquery.jmri.js"><em>jquery.jmri.js</em></a>
|
|
is a <a href="https://jquery.com">jQuery</a> library that ships with
|
|
JMRI and makes the JSON protocol support "just work" on most current
|
|
browsers.
|
|
</p>
|
|
|
|
<p>Examples of use of the jquery.jmri.js JavaScript library that
|
|
ships with JMRI include:</p>
|
|
|
|
<dl>
|
|
<dt>Operations Conductor</dt>
|
|
|
|
<dd>
|
|
source <a
|
|
href="https://github.com/JMRI/JMRI/blob/master/web/js/operations.js">/js/operations.js</a>
|
|
</dd>
|
|
|
|
<dt>Panel</dt>
|
|
|
|
<dd>
|
|
source <a
|
|
href="https://github.com/JMRI/JMRI/blob/master/web/js/panel.js">/js/panel.js</a>
|
|
</dd>
|
|
|
|
<dt>JSON Console</dt>
|
|
|
|
<dd>
|
|
source <a
|
|
href="https://github.com/JMRI/JMRI/blob/master/web/js/json-console.js">/js/json-console.js</a>
|
|
</dd>
|
|
|
|
<p>
|
|
Note: The source code for the above is found in the web/ts
|
|
directory, which contains the JavaScript and Typescript source
|
|
code. This is <a href="../doc/Technical/Patterns.shtml#typescript">compiled
|
|
to the web/js directory</a> for actual execution.
|
|
<dt>
|
|
<a href="/web/power.html">Power
|
|
Demonstration</a> (with JMRI Web Server running).
|
|
</dt>
|
|
<dd>
|
|
source <a
|
|
href="https://github.com/JMRI/JMRI/blob/master/web/power.html">/web/power.html</a>
|
|
</dd>
|
|
</dl>
|
|
|
|
<h2 id="websocket_examples">WebSocket Examples</h2>
|
|
<p>
|
|
The <b>WebSocket</b> feature of the servlet can be seen by browsing
|
|
to the <b>/json/</b> url, where a <b>JSON console</b> is provided
|
|
for testing.<br>
|
|
Notes: Method "get" is default. "get"ting an item sets up a listener which sends all subsequent changes as well.<br>
|
|
</p>
|
|
<table id="jsonResponses">
|
|
<caption><b>Example commands and responses</b></caption>
|
|
<tr>
|
|
<th>command</th>
|
|
<th>response</th>
|
|
<th>notes</th>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"sensor","data":{"name":"IS2"}}</code></td>
|
|
<td><code>{"type":"sensor","data":{"name":"IS2","state":2,"userName":null,"comment":null,"properties":[],"inverted":false}}</code></td>
|
|
<td>request current state of sensor IS2</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"sensor","method":"post","data":{"name":"IS2","state":4}}</code></td>
|
|
<td><code>{"type":"sensor","data":{"name":"IS2","state":4,"userName":null,"comment":null,"properties":[],"inverted":false}}</code></td>
|
|
<td>set sensor IS2 to InActive (4)</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"turnout","data":{"name":"IT99"}}</code></td>
|
|
<td><code>{"type":"turnout","data":{"name":"IT99","state":4,"userName":null,"comment":null,"properties":[],"inverted":false,"feedbackMode":1,"feedbackModes":[16,32,128,1],"sensor":[null,null]}}</code></td>
|
|
<td>request current state of turnout IT99</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"turnout","method":"put","data":{"name":"IT98","userName":"Test Turnout 98"}}</code></td>
|
|
<td><code>{"type":"turnout","data":{"name":"IT98","userName":"Test Turnout 98","comment":null,"properties":[],"inverted":false,"state":0,"feedbackMode":1,"feedbackModes":[16,32,128,1],"sensor":[null,null]}}</code></td>
|
|
<td>creaate turnout IT98 using "put" method</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"power","method":"get"}</code></td>
|
|
<td><code>{"type":"power","data":{"name":"LocoNet","state":2,"default":true,"prefix":"L"}}</code></td>
|
|
<td>get power state of the default connection; state 2=ON, 4=OFF, 8=IDLE, 0=UNKNOWN</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"power","method":"get","data":{"prefix":"L2"}}</code></td>
|
|
<td><code>{"type":"power","data":{"name":"LocoNet Prog","state":4,"default":false,"prefix":"L2"}}</code></td>
|
|
<td>get power state of a specific connection by system prefix</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"power","method":"post","data":{"prefix":"L","state":2}}</code></td>
|
|
<td><code>{"type":"power","data":{"name":"LocoNet","state":2,"default":true,"prefix":"L"}}</code></td>
|
|
<td>set power state on a specific connection; use state 2 for ON, 4 for OFF; omit "prefix" to target the default connection</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"list":"power"}</code></td>
|
|
<td><code>[{"type":"power","data":{"name":"LocoNet","state":2,"default":true,"prefix":"L"}},{"type":"power","data":{"name":"LocoNet Prog","state":4,"default":false,"prefix":"L2"}}]</code></td>
|
|
<td>list all configured power connections, one entry per connection</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"memory","data":{"name":"IMCURRENTTIME"}}</code></td>
|
|
<td><code>{"type":"memory","data":{"name":"IMCURRENTTIME","userName":null,"comment":null,"value":"2:53
|
|
PM"}}</code></td>
|
|
<td>get builtin memory (fast)clock time.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"ping"}</code></td>
|
|
<td><code>{"type":"pong"}</code></td>
|
|
<td>ping request and response</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"list":"panels"}</code></td>
|
|
<td><code>[{"type":"panel","data":{"name":"ControlPanel/R&R","URL":"/panel/ControlPanel/R&R?format=xml","userName":"R&R","type":"Control
|
|
Panel"}},{"type":"panel","data":{"name":"Layout/Waccamaw%20Coast%20Line","URL":"/panel/Layout/Waccamaw%20Coast%20Line?format=xml","userName":"Waccamaw
|
|
Coast Line","type":"Layout"}}]</code></td>
|
|
<td>request a list of panels, respond with array, example
|
|
shows two panels</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"throttle","data":{"name":"CSX754","address":754}}</code></td>
|
|
<td><code>{"type":"throttle","data":{"name":"CSX754","address":754,"speed":0.0,"forward":true,
|
|
"F0":false,"F1":false,"F2":false,"F3":false,"F4":false,"F5":false,"F6":false,"F7":false,
|
|
"F8":false,"F9":false,"F10":false,"F11":false,"F12":false,"F13":false,"F14":false,
|
|
"F15":false,"F16":false,"F17":false,"F18":false,"F19":false,"F20":false,"F21":false,
|
|
"F22":false,"F23":false,"F24":false,"F25":false,"F26":false,"F27":false,"F28":false,
|
|
"throttle":"CSX754"}}</code></td>
|
|
<td>request throttle for address 754 on the default connection, referred to as "CSX754"; add "prefix" to target a specific connection instead</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"throttle","data":{"name":"CSX754","address":754,"prefix":"L"}}</code></td>
|
|
<td><code>{"type":"throttle","data":{"name":"CSX754","address":754,"prefix":"L","speed":0.0,"forward":true,"throttle":"CSX754"}}</code></td>
|
|
<td>request throttle for address 754 on a specific connection by system prefix — useful when multiple command stations are configured; subsequent speed/function commands use the name "CSX754" as normal</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"throttle","data":{"name":"CSX754","speed":0.25}}</code></td>
|
|
<td><code>{"type":"throttle","data":{"name":"CSX754","speed":0.25,"throttle":"CSX754"}}</code></td>
|
|
<td>request speed of throttle "CSX754" to 25%</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"throttle","data":{"name":"CSX754","release":null}}</code></td>
|
|
<td><code>{"type":"throttle","data":{"name":"CSX754","release":null,"throttle":"CSX754"}}</code></td>
|
|
<td>release the throttle "CSX754"</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"light","data":{"name":"IL1"}}</code></td>
|
|
<td><code>{"type":"light","data":{"name":"IL1","userName":"Yard Light","comment":null,"state":4,"properties":[]}}</code></td>
|
|
<td>get current state of light IL1; state 2=ON, 4=OFF, 0=UNKNOWN</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"light","method":"post","data":{"name":"IL1","state":2}}</code></td>
|
|
<td><code>{"type":"light","data":{"name":"IL1","userName":"Yard Light","comment":null,"state":2,"properties":[]}}</code></td>
|
|
<td>turn light IL1 on (state 2); use state 4 to turn off</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"list":"lights"}</code></td>
|
|
<td><code>[{"type":"light","data":{"name":"IL1","userName":"Yard Light","comment":null,"state":2,"properties":[]}},{"type":"light","data":{"name":"IL2","userName":null,"comment":null,"state":4,"properties":[]}}]</code></td>
|
|
<td>list all configured lights; returns an empty array <code>[]</code> if none are configured</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"block","data":{"name":"IB1"}}</code></td>
|
|
<td><code>{"type":"block","data":{"name":"IB1","userName":"AUTOBLK:1","comment":null,"value":"ns2608"}}</code></td>
|
|
<td>request current value for block IB1</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"train","data":{"name":"3"}}</code></td>
|
|
<td><code>{"type":"train","data":{"name":"3","userName":"BB","iconName":"BB 1017",
|
|
"departureTime":"07:50","description":"Bakersfield - Sweeper","route":"Bksfld-turn",
|
|
"routeId":"4","locations":[</code>...<code>],"engines":[</code>...<code>],
|
|
"cars": [</code>...<code>],"trainDepartsName":"Bakersfield",
|
|
"trainTerminatesName":"Bakersfield","location":"Bakersfield",
|
|
"locationId":"4r1","status":"Partial 4/8 cars","statusCode":20,
|
|
"length":87,"weight":144,"leadEngine":"SP 1017",
|
|
"caboose":"NH 681"}}</code></td>
|
|
<td>request train by name<br />
|
|
NOTE: locations, engines and cars arrays not shown here for clarity</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>{"type":"car","method":"post","data":{"name":"ATSF10407",
|
|
"trainId":null,"locationUnknown":true,"location":null}}</code></td>
|
|
<td><code>
|
|
{"type":"car","data":{"name":"ATSF10407","number":"10407","road":"ATSF","rfid":"","carType":"Boxcar","carSubType":"",
|
|
"length":50,"weight":4.4,"weightTons":88.0,"color":"Tuscan","owner":"AT","built":"1943","comment":"",
|
|
"outOfService":false,"locationUnknown":true,"location":null,"trainId":null,"trainName":null,"destination":null,
|
|
"load":"L","hazardous":false,"caboose":false,"passenger":false,"fred":false,"removeComment":"","addComment":"",
|
|
"kernel":"","utility":false,"isLocal":false,"finalDestination":null,"returnWhenEmpty":null,"returnWhenLoaded":null,
|
|
"division":"","status":"<?>"}} </code></td>
|
|
<td>use post method to remove car from train and mark it as
|
|
LocationUnknown.</td>
|
|
</tr>
|
|
</table>
|
|
<!--#include virtual="/help/en/parts/Footer.shtml" -->
|
|
</div>
|
|
<!-- closes #mainContent-->
|
|
</div>
|
|
<!-- closes #mBody-->
|
|
<script src="/js/help.js"></script>
|
|
</body>
|
|
</html>
|