| /******************************************************************************** |
| * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation |
| * |
| * See the NOTICE file(s) distributed with this work for additional |
| * information regarding copyright ownership. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| ********************************************************************************/ |
| |
| import { HttpClient, HttpHeaders } from '@angular/common/http'; |
| import { Injectable } from '@angular/core'; |
| |
| import { plainToClass } from 'class-transformer'; |
| import { map, catchError } from 'rxjs/operators'; |
| |
| import { HttpErrorHandler } from '../../core/http-error-handler'; |
| import { PropertyService } from '../../core/property.service'; |
| import { Node } from '../../navigator/node'; |
| import { MeasuredValuesResponse, MeasuredValues, PreviewValueList } from '../model/chartviewer.model'; |
| import { QueryService, Query, SearchResult, Row } from '../../tableview/query.service'; |
| import { throwError } from 'rxjs'; |
| import { ChannelGroup } from '../model/types/channelgroup.class'; |
| import { Channel } from '../model/types/channel.class'; |
| import { Measurement } from '../model/types/measurement.class'; |
| import { TYPE_CHANNEL, TYPE_CHANNELGROUP, TYPE_MEASUREMENT } from '../model/constants'; |
| |
| export function getDataArray(m: MeasuredValues) { |
| if (m.scalarType === 'INTEGER') { |
| return m.integerArray; |
| } else if (m.scalarType === 'FLOAT') { |
| return m.floatArray; |
| } else if (m.scalarType === 'DOUBLE') { |
| return m.doubleArray; |
| } else if (m.scalarType === 'DATE') { |
| return m.dateArray; |
| } else if (m.scalarType === 'SHORT') { |
| return m.shortArray; |
| } else if (m.scalarType === 'BOOLEAN') { |
| return m.booleanArray; |
| } else if (m.scalarType === undefined && m.stringArray !== undefined) { |
| m.scalarType = 'STRING'; |
| return m.stringArray; |
| } |
| } |
| |
| @Injectable({ |
| providedIn: 'root' |
| }) |
| export class ChartViewerDataService { |
| private _contextUrl: string; |
| |
| private httpOptions = { |
| headers: new HttpHeaders({ |
| 'Content-Type': 'application/json', |
| 'Accept': 'application/json' |
| }) |
| }; |
| |
| constructor(private http: HttpClient, |
| private httpErrorHandler: HttpErrorHandler, |
| private _prop: PropertyService, |
| private queryService: QueryService) { |
| this._contextUrl = _prop.getUrl('mdm/environments'); |
| } |
| |
| /** |
| * Loads preview value (if chunks > 0) or measured values (if chunks == 0). |
| * @param channelGroup channel group node |
| * @param channels channel nodes |
| * @param startIndex start index to load the data |
| * @param requestSize number of requested values |
| * @param chunks preview chunks. If 0, preview is disabled and original values are loaded |
| */ |
| loadValues(channelGroup: ChannelGroup, channels: Channel[], startIndex = 0, requestSize = 0, chunks = 0) { |
| if (chunks > 0) { |
| return this.loadPreviewValues(channelGroup, channels, chunks, startIndex, requestSize); |
| } else { |
| return this.loadMeasuredValues(channelGroup, channels, startIndex, requestSize); |
| } |
| } |
| |
| /** |
| * Loads measured values |
| * @param channelGroup channel group node |
| * @param channels channel nodes |
| * @param startIndex start index to load the data |
| * @param requestSize number of requested values |
| */ |
| loadMeasuredValues(channelGroup: ChannelGroup, channels: Channel[], startIndex = 0, requestSize = 0) { |
| let readRequest = { |
| 'channelGroupId': channelGroup.id, |
| 'channelIds': channels !== undefined ? channels.filter(channel => channel.type === 'Channel').map(channel => channel.id) : [], |
| 'start_index': startIndex, |
| 'request_size': requestSize, |
| 'valuesMode': 'CALCULATED' |
| }; |
| |
| return this.http.post<MeasuredValuesResponse>(this._contextUrl + '/' + channelGroup.source + '/values/read', |
| readRequest, this.httpOptions) |
| .pipe( |
| map(res => plainToClass(MeasuredValues, res.values)), |
| map(measurementValues => measurementValues.sort((a, b) => a.name.localeCompare(b.name))), |
| catchError(this.httpErrorHandler.handleError) |
| ); |
| } |
| |
| /** |
| * Loads preview values. |
| * @param channelGroup channel group node |
| * @param channels channel nodes |
| * @param chunks preview chunks |
| * @param startIndex start index to load the data |
| * @param requestSize number of requested values |
| */ |
| loadPreviewValues(channelGroup: ChannelGroup, channels: Channel[], chunks: number, startIndex = 0, requestSize = 0) { |
| let readRequest = { |
| 'channelGroupId': channelGroup.id, |
| 'channelIds': channels !== undefined ? channels.filter(channel => channel.type === 'Channel').map(channel => channel.id) : [], |
| 'start_index': startIndex, |
| 'request_size': requestSize, |
| 'valuesMode': 'CALCULATED' |
| }; |
| let previewRequest = { |
| 'numberOfChunks': chunks, |
| 'readRequest': readRequest |
| }; |
| |
| return this.http.post<PreviewValueList>(this._contextUrl + '/' + channelGroup.source + '/values/preview', |
| previewRequest, this.httpOptions) |
| .pipe( |
| map(res => plainToClass(MeasuredValues, res.avg)), |
| catchError(this.httpErrorHandler.handleError) |
| ); |
| } |
| |
| loadMeasurement(node: Node) { |
| if (node.type !== TYPE_MEASUREMENT && node.type !== TYPE_CHANNELGROUP && node.type !== TYPE_CHANNEL) { |
| return throwError('Node must be of type: ' + TYPE_MEASUREMENT + ' or ' + TYPE_CHANNELGROUP + ' or ' + TYPE_CHANNEL); |
| } |
| const query = new Query(); |
| query.addFilter(node.sourceName, node.type + '.Id eq ' + node.id); |
| query.columns = ['Measurement.Id', 'ChannelGroup.Id', 'ChannelGroup.Name', 'ChannelGroup.SubMatrixNoRows', |
| 'Channel.Id', 'Channel.Name', 'LocalColumn.axistype', 'LocalColumn.IndependentFlag']; |
| query.resultType = 'Channel'; |
| |
| return this.queryService.query(query).pipe( |
| map(sr => sr.rows.map(row => this.mapRow(row))), |
| map(pairs => { |
| let mea = new Measurement(); |
| mea.type = TYPE_MEASUREMENT; |
| |
| pairs.forEach(entry => { |
| mea.put(entry.channelGroup, entry.channel); |
| mea.source = entry.channelGroup.source; |
| mea.id = entry.meaId; |
| }); |
| |
| return mea; |
| }), |
| ); |
| } |
| |
| private mapRow(row: Row) { |
| let channel = new Channel(); |
| channel.id = row.id; |
| channel.name = row.getColumn('Channel.Name'); |
| channel.channelGroupId = row.getColumn('ChannelGroup.SubMatrixNoRows'); |
| channel.axisType = row.getColumn('LocalColumn.axistype'), |
| channel.isIndependent = row.getColumn('LocalColumn.IndependentFlag') === '1'; |
| |
| let channelGroup = new ChannelGroup( |
| row.source, |
| row.getColumn('ChannelGroup.Id'), |
| parseInt(row.getColumn('ChannelGroup.SubMatrixNoRows'), 10)); |
| |
| channelGroup.name = row.getColumn('ChannelGroup.Name'); |
| return { meaId: row.getColumn('Measurement.Id'), channelGroup: channelGroup, channel: channel }; |
| } |
| } |