...
 
Commits (2)
GPSdata
=======
![N|Solid](http://www.ingv.it/templates/ingv/images/head_ingv.png)
Aim of GPSdata is to provide users the possibility of downloading GPS
rinex data worldwide, avoiding as much as possible the code writing.\
To achieve this goal, a thorough analysis is required.\
We can identify the following three main areas in the rinex data
recovery activity, to simplify at a maximun level
- *Connect* to the Network Site
- *Retrieve* the list of the GPS data stations and then, one by one,
retrieve the GPS data for the Stations of interest
- *Transform* available GPS data to obtain the standard 2.11 rinex
format, whenever necessary, and store it into the INGV repository
We could have easily implemented these three activity areas by
developing dedicated software for each Network. Instead, we followed
another more comlplex approach to manage all these features by
developing an integrated application which provides the user with the
following features:
- Configure Networks Site (**Ready**)
- Schedule download processes, separately for each Site (**Ready**)
- start and stop processes (**Ready**)
- Monitor the activity (**in progress**)
- Analyze results (**in progress**)
At this state of the implementation a first release of the product ha
been realized. The following sections describe it in detail.
#### Output (Ready)
The output of GPSdata processes consists of:
- rinex data in standard rinex 2.11 format
- logs
- *Missing Stations* list file, as stations requested but not found
- *New Stations* list file, as stations available but not requested
*Missing Stations list* and *New Stations list* arise from the
comparison between Stations list of interest (provided and mantained by
the users) and list af available stations (retrieved from Sites)\
These lists will be available to the user for his activity of results
analisys
#### User interface
Current release of GPSdata offers to the user a raw interface:
(**Ready**)
- configuration files has to be manually set
- process is launched from command line
- process activity monitoring is demanded to operative system tools
- no tools for showing results has been developed
A browser-based graphical user interface is scheduled as a future
implementation. From this interface user should manage all the
interaction with GPSdata application (**in progress**)
- Configure
- start, stop and Monitoring the activity
- View results
#### Execution
To show the usage of *GPSdata* script, run the command:
$ gpsdata.py -h
The simplest ways to start *GPSdata* is:
$ gpsdata.py start
With this command all the configured networks will be scheduled as
specified in config\_net.json. Each network is controlled by a dedicated
background process (*Daemon*). The task of Daemon is to execute its
network process at each scheduled time\
Network process downloads the rinex data of the requested days for all
Stations listed in *\<Station-Name\>*.list file\
The command for stopping all active *Daemons* is
$ gpsdata.py stop
##### Execution examples
*interactive mode with no schedulation*:
$ gpsdata.py -x start
*iterate on number of days back (20) at each execution date*
$ gpsdata.py -db 20 start
*iterate on number of days in a specific time range*
$ gpsdata.py -y1 2016 -d1 350 -y2 2017 -d2 10 start
*process only a specific network*
$ gpsdata.py -n italpos start
*process a list of networks contained in an external file*
$ gpsdata.py -l [listfile] start
*process any network immediately before normal scheduling*
$ gpsdata.py -i start
All options can be combined, except some mutual exclusions, like for
example *–immediate* (*-i*) and *–execute* (*-x*) options\<br\>\
*Stop* action admit only *-n (–net)* option
#### Configuration
The user sets up the program trough two configuration files (both in
json format), `config.json` and `config_nets.json`.\
The advantages of *JSON* format are the power to represent complex data
structure and the easy way to encode/decode it by the program.\
The disadvantages are that it don’t admit any error in the codification
and is not possible to insert comments.
##### config.json
This file contains global configuration and default values for networks
parameters.\
Its structure is the following:
{
"download": {
"file_name": "__STATION_CODE_LOWER_CASE____DOY__0.__YY__d",
"path_name": "/pub/rinex/__CCYY__/__DOY__",
"ftp_anonymous_user" : "anonymous",
"ftp_anonymous_password" : "[email protected]"
},
"schedule": {
"mins": [1, 10],
"hours": 10,
"days": 10,
"months": 11
},
"log_path": "/opt/GPSdata/log",
"data_archive": "/data/archive/rinex/CGPS",
"data_archive_NETS": "NETS",
"data_archive_YEARS": "YEARS"
}
`Download` section cointains the following parameters:
- file\_name
- path\_name
- ftp\_anonymous\_user
- ftp\_anonymous\_password
`file_name` and `path_name` refer to remote names. They are used as
default, when missing in the Station configuration. They can be composed
merging fixed string with the following global value:
- `__DOY__` (day of the year left padded with zeroes. From 000 to
365/366)
- `__YY__` (year without century)
- `__CCYY__` (century + year)
- `__MM__` (month from 01 to 12)
- `__MONTH__` (month in three letters, from ‘Jan’ to ‘Dec’)
- `__DD__` (day of the month, from 00 to 28/31)
- `__STATION_CODE_LOWER_CASE__`
- `__STATION_CODE_UPPER_CASE__`
`file_name` does not contain the extension. This is evaluated internally
by the process.
`ftp_anonymous_user` and `ftp_anonymous_password` are used for ftp
connection as default, when missing in the Station configuration
`log_path`: indicate the folder for log files. Each Station has a
dedicaded log file in this folder with the name *network-name*.log
`data_archive`: indicate the root of output data
`data_archive_NETS`: sub folder of *data\_archive*, for rinex data files
`data_archive_YEARS`: sub folder of *data\_archive*, for symbolic link
to rinex data file.
for Each configured Network, a file with the list of requested stations
is searched by the process, with name: *\<Station-code\>.list*. This
file has to be formatted in three words per line to indicate:
- STATION-CODE
- STATION-NAME
- STATION-LINK
Output path of rinex data files is a sub-path of *data\_archive\_NETS*
configuration parameter and is composed as follow:
`uppercase-of-network-configuration-name/__CCYY__/__DOY__`
Names of standard INGV rinex data (Hatanaka plus unix compressed) are
composed as follow:
`__STATION_CODE_LOWER_CASE__/__DOY__/0.__YY__d.Z`
Path of symbolic links to rinex data files is a sub-path of
*data\_archive\_YEARS* configuration parameter and is composed as
follow:
`__CCYY__/__DOY__`
Names of symbolic links are composed as follow:
`STATION-LINK/__DOY__/0.__YY__d.Z`
`Schedule` section cointains the following parameters:
- mins
- hours
- days
- months
Each of this parameter can assume a single value or set o values.
Parameter missing stands for ‘ALL’. Let’s show some examples:
`mins = [1, 30]`: the process will run at minutes 1 and 30 of every
hour, of every day
`mins = 10, hour = [0, 12]`: the process will run at minute 10 of hour 0
and hour 12, of every day
`mins = 0, hour = [12], month = 1`: the process will run at minute 0 of
hour 12 of every day of every january
The schedule set in `config.json` is used as default, for Networks who
missing schedule section
##### config\_nets.json
This file contains a list of Networks configuration.
[
{
"name": "cven",
"org" : "ftp://garner.ucsd.edu"
},
{
"name": "italpos",
"org": "ftps://it.nrtk.eu:990",
"user": "30secfree",
"password": "30sec1258",
"path_name": "/__CCYY__/__DOY__",
"file_name": "__STATION_CODE_LOWER_CASE____DOY__0",
"post_download_action": 1
},
{
"name": "irealp",
"post_download_action": 1,
"org": "http://158.102.161.199:8080",
"user": "retegnss",
"password": "retegnss",
"path_name": "Data/__CCYY__/__DOY__",
"file_name": "__STATION_CODE_LOWER_CASE____DOY__0",
"schedule": {
"mins" : 0,
"hours": [00, 12]
}
},
}]
### Future implementation!
`browser-based graphical control interface`
From this control panel, the administrator users should manage the
application, doing the following activities:
- Modify configuration data in a controlled manner. New networks which
deliver data in standard format, should works in plug and play
mode.\
User should test the connection and the path and station-names
composition, directly from the control-panel
- Start/Stop process for desired networks and monitoring the status
- View the output GPS data file loaded in the INGV repository
- View the log files of runned procesess
- View and compare lists of requested, missing and new stations
- Storing data in 3.0 rinex format?
- Any differences between Networks (variable list) and Projects (Fixed
list)
`post load processing`
The aim of this task is to analyze the content of rinex data loaded into
INGV repository, in order to guarantees their consistency.\
Also data will be processed by INGV analysis engines that provide
output products
`browser-based graphical external user interface`
From this panel, external users can download data from INGV repository
and use all products exposed from INGV
<!--ts-->
* [1. Introduction](#1-introduction)
* [1.1 Current version of GPSDataMonitor](#11-current-version-of-gpsdatamonitor)
* [1.3 Files in the project](#13-files-in-the-project)
* [2. Installation](#2-installation)
* [3. Notes](#3-notes)
<!-- Added by: sergio, at: 2019-01-04T14:23+01:00 -->
<!--te-->
# 1. Introduction #
This document describes the usage and adaptation of a GPSDataMonitor being developed by INGV and is part of geodetic research software
The server is based on Angular2 platform.
**Author:** Sergio Bruni (sergio.bruni@ingv.it)
**Document created:** 5. January 2018
**Last updated:** 5. January 2018
## 1.1 Current version of GPSDataMonitor
The current version of the GPSDataMonitor is ... This documentation should reflect the status of the system in this version.
## 1.3 Files in the project ##
The following files are maintained in the archive
# 2. Installation
# 3. Notes #
This project contains two subprojects:
1. The first is contained in app folder. This is GPSDataMonitor project
2. The second is contained in RestServices folder. This project has been moved on the top level of repository and renamed in GPSRestServices. So, It can be ignored
# Editor configuration, see http://editorconfig.org --
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false
# DwNg2App
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.6.8.
## Development server
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
## Code scaffolding
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
## Build
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.
## Running unit tests
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
## Running end-to-end tests
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"dw-ng2-app": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist",
"index": "src/index.html",
"main": "src/main.ts",
"tsConfig": "src/tsconfig.app.json",
"polyfills": "src/polyfills.ts",
"assets": [
"src/assets",
"src/favicon.ico"
],
"styles": [
"src/assets/css/styles1.css",
"src/assets/css/styles.css",
"src/assets/css/styles_tabs.css",
"node_modules/font-awesome/css/font-awesome.css",
"node_modules/primeng/resources/themes/omega/theme.css",
"node_modules/primeng/resources/primeng.css"
],
"scripts": [
"src/assets/js/zingchart.min.js"
]
},
"configurations": {
"prod": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "dw-ng2-app:build"
},
"configurations": {
"prod": {
"browserTarget": "dw-ng2-app:build:prod"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "dw-ng2-app:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"karmaConfig": "./karma.conf.js",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"scripts": [
"src/assets/js/zingchart.min.js"
],
"styles": [
"src/assets/css/styles1.css",
"src/assets/css/styles.css",
"src/assets/css/styles_tabs.css",
"node_modules/font-awesome/css/font-awesome.css",
"node_modules/primeng/resources/themes/omega/theme.css",
"node_modules/primeng/resources/primeng.css"
],
"assets": [
"src/assets",
"src/favicon.ico"
]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
},
"dw-ng2-app-e2e": {
"root": "",
"sourceRoot": "",
"projectType": "application",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "./protractor.conf.js",
"devServerTarget": "dw-ng2-app:serve"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"e2e/tsconfig.e2e.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
}
},
"defaultProject": "dw-ng2-app",
"schematics": {
"@schematics/angular:component": {
"prefix": "app",
"styleext": "sass"
},
"@schematics/angular:directive": {
"prefix": "app"
}
}
}
\ No newline at end of file
import { AppPage } from './app.po';
describe('dw-ng2-app App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display welcome message', () => {
page.navigateTo();
expect(page.getParagraphText()).toEqual('Welcome to app!');
});
});
import { browser, by, element } from 'protractor';
export class AppPage {
navigateTo() {
return browser.get('/');
}
getParagraphText() {
return element(by.css('app-root h1')).getText();
}
}
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/e2e",
"baseUrl": "./",
"module": "commonjs",
"target": "es5",
"types": [
"jasmine",
"jasminewd2",
"node"
]
}
}
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma')
],
client:{
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, 'coverage'), reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true
},
angularCli: {
environment: 'dev'
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
});
};
This diff is collapsed.
{
"name": "dw-ng2-app",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"ng": "ng",
"start": "ng serve --host 0.0.0.0",
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"build:sass": "node-sass src/assets/css -o src/assets/css",
"watch:sass": "npm run build:sass && node-sass src/assets/css -wo src/assets/css"
},
"private": true,
"dependencies": {
"@angular/animations": "^6.1.10",
"@angular/common": "^6.1.10",
"@angular/compiler": "^6.1.10",
"@angular/core": "^6.1.10",
"@angular/forms": "^6.1.10",
"@angular/http": "^6.1.10",
"@angular/platform-browser": "^6.1.10",
"@angular/platform-browser-dynamic": "^6.1.10",
"@angular/router": "^6.1.10",
"@ngui/ngui": "^0.15.2",
"@ngui/overlay": "^0.8.0",
"angular2-modal": "^3.0.3",
"core-js": "^2.4.1",
"font-awesome": "^4.7.0",
"jquery": "^3.3.1",
"less": "^3.0.1",
"ng2-popup": "^0.4.0",
"ng2-ui": "^0.14.1",
"ngx-bootstrap": "^3.0.1",
"node-sass": "^4.7.2",
"primeng": "^5.2.6",
"rxjs": "^6.3.3",
"rxjs-compat": "^6.0.0-rc.0",
"sass-loader": "^6.0.7",
"svg-icon": "^0.8.2",
"systemjs": "^0.21.3",
"underscore": "^1.8.3",
"zingchart": "^2.7.1",
"zingchart-angularjs": "^1.2.0",
"zone.js": "^0.8.26"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.6.8",
"@angular/cli": "^6.2.5",
"@angular/compiler-cli": "^6.1.10",
"@angular/language-service": "^6.1.10",
"@swimlane/ngx-charts": "^8.1.0",
"@types/jasmine": "~2.8.3",
"@types/jasminewd2": "~2.0.2",
"@types/jquery": "^3.3.1",
"@types/node": "~6.0.60",
"codelyzer": "^4.0.1",
"jasmine-core": "~2.8.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~2.0.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "^1.2.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.1.2",
"ts-node": "~4.1.0",
"tslint": "~5.9.1",
"typescript": "~2.9.2"
}
}
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./e2e/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: 'e2e/tsconfig.e2e.json'
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};
//
// panel.sass
//
.panel
background-color: #ffe;
border: 1px solid transparent;
border-radius: 4px;
-webkit-box-shadow: 0 1px 1px rgba(0,0,0,.05);
box-shadow: 0 1px 1px rgba(0,0,0,.05);
color: #333;
.panel-header
padding: 10px 15px;
border-bottom: 1px solid transparent;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
background-color: #f5f5f5;
border-color: #ddd;
/* EXAMPLE STYLES
-------------------------------*/
body {
font-family: roboto;
padding: 20px;
}
nav {
margin-bottom: 20px;
padding-bottom: 20px;
border-bottom: 1px solid #ddd;
a {
margin-right: 8px;
}
}
/* MODAL STYLES
-------------------------------*/
modal {
/* modals are hidden by default */
display: none;
.modal {
/* modal container fixed across whole screen */
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
/* z-index must be higher than .modal-background */
z-index: 1000;
/* enables scrolling for tall modals */
overflow: auto;
.modal-body {
padding: 20px;
background: #fff;
/* margin exposes part of the modal background */
margin: 40px;
}
}
.modal-background {
/* modal background fixed across whole screen */
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
/* semi-transparent black */
background-color: #000;
opacity: 0.75;
/* z-index must be below .modal and above everything else */
z-index: 900;
}
}
body.modal-open {
/* body overflow is hidden to hide main scrollbar when modal window is open */
overflow: hidden;
}
import { Component, ElementRef, Input, OnInit, OnDestroy } from '@angular/core';
import * as $ from 'jquery';
import { ModalService } from '../_services/index';
@Component({
moduleId: module.id.toString(),
selector: 'gps_modal',
template: '<ng-content></ng-content>'
})
export class ModalComponent implements OnInit, OnDestroy {
@Input() id: string;
private element: JQuery;
constructor(private modalService: ModalService, private el: ElementRef) {
this.element = $(el.nativeElement);
}
ngOnInit(): void {
let modal = this;
// ensure id attribute exists
if (!this.id) {
console.error('modal must have an id');
return;
}
// move element to bottom of page (just before </body>) so it can be displayed above everything else
this.element.appendTo('body');
// close modal on background click
this.element.on('click', function (e: any) {
var target = $(e.target);
if (!target.closest('.modal-body').length) {
//modal.close();
}
});
// add self (this modal instance) to the modal service so it's accessible from controllers
this.modalService.add(this);
}
// remove self from modal service when directive is destroyed
ngOnDestroy(): void {
this.modalService.remove(this.id);
this.element.remove();
}
// open modal
open(): void {
this.element.show();
$('body').addClass('gps_modal-open');
}
// close modal
close(): void {
this.element.hide();
$('body').removeClass('gps_modal-open');
}
}
import * as _ from 'underscore';
export class ModalService {
private modals: any[] = [];
add(modal: any) {
//console.log("sono add di modal.service.ts aggiungo: " + modal.id);
// add modal to array of active modals
this.modals.push(modal);
/*
console.log("prima di each-add");
this.modals.forEach(function(element) {
console.log(element.id);
});
console.log("dopo di each-add");
*/
}
remove(id: string) {
// remove modal from array of active modals
let modalToRemove = _.findWhere(this.modals, { id: id });
this.modals = _.without(this.modals, modalToRemove);
}
open(id: string) {
//console.log("sono open di modal.service.ts: apro " + id);
// open modal specified by id
/*
console.log("ModalService.open prima di each");
this.modals.forEach(function(element) {
console.log(element.id);
});
console.log("ModalService.open. dopo di each");
*/
let modal = _.findWhere(this.modals, { id: id });
//console.log("sono open di modal.service.ts: recuperata " + modal.id);
modal.open();
}
close(id: string) {
// close modal specified by id
let modal = _.find(this.modals, { id: id });
modal.close();
}
}
import { Injectable } from '@angular/core';
import { Http, Headers, Response } from "@angular/http";
import 'rxjs/Rx';
import { Network } from '../domain/network';
import { Station } from '../domain/station';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/toPromise';
import { environment } from '../../environments/environment';
import {RequestOptions, Request, RequestMethod} from '@angular/http';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
@Injectable()
export class NetworkService {
URL_NET_LIST = environment.apiEndpoint + "/netlist";
URL_NET_UPDATE = environment.apiEndpoint + "/network";
URL_STATION_LIST = environment.apiEndpoint + "/stationlist/";
URL_DOWNLOAD_INDICATOR = environment.apiEndpoint + "/download_indicator";
//constructor(private http: HttpClient) {}
constructor(private http: Http) {}
getNetworks() {
//return this.http.get<any>('assets/data/cars-small.json')
// .toPromise()
// .then(res => <Car[]> res.data)
// .then(data => data);
return this.http.get(this.URL_NET_LIST)
.map(response => {
{ return <Network[]> response.json().detailed_list };
})
.catch((res: Response) => this.handleError(res));
}
updateNetwork(network) {
let body = JSON.stringify(network);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
console.log("call " + this.URL_NET_UPDATE + " service")
//return this.http.post(this.URL_NET_UPDATE + '/' + network.id, body, options)
return this.http.post(this.URL_NET_UPDATE, body, options)
.map(response => {
{ return <Network> response.json() };
})
.catch((res: Response) => this.handleError(res));
}
StationList(network_id) {
//console.log("Prima di _http.get: " + this.URL_STATION_LIST);
return this.http.get(this.URL_STATION_LIST + network_id)
.map(response => {
{ return response.json() };
})
.catch((res: Response) => this.handleError(res));
}
getDownloadIndicator(param) {
let network_id: number = param;
let url = this.URL_DOWNLOAD_INDICATOR + '/' + network_id
//alert (url)
return this.http.get(url)
.map(response => {
{ return response.json()};
})
.catch((res: Response) => this.handleError(res));
}
private handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg);
console.error("error.text=" + error.text());
return Observable.throw(errMsg);
}
}
import { Injectable } from '@angular/core';
import { Http, Headers, Response } from "@angular/http";
import 'rxjs/Rx';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/toPromise';
import { environment } from '../../environments/environment';
import {RequestOptions, Request, RequestMethod} from '@angular/http';
import { BrowserModule } from '@angular/platform-browser';
import { Station } from '../domain/station';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
@Injectable()
export class StationService {
URL_DATA_AVAILABILITY = environment.apiEndpoint + "/availability_data";
URL_DATA_AVAILABILITY2 = environment.apiEndpoint + "/availability_data2";
URL_DATA_AVAILABILITY3 = environment.apiEndpoint + "/availability_data3";
URL_DATA_AVAILABILITY_SCROLLING = environment.apiEndpoint + "/availability_data_scrolling";
URL_STATIONS_WITH_NETWORKS = environment.apiEndpoint + "/stations_with_networks";
URL_STATION_LIST = environment.apiEndpoint + "/stationlist";
URL_STATION_UPDATE = environment.apiEndpoint + "/station";
constructor(private http: Http) {}
getAvailabilityData(param) {
let body = JSON.stringify(param);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(this.URL_DATA_AVAILABILITY, body, options)
.map(response => {
{ return response.json()};
})
.catch((res: Response) => this.handleError(res));
}
getAvailabilityData2(param) {
let stations_id: any = {};
stations_id["ids"] = param;
let body = JSON.stringify(stations_id);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(this.URL_DATA_AVAILABILITY2, body, options)
.map(response => {
{ return response.json()};
})
.catch((res: Response) => this.handleError(res));
}
getAvailabilityData3(param, net_id) {
let stations_id: any = {};
stations_id["ids"] = param;
let my_params: any = {};
my_params["ids"] = stations_id["ids"];
my_params["net_id"] = net_id;
let body = JSON.stringify(my_params);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(this.URL_DATA_AVAILABILITY3, body, options)
.map(response => {
{ return response.json()};
})
.catch((res: Response) => this.handleError(res));
}
getAvailabilityDataScrolling(param) {
let stations_id: any = {};
stations_id["ids"] = param;
let body = JSON.stringify(stations_id);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(this.URL_DATA_AVAILABILITY_SCROLLING, body, options)
.map(response => {
{ return response.json()};
})
.catch((res: Response) => this.handleError(res));
}
getStations_with_networks() {
return this.http.get(this.URL_STATIONS_WITH_NETWORKS)
.map(response => {
{ return response.json()};
})
.catch(error => Observable.throw("Error"));
}
getStations() {
console.log("StationService. Eseguo: " + this.URL_STATION_LIST)
return this.http.get(this.URL_STATION_LIST)
.map(response => {
{ return <Station[]> response.json().data };
})
.catch((res: Response) => this.handleError(res));
}
updateStation(station) {
let body = JSON.stringify(station);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
console.log("call " + this.URL_STATION_UPDATE + " service")
return this.http.post(this.URL_STATION_UPDATE, body, options)
.map(response => {
{ return <Station> response.json().data };
})
.catch((res: Response) => this.handleError(res));
}
private handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg);
console.error("error.text=" + error.text());
return Observable.throw(errMsg);
}
}
<!--The content below is only a placeholder and can be replaced.-->
<!--
<app-menu>
<app-menu-header>
Titolo Menu
</app-menu-header>
</app-menu>
aaa
-->
<div class="container">
<router-outlet></router-outlet>
</div>
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
}));
});
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
// title = 'My Angular 2 app works!';
}
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
import { MenuComponent } from './menu.component';
import { WeatherComponent } from './weather/weather.component';
import { CurrencyComponent } from './currency/currency.component';
import { MovieComponent } from './movie/movie.component';
import { CONST_ROUTING } from './app.routing';
import { SharedService } from "./shared.service";
import { MonitorComponent } from './monitor/monitor.component';
import { Injectable, Pipe, PipeTransform } from '@angular/core';
//import { NguiOverlayModule } from '@ngui/overlay';
import { Ng2PopupModule } from 'ng2-popup';
import { ModalComponent } from './_directives/index';
import { ModalService } from './_services/index';
import { NetworkComponent } from './network/network.component';
import { NetworksComponent } from './networks/networks.component';
import { InputTextModule } from 'primeng/inputtext';
import { ButtonModule } from 'primeng/button';
import { TableModule } from 'primeng/table';
import { DataTableModule } from 'primeng/datatable';
import { DialogModule } from 'primeng/dialog';
import { DataAvailabilityComponent } from './data-availability/data-availability.component';
import { ZingChartComponent } from './zing-chart/zing-chart.component';
import {NgxChartsModule} from '@swimlane/ngx-charts';
import { DownloadIndicatorComponent } from './download-indicator/download-indicator.component';
import { StationsSearchComponent } from './stations-search/stations-search.component';
import { TypeaheadModule } from 'ngx-bootstrap';
import { StationsComponent } from './stations/stations.component';
//import { ModalModule} from 'angular2-modal';
//import { BootstrapModalModule } from 'angular2-modal/plugins/bootstrap';
@Pipe({
name: 'SearchFilterList'
})
@Injectable()
export class SearchFilterListPipe implements PipeTransform {
transform(items: any[], field: string, value: string): any[] {
if (!items) return [];
return items.filter(it => it[field] == value);
}
}
@Pipe({
name: 'SearchFilterDict'
})
@Injectable()
export class SearchFilterDictPipe implements PipeTransform {
transform(items: {}, field: string, value: string): {} {
if (!items) return {};
//var filtered_key_list: string[];
//filtered_key_list = Object.keys(items).filter(key => items[key][field] == value);
//filtered_key_list = Object.keys(items);
//return filtered_key_list.map(function(key){key => items[key]});
//return items;
//return {'ics': 'ipslon'}
//var pippo: {};
//pippo = { eee: 'udddno' };
//pippo = items;
//delete pippo['keyTwo'];
//console.log("bbbbbbbbbbbbbbbbbbbbbbbb");
//return pippo;
}
}
// patch
//import { JsonpModule } from '@angular/http';
@NgModule({
declarations: [
AppComponent,
WeatherComponent,
CurrencyComponent,
MovieComponent,
MonitorComponent,
SearchFilterListPipe,
SearchFilterDictPipe,
ModalComponent,
NetworkComponent,
NetworksComponent,
DataAvailabilityComponent,
ZingChartComponent,
StationsSearchComponent,
DownloadIndicatorComponent,
StationsComponent
],
imports: [
// [JsonpModule],
BrowserModule,
FormsModule,
HttpModule,
CONST_ROUTING,
Ng2PopupModule,
TableModule,
InputTextModule,
DialogModule,
ButtonModule,
NgxChartsModule,
TypeaheadModule.forRoot()
],
providers: [
SharedService,
ModalService
],
bootstrap: [AppComponent],
schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
})
export class AppModule { }
import { Routes, RouterModule } from '@angular/router';
import { CurrencyComponent } from "./currency/currency.component";
import { WeatherComponent } from "./weather/weather.component";
import { MovieComponent } from "./movie/movie.component";
import { MonitorComponent } from "./monitor/monitor.component";
import { NetworkComponent } from "./network/network.component";
import { NetworksComponent } from "./networks/networks.component";
import { DataAvailabilityComponent } from './data-availability/data-availability.component';
const MAINMENU_ROUTES: Routes = [
//full : makes sure the path is absolute path
{ path: '', redirectTo: '/monitor', pathMatch: 'full' },
{ path: 'weather', component: WeatherComponent },
{ path: 'movie', component: MovieComponent },
{ path: 'currency', component: CurrencyComponent },
{ path: 'monitor', component: MonitorComponent },
{ path: 'network/:id', component: NetworkComponent },
{ path: 'networks', component: NetworksComponent },
// { path: 'availability/:id', component: DataAvailabilityComponent },
{ path: 'availability2', component: DataAvailabilityComponent }
];
export const CONST_ROUTING = RouterModule.forRoot(MAINMENU_ROUTES);
<h2>Currency Exchange Rates</h2>
<div class="col-md-8 col-md-offset-2">
<div class="form-group">
<input type="text" [(ngModel)]="id_currency" (change)="callCurrencyService()" class="form-control" placeholder="Enter Currency Symbol. Example: GBP(,AUD,INR)...">
<br><br>
<h3>Rate Details</h3>
<br>
<p class="well lead">Exchange rate relative to Euro in a JSON format: : {{ this.my_result }} </p>
<p class="text-info">Total # of all the service requests including Weather, Movie, and Currency is :
<span class="badge">{{this._sharedService.totReqsMade}}</span>
</p>
</div>
</div>
\ No newline at end of file
import { Component, OnInit } from '@angular/core';
import { SharedService } from "./../shared.service";
@Component({
selector: 'app-currency',
templateUrl: './currency.component.html',
styles: []
})
export class CurrencyComponent implements OnInit {
id_currency: string = "";
my_result: any;
constructor(private _sharedService: SharedService) {
}
ngOnInit() {
}
callCurrencyService() {
this._sharedService.getCurrencyExchRate(this.id_currency.toUpperCase())
.subscribe(
lstresult => {
this.my_result = JSON.stringify(lstresult);
},
error => {
console.log("Error. The callCurrencyService result JSON value is as follows:");
console.log(error);
}
);
}
}
<div *ngIf="chart !== undefined; then content else other_content"></div>
<ng-template #content>
<app-zing-chart [chart]="chart"></app-zing-chart>
</ng-template>
<ng-template #other_content>loading ...</ng-template>
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DataAvailabilityComponent } from './data-availability.component';
describe('DataAvailabilityComponent', () => {
let component: DataAvailabilityComponent;
let fixture: ComponentFixture<DataAvailabilityComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ DataAvailabilityComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DataAvailabilityComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
//import { Component, OnInit, Input } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { Chart } from '../zing-chart/chart.model';
import { StationService} from '../_services/stationservice';
import { ActivatedRoute } from '@angular/router';
//import { ChangeDetectorRef } from '@angular/core';
@Component({
selector: 'app-data-availability',
templateUrl: './data-availability.component.html',
styles: [],
providers: [StationService]
})
export class DataAvailabilityComponent implements OnInit {
//@Input() stations_id: any[];
chart: Chart = undefined;
//id: number ;
//private sub: any;
ids: any[];
net_id: number;
//pippo: string =' this.chart = new Chart( { id: "chart-1", data: { type: "line", backgroundColor: "2C2C39", title: { text: "Time Series Data with null values", adjustLayout: true, fontColor: "#E3E3E5", marginTop: 1 }, "legend":{ "max-items":5, "overflow":"scroll", "layout":"5x1", "scroll":{ "bar":{ "background-color":"#ffe6e6", "border-left":"1px solid red", "border-right":"1px solid red", "border-top":"1px solid red", "border-bottom":"1px solid red", }, "handle":{ "background-color":"#ffe6e6", "border-left":"2px solid red", "border-right":"2px solid red", "border-top":"2px solid red", "border-bottom":"2px solid red", "border-radius":"15px" } }, "highlight-plot":true, "x":"80%", "y":"15%" }, plotarea: { "margin-top":"1%", "margin-right":"30%" }, "plot": { "aspect": "line", "lineWidth": 2, "marker":{ "visible":false }, "tooltip":{ "visible":false } }, scaleX: { lineColor: "#E3E3E5", zooming: true, zoomTo: [0, 25], minValue: 1569578800000, step: "day", item: { fontColor: "#E3E3E5" }, transform: { type: "date", all: "%Y %M %d" }, }, scaleY: { minorTicks: 100, lineColor: "#E3E3E5", tick: { lineColor: "#000000" }, minorTick: { lineColor: "#E3E3E5" }, minorGuide: { visible: true, lineWidth: 2, lineColor: "#E3E3E5", alpha: 0.7, lineStyle: "dashed" }, guide: { lineStyle: "dashed" }, item: { fontColor: "#000000" } }, tooltip: { borderWidth: 1, borderRadius: 1 }, preview: { borderColor: "#E3E3E5", mask: { backgroundColor: "#E3E3E5" } }, crosshairX: { plotLabel: { multiple: true, borderRadius: 3, "visible":false }, scaleLabel: { backgroundColor: "#53535e", borderRadius: 300 }, marker: { size: 7, alpha: 0.5 } }, shapes: [{ type: "rectangle", id: "view_all", height: "10px", width: "75px", borderColor: "#E3E3E5", borderWidth: 2, borderRadius: 3, x: "85%", y: "10%", backgroundColor: "#53535e", cursor: "hand", label: { text: "view all", fontColor: "#E3E3E5", fontSize: 10, bold: true } }], series: [ { values: [1, 1, 1, 1, 1,1, null, null, null, null, null, 1, 1], lineColor: "red", name: "aaa", "legend-text":"stazione 1", "marker": { "type": "line", "background-color": "#0066cc" } }, { values: [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], lineColor: "green", name: "aaa", marker: { backgroundColor: "#E34247" }, "legend-text":"stazione 1" }, { values: [null, null, 3, 3, null, 3, null, 3, null, null, null, 3, 3], lineColor: "yellow", name: "aaa", marker: { backgroundColor: "#E34247" }, "legend-text":"stazione 1" }, { values: [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, null, null], lineColor: "blue", name: "aaa", marker: { backgroundColor: "#E34247" }, "legend-text":"stazione 2" } ] }, height: 450 }) ';
//constructor (private stationService: StationService, private route: ActivatedRoute) {
constructor (private stationService: StationService, private activatedRoute: ActivatedRoute) {
//this.chart = new Chart(JSON.parse(this.pippo))
}
ngOnInit() {
this.activatedRoute.queryParams
//.filter(params => params.stations_id)
.filter(params => params.ids)
.subscribe(params => {
console.log(params); // {order: "popular"}
this.ids = params.ids;
this.net_id = params.net_id;
//console.log("aaaaaaaaaaaaaaaaaaaa:" + params.net_id); // popular
//console.log(this.ids); // popular
});
//this.sub = this.activatedRoute.params.subscribe(params => {
// this.id = +params['id']; // (+) converts string 'id' to a number
//});
}
/*
ngOnInit() {
console.log("Hello ngOnInit");
let pippo: string = JSON.stringify(this.activatedRoute.queryParamMap)
console.log("aaaaaaaaaaaaaaaaaaaaa" + pippo);
let y: {} = this.activatedRoute.queryParamMap;
let ciao: string = JSON.stringify(y['destination']['_value']['stations_id'])
console.log("wwwwwwwwwwwwwwwwwwww: " + ciao);
const routeParams = this.activatedRoute.snapshot.params;
let pluto: string = JSON.stringify(routeParams._value)
console.log("bbbbbbbbbbbbbbbbb" + pluto);
let xxx: {} = this.activatedRoute.snapshot.queryParamMap['destination']
let nonna: string = JSON.stringify(xxx)
console.log("cccccccccc: " + nonna);
// let token = null;
// this.activatedRoute.queryParamMap.subscribe((next : ParamMap) => {
// token = next.get("token")
// if (token) {
// console.log(token);
// } else {
// console.log("no token given in url");
// }
//});
//this.sub = this.route.params.subscribe(params => {
//this.id = +params['id']; // (+) converts string 'id' to a number
//});
}
*/
ngAfterViewInit() {
//alert(this.stations_id[0] + ', ' + this.stations_id[1] + ', ' + this.stations_id[2] )
this.callGetAvailabilityData()
//this.chart = undefined
}
/*