Skip to content

Latest commit

 

History

History
334 lines (226 loc) · 10.1 KB

File metadata and controls

334 lines (226 loc) · 10.1 KB

JNAP JavaScript Library

This document provides instructions on how to use the jnap.js library for communicating with JNAP-enabled devices.

Overview

The JNAP JavaScript Library is a client-side wrapper that simplifies making JNAP calls from a web browser. It is compiled from Dart and provides a Promise-based API for asynchronous operations.

Compiling Dart to JavaScript

The jnap.js library is generated by compiling the Dart code in this project to JavaScript. The compilation process is handled by the Dart compiler, which can be invoked using the dart compile js command.

The entry point for the compilation is bin/jnap_web.dart. This file is responsible for setting up the JavaScript interoperability layer.

To build the library, run the following command from the project's root directory:

dart compile js -o dist/jnap.js bin/jnap_web.dart

This will create the dist/jnap.js file, which can then be included in any web page.

The Dart-JavaScript Bridge

The communication between Dart and JavaScript is handled by the dart:js_interop library. The bin/jnap_web.dart file serves as the bridge, exposing Dart functions to the JavaScript environment.

In bin/jnap_web.dart, Dart functions are annotated with @JSExport to make them accessible from JavaScript. These functions are then attached to the window object, making them globally available in the browser.

Usage Example

The dist/index.html file provides a working example of how to use the jnap.js library.

1. Include the Library

First, the jnap.js library is included in the HTML file using a <script> tag:

<script src="jnap.js"></script>

2. Initialize the Library

Before making any JNAP calls, the library must be initialized. This is typically done in a separate <script> block:

// Example initialization
jnap.init({
  // options
});

3. Call JNAP Functions

Once initialized, you can call the exported JNAP functions. Since the Dart functions are asynchronous, the JavaScript functions return Promises.

// Example of calling a JNAP function
jnap.someFunction()
  .then(result => {
    console.log('Success:', result);
  })
  .catch(error => {
    console.error('Error:', error);
  });

By examining the source code of dist/index.html and bin/jnap_web.dart, you can see a complete, working example of how to integrate the JNAP library into a web application.

Running with Nginx

To serve the JNAP JavaScript library and example page using Nginx, follow these steps:

  1. Install Nginx (if not already installed):

    # On macOS (using Homebrew)
    brew install nginx
    
    # On Ubuntu/Debian
    sudo apt update
    sudo apt install nginx
  2. Configure Nginx: Create a new configuration file or update the default one. Here's an example configuration (/usr/local/etc/nginx/nginx.conf on macOS or /etc/nginx/sites-available/default on Ubuntu):

    events {}
    
    http {
        server {
            listen 8080;
            server_name localhost;
    
            # Update this path to point to your dist directory
            root /path/to/privacyGUI/PrivacyGUI/plugins/jnap/dist;
    
            index index.html;
    
            location / {
                try_files $uri $uri/ =404;
            }
    
    
            location /JNAP/ {
                # Replace with your device's IP address
                proxy_pass http://192.168.1.1/JNAP/;
    
    
                # CORS headers
                add_header 'Access-Control-Allow-Origin' '*' always;
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
                add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
            }
        }
    }
  3. Update the paths and configuration:

    • Set the root directive to point to your dist directory
    • Update the proxy_pass URL to point to your JNAP device
    • Adjust the port (8080) if needed
  4. Test the configuration:

    sudo nginx -t
  5. Start/Restart Nginx:

    # On macOS (using Homebrew)
    brew services restart nginx
    
    # On Ubuntu/Debian
    sudo systemctl restart nginx
  6. Access the example page: Open your browser and navigate to http://localhost:8080

API Reference

The library is exposed on the global window object under the jnap namespace.

jnap.init(options)

Initializes the JNAP library with your device's configuration. This must be called before any other methods.

