OpenROV / openrov-software

Meta project for all of the OpenROV Software projects
http://openrov.com
Other
422 stars 188 forks source link

Proposal for architecture to support discovery of new web controls in a theme #555

Closed BrianAdams closed 8 years ago

BrianAdams commented 8 years ago

Part of #506, #442

This proposal is in DRAFT and open to discussion.

Problem statement:

Today, each control has to be manually wired in to each theme. If someone creates a new plugin that has a cool new control for displaying an aspect of the telemetry, each theme developer would have to manually integrate that control. We would like a system where a properly classified control can be discovered and automatically loaded without a theme developers involvement.

Overview

Introduce a class of web control behaviors that expose public messages for the discovery of classes of controls.

From #442:

The semantic portions of the UI that I am proposing are based on the current information management practices that designed the A340 cockpit controls, modified for our domain.

Semantic ares of the Cockpit UI

System Panel : status indicator of things like lights, flight mode, etc Navigation Display: routes information, navigation aids Primary Flight Display: altitude, speed, heading... Standby Instruments: alternative display information if Primary Flight Display instruments are insufficient Warning Display: for system warning messages and alerts System Display: temp, time, battery remaining Flight Control State: throttle, rudder state information Multipurpose Display: for special modal operations like flight planning Flight Control Unit: state of autopilot or assist systems Data Control Display: text based chat, bandwidth monitor Primary Video:

The above sections can be named: system-panel nav-display primary-flight-display standy-flight-display warning-display systems-display flight-control-state multipurpose-display flight-control-unit data-control-unit camera-display

Let use "warning-display" as an example:

<warning-display-panel discover-widgets="true">
  <theme-custom-battery-warning overrides="battery-warning">
</warning-display-panel>

When rendered it would look something like

<warning-display-panel discover-widgets="true">
  <theme-custom-battery-warning overrides="battery-warning">
  <!-- battery-warning></battery-warning-->
  <max-depth-warning></max-depth-warning> 
  <thruster-warning></thruster-warning>
</warning-display-panel>

Where all of the other widgets were automatically discovered and injected as content controls within the panel.

A panel developer can always create settings for the panel that can be managed through the settings screen for fine tuning the widgets. They could for instance discover the compatible widgets and still require that the user click enable in settings for the widget to be pulled in to the panel.

A panel developer can also integrate many of these classes of widgets in a single panel.

A theme developer can choose to put any number of these panels in an applet, and may choose to put one version of a panel with a fixed number of widgets along side a second copy of the panel that is using automatic discovery.

The concept for automatically discovered controls are not limited to the panels above. The same concept would work for classifying a widget as a "switch" which would imply it has on/off/state behaviors without implying which panel it should belong in.

Discovery and Widget contracts

The widgets should only exist in browser space if the panel intends to instantiate it. This creates a chicken and egg problem where we cannot interrogate the widget directly unless it has already been instantiated.

Approach-1

Discovery is through duck typing of the widget interface by the panel. If the panel requires that the widget support on(),off(), and a onStateChange handler it needs to check for those. We propose the duck typing checks over exposing "named" interfaces to allow redefinition of panel concepts in the future. We create a web control that runs on the front end. That web control has a server side plugin that enumerates a web controls in the file directories. It then loads each web control and interrogates them and then discards them.
These web controls can load inside a hidden div tag and will not be wired to the event emitter. It might take noticeable time to run through all of the widgets in which case we might end up needing a small loading screen. It might take a lot of memory to load all controls. In which case we can load the components one by one. This widget registry accepts messages from the panels that ask for a filtered list of widgets that match its filter function.

Approach-2

To discover the widgets that are available, we use a server side process that crawls the plugin\public\lib folders for widget registration file(widget_name-autodiscovery.js) that identifies the interfaces that the widget supports.

(function (window) {
  'use strict';
  var widgets = namespace('widgets');
  widgets['orov-blackbox'] = {
    name: 'orov-blackbox',
    defaultUISymantic: 'multipurpose-display',
    url: 'blackbox/orov-blackbox.html'
  };
  widgets['orov-blackbox-status'] = {
    name: 'orov-blackbox-status',
    defaultUISymantic: 'system-panel',
    url: 'blackbox/orov-blackbox-status.html'
  };
} (window));

Widget Interfaces

To make this work, lets assume that all well behaved widgets that are discoverable are required to support any sizing that is sent down from the parent. If the widget needs to switch from a text display to an icon display as it shrinks, that should be a default detect and adjust feature within the widget.

