Author: Marcelo Blechner, Staff Software Engineer.
How to make any geo referenced Maximo object to be displayed on a Maximo Scheduler Map component using Location-Based Service data
In the article Making your Maximo objects available on the Map you learned how to make the necessary changes so that Maximo objects that have no mapping support out-of-the-box can be displayed on a custom Map component. Maximo Scheduler 7.5.2 introduced a new concept for mappable objects: objects that can have 2 sources of positional data (static and dynamic). Labors and Crews are examples of Maximo objects that have dynamic location information. Once a user logs on to Maximo Everyplace, the Labor associated with them (or active Crew that contains that Labor) starts to have its current location stored to Maximo's LBSLOCATION table and updated in a timely manner according to a preconfigured period. The location information such as latitude, longitude, location accuracy is fetched from the device browser's geolocation APIs using Location-Based Service (LBS) capabilities. However, a client may need existing GISable objects to also store dynamic location information. In Maximo Scheduler 7.5.2., the Asset class has been extended to support both static and dynamic location information. For instance a train, which is a movable asset, can be assigned the coordinates of a depot in its Service Address but, as the train starts operating, its location will change. By periodically storing the train's dynamic coordinates as an entry in the LBSLOCATION table, it is possible for a Map Tool to track the train's current location.
This article describes how to extend any Maximo GISable MBO to be placed in Maximo Scheduler Map component using its dynamic LBS coordinates rather than its static GIS coordinates (fetched either from a Service Address record or from a GIS database in case of Maximo Spatial).
Implementing CombinedLBS interface on MBOs
The Asset MBO is an example of MBO that has been extended to support both GIS coordinates and LBS coordinates. An optional Map Tool, AssetLocationTool, has been implemented to allow for the switching of source of positional data for asset records between the service address (or GIS database in case of Maximo Spatial) and LBS. However, a functionality that fetches LBS information for assets has not been implemented.
Assuming that the MBO to be extended already implements the GISable interface (if not, refer to Making your Maximo objects available on the Map and follow the instructions to make the MBO a GISable MBO), here is how the MBO can be extended.
First of all, remove the com.ibm.tivoli.maximo.map.interfaces.GISable interface from your MboRemote interface and add this provided one: com.ibm.tivoli.maximo.map.interfaces.CombinedLBS. This interface combines, as its name suggests, the functionalities required for a GISable MBO and an LBS MBO. Besides the existing methods that load the MBO's GIS coordinates, this new interface provides the MBO with methods that are used for loading LBS data such as LBS coordinates, location accuracy and the time of the last update.
LBS methods:
-
Double getLocationAccuracy() - return the location accuracy.
-
Double getAltitudeAccuracy() - return the altitude accuracy.
-
Double getAltitude() - return the altitude.
-
Double getHeading() - return the heading.
-
Double getSpeed() - return the speed.
-
Date getLastUpdate() - return the last time that LSB data has been saved.
-
void saveLBSData(Double lat, Double lng, Double locationAccuracy, Double altitudeAccuracy, Double altitude, Double heading, Double speed) – save LBS data.
CombinedLBS methods:
-
Double getLBSLatitudeY() - return the last latitude coordinate stored by saveLBSData, rather than the GISable's getLatitudeY() which fetches the latitude coordinate (or Y coordinate in the case of a generic coordinate system) according to the Auto Locate logic.
-
Double getLBSLongitudeX() - same as getLBSLatitudeY() for the longitude (or X coordinate).
Besides all existing map functionalities that the GISable MBO had, by implementing these CombinedLBS methods on a MBO, it will also be possible for a custom map tool to switch the source of positional information so that LBS data can be used instead of GIS data.
The next section is an easy step-by-step example with code samples to show how to make GISable Maximo object a CombinedLBS Maximo object.
Code Sample: Converting a GISable Maximo Object into a CombinedLBS Maximo object
As described in the previous section, in order to make a Maximo Object be able to show up on a Maximo Scheduler Map component using either GIS or LBS location information, you have to implement the CombinedLBS interface (note that CombinedLBS extends LBS, which extends GISable, so all methods in LBS and CombinedLBS need to be implemented). Here are code samples demonstrating how to do that.
First of all we need to add the relationship that creates the link between a MBO record and a record from the LBSLOCATION table (no new attributes need to be created as the LBSLOCATION table can store all the data that we need). The Database Configuration application can be used to accomplish this, or you can use a DBC script line (similar to this one for Asset) to add the new relationship:
<create_relationship parent="ASSET" name="LBSLOCATION" child="LBSLOCATION" whereclause="refobject='ASSET'
and key1 =:orgid and key2 =:assetnum and key3 =:siteid" remarks="Relationship to find the lbslocation from
an asset" />
Note that KEY1 needs to be bound to the ORGID and KEY2 needs to be bound to the MBO “org level” (or “site level”) idendifier. If the MBO is “site level”, then KEY3 needs to be bound to the SITEID. Otherwise, the KEY3 linking (“and key3=:siteid”) can be omitted.
In the MBO remote interface, remove this line:
import com.ibm.tivoli.maximo.map.interfaces.GISable;
and add this one instead:
import com.ibm.tivoli.maximo.map.interfaces.CombinedLBS;
and then implement the required methods in the MBO class. Here are some examples from the Asset class.
@Override
public
Double getLBSLongitudeX()
throws
MXException, RemoteException
{
MboSetRemote lastLocationSet = getMboSet("lbslocation");
MboRemote location = lastLocationSet.getMbo(0);
if
(location!=
null
)
{
return
location.getDouble("LONGITUDE");
}
return
null
;
}
All other get methods will follow the same template, but each one will return a different field from the LBSLOCATION table (LATITUDE, LOCATIONACCURACY, ALTITUDE, ALTITUDEACCURACY, HEADING, SPEED, LASTUPDATE).
The save method, however, needs to pass along all LBS data to the LBSLocation.setLBSValues method.
@Override
public
void
saveLBSData(Double lat, Double lng, Double locationAccuracy,
Double altitudeAccuracy, Double altitude, Double heading, Double speed)
throws
MXException, RemoteException
{
MboSetRemote lastLocationSet = getMboSet("lbslocation");
LBSLocationRemote newMbo = (LBSLocationRemote)lastLocationSet.getMbo(0);
if
(newMbo ==
null
)
{
newMbo = (LBSLocationRemote)lastLocationSet.add();
}
// key1=ORGID, key2=ASSETNUM and key3=SITEID
String[] values =
new
String[3];
values[0] =
this
.getString("orgid");
values[1] =
this
.getString("assetnum");
values[2] =
this
.getString("siteid");
newMbo.setLBSValues("ASSET", values, lat, lng, locationAccuracy,
altitudeAccuracy, altitude, heading, speed);
lastLocationSet.save();
}
Note that the first argument in LBSLocation.setLBSValues is the MBO name and the second one is a String array containing the 3 keys in LBSLOCATION.
Keep in mind that, although the get methods are called automatically by the Map component framework, the developer is responsible for implementing the logic that calls the MBO's saveLBSData method whenever new LBS data is available (either from the browser's geolocation API or other sources).
After implementing all required interface methods, the MBO is now ready to send LBS data to the Map component. However, the Map component only uses GIS positional data by default. The only exceptions are MBOs that only have LBS information, i.e. MBOs that implement the LBS interface (Labors and Crews). For a CombinedLBS MBO to be able to show up on the Map component using its LBS data, a custom Map Tool needs to be created.
The next section is an easy step-by-step example with code samples to show how to implement a custom map tool that allows the map component to switch the source of coordinates from either GIS data or LBS data.
Code Sample: Creating a Map Tool that allows for a CombinedLBS object to show up on the Map component using its LBS data
In Creating Custom Tools in Maximo Scheduler Maps you learned how to create a custom map tool and make it available in the map component. A custom map tool that can switch the source of positional data of a record is as simple as creating the simple tool sample from that article.
Following the steps of section on creating custom tools in Creating Custom Tools in Maximo Scheduler Maps, create a text file with a .js extension and choose a suitable name. This tool, however, will extend _ToggleTool, instead of _ToolTemplate because it has two states (GIS data will be used when the tool is off, and LBS data will be used when the tool is on).
Instead of implementing the execute() function from the _ToolTemplate class, implement the executeOn() and executeOff() functions as follows:
executeOn:
function
()
{
dojo.publish("changeLayerLatLngSource_" +
this
.map.getId(), [ "asset",
true
]);
},
executeOff:
function
()
{
dojo.publish("changeLayerLatLngSource_" +
this
.map.getId(), [ "asset",
false
]);
},
All other functions can have the same default implementation as the ones in the HelloTool.js example. No bean class is needed here as no extra requests to the Maximo server are made by the new Map Tool. Note that, instead of asset, you need to use the layer ID of the Maximo object that you are using. For further information on layers, refer to Configuring Map Symbology on Maximo Scheduler.
The changeLayerLatLngSource event is used to tell the Map component which source of positional data should be used when displaying a CombinedLBS MBO (false is the default value and tells the Map component that it must use GIS data; true tells the Map component that it must use LBS data).
Assuming that the MBO was a GISable before, a Map tab is already available for the MBO application. So, in Application Designer, add the tool to the Toolbar items field of the map properties.
That is all! When the map is loaded in the Map tab, the new tool will show up in the toolbar. If the tool is turned on and one or more records do not have LBS data available, an error message will be displayed.
When a CombinedLBS MBO is being displayed on the Map using its LBS data, only the following attributes are taken into account when drawing the marker:
-
LATITUDE and LONGITUDE (used to pinpoint the position of the marker on the map);
-
LOCATIONACCURACY (radius - in meters - used to draw the accuracy circle around the marker)
-
LASTUPDATE (used to select the color of the “age” indicator of the marker)
The HEADING, SPEED, ALTITUDE and ALTITUDEACCURACY attributes are not being used by the Map component in Maximo Scheduler 7.5.2.
Figure 1: Example of a tool that toggles between the Asset's GIS location (to the left) and LBS location (to the right).