UNPKG

webgme-gridlabd

Version:

Metamodel, visualization, and model generators for gridlab-d in WebGME. Allows graphical model-driven development and simulation of power grids and power generation / transmission / distribution / storage systems.

238 lines (203 loc) 6.57 kB
/*globals define*/ /*jshint node:true, browser:true*/ /** * Generated by PluginGenerator 0.14.0 from webgme on Mon Apr 04 2016 12:18:55 GMT-0700 (PDT). */ define([ 'plugin/PluginConfig', 'text!./metadata.json', 'plugin/PluginBase', 'gridlabd/meta', 'gridlabd/modelLoader', 'gridlabd/renderer', 'q' ], function ( PluginConfig, pluginMetadata, PluginBase, MetaTypes, loader, renderer, Q) { 'use strict'; pluginMetadata = JSON.parse(pluginMetadata); /** * Initializes a new instance of SimulateWithGridlabD. * @class * @augments {PluginBase} * @classdesc This class represents the plugin SimulateWithGridlabD. * @constructor */ var SimulateWithGridlabD = function () { // Call base class' constructor. PluginBase.call(this); this.pluginMetadata = pluginMetadata; this.metaTypes = MetaTypes; }; /** * Metadata associated with the plugin. Contains id, name, version, description, icon, configStructue etc. * This is also available at the instance at this.pluginMetadata. * @type {object} */ SimulateWithGridlabD.metadata = pluginMetadata; // Prototypal inheritance from PluginBase. SimulateWithGridlabD.prototype = Object.create(PluginBase.prototype); SimulateWithGridlabD.prototype.constructor = SimulateWithGridlabD; SimulateWithGridlabD.prototype.notify = function(level, msg) { var self = this; var prefix = self.projectId + '::' + self.projectName + '::' + level + '::'; if (level=='error') self.logger.error(msg); else if (level=='debug') self.logger.debug(msg); else if (level=='info') self.logger.info(msg); else if (level=='warning') self.logger.warn(msg); self.createMessage(self.activeNode, msg, level); self.sendNotification(prefix+msg); }; /** * Main function for the plugin to execute. This will perform the execution. * Notes: * - Always log with the provided logger.[error,warning,info,debug]. * - Do NOT put any user interaction logic UI, etc. inside this method. * - callback always has to be called even if error happened. * * @param {function(string, plugin.PluginResult)} callback - the result callback */ SimulateWithGridlabD.prototype.main = function (callback) { // Use self to access core, project, result, logger etc from PluginBase. // These are all instantiated at this point. var self = this, modelNode; self.result.success = false; if (typeof WebGMEGlobal !== 'undefined') { var msg = 'You must run this plugin on the server!'; self.notify('error', msg); callback(new Error(msg), self.result); } self.updateMETA(self.metaTypes); // What did the user select for our configuration? var currentConfig = self.getCurrentConfig(); self.returnZip = currentConfig.returnZip; modelNode = self.activeNode; self.modelName = self.core.getAttribute(modelNode, 'name'); self.fileName = self.modelName + '.glm'; var path = require('path'); var filendir = require('filendir'); self.root_dir = path.join(process.cwd(), 'generated', self.project.projectId, self.branchName, 'models'); return loader.loadModel(self.core, modelNode, true, true) .then(function(powerModel) { self.powerModel = powerModel; }) .then(function() { return self.renderModel(); }) .then(function() { return self.writeInputs(); }) .then(function() { return self.runSimulation(); }) .then(function() { return self.generateBlobArtifacts(); }) .then(function() { self.result.success = true; self.createMessage(self.activeNode, 'Simulation Complete.'); callback(null, self.result); }) .catch(function(err) { self.result.success = false; self.createMessage(self.activeNode, err, 'error'); callback(err, self.result); }); }; SimulateWithGridlabD.prototype.renderModel = function() { var self = this; self.notify('info', 'Rendering GLM'); self.fileData = renderer.renderGLM(self.powerModel, self.core, self.META); }; SimulateWithGridlabD.prototype.writeInputs = function() { var self = this, basePath = self.root_dir, inputFiles = {}, fs = require('fs'), path = require('path'), filendir = require('filendir'); inputFiles[self.fileName] = self.fileData; self.notify('info', 'Creating input files'); var fileNames = Object.keys(inputFiles); var tasks = fileNames.map((fileName) => { var deferred = Q.defer(); var data = inputFiles[fileName]; filendir.writeFile(path.join(basePath, fileName), data, (err) => { if (err) { deferred.reject('Couldnt write ' + fileName + ': ' + err); } else { deferred.resolve(); } }); return deferred.promise; }); return Q.all(tasks) .then(function() { self.notify('info', 'Generated artifacts.'); }); }; SimulateWithGridlabD.prototype.runSimulation = function() { var self = this; var path = require('path'); var cp = require('child_process'); self.notify('info', 'Starting Simulation'); var deferred = Q.defer(); var fname = path.join(self.root_dir, self.fileName); self.sim_stdout = ''; self.sim_stderr = ''; self.simProcess = cp.spawn('gridlabd', [fname], { cwd: self.root_dir }); self.simProcess.stdout.on('data', (data) => { self.sim_stdout += data; }); self.simProcess.stderr.on('data', (data) => { self.sim_stderr += data; }); self.simProcess.on('close', (code) => { self.notify('info', 'Simulation exited with code: ' + code); deferred.resolve(); }); self.simProcess.on('error', (err) => { deferred.reject('Couldnt run simulation: ' + err); }); return deferred.promise; }; SimulateWithGridlabD.prototype.generateBlobArtifacts = function() { var self = this; if (!self.returnZip) { self.notify('info', 'User did not request the output to be returned.'); return; } var path = require('path'); var stdoutFile = self.modelName + '.stdout'; var stderrFile = self.modelName + '.stderr'; self.notify('info', 'Returning output to user.'); return self.blobClient.putFile(stdoutFile, self.sim_stdout) .then(function (hash) { self.result.addArtifact(hash); }) .then(function() { return self.blobClient.putFile(stderrFile, self.sim_stderr); }) .then(function (hash) { self.result.addArtifact(hash); }); }; return SimulateWithGridlabD; });