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

    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

    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
    • RE: Difference between MangoES and MangoHTS

      I would also be interested for more information in the GT version of ES.

      posted in Hardware
      ThomasEinastoT
      ThomasEinasto
    • RE: Suspected hardware failure

      @MattFox I was hesitant to give my 2 cents about this but we also have been come into contact with this issue where eMMC drive has become corrupted.

      posted in MangoES Hardware
      ThomasEinastoT
      ThomasEinasto
    • RE: Script to convert from Hex to Dec

      @jorge-gonzalez said in Script to convert from Hex to Dec:

      13:32

      @Jorge-Gonzalez, documentation to solve your problems.

      Firstly see what parseInt does - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt

      There you can see that the hexdecimal value has to be in correct format be it with 0x or without. Your string splits 2 bytes in the hexdecimal format by using a colon. You need to remove it. Simply do it by utilizing .replace method on a string before putting it into parseInt. Or if you have a string which contains multiple values utilize .split method on a string and then put the bytes together before putting the value into parseInt.

      Replace method explanation
      https://www.w3schools.com/jsref/jsref_replace.asp

      Split method explanation
      https://www.w3schools.com/jsref/jsref_split.asp

      Following function is following the detailed explanation you provided in the post.

      function stringsplitter (string) {
      
      var result = {};
      
      // This contains the bytes of data
      result.arrayofbytes = string.split(':');
      
      // Get byte count of data inside the string
      result.bytecount = result.arrayofbytes.length;
      
      // Start at the beginning
      var variablecounter = 0;
      
      result.hexdata = [];
      result.decimaldata = [];
      
      // Loop over the array, but taking into account that we have 2 byte data, use try/catch so that function will return if something should fail
      try{
      for (var x = 0;x < result.bytecount / 2;x++){
       
      result.hexdata[x] = result.arrayofbytes[variablecounter] + result.arrayofbytes[variablecounter+1];
      result.decimaldata[x] = parseInt(result.hexdata[x],16);
      variablecounter += 2;
      
      }
      }catch(err){
       return err
      }
      
      
      
      
      // return object with all our data which includes hexdecimal data, decimaldata and byte count inside the string
      return result;
      
      }
      
      // Example usage
      
      var devicestring = '13:30:27:14:01:33:02:6c:02:76';
      
      var data = stringsplitter(devicestring);
      
      //get array in hexdecimal and decimal format
      var hexdata = data.hexdata;
      var decimaldata = data.decimaldata;
      
      // first value in hexdecimal and decimal format
      var firstvaluehex = hexdata[0];
      var firstvaluedecimal = decimaldata[0];
      
      // Second value in hexdecimal and decimal format
      var secondvaluehex = hexdata[1];
      var secondvaluedecimal = decimaldata[1];
      
      // Following that your post had used an example with the last value
      
      var lastvalue = decimaldata[4];
      
      // Should be 23
      var lastvaluecorrected = lastvalue * 0.1 - 40;
      
      

      Thomas

      posted in How-To
      ThomasEinastoT
      ThomasEinasto
    • RE: Calculation using ^ (to the power of) in a Meta Data Point

      @steve-o said in Calculation using ^ (to the power of) in a Meta Data Point:

      (610.7*10^((7.5x23)/(237.3+23))/1000)

      Steve, what is your temp variable? Is it the name of your variable? Then you should use this:

      (610.7*Math.pow(10,((7.5*temp.value))/(237.3+23))/1000) 
      

      Following works as it should on math pow

      (610.7*Math.pow(10,((7.5*23))/(237.3+23))/1000) 
      // returns 2.808825816730143
      
      posted in User help
      ThomasEinastoT
      ThomasEinasto
    • RE: Why this kind of <style> can not work?

      @jared-wiltshire said in Why this kind of <style> can not work?:

      @Zhilin-Chen
      Open up the Chrome debugger (Right click, inspect element) and confirm that

      • The classes are being applied to the element(s) you are trying to target
      • The styles from the class are not being overridden by a higher priority rule or inline style

      @Jared-Wiltshire So basically adding !important to style solves it right?

      @Zhilin-Chen, Following solves this by @Jared-Wiltshire explanations.

      <style>
      .grey-fill {
      fill: grey !important;
      }
      .red-fill {
      fill: red  !important;
      }
      .blue-fill {
      fill: blue  !important;
      }
      .green-fill {
      fill: green  !important;
      }
      </style>
      
      <div class="ma-designer-root" id="445b6000b-362e-407f-aa27-05545fea5884" style="width: inherit; height: inherit; position: relative; bottom: inherit; left: inherit;">
      <ma-svg ng-include="'/rest/v2/file-stores/default/sss/demo.svg'">
      <div ma-selector="#t1" ng-class="{'grey-fill': (v342.value < 0.94) || (v342.value > 1.06), 'red-fill':(v342.value >= 0.94 &amp;&amp; v342.value < 0.95) , 'blue-fill': (v342.value <= 1.06 &amp;&amp; v342.value > 1.05), 'green-fill': (v342.value >= 0.95) &amp;&amp; (v342.value <= 1.05)}">
      </div>
      </ma-svg>
      <ma-get-point-value point-xid="demo1" point="v342"></ma-get-point-value>
      </div>
      
      posted in User help
      ThomasEinastoT
      ThomasEinasto
    • RE: Why this kind of <style> can not work?

      @zhilin-chen said in Why this kind of <style> can not work?:

      Hi, Thomas and Jared

      Thank you so much!! You guys are so quick! However, That is not what I mean. What I mean is that the style statement still does not work with your code. Other kinds of style such as something with animation could work with this condition. But this colour-fill one could not. Quite confusing though. Sorry still new in Mango.

      eg. below

      <div class="ma-designer-root" id="a7f018fd-f4bf-469e-bec7-1282ad4606bc" style="width: 1366px; height: 768px; position: relative;"></div>
      <style>
      .grey-fill {
      fill: grey;
      }
      .red-fill {
      fill: red;
      }
      .blue-fill {
      fill: blue;
      }
      .green-fill {
      fill: green;
      }
      </style>
      
      <div class="ma-designer-root" id="445b6000b-362e-407f-aa27-05545fea5884" style="width: inherit; height: inherit; position: relative; bottom: inherit; left: inherit;">
      <ma-svg ng-include="'/rest/v2/file-stores/default/sss/demo.svg'">
      <div ma-selector="#t1" ng-class="{'grey-fill': (v342.value < 0.94) || (v342.value > 1.06), 'red-fill':(v342.value >= 0.94 &amp;&amp; v342.value < 0.95) , 'blue-fill': (v342.value <= 1.06 &amp;&amp; v342.value > 1.05), 'green-fill': (v342.value >= 0.95) &amp;&amp; (v342.value <= 1.05)}">
      </div>
      </ma-svg>
      <ma-get-point-value point-xid="demo1" point="v342"></ma-get-point-value>
      </div>
      

      Actually I tested my code out and you are right that ng-class fails but ng-style does not.

      One way you could achieve your result is following:

      <div class="ma-designer-root" id="445b6000b-362e-407f-aa27-05545fea5884" style="width: inherit; height: inherit; position: relative; bottom: inherit; left: inherit;">
      
      <ma-svg ng-include="'/rest/v2/file-stores/default/sss/demo.svg'">
      
      <div ma-selector="#t1" 
      ng-style="{'fill': (v342.value < 0.94) || (v342.value > 1.06) ? 'gray' : (v342.value >= 0.94 && v342.value < 0.95) ? 'red' : (v342.value <= 1.06 && v342.value > 1.05) ? 'blue' : (v342.value >= 0.95) && (v342.value <= 1.05) ? 'green' : 'default' }"
      >
      </div>
      </ma-svg>
      <ma-get-point-value point-xid="demo1" point="v342"></ma-get-point-value>
      </div>
      

      This is ng-style which is the same equivalent as:

      if (condition1){
      
      fill:gray
      
      }else{
      
      if (condition3){
      
      fill:red
      
      }else{
      
      if (condition3){
      
      fill:blue
      
      }else{
      
      if (condition4){
      
      fill:green
      
      }else{
      
      fill:default
      
      }
      
      }
      
      }
      
      }
      
      posted in User help
      ThomasEinastoT
      ThomasEinasto
    • RE: Why this kind of <style> can not work?

      This is because you have no variable assigned to ng-class and currently you probably have multiple same conditions on multiple classes. i.e 'red-fill', 'blue-fill and 'green-fill' are assigned currently as 0?.

      Correct way would be something like this:

      <style>
      .grey-fill {
      fill: grey;
      }
      .red-fill {
      fill: red;
      }
      .blue-fill {
      fill: blue;
      }
      .green-fill {
      fill: green;
      }
      </style>
      
      <div class="ma-designer-root" id="445b6000b-362e-407f-aa27-05545fea5884" style="width: inherit; height: inherit; position: relative; bottom: inherit; left: inherit;">
      <ma-svg ng-include="'/rest/v2/file-stores/default/sss/demo.svg'">
      <div ma-selector="#t1" ng-class="{'grey-fill': point.value == 1, 'red-fill': point.value == 2, 'blue-fill': point.value == 3, 'green-fill': point.value == 4}"></div>
      </ma-svg>
      </div>
      

      See /ui/examples/basics/style-via-value for a correct example on how to use ng-class or https://docs.angularjs.org/api/ng/directive/ngClass

      posted in User help
      ThomasEinastoT
      ThomasEinasto
    • RE: ng-init for date.to and date.from

      Hi @Phillip-Weeks ,

      One can create a new usermodule component to handle like ng-init.

      userModule.component('gettime', {
          bindings:{
              timestampIn: '@?',
              tsFormat: '@?',
              newDateo: '=?',
              newDates: '=?'
          },
          controller:['$scope',
              function($scope){
      
                  $scope.$watch('$ctrl.timestampIn', () => {
      
                      let dateobject = moment(this.timestampIn);
                      
                      let datestring = moment(this.timestampIn).format(this.tsFormat);
                      
                      if (typeof this.timestampIn !== "undefined"){
                          
                              this.newDateo = dateobject;
                              this.newDates = datestring;
                              
                              //console.log(typeof(this.newDateo)); << returns dateobject
                              //console.log(typeof(this.newDates)); << returns string
                      }
                      
                  }, true);
              
              
          }]
          
      });
      
      

      new-dateo is date object which you should be able to use as your date.from / date.to variable.
      new-dates is date string which is formatted like you want based on momentjs format function.

      Usage in dashboard:

      <gettime timestamp-in="10/05/2019 22:10:10" ts-format="DD/MM/YYYY HH:mm:ss" new-dateo="js" new-dates="jss"></gettime>
      
      {{js}}
      <br>
      {{jss}}
      

      Result in dashboard:

      Sat Oct 05 2019 22:10:10 GMT+0300
      05/10/2019 22:10:10
      
      posted in Dashboard Designer & Custom AngularJS Pages
      ThomasEinastoT
      ThomasEinasto
    • RE: Modbus TCP write or settable

      @ORU_david To put 74 ° you should probably write 740 but I am not sure if the value put into the modbus request is actually a 2 byte integer or a floating point,

      i.e does Mango parseInt the value after multiplier + additive before putting it into the modbus request or not..

      IAS staff could be of more help on that.

      posted in How-To
      ThomasEinastoT
      ThomasEinasto
    • RE: Modbus TCP write or settable

      If we are talking about MC6 Test Stat: MC6 Stat - Space temp point then following is related.

      Transcript from modbus documentation:
      See here for more info: http://www.simplymodbus.ca/exceptions.htm
      03 (03 hex) Illegal Data Value
      A value contained in the query data field is not an allowable value for the slave. This indicates a fault in the structure of remainder of a complex request, such as that the implied length is incorrect. It specifically does NOT mean that a data item submitted for storage in a register has a value outside the expectation of the application program, since the MODBUS protocol is unaware of the significance of any particular value of any particular register.

      Please see that your multiplier and additive is actually as it should. Device responds to mango that the value you want to write is not allowed.

      Edit: I looked at your previous point and it seems that we are actually talking about the same point. If you click on info icon on the datapoint edit page you can see documentation related to multiplier and additive.

      The Multiplier and Additive fields can be used when trivial value conversions are required. Numeric values read from the network are calculated as follows: (raw value) * multiplier + additive. The reverse is applied when a numeric value is written to the network.

      So generally speaking. You have to consider the multiplier you set to the point and also modbus 2 byte integers take integer values not floating values.

      posted in How-To
      ThomasEinastoT
      ThomasEinasto