• Jared Wiltshire

    @wingnut2-0 said in Heartbeat for Cloud Connect Clients:

    The goal is to monitor the status of cloud connect clients via the cloud connect server and alert/generate an event if a client becomes unresponsive.

    We could probably add some events to the Cloud Connect module for this purpose. On both the client and the server. Good idea!

    @wingnut2-0 said in Heartbeat for Cloud Connect Clients:

    Would/Can this be done by creating points on the clients and publish to the server?

    I assume you are talking about the Persistent TCP publisher/data source? This does not currently operate through the Cloud Connect module so it wont tell you anything about the status of the Cloud Connect tunnel. We definitely have it in our plans to allow it to tunnel through the CC module. Stay posted.

    posted in User help read more
  • Jared Wiltshire

    @gordoe said in Values not showing up in v3 pages but will in v2:

    /rest/v2/data-points/DP_Site99_CB2-breakerStatus:1 Failed to load resource: the server responded with a status of 404 (Not Found)

    This indicates that the data point with XID DP_Site99_CB2-breakerStatus doesn't exist but that doesn't seem to be the data point you are looking at.

    @gordoe said in Values not showing up in v3 pages but will in v2:

    The server is running with a dual nic. Think that might have an impact?

    Not unless your routing is setup incorrectly.

    @gordoe said in Values not showing up in v3 pages but will in v2:

    WebSocket connection to 'ws://172.30.0.5/rest/v1/websocket/json-data' failed: Error during WebSocket handshake: net::ERR_CONNECTION_RESET

    WebSocket issues normally indicate that there is a transparent proxy between the client and the server. We always recommend to use HTTPS for security and reliability of WebSocket connections.

    The old UI pages use a long polling technique not WebSockets so this does not affect them.

    posted in User help read more
  • Jared Wiltshire

    @davide27 said in DataPoint values into a var javascript:

    I need to download a csv file with the values ​​of multiple data points, but not all values ​​have the same timestamp. For this reason, I would like to have the values in a variable so I can process it and write it all in one line.

    Please have a play with the CSV download from the watch list. Try it with different rollup options and see if you can get something that works for you. If this suffices I can give you an example of a new URL you can use in the example I posted above.

    The reason I am suggesting this is because it will be easier for you, I have given you suggestions on how to proceed if you really want to process the values using JavaScript but you haven't given me any indication that you have looked at the documentation I referenced.

    posted in How-To read more
  • Jared Wiltshire

    There are no options for password complexity yet, we have added support for it in the back-end but it is not configurable yet. Next release should have some options for it.

    posted in Mango Automation general Discussion read more
  • Jared Wiltshire

    Since you did not provide any sort of logs, screenshots or metrics I cannot really comment. I would suggest looking at the network tab of the chrome debugger (ensure that "Disable cache" is not checked).

    The first load after upgrading a module will take longer as it has to fetch the new versions of resources. After that it should be cached.

    posted in User help read more
  • Jared Wiltshire

    You can add &dateTimeFormat=yyyy-MM-dd%20HH%3Amm%3Ass.SSS to the end of the URL to change the date encoding to a Excel compatible format.

    edit.
    Also, you can write a user module that loads point values using the maPointValues service and do whatever you please. Reference the thread that @MattFox linked to above for inspiration. Also search the help site and forum, there are lots of threads about user modules / components.

    posted in How-To read more
  • Jared Wiltshire

    Here's an example, you can download CSV straight from the REST API

    <ma-watch-list-get ng-model="designer.watchList" parameters="designer.parameters" on-points-change="designer.points = $points" id="29305bf3-cc2a-4bac-9650-3cbf64d738a9" watch-list-xid="WL_Flow"></ma-watch-list-get>
    <div class="ma-designer-root" id="1a2a6980-f5bb-4acc-a41a-f8f69d5c12d2" style="width: 1366px; height: 768px; position: relative;">
    
        <ma-calc input="designer.points | filter:{name:'Flow'}:true | maFirst" output="point"></ma-calc>
        
        <md-button id="2585b1fa-a630-4255-8670-41884b8754e2" style="position: absolute; left: 260px; top: 70px;" class="md-raised" ng-href="/rest/v2/point-values/time-period/{{point.xid}}?fields=TIMESTAMP&fields=VALUE&fields=ANNOTATION&from={{dateBar.from.toISOString()}}&to={{dateBar.to.toISOString()}}&format=csv2" download="{{point.name}}.csv">Download values</md-button>
    </div>
    

    posted in How-To read more
  • Jared Wiltshire

    Personally, I would create a little dashboard to do what you need to do in his browser, you wouldn't need to upload the file to Mango at all. There's obviously a lot of ways to skin this cat and I'm sure my colleagues might chime in with another solution. You could for example upload the file to the file store via a dashboard and do the processing via a script run on the back-end.

    Front-end only solution using Papa Parse (see their documentation for parsing / output options). You need to add this as a user module - https://help.infiniteautomation.com/getting-started-with-a-user-module/

    define(['angular', 'require', 'papaparse'], function(angular, require, Papa) {
        'use strict';
        
        const userModule = angular.module('userModule', ['maUiApp']);
        
        class ProcessCsvController {
            fileSelected(event) {
                const files = event.target.files;
                if (files.length) {
                    this.parseFile(files[0]);
                }
                event.target.value = null;
            }
            
            parseFile(file) {
                Papa.parse(file, {
                	complete: results => {
                		this.modifyRows(results.data);
                	}
                });
            }
            
            modifyRows(rows) {
                rows.forEach(row => {
                    // whatever you want to do
                    console.log(row);
                });
                
                this.downloadCsv(rows, 'myFile.csv');
            }
            
            downloadCsv(rows, filename) {
                const csvBlob = new Blob([Papa.unparse(rows)]);
                const url = URL.createObjectURL(csvBlob);
                try {
                    const a = document.createElement('a');
                    a.style.display = 'none';
                    a.href = url;
                    a.download = filename;
                    document.body.appendChild(a);
                    a.click();
                    document.body.removeChild(a);
                } finally {
                    URL.revokeObjectURL(url);
                }
            }
        }
    
        userModule.component('processCsv', {
            template: `<input type="file" accept="text/*,.csv,.txt" ma-change="$ctrl.fileSelected($event)">`,
            controller: ProcessCsvController
        });
        
        return userModule;
    }); // define
    

    All you have to do to use this is plonk it onto a page -

    <process-csv></process-csv>
    

    posted in User help read more
  • Jared Wiltshire

    Here's another way of doing it that will only fetch the values for the selected point. The buttons also highlight to show which point is selected.

    <!-- set the initial data point XID for when the page loads -->
    <div ng-init="dataPointXid = 'temperature'"></div>
    
    <ma-get-point-value point-xid="{{dataPointXid}}" point="selectedPoint"></ma-get-point-value>
    <md-button ng-click="dataPointXid = 'temperature'" ng-class="{'md-raised': dataPointXid === 'temperature'}">Data point 1</md-button>
    <md-button ng-click="dataPointXid = 'voltage'" ng-class="{'md-raised': dataPointXid === 'voltage'}">Data point 2</md-button>
    
    <ma-point-values point="selectedPoint" values="pointValues" from="dateBar.from" to="dateBar.to" rollup="{{dateBar.rollupType}}" rollup-interval="{{dateBar.rollupIntervals}} {{dateBar.rollupIntervalPeriod}}">
    </ma-point-values>
    
    <ma-serial-chart style="height: 300px; width: 100%" series-1-values="pointValues" series-1-point="selectedPoint">
    </ma-serial-chart>
    

    0_1548952726907_cca593a7-6577-4b09-b4b7-70066a9d8e9a-image.png

    posted in User help read more
  • Jared Wiltshire

    @andrewh The timeout is configured from our code, its not something set by the browser. You can change the default timeout using a user module like so -

    define(['angular', 'require'], function(angular, require) {
        'use strict';
        const userModule = angular.module('userModule', ['maUiApp']);
        userModule.constant('MA_TIMEOUT', 60000);
        return userModule;
    }); // define
    

    PS I might increase the default timeout for point value requests in the next release.

    posted in User help read more
  • Jared Wiltshire

    @psysak said in Calculating values on the fly:

    Is the
    {xid: 'cost'}

    an implied search term for xid which contains "cost"?

    No. This is object literal syntax - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Object_literals

    By using points="[power, price, {name: 'Cost', xid: 'cost', deviceName: 'Cost'}]" I am creating an array containing the two points stored in the scope as power and price, and creating a third object in the array with its xid property set to the string cost.

    posted in User help read more
  • Jared Wiltshire

    @psysak said in Calculating values on the fly:

    Is that about correct?

    Yes, you followed it through almost spot on. The property names for the values are actually more like -
    [{timestamp: xxx, value_DP_power_xid: xxx, value_DP_price_xid: xxx, value_cost: xxx}]

    @psysak said in Calculating values on the fly:

    So then in ma-serial-chart what exactly is the relationship between "points" and "values"?

    The serial chart directive will only plot a series for a point in the points array. It will take each point's XID and plot the property value_${XID} from the values array.

    @psysak said in Calculating values on the fly:

    Then for "points" do they have to be listed in the order that the values array has them in?

    The order of the points is irrelevant, except maybe for the order they are displayed in the legend.

    @psysak said in Calculating values on the fly:

    you said that you added a dummy point so that it catches the new value

    As above the serial chart directive needs a point to plot its series, I added a dummy point with XID cost so that it looks in the values array for the property value_cost and plots it.

    @psysak said in Calculating values on the fly:

    If the dummy point wasn't there would it just ignore the value_cost values?

    Correct.

    @psysak said in Calculating values on the fly:

    And what would be the minimum requirements for this dummy point? Name, xid and device name?

    Basically. That is all that is displayed in this configuration.

    posted in User help read more
  • Jared Wiltshire

    @psysak said in Chrome on a MacBook:

    I just had this issue pop up in page editor as well. However, I've also realized that everything works perfectly fine in FireFox so if I have any issues I just open that up.

    If it is happening on the dashboard designer I would also expect it to affect the page editor too. They use the exact same ace editor component. Chrome should work 100% perfectly, the fact that you are still experiencing issues with this indicates there is something amiss with your installation. Please contact me via private message / chat and I'll get you to screen share and we can get to the bottom of it.

    You also commented that you were experiencing this issue which was patched long ago.

    posted in User help read more
  • Jared Wiltshire

    The paths that I posted were URLs, I have edited the post to show the override paths. If you override all the paths listed above you will not have a problem, just be sure to clear your cache. Sometimes browsers will hang onto the icons even after you clear your cache.

    You can also override the following files if desired to change the locations, sizes etc of the images. I would strongly not recommend overriding index.html though because if we make changes to this in the codebase you will not get the updates and it will also affect the caching of resources (Each resource linked to from the index.html file has a hash appended which changes when the file is modified).

    $MA_HOME/overrides/web/modules/mangoUI/web/ui/manifest.json
    $MA_HOME/overrides/web/modules/mangoUI/web/ui/index.html
    

    posted in MangoES Hardware read more
  • Jared Wiltshire

    Easiest way to create a heap of data points would be to use the CSV upload on the "Bulk data point edit" page.

    posted in How-To read more
  • Jared Wiltshire

    You could also just stick something on your page to reset the date range if they try -

    <ma-calc input="dateBar.from" on-change="startOfMonth = ('now' | maMoment:'startOf':'month'); $value > startOfMonth && (dateBar.from = startOfMonth.toDate())"></ma-calc>
    <ma-calc input="dateBar.to" on-change="startOfMonth = ('now' | maMoment:'startOf':'month'); $value > startOfMonth && (dateBar.to = startOfMonth.toDate())"></ma-calc>
    

    posted in User help read more
  • Jared Wiltshire

    @phildunlap said in Is it a problem having a big H2 database?:

    but MSSQL and Postgres should also work.

    MSSQL and Postgres will not work, yes there is technically some support for them in the code but it has gaps and is entirely untested.

    posted in User help read more
  • Jared Wiltshire

    @psysak said in Calculating values on the fly:

    what language/syntax are the expressions written in in all this?

    They are AngularJS expressions, essentially JavaScript

    @psysak said in Calculating values on the fly:

    what is maFirst

    It is an AngularJS filter that simply takes the first value of an array.

    posted in User help read more
  • Jared Wiltshire

    @psysak said in Calculating values on the fly:

    Is it then possible to calculate and display the statistics for the calculated values?

    It is if you are willing to do the calculations yourself, use Array.prototype.reduce()

    Here's an example calculating the max/avg/total.

    <ma-watch-list-get ng-model="designer.watchList" parameters="designer.parameters" on-points-change="designer.points = $points" id="b7bdf2f9-bf34-417b-af00-58410963e785" watch-list-xid="WL_9950dd8e-91a1-4cf3-8ab1-e6c2b74ccab0"></ma-watch-list-get>
    
    <ma-calc input="designer.points | filter:{name:'Real power'}:true | maFirst" output="power"></ma-calc>
    <ma-calc input="designer.points | filter:{name:'Power factor'}:true | maFirst" output="price"></ma-calc>
    <ma-fn expression="$input.value_cost = $input['value_' + power.xid] * $input['value_' + price.xid]" fn="multiply" arg-names="['$input']"></ma-fn>
    <ma-fn expression="$item.value_cost > $max ? $item.value_cost : $max" fn="find_max" arg-names="['$max', '$item']"></ma-fn>
    <ma-calc input="::(1).constructor.isFinite" output="isFinite"></ma-calc>
    <ma-fn expression="isFinite($item.value_cost) ? $accum + $item.value_cost : $accum" fn="accumulate" arg-names="['$accum', '$item']"></ma-fn>
    
    <div class="ma-designer-root" id="8ee80d8a-f0cc-4dd3-a8a4-34e96dbbbdb9" style="width: 1366px; height: 768px; position: relative;">
        <ma-watch-list-parameters id="2c9a323a-440f-4fc0-86c9-f07b6ab4f13b" ng-model="designer.parameters" watch-list="designer.watchList" style="position: absolute; width: 100%; left: 0px; top: 0px;"></ma-watch-list-parameters>
        <ma-point-values id="0be711f5-7aa2-4f1c-985d-f1009ccb7143" points="designer.points" from="dateBar.from" to="dateBar.to" rollup="{{dateBar.rollupType}}" rollup-interval="{{dateBar.rollupIntervals + ' ' + dateBar.rollupIntervalPeriod}}" style="position: absolute; left: 0px; top: 700px;" values="values"></ma-point-values>
        <ma-serial-chart id="daeda3f3-3509-46c0-a63a-5877bbfb7946" style="position: absolute; width: 100%; height: 600px; left: 0px; top: 70px;" values="values.forEach(multiply); values" points="[power, price, {name: 'Cost', xid: 'cost', deviceName: 'Cost'}]" legend="true" export="true" series3-type="step"></ma-serial-chart>
    
        <h1 id="59669906-8019-49fa-88f4-2a3d6c3d4b6c" style="position: absolute; left: 430px; top: 90px;">Max cost is {{values.reduce(find_max, 0) | currency}}</h1>
        <h1 id="b2cca2ae-d6a9-4265-a3db-ba4526bfd244" style="position: absolute; left: 430px; top: 130px;">Total cost is {{values.reduce(accumulate, 0) | currency}}</h1>
        <h1 id="b2cca2ae-d6a9-4265-a3db-ba4526bfd245" style="position: absolute; left: 430px; top: 170px;">Average cost is {{values.reduce(accumulate, 0) / values.length | currency}}</h1>
    </div>
    

    Screenshot for good measure:
    0_1548361912789_9903c6ab-933a-414b-9fd5-bd27cffe4d69-image.png

    posted in User help read more
  • Jared Wiltshire

    @psysak said in Excel report:

    Is it still the case that the <ma-excel-report-run> does not support multiple ranges?

    There are three ways of running it, by default it only sets the date range for one time series. You can however get it to set the dates for all the time series by setting all-time-series="true" or only certain time series by passing time-series-names="['Time series 1', 'Time series 3']"

    posted in Dashboard Designer & Custom AngularJS Pages read more