Create a gist now

Instantly share code, notes, and snippets.

A Matlab class for processing APMonitor models on a remote server
% APMONITOR A class for processing APMonitor models on a remote server.
%
% SYNOPSIS
%
% apmonitor(server)
% Initializes an APMonitor application on a remote server and
% returns an object with methods to upload, solve, and download
% application data. Results in an error if the server does not
% respond.
%
% server url string of the host server.
%
% USAGE
%
% a = apmonitor
% Creates an APMonitor application on the default server.
%
% a = apmonitor('http://xps.apmonitor.com')
% Creates an APMonitor application on the named server.
%
% METHODS
%
% response = a.apm(command)
% response = apm(a,command)
% Return the response to a command to APMonitor server.
% 'solve' : solve the loaded model
% 'clear all' : clear application and all files
% 'clear apm' : clear model file (.apm)
% 'clear csv' : clear data file (.csv)
% 'info {FV,MV,SV,CV} {name}' : create interface to variable
% 'ss.t0 {values}' : load ss.t0 restart file
% 'csva {contents}' : add contents to .csv data file
% 'csv {line}' : add one line to .csv data file
% 'apm {contents}' : add to apm file without c/r
% '{otherwise}' : add line to apm file
% 'option {name} = {value}' : set an option
%
% a.webroot
% webroot(a)
% Show all files on the server using the default browser.
%
%
%
% DEVELOPMENT NOTES
%
% * The constructor was kept simple because it is hard to predict the
% use cases for the class. The purpose of the constructor is to
% instantiate the apmonitor object, confirm that the APMonitor server
% is available, and initialize an application on the server. A
% destructor 'delete' executes a 'clear all' on the server when there is
% no longer any reference to the object.
%
% * The apmonitor object is a subclass of handle. This makes it
% possible for class methods to modify the class object.
%
% * Because an object has it's own name inside the Matlab workspace,
% the application name on the remote server appears redundant and
% potentially confusing to a new user. Therefore the design decision was
% to more or less hide the remote app name from the end user.
%
classdef apmonitor < handle
properties
server = 'http://byu.apmonitor.com' % default server
app = ''
results
vars
solver = 1 % 1:APOPT 2:BPOPT 3:IPOPT
imode = 3 % 3:
end
properties (Dependent = true)
% properties with getters
url_base
ip
appstatus
ctrlmode
cyclecount
iterations
objfcnval
solvestatus
solvetime
end
methods
% Class constructor, initializing server and app name
function obj = apmonitor(server)
if(nargin > 0)
obj.server = deblank(server);
else
% force a call to the setter function set.server
obj.server = obj.server;
end
obj.app = lower(deblank(['app' int2str(rand()*100000)]));
end
% Class destructor. Called automatically to clears APMonitor server
% when there are no longer any references to the object.
function delete(obj)
obj.apm('clear all');
end
% setter function for server url
function set.server(obj,url)
oldurl = obj.server;
obj.server = url;
try
obj.apm('clear all');
catch
obj.server = oldurl;
error(['Error reading ' url]);
end
end
% getter function for server url
function url = get.server(obj)
url = obj.server;
end
% getter function for obj.ip
function ip = get.ip(obj)
ip = deblank(urlread([obj.server '/ip.php']));
end
% getter function for obj.url_base
function url = get.url_base(obj)
url = [obj.server '/online/apm_line.php'];
end
% getter function for obj.appstatus
function y = get.appstatus(obj)
y = obj.tag('nlc.appstatus');
end
% getter function for obj.ctrlmode
function y = get.ctrlmode(obj)
y = obj.tag('nlc.ctrlmode');
end
% getter function for obj.cyclecount
function y = get.cyclecount(obj)
y = obj.tag('nlc.cyclecount');
end
% getter function for obj.iterations
function y = get.iterations(obj)
y = obj.tag('nlc.iterations');
end
% getter function for obj.objfcnval
function y = get.objfcnval(obj)
y = obj.tag('nlc.objfcnval');
end
% getter function for obj.solvestatus
function y = get.solvestatus(obj)
y = obj.tag('nlc.solvestatus');
end
% getter function for obj.solvetime
function y = get.solvetime(obj)
y = obj.tag('nlc.solvetime');
end
% APM: send command to server and return response filter for \r
function response = apm(obj,aline)
params = {'p',obj.app,'a',aline};
response = strrep(urlread(obj.url_base,'get',params),'\r','');
end
% APMLOAD: load .apm file to server
function response = apmload(obj,filename)
fid=fopen(filename,'r');
if fid < 0
error(['File ' filename ' not found.']);
end
tline = [];
while ~feof(fid)
tline = [tline fgets(fid)];
end
fclose(fid);
len = size(tline,2);
blocksize = 2000;
j = 1;
while j <= len
k = min(j+blocksize,len);
obj.apm(['apm ' tline(j:k)]);
j = k + 1;
end
response = 'Successfully loaded APM file';
end
% CSVLOAD: load .csv file to server
function response = csvload(obj,filename)
fid=fopen(filename,'r');
if fid < 0
error(['File ' filename ' not found.']);
end
tline = [];
while ~feof(fid)
% remove any double quote marks
tline = [tline strrep(fgets(fid),'"',' ')];
end
fclose(fid);
len = size(tline,2);
blocksize = 2000;
j = 1;
k = min(j+blocksize,len);
while k < len
obj.apm(['csva ' tline(j:k)]);
j = k;
k = min(j+blockize,len);
end
obj.apm(['csv ' tline(j:end)]);
response = 'Successfully loaded CSV file';
end
% OPTION: sends option specification to the APMonitor server
function response = option(obj,name,value)
response = apm(obj,['option ' deblank(char(name)) '=' num2str(value)]);
end
% SOL: retrieve solution to results file and load into object
function y = sol(obj)
url = [obj.server '/online/' obj.ip '_' obj.app '/results.csv'];
filename = ['solution_' obj.app '.csv'];
fid = fopen(filename,'w+');
fwrite(fid,urlread(url));
% load data from csv file with header on the right column
frewind(fid);
ctr = 0;
obj.results.names = {};
obj.results.values = [];
while(~feof(fid))
aline = fgetl(fid);
ctr = ctr + 1;
a = strsplit(aline,',');
obj.results.names(ctr) = a(1);
for j = 2:length(a)
obj.results.values(j-1,ctr) = str2num(a{j});
end
% remove characters for MATLAB allowed in APM: "[],()."
var_name = regexprep(a(1),'[\[\],().]','');
obj.vars.(var_name{1}) = obj.results.values(:,ctr);
end
fclose(fid);
end
% SOLVE: ``
function solve(obj,fname)
obj.apm('clear all');
obj.apmload([fname '.apm']);
try
obj.csvload([fname '.csv']);
obj.imode = 7;
catch
obj.imode = 3;
end
obj.option('nlc.web',0);
obj.option('nlc.nodes',3);
obj.option('nlc.solver',obj.solver);
obj.option('nlc.sensitivity',0);
obj.option('nlc.imode',obj.imode);
solver_output = obj.apm('solve');
if obj.appstatus == 1
obj.sol
else
disp(solver_output);
end
end
% TAG: retrieve an option specification from the APMonitor server
function response = tag(obj,name)
url_base = [obj.server '/online/get_tag.php'];
params = {'p',obj.app,'n',name};
response = str2num(urlread(url_base,'get',params));
end
% WEBROOT: open default web browser showing files on server
function stat = webroot(obj)
url = [obj.server '/online/' obj.ip '_' obj.app '/'];
stat = web(url,'-browser');
end
% WEB: open default browser showing application dashboard
function [stat] = web(obj)
iapp = [obj.ip '_' obj.app];
url = [deblank(obj.server) '/online/' iapp '/' iapp '_dashboard.php'];
stat = web(url,'-browser');
end
end
methods(Static = true)
function a = ss(fname)
a = apmonitor;
a.imode = 1;
a.solve(fname);
end
function a = rto(fname)
a = apmonitor;
a.imode = 3;
a.solve(fname);
end
function obj = sim(fname)
obj = apmonitor;
obj.imode = 6;
obj.apm('clear all');
obj.apmload([fname '.apm']);
try
obj.csvload([fname '.csv']);
end
obj.option('nlc.web',0);
obj.option('nlc.nodes',3);
obj.option('nlc.solver',obj.solver);
obj.option('nlc.sensitivity',0);
obj.option('nlc.imode',obj.imode);
solver_output = obj.apm('solve');
if obj.appstatus == 1
obj.sol
else
disp(solver_output);
end
end
function demo()
% demo/demo
a = apmonitor.sim('demo/demo');
t = a.vars.time;
x = a.vars.x;
y = a.vars.y;
plot(t,[x,y]);
xlabel('Time');
legend({'x','y'},'location','nw');
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment