@@ -14,7 +14,6 @@ function lerp(x, y, a){
1414 return x * ( 1 - a ) + y * a
1515}
1616
17-
1817function get_oif411_Cef ( pressure ) {
1918 // Get the Pump efficiency correction value for a given pressure.
2019
@@ -40,6 +39,64 @@ function get_oif411_Cef(pressure){
4039 return 1.0 ;
4140}
4241
42+ function parseOzonesonde ( xdata , pressure ) {
43+ // Attempt to parse an XDATA string from an ECC Ozonesonde
44+ // Returns an object with parameters to be added to the sondes telemetry.
45+ //
46+ // References:
47+ // https://gml.noaa.gov/aftp/user/jordan/iMet%20Radiosonde%20Protocol.pdf
48+ //
49+ // Sample data: 01010349FDC54296 (length = 16 characters)
50+
51+ // Run some checks over the input
52+ if ( xdata . length != 16 ) {
53+ // Invalid Ozonesonde dataset
54+ return { } ;
55+ }
56+
57+ if ( xdata . substr ( 0 , 2 ) !== '01' ) {
58+ // Not an Ozonesonde (shouldn't get here)
59+ return { } ;
60+ }
61+
62+ var _output = { } ;
63+
64+ // Instrument number is common to all XDATA types.
65+ _output [ 'ozonesonde_instrument_number' ] = parseInt ( xdata . substr ( 2 , 2 ) , 16 ) ;
66+
67+ // Cell Current
68+ _cell_current = parseInt ( xdata . substr ( 4 , 4 ) , 16 ) * 0.001 ; // uA
69+ _output [ 'ozonesonde_cell_current' ] = Math . round ( _cell_current * 1000 ) / 1000 ; // 3 DP
70+
71+ // Pump Temperature
72+ _pump_temperature = parseInt ( xdata . substr ( 8 , 4 ) , 16 ) ;
73+ if ( ( _pump_temperature & 0x8000 ) > 0 ) {
74+ _pump_temperature = _pump_temperature - 0x10000 ;
75+ }
76+ _pump_temperature = _pump_temperature * 0.01 ; // Degrees C
77+ _output [ 'ozonesonde_pump_temperature' ] = Math . round ( _pump_temperature * 100 ) / 100 ; // 2 DP
78+
79+ // Pump Current
80+ _pump_current = parseInt ( xdata . substr ( 12 , 2 ) , 16 ) ; // mA
81+ _output [ 'ozondesonde_pump_current' ] = Math . round ( _pump_current * 10 ) / 10 ; // 1 DP
82+
83+ // Battery Voltage
84+ _battery_voltage = parseInt ( xdata . substr ( 14 , 2 ) , 16 ) * 0.1 ; // Volts
85+ _output [ 'ozondesonde_battery_voltage' ] = Math . round ( _battery_voltage * 10 ) / 10 ; // 1 DP
86+
87+ // Now attempt to calculate the O3 partial pressure (copy OIF411 calculations)
88+
89+ // Calibration values
90+ Ibg = 0.0 ; // The BOM appear to use a Ozone background current value of 0 uA
91+ Cef = get_oif411_Cef ( pressure ) ; // Calculate the pump efficiency correction.
92+ FlowRate = 28.5 ; // Use a 'nominal' value for Flow Rate (seconds per 100mL).
93+
94+ _O3_partial_pressure = ( 4.30851e-4 ) * ( _output [ 'ozonesonde_cell_current' ] - Ibg ) * ( _output [ 'ozonesonde_pump_temperature' ] + 273.15 ) * FlowRate * Cef ; // mPa
95+ _output [ 'ozondesonde_O3_partial_pressure' ] = Math . round ( _O3_partial_pressure * 1000 ) / 1000 ; // 3 DP
96+
97+ return _output
98+ }
99+
43100function parseOIF411 ( xdata , pressure ) {
44101 // Attempt to parse an XDATA string from an OIF411 Ozone Sounder
45102 // Returns an object with parameters to be added to the sondes telemetry.
@@ -159,36 +216,36 @@ function parseCOBALD(xdata) {
159216 // Internal temperature
160217 _internal_temperature = parseInt ( xdata . substr ( 7 , 3 ) , 16 ) ;
161218 if ( ( _internal_temperature & 0x800 ) > 0 ) {
162- _internal_temperature = _internal_temperature - 0x1000 ;
219+ _internal_temperature = _internal_temperature - 0x1000 ;
163220 }
164221 _internal_temperature = _internal_temperature / 8 ; // Degrees C (-40 - 50)
165222 _output [ 'cobald_internal_temperature' ] = Math . round ( _internal_temperature * 100 ) / 100 ; // 2 DP
166223
167224 // Blue backscatter
168225 _blue_backscatter = parseInt ( xdata . substr ( 10 , 6 ) , 16 ) ;
169226 if ( ( _blue_backscatter & 0x800000 ) > 0 ) {
170- _blue_backscatter = _blue_backscatter - 0x1000000 ;
227+ _blue_backscatter = _blue_backscatter - 0x1000000 ;
171228 }
172229 _output [ 'cobald_blue_backscatter' ] = _blue_backscatter ; // (0 - 1000000)
173230
174231 // Red backckatter
175232 _red_backscatter = parseInt ( xdata . substr ( 16 , 6 ) , 16 ) ;
176233 if ( ( _red_backscatter & 0x800000 ) > 0 ) {
177- _red_backscatter = _red_backscatter - 0x1000000 ;
234+ _red_backscatter = _red_backscatter - 0x1000000 ;
178235 }
179236 _output [ 'cobald_red_backscatter' ] = _red_backscatter ; // (0 - 1000000)
180237
181238 // Blue monitor
182239 _blue_monitor = parseInt ( xdata . substr ( 22 , 4 ) , 16 ) ;
183240 if ( ( _blue_monitor & 0x8000 ) > 0 ) {
184- _blue_monitor = _blue_monitor - 0x10000 ;
241+ _blue_monitor = _blue_monitor - 0x10000 ;
185242 }
186243 _output [ 'cobald_blue_monitor' ] = _blue_monitor ; // (-32768 - 32767)
187244
188245 // Red monitor
189246 _red_monitor = parseInt ( xdata . substr ( 26 , 4 ) , 16 ) ;
190247 if ( ( _red_monitor & 0x8000 ) > 0 ) {
191- _red_monitor = _red_monitor - 0x10000 ;
248+ _red_monitor = _red_monitor - 0x10000 ;
192249 }
193250 _output [ 'cobald_red_monitor' ] = _red_monitor ; // (-32768 - 32767)
194251
@@ -565,10 +622,12 @@ function parseXDATA(data, pressure, temperature){
565622 _instrument = _current_xdata . substr ( 0 , 2 ) ;
566623
567624 if ( _instrument === '01' ) {
568- // V7
569- // 0102 time=1001 cnt=0 rpm=0
570- // 0102 time=1001 cnt=7 rpm=419
571- if ( ! _instruments . includes ( "V7" ) ) _instruments . push ( 'V7' ) ;
625+ if ( _current_xdata . length = 16 ) {
626+ // Ozonesonde
627+ _xdata_temp = parseOzonesonde ( _current_xdata , pressure ) ;
628+ _output = Object . assign ( _output , _xdata_temp ) ;
629+ if ( ! _instruments . includes ( "Ozonesonde" ) ) _instruments . push ( 'Ozonesonde' ) ;
630+ }
572631 } else if ( _instrument === '05' ) {
573632 // OIF411
574633 _xdata_temp = parseOIF411 ( _current_xdata , pressure ) ;
0 commit comments