enteliWEB 4.5 Developer Guide
enteliWEB 4.5 Developer Guide
5
Developer Guide
Edition 2.1
Copyright
Copyright © Delta Controls Inc. All rights reserved.
Information in this document is subject to change without notice and does not represent a
commitment to past versions of this document on the part of Delta Controls Inc. Delta Controls
Inc. may make improvements and/or changes to this document /the associated software/or
associated hardware at any time.
The Delta logo and enteliWEB and are registered trademarks of Delta Controls Inc.
In version 2.2 and later, enteliWEB provides both PHP and REST APIs with which developers
can leverage enteliWEB's Zend framework, MVC software architecture and web application
development languages to develop and integrate an application with enteliWEB.
The enteliWEB Version 4.5 Developer Guide does not contain information about the PHP and
REST APIs. This information is located in the enteliWEB help.
Audience
The audience for this document includes web developers and technical personnel who want to
create custom reports and custom widget types to suit an application.
Required Knowledge
A developer can create custom reports and custom widget types based on a good
understanding of the following technologies:
• PHP programming
• Model-View-Controller (MVC) architecture and design patterns
• SQL
• XML, HTML and CSS
• JavaScript
• BIRT (Business Intelligence and Reporting Tools) Report Designer
By the end of this tutorial, you will have created a working report which retrieves raw data
from Historian, displays it in a tabular format, and filters it based on a BACnet object reference
and time range.
This tutorial is not intended to be a training tool for BIRT Report Designer or for PHP. To
develop custom reports you need competence with both. Here are some training resources:
• Eclipse offers a number of tutorials and examples to become familiar with the various
aspects of BIRT Report Designer - http://www.eclipse.org/birt/phoenix/examples/.
• The PHP website provides a comprehensive manual detailing every aspect of the
programming language – http://php.net.
• Countless tutorials and examples of PHP scripts can be found online.
• Online and classroom training is available from a number of companies for both PHP
and BIRT Designer.
A web service is an Application Protocol Interface (API) which can be accessed through a
browser or called by web pages (commonly through JavaScript AJAX requests). Each
enteliWEB report uses one or more PHP web services which calculate and format report data
in a specific way. These web services have been created for general use by multiple reports
and can be used by custom reports as well.
The report designs are created for the Java BIRT (Business Intelligence and Reporting Tools)
engine, which formats and displays the report data provided by the web service
(http://eclipse.org/birt).
A
ODBC Data CopperCube Delta
Source Historian
B
Report User Interface Report Instance
8
C 2 7
PHP Classes enteliWEB
Database
BIRT Runner
1
Web Services
D
Custom
Report
6 Custom Web Service
Design 4 5
Legend
A External Components
B enteliWEB User Interface
C enteliWEB Core
D User-Generated Components
• A plain text editor to create the PHP file. A dedicated PHP editor is recommended.
• BIRT Report Designer 4.4.2 to create the BIRT report. Download Report Designer from
the enteliWEB page of the Delta Support site rather than from the Eclipse website to
ensure that the version of Report Designer is correct.
• A historical trend log in Historian with a month of data. The data doesn’t necessarily
have to be real demand or consumption data. This tutorial assumes that data exists
from January 1, 2011 through January 31, 2011.
• enteliWEB with the Energy Management add-on with access to the Historian database.
• A basic understanding of XML markup.
• A basic understanding of object oriented programming.
• A basic understanding of the Historian database architecture.
http://locahost/enteliweb/[controller]/[action]/[arguments]
where:
Controller: Specifies the name of the controller being accessed and the name of the class
being used. Each controller uses a single PHP script located in
/enteliweb/website/application/controllers/[controller]Controller.php. Controllers beginning
with ‘ws’ provide web services such as wsreportdata.
Action: Specifies the function being called within the specific controller. If no action is
specified the controller’s indexAction function is called. Actions are always defined as
[action]Action(). In the case of reporting, actions may be custom web services created for a
custom report. Actions can make use of public functions from PHP Libraries (Delta or Zend),
from Models, or from their parent controller.
Arguments: Defines optional parameters as required by the specified action of the controller.
This provides a means of passing all other information to the controller. For reporting,
common arguments are the meter list, the start and end date, and formatting details such as
report title, time interval, and so on.
The report engine uses BIRT and it relies on data from specified Historian databases.
The BIRT report engine supplies a command line to BIRT Runner and it generates the report.
However, BIRT Runner runs as a process that is available to generate a report immediately.
When a user wants to generate a report, PHP writes an entry to the queue table in the
database. BirtRunner generates the report as soon as it sees the queue entry.
To open a report design or to create a new one, the BIRT Report Designer (a component of
Eclipse IDE) must be available. BIRT Report Designer generates .rptdesign files, which are
used by BIRT’s runtime component to format and display data each time a report instance is
generated.
1. Create a site and connect it to the Historian database which is used for this tutorial.
While the site can be given any name, this tutorial refers to the site as MainSite.
2. Create an Area and add an Electric Meter to it.
3. Define the trended datapoint as a consumption datapoint for this meter. For the
purposes of this tutorial, the datapoint object reference is referred to as
//MainSite/100.AV1.Present_Value .
Use the following naming convention for all action names: all letters in
lower case and append the word Action. For example: public function
gethistoriandataAction()
http://localhost/enteliweb/wsreportdata/mycustomdata/call/gethistoriandata
The action mycustomdata in the wsreportdata controller is regarded as a custom web service.
enteliWEB searches for the class MycustomdataController in the file
\enteliweb\website\report\MycustomdataController.php. The parameter call specifies an
action for this custom web service, which is gethistoriandata in this case.
In this example, enteliWEB attempts to load the file MycustomdataController.php and call the
function gethistoriandataAction inside the MycustomdataController class.
<?/**
* @file $File: MycustomdataController.php$
* Copyright (C) Delta Controls Inc. 2011
*/
/**
* @class MycustomdataController
* @extends WsreportdataController
*/
class MycustomdataController extends WsreportdataController
{
/**
* @name gethistoriandataAction
* @brief query Historian for trend log data
*/
public function gethistoriandataAction()
{
$this->reportData->appendChild($this->xml->createElement('Status', 'It
worked!'));
}
}
Browsing to http://localhost/enteliweb/wsreportdata/mycustomdata/call/gethistoriandata
now produces the following result:
• All custom report web services must extend wsreportdata Controller. By doing so, the
custom actions have access to the same information and configuration that the
standard actions in the wsreportdata controller do.
• Appending child XML elements to $this->reportData adds a node to the SimpleXML
object which is automatically output by wsreportdata after the action is completed (the
custom web service does not have to do anything additional to have the XML output).
• This single custom controller may have multiple actions (callable web services) and
may have private functions for these actions to use.
$StartTime = $this->getParam('starttime');
$EndTime = $this->getParam('endtime');
$FullRef = $this->getParam('datapoint');
$Format = 'Y-m-d\TH:i:s\.u';
// get TLInstance row from model
$TLInstance = Report_Rate_TLInstance::getOneByFullRef($FullRef);
In a browser, call:
http://localhost/enteliweb/wsreportdata/mycustomdata/call/gethistoriandata?starttime=
2011-01-01&endtime=2011-01-31&datapoint=//MainSite/100.AV1.Present_Value
It displays the Historian data as XML:
• Parameters passed through the URL (such as starttime, endtime and datapoint) can be
accessed using $this->getParam().
• getParam() is not case sensitive.
• The Report_Rate_TLInstance row corresponding to the datapoint provided in the URL is
loaded using Report_Rate_TLInstance::getOneByFullRef($FullRef).
• The code verifies that $TLInstance is an instance of Report_Rate_TLInstance before
reading any properties from it.
• If this check is not done, and no Report_Rate_TLInstance row is found, reading
properties from the $TLInstance variable causes a fatal PHP error.
• The SQL query to read Historian data is built up as an array, and then imploded into a
string. This step is not necessary, but helps improve readability when SQL queries
become complex and take multiple lines.
• The SQL query is a prepared statement and uses the ‘?’ character as parameter
markers.
• When repeatedly running the same query with different parameters, MySQL caches the
query itself and only has to change these parameters. By marking parameters with ‘?’
the SQL query time is reduced.
• The binding array is passed to MySQL – each element replaces a ‘?’ in the prepared
statement.
• The number of array elements (number of bindings) must match the number of
parameter markers in the query.
Select the XML document previously saved from the mycustomdata web service as the XML
source and click Finish.
Specify the XML data source as HistorianData, give the data set a name of HistorianDataSet,
and click Next.
Select the Use the XML file defined in the data source option in the next dialog and click
Continue.
Select the ‘XML Elements named “Row” at fixed absolute position’ option and click Next.
Map the Timestamp and Value XML nodes as column mappings in the data set. Select both
items and click the arrow to add them.
Change the Value column to be a float instead of string. Select the Value item in the Column
Mapping area and click Edit to change it.
As a final check, click Show Sample Data to see the data set result.
The simplest way of showing the data set in the layout is to drag and drop the HistorianDataSet
element from the Data Sets node in the Data pane into the report layout window. This creates a
table with one column for each data set mapped column.
Alternatively, follow the My First Report tutorial in BIRT Designer to create an empty table and
add each mapped column as a table column.
The report layout now shows a table containing two columns, one for each mapped column.
Name the parameter ReportTitle and give it a prompt text of ‘Report Title’.
Check the Is Required checkbox to force the user to enter a value in the report form.
From the Outline pane, drag and drop the ReportTitle parameter into the layout. This creates a
data element with a value of the report parameter ReportTitle:
Save the report, reload the saved instance, and verify the Report Title field appears.
Try to save the report without a value specified for Report Title, and verify the field is
highlighted as being required.
Enter a title and run the report, verifying the ReportTitle parameter appears where it was
added to the layout.
Log into enteliWEB in a web browser and verify that Custom Report appears as a report type in
the Reports tab. If already logged in, refresh the window to update the list.
Select the Custom Report node and create a report instance with the name Test.
As before, drag and drop each parameter into the layout. Notice that the Report Type field is
not a regular text field, but is a select list with specific options.
This is because ReportType is a special parameter name used by other reports. See Special
BIRT Parameters for a list of all parameter names which shows as a special UI component.
Select the meter My Meter and add it to the report. Even though the XML data source is
hardcoded, the report form does not allow a user to save a report with an empty meter list.
Save the report instance and run the report to verify it generates a table showing the data from
the XML document.
If the report does not generate properly, or shows errors, see Troubleshooting Failed Reports.
Create a report parameter group by right clicking Report Parameters in the Outline pane and
selecting New Parameter Group.
Create the final 2 parameters, GroupName1 and MeterList1, inside this group.
Drag and drop both parameters to verify their contents when the report is run.
Reload the report in enteliWEB and verify the GroupName1 and Meterlist1 parameters do not
appear in the form. Run the report and verify that they both receive a value automatically (the
name of the meter and its ID).
Update the report design to use the custom web service as the data source, rather than a static
XML file. In BIRT Designer, open the Historian Data data source and remove the XML document
path from the XML source field.
Select the Property Binding item from the left menu and press the Expression Builder button
next to the XML Data Source File field.
encodeURI("http://localhost/enteliweb/wsreportdata/mycustomdata/call/gethistoriandata
?"
+ "meterlist=(" + params["MeterList1"].value +")"
+ "&starttime=" + params["Start"].value
+ "&endtime=" + params["End"].value
+ "&reporttype=" + params["ReportType"].value
);
Save the changes to the report design and run the report again in enteliWEB. Notice that there
is now no data returned from the web service. This is because BIRT is passing the ID of the
meter, rather than its object reference.
$StartTime = $this->getParam('starttime');
$EndTime = $this->getParam('endtime');
$Format = 'Y-m-d\TH:i:s\.u' ;
$TLList = Report_Rate_Data::GetTLInstanceList($this->GetMeterList(), $this-
>getParam('reporttype'), 'Consumption');
if (!empty($TLList))
{
foreach ($TLList as $TL)
{
// get TLInstance row from model
$TLInstance = Report_Rate_TLInstance::getOneByID($TL['TLInstance']);
if ($TLInstance instanceof Report_Rate_TLInstance)
{
// build up SQL query
$sql = array('SELECT RecordNumber, Timestamp, Data FROM TLData
WHERE');
$sql[] = ' TLInstance=? AND Timestamp BETWEEN ? AND ?';
$sql[] = ' AND Type=? ORDER BY Timestamp';
• The web service no longer is using the parameter datapoint, but instead is calling the
function GetTLInstanceList to load all consumption datapoints.
o This function, defined in WsreportdataController.php, determines all critical
information for each datapoint belonging to each meter passed to the web
service in the meterlist parameter (information such as the object reference of
the item, its ID, the meter it belongs to, and so on).
o It uses the parameter reporttype to filter these datapoints by type.
• The variable $TLList is an array, so a foreach loop is added around the previously used
code which read data for a single trend log instance.
Running the report with this updated web service should produce a report showing values
from Historian once again.
Advanced reporting
One of the best ways to become familiar with how enteliWEB and BIRT interact is to open the
report design files which come with enteliWEB and look at how they are built. When trying to
add more complex features, find an existing report which behaves in a similar fashion and
check how it was designed.
Prompt Text: used as the field label in the report form. If not provided, the Name parameter is
used as the label.
Is Required: if checked, the report form does not allow the user to save or run the report if
this field is empty.
Default Value: when a new instance of a report is being created, this default value populates
the field.
ReportType: generates a dropdown list of all types of meter data. Required if using built-in
functionality of WsreportdataController to determine the trend log instance list from the
meter list (using GetTLInstanceList() for example).
Interval: generates a dropdown list of report interval options. In existing reports, some web
services group data by this interval.
StartTime and EndTime: generates a period dropdown, with a number of relative options
(Yesterday, Current Month, Last Year, etc.) and a custom period option, allowing the user to
enter a starting and ending date. Both are sent to BIRT in the format ‘Y-m-d’ when the report is
generated (for example, ‘2011-06-19’).
OnHoursStart and OnHoursEnd: generates a dropdown list of time options for the report on
hours transition and off hours transition. Both are sent to BIRT in the format ‘H:I’ when the
report is generated (for example, ’19:10’).
Weekdays: generates a checkbox for each day of the week. When the report is generated, BIRT
receives a comma delimited list of numbers, indicating which days are selected. The numbers
start at 0 for Sunday, incrementing to 6 for Saturday (for example, only selecting Monday and
Tuesday would create a Weekdays value of ‘1,2’).
BaselineStart and BaselineEnd: generates a baseline field set which allows the user to
specify a relative offset from the selected report period, or specify a custom start date. Both
fields are submitted to BIRT in the format ‘Y-m-d’ just as with the StartTime and EndTime
parameters. Note that the report must have both StartTime and EndTime fields defined, as the
baseline is based off their values.
To check for PHP errors, watch the PHP log in the enteliWEB logfiles directory, while the
report generates. Any fatal or critical errors are logged immediately. If enteliWEB is in
development mode, additional debug information is output while the report calls on the PHP
web services.
To check for a report design error, use the Preview tab in BIRT Designer. This runs the report
directly inside the designer and may provide useful error messages when problems occur.
Alternatively, check the BIRT log in the enteliWEB logfiles directory for any errors or
exceptions.
In the report design file, when a grid is added, and in the bottom row a few cells are set up to
be aggregated values with aggregate functions like SUM(). When all the values in a column are
NULL, SUM() returns NULL in Birt 3.7, but in Birt 4.4, it returns 0. Therefore, you cannot
hide/show a column in grid based on if the aggregate functions return NULL or not.
If you have created a custom widget in enteliWEB version 1.1 or earlier then it must be
upgraded to work properly in 1.2 and later versions. See the Upgrading Widgets from 1.1 to 2.2
section. Widgets from 1.2 work in later versions without any need to upgrade.
You must have a good understanding of the JavaScript scripting language and XML syntax
usage. Please familiarize yourself with these technologies.
The following tutorials are recommended if you are new to these concepts or would like a
refresher:
https://developer.mozilla.org/en-US/docs/JavaScript/A_re-introduction_to_JavaScript
http://www.w3schools.com/xml/
Suggested tools
An enteliWEB widget is essentially a web page – it is an HTML file with a little PHP that injects
widget information from the server and database. JavaScript is the scripting language used to
create the client side functionality for the widget. Because of this, development and debugging
environments are flexible – there is no required application to develop in.
Development environments
There are many tools available, which allow the development of a web page, but the most
beneficial have JavaScript support. Many commercial applications are capable, and even some
open source options. A widget can be developed in Notepad, however this might prove
challenging.
The following wiki provides a comprehensive list of common HTML editors that may help:
http://en.wikipedia.org/wiki/List_of_HTML_editors#Basic_text_editors
Debugging environments
Most modern browsers such as IE, Chrome and FireFox have built in developer tools which
allow developers to trigger debug statements in their code. Becoming familiar with one or
more of these browsers, and learning how to use their developer toolkits, is highly
recommended.
The example widget takes a trend log object reference, finds the top five values in the trend
log’s data buffer, and displays them in descending order, listed with their times. While this
widget is simple, it demonstrates some key features of widgets and widget development, and it
provides a good basis for developing your own widget.
• An XML config file which indicates widget attributes as well as what settings and
preferences should be made available to those who use the widget.
• A PHTML script file which contains the widget implementation.
• A custom PHP controller file which may contain the custom web services required by
the widget to function correctly. A custom PHP controller file is optional.
• The PHTML script file name must match the name of the widget, located in the main
folder for the widget. Example widget has ‘Example.phtml’ file
• Each widget must have a Config.xml, located in the main folder for the widget.
• If a custom PHP controller is required, its name must follow the naming convention
Ws<widgettype>Controller.php, located in the main folder for the widget. The file must
only have capitalization on the W (of Ws) and C (of Controller). All other characters
must be lowercase.
• Example widget has WsexampleController.php file
• Icons for the widget must be located in the images folder for the widget.
Widget config.xml
The config file is essentially the definition of the widget. It indicates the widget type properties,
as well as any required settings and preferences for the widget. The file is written in XML
format and follows a specific schema recognized by enteliWEB.
type="Example"
title="TL Value Example"
icon="tl"
description="Testing new example">
WidgetType root
<?xml version="1.0" encoding="utf-8"?>
<WidgetType
xmlns="http://www.deltacontrols.com/enteliweb/widget/widgets.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.deltacontrols.com/enteliweb/widget/widgets.xsd
../widgets.xsd"
The first section of the config file declares the XML version and encoding. It is followed by the
root XML node – a “WidgetType” element, and its schema location.
This section should not be modified and should be present in each config file.
WidgetType attributes
There are four attributes that can be set on the WidgetType element and they can and should
be changed for each widget type:
type="Example"
title="TL Value Example"
icon="tl"
description="Testing new example">
type: This attribute indicates the NAME of the widget type and it directly corresponds to the
name of the script files associated with the widget. It is largely used only for development and
database purposes. It is not seen by the end user - think of it as a more of a meaningful ID for
the widget. It is highly recommended to make this something short but meaningful, using
letters only. All enteliWEB widgets start with an uppercase letter as a convention, so it may be
best to adopt the same for custom widget types as well. Restricted to 50 characters or less.
• Correct: type=”ManualOn”
• Incorrect: type=”Manual On” (spaces not allowed)
• Incorrect: type=”On4Good” (numbers not allowed)
title: This attribute indicates the human readable title that is displayed to the end user. It
appears in the widget creation pages, as well on the widget title bar. It is recommended to
make this short, but meaningful. Unlike the type attribute, spaces, symbols and numbers are
allowed in the title, but remember, it is highly visible to the user. Restricted to 255 characters
or less.
icon: This attribute indicates the name of the icon to be associated with the widget. Icon names
are restricted to 50 characters or less. There are a few things to note regarding widget icons:
• Widgets make use of multiple icon sizes throughout enteliWEB. A widget icon must be
available in 5 different sizes: 16px, 24px, 32px, 48px, 64px. Each of these icons must be
named according to their size (i.e. icon_16.png, icon_24.png, etc…), to be properly
identified by the widget.
• Only .png images are supported for icons.
• The icon attribute contains the icon name only. Do not include the size and extension
identifier. Correct: icon=’gear’, Incorrect: icon=’gear_16.png’
• Icons must be located in the widget’s local Images folder.
description: This attribute should contain a brief description of the widget’s functionality.
Restricted to 255 characters or less.
WidgetType settings
Settings are the variables that administrators have access to when instantiating a widget.
These settings directly influence the widget functionality and output. A widget does not require
any settings at all, but without settings a widget’s behavior depends solely on the
implementation, and not on any user input. Settings have their own attributes.
• Correct: name=”LargestValue”
• Incorrect: name=”Largest Value” (spaces not allowed)
• Incorrect: name=”Value4You” (numbers not allowed)
displayName: Similar to the WidgetType’s ‘title’, the displayName attribute of a setting is the
name that is presented to the user when they are instantiating a copy of the widget for
themselves. Unlike the ‘name’ attribute, spaces, symbols, and numbers can be used in the
displayName.
• string, number, bool, date, color, objRef, report, graphic, enum, site, meter
• string, bool (uses 0 and 1 for values), enum, site, objRef and meter have customized
input objects to help the user more easily enter in a value
• number, date, color, report and graphic do not have specialized inputs and simply use a
text box for value entry. In the future these types will be expanded on to have more
customized inputs
array: (optional, if omitted defaults to “false”) This attribute indicates if the setting should
allow multiple values to be entered. For example, a setting can have multiple object
references. If “true”, then in the settings page, plus and minus buttons are available that allow
values to be added and removed.
Default Values
A setting may also be given a default value. This default value is automatically used in the
widget unless changed by the user when instantiating the widget for use.
To give a default for a non-array setting, add a “Value” XML element. It has no attributes, and
contains the value within the overall tag.
To give a default for an array setting, enclose all “Value” elements within a parent “Values”
element.
<Setting name="TrendLogRefs" displayName="Trend Log References"
type="objRef" description="Trend logs to run results on." array="true">
<Values>
<Value>//MainSite/2007.TL1</Value>
<Value>//MainSite/2007.TL2</Value>
</Values>
</Setting>
Setting a default value for an array setting.
WidgetType preferences
Preferences are very similar to settings, in terms of how they are setup in the Config.xml file.
However, they should be regarded differently than settings. Preferences are values that are
intended to be changed by the dashboard user at run time when the widget is being used.
Preferences are often variables that affect the UI more than the function of the widget. For
example, the number of values to show, or the highlight color of a column. It is up to the widget
implementation to decide how to present these preferences to the user at run time, which is
discussed later when we look at the widget implementation script code.
However, the previous preference example does show something new – how to setup a
Preference (or Setting) to use an enumerated listed of values for selection.
<EnumValues>
<EnumValue displayValue="Five">5</EnumValue>
<EnumValue displayValue="Ten">10</EnumValue>
<EnumValue displayValue="Fifteen">15</EnumValue>
</EnumValues>
<Value>5</Value>
In the example, each EnumValue element may have a displayValue attribute set. This is the
value that is displayed to the user in the enum drop down selection box. The value for the
Preference stored in the DB and used by the widget script is given as the EnumValue element
content – in the previous example: 5, 10 and 15.
For those familiar with HTML option tag, the displayValue attribute corresponds to the display
value of the option, and the EnumValue content corresponds to the key value of the option.
A default value may also be set for the enum, and indicates which option is to be selected by
default when an admin instantiates a widget.
Here you can see the how the settings and preferences are displayed to the administrator:
1. Widget attributes: Title and description can be changed for each instance of the
widget for a more detailed explanation of the functionality.
2. Widget settings: Settings are displayed with the desired display name.
3. Setting input: Inputs based on setting type are displayed to the admin; the example
shows the objRef ‘object picker’ input.
4. Widget Preferences: Preferences are displayed with the desired display name.
5. Preference inputs: Inputs based on preference type are displayed to the admin; the
example shows the enum ‘dropdown’ input.
6. Preferences in the widget: The example widget contains a dropdown box allowing
users to change the preference value on the fly. The implementation of this is
discussed when we look at the widget implementation script.
Now that we’ve covered the Config.xml file, let’s move onto the other big piece of the picture:
the widget implementation script.
PHP web service controllers are part of enteliWEB’s MVC (Model, View, Controller)
framework. Their job is to accept http requests from a client, the widget in our example,
process data from database object models, and ,in our example, return an http response to the
client containing the desired data.
enteliWEB contains a number of web service controllers that provide data to be used by
widgets. For example, there are web services that return information about object properties
or alarming information that a custom widget can make use of.
Custom widgets may require more specialized results though, and to support this, each widget
may have its own custom PHP controller. This controller is loaded into the enteliWEB
framework when the widget is run. It functions like an existing enteliWEB web service
controller and has access to database and device information.
The controller must be placed in the root folder for the widget.
Custom actions
Each web service controller contains one or more Action functions. These are the functions
that are called from your widget via AJAX to get required data.
• The controller class must follow the same naming convention as the file name
Example: WsexampleController.php
• The controller class must extend the Delta_Controller_Service class
• The action name must be all in lower case, and have the word ‘Action’ appended to the
end of it. Example: gettoptlvaluesAction
The following action takes in two parameters, a number and an object reference, and returns a
JSON object containing result information, as well as an array of ‘top’ values found in the trend
log’s data buffer.
<?/**
* @file $File: WsexampleController.php$
* Copyright (C) Delta Controls Inc. 2012
*/
/**
* @class WSExampleController
* @extends Delta_Controller_Action
*/
class WsexampleController extends Delta_Controller_Service
{
/**
* @name SortTopValues
* @brief Custom sorting function which compares two TL buffer XML items based on
their datapoint 'value'.
* @param SimpleXMLElement $a XML for a TL buffer item found in a
ReadRangeByIndex response.
* @param SimpleXMLElement $b XML for a TL buffer item found in a
ReadRangeByIndex response.
* @return bool true if $aValue < $bValue, which will result in an array sorted
from largest to smallest values.
*/
public static function SortTopValues($a, $b)
{
$aValue = (float)$a->Union->Property['value'];
$bValue = (float)$b->Union->Property['value'];
return ($aValue < $bValue);
}
// (5) Grab the desired top number of values and return the value and
time
for($i=0; $i < $NumValues; $i++)
{
if (!isset($BufferArray[$i])) { break; }
$TopValues[] = array(
'Timestamp' => (string)$BufferArray[$i]->Property['value'],
'Value' => (float)$BufferArray[$i]->Union->Property['value']);
}
}
}
else
{
$Result = 'ERROR';
$Message = "Unable to get buffer for $TL";
}
// (6) Craft and send response
$Response = array('Result' => $Result, 'Message' => $Message, 'TopValues' =>
$TopValues);
// (7) Respond in JSON format; use the json helper method to handle our
response.
$this->getHelper('json')->direct($Response);
}
}
The preceding code does the following:
With an action like this setup, our widget script can access the desired trend log information
on demand.
enteliWEB uses a PHP server framework and each widget file must be a PHTML file. Various
global variables and JavaScript libraries are automatically added into the script by the server
for the developer and are required for the widget to function correctly.
Reference the example widget, located under the public/widget/Example folder of your
enteliWEB installation.
Each widget must have a corresponding phtml file named to match the
widget name.
The example widget script is too long to display in its entirety here, so it is broken down into
fragments. It is recommended to open the script file, located under the public/widget/Example
folder, and follow along.
<!DOCTYPE html>
<html>
<head>
<?=$this->headScript()?> <!-- Includes required variables and libraries -->
The widget has access to some useful JavaScript libraries at run time. These include the
jQuery and EXT JavaScript libraries, as well as some Delta JavaScript libraries containing
common functionality that are used in widget development.
The PHP code injects some useful JavaScript libraries at run time for the widget to make use
of. These include the jQuery and EXT JavaScript libraries, as well as some Delta JavaScript
libraries containing common functionality that are used in widget development.
<body>
<div>
<label for="numResults">Show top </label>
<select id="numResults"></select>
<label for="numResults" id="valuesForXLabel"> values for <a id="aToObj"
href="#"></a></label>
</div>
<div>
<div>
<div id="status"> </div>
<table id="result" style="border-collapse: collapse; ">
<thead>
<tr>
<th style="padding: 0;">Value</th>
<th style="padding: 0;">Date</th>
</tr>
</thead>
<tbody id="resultTBody">
</tbody>
</table>
</div>
<div id="tlLinkDiv">
<img src="Images/tl_64.png" alt="tl"/>
</div>
<div style="clear:both;"></div>
</div>
</body>
Nothing too special or complex, the previous HTML simply sets up the following:
• A select element (dropdown) which allows the user to select the number of results to
show, along with some label text.
• A table to hold the data.
• An image which is eventually be used as a link to an object page.
The “widget” object is a JavaScript object that is global in the JavaScript widget scope, and
contains a lot of variables and functions that enable the widget to work within a dashboard.
Most importantly, it contains the variables that indicate user settings and preferences, which
ultimately determine how the widget functions. We discuss the most important properties of
this object here, but note that this list does not cover all properties. For detailed information
about the widget object, see .../website/public/javascript/delta/Delta.Widget.js .
widget.refreshRate (int): Indicates the time (in seconds) to wait before attempting to update
(refresh) the widget. Once this time has expired, the widget.update() function is called. If set to
0, the widget does not refresh (the update function is called only once). Keep in mind, the
faster the refresh rate, the more taxing it is on the system. It is not recommended to drop the
refresh rate below a few seconds. Default is 0 (no refresh).
widget.preferences (object): This and the settings object are the most used in your widget
script. This object contains a variable corresponding with each preference setup in the
Config.xml file.
widget.clearError(): Removes the error icon (if it exists) from the top right corner of the
widget.
widget.setHeight(height): This function sets the height of the widget to a specific size in
pixels. If no height is given (or height is null), then the widget automatically sizes itself to
match the height of its content. If you have made changes to the DOM of your widget
dynamically after it has been loaded, you may need to call this function accordingly.
• height (optional int): Desired height for widget (the widget title bar is not included in
this height, this sets the height of the widget content.
• Example: widget.setHeight(50) sets the widget height to 50px.
• Example: widget.setHeight() sets the widget to fit its contents.
• PreferenceName (string): The name of the preference as found in the Config.xml file.
• ValueArr (array): An array containing one or more preference values. Note, a non-array
preference type still needs to set its preference as an array with a single item.
• Example: widget.setPreference(“NumResults”, [“15”]);
widget.update(): The update function is perhaps the most important widget function. All
functionality that updates the widget UI with data, must be placed, or called, from within this
function. Some widgets only have this function called once on load (if widget.refreshRate is 0),
where other widgets may need to have content updated more frequently, therefore, this
function would be called at regular intervals (based on widget.refreshRate). This function is
overridden in each widget as shown in the following section.
Embedded JavaScript
Now that we have looked at the HTML structure, and global JavaScript ‘widget’ object, we can
look into the JavaScript code that makes the widget work! Since the files are rather lengthy,
they are referenced in snippets. Open the script file, located under the public/widget/Example
folder, in the Example.phtml file, and see the following:
Widget initialization
A widget is really just a web page, so a developer may choose to initialize the widget however
he or she pleases. enteliWEB widgets use the jQuery JavaScript library to simplify
development. The example widget uses the same principles.
If you are unfamiliar with jQuery and its syntax, it is strongly recommended to do a quick
overview of how it works:
http://docs.jquery.com/How_jQuery_Works
//--------------------------------------------
// Widget initialization code
//--------------------------------------------
// Using jquery - This will be called when the page
// is loaded, so we know that all HTML elements
// can now be accessed in the DOM.
//--------------------------------------------
$(function()
{
// (1) Populate select with enums
$.each(widget.preferences.NumResultsEnumValues,
function(index, enumObj)
{
$('#numResults')
.append($('<option>', { value : enumObj['value'] })
.text(enumObj['displayValue']));
});
Widget preferences
As mentioned before, there is a logical difference between widget settings and widget
preferences:
Widget settings are not expected to change at run-time and are used by the widget code as-is.
Widget preferences are expected to change at run-time by the user, so changes made to the
preferences must be saved for future use.
Widget developers need only to be concerned about saving preference values if they change at
run time – settings should not change at run time.
widget.setPreference("NumResults", [widget.preferences.NumResults]);
Widget update
The widget is all setup to function now — the HTML structure is in place and the widget has
been initialized — now can we make it do something?
When a widget is ‘refreshed’, its update function is called, so the next step in implementing a
custom widget, is writing the update function.
//--------------------------------------------
// Widget Update function
//--------------------------------------------
// This function is called automatically once the widget has loaded
// and then is called every time the refresh rate time is reached.
// Code that updates the UI, or makes web service requests should be made
// done in this function.
//--------------------------------------------
widget.update = RequestData;
Here, we indicate that the widget.update function is set to a function called RequestData, but
where is this function? The RequestData function resides in the external JavaScript file
Example.js, which if you recall, we included in the head of our widget HTML page.
There are other ways to set the widget.update function using JavaScript
syntax, so the exact definition method is left up to developer discretion. The
previous example simply indicates one method. For example, an inline
function could be also be used to define widget.update:
widget.update = function() { … };
/**
* RequestData
* This function is responsible for requesting the data from our custom
* webservice controller, storing the value and then calling the Display function.
*/
function RequestData()
{
// (1) Clear any existing errors
widget.clearError();
$("#status").html("Requesting data...");
if (Delta.FullRef.getAbbr(widget.settings.TrendLogRef) != "TL")
{
widget.setError("This widget requires a trend log reference to function
correctly");
return;
}
// (2) Use the Delta.WS library to make a webservice call to get our data.
var wscall = widget.customController + "gettoptlvalues";
var postdata =
{
"numValues": parseInt(widget.preferences.NumResults),
"ObjRef": widget.settings.TrendLogRef
};
4. If the data is valid, save it to a widget variable and then call a function to display the
data.
/**
* DisplayData
* This function is responsible generating a table to display the data found in
* widget.topValue, and then resetting the widget height.
*/
function DisplayData()
{
$("#resultTBody").html(""); // (1) Clear out last result
$("#status").html(""); // Clear 'requesting' status message.
// (2) For each value in topValues, create a row in the results table.
for (var i=0; i < widget.topValues.length; i++)
{
tlValue = widget.topValues[i]['Value'];
// Parse BACnet time stamp into a JS Date object, and then format as desired.
tlTimestamp =
Delta.DateTime.BACtoJSDate(widget.topValues[i]['Timestamp']).format("Y-m-d H:i:s");
$("#resultTBody").append($("<tr><td>"+tlValue+"</td><td>"+tlTimestamp+"</td></tr>")
);
}
// (3) Since we have modified the DOM structure by adding elements to the table,
// we may want to set the height of the widget frame to match.
widget.setHeight();
}
DisplayData performs the following tasks:
o Each value contains a ‘Value’ and ‘Timestamp’ property which are displayed
accordingly.
o The timestamp returned from our service is a derivation of the BACnet timestamp
format. In order to format it into something more desirable, we first convert it to a
JavaScript Date object via the Delta.DateTime.BACtoJSDate function. Once we have
converted it to a JavaScript Date object, we use the Date.format function to produce
a nicer timestamp to display to the user.
3. Once all rows are added to the table, sync the widget height to fit the new content
perfectly; to do this call widget.setHeight() (note, no parameter given).
There is one final step before the widget can be used in enteliWEB – the widget must be
imported into enteliWEB. The steps to do this are discussed in Import the widget into
enteliWEB .
Once imported, the example widget can be created and added to dashboards.
All custom widget management is done from the Development admin menu, under Manage
Custom Widgets.
The Manage Custom Widgets page lists all imported custom widgets. From here, custom
widgets can be imported or removed, and new ones generated. Click on the ‘Generate Widget
Files’ link to begin the process, and input in the name of the new widget.
Generating the file structure for a new widget ‘Tetris’. Note the message
that indicates that this process merely creates folders and files - it does not
import the widget.
Using this method, the following folders and files are generated:
Navigate to the public/widget/ folder in the enteliWEB installation to see the new folders and
files for the created widget. If the folders and files were not created, verify that the PC user
account has administrator access (check Windows SUA).
The folders and files auto generated for the Tetris widget.
Import a widget from the Manage Custom Widgets admin page by clicking on the ‘Import
Widget Type’ link.
In the selection window, a list of all widgets in the public/widget folder that are not registered
in enteliWEB is visible. If something has happened to either the Config.xml file or the script file
for the widget, an error is shown beside the widget name because both are required files.
Select the checkbox beside the widget and click Import. The imported widget is listed under
the Custom Widget Types.
Updating a widget removes all existing copies of the widget from enteliWEB
and then imports it using the new config settings. It is therefore
recommended to take care and do the majority of major updates before the
widget goes into full use.
The
Widget admin menu.
From here you, create a new instance of the widget, and experiment with the setting and
preference values. Then reload the widget using these new values to see how they affect the
widget, or to debug specific cases.
The help page is an HTML file that is placed in the website\public\help\widget folder. The help
file must be named to match your custom widget type, using all lowercase letters:
For example, the Tetris widget would have a tetris.html help file.
For ideas on HTML formatting and the type of content you may want to include in your help file,
see the enteliWEB widget help files.
Removing a widget type from enteliWEB does not remove the folders and
files associated with a widget. Those must be removed manually if they are
no longer needed. This ensures that the files cannot accidentally be deleted
by removing the widget from enteliWEB.
All mobile widgets use 13px font size by default. If you want your widget to
use a different font size, the widget phtml page will need CSS code similar
to following to change the default.
In the followings steps, a fictional custom widget named “trend.phtml” is upgraded to the 1.2
framework.
The easiest way to create the folder structure for your widget is to have enteliWEB create it for
you. To do this, as an administrator, go to the Development->Manage Custom Widget page.
Click the “Generate Widget Files” link and enter in the name of your widget script. Note that
capitalization DOES matter here, so use the exact name of the file. Once you hit create, the
folder is generated for you under the public folder “website\public\widget”
Now that the structure is in place, we need to move and update the existing widget files.
When you first created your custom widget, you added the custom config to the widgets.xml
file. On upgrade, the config file should have been renamed to config_old.xml.
type="trend"
title="trend" (1)
icon="gear" (2)
description=""> (3)
</WidgetType>
You should see the above template. The widget type should remain the same, but you may
need to update the title, icon and description for your widget, labeled (1)-(4). Then remove the
default setting “MySetting”, and add in any settings and preferences you have in your old
config.
type="trend"
title="Trend Log"
icon="trendIcon"
description="A basic trend log given a TL object.">
If you open the phtml file created for you in your new folder, you can see the basic structure of
the page. In 1.2 and later versions, your widget is no longer a script ‘snippet’, it is an entire
web page. So for those of you familiar with complete HTML pages, this conversion should be
simple.
1. Copy your JavaScript from your existing widget into the inline script tag (or add it
externally if you have moved your JavaScript to an external file.
2. Remove the following lines of code from your widget :
/**************************************************************************
* DO NOT REMOVE
* This gives you javascript access to the widget properties including:
* widget.id, widget.type, widget.title, widget.settings, widget.preferences
**************************************************************************/
var widget = Delta.DashboardManager.widgets["<?=$this->id?>"];
/*************************************************************************/
It says DO NOT REMOVE, but the new framework automatically generates the “widget”
variable for you, so this is no longer required and actually causes an error.
3. Previously, a custom widget did not contain the BODY tag, so copy all of your widget’s
HTML code and place it within the BODY tag in the new phtml file.
4. Using the php <?=$this->id%> to make unique IDs is no longer required in the new
framework, so all these ID references may be removed. No harm is done by leaving
these references in, but your code may look a little messier.
Your application module can integrate seamlessly into the enteliWEB user interface through
its own navigation section or accordion in the left pane navigation tree.
Your application module can also add a page in the Administration section of the enteliWEB
user interface that can be accessed from the administration menu bar.
For detailed documentation to guide you to develop and integrate an application module, see
the Zend Module Support documentation included in the enteliWEB help.
// getdataAction
// query CopperCube for trend log data
$IP = $archiver->getArchiverIP();
//get CopperCube port from Settings_Archiver
$port = $archiver->getArchiverPort();
//get CopperCube user from Settings_Archiver
$archiverUser = $archiver->getArchiverUser();
//get CopperCube password from Settings_Archiver
$archiverPwd = $archiver->getArchiverPwd();
//get CopperCube sitename from Settings_ArchiverSite
$archiverSiteName = $archiverSite->getArchiverSite();
//https://x.x.x.x/api/get_tl_data_count.json/PD_mainsite/5600/14/2014-04-
18 13_19_43/2/
$uri = sprintf("https://%s:%s/api/%s", $IP, $port, $apiRequest);
$Config = array(
'adapter' => 'Zend_Http_Client_Adapter_Curl',
'curloptions' => array(
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_USERPWD => $archiverUser.':'.$archiverPwd,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false, //lpc need this too
CURLOPT_TIMEOUT => 8, //Wait max 8 seconds per Archiver
request
CURLOPT_SSLVERSION => 1
));
http://localhost/enteliweb/Wsreportdata/Mycustomdata/call/getdata?starttime=2014-04-
18 13:19:43&count=2&datapoint=//MainSite/5600.TL14.Present_Value
It displays the archiver data as XML:
<ReportData>
<Row>
<Timestamp>2014-03-18 22:10:00</Timestamp>
<Value>732.83345305856</Value>
<Seq>47338</Seq>
</Row>
<Row>
<Timestamp>2014-03-18 22:15:00</Timestamp>
<Value>732.83345309876</Value>
<Seq>47339</Seq>
</Row>
</ReportData>
Notes:
• Parameters passed through the URL, such as starttime, count and datapoint, can be
accessed using $this->getParam().
• getParam() is not case sensitive.
• The code gets CopperCube site settings by enteliWEB site name, ArchiverSite will give
information about archiver ID to be used
• The data from the CopperCube archive is retrieved by calling get_tl_data_count.json,
given a TL reference, start datetime, and a count, the service returns up to count data
samples relative to the start datetime.
The datetime format is "YYYY-MM-DD HH_MM_SS" ,in 24 hour time.
Note: '_' is because of URL encoding restrictions.
Parameters
$EWEBSite- enteliWEB site name to search for in the CopperCube archives (Type: string)
Returns
If successful, Settings_Archiver object. Otherwise, NULL. (Type: NULL / object)
Example
Settings_ArchiverSite::getByEWEBSite(‘MainSite’)
Returns
Returns CopperCube IP address. (Type: string)
Example
Note: $archiver is the instance of Settings_Archiver
$archiver->getArchiverIP();
Returns
Returns CopperCube IP port. (Type: string)
Example
Note: $archiver is the instance of Settings_Archiver
$archiver-> getArchiverPort();
public getArchiverUser()
Returns related CopperCube user name.
Returns
Returns CopperCube user name. (Type: string)
Example
Note: $archiver is the instance of Settings_Archiver
$archiver-> getArchiverUser();
public getArchiverPwd()
Returns related CopperCube password.
Returns
Returns CopperCube password. (Type: string)
Example
Note: $archiver is the instance of Settings_Archiver
$archiver-> getArchiverPwd();
See idotbacnet class API for similar functions. Documentation for enteliWEB APIs is located in
the help that is installed with enteliWEB.
See idotbacnet class API for similar functions. Documentation for enteliWEB APIs is located in
the help that is installed with enteliWEB.
Aggregates action
Calculates the average, total, maximum, minimum, and number of samples (normalized to 5
minute intervals) for the specified meters during occupied and unoccupied times. The
aggregates can optionally be grouped by a time interval (day, week, month, or year).
Parameters
meterlist[] – The ID of the areas/meters to read data for. Each meterlist[] parameter is
treated as a group.
weekdays – The days of the week to include in the returned data. Specified as a comma
delimited list of numbers 0 through 6, where 0 represents Sunday and 6 represents Saturday.
occupiedweekdays – The days of the week to consider as occupied days. Days included in the
weekdays parameter but not in the occupiedweekdays parameter show all their values as
unoccupied hours. Same format as weekdays.
ohstart – Starting time of occupied hours. Specified in hours and minutes in 24 hour time.
ohend – Ending time of occupied hours (start time of unoccupied hours). Specified in hours and
minutes in 24 hour time.
interval – How to group data – options are ‘day’, ‘week’, ‘month’, and ‘year’. If not specified,
data is not grouped by time.
reporttype – The type of data to use from the specified meters and areas. Possible values are
Electric_Energy, Electric_Apparent, Gas_Volume, Gas_Energy, Fuel_Volume, Water_Volume,
Thermal_Energy, Steam_Weight, and Carbon_Emission.
Sample URL
http://localhost/enteliweb/wsreportdata/aggregates?meterlist[]=(a983f772-406c-11e1-a360-
005056a20023, a36gd772-406c-11e1-a360-005056a20023)&meterlist[]= (d0f3f772-406c-11e1-
a360-005056a20023)&datatype=demand&starttime=2012-01-01&endtime=2012-01-
31&weekdays=1,2,3,4,5&occupiedweekdays=2,3,4,5&ohstart=09:15&ohend=17:30&interval=
week&reporttype=Electric_Energy
Returns
<?xml version="1.0" encoding="UTF-8"?>
<ReportData>
<StartTime>2011-05-03</StartTime>
<EndTime>2011-05-11</EndTime>
<Interval>NONE</Interval>
<Row>
<GroupNo>1</GroupNo>
<Timeslice>ALL</Timeslice>
<OnHours>
<Avg>145.61010603829</Avg>
<Sum>98869.262</Sum>
<Count>679</Count>
<Min>116.426</Min>
<Max>164.43</Max>
</OnHours>
<OffHours>
<Avg>53.949442237324</Avg>
<Sum>103205.283</Sum>
<Count>1913</Count>
<Min>25.541</Min>
<Max>160.196</Max>
</OffHours>
</Row>
<Row>
<GroupNo>2</GroupNo>
<Timeslice>ALL</Timeslice>
<OnHours>
<Avg>36.361743740795</Avg>
<Sum>24689.624</Sum>
<Count>679</Count>
<Min>28.894</Min>
<Max>41.108</Max>
</OnHours>
<OffHours>
<Avg>13.458914793518</Avg>
<Sum>25746.904</Sum>
<Count>1913</Count>
<Min>6.385</Min>
<Max>39.887</Max>
</OffHours>
</Row>
</ReportData>
Parameters
meterlist[] – The ID of the areas/meters to read data for. Each meterlist[] parameter is
treated as a group.
Sample URL
http://localhost/enteliweb/wsreportdata/costranking?meterlist[]=(a983f772-406c-11e1-a360-
005056a20023, a36gd772-406c-11e1-a360-005056a20023)&meterlist[]= (d0f3f772-406c-11e1-
a360-005056a20023 )&starttime=2011-01-01&endtime=2011-02-28
Returns
<?xml version="1.0" encoding="UTF-8"?>
<ReportData>
<StartTime>2011-01-01 00:00:01</StartTime>
<EndTime>2011-02-01 00:00:00</EndTime>
<Row>
<GroupNo>1</GroupNo>
<D>2011-01</D>
<ConsumptionValue>52592.187</ConsumptionValue>
<ConsumptionCost>143433.132</ConsumptionCost>
<DemandValue>154.58</DemandValue>
<EngineDemandValue>154.58</EngineDemandValue>
<DemandCost>3871.3030658</DemandCost>
<EngineDemandCost>2504.401</EngineDemandCost>
<TotalCost>147304.4350658</TotalCost>
</Row>
<Row>
<GroupNo>2</GroupNo>
<D>2011-01</D>
<ConsumptionValue>252581.186</ConsumptionValue>
<ConsumptionCost>688709.996</ConsumptionCost>
<DemandValue>746.887</DemandValue>
<EngineDemandValue>746.887</EngineDemandValue>
<DemandCost>18705.04549687</DemandCost>
<EngineDemandCost>2504.401</EngineDemandCost>
<TotalCost>707415.04149687</TotalCost>
</Row>
<StartTime>2011-02-01 00:00:01</StartTime>
<EndTime>2011-03-01 00:00:00</EndTime>
<Row>
<GroupNo>1</GroupNo>
<D>2011-02</D>
<ConsumptionValue>45938.682</ConsumptionValue>
<ConsumptionCost>112007.182</ConsumptionCost>
<DemandValue>151.656</DemandValue>
<EngineDemandValue>151.656</EngineDemandValue>
<DemandCost>3742.80486792</DemandCost>
<EngineDemandCost>2467.957</EngineDemandCost>
<TotalCost>115749.98686792</TotalCost>
</Row>
<Row>
<GroupNo>2</GroupNo>
<D>2011-02</D>
<ConsumptionValue>220429.073</ConsumptionValue>
<ConsumptionCost>537322.257</ConsumptionCost>
<DemandValue>737.663</DemandValue>
<EngineDemandValue>737.663</EngineDemandValue>
<DemandCost>18205.20564491</DemandCost>
<EngineDemandCost>2467.957</EngineDemandCost>
<TotalCost>555527.46264491</TotalCost>
</Row>
</ReportData>
Parameters
meterlist[] – The ID of the areas/meters to read data for. Each meterlist[] parameter is
treated as a group.
interval – How to group data – options are ‘day’, ‘week’, ‘month’, and ‘year’. If not specified,
data arenot grouped by time.
reporttype – The type of data to use from the specified meters and areas. Possible values are
Electric_Energy, Electric_Apparent, Gas_Volume, Gas_Energy, Fuel_Volume, Water_Volume,
Thermal_Energy, Steam_Weight, and Carbon_Emission.
Sample URL
http://localhost/enteliweb/wsreportdata/cumulativeconsumption?meterlist[]=(a983f772-
406c-11e1-a360-005056a20023, a36gd772-406c-11e1-a360-005056a20023)&meterlist[]=
(d0f3f772-406c-11e1-a360-005056a20023)&starttime=2011-01-01&endtime=2011-02-
28&interval=week&reporttype=Electric_Energy
Returns
<?xml version="1.0" encoding="UTF-8"?>
<ReportData>
<Value_StartTime>2011-01-01</Value_StartTime>
<Value_EndTime>2011-12-31</Value_EndTime>
<Value_Interval>MONTH</Value_Interval>
<Row>
<GroupNo>1</GroupNo>
<Timeslice>2011-01</Timeslice>
<Total>52621.41</Total>
<RunningTotal>52621.41</RunningTotal>
</Row>
<Row>
<GroupNo>1</GroupNo>
<Timeslice>2011-02</Timeslice>
<Total>45909.02</Total>
<RunningTotal>98530.43</RunningTotal>
</Row>
<Row>
<GroupNo>2</GroupNo>
<Timeslice>2011-01</Timeslice>
<Total>126319.01</Total>
<RunningTotal>126319.01</RunningTotal>
</Row>
<Row>
<GroupNo>2</GroupNo>
<Timeslice>2011-02</Timeslice>
<Total>110231.31</Total>
<RunningTotal>236550.32</RunningTotal>
</Row>
</ReportData>
Parameters
meterlist[] – The ID of the areas/meters to read data for. Each meterlist[] parameter is
treated as a group.
weekdays – The days of the week to include in the returned data. Specified as a comma
delimited list of numbers 0 through 6, where 0 represents Sunday and 6 represents Saturday.
occupiedweekdays – The days of the week to consider as occupied days. Days included in the
weekdays parameter but not in the occupiedweekdays parameter show all their values as
unoccupied hours. Same format as weekdays.
ohstart – Starting time of occupied hours. Specified in hours and minutes in 24 hour time.
ohend – Ending time of occupied hours (start time of unoccupied hours). Specified in hours and
minutes in 24 hour time.
interval – How to group data – options are ‘day’, ‘week’, ‘month’, and ‘year’. If not specified,
data are not grouped by time.
reporttype – The type of data to use from the specified meters and areas. Possible values are
Electric_Energy, Electric_Apparent, Gas_Volume, Gas_Energy, Fuel_Volume, Water_Volume,
Thermal_Energy, Steam_Weight, and Carbon_Emission.
Sample URL
http://localhost/enteliweb/wsreportdata/cumulatives?meterlist[]=(a983f772-406c-11e1-
a360-005056a20023, a36gd772-406c-11e1-a360-005056a20023)&starttime=2012-01-
01&endtime=2012-01-
31&weekdays=0,1,2,3,4,5,6&occupiedweekdays=1,2,3,4,5&ohstart=09:15&ohend=17:30&inte
rval=week&reporttype=Electric_Energy
Returns
<?xml version="1.0" encoding="UTF-8"?>
<ReportData>
<Value_StartTime>2012-01-01</Value_StartTime>
<Value_EndTime>2012-01-31</Value_EndTime>
<Value_Interval>WEEK</Value_Interval>
<Row>
<GroupNo>1</GroupNo>
<Timeslice>2012-01-01</Timeslice>
<TotalOn>1196.83</TotalOn>
<TotalOff>2028.61</TotalOff>
<Total>3225.44</Total>
</Row>
<Row>
<GroupNo>1</GroupNo>
<Timeslice>2012-01-08</Timeslice>
<TotalOn>1202.04</TotalOn>
<TotalOff>2233.79</TotalOff>
<Total>3435.82</Total>
</Row>
</ReportData>
Parameters
meterlist[] – The ID of the areas/meters to read data for. Each meterlist[] parameter is
treated as a group.
interval – How to group data – options are ‘day’, ‘week’, ‘month’, and ‘year’. If not specified,
data arenot grouped by time.
reporttype – The type of data to use from the specified meters and areas. Possible values are
Electric_Energy, Electric_Apparent, Gas_Volume, Gas_Energy, Fuel_Volume, Water_Volume,
Thermal_Energy, Steam_Weight, and Carbon_Emission.
Sample URL
http://localhost/enteliweb/wsreportdata/cumulativetargets?meterlist[]=(a983f772-406c-11e1-a360-
005056a20023, a36gd772-406c-11e1-a360-005056a20023)&meterlist[]= (d0f3f772-406c-11e1-a360-
005056a20023)&starttime=2011-01-01&endtime=2011-01-
28&interval=month&reporttype=Electric_Energy
Returns
<?xml version="1.0" encoding="UTF-8"?>
<ReportData>
<StartTime>2011-01-01</StartTime>
<EndTime>2011-12-31</EndTime>
<Interval>MONTH</Interval>
<Row>
<GroupNo>1</GroupNo>
<Timeslice>2011-01</Timeslice>
<Target>51621.4100000000</Target>
<TotalTarget>51621.41</TotalTarget>
</Row>
<Row>
<GroupNo>2</GroupNo>
<Timeslice>2011-01</Timeslice>
<Target>0.0000000000</Target>
<TotalTarget>51621.41</TotalTarget>
</Row>
<Row>
<GroupNo>1</GroupNo>
<Timeslice>2011-02</Timeslice>
<Target>45009.0200000000</Target>
<TotalTarget>206860.43</TotalTarget>
</Row>
<Row>
<GroupNo>2</GroupNo>
<Timeslice>2011-02</Timeslice>
<Target>110230.0000000000</Target>
<TotalTarget>206860.43</TotalTarget>
</Row>
</ReportData>
Parameters
meterlist[] – The ID of the areas/meters to read data for. Each meterlist[] parameter is
treated as a group.
weekdays – The days of the week to include in the returned data. Specified as a comma
delimited list of numbers 0 through 6, where 0 represents Sunday and 6 represents Saturday.
reporttype – The type of data to use from the specified meters and areas. Possible values are
Electric_Energy, Electric_Apparent, Gas_Volume, Gas_Energy, Fuel_Volume, Water_Volume,
Thermal_Energy, Steam_Weight, and Carbon_Emission.
Sample URL
http://localhost/enteliweb/wsreportdata/dailyaverageprofile?meterlist[]=(a983f772-406c-
11e1-a360-005056a20023, a36gd772-406c-11e1-a360-005056a20023)&starttime=2012-01-
01&endtime=2012-01-31&weekdays=0,1,2,3,4,5,6&rollup=10&reporttype=Electric_Energy
Returns
<?xml version="1.0" encoding="UTF-8"?>
<ReportData>
<StartTime>2010-01-31 00:00:00</StartTime>
<EndTime>2010-02-06 23:59:59</EndTime>
<Row>
<Time>00:00:00</Time>
<Data1>66.99464</Data1>
<Data2>20.15664</Data2>
</Row>
<Row>
<Time>00:10:00</Time>
<Data1>66.90170</Data1>
<Data2>20.02260</Data2>
</Row>
<Row>
<Time>00:20:00</Time>
<Data1>67.21421</Data1>
<Data2>20.20269</Data2>
</Row>
<Row>
<Time>23:40:00</Time>
<Data1>68.20064</Data1>
<Data2>21.08550</Data2>
</Row>
<Row>
<Time>23:50:00</Time>
<Data1>67.06782</Data1>
<Data2>20.28247</Data2>
</Row>
</ReportData>
Parameters
meterlist[] – The ID of the areas/meters to read data for. Each meterlist[] parameter is
treated as a group.
weekdays – The days of the week to include in the returned data. Specified as a comma
delimited list of numbers 0 through 6, where 0 represents Sunday and 6 represents Saturday.
reporttype – The type of data to use from the specified meters and areas. Possible values are
Electric_Energy, Electric_Apparent, Gas_Volume, Gas_Energy, Fuel_Volume, Water_Volume,
Thermal_Energy, Steam_Weight, and Carbon_Emission.
Sample URL
http://localhost/enteliweb/wsreportdata/loaddurationmultiple?meterlist[]=(a983f772-406c-
11e1-a360-005056a20023, a36gd772-406c-11e1-a360-005056a20023)&starttime=2012-01-
01&endtime=2012-01-31&weekdays=0,1,2,3,4,5,6&loadstep=5&reporttype=Electric_Energy
Returns
<?xml version="1.0" encoding="UTF-8"?>
<ReportData>
<StartTime>2012-01-01</StartTime>
<EndTime>2012-01-31</EndTime>
<Row>
<Load>0</Load>
<Data1>744</Data1>
<Data2>744</Data2>
</Row>
<Row>
<Load>5</Load>
<Data1>566.75</Data1>
<Data2>528.25</Data2>
</Row>
<Row>
<Load>10</Load>
<Data1>374.08333333333</Data1>
<Data2>310.91666666667</Data2>
</Row>
<Row>
<Load>15</Load>
<Data1>248.08333333333</Data1>
<Data2>120</Data2>
</Row>
<Row>
<Load>20</Load>
<Data1>153.75</Data1>
<Data2>21.333333333333</Data2>
</Row>
<Row>
<Load>60</Load>
<Data1>1.25</Data1>
<Data2/>
</Row>
<Row>
<Load>65</Load>
<Data1>0.16666666666667</Data1>
<Data2/>
</Row>
</ReportData>
This appendix outlines the most useful functions in these libraries.You can open up the library
files for viewing – they are not minified so they are easily readable.
Delta.js
Delta.js is the main API file for use. It contains the following collection of useful namespaces:
Delta.FullRef
Contains reference parsing functionality for dealing with BAC object references.
Delta.Util
Contains common JavaScript utilities for trimming spaces and encoding text.
Delta.WS
Contains wrappers for AJAX web service calls, as well as some common enteliWEB web
service calls.
Delta.DateTime.js
The Delta.DateTime.js library contains custom date/time parsing and formatting functions that
help to handle the differences between BACnet and JavaScript date formatting.
BACtoJSDate
JStoBACDateTime
formatDate
getPrettyDateTime
Delta.UI.js
The Delta.UI.js library contains functions which help aid in getting object UI information such
as icons and links.
getObjectLink
getIcon
playSound