argos-ruby 1.1.3.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -13
- data/Gemfile +1 -4
- data/README.md +28 -39
- data/argos-ruby.gemspec +1 -1
- data/bin/argos-soap +6 -4
- data/lib/argos/_xsd/argos-data.xsd +158 -0
- data/lib/argos/_xslt/argos-json.xslt +81 -0
- data/lib/argos/download.rb +51 -13
- data/lib/argos/soap.rb +25 -7
- data/lib/argos/soap_command.rb +7 -8
- data/lib/argos.rb +1 -1
- data/spec/argos/_soap/csvResponse.xml +46 -0
- data/spec/argos/_soap/getObsXml.xotm +13 -0
- data/spec/argos/_soap/getStreamXml.xml +1 -0
- data/spec/argos/_soap/getStreamXml.xom +13 -0
- data/spec/argos/_soap/getStreamXml.xop +13 -0
- data/spec/argos/_soap/getXml.xml +1896 -1
- data/spec/argos/_soap/getXml.xop +8 -0
- data/spec/argos/_soap/json_from_getCsv.json +1 -0
- data/spec/argos/_soap/observationResonse.xml +13 -0
- data/spec/argos/_soap/xmlResponse.xml +393 -0
- data/spec/argos/ascii_spec.rb +2 -2
- data/spec/argos/soap_spec.rb +3 -7
- data/spec/spec_helper.rb +6 -2
- metadata +22 -10
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
ZjNhYTliZDM2ZWNjOTg4OWFlMzEyYjZiMmYzMjVkZDY0MDc4MmUzMA==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c8fc28465dbe802bf2961bea1d3913654d4969b9
|
4
|
+
data.tar.gz: fb761e384ab9d9761bd601c641fcbd87e0d2525a
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
ZTVmZWM5ZTc3ZmM0OWNkZDE2ZTNiZGI0ZTc2NzFmY2UzOTM5ZGRjYWYxOGM4
|
11
|
-
NmVmOWU3ODAxZDdlOWVkNmJlODg3MDVhNGJmMWQ0NTA1NzJlZjY=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MjlkNmM4MDhmMDZhNGIwY2FlNWU2MTYxNmQ1MWJlMTUxNDEyZDYxMjY0MThh
|
14
|
-
MmZjNGU3NTgyOGE4MjZhNTUwNGVlZDI1OTYyYjEwYjQ3MmQxMWIxMWE0NTQz
|
15
|
-
NjQyYWI4Y2EwNDFjMWUwNzg1MjEyMjExZGUzOWZjYTdiMzQ3NGI=
|
6
|
+
metadata.gz: 74ac8e53f830ec8119d0339e9ea12c98f09640baf7992b1e3288c92d23f80ae13198a0bf32206ff0b047b2610c48403271d3f54db44145022f720f07297678ea
|
7
|
+
data.tar.gz: c4894a56bdae7a75c581f3dff27da1c2c91a88a1a67f58745c2755a6ba6bc5cbd7731d10d747715d9adfe12b9dfbaa3dbf4bc9eefbab734ca897583805551106
|
data/Gemfile
CHANGED
@@ -4,12 +4,9 @@ gem "yajl-ruby", git: "git://github.com/brianmario/yajl-ruby.git"
|
|
4
4
|
gem "uuidtools"
|
5
5
|
gem "hashie", git: "git://github.com/intridea/hashie.git"
|
6
6
|
#gem "json-schema", git: "git://github.com/hoxworth/json-schema.git"
|
7
|
-
gem "savon", github:
|
7
|
+
gem "savon", github: "savonrb/savon", branch: "version3"
|
8
8
|
|
9
9
|
group :development, :test do
|
10
|
-
gem "thin"
|
11
|
-
gem "shotgun"
|
12
10
|
gem "rspec"
|
13
11
|
gem "simplecov"
|
14
|
-
gem "ruby-prof"
|
15
12
|
end
|
data/README.md
CHANGED
@@ -1,57 +1,46 @@
|
|
1
1
|
# argos-ruby
|
2
2
|
|
3
|
-
|
3
|
+
[argos-ruby](https://github.com/npolar/argos-ruby) contains tools for working with
|
4
|
+
[Argos](http://www.argos-system.org) satellite tracking data and services:
|
4
5
|
|
5
|
-
|
6
|
+
* Parsers for Argos legacy ASCII (DS/DAT and DIAG/DIA files)
|
7
|
+
* SOAP web service client
|
8
|
+
* Web service download tool
|
9
|
+
* JSON conversion from ASCII and XML
|
6
10
|
|
7
|
-
|
8
|
-
```json
|
9
|
-
["getCsv","getStreamXml","getKml","getXml","getXsd","getPlatformList","getObsCsv","getObsXml"]
|
10
|
-
```
|
11
|
-
**All programs**
|
12
|
-
Data from all programs and all platforms are fetched by default
|
13
|
-
|
14
|
-
$ argos-soap --operation=getXml > [getXml.xml](https://github.com/npolar/argos-ruby/blob/master/spec/argos/_soap/getXml.xml)
|
15
|
-
|
16
|
-
$ argos-soap --operation=getXml --format=json > [getXml.json](https://github.com/npolar/argos-ruby/blob/master/spec/argos/_soap/getXml.json)
|
17
|
-
|
18
|
-
$ argos-soap --operation=getKml > [getKml.xml](https://github.com/npolar/argos-ruby/blob/master/spec/argos/_soap/getKml.xml)
|
19
|
-
|
20
|
-
$ argos-soap --operation=getCsv --format=text > [getCsv.csv](https://github.com/npolar/argos-ruby/blob/master/spec/argos/_soap/getCsv.csv)
|
21
|
-
|
22
|
-
**Select program(s)**
|
23
|
-
argos-soap --operation getXml --programNumber 9660
|
24
|
-
|
25
|
-
**Select platformId(s)**
|
26
|
-
$ argos-soap --operation getXml --platformId 81308
|
11
|
+
Developed by staff at the [Norwegian Polar Data Centre](http://data.npolar.no), [Norwegian Polar Institute](http://npolar.no).
|
27
12
|
|
13
|
+
## Webservice
|
28
14
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
## Argos file parsing
|
35
|
-
### DS/DIAG to JSON
|
36
|
-
$ #
|
15
|
+
```sh
|
16
|
+
$ argos-soap --download archive/tracking/CLS --username=USERNAME --password=PASSWORD --debug
|
17
|
+
$ argos-soap -o getXml --username=USERNAME --password=PASSWORD
|
18
|
+
```
|
19
|
+
See [argos-soap](https://github.com/npolar/argos-ruby/wiki/argos-soap) for more usage examples.
|
37
20
|
|
38
|
-
|
21
|
+
### Legacy file parsing
|
39
22
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
23
|
+
```sh
|
24
|
+
$ argos-ascii spec/argos/_ds/*.DAT
|
25
|
+
$ argos-ascii --action=source "spec/argos/_d*"
|
26
|
+
$ argos-ascii --filter='lambda {|d| d[:program] == 9660 and d[:platform] == 2189 }' spec/argos/_ds/990660_A.DAT
|
27
|
+
```
|
28
|
+
The **source** action provides a metadata summary, list of programs, platforms, etc.
|
44
29
|
|
45
|
-
|
30
|
+
### JSON (via XSLT)
|
31
|
+
```sh
|
32
|
+
$ xsltproc lib/argos/_xslt/argos-json.xslt spec/argos/_soap/getXml.xml
|
33
|
+
```
|
46
34
|
|
47
35
|
## Install
|
36
|
+
```sh
|
48
37
|
$ gem install argos-ruby
|
38
|
+
```
|
49
39
|
|
50
40
|
## Links
|
51
|
-
|
52
41
|
* https://github.com/npolar/api.npolar.no/wiki/Tracking-API-JSON
|
53
42
|
* [Argos User's Manual](http://www.argos-system.org/manual/)
|
54
|
-
* [Argos Web Service Interface Specification v1.
|
43
|
+
* [Argos Web Service Interface Specification v1.4](http://www.argos-system.org/manual/argos_webservices-1_4.pdf)
|
55
44
|
* http://alaska.usgs.gov/science/biology/spatial/
|
56
45
|
* http://gis-lab.info/programs/argos/argos-manual-eng.html
|
57
|
-
|
46
|
+
* [CLS](http://www.cls.fr/welcome_en.html) - operates the Argos system
|
data/argos-ruby.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.summary = %q{Argos satellite tracking library and command-line tools}
|
13
13
|
s.description = %q{Argos (http://www.argos-system.org/) webservice client and Argos legacy file (DS/DAT and DIAG/DIA) parser.}
|
14
14
|
s.license = "GPL-3.0"
|
15
|
-
s.add_development_dependency
|
15
|
+
s.add_development_dependency 'rspec', '~> 3'
|
16
16
|
s.files = `git ls-files`.split("\n")
|
17
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
18
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
data/bin/argos-soap
CHANGED
@@ -4,10 +4,12 @@
|
|
4
4
|
# Ruby-based command line client for Argos' Soap webservice
|
5
5
|
#
|
6
6
|
# For more information:
|
7
|
-
# $
|
7
|
+
# $ argos-soap --help
|
8
8
|
# https://github.com/npolar/argos-ruby/blob/master/README.md
|
9
9
|
|
10
|
-
|
11
|
-
require_relative "../lib/argos
|
10
|
+
Dir.chdir(__dir__) do
|
11
|
+
require_relative "../lib/argos"
|
12
|
+
require_relative "../lib/argos/soap_command"
|
13
|
+
end
|
14
|
+
Argos::SoapCommand.run
|
12
15
|
|
13
|
-
Argos::SoapCommand.run
|
@@ -0,0 +1,158 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
3
|
+
|
4
|
+
<!-- W3C specifications http://www.w3.org/TR/xmlschema-0 -->
|
5
|
+
|
6
|
+
<!-- DATA DECLARATION -->
|
7
|
+
<xs:element name="data">
|
8
|
+
<xs:complexType>
|
9
|
+
<xs:sequence>
|
10
|
+
<xs:element name="program" type="program" minOccurs="0" maxOccurs="unbounded"/>
|
11
|
+
<xs:element name="errors" type="errors" minOccurs="0"/>
|
12
|
+
</xs:sequence>
|
13
|
+
<xs:attribute name="version" type="xs:string"/>
|
14
|
+
</xs:complexType>
|
15
|
+
</xs:element>
|
16
|
+
|
17
|
+
<!-- PROGRAM DECLARATION -->
|
18
|
+
<xs:complexType name="program">
|
19
|
+
<xs:sequence>
|
20
|
+
<xs:element name="programNumber" type="xs:int" minOccurs="0"/>
|
21
|
+
<xs:element name ="platform" type="platform" minOccurs="0" maxOccurs="unbounded"/>
|
22
|
+
</xs:sequence>
|
23
|
+
</xs:complexType>
|
24
|
+
|
25
|
+
<!-- PLATFORM DECLARATION -->
|
26
|
+
<xs:complexType name="platform">
|
27
|
+
<xs:sequence>
|
28
|
+
<xs:element name="platformId" type="xs:int" minOccurs="0"/>
|
29
|
+
<xs:element name="platformType" type="xs:string" minOccurs="0"/>
|
30
|
+
<xs:element name="platformName" type="xs:string" minOccurs="0"/>
|
31
|
+
<xs:element name="platformModel" type="xs:string" minOccurs="0"/>
|
32
|
+
<xs:element name="platformHexId" type="xs:string" minOccurs="0"/>
|
33
|
+
<xs:element name ="satellitePass" type="satellitePass" minOccurs="0" maxOccurs="unbounded"/>
|
34
|
+
</xs:sequence>
|
35
|
+
</xs:complexType>
|
36
|
+
|
37
|
+
<!-- SATELLITE PASS DECLARATION -->
|
38
|
+
<xs:complexType name="satellitePass">
|
39
|
+
<xs:sequence>
|
40
|
+
<xs:element name="satellite" type="xs:string" minOccurs="0"/>
|
41
|
+
<xs:element name="bestMsgDate" type="xs:dateTime" minOccurs="0"/>
|
42
|
+
<!-- unit : second -->
|
43
|
+
<xs:element name="duration" type="xs:int" minOccurs="0"/>
|
44
|
+
<xs:element name="nbMessage" type="xs:int" minOccurs="0"/>
|
45
|
+
<xs:element name="message120" type="xs:int" minOccurs="0"/>
|
46
|
+
<!-- unit : dBm -->
|
47
|
+
<xs:element name="bestLevel" type="xs:int" minOccurs="0"/>
|
48
|
+
<!-- unit : Hertz -->
|
49
|
+
<xs:element name="frequency" type="xs:double" minOccurs="0"/>
|
50
|
+
<xs:element name="location" type="location" minOccurs="0"/>
|
51
|
+
<xs:element name ="message" type="message" minOccurs="0" maxOccurs="unbounded"/>
|
52
|
+
</xs:sequence>
|
53
|
+
</xs:complexType>
|
54
|
+
|
55
|
+
<!-- LOCATION DECLARATION -->
|
56
|
+
<xs:complexType name="location">
|
57
|
+
<xs:sequence>
|
58
|
+
<!-- GMT -->
|
59
|
+
<xs:element name="locationDate" type="xs:dateTime" minOccurs="0"/>
|
60
|
+
<!-- range : -90°..+90° -->
|
61
|
+
<xs:element name="latitude" type="xs:double" minOccurs="0"/>
|
62
|
+
<!-- range : -180°..+180° -->
|
63
|
+
<xs:element name="longitude" type="xs:double" minOccurs="0"/>
|
64
|
+
<!-- unit : meter -->
|
65
|
+
<xs:element name="altitude" type="xs:double" minOccurs="0"/>
|
66
|
+
<xs:element name="locationClass" type="xs:string" minOccurs="0"/>
|
67
|
+
<!-- unit : meter/second -->
|
68
|
+
<xs:element name="gpsSpeed" type="xs:float" minOccurs="0"/>
|
69
|
+
<!-- range : 0°..+360°, clockwise -->
|
70
|
+
<xs:element name="gpsHeading" type="xs:float" minOccurs="0"/>
|
71
|
+
<xs:element name="diagnostic" type="diagnostic" minOccurs="0"/>
|
72
|
+
</xs:sequence>
|
73
|
+
</xs:complexType>
|
74
|
+
|
75
|
+
<!-- DIAGNOSTIC DECLARATION -->
|
76
|
+
<xs:complexType name="diagnostic">
|
77
|
+
<xs:sequence>
|
78
|
+
<!-- range : -90°..+90° -->
|
79
|
+
<xs:element name="latitude2" type="xs:float" minOccurs="0"/>
|
80
|
+
<!-- range : -180°..+180° -->
|
81
|
+
<xs:element name="longitude2" type="xs:float" minOccurs="0"/>
|
82
|
+
<!-- unit : meter -->
|
83
|
+
<xs:element name="altitude2" type="xs:float" minOccurs="0"/>
|
84
|
+
<xs:element name="index" type="xs:int" minOccurs="0"/>
|
85
|
+
<xs:element name="nopc" type="xs:int" minOccurs="0"/>
|
86
|
+
<!-- unit : meter -->
|
87
|
+
<xs:element name="errorRadius" type="xs:float" minOccurs="0"/>
|
88
|
+
<!-- unit : meter -->
|
89
|
+
<xs:element name="semiMajor" type="xs:float" minOccurs="0"/>
|
90
|
+
<!-- unit : meter -->
|
91
|
+
<xs:element name="semiMinor" type="xs:float" minOccurs="0"/>
|
92
|
+
<!-- range 0°..180°, clockwise -->
|
93
|
+
<xs:element name="orientation" type="xs:float" minOccurs="0"/>
|
94
|
+
<xs:element name="hdop" type="xs:string" minOccurs="0"/>
|
95
|
+
</xs:sequence>
|
96
|
+
</xs:complexType>
|
97
|
+
|
98
|
+
<!-- MESSAGE DECLARATION -->
|
99
|
+
<xs:complexType name="message">
|
100
|
+
<xs:sequence>
|
101
|
+
<!-- GMT -->
|
102
|
+
<xs:element name="bestDate" type="xs:dateTime" minOccurs="0"/>
|
103
|
+
<xs:element name="compression" type="xs:int" minOccurs="0"/>
|
104
|
+
<xs:element name ="collect" type="collect" minOccurs="0" maxOccurs="unbounded"/>
|
105
|
+
<xs:element name ="format" type="format" minOccurs="0" maxOccurs="unbounded"/>
|
106
|
+
</xs:sequence>
|
107
|
+
</xs:complexType>
|
108
|
+
|
109
|
+
<!-- COLLECT DECLARATION -->
|
110
|
+
<xs:complexType name="collect">
|
111
|
+
<xs:sequence>
|
112
|
+
<xs:element name="type" type="xs:string" minOccurs="0"/>
|
113
|
+
<xs:element name="alarm" type="xs:string" minOccurs="0"/>
|
114
|
+
<xs:element name="concatenated" type="xs:string" minOccurs="0"/>
|
115
|
+
<!-- GMT -->
|
116
|
+
<xs:element name="date" type="xs:dateTime" minOccurs="0"/>
|
117
|
+
<!-- unit : dBm -->
|
118
|
+
<xs:element name="level" type="xs:float" minOccurs="0"/>
|
119
|
+
<!-- unit : Hertz -->
|
120
|
+
<xs:element name="doppler" type="xs:double" minOccurs="0"/>
|
121
|
+
<xs:element name="rawData" type="xs:string" minOccurs="0"/>
|
122
|
+
</xs:sequence>
|
123
|
+
</xs:complexType>
|
124
|
+
|
125
|
+
|
126
|
+
<!-- FORMAT DECLARATION -->
|
127
|
+
<xs:complexType name="format">
|
128
|
+
<xs:sequence>
|
129
|
+
<xs:element name="formatOrder" type="xs:int" minOccurs="0"/>
|
130
|
+
<xs:element name="formatName" type="xs:string" minOccurs="0"/>
|
131
|
+
<xs:element name ="sensor" type="sensor" minOccurs="0" maxOccurs="unbounded"/>
|
132
|
+
</xs:sequence>
|
133
|
+
</xs:complexType>
|
134
|
+
|
135
|
+
<!-- SENSOR DECLARATION -->
|
136
|
+
<xs:complexType name="sensor">
|
137
|
+
<xs:sequence>
|
138
|
+
<xs:element name="order" type="xs:int" minOccurs="0"/>
|
139
|
+
<xs:element name="name" type="xs:string" minOccurs="0"/>
|
140
|
+
<xs:element name="valueType" type="xs:string" minOccurs="0"/>
|
141
|
+
<xs:element name="value" type="xs:string" minOccurs="0"/>
|
142
|
+
<xs:element name="valueStr" type="xs:string" minOccurs="0"/>
|
143
|
+
</xs:sequence>
|
144
|
+
</xs:complexType>
|
145
|
+
|
146
|
+
|
147
|
+
<!-- ERRORS DECLARATION -->
|
148
|
+
<xs:complexType name="errors">
|
149
|
+
<xs:sequence>
|
150
|
+
<xs:element name ="error" type="xs:string" minOccurs="0" maxOccurs="unbounded">
|
151
|
+
|
152
|
+
</xs:element>
|
153
|
+
</xs:sequence>
|
154
|
+
</xs:complexType>
|
155
|
+
|
156
|
+
</xs:schema>
|
157
|
+
|
158
|
+
|
@@ -0,0 +1,81 @@
|
|
1
|
+
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
2
|
+
<xsl:output omit-xml-declaration="yes" indent="yes"/>
|
3
|
+
<xsl:strip-space elements="*"/>
|
4
|
+
<!--
|
5
|
+
Transform Argos data XML to Tracking JSON (http://api.npolar.no/schema/tracking)
|
6
|
+
|
7
|
+
Usage:
|
8
|
+
xsltproc argos-json.xslt argos.xml
|
9
|
+
|
10
|
+
xsltproc argos-json.xslt - -stringparam filename "argos-2014-06-11-platform-129654.xml" argos-2014-06-11-platform-129654.xml
|
11
|
+
|
12
|
+
@todo param name system to force gps on known gps devices?
|
13
|
+
@todo test with errors
|
14
|
+
|
15
|
+
-->
|
16
|
+
<xsl:param name="filename" select="''"/>
|
17
|
+
<xsl:param name="npolar" select="'true'"/>
|
18
|
+
|
19
|
+
|
20
|
+
<xsl:template match="/">
|
21
|
+
[<xsl:for-each select="/data[number(@version) < 2]/program/platform/satellitePass/message">
|
22
|
+
|
23
|
+
<xsl:variable name="programNumber" select="ancestor::program/programNumber" />
|
24
|
+
<xsl:variable name="platform" select="ancestor::program/platform" />
|
25
|
+
<xsl:variable name="satellitePass" select="parent::satellitePass" />
|
26
|
+
<xsl:variable name="location" select="$satellitePass/location" />
|
27
|
+
|
28
|
+
{ "program": "<xsl:value-of select="$programNumber"/>",
|
29
|
+
"platform": "<xsl:value-of select="$platform/platformId"/>",
|
30
|
+
"platform_type": "<xsl:value-of select="$platform/platformType"/>",
|
31
|
+
"platform_model": "<xsl:value-of select="$platform/platformModel"/>",
|
32
|
+
"platform_name": "<xsl:value-of select="$platform/platformName"/>",
|
33
|
+
"platform_id": "<xsl:value-of select="$platform/platformHexId"/>",
|
34
|
+
"latitude": <xsl:choose><xsl:when test="number($location/latitude) = $location/latitude"><xsl:value-of select="$location/latitude"/></xsl:when><xsl:otherwise>null</xsl:otherwise></xsl:choose>,
|
35
|
+
"longitude": <xsl:choose><xsl:when test="number($location/longitude) = $location/longitude"><xsl:value-of select="$location/longitude"/></xsl:when><xsl:otherwise>null</xsl:otherwise></xsl:choose>,
|
36
|
+
"altitude": <xsl:choose><xsl:when test="number($location/altitude) = $location/altitude"><xsl:value-of select="$location/altitude"/></xsl:when><xsl:otherwise>null</xsl:otherwise></xsl:choose>,
|
37
|
+
"measured": "<xsl:value-of select="$satellitePass/bestMsgDate"/>",
|
38
|
+
"satellite": "<xsl:value-of select="$satellitePass/satellite"/>",
|
39
|
+
"duration": <xsl:value-of select="$satellitePass/duration"/>,
|
40
|
+
"messages": <xsl:value-of select="$satellitePass/nbMessage"/>,
|
41
|
+
"messages_120dB": <xsl:choose><xsl:when test="number($satellitePass/message120) = $satellitePass/message120"><xsl:value-of select="$satellitePass/message120"/></xsl:when><xsl:otherwise>null</xsl:otherwise></xsl:choose>,
|
42
|
+
"best_level": <xsl:choose><xsl:when test="number($satellitePass/bestLevel) = $satellitePass/bestLevel"><xsl:value-of select="$satellitePass/bestLevel"/></xsl:when><xsl:otherwise>null</xsl:otherwise></xsl:choose>,
|
43
|
+
"frequency": <xsl:choose><xsl:when test="number($satellitePass/frequency) = $satellitePass/frequency"><xsl:value-of select="$satellitePass/frequency"/></xsl:when><xsl:otherwise>null</xsl:otherwise></xsl:choose>,
|
44
|
+
"positioned": <xsl:choose><xsl:when test="$location/locationDate != ''">"<xsl:value-of select="$location/locationDate"/>"</xsl:when><xsl:otherwise>null</xsl:otherwise></xsl:choose>,
|
45
|
+
"lc": <xsl:choose><xsl:when test="$location/locationClass != ''">"<xsl:value-of select="$location/locationClass"/>"</xsl:when><xsl:otherwise>null</xsl:otherwise></xsl:choose>,<xsl:choose><xsl:when test="$location/diagnostic">
|
46
|
+
"lc_index": <xsl:choose><xsl:when test="number($location/diagnostic/index) = $location/diagnostic/index"><xsl:value-of select="$location/diagnostic/index"/></xsl:when><xsl:otherwise>null</xsl:otherwise></xsl:choose>,
|
47
|
+
"latitude2": <xsl:value-of select="$location/diagnostic/latitude2"/>,
|
48
|
+
"longitude2": <xsl:value-of select="$location/diagnostic/longitude2"/>,
|
49
|
+
"altitude2": <xsl:value-of select="$location/diagnostic/altitude2"/>,
|
50
|
+
"nopc": <xsl:value-of select="$location/diagnostic/nopc"/>,
|
51
|
+
"error_radius": <xsl:value-of select="$location/diagnostic/errorRadius"/>,
|
52
|
+
"semi_major": <xsl:value-of select="$location/diagnostic/semiMajor"/>,
|
53
|
+
"semi_minor": <xsl:value-of select="$location/diagnostic/semiMinor"/>,
|
54
|
+
"speed": <xsl:choose><xsl:when test="number($location/diagnostic/gpsSpeed) = $location/diagnostic/gpsSpeed"><xsl:value-of select="$location/diagnostic/gpsSpeed"/></xsl:when><xsl:otherwise>null</xsl:otherwise></xsl:choose>,
|
55
|
+
"heading": <xsl:choose><xsl:when test="number($location/diagnostic/gpsHeading) = $location/diagnostic/gpsHeading"><xsl:value-of select="$location/diagnostic/gpsHeading"/></xsl:when><xsl:otherwise>null</xsl:otherwise></xsl:choose>,
|
56
|
+
"orientation": <xsl:value-of select="$location/diagnostic/orientation"/>,
|
57
|
+
"hdop": <xsl:value-of select="$location/diagnostic/hdop"/>,</xsl:when></xsl:choose>
|
58
|
+
"row": <xsl:value-of select="position()"/>,
|
59
|
+
"total": <xsl:value-of select="count(//message)"/>,
|
60
|
+
"file": "<xsl:value-of select="$filename"/>",
|
61
|
+
"identical": <xsl:value-of select="compression"/>,
|
62
|
+
"sensor_data": [<xsl:for-each select="format/sensor/value">"<xsl:value-of select="."/>"<xsl:choose><xsl:when test="position() < last()">,</xsl:when></xsl:choose></xsl:for-each>],
|
63
|
+
"sensor_hex": "<xsl:value-of select="collect/rawData"/>",
|
64
|
+
"sensor": [<xsl:for-each select="format/sensor">{"name": "<xsl:value-of select="name"/>", "value": "<xsl:value-of select="value|valueStr"/>", "value_type": "<xsl:value-of select="valueType"/>", "order": <xsl:value-of select="order"/> }<xsl:choose><xsl:when test="position() < last()">, </xsl:when></xsl:choose></xsl:for-each>],
|
65
|
+
"doppler": <xsl:value-of select="collect/doppler"/>,
|
66
|
+
"level": <xsl:value-of select="collect/level"/>,
|
67
|
+
"collects": <xsl:value-of select="count(collect)"/>,
|
68
|
+
"formats": <xsl:value-of select="count(format)"/>,
|
69
|
+
"collect": [<xsl:for-each select="collect">{ "level": <xsl:value-of select="level"/>, "type": "<xsl:value-of select="type"/>", "alarm": "<xsl:value-of select="alarm"/>", "concatenated": "<xsl:value-of select="concatenated"/>", "hex": "<xsl:value-of select="rawData"/>", "doppler": <xsl:value-of select="doppler"/>, "measured": "<xsl:value-of select="date"/>" }<xsl:choose><xsl:when test="position() < last()">,</xsl:when></xsl:choose></xsl:for-each>],
|
70
|
+
"format": [<xsl:for-each select="format">{ "order": <xsl:value-of select="formatOrder"/>, "name": "<xsl:value-of select="formatName"/>" }<xsl:choose><xsl:when test="position() < last()">,</xsl:when></xsl:choose></xsl:for-each>]<xsl:choose><xsl:when test="$npolar = 'true'">,
|
71
|
+
"schema": "http://api.npolar.no/schema/tracking",
|
72
|
+
"collection": "tracking",
|
73
|
+
"technology": "argos",
|
74
|
+
"system": "<xsl:choose><xsl:when test="number($location/diagnostic/gpsSpeed) = $location/diagnostic/gpsSpeed">gps</xsl:when><xsl:otherwise>argos</xsl:otherwise></xsl:choose>",
|
75
|
+
"parser": "argos-json.xslt",
|
76
|
+
"type": "xml"</xsl:when></xsl:choose><xsl:choose><xsl:when test="count(/data/errors/error) > 0">,
|
77
|
+
"warn": [<xsl:for-each select="/data/errors/error">"<xsl:value-of select="."/> (argos webservice error code <xsl:value-of select="@code"/>)"<xsl:choose><xsl:when test="position() < last()">,</xsl:when></xsl:choose></xsl:for-each>]</xsl:when></xsl:choose>}<xsl:choose><xsl:when test="position() < last()">,</xsl:when></xsl:choose>
|
78
|
+
</xsl:for-each>]
|
79
|
+
</xsl:template>
|
80
|
+
|
81
|
+
</xsl:stylesheet>
|
data/lib/argos/download.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require "fileutils"
|
2
2
|
require "logger"
|
3
3
|
require "time"
|
4
|
+
require "digest"
|
5
|
+
require "nokogiri"
|
4
6
|
|
5
7
|
module Argos
|
6
8
|
|
@@ -11,17 +13,22 @@ module Argos
|
|
11
13
|
# /{archive}/{year}/program-{programNumber}/platform-{platformId}/argos-{YYYY-MM-DD}-platform-{platformId}.[xml|csv]
|
12
14
|
#
|
13
15
|
# Command line:
|
14
|
-
# $ ./bin/argos-soap --download /
|
16
|
+
# $ ./bin/argos-soap --download /tmp/tracking/ws-argos.cls.fr --username=xyz --password=123 --debug
|
17
|
+
# Crontab example:
|
18
|
+
# 27 3 * * * source /home/argos/.rvm/environments/default && argos-soap --download /var/ws-argos.cls.fr --username=user --password=pw
|
19
|
+
|
15
20
|
|
16
21
|
class Download
|
17
22
|
|
18
23
|
def self.download(username, password, archive, log, days=20)
|
19
24
|
|
25
|
+
log.debug "Starting download of Argos XML to #{archive}"
|
26
|
+
|
20
27
|
soap = Argos::Soap.new({username: username, password: password})
|
21
28
|
soap.log = log
|
22
29
|
|
23
30
|
programs = soap.programs
|
24
|
-
|
31
|
+
log.debug "Programs for #{username}: #{programs.to_json}"
|
25
32
|
year = DateTime.now.year
|
26
33
|
|
27
34
|
soap.getPlatformList["data"]["program"].each do |program|
|
@@ -29,9 +36,8 @@ module Argos
|
|
29
36
|
soap.programNumber = programNumber
|
30
37
|
|
31
38
|
platforms = soap.platforms
|
32
|
-
log.debug "Program: #{program["programNumber"]}, #{platforms.size} platform(s)"
|
33
39
|
|
34
|
-
program["platform"].select {|platform|
|
40
|
+
active = program["platform"].select {|platform|
|
35
41
|
|
36
42
|
lastCollectDate = DateTime.parse(platform["lastCollectDate"])
|
37
43
|
lastLocationDate = DateTime.parse(platform["lastLocationDate"])
|
@@ -40,13 +46,24 @@ module Argos
|
|
40
46
|
|
41
47
|
(lastCollectDate > twentydays or lastLocationDate > twentydays)
|
42
48
|
|
43
|
-
|
49
|
+
}
|
50
|
+
|
51
|
+
|
52
|
+
inactive = program["platform"] - active
|
53
|
+
|
54
|
+
active.each_with_index do |a,m|
|
55
|
+
log.debug "Active [#{m+1}/#{active.size}]: #{a.reject{|k,v| k =~ /location/i }.to_json}"
|
56
|
+
end
|
57
|
+
inactive.each_with_index do |i,n|
|
58
|
+
log.debug "Inactive [#{n+1}/#{inactive.size}]: #{i.reject{|k,v| k =~ /location/i }.to_json}"
|
59
|
+
end
|
60
|
+
active.each_with_index do | platform, idx |
|
44
61
|
|
45
62
|
|
46
63
|
platformId = platform["platformId"]
|
47
64
|
soap.platformId = platformId
|
48
65
|
|
49
|
-
log.debug "
|
66
|
+
log.debug "About to download program: #{programNumber}, platform: #{platformId} [#{idx+1}/#{active.size}], lastCollectDate: #{platform["lastCollectDate"]}"
|
50
67
|
|
51
68
|
20.downto(1) do |daysago|
|
52
69
|
|
@@ -58,27 +75,48 @@ module Argos
|
|
58
75
|
soap.period = {startDate: "#{date}T00:00:00Z", endDate: "#{date}T23:59:59.999Z"}
|
59
76
|
soap.getXml
|
60
77
|
|
61
|
-
|
62
78
|
FileUtils.mkdir_p(destination)
|
63
79
|
filename = destination+"/argos-#{date}-platform-#{platformId}.xml"
|
64
|
-
|
65
|
-
File.open(filename, "wb") { |file| file.write(soap.xml)}
|
66
|
-
log.debug "Saved #{filename}"
|
67
80
|
|
68
|
-
|
81
|
+
if File.exists? filename
|
82
|
+
existing_sha1 = Digest::SHA1.file(filename).hexdigest
|
83
|
+
existing_errors = Argos::Soap.new.validate(File.read(filename))
|
84
|
+
if existing_errors.any?
|
85
|
+
log.error "Validation error for existing data #{filename} (#{File.size(filename)} bytes): #{existing_errors.uniq.to_json}"
|
86
|
+
end
|
87
|
+
#log.debug "Keeping existing file #{filename} from #{File.mtime(filename)}, fresh data is identical"
|
88
|
+
end
|
89
|
+
|
90
|
+
new_xml_ng = Nokogiri::XML(soap.xml, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS | Nokogiri::XML::ParseOptions::NOCDATA | Nokogiri::XML::ParseOptions::STRICT)
|
91
|
+
new_xml = new_xml_ng.canonicalize
|
92
|
+
new_sha1 = Digest::SHA1.hexdigest(new_xml)
|
69
93
|
|
70
|
-
|
94
|
+
if existing_sha1.nil? or existing_errors.any? or existing_sha1 != new_sha1
|
95
|
+
|
96
|
+
if errors = Argos::Soap.new.validate(new_xml_ng).any?
|
97
|
+
raise "Failed XML schema validation"
|
98
|
+
else
|
99
|
+
File.open(filename, "wb") { |file| file.write(new_xml)}
|
100
|
+
log.debug "Validated and saved new data: #{filename}"
|
101
|
+
end
|
71
102
|
|
103
|
+
end
|
104
|
+
log.debug "Day -#{daysago}: #{date}: #{new_xml_ng.xpath("//message").size} message(s) (program #{programNumber}, platform #{platformId})"
|
72
105
|
rescue Argos::NodataException
|
73
106
|
# noop
|
107
|
+
log.debug "Day -#{daysago}: #{date}: No data for (program #{programNumber}, platform #{platformId})"
|
74
108
|
rescue => e
|
75
109
|
log.error e
|
76
110
|
end
|
77
111
|
|
78
112
|
end
|
113
|
+
|
114
|
+
log.debug "Completed download of #{platformId}"
|
115
|
+
|
79
116
|
end
|
117
|
+
log.debug "Completed download for #{username}"
|
80
118
|
end
|
81
119
|
end
|
82
120
|
|
83
121
|
end
|
84
|
-
end
|
122
|
+
end
|
data/lib/argos/soap.rb
CHANGED
@@ -18,8 +18,7 @@ end
|
|
18
18
|
module Argos
|
19
19
|
class Soap
|
20
20
|
|
21
|
-
# A
|
22
|
-
# http://wanderingbarque.com/nonintersecting/2006/11/15/the-s-stands-for-simple/
|
21
|
+
# A [simple](http://wanderingbarque.com/nonintersecting/2006/11/15/the-s-stands-for-simple/) Soap client for the Argos satellite tracking webservice operated by CLS
|
23
22
|
|
24
23
|
# client [Savon] (version 3)
|
25
24
|
# request [String] Soap:Envelope (XML request body)
|
@@ -244,7 +243,6 @@ module Argos
|
|
244
243
|
platformListPrograms.each do |program|
|
245
244
|
platforms += program["platform"].map {|p| p["platformId"].to_i}
|
246
245
|
end
|
247
|
-
|
248
246
|
platforms
|
249
247
|
end
|
250
248
|
|
@@ -283,6 +281,18 @@ module Argos
|
|
283
281
|
client.services
|
284
282
|
end
|
285
283
|
|
284
|
+
def schema
|
285
|
+
Nokogiri::XML::Schema(File.read("#{__dir__}/_xsd/argos-data.xsd"))
|
286
|
+
end
|
287
|
+
|
288
|
+
def validate(xml)
|
289
|
+
if xml.is_a? String
|
290
|
+
xml = Nokogiri.XML(xml)
|
291
|
+
end
|
292
|
+
schema.validate(xml)
|
293
|
+
|
294
|
+
end
|
295
|
+
|
286
296
|
# @return [String]
|
287
297
|
def text
|
288
298
|
@text||=""
|
@@ -336,6 +346,7 @@ module Argos
|
|
336
346
|
end
|
337
347
|
|
338
348
|
# Handle errors
|
349
|
+
|
339
350
|
ng = Nokogiri.XML(xml)
|
340
351
|
ng.xpath("/data/errors/error").each do | error |
|
341
352
|
if error.key?("code")
|
@@ -351,11 +362,18 @@ module Argos
|
|
351
362
|
end
|
352
363
|
end
|
353
364
|
|
354
|
-
# Validation
|
355
|
-
|
356
|
-
|
357
|
-
|
365
|
+
# Validation - only :getXml
|
366
|
+
if [:getXml].include? op_sym
|
367
|
+
# Validation against getXSD schema does not work: ["Element 'data': No matching global declaration available for the validation root."]
|
368
|
+
# See https://github.com/npolar/argos-ruby/commit/219e4b3761e5265f8f9e8b924bcfc23607902428 for the fix
|
369
|
+
schema = Nokogiri::XML::Schema(File.read("#{__dir__}/_xsd/argos-data.xsd"))
|
370
|
+
v = schema.validate(ng)
|
371
|
+
if v.any?
|
372
|
+
log.debug "#{v.size} errors: #{v.map{|v|v.to_s}.uniq.to_json}"
|
373
|
+
end
|
374
|
+
end
|
358
375
|
|
376
|
+
|
359
377
|
# Convert XML to Hash
|
360
378
|
nori = Nori.new
|
361
379
|
nori.parse(xml)
|
data/lib/argos/soap_command.rb
CHANGED
@@ -117,7 +117,7 @@ module Argos
|
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
120
|
-
opts.on("--download
|
120
|
+
opts.on("--download=/path/to/archive", "Download") do |archive|
|
121
121
|
@param[:archive] = archive
|
122
122
|
end
|
123
123
|
|
@@ -178,7 +178,7 @@ module Argos
|
|
178
178
|
else
|
179
179
|
raise ArgumentError, "Unspported operation: #{param[:operation]}"
|
180
180
|
end
|
181
|
-
puts output
|
181
|
+
puts output.to_s
|
182
182
|
|
183
183
|
rescue NodataException
|
184
184
|
log.debug output
|
@@ -216,8 +216,7 @@ module Argos
|
|
216
216
|
when :raw
|
217
217
|
soap.raw
|
218
218
|
when :xml
|
219
|
-
|
220
|
-
soap.xml+xml_trailer
|
219
|
+
soap.xml+"\n"
|
221
220
|
else
|
222
221
|
raise ArgumentError, "Unknown format: #{format}"
|
223
222
|
end
|
@@ -236,9 +235,9 @@ module Argos
|
|
236
235
|
[:getCsv, :getStreamXml, :getKml, :getXml, :getXsd, :getPlatformList, :getObsCsv, :getObsXml]
|
237
236
|
end
|
238
237
|
|
239
|
-
def xml_trailer
|
240
|
-
|
241
|
-
end
|
242
|
-
|
238
|
+
#def xml_trailer
|
239
|
+
# "<!-- #{Argos.library_version} #{param.reject {|k,v| k =~ /^password$/}.to_json} now: #{Time.now.utc.xmlschema} -->\n"
|
240
|
+
#end
|
241
|
+
#
|
243
242
|
end
|
244
243
|
end
|