GET realtime function
-
Hi sky_watcher,
Fox's solution will probably work, but I suspect you'll want to look at the returned model, as you may need to make some adjustments to what is being assigned.
If there were more than a couple points, I would tag the points using the /bulk-data-point-edit page, and them query for them like,
$.get("/rest/v1/realtime?eq(tags.TagNamer,TagValue)&limit(1000)", function( data ) { for (var i in data){ param.scope.xidToValueMap[ data[ i ].xid ] = data[ i ].value; } });
Sample list of real time data values from the query endpoint:
[ { //comments aren't valid in real JSON "value" : "my alphanumeric value here", "name" : "Point Name", "type" : "Alphanumeric", "path" : "/", //Point Hierarchy path "timestamp" : 1542396942116, "status" : "OK", "xid" : "DP_0e02f7b2-342b-4c49-9cb1-b7c41a480d04", "deviceName" : "Device", "tags" : { "Site" : "Space", "Customer" : "NASANTA", "Sensor" : "Air Pressure" }, "unit" : "", "renderedValue" : "my alphanumeric value here" } ]
-
Thanks Phl, looks like you know more about his situation than I do. My suggestions won't likely work in a loop format without a proper callback but I was under the assumption he just wanted alternatives to pull realtime data. I'd have to do a bit more coding to likely produce whatever he may asking for.
-
looks like you know more about his situation than I do.
Probably - the question got redirected to the forum after a long email chain :D. But, thanks for answering!
He's written a custom dashboard that is not using angular (which would use websockets and be even more efficient for staying up with the latest values for points), and I thought he could lessen the load on his system by requesting from the realtime endpoints than from the point values endpoint for just the last value. The realtime endpoints have more caching and fewer database calls, but are not as versatile (aside from having an RQL query-able endpoint).
-
@phildunlap said in GET realtime function:
The realtime endpoints have more caching and fewer database calls,
Now that's handy to know.
@phildunlap said in GET realtime function:
He's written a custom dashboard that is not using angular
No worries there either. Happy to help where I can.
-
The other solution that could work better for him is to use a WebSocket. Something like...
var myWs = new WebSocket("ws://" + window.location.host + "/rest/v1/websocket/point-value"); // use wss:// for https:// myWs.onmessage = function( message ) { /**For point's events subscribed to, his function will receive messages from the websocket like, * JSON.parse( message.data ) --> * { * "status" : "OK", * "payload" : { * "xid" : "DP_db22d06f-af05-4e44-af0e-50dec6a5c981", * "event" : "UPDATE", * "value" : { * "dataType" : "NUMERIC", * "value" : -2.0, * "timestamp" : 1542824470110, * "anotation" : "Set from web by user: admin" * }, * "renderedValue" : "-2.00 ", * "convertedValue" : -2.0, * "enabled" : true, * "attributes" : { } * } * } * * So this function should update whatever's driving the page */ // console.log( JSON.parse(message.data) ); } myWs.subscribePoint = function(xid) { myWs.send('{"xid":"' + xid + '","eventTypes":["ATTRIBUTE_CHANGE","INITIALIZE","REGISTERED","TERMINATE","UPDATE"]}'); } myWs.unsubscribePoint = function(xid) { myWs.send('{"xid":"' + xid + '","eventTypes":[]}'); }
As the eventTypes array suggests, this will also let your page be aware of attribute changes (point reliability) or the point getting disabled. The websockets are most efficient.
For a list of all point value websocket event types, see https://github.com/infiniteautomation/ma-modules-public/blob/main/Mango API/src/com/serotonin/m2m2/web/mvc/rest/v1/websockets/pointValue/PointValueEventType.java Note that a new value may produce more than one type of event message.
-
@phildunlap Thanks for the solution with WebSockets and sorry for the late response...
I don't know so much about WebSockets and I don't know how to implement this on my website...
If you could give me a bit more information it will very helpful for me.
Thank you!
-
What question are you running into? Aren't you already updating the page in a callback from an API query? You would just update the same scope / view via the websocket onmessage function instead, where the messages should have a form similar to what I posted as a comment in that function.
-
@phildunlap this is my initial function:
UtilObj.getPointsValues = function(param){ if (!param.options){ param.options = {} } param.options.from = param.from.toISOString(); param.options.to = param.to.toISOString(); $.get( "/rest/v1/point-values/" + param.points + "/multiple-points-multiple-arrays", param.options, function( data ) { for (var i = 0; i < param.points.length; i++){ if (data[param.points*]){ param.scope[param.points*] = data[param.points*]; }else{ console.log('Point not available in mango: ' + param.points*) } } param.done(); if (param.scope.$apply){ param.scope.$apply(); } }, "json"); };
This function is inside a if (MangoAPI) statement and the hole thing is inside this function:
define(utilDep, function (angularAMD, MangoAPI) {
var Util = function ($cookies, $route) { -
@phildunlap I'm not sure where should I put the WebSockets code that you gave to me...
-
I would think it would work fine in the same place. Should just need to be in some JavaScript that gets executed, which that excerpt must. You may also need to do something like check the
myWs.readyState
periodically to see if it closed or not connected for some reason (then you'd need to create a new websocket), but I wouldn't worry about that at first. -
@phildunlap I've changed to this, but the points are not displayed anymore in my website, I think I'm doing something wrong, but I don't know what.
UtilObj.getPointsValues = function(param){ var myWs = new WebSocket("ws://" + window.location.host + "/rest/v1/websocket/point-value"); // use wss:// for https:// myWs.onmessage = function( message ) { /**For point's events subscribed to, his function will receive messages from the websocket like, * JSON.parse( message.data ) --> * { * "status" : "OK", * "payload" : { * "xid" : "DP_db22d06f-af05-4e44-af0e-50dec6a5c981", * "event" : "UPDATE", * "value" : { * "dataType" : "NUMERIC", * "value" : -2.0, * "timestamp" : 1542824470110, * "anotation" : "Set from web by user: admin" * }, * "renderedValue" : "-2.00 ", * "convertedValue" : -2.0, * "enabled" : true, * "attributes" : { } * } * } * * So this function should update whatever's driving the page */ //console.log( JSON.parse(message.data) ); }; myWs.subscribePoint = function(xid) { myWs.send('{"xid":"' + xid + '","eventTypes":["ATTRIBUTE_CHANGE","INITIALIZE","REGISTERED","TERMINATE","UPDATE"]}'); }; myWs.unsubscribePoint = function(xid) { myWs.send('{"xid":"' + xid + '","eventTypes":[]}'); } };
And in the console I don't get any error.
-
...Everything in the onmessage function is still commented out... And, you only need to create one websocket so long as it is working, then subscribe to all the points you need via the functions I provided on the websocket. So, you probably don't want to be calling this function as you used to.
Y'know, you really should just enter this into your browser's developer console and play with it until you have some idea.
var myWs = new WebSocket("ws://" + window.location.host + "/rest/v1/websocket/point-value"); // use wss:// for https:// myWs.onmessage = function( message ) { console.log( JSON.parse(message.data) ); } myWs.subscribePoint = function(xid) { myWs.send('{"xid":"' + xid + '","eventTypes":["ATTRIBUTE_CHANGE","INITIALIZE","REGISTERED","TERMINATE","UPDATE"]}'); } myWs.unsubscribePoint = function(xid) { myWs.send('{"xid":"' + xid + '","eventTypes":[]}'); } myWs.subscribePoint( "DP_1234" ); //change to a data point's xid from your system that updates somewhat often
-
@phildunlap I tried to uncomment onmesssage but something is not wright with this part over here:
JSON.parse( message.data )
{
"status" : "OK",
"payload" : {
"xid" : "DP_db22d06f-af05-4e44-af0e-50dec6a5c981",
"event" : "UPDATE",
"value" : {
"dataType" : "NUMERIC",
"value" : -2.0,
"timestamp" : 1542824470110,
"anotation" : "Set from web by user: admin"
},
"renderedValue" : "-2.00 ",
"convertedValue" : -2.0,
"enabled" : true,
"attributes" : { }
}
}I get some errors.
I've pasted the code from your last post into the developer console and I get this:
Thank you!
-
Was this on a browser tab that was logged in to Mango?
Yeah, the first part of the comment was to show the structure of the message passed into the onmessage function. The console.log is actual code at least...
-
@phildunlap Yes, was into a browser tab logged in to Mango.
Maybe a picture with the uncommented function is better, so i put it bellow:
-
My mistake, forgot to put the subscription in the onopen function like,
var myWs = new WebSocket("ws://" + window.location.host + "/rest/v1/websocket/point-value"); // use wss:// for https:// myWs.onmessage = function( message ) { console.log( JSON.parse(message.data) ); } myWs.subscribePoint = function(xid) { myWs.send('{"xid":"' + xid + '","eventTypes":["ATTRIBUTE_CHANGE","INITIALIZE","REGISTERED","TERMINATE","UPDATE"]}'); } myWs.unsubscribePoint = function(xid) { myWs.send('{"xid":"' + xid + '","eventTypes":[]}'); } myWs.onopen = function() { myWs.subscribePoint("DP_1234") }; //change to a data point's xid from your system that updates somewhat often
-
@phildunlap Yes, now when I paste it in the console it is working.
But I have a question, I see there renderedValue and value, but If I want to get data for a chart how can I get values for the past?
-
For values from the past you should continue to use the point-values endpoint. Iirc, the majority of your queries were only for the current, latest value, which the websocket can keep up to date for you.
-
@phildunlap Ok, so I get it wrong... The function that I showed here was the function for my points for my graphic because that was the most time consuming, the function for the points only wasn't so time consuming and I thought that I can use WebSockets to reduce the time for the function that get my points for the graphics...
-
So I tried to modify the function that get my point values like below and I get some errors.
param.points* get my xid's.
Maybe I've done something wrong there.