graphem
TypeScript icon, indicating that this package has built-in type declarations

2.0.3 • Public • Published

Graphem

Graphem

🚀 Connector to integrate GraphQL to NASA OpenMCT in queries and subscriptions.

🚀 www.graphem.space 🪐

Demo of Graphem

🚀 Concept

Graphem is a plugin that allows viewing telemetry data in NASA Open MCT directly from a GraphQL server.

  • NASA Open MCT is a next-generation mission operations data visualization framework. Web-based, for desktop and mobile.

  • GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data.

🛃 All with support for TypeScript.

🪐 Installation

You can install Graphem from your favorite package manager:

# Yarn
yarn add graphem
# NPM
npm install graphem

Once installed in your project you can integrate it in the <head> tag using:

<script src="node_modules/graphem/dist/index.js"></script>

Before connecting the GraphQL server you will need a JSON dictionary file. This file contains the structure of the folder, how each subscription is managed, and the naming of the units. This is file is usually stored in the client.

Here is a basic example with the prop_happiness object:

/* dictionary.json */
{
  "name": "Name of the mission",
  "key": "your_key",
  "measurements": [
    {
      "name": "Happiness",
      "key": "prop_happiness",
      "values": [
        {
          "key": "value",
          "name": "Value",
          "units": "kilograms",
          "format": "float",
          "min": 0,
          "max": 100,
          "hints": {
            "range": 1
          }
        },
        {
          "key": "utc",
          "source": "timestamp",
          "name": "Timestamp",
          "format": "utc",
          "hints": {
            "domain": 1
          }
        }
      ]
    }
  ]
}

🔌 And finally you can connect the plugin with the necessary information from your GraphQL server.

...

openmct.install(Graphem({
    namespace: "rocket.taxonomy", // Custom namespace
    key: "orion", // Custom Key
    dictionaryPath: "/dictionary.json", // Path of dictionary
    telemetryName: "rocket.telemetry", // Name of telemetry
    subscriptionName: "formatted", // Name of the <GraphQL> subscription for historical telemetry
    urn: "localhost:4000/graphql" // Source URN (Uniform Resource Name)
}));

openmct.start();

🛰 Create a GraphQL server

In order to use Graphem correctly you can use the server template that we provide.

Template GraphQL server from Graphem

This server has a query available to obtain historical telemetry values, and a subscription to obtain real-time telemetry values.

It has minimal setup in TypeScript, and comes with Nodemon ideal for development on top of it.

💻 Development

Structure

Graphem's source code is written in TypeScript. This is a file with a default export function called Graphem. This Graphem function returns a function install.

export default function Graphem(configuration: IGraphemConfiguration) {
  ...
  return function install(openmct: IOpenMCT) {
    ...

I developed this following the structure recommended by the NASA Open MCT documentation for plugins. So the install function is the function that is executed when importing and using the plugin in a client with Open MCT.

In both cases we use an interface to check the passed parameters. IGraphemConfiguration is defined at installation time and contains information about the connection between GraphQL and Open MCT.

IOpenMCT instead is an interface to ensure intellisense over Open MCT functions. Since Open MCT is not written in TypeScript.

⚙️ Configuration Object

The configuration object of Graphem is a parameter that contains relevant information to start with the plugin. This object is defined by the IGraphemConfiguration interface. Some fields are necessary, and others are optional.

interface IGraphemConfiguration {
  namespace: string;
  key: string;
  dictionaryPath: string;
  telemetryName: string;
  subscriptionName: string;
  urn: string;
  telemetryType?: {
    name: string;
    description: string;
    cssClass?: string;
  };
}

🎟 GraphQL Client Connection

When installing Graphem we create a GraphQL client whose main purpose will be to provide real-time information about the data transferred.

As the real-time transfer is established on WebSocket. A computer communications protocol that provides full-duplex communication channels.

When establishing the connection we require the server address, this address can vary a lot in each use case, so it is established through the URN variable in the Graphem configuration when installed.

Also the createClient function comes from graphql-ws library.

const client = createClient({
  webSocketImpl: WebSocket,
  url: `ws://${configuration.urn}`,
});

🌳 Root creation

Before connection and population of data, Graphem will set a new object root. This process will expose a telemetry folder as a hierarchy of telemetry-providing domain objects.

const objectRoot = {
  namespace: configuration.namespace,
  key: configuration.key,
};
openmct.objects.addRoot(objectRoot);

🧭 Object Provider

The object provider will build Domain Objects. The structure of the Domain Objects comes from the dictionary.

const objectProvider: ObjectProvider = {
  get: async (identifier: DomainObjectIdentifier) => {
    const dictionaryResponse = await fetch(configuration.dictionaryPath);
    const dictionary = await dictionaryResponse.json();
    if (identifier.key === configuration.key) {
      return {
        identifier,
        name: dictionary.name,
        type: OBJECT_TYPE.FOLDER,
        location: "ROOT",
      };
    } else {
      const measurement = dictionary.measurements.find(
        (m: Measurement) => m.key === identifier.key
      );
      return {
        identifier,
        name: measurement.name,
        type: configuration.telemetryName,
        telemetry: {
          values: measurement.values,
        },
        location: `${configuration.namespace}:${configuration.key}`,
      };
    }
  },
};

openmct.objects.addProvider(configuration.namespace, objectProvider);

🗂 Composition Provider

This is a crucial part of Graphem. While Open MCT provides a solution for a composition provider, in Graphem we define a custom composition provider.

Every provider has appliesTo and load methods.

The appliesTo method will filter domain objects by the namespace specified in the configuration parameter, and by the type of FOLDER.

After that we load (from the load method) the mesaurements objects from the JSON dictionary. This process starts requesting the object from a dictionaryPath (provided by the NASA developer) and then destructuring each object returning the key property with the namespace as a whole object in an array.

const compositionProvider = {
  appliesTo: (domainObject: DomainObject) => {
    return (
      domainObject.identifier.namespace === configuration.namespace &&
      domainObject.type === OBJECT_TYPE.FOLDER
    );
  },
  load: async () => {
    const dictionaryResponse = await fetch(configuration.dictionaryPath);
    const dictionary = (await dictionaryResponse.json()) as IDictionary;
    return dictionary.measurements.map((m: Measurement) => {
      return {
        namespace: configuration.namespace,
        key: m.key,
      };
    });
  },
};

openmct.composition.addProvider(compositionProvider);

🏛️ History

The development of Graphem began by generating a prototype of how to build a plugin that obtains basic GraphQL queries. Although I was able to use the Apollo client, I preferred to use the fetch API to get more lightness in the plugin.

The structure of Graphem will be the following. It is made up of a part to integrate domain objects with object provider and composition provider. Then require the historical data, to display it on the screen, and finally require the real-time data continuously to link them on the same screen.

I was inspired by NASA Spacecraft tutorial to develop these parts.

Currently NASA Open MCT does not support TypeScript (see these issues), but for a better development experience this plugin was built on it.

For better integration with the Graphem package it uses RollUp, a module bundler, in the same style as Open MCT YAMCS. Thanks to this same configuration, it will export a file in UMD (Universal Module Definition) format.

🤲 Contributing

Do you would like to contribute? Do you want to be the author of a new feature? Awesome! please fork the repository and make changes as you like. Pull requests are warmly welcome.

📃 License

Distributed under the Apache 2.0 License. See LICENSE for more information.

Install

npm i graphem

DownloadsWeekly Downloads

6

Version

2.0.3

License

Apache-2.0

Unpacked Size

64.3 kB

Total Files

5

Last publish

Collaborators

  • 360macky