# WS-API: VariableServer

`ws://localhost:8888/api/ws/VariableServer`

## Purpose

JSON Variable Server

## Client to Server Command Messages

Add a Trick Variable to the current session.

    { "cmd" : "var_add",
      "var_name" : string
    }

Stop sending periodic `var_list` messages (see below) from the server.

    { "cmd" : "var_pause" }

Resume sending periodic `var_list` response messages from the server.

    { "cmd" : "var_unpause" }

Send one `var_list` message from the server.

    { "cmd" : "var_send" }

Clear all variables from the current session, that is: undo all of the `var_add` commands.

    { "cmd" : "var_clear" }

Disconnect from the variable server.

    { "cmd" : "var_exit" }

Set the period (in milliseconds) at which `var_list` messages are sent form the server.

    { "cmd" : "var_cycle",
      "period" : integer
    }

Execute the given Python code in the host sim.

    { "cmd" : "python",
      "pycode" : string
    }

Send the sie structure from the server. Response will be the `sie` response message (below).

    { "cmd" : "sie" }

Send the units for the given variable. Response will be the `units` response message (below).

    { "cmd" : "units",
      "var_name" : string
    }

## Server to Client Response Messages

Error Response

    { "msg_type" : "error",
      "error_text" : string
    }

Periodic response containing the values of variables requested by `var_add`.

    { "msg_type" : "var_list"
      "time" : double
      "values" : []
    }

Response to the `sie` command (above).

    { "msg_type" : "sie",
      "data" : string
    }

Response to the `units` command (above).

    { "msg_type" : "units",
      "var_name" : string,
      "data" : string
    }

## Example Variable Server Client

    <!DOCTYPE html>
    <html>
      <head>
        <title>WS Experiments</title>
      </head>
      <body>
          <style>
              table { border-collapse: collapse; width: 100%; }
              th, td { text-align: left; padding: 8px; }
              tr:nth-child(even){background-color: #f2f2f2}
              th { background-color: #562399; color: white; }
          </style>
          <header>
          </header>

          <div class="variableDisplay"></div>
          <table class="variables">
              <tr>
                  <th>Variable</th>
                  <th>Value</th>
              </tr>
          </table>

          <div id="output"></div>
          <script type="text/javascript">
              function log(s) {
                  var p = document.createElement("p");
                  p.style.wordWrap = "break-word";
                  p.textContent = s;
                  output.appendChild(p);
              }
              function sendMessage(msg) {
                  ws.send(msg);
              }
              // Interface to Trick WebSocket Variable Server
              function setPeriod(period) {
                  sendMessage(`{"cmd":"var_cycle","period":${period}}`);
              }
              function addVarTableRow(name, value) {
                  // create a row in the table that contains two <td>s, one for the var_name and one for its value.
                  let tr = document.createElement('tr');
                  let td1 = document.createElement('td');
                  td1.textContent = `${name}`;
                  let td2 = document.createElement('td');
                  td2.textContent = `${value}`;
                  td2.className = "values";
                  tr.appendChild(td1);
                  tr.appendChild(td2);
                  varTable.appendChild(tr);
              }
              function addVariable(name, value) {
                  sendMessage(`{"cmd":"var_add","var_name": "${name}"}`);
                  addVarTableRow(name, value);
              }
              var varTable = document.querySelector('table.variables');

              var ws = new WebSocket('ws://localhost:8888/api/ws/VariableServer');
              ws.onopen = function(e) {
                  setPeriod(100);
                  addVarTableRow("Time", 0.0);
                  addVariable("dyn.cannon.pos[0]", 0.0);
                  addVariable("dyn.cannon.pos[1]", 0.0);
                  addVariable("dyn.cannon.vel[0]", 0.0);
                  addVariable("dyn.cannon.vel[1]", 0.0);
                  addVariable("dyn.cannon.time", 0.0);
                  addVariable("dyn.cannon.timeRate", 0.0);
                  addVariable("dyn.cannon.impact", 0.0);
                  addVariable("I.dont.exist", 0.0);
                  sendMessage("{\"cmd\":\"var_unpause\"}");
              };
              ws.onmessage = function(e) {
                 let msg = JSON.parse(e.data);
                 if (msg.msg_type == "values") {
                     let valueNodes = varTable.getElementsByClassName("values");
                     valueNodes[0].textContent = msg.time;
                     for (let i = 0; i < msg.values.length; i++ ) {
                         valueNodes[i+1].textContent = msg.values[i];
                     }
                 }
              };
              ws.onerror = function(e) {
                 console.log("WebSocket Error: " , e);
                 handleErrors(e);
              };
              ws.onclose = function(e) {
                 console.log("Connection closed", e);
              };

          </script>
      </body>
    </html>