• Recent
    • Tags
    • Popular
    • Register
    • Login
    1. Home
    2. ThomasEinasto

    Please Note This forum exists for community support for the Mango product family and the Radix IoT Platform. Although Radix IoT employees participate in this forum from time to time, there is no guarantee of a response to anything posted here, nor can Radix IoT, LLC guarantee the accuracy of any information expressed or conveyed. Specific project questions from customers with active support contracts are asked to send requests to support@radixiot.com.

    Radix IoT Website Mango 3 Documentation Website Mango 4 Documentation Website Mango 5 Documentation Website
    • Profile
    • Following 0
    • Followers 0
    • Topics 25
    • Posts 124
    • Best 21
    • Controversial 0
    • Groups 0

    ThomasEinasto

    @ThomasEinasto

    26
    Reputation
    1.5k
    Profile views
    124
    Posts
    0
    Followers
    0
    Following
    Joined Last Online
    Location Estonia

    ThomasEinasto Unfollow Follow

    Best posts made by ThomasEinasto

    • RE: How to create a bar chart with benchmark line?

      Hi @cwangv ,

      From and To objects are actually date objects in Javascript made using MomentJS if I am not mistaken.

      https://momentjs.com/

      Mango uses date-picker which is hooked into the header if page is configured to use date-picker on this page.

      https://material.angular.io/components/datepicker/overview

      By utilizing these previous two ma-date-picker is created.

      ValueOf represents ms of the presented date in epoch.

      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/valueOf

      Date picker then creates a date object which can be used in amCharts date axis (typically x axis).

      Example:

      https://www.amcharts.com/demos/date-based-data/

      AmCharts is then used to create a chart for us following amCharts documentation in here:

      https://docs.amcharts.com/3/javascriptcharts/ValueAxis << See all sub-sections on the left to see all the properties of the Chart itself. All can be hooked into ma-serial-chart.

      To solve the confusion IAS staff has created ma-serial-chart compontent which solves all programming and helps user to create charts without going into details what is actually happening.

      Actually a lot of information about the tools is written in API Docs with examples and links to all information.

      posted in How-To
      ThomasEinastoT
      ThomasEinasto
    • RE: ma-serial-chart can not run

      Hi @benaznbe!

      As @phildunlap suggested, you should take a look at that forum thread on how to create your own customized module.

      You can see that you are limited for 10 series by using mangos own component.

      In mango 3.x you can access user module page in Administration -> UI settings. Scroll down until you find Miscellaneous settings. There you can find User module URL. Click on the paperclip and click + sign on top right corner.

      ref: https://help.infiniteautomation.com/getting-started-with-a-user-module/

      The following is taken from this forum post https://forum.infiniteautomation.com/topic/2862/bar-chart-category-as-x-axis/15 .

      Thank @Jared-Wiltshire for input.

      Create filename usermodule.js. Add following to there.

      define(['angular', 'require', 'amcharts/serial'], function(angular, require, AmCharts) {
      'use strict';
      
      var userModule = angular.module('userModule', ['maUiApp']);
      userModule.component('categoryXAxis', {
          bindings: {
              values: '<?',
          },
          controller: ['$scope', '$element', function($scope, $element) {
              const options = {
                "type": "serial",
                "theme": "light",
                "addClassNames": true,
                "marginRight": 70,
                "dataProvider": [],
                "valueAxes": [{
                  "axisAlpha": 0,
                  "position": "left",
                  "title": "Level"
                }],
                "startDuration": 1,
                "graphs": [{
                  "balloonText": "<b>[[category]]: [[value]]</b>",
                  "fillColorsField": "color",
                  "fillAlphas": 0.9,
                  "lineAlpha": 0.2,
                  "type": "column",
                  "valueField": "level"
                }],
                "chartCursor": {
                  "categoryBalloonEnabled": false,
                  "cursorAlpha": 0,
                  "zoomable": false
                },
                "categoryField": "INVxx",
                "categoryAxis": {
                  "gridPosition": "start",
                  "labelRotation": 45
                },
                  "titles": [{
                   "text": "Production Chart"
               }]
              };
              
              const chart = AmCharts.makeChart($element[0], options);
      
              $scope.$watch('$ctrl.values', () => {
                  chart.dataProvider = this.values;
                  chart.validateData();
              }, true);
          }]
      });
      
      return userModule;
      
      }); // define
      
      
      userModule.component('categoryXAxis', {
      

      categoryXAxis string is defining the brackets of HTML. You can rename it as you like.

                "categoryField": "INVxx",
      

      Declares the variable name in an values array which describes labels of columns.

                  "valueField": "level"
      

      Declares the variable in an values array which describes the value of the point.

      For making it dynamic and live

              $scope.$watch('$ctrl.values', () => {
                  chart.dataProvider = this.values;
                  chart.validateData();
              }, true);
      

      This looks at values variable change. see ref: https://www.sitepoint.com/mastering-watch-angularjs/

      For more customization see amCharts own documentation which @Jared-Wiltshire and @phildunlap promote all the time on the forums and in Mango. It has all the documentation for them.

      ref: https://www.amcharts.com/demos/simple-column-chart/

      Now press OK on the opened modal and press SAVE on top left corner of the UI Settings page.

      You have now created your own component called categoryXAxis.

      How can you use it on your own page?

      As @phildunlap said you probably do not need to use statistics to get last values of your points.

      <ma-get-point-value> 
      

      already does it for you

      So for your page I eliminated the statistics to make it more shorter. It is below

      <md-whiteframe id="graph2" align="center" style="position: absolute; left: 24px; top: 240px; width: 900px; height: 280px; background-color: rgb(255, 255, 255); border: 1px solid rgb(169, 169, 169); font-size: 20px; font-weight: bolder; color: rgb(1, 1, 1);">Production Chart
              <div style="display:none;" ng-init="myPreset='DAY_SO_FAR'"></div>
                  <div ng-init="myInterval='1 minutes'"></div>
                  <ma-date-range-picker style="display:none;" update-interval="{{myInterval}}" preset="{{myPreset}}" to="to" from="from"></ma-date-range-picker>
                  <div id="14145" style="display:none;width: 500px; height: 35px; position: absolute; left: 800px; top: 700px;" layout="row">
                      <md-input-container flex=""> 
                      <label>From date</label>
                          <ma-date-picker format="DD-MM-YYYY" mode="both" ng-model="from"></ma-date-picker>
                          </md-input-container>
                          <md-input-container flex="">
                          <label>To date</label>
                          <ma-date-picker format="DD-MM-YYYY" mode="both" ng-model="to"></ma-date-picker>
                          </md-input-container>
          </div>
          
          <ma-get-point-value point-xid="INV01.DailyEnergy" point="point1"></ma-get-point-value>
          <ma-get-point-value point-xid="INV02.DailyEnergy" point="point2"></ma-get-point-value>
          <ma-get-point-value point-xid="INV03.DailyEnergy" point="point3"></ma-get-point-value>
          <ma-get-point-value point-xid="INV04.DailyEnergy" point="point4"></ma-get-point-value>
          <ma-get-point-value point-xid="INV05.DailyEnergy" point="point5"></ma-get-point-value>
          <ma-get-point-value point-xid="INV06.DailyEnergy" point="point6"></ma-get-point-value>
          <ma-get-point-value point-xid="INV07.DailyEnergy" point="point7"></ma-get-point-value>
          <ma-get-point-value point-xid="INV08.DailyEnergy" point="point8"></ma-get-point-value>
          <ma-get-point-value point-xid="INV09.DailyEnergy" point="point9"></ma-get-point-value>
          <ma-get-point-value point-xid="INV10.DailyEnergy" point="point10"></ma-get-point-value>
          <ma-get-point-value point-xid="INV11.DailyEnergy" point="point11"></ma-get-point-value>
          <ma-get-point-value point-xid="INV12.DailyEnergy" point="point12"></ma-get-point-value>
          <ma-get-point-value point-xid="INV13.DailyEnergy" point="point13"></ma-get-point-value>
          <ma-get-point-value point-xid="INV14.DailyEnergy" point="point14"></ma-get-point-value>
          <ma-get-point-value point-xid="INV15.DailyEnergy" point="point15"></ma-get-point-value>
          <ma-get-point-value point-xid="INV16.DailyEnergy" point="point16"></ma-get-point-value>
          <ma-get-point-value point-xid="INV17.DailyEnergy" point="point17"></ma-get-point-value>
          <ma-get-point-value point-xid="INV18.DailyEnergy" point="point18"></ma-get-point-value>
         
         <category-x-axis class="amchart"
         values="[{INVxx: point1.name, level: point1.value,color:'blue'}, 
                  {INVxx: point2.name, level: point2.value,color:'red'}, 
                  {INVxx: point3.name, level: point3.value,color:'green'}, 
                  {INVxx: point4.name, level: point4.value,color:'gray'}, 
                  {INVxx: point5.name, level: point5.value,color:'brown'}, 
                  {INVxx: point6.name, level: point6.value,color:'orange'}, 
                  {INVxx: point7.name, level: point7.value,color:'yellow'}, 
                  {INVxx: point8.name, level: point8.value,color:'purple'}, 
                  {INVxx: point9.name, level: point9.value,color:'blue'}, 
                  {INVxx: point10.name, level: point10.value,color:'blue'} , 
                  {INVxx: point11.name, level: point11.value,color:'blue'} , 
                  {INVxx: point12.name, level: point12.value,color:'blue'} , 
                  {INVxx: point13.name, level: point13.value,color:'blue'} , 
                  {INVxx: point14.name, level: point14.value,color:'blue'} , 
                  {INVxx: point15.name, level: point15.value,color:'blue'} , 
                  {INVxx: point16.name, level: point16.value,color:'blue'} , 
                  {INVxx: point17.name, level: point17.value,color:'blue'} , 
                  {INVxx: point18.name, level: point18.value,color:'blue'}]">
         </category-x-axis>
         
          </md-whiteframe>
      

      ref: https://forum.infiniteautomation.com/topic/3503/how-to-chart-with-data-points-in-the-x-axis-instead-of-time

      I wish you good luck in all.

      Thomas

      posted in Dashboard Designer & Custom AngularJS Pages
      ThomasEinastoT
      ThomasEinasto
    • RE: Overrides... logo.svg troubles

      Old UI topic

      Older users of Mango were using Legacy UI before Angular was introduced in Mango. But Mango legacy pages did not have so much flexibility / easy configuration to create your own system like you want which is probably why IAS took the direction for the Mango 3.x UI.

      Most simply said in Mango 3.x user is in a web-application developed in Angular which uses Mango (and other) API's/ libraries to configure Mango settings. The same way like in the old UI.

      You can go to legacy (old-UI) by going to lets say /data_sources.shtm to see how old Mango looked like. There on top left corner you can also see your overrides logo if I am not mistaken.

      File topic

      And you are correct. The uploaded file should stay in that folder if you update Mango. The file is actually put in $ROOT/filestore/public/ folder which is not modified by updates.

      Have a nice weekend!
      Thomas

      posted in User help
      ThomasEinastoT
      ThomasEinasto
    • Native desktop app with NodeJS / Electron without having to think about how to solve browser issues

      Dear Mango community,

      I don't know if it is the right forum section for this but it seemed like so.

      Sometimes while doing your Mango projects you might come into a situation where your clients cannot use Chrome or a modern browser due to the limitations of their own internal policy, be it some restrictions on computer usage or whatever.

      For that sometimes it is required to create your own cross-platform application which your client can use to get to their Mango instance. This actually creates your own application and you can distribute the application to your users while commissioning.

      NodeJS and Electron is quite good solution to solve this. Even better solution without having to learn all the steps in NodeJS and Electron is Nativefier.

      https://nodejs.org/en/download/
      https://github.com/jiahaog/nativefier

      Tutorial is on the github page above.

      This lets you create an cross-platform application for any website by just running one command on the NodeJS command line to create your own application easily.

      I am not the developer for this but just searching around the internet I stumbled upon a easy solution without having to learn really anything and thought it would be useful for the community.

      The post is made just to share to the community as there are many users who are not so good in modern web development but might come into these troubles while trying to sell your solution to your customer.

      posted in Dashboard Designer & Custom AngularJS Pages
      ThomasEinastoT
      ThomasEinasto
    • RE: Native desktop app with NodeJS / Electron without having to think about how to solve browser issues

      Thanks @Jared-Wiltshire

      App works perfectly with buttons so that Mango is looking like a real app with buttons. Is it possible to inject them behind help button so that it would look better?

      0_1571163280269_1c745c87-661d-4435-a9ae-4d1b6f7a0dd2-image.png

      Anyone who is interested:

      Solved this by first creating preloader.js file in the folder where app will be created with following code. There are several options I guess but this was just one of the easiest to accomplish:

      function sd() {
      	const remote = require('electron').remote;
      	var currentwindow = remote.getCurrentWindow();
      	var logFn = console.log;
      
      console.log = function(arg1) {
      
         if (arg1 == 'close-electron'){
      	   
              let windows = remote.getCurrentWindow();
              windows.close();	
      		
         }else if (arg1 == 'maximize-electron'){
      	   
      	   if(currentwindow.isMaximized()){
      			let windows = remote.getCurrentWindow();
      			windows.unmaximize();
      	   }else{
      			let windows = remote.getCurrentWindow();
      			windows.maximize();
      	   }
      	   
         }else if (arg1 == 'minimize-electron'){
      	   
      	   let windows = remote.getCurrentWindow();
             windows.minimize();
      		
         }else{
      	   
      	   logFn(arg1)
      	   
         }
         
      }
      
      }
      
      sd();
      
      
      
      

      Following code actually rewrites console.log function to a custom function in a global scope within the application.

      Then add usermodule by modifying @Jared-Wiltshire usermodule like this:

      define(['angular', 'require'], function(angular, require) {
          'use strict';
      var electron = false;
      const userModule = angular.module('userModule', ['maUiApp','ngLocale']);
      
                      var userAgent = navigator.userAgent.toLowerCase();
                      console.log(userAgent)
                      if (userAgent == 'electron') {
                          electron = true
                      }else{
                          electron = false;
                      }
      if (electron){
          
          run.$inject = ['$rootScope', 'maTranslate', '$templateCache'];
          function run($rootScope, Translate, $templateCache) {
              const userActionsUrl = 'userActions.html';
              $templateCache.put(userActionsUrl,
                  `
                  <md-button class="md-icon-button" ng-click="minimize()">
                      <md-icon>more_horiz</md-icon>
                  </md-button>
                  <md-button class="md-icon-button" ng-click="maximize()">
                      <md-icon>fullscreen</md-icon>
                  </md-button>
                  <md-button class="md-icon-button" ng-click="close()">
                      <md-icon>close</md-icon>
                  </md-button>`);
                  
              $rootScope.userActions = userActionsUrl;
              $rootScope.close = () => {
                  console.log('close-electron');
              };
              $rootScope.maximize = () => {
                  console.log('maximize-electron');
              };
              $rootScope.minimize = () => {
                  console.log('minimize-electron');
              };
          }
          
          userModule.run(run);     
          
      }      
              return userModule;
          
          }); // define
      

      This module actually console.logs commands which are analyzed in a function located in preloader.js file and only activates when userAgent is called 'electron' which we will define in a final function below.

      Add also your custom css in mango UI settings to make header draggable.

      .ma-ui-main-toolbar{
          
          -webkit-app-region: drag;
          
      }
      button {
          
          -webkit-app-region: no-drag;
          
      }
      md-input-container{
          -webkit-app-region: no-drag;
      }
      
      .ma-ui-tools > div[ng-include=userActions] {
        order: 1;
      }
      

      Finally, ensure that you are using nativefier version 7.6.10 so that injection actually would work correctly. Check your version with nativefier -v, should output as

      7.6.10
      

      If not then following command will allow you to install correct version from npm.

      npm install -g nativefier@7.6.10
      

      Now create app with following command:

      nativefier -u electron -e 2.0.8 http://url-to-mangoinstance --browserwindow-options "{ \"webPreferences\": { \"nodeIntegration\":true } }" --inject preloader.js --hide-window-frame
      

      -u specifies your useragent which is electron,
      -e specifies electron version (use 2.0.8 so that --inject would be successful.
      your link to the mango instance
      --browserwindows-options JSON string for specifing electron browser options. see https://electronjs.org/docs/api/browser-window#new-browserwindowoptions
      (we are using nodeIntegration to enable electron in front-end)
      --inject The file to inject to the page after DOM has loaded.
      --hide-window-frame Hide windows framing because we will be using mango header which css we have enabled in UI settings.

      You have now created the application for your Mango instance.

      posted in Dashboard Designer & Custom AngularJS Pages
      ThomasEinastoT
      ThomasEinasto
    • RE: External IP

      Hi @sky_watcher

      I assume your external IP which you provided is your own modem IP (router). And your MangoES is connected into your local network. You should first see port forwarding to make it secure and to make your router forward remote connections to your ES. This is not good practice as you will be providing to everyone your router which is not a server per say.

      See, for more information-> https://portforward.com/

      Secondly you should buy a domain to get an human understandable address. https://www.sky_watcher.net for an example.

      After buying a domain you can assign this domain dns to be linked with your ip address. Then you would have to wait for a few hours after your dns settings have been updated through all dns servers.

      Then if you go to your bought domain name through your browser then the dns server which you are using for your computer will connect you remotely to your assigned IP address.

      More information is in available like this.
      https://www.ntchosting.com/encyclopedia/dns/ip-address/

      Thomas

      posted in Mango General
      ThomasEinastoT
      ThomasEinasto
    • RE: Logging on value change

      As reading through the help :

      When point value changes is the default logging setting. The point value and its time of occurrence is written to the database only if the value of the point actually changes. This setting provides the best compromise of quality of historical information vs storage space efficiency. For Numeric points, a Tolerance, or "deadband", can also be provided; the value will be logged if the absolute value of the difference between the present value and the previous value equals or exceeds the given tolerance.

      I would suggest to use The When point timestamp changes setting which is similar in behaviour to the on value change setting, but the timestamp of the sample is compared instead of the value to save all triggers to Mango database.

      Thomas

      posted in User help
      ThomasEinastoT
      ThomasEinasto
    • RE: How to display Alarms/Events in a custom HTML dashboard?

      Hi @Nomathamsanqa-Philiso

      You can create one dashboard page for your customers and then change the datapoint permissions according to your customer points. Log into your Mango instance as an admin. I hope you have created the datasources/datapoints for your clients.

      After logging in click on the users icon. ( 3rd icon from the left ) Then you have opened this: 0_1477064859909_upload-020c9a15-2a69-40db-b771-5e4393ac6227

      On the Edit user dropdown list you have an icon Add User. When clicked you will open up a new user details.

      Edit the Username, password, e-mail etc... Set the home URL as the link to the custom dashboard page. Change the permissions to some keyword which Mango uses to link the datapoints according to the user. e.g "Client1" or "Client2" etc... so that you will remember that the user permissions are linked that specific client. Then save the user.

      After that you have created a new user and then you can go and click on the Data point permissions where you can setup the points which the user can see. There you can filter the points by datasource name / xid etc.

      I have filtered the datasource as "Client1DataSource"

      0_1477065431591_upload-4687c80e-ae00-47c9-b360-a3dadec2bc61

      Then you can bulk apply permissions to the filtered points on the bottom of the page. I have my client setup as their permissions name "gases".

      0_1477065549962_upload-b4b4c786-9d2f-4a89-99fd-dccd86374692

      Then the client who logs into their session with the home url as the custom dashboard link can only see the points which have been assigned to them in their dashboard.

      Hope you understood the quick tutorial where I tried to explain the basics of the permissions. But I strongly suggest you take a look at the links which Will pointed you out in the previous post.

      Thomas,

      posted in Dashboard Designer & Custom AngularJS Pages
      ThomasEinastoT
      ThomasEinasto
    • RE: Amcharts on-init zoom

      Hi @MattFox !

      Sorry for replying so late but I went with your suggestion on doing some programming for achieving the results which I need.

      I was pleased to see your requests / posts on the forum which pointed me to right directions while customizing for new directives.

      Mainly where @jared-wiltshire said in future defining of usermodule required scripts/functions help:

      https://github.com/infiniteautomation/ma-dashboards/blob/3.3.x/UI/web/ngMango/directives/PointValueController.js

      Which helped my a lot for customizing Mangos own directives in the future as for 3.3.x all the directives and components are in AMD/Require style which usermodules use.

      If someone have not noticed then this should be number one place to go to see how @Jared-Wiltshire has done the directives. https://github.com/infiniteautomation/ma-dashboards/blob/3.3.x/UI/web/ngMango/

      I'll put out the customized directive and component if someone wants to use prezooming, start-end date of the zoom for further data analysis.

      https://pastebin.com/8h4MV8B1

      I changed the dateformats from original as ngMango own directive uses other services etc.

      Function pointValueToString was taken from https://github.com/infiniteautomation/ma-dashboards/blob/3.3.x/UI/web/ngMango/services/Util.js

      Added bindings:

      End - takes timestamp of zoom end
      hours - takes a number of hours and then uses moment for subtracting the hours from end zoom.
      selected - Object output binding

      • selected.start >> zoomed chart start date
      • selected.end >> zoomed chart end date

      Example usage:

      <my-custom-mango-chart id="8ec0e029-4b0b-4f53-aa0d-6c25b4ds22sssdsdbfa991" style="position: absolute; left: 1058px; top: 1022px; width: 798px; height: 500px;"  series-1-values="tank1Values" series-1-point="tank1" series-1-type="line" series-1-color="blue" legend="true" balloon="true" cursor-sync-id="graphs" series-1-graph-options="{id:'graph-id-2'}" end="start2.time" hours="6" options="{ zoomOutText: '',chartScrollbar:{graph:'graph-id-2' }}">
      </my-custom-mango-chart>
      

      These dates can be used as variables for ma-point-statistics directive to get current selection statistics for example.

      As Angular is still quite hard I'll keep learnin and askin. But as @Jared-Wiltshire and all of you in IAS staff are publishing all online it is relatively easier to customize and learn.

      Huge thanks and cheers!

      Thomas

      posted in How-To
      ThomasEinastoT
      ThomasEinasto
    • RE: Overrides... logo.svg troubles

      Hi @fleh

      It depends on what are you actually trying to do. In new UI it is simple. Go to Administration => UI settings and change logo source and it will be changed after you save your UI settings. Note that it should be in public folder because mango might restrict access to other parts of the system for not logged in users.

      If you want to change via overrides then you are mostly doing changes to the old UI and Mango system itself.

      posted in User help
      ThomasEinastoT
      ThomasEinasto

    Latest posts made by ThomasEinasto

    • RE: Quick View and Dialog Window Chart Freeze

      Just a bump on this thread because the problem is still relevant for 3.x versions and probably 4.x if AmCharts 3.x is used there also.

      As analyzing the problem I think the problem lies with the API updating some data where graphs gets nulled straight after Mango updates values using <ma-get-point-values>.

      For fix basically add try {}catch(e){} method on the underlying loop where the bug happens (handleCursorMove method) and this seems to help with the graph not freezing.

      Fix:

      Navigate to /mango_root/web/modules/mangoUI/web

      Open amcharts.js

      search in file for following:

      if (this.prevCursorItem != s || c != this.prevMostCloseGraph) {
      

      After this add

      try{
      

      Now search in the file for following (should be basically quite close to previous search.

      this.prevCursorItem = s
      

      Add after that following

      }catch(e){}
      

      Then save the file and update cache as amcharts is cached with a version. Now your chart should not freeze while cursor is on the chart. Basically you can do it with overrides folder also as Mango updates will probably lose the fix.

      Pretty printed whole handleCursorMove method with added fix. see Fix start and Fix end comments

      handleCursorMove: function(t) {
                          A.AmSerialChart.base.handleCursorMove.call(this, t);
                          var e = t.target
                            , i = this.categoryAxis;
                          if (t.panning)
                              this.handleCursorHide(t);
                          else if (this.chartData && !e.isHidden) {
                              var s, r = this.graphs;
                              if (r)
                                  if (s = i.xToIndex(this.rotate ? t.y : t.x),
                                  s = this.chartData[s]) {
                                      var n, a, o, c;
                                      if (e.oneBalloonOnly && e.valueBalloonsEnabled) {
                                          var h = 1 / 0;
                                          for (n = r.length - 1; 0 <= n; n--)
                                              if ((a = r[n]).balloon.enabled && a.showBalloon && !a.hidden) {
                                                  if (o = a.valueAxis.id,
                                                  o = s.axes[o].graphs[a.id],
                                                  e.showNextAvailable && isNaN(o.y) && !(o = this.getNextItem(o)))
                                                      continue;
                                                  o = o.y,
                                                  "top" == a.showBalloonAt && (o = 0),
                                                  "bottom" == a.showBalloonAt && (o = this.height);
                                                  var l = e.mouseX
                                                    , g = e.mouseY;
                                                  (o = this.rotate ? Math.abs(l - o) : Math.abs(g - o)) < h && (h = o,
                                                  c = a)
                                              }
                                          e.mostCloseGraph = c
                                      }
                                      if (this.prevCursorItem != s || c != this.prevMostCloseGraph) {
                                          /*start of fix*/
                                          try {
                                              for (h = [],
                                              n = 0; n < r.length; n++)
                                                  o = (a = r[n]).valueAxis.id,
                                                  o = s.axes[o].graphs[a.id],
                                                  e.showNextAvailable && isNaN(o.y) && !(o = this.getNextItem(o)) && a.balloon ? a.balloon.hide() : c && a != c ? (a.showGraphBalloon(o, e.pointer, !1, e.graphBulletSize, e.graphBulletAlpha),
                                                  a.balloon.hide(0)) : e.valueBalloonsEnabled ? (a.balloon.showBullet = e.bulletsEnabled,
                                                  a.balloon.bulletSize = e.bulletSize / 2,
                                                  t.hideBalloons || (a.showGraphBalloon(o, e.pointer, !1, e.graphBulletSize, e.graphBulletAlpha),
                                                  a.balloon.set && h.push({
                                                      balloon: a.balloon,
                                                      y: a.balloon.pointToY
                                                  }))) : (a.currentDataItem = o,
                                                  a.resizeBullet(o, e.graphBulletSize, e.graphBulletAlpha));
                                              e.avoidBalloonOverlapping && this.arrangeBalloons(h),
                                              this.prevCursorItem = s
                                              /*end of fix*/
                                          } catch (e) {}
                                      }
                                      this.prevMostCloseGraph = c
                                  }
                              r = A.fitToBounds(t.x, 0, e.width),
                              c = A.fitToBounds(t.y, 0, e.height),
                              i.showBalloon(r, c, e.categoryBalloonDateFormat, t.skip),
                              this.updateLegendValues()
                          }
                      },
      
      posted in User help
      ThomasEinastoT
      ThomasEinasto
    • RE: Writting to JSON store from a Global Script

      Can you show your whole method instead of the error? Cant really help otherwise. Also version of Mango would also be helpful to know as 4.x has some major changes in scripting env.

      posted in How-To
      ThomasEinastoT
      ThomasEinasto
    • RE: Getting value at specific time using metadata scripting

      Have you read https://docs-v3.mango-os.com/about-mango-java-script ?

      Look at Statistical objects section. Hint, there is a delta in statistical object.

      posted in Scripting general Discussion
      ThomasEinastoT
      ThomasEinasto
    • RE: Hiding Dashboard Elements if DataPoints are Disabled.

      @ristola said in Hiding Dashboard Elements if DataPoints are Disabled.:

      Sorry, perhaps I am not describing my intention clearly.

      Using a ma-gauge-chart.
      When disabling the datasource this is what I get.
      Instead of the red cross hatch, I am trying to make the gauge not show at all.

      In the dashboard designer under the properties, Under the Advanced CSS's display property, I can manually set to "none" and it hides it but not sure how to set it with the point.enabled flag.

      The Angular JS, the ng-hide / show causes the red cross hatch.

      Screen Shot 2021-04-03 at 2.13.57 PM.png

      When disabling the datasource this is what I get.

      That's what's wrong and why you see this like that. Disabling datasources and disabling datapoints are different methods so seeing this is actually intended. If you want it also to remove based on datasource state then do a datasource query like this

      <!-- Get our point based on xid -->
      <ma-get-point-value point-xid="dp_2323fsadilj" point="point"></ma-get-point-value>
      <!-- Get our datasource based on point datasource xid -->
      <ma-data-source-query data-sources="dataSourcesArray" query="{xid: point.dataSourceXid}" limit="10"></ma-data-source-query>
      <!-- Hide element when datasource is not enabled or point is not enabled -->
      <div ng-hide="!dataSourcesArray[0].enabled || !point.enabled">
      <span ng-bind="point.value"></span>
      </div>
      
      posted in Dashboard Designer & Custom AngularJS Pages
      ThomasEinastoT
      ThomasEinasto
    • RE: Hiding Dashboard Elements if DataPoints are Disabled.

      Not quite sure how you are implementing it right now so I guess there is something else you are not saying. You are saying that on following example which I provided this part does not disappear if you disable the datapoint?

      <div ng-show="point.enabled">
      <span ng-bind="point.value"></span>
      </div>
      
      posted in Dashboard Designer & Custom AngularJS Pages
      ThomasEinastoT
      ThomasEinasto
    • RE: Hiding Dashboard Elements if DataPoints are Disabled.

      As ng-hide and ng-show utilize boolean inputs so you can put like

      <ma-get-point-value point-xid="dp_2323fsadilj" point="point"></ma-get-point-value>
      <!-- point.enabled is boolean which can be inserted into ng-show so following div will show only when point is enabled -->
      <div ng-show="point.enabled">
      <span ng-bind="point.value"></span>
      </div>
      <!-- Following will show all keys available in point object -->
      {{point | json}}
      
      posted in Dashboard Designer & Custom AngularJS Pages
      ThomasEinastoT
      ThomasEinasto
    • RE: Hiding Dashboard Elements if DataPoints are Disabled.

      You answered your own question. Datapoint from <ma-get-point-value> has .enabled key which you can use together with ng-show to hide/show elements based on enabled configuration.

      posted in Dashboard Designer & Custom AngularJS Pages
      ThomasEinastoT
      ThomasEinasto
    • RE: Writting to JSON store from a Global Script

      Dao and serotonin stuff are Mango backend in Java. As Scripting in Mango allows users to write either in Java or Javascript you are able to initiate backend functions also easily. This in return allows users to search around IAS Github but without documentation. e.g. you can get points and set them also using Java methods if you know how to access them instead of adding points to context in the DS.

      posted in How-To
      ThomasEinastoT
      ThomasEinasto
    • RE: Writting to JSON store from a Global Script

      Hi

      I would suggest searching the forums first. There is a thread for that and an answer by @CraigWeb

      @craigweb said in Calling JSON store item in scripting datasource:

      Hi @ThomasEinasto

      Here is some extracts of a scripting data source I did recently minus the logic I did on the JSON.

      var dao = com.serotonin.m2m2.db.dao.JsonDataDao.instance;
      var objectMapper = com.serotonin.m2m2.Common.getBean(com.fasterxml.jackson.databind.ObjectMapper.class, "daoObjectMapper");
      
      var jsonDataVo = dao.getByXid('8b203a82-166a-4963-8dc5-17bba149e28b');
      var dataAsString = jsonDataVo.jsonData.toString();
      var data = JSON.parse(dataAsString);
      

      You can now edit the data object as you would normally in JS

        var newJsonData = objectMapper.readTree(JSON.stringify(data)); 
       //If objectmapper is not used before saving, all objects get saved as an array.
        jsonDataVo.setJsonData(newJsonData); 
        dao.save(jsonDataVo) 
      

      To save back to the JSON store.

      posted in How-To
      ThomasEinastoT
      ThomasEinasto
    • RE: Data Point different logging then configuration

      Interestingly i have just tested it out and it seems that there is some kind of a rounding thing coming up with values being exactly the threshold value. If value changes next fraction of the threshold then this does not happen.

      A quick test

      Create a virtual point with exact settings

      Current value 1
      Set point to 1.01
      No logging
      Set point back to 1.0
      Set point to 1.011
      Logging appears

      If going to other way around

      Current value 1.01
      Set point to 1.00
      Logging appears

      I am guessing datalogging does not happen if new value is greater than current value in the defined threshold but if new value is lower then current value in the defined threshold then logging works correctly.

      I might also fish out an idea that @Nurr polling time is related to the issue (I guess it might be once per minute?) where the cached value is the new over threshold limit but it does not get logged but still triggers a reset for interval logging and then it has been the same for 5 minutes and then it gets logged by the interval logging sequence.

      But still even though this happens, interval logging still works in my instance so I guess this information is not actually so relevant.

      posted in User help
      ThomasEinastoT
      ThomasEinasto