Is Murano get history possible?


#1

Hi,

I need history data with time and value to draw a chart(e.g. temperature).

So I want create a services or modules in murano solutions. How could I query the history data?

Am I look for right place in Murano scripting?

Cause I see the Tsdb is a time storage service but it seem can’t query the product’s device attribute.
Is it store data in other space not binding on product’s device?

I not clear understand about to get history data in Murano Solutions.

Appreciate any suggestions.


#2

Hi Johnathan,

Thanks for posting to our forum!

How could I query the history data?
Am I look for right place in Murano scripting?

Absolutely! Murano resources do not keep track of historical data, and will always present only the most recent value written to them. For historical data, we suggest using Tsdb, just as you suspected!

I see the Tsdb is a time storage service but it seem can’t query the product’s device attribute.
Is it store data in other space not binding on product’s device?

Tsdb does not work with metrics based on device resources, but rather its own database of fully customizable metrics and tags that are written-to and queried-from. One common use of Tsdb is to take data that is written to a device and create a historical log by writing those values into Tsdb. The script held under Solutions > Services > Product will trigger any time a resource under a linked Product is updated. The data that triggers the script is passed into the script as a datapoint.

For example, if you have a temperature sensor that is writing to a resource in Murano, you could use the script mentioned above to have Tsdb.write() calls automatically populate the historical log you are looking to make. You could then also create a custom endpoint that, when hit, returns a preset or custom range of data values using Tsdb.query().

I would suggest making two custom endpoints to start, say /tsdb/write and /tsdb/query, putting in the example code given in the Tsdb documentation. Play around with this code to get the feel for how metrics, tags, and start/end times work!

Of course, do not hesitate to communicate here if you run into any trouble!

Happy to help,
Eli


#3

Hi Eli,

Thanks your reply.

I create end point /tsdb/write and /tsdb/query, test it work fine.

Than I try insert the handler to Solutions > Services > Product

function handle_device_datapoint (data)
  local alias = data.alias
  local tem = alias['temperature']
  local hui = alias['humidity']
  local metrics = {
    emperature = tem,
    humidity = hui,
  }
  local tags = {
   pid = "MY_PROCDUCT_ID",
   identity = "000001",
   region = "asia",
   city = "taipei"
  }
  local out = Tsdb.write({
    metrics = metrics,
    tags = tags
  })
  print(out)
end

Add this code seem make behavior strange and not do right thing eventually cost good function not work.

I assume when I add the code than write value will cause tsdb.write(). But result look like not good.

How can I fix it right? How I write workable Service Lua script?


#4

Hi Johnathan,

I assume when I add the code than write value will cause tsdb.write(). But result look like not good.

You are on the right track, we just need to shift your thinking a little bit! First, remember that the script in this area will run when a resource of a device under a selected product is updated. This means one alias at a time will pass it’s data into the scripting environment as the data object.

local alias = data.alias
local tem = alias[‘temperature’]
local hui = alias[‘humidity’]
local metrics = {
emperature = tem,
humidity = hui
}

This looks like you are trying to grab the data out of each resource at will. While it is possible to do this, using other methods, we want instead to explore actively handling the data the moment it comes into each resource.

For example: Your temperature/humidity sensor reads temperature and humidity as 70 and 53 respectively, and updates each of the device resources accordingly. The moment the first resource is updated, it fires the Event Trigger (script held in Solutions > Services > Product), passing in it’s information as a datapoint object.

Note that the datapoint object has many different fields that we can access and potentially use within Tsdb. Let’s explore an implementation where each alias gets it’s own column in the database:

local metrics = {}
metrics[data.alias] = data.value[2]

First, we create an empty Lua table, then we use the alias that is brought to us in the datapoint object as the name of our database column, passing in our value.

Note that the actual value of a datapoint (what was written to the resource) is always data.value[2]

local tags = {
   pid = data.pid,
   identity = data.device_sn,
   region = "asia",
   city = "taipei"
   }

This first two tag fields here actually have values passed-in through ‘data’. Tags provide potential filters for your queries; maybe only values with a specified identity or from a particular region.

local out = Tsdb.write({
    metrics = metrics,
    tags = tags
    })

Now that we have everything set up how we want it, this is exactly how you would write to Tsdb. Because there is no timestamp specified, it will use the time in microseconds as received from server side at the time of execution.

Note that this handler is capable of handling each event in a unique way, using the fields from our datapoint object to identify how to update our database.

Now, maybe you want to create an endpoint to retrieve data from Tsdb. This can be done many different ways; maybe you want to have an endpoint that retrieves all data from every metric on every device (e.g. /tsdb/query/all), or maybe you want one endpoint for each possible metric (e.g. /tsdb/query/temperature and /tsdb/query/humidity respectively), or maybe one that uses custom values to specify which metric to get (e.g. /tsdb/query/{sn}/{alias}).

Let’s explore that last example:
Whatever you pass through {sn} and {alias} when you hit the endpoint will become usable values within the endpoint script.

local metrics = {
    request.parameters.alias
    } 
local tags = {
    identity = request.parameters.sn
    } 
local out = Tsdb.query({
    tags = tags,
    metrics = metrics
    limit = 100
    })

There are of course many customizations you can use beyond this, but I hope this gives you a little more insight into how things can be done using Tsdb.

As always, don’t hesitate to reach out with any further questions!

Happy to help,
Eli


#5

Hi Eli,

So many thanks!

It’s works smoothly. Your support really helpful and inspire me.

Thanks again!