##############################
Connection to the HOOPS Server
##############################

Summary
=======

In this section, we will show how to request a viewing session and stream a model into your application via the :doc:`HOOPS Server </prog_guide/servers/overview>`.

Normally, the infrastructure to facilitate the on-demand streaming will be sitting behind a proxy on the internet or within a corporate network. For this simplified example, we are taking advantage of the local HOOPS Server that is bundled with the |HCNOW| package and that you have already used to view the quick-start samples in the first section.

.. note::
	
	Among the main benefits of |HCNOW| are the capabilities to: 1) quickly stream massive models to the client, 2) request subsets of a model on-demand, and 3) render a model completely server-side. All of this functionality requires a :doc:`Stream Cache Server </prog_guide/servers/stream_cache_server/overview>` to be spawned for every viewing session, which handles the view-dependent streaming and keeps interacting with the Web Viewer component as long as the viewing session is active. To manage and monitor those viewing sessions, we provide a Node.js-based framework simply called the HOOPS Server.


Concepts
========

* Requesting a session from the HOOPS Server
* Starting a Stream Cache Server

----------------------------------------

Running the server
==================

If you are not already running the server, start it by navigating to the *quick_start* directory of the installation and running *start_server.bat/sh*. You should see a console window with status information indicating that the server is up and its services are listening on specific ports.


Requesting a viewing session
============================

Now, let's write some code that connects your application to this server. First, we start with an empty file called *ServerConnection.js* which we fill with the class below:

.. code-block:: js

	class ServerConnection {
	  constructor(endpoint) {
		this._endpoint = endpoint;
	  }
	  
	  connect() {
		var _this = this;
		var request = new XMLHttpRequest();
		request.open("POST", this._endpoint + "/api/spawn");
		request.overrideMimeType("application/json");
		request.setRequestHeader("Content-Type", "application/json");
		request.timeout = 60000;

		var promise = new Promise(function (resolve, reject) {
		  request.onreadystatechange = function () {
			if (request.readyState == 4) {
			  if (request.status == 200) {
				resolve(_this.parseServerSuccessResponse(request.responseText));
			  }
			  else {
				reject(alert("Couldn't Connect"));
			  }
			}
		  };
		  
		  request.send('{"class":"csr_session","params":{}}');
		});
		
		return promise;
	  }
	  
	  parseServerSuccessResponse(text) {
		this._jsonResponse = JSON.parse(text);
		this._endpointuri =  this._jsonResponse.endpoints["ws"];
	  }
	}

The only purpose of this class is to make a standard HTTP POST request to the HOOPS Server at the endpoint to request a viewing session and wrap this request into a promise. If the server responds and the request is successful it will return a response that includes the IP and port of the viewing session that has been reserved for this viewing request. Please see the Programming Guide for more info on the :doc:`HOOPS Server REST API </api_ref/servers/rest-api-reference>`.

.. note::
	
	Every HOOPS Server supports a large number of simultaneous viewing sessions each assigned to their own port. In a real-world web application requesting those sessions would not be done directly via the client-side JS code but instead within your server application, most likely utilizing a reverse-proxy setup for security reasons and to ensure that all WebSockets traffic goes through standard ports.
	
	See the :doc:`Programming Guide </prog_guide/servers/stream_cache_server/overview>` for more information.

Add functionality of this new JS file to your application by adding the line below to your HTML page:

.. code-block:: html

    <script type="module">
        import * as Communicator from "/js/hoops/hoops-web-viewer.mjs";
        import * as ServerConnection from "/js/hoops/ServerConnection.js";
        ...
    </script>
    

Modifying the loading code
==========================

Let's also modify the main HTML document to utilize this new ``ServerConnection`` class to connect to the Stream Cache Server instead of loading *.scs* files from the web server included in your development environment:

.. code-block:: js

	window.onload = function () {
		server = new ServerConnection("http://localhost:11182");
		server.connect().then(function () {
		  hwv = new Communicator.WebViewer({
			containerId: "viewer",
			endpointUri: server._endpointuri,
			model: "moto"
		  });

		  hwv.setCallbacks({
			sceneReady: () => {
			  hwv.view.setBackgroundColor(Communicator.Color.blue(), Communicator.Color.white());
			},
			modelStructureReady: () => {
			  document.getElementById('ModelStructureReady').innerHTML = 'Model Structure Ready';
			  modelTree.generate();
			},
			camera: () => {
			  document.getElementById('CameraData').innerHTML = JSON.stringify(hwv.view.getCamera());
			},
			selectionArray: (selectionItems) => {
			  if (selectionItems.length > 0) {
				for (const selectionItem of selectionItems) {
				  modelTree.onSelection(selectionItem);
				}
			  } else {
				modelTree.onSelection(null);
			  }
			}
		  });

		  let menu = new Menu(hwv);
		  modelTree = new ModelTree(hwv, "modeltree");
		  hwv.start();
		});
	}

We start by initializing our new class with the port that the demo server in our package is listening to. After the POST request has successfully resolved, we are passing the websocket endpoint into the ``endpointUri`` property of the Web Viewer component initialization and specify the model we want to load separately. Again, we are not loading the scs file we have copied to our application directory anymore but this time the referenced SC model (which happens to be a shattered model) will be streamed via a websocket connection from the Stream Cache Server.

After this modification to the startup code, the Web Viewer component is now ready for streaming models via the HOOPS Server. No further modifications are required.

We only scratched the surface with this example. Implementing a viewing infrastructure on your server-backend that can scale to many simultaneous users is not an easy task and requires considerable web-expertise even when using web platforms like AWS or Azure. However, it is often worth the effort, in particular, if your models are large and/or you want to provide your user with a consistent experience across all devices.

Please see the :doc:`Programming Guide </prog_guide/servers/overview>` for more information about server setup.

Thank you for taking the time to read through this tutorial with |HCNOW|. We recommend continuing your training by visiting our Tutorials section. You will find information about setting up your local development environment for |HCNOW|, as well as more tutorials that explore real-world problems that |HCNOW| can solve for your company.
