Commit 10062fa6 authored by Sergio Bruni's avatar Sergio Bruni

first

parent 0f10c9e9
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
This diff is collapsed.
......@@ -42,7 +42,9 @@ export class NetworkService {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.put(this.URL_NET_UPDATE + '/' + network.id, body, options)
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() };
})
......
......@@ -6,11 +6,12 @@ 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";
......@@ -18,6 +19,8 @@ export class StationService {
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) {}
......@@ -47,10 +50,15 @@ export class StationService {
.catch((res: Response) => this.handleError(res));
}
getAvailabilityData3(param) {
getAvailabilityData3(param, net_id) {
let stations_id: any = {};
stations_id["ids"] = param;
let body = JSON.stringify(stations_id);
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 });
......@@ -83,6 +91,29 @@ export class StationService {
.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';
......
......@@ -30,6 +30,7 @@ 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';
......@@ -90,7 +91,8 @@ export class SearchFilterDictPipe implements PipeTransform {
DataAvailabilityComponent,
ZingChartComponent,
StationsSearchComponent,
DownloadIndicatorComponent
DownloadIndicatorComponent,
StationsComponent
],
imports: [
// [JsonpModule],
......
......@@ -17,6 +17,7 @@ export class DataAvailabilityComponent implements OnInit {
//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 }) ';
......@@ -33,7 +34,9 @@ export class DataAvailabilityComponent implements OnInit {
console.log(params); // {order: "popular"}
this.ids = params.ids;
console.log(this.ids); // popular
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 => {
......@@ -93,9 +96,9 @@ export class DataAvailabilityComponent implements OnInit {
//pippo["from"] = "2018-01-01";
//pippo["to"] = "2018-02-01";
//pippo["ids"] = [this.id];
//console.log("sergio: this.ids:" + this.ids + ", this.net_id: " + this.net_id);
//this.stationService.getAvailabilityDataScrolling(this.ids)
this.stationService.getAvailabilityData3(this.ids)
this.stationService.getAvailabilityData3(this.ids, this.net_id)
.subscribe(
lstresult => {
this.chart = lstresult;
......
......@@ -2,5 +2,9 @@ export interface Station {
id?: number;
code?: string;
name?: string;
description?: string;
monument_num?: number;
receiver_num?: number;
country_code?: string;
selected?;
}
......@@ -23,7 +23,7 @@ export class DownloadIndicatorComponent implements OnInit {
//alert('aaaa <' + this.id_network + '>')
//Object.assign(this, {multi})
//this.multi = this.pippo
this.callGetADownloadIndicator()
// RIPRISTINARE this.callGetADownloadIndicator()
}
multi: any[];
......@@ -50,30 +50,12 @@ export class DownloadIndicatorComponent implements OnInit {
ngAfterViewInit() {
//alert('id_network: <' + this.id_network + '>')
// Object.assign(this, {multi})
//this.callGetADownloadIndicator()
this.callGetADownloadIndicator()
//this.chart = undefined
}
/*
ngAfterViewInit() {
this.interval = setInterval(() => {
//multi[0]["series"][0]["value"]= 10
// Object.assign(this, {multi})
//this.multi = this.pippo
}, 5000);
}
*/
callGetADownloadIndicator() {
//this.pippo = multi
//alert('id_network: <' + this.id_network + '>')
//Object.assign(this, {multi})
// this.multi = this.pippo
this.networkService.getDownloadIndicator(this.id_network)
this.networkService.getDownloadIndicator(this.id_network)
.subscribe(
lstresult => {
this.multi = lstresult;
......
......@@ -5,14 +5,14 @@
<ul class="tab-slider--tabs">
<li class="tab-slider--trigger" [class.active]="viewMode == 'tab-monitor'" rel="tab-monitor" (click)="viewMode ='tab-monitor'">Monitor</li>
<li class="tab-slider--trigger" [class.active]="viewMode == 'tab-data'" rel="tab-data" (click)="viewMode ='tab-data'">Networks</li>
<li class="tab-slider--trigger" [class.active]="viewMode == 'tab-data'" rel="tab-data" (click)="viewMode ='tab-data'">Networks</li>
<li class="tab-slider--trigger" [class.active]="viewMode == 'tab-stations'" rel="tab-station" (click)="viewMode ='tab-stations'">Stations</li>
</ul>
</div>
<div class="tab-slider--container" [ngSwitch]="viewMode">
<div id="tab-monitor" class="tab-slider--body" *ngSwitchCase="'tab-monitor'">
<!-- <div class="col-md-8 col-md-offset-2">
<!-- <div class="col-md-8 col-md-offset-2">
<div class="form-group">
......@@ -36,7 +36,7 @@
<app-stations-search></app-stations-search>
<!-- BOTTONE DI RICERCA
<!-- BOTTONE DI RICERCA *
<div class="form-group">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
......@@ -140,14 +140,22 @@
<div id="tab-data" class="tab-slider--body" *ngSwitchCase="'tab-data'">
<app-networks></app-networks>
<app-networks></app-networks>
</div>
<div id="tab-stations" class="tab-slider--body" *ngSwitchCase="'tab-stations'">
<app-stations></app-stations>
</div>
</div>
<script>
onRowClick(event, id){
onRowClick(event, id)
{
// --
console.log(event.target.outerText, id);
}
</script>
......
......@@ -50,6 +50,7 @@ export class MonitorComponent implements OnInit {
this._sharedService.NetworkList(this.id_finto)
.subscribe(
lstresult => {
console.log("NetworkList eseguita")
if (lstresult.error != "") {
this.openPopup(lstresult.error);
return;
......
......@@ -5,12 +5,11 @@
<table class="table table-hover">
<thead>
<th>
</th>
<th>
</th>
<th></th>
<th></th>
<th>Code</th>
<th>Name</th>
<th>Position</th>
</thead>
<tbody>
<tr>
......@@ -24,6 +23,7 @@
</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr *ngFor="let item of this.stationList">
......@@ -39,11 +39,15 @@
</button>
</td>
<td>
{{item.code}}
{{item.marker}}{{item.monument_num}}{{item.receiver_num}}{{item.country_code}}
</td>
<td>
{{item.name}}
</td>
<td>
<label>35.654</label>
<label>13.656</label>
</td>
</tr>
</tbody>
</table>
......
......@@ -49,9 +49,13 @@ export class NetworkComponent implements OnInit {
let stations_id: any = {};
stations_id["ids"] = [id];
let params: any = {};
params["net_id"] = this.network.id;
params["ids"] = stations_id["ids"];
let navigationExtras: NavigationExtras = {
queryParams:stations_id
queryParams:params
//queryParams:stations_id
};
//this.router.navigate(['/availability/1'], navigationExtras);
......@@ -80,6 +84,7 @@ export class NetworkComponent implements OnInit {
let stations_id: any = {};
stations_id["ids"] = [];
if (this.checkIfAllDeselected() == true) {
alert("Select at least one station")
return;
......@@ -92,8 +97,14 @@ export class NetworkComponent implements OnInit {
}
}
let params: any = {};
params["ids"] = [];
params["net_id"] = this.network.id;
params["ids"] = stations_id["ids"];
let navigationExtras: NavigationExtras = {
queryParams:stations_id
queryParams:params
//queryParams:stations_id
};
this.router.navigate(['/availability2'], navigationExtras);
......
......@@ -21,6 +21,7 @@ export class SharedService {
findMovieURL1 = "http://www.omdbapi.com/?t=";
findMovieURL2 = "&y=&plot=short&r=json";
NetworkListURL = environment.apiEndpoint + "/netlist";
//NetworkListURL = 'http://'+window.location.hostname + ":4300/netlist";
//StationListURL = environment.apiEndpoint + "/stationlist/";
getNetLogURL = environment.apiEndpoint + "/getNetLog";
//NetworkListURL = "http://192.168.204.128:8080/users/2";
......
This diff is collapsed.
{
"database": {
"active": "true"
},
"alert_mailing_list_save": [
"brunisergio@gmail.com",
"adriano.cavaliere@ingv.it",
"enrico.serpelloni@ingv.it",
"roberto.devoti@ingv.it"
],
"alert_mailing_list": [
"brunisergio@gmail.com"
],
"rest_services_url": "http://localhost:4300",
"refresh_stations_list": {
"active": "true",
"org": "http://gat.bo.ingv.it",
"path_name": "rinex/networks",
"user" : "gnssdata",
"password" : "nasspritz"
},
"download": {
"file_name": "__STATION_CODE_LOWER_CASE____DOY__0.__YY__d",
"path_name": "/pub/rinex/__CCYY__/__DOY__",
"ftp_anonymous_user" : "anonymous",
"ftp_anonymous_password" : "serpelloni@bo.ingv.it"
},
"schedule": {
"mins": 15,
"hours": 19
},
"log_path": "/home/sergio/GPSdata/log",
"data_archive_NETS": "/mnt/data/archive/rinex/CGPS/NETS",
"data_archive_YEARS": "/mnt/data/archive/rinex/CGPS/YEARS",
"data_archive_STN_LIST": "/mnt/data/archive/rinex/CGPS/STATIONS_LIST"
}
This diff is collapsed.
This diff is collapsed.
import sys, os, time, atexit
from signal import SIGTERM
class Daemon:
"""
A generic daemon class.
Usage: subclass the Daemon class and override the run() method
"""
# ATTENZIONE, ATTIVANDO QUESTO BLOCCO REDIRIGE SUL /DEV/NULL, QUINDI NON SCRIVE NULLA SU TERMINALE
#-----------------------------
def __init__(self, nNET, CGPSconf):
pass # prende i parametri passati su __init__ di class daemEPOS(Daemon):
# self.stdin = stdin
# self.stdout = stdout
# self.stderr = stderr
def daemonize(self):
"""
do the UNIX double-fork magic, see Stevens' "Advanced
Programming in the UNIX Environment" for details (ISBN 0201563177)
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
"""
try:
pid = os.fork()
if pid > 0:
# exit first parent
sys.exit(0)
except OSError, e:
sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
# decouple from parent environment
# os.chdir("/") # ************** ATTENZIONE 1: questo impone la directory di lavoro, se non eseguito usa quella corrente del programma py
os.setsid() # set_session_id()
os.umask(0) # ************** ATTENZIONE 2: con (0) imposto i privilegi rw-rw-rw- *****************
# do second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent
sys.exit(0)
except OSError, e:
sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
# ATTENZIONE, ATTIVANDO QUESTO BLOCCO REDIRIGE SUL /DEV/NULL, QUINDI NON SCRIVE NULLA SU TERMINALE
# redirect standard file descriptors
# sys.stdout.flush()
# sys.stderr.flush()
# si = file(self.stdin, 'r')
# so = file(self.stdout, 'a+')
# se = file(self.stderr, 'a+', 0)
# os.dup2(si.fileno(), sys.stdin.fileno())
# os.dup2(so.fileno(), sys.stdout.fileno())