Hi,
I am developing a custom block for Analytics Builder in Cumulocity and need to output multiple results on a single activation. Calling the corresponding $setOutput action multiple times with the same $activation results in only the last result being sent out. I can think of two options:
- Putting the results into an sequence and store it in a property of a Pulse output - this would make it less convenient for people to use.
- Use timers to sent the results one after another with a small delay (0.1s)
A bit of background what I am trying to do: I am performing calculation on a fixed interval (e.g. 60s). In most cases a single result would be sent after every 60s but there are cases where I may have to wait several intervals before I can finish the calculation and then I want to send the calculation results of multiple intervals at the same time.
A single activation results in a single state across the model. I don’t think there’s any way of setting an output to more than one value during a given activation, just as there’s no way of having an input process more than one value per activation, which is what you would be expecting to happen if an output wires to it changed.
The timed approach you mentioned would have to output a value per activation, and would require you to maintain state between activations.
If you have to send several results on the same activation, you will have to do so as part of a collection, and have a block that can process that collection at the other end of the wire.
To some extent I think the solution will depend on exactly what it is you want to do with the values being output by this block.
The other potential approach is to have multiple outputs, with all but the ‘main’ one being optional in whether they have a value. As I don’t variable inputs/output counts has ever been implemented, you’d have to take a best guess as to how many you might conceivably need (a bit like the logic blocks having an arbitrary five inputs). I think that;s the only way you’ll be able to get uncollected values output in the same activation.
Hi Nicholas,
I provided some context in the last paragraph. The outputs are independent and I cannot predict how many there are. In the end I want to send each result out as a measurement with a different timestamp. There is no way of predicting how many results there will be. So multiple outputs are not an option (and in fact I have 4 outputs which I would have to multiply). As there is no built-in way to loop over things, outputting a collection also seems cumbersome.
To avoid keeping state, I was thinking about creating multiple timers with incremental offsets (0.1s, 0.2s, and so on). If that’s not possible, I could just send the collection to the alarm, remove the current element and raise a new alarm with the smaller collection until it is empty.
Edit: i do not care for them to be in the same activation as the timestamps of the produced are in the past anyway.
One thing that has occurred to me, is that there’s nothing intrinsically stopping you from sending Measurements directly to the REST API to my knowledge. If it’s Measurements you r want, rather than an output to another model block. , essentially creating a custom Output block. I’ve not created a block to do that before, so I don’t know offhand whether there are any constraints built into the framework on that score. As far as I know the activation constraint only applies to the values on model wires, so freeform REST API EPL should be fine. If you do need the Measurements to be processed by a model, you could have a separate model listening for those Measurements, so essentially two models instead of one.
Alternatively, you could send a specific event, Alarm, Event, Measurement out of the model with a collection of a given type, and just have an EPL App handle the job of spinning out the individual Measurements. That may go outside of the scope of where you want to operate though.
Hi Nicolas,
I decided to use the approach with multiple timers:
float offset := 0.1;
for output1 in $blockState.results[$blockState.output1] {
$base.createTimerWith(TimerParams.relative(offset).withPayload(output1));
offset := offset + 0.1;
}
}
...
action $timerTriggered(Activation $activation, Value $payload) {
$setOutput_output1($activation, $payload);
}