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.

  • This topic is deleted!

    1
    0 Votes
    1 Posts
    4 Views
    No one has replied
  • Virtual Data Source to store plant name

    4
    0 Votes
    4 Posts
    2k Views
    phildunlapP
    Certainly! You may still be able to mitigate this by lowering the max open files in your Mango/overrides/properties/env.properties file. In specific, the #Set the number of files the database can have open at one time db.nosql.maxOpenFiles=500 property. The comment is somewhat misleading, what this number really means is the maximum number of output streams that can be held open. Setting this to 0 would tell the database to always close files after every write, which would encourage flushing to disk (I believe MAPPED_BYTE_BUFFER streams may not be flushed until a subsequent garbage collection) The downside would be that buffering is done for a reason, which is efficiency, especially when points are receiving fairly rapid writes. So, performance can be affected.
  • Database Reporting

    3
    0 Votes
    3 Posts
    1k Views
    phildunlapP
    Hi Brad_GMI, Fox's suggestion of the API is the right one. Without knowing any idiosyncrasies of how you need the data exposed it is difficult to make a definite recommendation other than the API as that is definitely part of its purpose.
  • A global way to define colors for AMCharts

    13
    0 Votes
    13 Posts
    4k Views
    MattFoxM
    OK! As promised, here we are. I'm using 3.5.6 so I'm not entirely certain how well this will work. I've stuck to mango components to the best of my ability to allow the best compatibility sans the colour picker. If it doesn't work you may need to alter the HTML to use <ma-color-picker instead. You'll need to set up a userModule file to incorporate this. I've saved my files in /opt/mango/overrides/web/modules/mangoUI/web/dev/directives/chartProfile the userModule.js is in /opt/mango/overrides/web/modules/mangoUI/web/dev For the mangoUI settings, the url for the userModule.js file is: /modules/mangoUI/web/dev/userModule.js The user module file contains this: define(['angular', 'require','./directives/chartProfile/serialChartProfile.js'],function(angular, require,serialChartProfile) { 'use strict'; var userModule = angular.module('userModule', ['maUiApp']); try { userModule.directive('serialChartProfile', serialChartProfile); }catch(e){console.log(e);} return userModule; });//define serialChartProfile.js /* Date: 13/8/19 File:serialChartProfile.js Author: Matt 'Fox' Fox Desc: Directive that allows mangoUI users to create chart profiles for their dashboard pages. Name of the JSON store can be set as well as the names of each of the chart profiles. Credit goes to Will Geller and Jared Wiltshire for original codebase */ define(['angular', 'require'],function(angular, require) { 'use strict'; serialChartProfile.$inject = ['maJsonStore','$mdDialog','$mdColorPicker','$mdToast']; function serialChartProfile( JsonStore, $mdDialog, $mdColorPicker,$mdToast ) { console.log($mdColorPicker); var scope = { jsonStore: '<?',//has default option }; return { restrict: 'E', templateUrl:'/modules/mangoUI/web/dev/directives/chartProfile/chartProfile.html', designerInfo: { translation: 'ui.components.serialChartProfile', icon: 'show_chart', category: 'pointValuesAndCharts', attributes: { jsonStore: {type: 'text'} }, }, scope: scope, compile: function() { return linkFn; } }; function linkFn(scope, $element, attrs) { scope.profileStore={}; /* Default for ensuring we have a json store name */ var hasStoreName = !!attrs.jsonStore; if(!hasStoreName) { scope.jsonStore = "chartProfile1"; getChartProfiles(); } else { if( scope.jsonStore.length < 3 ) { scope.jsonStore = "chartProfile1"; getChartProfiles(); } else { getChartProfiles();} } scope.axisOptions = [ {name: 'left', translation: 'ui.app.left'}, {name: 'right', translation: 'ui.app.right'}, {name: 'left-2', translation: 'ui.app.farLeft'}, {name: 'right-2', translation: 'ui.app.farRight'} ]; function getChartProfiles() { JsonStore.get({ xid: scope.jsonStore }).$promise.then(function (item) { scope.profileStore = item.jsonData; scope.chartProfile = Object.keys(scope.profileStore)[0]; }, function () { //create prompt - no data scope.createProfile(); }).then(function() { }); } scope.saveToStore=function() { var item = new JsonStore(); item.jsonData = scope.profileStore; item.xid = scope.jsonStore; item.name = scope.jsonStore; item.readPermission = "user"; item.editPermission = "user"; var r = item.$save(); r.then(function(){$mdToast.show( $mdToast.simple() .textContent("Chart Profiles Saved") .position("top") .hideDelay(3000)); }, function myError(response) { console.log( response.statusText ); $mdToast.show( $mdToast.simple() .textContent(response.data) .position("top") .hideDelay(3000)); }); if (r.status) {} else {} }; scope.showColorPicker = function($event, object, propertyName, rebuild) { if (!object) return; this.$mdColorPicker.show({ value: object[propertyName] || tinycolor.random().toHexString(), defaultValue: '', random: false, clickOutsideToClose: true, hasBackdrop: true, skipHide: false, preserveScope: false, mdColorAlphaChannel: true, mdColorSpectrum: true, mdColorSliders: false, mdColorGenericPalette: true, mdColorMaterialPalette: false, mdColorHistory: false, mdColorDefaultTab: 0, $event: $event }).then(color => { object[propertyName] = color; }); }; scope.createProfile = function(ev) { // Appending dialog to document.body to cover sidenav in docs app var confirm = $mdDialog.prompt() .title('Create New Chart Profile') .textContent('Enter new profile name:') .placeholder('PowerUsage') .ariaLabel('PowerUsage') .initialValue('chartProfile1') .targetEvent(ev) .required(true) .ok('CREATE') .cancel('CANCEL'); $mdDialog.show(confirm).then(function(result) { scope.profileStore[ result ] = {}; scope.chartProfile = result; }, function() { //Do nothing and hide. }); }; scope.deleteProfile = function(ev) { // Appending dialog to document.body to cover sidenav in docs app var confirm = $mdDialog.confirm() .title('Delete Profile') .textContent('Are you sure you want to delete this profile?') .ariaLabel('Delete Chart Profile') .targetEvent(ev) .ok('Confirm Delete') .cancel('Cancel'); $mdDialog.show(confirm).then(function() { delete(scope.profileStore[scope.chartProfile]); scope.status = 'Profile Deleted, save settings to confirm'; }, function() { $scope.status = 'Operation cancelled'; }); }; } } return serialChartProfile; });//define chartProfile.html <main> <!-- <ma-json-store xid="jsonStore" name="jsonStore"></ma-json-store> --> <ma-button ng-click="createProfile()" label="Create Profile"></ma-button> <ma-button ng-click="saveToStore()" label="Save All Profiles"></ma-button> <ma-button ng-click="deleteProfile()" label="Delete Selected Profile"></ma-button> <md-select ng-model="chartProfile"> <md-option ng-repeat="(profile,vals) in profileStore" value="{{profile}}">{{profile}}</md-option> </md-select> <div class="md-padding"> <div ng-if="chartProfile.length>3"> <md-checkbox ng-model="profileStore[chartProfile].enabled.series1"><span>Configure Series 1:</span></md-checkbox> <md-checkbox ng-model="profileStore[chartProfile].enabled.series2"><span>Configure Series 2:</span></md-checkbox> <md-checkbox ng-model="profileStore[chartProfile].enabled.series3"><span>Configure Series 3:</span></md-checkbox> <md-checkbox ng-model="profileStore[chartProfile].enabled.series4"><span>Configure Series 4:</span></md-checkbox> <md-checkbox ng-model="profileStore[chartProfile].enabled.series5"><span>Configure Series 5:</span></md-checkbox> <md-checkbox ng-model="profileStore[chartProfile].enabled.series6"><span>Configure Series 6:</span></md-checkbox> <md-checkbox ng-model="profileStore[chartProfile].enabled.series7"><span>Configure Series 7:</span></md-checkbox> <md-checkbox ng-model="profileStore[chartProfile].enabled.series8"><span>Configure Series 8:</span></md-checkbox> <md-checkbox ng-model="profileStore[chartProfile].enabled.series9"><span>Configure Series 9:</span></md-checkbox> <md-checkbox ng-model="profileStore[chartProfile].enabled.series10"><span>Configure Series 10:</span></md-checkbox> {{chartProfile.enabled}} <div layout layout-align="start center" layout-wrap ng-repeat="(key,val) in profileStore[chartProfile].enabled" ng-if="val"> <strong flex="100" flex-gt-xs="30" flex-gt-md="15">Configure {{key}}</strong> <md-input-container flex> <label ma-tr="ui.app.lineColor"></label> <md-color-picker ng-model="profileStore[chartProfile][key].pointColor"></md-color-picker> </md-input-container> <!-- <md-input-container flex> <label ma-tr="ui.app.lineColor"></label> <input ng-model="profileStore[chartProfile][key].pointColor" ng-model-options="{debounce: 1000}"> </md-input-container> --> <md-input-container flex> <label ma-tr="ui.app.chartType"></label> <md-select ng-model="profileStore[chartProfile][key].type"> <md-option value=""><em ma-tr="ui.app.clear"></em></md-option> <md-option value="smoothedLine" ma-tr="ui.app.smooth"></md-option> <md-option value="line" ma-tr="ui.app.line"></md-option> <md-option value="step" ma-tr="ui.app.step"></md-option> <md-option value="column" ma-tr="ui.app.bar"></md-option> </md-select> </md-input-container> <md-input-container flex> <label ma-tr="ui.app.pointAxis"></label> <md-select ng-model="profileStore[chartProfile][key].axis"> <md-option value=""><em ma-tr="ui.app.clear"></em></md-option> <md-option ng-repeat="axis in axisOptions track by axis.name" ng-value="axis.name"> <span ma-tr="{{axis.translation}}"></span> </md-option> </md-select> </md-input-container> </div> <div> <md-checkbox ng-model="profileStore[chartProfile].configAxes"><span ma-tr="ui.app.configureAxes"></span></md-checkbox> </div> <div ng-if="profileStore[chartProfile].configAxes" ng-repeat="axis in axisOptions track by axis.name" layout="row" layout-align="start center" layout-wrap> <strong flex="100" flex-gt-xs="15" flex-gt-md="10" ma-tr="{{axis.translation}}"></strong> <div flex="100" flex-gt-xs="85" flex-gt-md="90" layout layout-align="start center" layout-wrap> <md-input-container flex="50" flex-gt-xs="33"> <label ma-tr="ui.app.axisTitle"></label> <input ma-empty-input="undefined" ng-model="profileStore[chartProfile].valueAxes[axis.name].title" ng-model-options="{debounce: 1000}" > </md-input-container> <div flex="50" flex-gt-xs="33" layout layout-align="start center"> <label ma-tr="ui.app.axisColor"></label> <md-color-picker ng-model="profileStore[chartProfile].valueAxes[axis.name].color" ></md-color-picker> <!-- <ma-color-picker ng-model="profileStore[chartProfile].valueAxes[axis.name].color" ></ma-color-picker> --> <!-- <md-input-container flex> <label ma-tr="ui.app.axisColor"></label> <input ma-empty-input="undefined" ng-model="profileStore[chartProfile].valueAxes[axis.name].color" ng-model-options="{debounce: 1000}" > </md-input-container> --> </div> <md-input-container flex="50" flex-gt-xs="33"> <label ma-tr="ui.app.stackType"></label> <md-select ma-empty-input="undefined" ng-model="profileStore[chartProfile].valueAxes[axis.name].stackType" > <md-option value=""><em ma-tr="ui.app.clear"></em></md-option> <md-option value="none" ma-tr="ui.app.none"></md-option> <md-option value="regular" ma-tr="ui.app.stacked"></md-option> <md-option value="100%">100% <span ma-tr="ui.app.stacked"></span></md-option> </md-select> </md-input-container> <md-input-container flex="50" flex-gt-xs="33"> <label ma-tr="ui.app.axisMinimum"></label> <input ma-empty-input="undefined" type="number" ng-model="profileStore[chartProfile].valueAxes[axis.name].minimum" ng-model-options="{debounce: 1000}" > </md-input-container> <md-input-container flex="50" flex-gt-xs="33"> <label ma-tr="ui.app.axisMaximum"></label> <input ma-empty-input="undefined" type="number" ng-model="profileStore[chartProfile].valueAxes[axis.name].maximum" ng-model-options="{debounce: 1000}" > </md-input-container> <md-input-container flex="50" flex-gt-xs="33"> <label ma-tr="ui.app.axisGridCount"></label> <input ma-empty-input="undefined" type="number" min="0" ng-model="profileStore[chartProfile].valueAxes[axis.name].gridCount" ng-model-options="{debounce: 1000}" > </md-input-container> </div> </div> </div> <style> .md-color-picker-input{color:black!important;}</style> </main> <!-- json-store is optional; --> <serial-chart-profile [json-store='jsonStoreName'] ></serial-chart-profile> Keep me informed, hopefully others can use this to make their chart templates for different statuses more dynamically!! I won't lie, this may require further testing... and more comments! Fox
  • Times series database storage format, point arrays, and downsampling

    3
    0 Votes
    3 Posts
    2k Views
    P
    @phildunlap said in Times series database storage format, point arrays, and downsampling: quite a lot going on there! Yes, I was considering whether to split my post into different topics. Thank you for all your answers. The POST /rest/v2/script/ run allows you to submit a script and get the results of its run. That sounds very interesting. I just completed a python script using XSRF token. Nice: I like how it eliminated the need to login. One could easily downsample their data via script, which I can provide a simple or efficient example of if desired. If you already have an existing script, it would be nice if you could post it under its own forum topic, as I'm sure many of us would like to downsample old data. In addition to downsampling old data, I have numerous points that were logged much too often due to initially setting a log tolerance threshold that was too small. However, I won't have time to run this script right away due to my other project. there is no data type that is "array of data type: numeric" and handled in Mango as such. You understood me correctly. I'm looking to store an array of readings (as in multiple channels for each timestamp). Basically, a 2D numerical array where the rows are for different timestamps and the columns are the same type of data type but from different sources (channels). If it were stored in a CSV or spreadsheet, it would look like this: timestamp t+0, channel[1],channel[2],channel[3],channel[4],channel[5],...,channel[1000] timestamp t+1, channel[1],channel[2],channel[3],channel[4],channel[5],...,channel[1000] timestamp t+2, channel[1],channel[2],channel[3],channel[4],channel[5],...,channel[1000] timestamp t+3, channel[1],channel[2],channel[3],channel[4],channel[5],...,channel[1000] timestamp t+4, channel[1],channel[2],channel[3],channel[4],channel[5],...,channel[1000] ... It seems to me that in order to reduce data redundancy (by not storing the same timestamp multiple times) I could store the data in HDF5 format. HDF5 includes the metadata for the stored information, so the data can be retrieved into a meaningful format using generic tools, even without the source code that stored it. Additionally, it can efficiently compress and decompress binary data such as numerical arrays. My array elements could be any number of bytes. HDF5 is also extremely fast. Summary Points - Benefits of HDF5 Self-Describing The datasets with an HDF5 file are self describing. This allows us to efficiently extract metadata without needing an additional metadata document. Supports Heterogeneous Data: Different types of datasets can be contained within one HDF5 file. Supports Large, Complex Data: HDF5 is a compressed format that is designed to support large, heterogeneous, and complex datasets. Supports Data Slicing: "Data slicing", or extracting portions of the dataset as needed for analysis, means large files don't need to be completely read into the computers memory or RAM. Open Format - wide support in the many tools: Because the HDF5 format is open, it is supported by a host of programming languages and tools, including open source languages like R and Python and open GIS tools like QGIS. I also found TsTables, a PyTables wrapper that will enable storing time stamped arrays into HDF5 files in daily shards and seamlessly stitch them together during queries. Appends are also efficient. The HDF5 tools will also help for debugging whether any inconsistency is occurring during the read or write operation.
  • Time RegEx

    8
    0 Votes
    8 Posts
    3k Views
    phildunlapP
    This is probably only a display issue. I would guess above that on the page it is showing the value for hour 23 as the current value, and that if you chart it for the day you will see the values in the chart. Thanks for bringing this to our attention!
  • Bad file descriptor?

    3
    0 Votes
    3 Posts
    2k Views
    P
    Mango is on the same LAN with the Modbus IP devices. I was using TCP, and have switched to TCP with keepalive to see if that helps.
  • Tab Navigation with dynamic pages

    11
    0 Votes
    11 Posts
    3k Views
    J
    @craigweb You are right! Thanks!
  • Password reset email

    5
    0 Votes
    5 Posts
    2k Views
    A
    Thank you..
  • Bug in script editor?

    6
    0 Votes
    6 Posts
    2k Views
    P
    The new data source UI doesn't seem to have the bug. Thanks!
  • LDAP for authentication

    3
    0 Votes
    3 Posts
    2k Views
    phildunlapP
    I do not believe it is possible. I think that may be somewhat under the scope of this git issue: https://github.com/infiniteautomation/ma-core-public/issues/1352
  • SQL Datasources not querying H2 in 3.6

    2
    0 Votes
    2 Posts
    1k Views
    phildunlapP
    Hi Ava, This is almost certainly caused by the name of the H2 database file changing to include the version of H2 in the filename. This was in the course of upgrading H2 from 196 to 199 which required doing a dump and restore. The advantage of using the newer version is that the LOB expansion that caused countless Mango users to shrink their H2 databases manually and in some cases regularly has been fixed. Currently the version is 199, so the filename is mah2-199.h2.db now. This means the connection URL needs to be modified to: jdbc:h2:/opt/mango/databases/mah2.199 I think given this it would probably be in the module's interest to add a way to say it's this Mango's database, to avoid this issue if we update H2 again / it requires an actual upgrade path like 196 to 199 did. Thanks for bringing this to our attention!
  • Data Source management permission can't enable datasources

    5
    0 Votes
    5 Posts
    2k Views
    A
    Oh yes, now I see that the problem happens only in the legacy UI, in the new datasource page UI, the feature is working properly!
  • Questions about point-values endpoint

    8
    0 Votes
    8 Posts
    3k Views
    J
    @jared-wiltshire said in Questions about point-values endpoint: /rest/v2/point-values/time-period/ Ok, thank you!!! I had not take a look to this endpoint before. It is good to know this variant of the request.
  • Mango 3.5.6 Crashing on ES

    9
    0 Votes
    9 Posts
    3k Views
    S
    I switched back to java se. I was able to get version 1.8.0 212-b10 installed. Hopefully this will be the fix.
  • Mango Speed up on Raspberry

    5
    0 Votes
    5 Posts
    2k Views
    phildunlapP
    Maybe I've to create a chron script that daily rsync backup directory on a remote server. Yes, that's a good way to do it.
  • Event WebSocket by query

    3
    0 Votes
    3 Posts
    1k Views
    J
    Ok, good idea. Thank you!!!
  • Compression during Mango boot

    2
    0 Votes
    2 Posts
    973 Views
    phildunlapP
    Hi etantonio, The logs you've shown span eight seconds and show that your publisher was running with debug logging on. I do not know what you're asking about as far as speeding things up, or the normality of it. All the log shows are a few packets being sent every second. If those messages are in the ma.log file, you can decrease the log settings in your Mango/classes/log4j2.xml or Mango/overrides/classes/log4j2.xml file that pertain to the package (which would lead me to believe you may have switched to the debug-log4j2.xml since these messages aren't in the default configuration). Otherwise, I suspect this is from the publisher log, and then your publisher is set to log debug messages in its publisher settings.
  • Heat map

    7
    1 Votes
    7 Posts
    3k Views
    Jared WiltshireJ
    @petermcs There is a component in Mango 3.6 to display heat maps like this (they rendered as a SVG in Mango) It is also customizable (color scale, legend position, number of weeks etc) [image: 9tsves2.png]
  • SSH datasource Auth fail

    3
    0 Votes
    3 Posts
    2k Views
    E
    Thanks, naturally you're right!