Files
JIMRI/help/en/html/web/JsonServlet.shtml
2026-06-17 14:00:51 +02:00

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
&rArr; Servers &rArr; 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 &#9662;</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&amp;R","URL":"/panel/ControlPanel/R&amp;R?format=xml","userName":"R&amp;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 &mdash; 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":"&lt;&quest;&gt;"}} </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>