Parameters:

  • options (object): Configuration options.
    • baseUrl (string): The base URL of the JNAP server (e.g., http://localhost:8080).
    • path (string, optional): The path to the JNAP endpoint. Defaults to /JNAP/.
    • extraHeaders (object, optional): A map of extra HTTP headers to send with every request.
    • auth (string): The authentication credentials. For Basic Auth, this must be a Base64 encoded string of username:password.
    • authType (string, optional): The authentication type. Can be 'basic' or 'token'. Defaults to 'basic'.

Example:

window.jnap.init({
  baseUrl: "http://my-router.local",
  auth: "YWRtaW46cGFzc3dvcmQ=", // admin:password
});

jnap.updateAuth(options)

Updates the authentication credentials after initialization.

Parameters:

  • options (object): Authentication options.
    • auth (string, optional): The new authentication credentials.
    • authType (string, optional): The new authentication type.

jnap.send(action, request)

Sends a single JNAP action to the device.

Parameters:

  • action (string): The JNAP action to perform (e.g., http://linksys.com/jnap/core/GetNodes).
  • request (object): The request data for the action.

Returns: A Promise that resolves with the JNAP response object.

jnap.transaction(commands)

Sends a sequence of JNAP actions as a single transaction.

Parameters:

  • commands (array): An array of command objects. Each object should have:
    • action (string): The JNAP action.
    • request (object): The request data for the action.

Returns: A Promise that resolves with the JNAP transaction response object.

jnap.getActionsWithVersions(action)

Gets the fully versioned action string for a given base action.

Parameters:

  • action (string): The base JNAP action (e.g., core/GetNodes).

Returns: A string with the full action URL.

Global Properties

In addition to the functions, the jnap object also exposes the following properties:

jnap.actions

An object containing all available JNAP actions, keyed by their short name (e.g., Core-GetDeviceInfo). This provides an easy way to discover and use the available actions.

jnap.services

An object containing all available JNAP services and their latest versions. This is useful for dynamically discovering the services supported by a device.

Initializes the JNAP library with your device's configuration. This must be called before any other methods.

Parameters:

  • options (object): Configuration options.
    • baseUrl (string): The base URL of the JNAP server (e.g., http://localhost:8080).
    • path (string, optional): The path to the JNAP endpoint. Defaults to /JNAP/.
    • extraHeaders (object, optional): A map of extra HTTP headers to send with every request.
    • auth (string): The authentication credentials. For Basic Auth, this must be a Base64 encoded string of username:password.
    • authType (string, optional): The authentication type. Can be 'basic' or 'token'. Defaults to 'basic'.

Example:

window.jnap.init({
  baseUrl: "http://my-router.local",
  auth: "YWRtaW46cGFzc3dvcmQ=", // admin:password
});

jnap.updateAuth(options)

Updates the authentication credentials after initialization.

Parameters:

  • options (object): Authentication options.
    • auth (string, optional): The new authentication credentials.
    • authType (string, optional): The new authentication type.

jnap.send(action, request)

Sends a single JNAP action to the device.

Parameters:

  • action (string): The JNAP action to execute (e.g., http://linksys.com/jnap/core/GetDeviceInfo).
  • request (object): The request payload for the action.

Returns:

A Promise that resolves with the parsed JSON response from the device.

jnap.transaction(commands)

Sends a batch of JNAP actions in a single transaction.

Parameters:

  • commands (array): An array of command objects.
    • action (string): The JNAP action.
    • request (object): The request payload.

Returns:

A Promise that resolves with the parsed JSON response.

Usage Example

Here is a complete example of how to use the library to get device information.

<!DOCTYPE html>
<html>
<head>
  <title>JNAP JS Library Test</title>
  <script src="jnap.js"></script>
</head>
<body>
  <h1>JNAP Test</h1>
  <p>Check the browser console for output.</p>

  <script>
    async function testJnap() {
      try {
        // 1. Initialize the library
        window.jnap.init({
          baseUrl: "http://localhost:8080",
          path: "/JNAP/",
          extraHeaders: {},
          auth: "YWRtaW46YWRtaW4=", // admin:admin
          authType: "basic",
        });
        console.log("JNAP Initialized");

        // 2. Send a command and await the result
        const deviceInfo = await window.jnap.send(
          "http://linksys.com/jnap/core/GetDeviceInfo",
          {}
        );
        console.log("Response from GetDeviceInfo:", deviceInfo);

      } catch (error) {
        console.error("An error occurred:", error);
      }
    }

    // Run the test
    testJnap();
  </script>
</body>
</html>

Building from Source

The jnap.js file is compiled from Dart source code located in the lib and bin directories. To make changes, edit the .dart files and then recompile using the Dart SDK.

Command:

dart compile js -O2 -o dist/jnap.js bin/jnap_web.dart