There are situations where for consistency, the template author wants to display just icons, or just text. Those the widgets should support a behavior that allows that control from the panel. Some classes of widgets have pre-defined states that are required. For instance "switch" can be off,on,transitioning. As well as pre-defined functions and events, on(), off(), on-state-change There is nothing that should prevent a widget from being incorporated in multiple panels if it supports the minimal set of interfaces that each panel requests.

BrianAdams commented 8 years ago

@spiderkeys @joakar , looking for feedback.

BrianAdams commented 8 years ago

An implementation of the widget-registry can be found in this PR: https://github.com/OpenROV/openrov-cockpit/pull/124

spiderkeys commented 8 years ago

One thing I'm rolling around in my head is that for discovery, it may not be that you want discovery of widgets to auto-populate a panel, but that you want to automatically discover signals or inputs and then display them with a compatible widget. We may have multiple sources of a type of signal (like a temperature; we may have 7 temp sensors in the vehicle). We may have multiple widgets that are capable of displaying that signal in different ways (text, bar graph, dial, etc).

What I think we might want to consider is two sets of registration. One is the registration of widgets that you describe above. Something I would add on to that registration is the registration of inputs and outputs and their types.

A temperature gauge would accept an input of numeric type, with subtype temperature. It would register itself as such a widget. If someone develops a plugin that talks to the MCU and emits 7 temperature values, those get registered as numeric temperatures in cockpit's "signal space". When the System Display panel does its initial setup, I would argue that it shouldn't be searching for which widgets are registered to fill up with. I would argue that it would instead search for temperature signals (and other system signals) and then search for widgets which fulfill the ability to display the data, allowing some kind of default setting which is overrideable by a theme designer. I could also imagine signals being registered with the "panel" type they're supposed to be in like "system". Ideally, you could add as many "labels" to a signal's type that you want and allow panels to pick and choose based on those labels however they like, like searching a database.

This also allows widgets which produce signals to be automatically routed to other UI elements which accept those signals, not just signals that are produced by a cockpit plugin.

Here is a diagram which hopes to explain what I'm getting at:

screenshot_20160901_143843

BrianAdams commented 8 years ago

The test case of handling n number of temperature readings is a really good one.

I like the idea of the smart-panels (signalManager) that are built to handle classes of messages such as telemetry data. Still chewing on the level of granularity to aim for in specifying the labels or properties of the widgets.

I have been mixing two different types of meta data surrounding the widgets.

And while we can combine the concepts in a single widget, I suspect we will end up with mostly two classes of widgets

Where many of the purpose built are likely to be heavy customization over the generic widgets.

Another concept that is half baked has to do with handling the default battery gauge use case. It makes sense that over time we will end up with a dozen battery fuel gauge widgets that are purpose built for showing the remaining battery. We will also have lots of generic telemetry gauges that could also display the remaining battery.

As a theme developer I want to either select the default fuel gauge to be used in my theme, or I want to include a custom fuel gauge that is tightly coupled with the look of the theme.

The theme developer can always hard code a widget in to the theme. But every time they do that they take away from the user being able to use a plugin to override that part of the theme.

It would be better to have the theme developer create smart panels, even if the panel is simply a place holder for a single widget, then describe the nature of the widgets that can be loaded in to the panel, and to be able to specify a default widget that can be over-ridden sometime in the future. Note, you can nest panels

<smart-panel widget-limit="1" compatible-well-know-widget-classes="fuel-gauge">
  <blue-theme-fuel-gauge out-of-fuel-icon="fonticon5"></blue-theme-fuel-gauge>
</smart-panel> 

The above concept would allow a theme developer to designate where in the theme the fuel gauge should live, yet provide a way for other widgets to be substituted in the future. It also specifies the semantic meaning implied by limiting the compatible widgets to only ones that claim to also be a "fuel-gauge".

And what about the temperatures example

<smart-telemetry-panel telemetry-match-regex="tmp*" compatible-well-know-widget-classes="gauge,numeric-label" default-widget="simple-circle-guage">
</smart-telemetry-panel> 

As a user I want to be able to use the default theme, and I want to be able to add plugins that introduce a new battery fuel gauge and to tell the theme to use the plugin's fuel gauge instead.

For the user things are simple. I am assuming we add UI tools to facilitate on screen configuration of the different panels. Our existing settings-manager will take care of saving and retrieving those settings for each widget that needs it.

For the panels that limit the class of UI widgets they are made to work with, the UI tools would simply filter out those widgets that don't fit when presenting selectors to the user for the widget they want to replace.

BrianAdams commented 8 years ago

Committed in https://github.com/OpenROV/openrov-cockpit/pull/124