jahmin
Version:
A JavaScript framework to build browser friendly Human Machine Interfaces for automation
265 lines (264 loc) • 12.6 kB
HTML
<!-- start:source.tmpl.hbs -->
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>ServiceManager.js</title>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link href="https://fonts.googleapis.com/css?family=PT+Mono" rel="stylesheet">
<link type="text/css" rel="stylesheet" href="css/bootstrap.min.css">
<link type="text/css" rel="stylesheet" href="css/prism.min.css">
<link type="text/css" rel="stylesheet" href="css/template.min.css">
<script type="text/javascript">
window.TEMPLATE_OPTIONS = {"includeDate":true,"dateFormat":"Do MMM YYYY","systemName":"JaHMIn","systemSummary":"A Javascript framework to build Human Machine Interfaces for IoT","systemLogo":"","systemColor":"","navMembers":[{"kind":"class","title":"Classes","summary":"All documented classes."},{"kind":"external","title":"Externals","summary":"All documented external members."},{"kind":"global","title":"Globals","summary":"All documented globals."},{"kind":"mixin","title":"Mixins","summary":"All documented mixins."},{"kind":"interface","title":"Interfaces","summary":"All documented interfaces."},{"kind":"module","title":"Modules","summary":"All documented modules."},{"kind":"namespace","title":"Namespaces","summary":"All documented namespaces."},{"kind":"tutorial","title":"Tutorials","summary":"All available tutorials."}],"footer":"","copyright":"FooDoc Copyright © 2016 The contributors to the JSDoc3 and FooDoc projects.","linenums":true,"collapseSymbols":true,"inverseNav":true,"inlineNav":false,"outputSourceFiles":true,"sourceRootPath":null,"disablePackagePath":true,"outputSourcePath":false,"showTableOfContents":true,"showAccessFilter":true,"analytics":null,"methodHeadingReturns":true,"sort":"linenum, longname, version, since","search":true,"favicon":null,"stylesheets":[],"scripts":[],"monospaceLinks":false,"cleverLinks":false,"theme":"yeti"};
window.DOCLET_TOC_ENABLED = false;
window.DOCLET_AFILTER_ENABLED = false;
</script>
</head>
<body>
<!-- start:navbar.hbs -->
<header class="navbar navbar-default navbar-fixed-top navbar-inverse">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="index.html">
JaHMIn
</a>
<!-- displayed on small devices -->
<button class="navbar-toggle" type="button" data-toggle="collapse" data-target="#topNavigation">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-collapse collapse" id="topNavigation">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="global.html" class="dropdown-toggle" data-toggle="dropdown">Globals<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="global.html#VarStatusCodes">VarStatusCodes</a></li>
</ul>
</li>
<li class="dropdown">
<a href="list_class.html" class="dropdown-toggle" data-toggle="dropdown">Classes<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="DataCommsEngine.html">DataCommsEngine</a></li>
<li><a href="DataTree.html">DataTree</a></li>
<li><a href="ErrorCodes.html">ErrorCodes</a></li>
<li><a href="ServiceManager.html">ServiceManager</a></li>
<li><a href="ServiceStatusCodes.html">ServiceStatusCodes</a></li>
<li><a href="systemError.html">systemError</a></li>
<li><a href="systemObject.html">systemObject</a></li>
<li><a href="systemVariable.html">systemVariable</a></li>
<li><a href="VarResponse.html">VarResponse</a></li>
</ul>
</li>
<li class="dropdown">
<a href="list_tutorial.html" class="dropdown-toggle" data-toggle="dropdown">Tutorials<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="tutorial-Getting-Started.html">Getting-Started</a></li>
</ul>
</li>
</ul>
<!-- start:lunr-search-navbar.hbs -->
<form class="navbar-form navbar-right" role="search">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search" id="lunr-search-input">
<div class="input-group-btn">
<button class="btn btn-default" id="lunr-search-submit">
<i class="glyphicon glyphicon-search"></i>
</button>
</div>
</div>
</form>
<!-- start:lunr-search-navbar.hbs --> </div>
</div>
</header>
<!-- end:navbar.hbs --> <div class="page-header">
<div class="container">
<span class="kind">source</span>
<h1><span class="name">ServiceManager.js</span></h1>
</div>
</div>
<div class="container content">
<div class="row">
<div class="col-md-12 main-content">
<section class="source-section">
<article></article>
<pre class="prettyprint source language-javascript line-numbers"><code class="language-javascript">import { systemVariable, ServiceStatusCodes, VarStatusCodes, systemError, Actions, ErrorCodes } from './DataModels/Types.js';
import { DataTree } from './DataModels/DataTree.js';
import { escape as escapeHtml } from 'html-escaper';
import { ErrorTray } from './DataModels/ErrorTray.js';
/**Organizzational class */
export class ServiceManager {
constructor() {
this.dataTree = new DataTree();
this.errorTray = new ErrorTray("errortray");
this.dataEngines = new Map();
this.status = ServiceStatusCodes.Down;
this._initPromise = new Promise((resolve) => {
this._initResolve = resolve;
});
this._defaultEngine = null;
}
/**
*
* @param subsystemName
* @param engine
*/
AddEngine(engine) {
let subsystemName = escapeHtml(engine.name);
this.dataEngines.set(subsystemName, engine);
engine.manager = this;
if (this._defaultEngine === null)
this._defaultEngine = engine;
}
SetDefaultEngine(engine) {
if (!this.dataEngines.has(engine.name))
this.AddEngine(engine);
this._defaultEngine = engine;
}
GetEngine(engine_name) {
if (typeof engine_name !== "string")
throw Error("Engine Name must be a string");
if (engine_name.toLocaleLowerCase() === "default")
return this._defaultEngine;
else
return this.dataEngines.get(engine_name);
}
async Subscribe(engine_name, target) {
if (typeof target.name !== "string" || typeof target.system !== "string")
throw Error("CANNOT SUBSCRIBE variable " + target.name);
await this.isInitialized();
target.name = escapeHtml(target.name);
target.system = escapeHtml(target.system);
let engine = this.GetEngine(engine_name);
if (engine) {
if (this.dataTree.ExistVar(target)) {
if (!engine.isVarSubscribed(target) && this.dataTree.GetVar(target).status !== VarStatusCodes.Pending) // var exist from localstorage but not yet subscribed
this.dataTree.UpdateStatus(target, VarStatusCodes.Pending);
}
else
this.dataTree.Create(target);
engine.RequestSubscription(target);
}
else {
this.dataTree.Create(target);
this.dataTree.UpdateStatus(target, VarStatusCodes.Error);
this.CreateAndDispatchError(target.system, ErrorCodes.EngineNotExist, "", Actions.Subscribe);
throw new Error(`Engine '${engine_name}' does not exist.`);
}
}
async Unsubscribe(engine_name, target) {
if (typeof target.name !== "string" || typeof target.system !== "string")
throw Error("CANNOT UNSUBSCRIBE variable " + target.name);
await this.isInitialized();
let engine = this.GetEngine(engine_name);
if (engine) {
engine.RequestUnsubscription(target);
}
else {
this.CreateAndDispatchError(target.system, ErrorCodes.EngineNotExist, "", Actions.Unsubscribe);
throw new Error(`Engine '${engine_name}' does not exist.`);
}
}
Update(data) {
this.dataTree.Update(data);
}
async Read(engine_name, vars) {
if (typeof vars !== "object")
throw new TypeError("'system' must be a string and 'vars' an array of strings");
await this.isInitialized();
let engine = this.GetEngine(engine_name);
if (engine) {
let resp = await engine.Read(vars);
// Maybe here we need something like STATUS OK - if was in error it is not clear that it would be subscribed
// see issue https://github.com/JaS-HMI/jashmi/issues/2
engine.UpdateVars(resp, VarStatusCodes.Subscribed, Actions.Read);
return resp;
}
else {
this.CreateAndDispatchError(engine_name, ErrorCodes.EngineNotExist, "", Actions.Read);
throw new Error(`Engine '${engine_name}' does not exist.`);
}
}
async Write(engine_name, vars, values) {
if (typeof vars !== "object" ||
typeof values !== "object")
throw new TypeError("'system' must be a string and 'vars' and values cannot be null");
await this.isInitialized();
let engine = this.GetEngine(engine_name);
if (engine) {
let sys_vars = vars.map(v => { let x = new systemVariable(v); x.status = VarStatusCodes.Pending; return x; });
this.dataTree.Update(sys_vars);
let resp = await engine.Write(vars, values);
// Maybe here we need something like STATUS OK - if was in error it is not clear that it would be subscribed
// see issue https://github.com/JaS-HMI/jashmi/issues/2
engine.UpdateVars(resp, VarStatusCodes.Subscribed, Actions.Write);
return resp;
}
else {
this.CreateAndDispatchError(engine_name, ErrorCodes.EngineNotExist, "", Actions.Write);
throw new Error(`Engine '${engine_name}' does not exist.`);
}
}
DispatchError(error) {
this.errorTray.Create(error);
}
CreateAndDispatchError(system, code, target = "", action = "") {
let error = new systemError(system, code, target, action);
this.DispatchError(error);
}
async Init() {
this.status = ServiceStatusCodes.Warming;
let proms = [];
Array.from(this.dataEngines.values()).forEach(engine => proms.push(engine._init()));
await Promise.all(proms);
this.status = ServiceStatusCodes.Ready;
// signal that all the engines are added, can start
// adding variables to subscription list
this._initResolve(true);
}
isInitialized() {
return this._initPromise;
}
}
// A bit ugly, but we must have a data instance that is shared
// automatically between the ui-elements
export var Manager = new ServiceManager();
</code></pre>
</section>
</div>
</div>
</div>
<footer>
<div class="copyright">FooDoc Copyright © 2016 The contributors to the JSDoc3 and FooDoc projects.</div>
<div class="generated-by">Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.7</a> on 11th Jun 2021 using the <a href="https://github.com/steveush/foodoc">FooDoc template</a>.</div>
</footer>
<script src="js/jquery.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/clipboard.min.js"></script>
<script src="js/prism.min.js"></script>
<script src="js/template.min.js"></script>
<!-- start:lunr-search-modal.hbs -->
<div class="modal fade" id="lunr-search-modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">Search results</h4>
</div>
<div class="modal-body" id="lunr-search-body">
</div>
<div class="modal-footer" id="lunr-search-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
<!-- end:lunr-search-modal.hbs --> <script src="js/lunr.min.js"></script>
</body>
</html>
<!-- end:source.tmpl.hbs -->