0

In Angularjs I need to display a list of datapoints {name:"", type:"", value:"",...} that I retrieve from the database of the Cumulocity cloud. Also I need the datapoints to update whenever their value changes in the backend. The datapoint name and type are known beforehand, but the value I have to retrieve separately and update after it changes in the backend.

function init(){
  var promiseDatapointNameType = c8yDevices.detail(deviceId);
  promiseDatapointNameType.then(c8yBase.getResData)
  .then(createDatapointObjectStack)
  .then(getDatapointObjectValues) // Problems start here
  .then(resolvedObjectsToView);
};

I am trying to accomplish this through an array of promised objects, where each object is the datapoint's {name and type} that were retrieve earlier and then I request the latest value for each of the datapoint Objects in the stack from the backend.

function getDatapointObjectValues(datapointStack){
  return datapointStack.map(function(dpObject){
    return getLatestMeasurement(dpObject);
  });
}

Therefore I call the function getLatestMeasurement on each object in the datapointStack, that fires a request to the Cumulocity database and returns a promise that returns the latest value for the datapoint Object when resolved. Additionally the realtime option is set, that updates this promised value in "realtime" on value change.

// For a given filter, function returns a promise of the latest     
function getLatestMeasurement(dpObject){

  var filter = {
    device: deviceId,
    fragment: "CloudControl Parameters",
    series: dpObject.name
  };
  var realtime = true;

  return c8yMeasurements.latest(filter, realtime).then(c8yBase.getResData).then(function (responseValue) {
    var jsonPathToDp = filter.fragment + "." + filter.series + ".value";
    var latestValueDB = getObjectValue(responseValue, jsonPathToDp);
    dpObject.valueLatest = latestValueDB;
    return dpObject;
  });
};

If any of the promises in the array of promised objects resolves, I want to update the corresponding Datapoint Object in the view so that the new value gets displayed.

function resolvedObjectsToView(dpStackValues){
  $q.race(dpStackValues).then(function(dpRaceObject){
    vm.device.datapointStack.push(dpRaceObject);
  });
}

My current state is that all the datapoints get displayed, however they do not update their values if they change in the backend. Here I got stuck as I don't know if reusing a promise after it resolved in an array is practicable and also how to accomplish it with an alternative way. If I use race only a single datapoint is shown in the list, if I use $q.all they are all shown but in both cases no value updates.

So my questions are:

How do i reuse resolved promised Objects if a value in the backend changes? And how do I update an objects value in the view if the associated promised object in an array resolves?

frmfl
  • 28
  • 4
  • `if reusing a promise after it resolved in an array is practicable` - what do you mean re-use? once a promise is resolved, that's it – Jaromanda X Mar 07 '17 at 12:27
  • _"Returns a promise which resolves to an object with latest measurement data for specified filter. Optionally, this object is updated in realtime."_ The discription for the c8yMeasurements.latest method from the API. If the promise resolves only once, how then is it possible to receive value updates without frequent requests? – frmfl Mar 07 '17 at 12:34
  • Web aocket. Server sent events. Long polling. That's 3 ways I can think of – Jaromanda X Mar 07 '17 at 12:37
  • Ok, lets assume long polling is implemented by c8yMeasurements.latest and it is doing exactly that. Function returns object when promise resolved. How to proceed from there? – frmfl Mar 07 '17 at 13:45

1 Answers1

0

Why do not use the cumulocity real time notification for this purpose? You can easily get when any type of measurement changes at the exactly right time they do. So you need to create a channel in cumulocity where you receive all measurements and send these measurement to a notification channel you want it. Here is how I see it: 1. The channel notification for every measurement

    insert into
      SendNotification
    select
      m.measurement as payload,
      "measurement/myspecificchannelname"
    from
      MeasurementCreated m;
  1. Create a subscription in your app to the channel you created, like:

Cumulocity angular notification module documentation .Note that in this example you must create a subscription to the measurement/myspecificchannelname channel.

like so:

var channel = '/measurement/myspecificchannelname';
function init() {
 c8yNotifications.subscribe(channel).then(onSubscription);
}

If you have a specific measurement this will be the best way. But if you want any measurement from any device which will be something weird you could just make a subscription to a /measurement channel which is already create in cumulocity.

This is just one way and hope this help you somehow!Maybe if some guy from cumulocity show up here will be better!

Jorge
  • 238
  • 1
  • 10