@@ -100,19 +100,19 @@ function parseOIF411(xdata, pressure){
100100 if ( ( _ozone_pump_temp & 0x8000 ) > 0 ) {
101101 _ozone_pump_temp = _ozone_pump_temp - 0x10000 ;
102102 }
103- _ozone_pump_temp = _ozone_pump_temp * 0.01 ; // Degrees C
104- _output [ 'oif411_ozone_pump_temp' ] = Math . round ( _ozone_pump_temp * 10 ) / 10 ; // 1 DP
103+ _ozone_pump_temp = _ozone_pump_temp * 0.01 ; // Degrees C (5 - 35)
104+ _output [ 'oif411_ozone_pump_temp' ] = Math . round ( _ozone_pump_temp * 100 ) / 100 ; // 2 DP
105105
106106 // Ozone Current
107- _ozone_current_uA = parseInt ( xdata . substr ( 8 , 5 ) , 16 ) * 0.0001 ; // micro-Amps
107+ _ozone_current_uA = parseInt ( xdata . substr ( 8 , 5 ) , 16 ) * 0.0001 ; // micro-Amps (0.05 - 30)
108108 _output [ 'oif411_ozone_current_uA' ] = Math . round ( _ozone_current_uA * 10000 ) / 10000 ; // 4 DP
109109
110110 // Battery Voltage
111- _ozone_battery_v = parseInt ( xdata . substr ( 13 , 2 ) , 16 ) * 0.1 ; // Volts
111+ _ozone_battery_v = parseInt ( xdata . substr ( 13 , 2 ) , 16 ) * 0.1 ; // Volts (14 - 19)
112112 _output [ 'oif411_ozone_battery_v' ] = Math . round ( _ozone_battery_v * 10 ) / 10 ; // 1 DP
113113
114114 // Ozone Pump Current
115- _ozone_pump_curr_mA = parseInt ( xdata . substr ( 15 , 3 ) , 16 ) ; // mA
115+ _ozone_pump_curr_mA = parseInt ( xdata . substr ( 15 , 3 ) , 16 ) ; // mA (30 - 110)
116116 _output [ 'oif411_ozone_pump_curr_mA' ] = Math . round ( _ozone_pump_curr_mA * 10 ) / 10 ; // 1 DP
117117
118118 // External Voltage
@@ -164,30 +164,6 @@ function parseCFH(xdata) {
164164 // Instrument number is common to all XDATA types.
165165 _output [ 'cfh_instrument_number' ] = parseInt ( xdata . substr ( 2 , 2 ) , 16 ) ;
166166
167- // Mirror temperature
168- _mirror_temperature = parseInt ( xdata . substr ( 4 , 6 ) , 16 ) ;
169- if ( ( _mirror_temperature & 0x80000 ) > 0 ) {
170- _mirror_temperature = _mirror_temperature - 0x1000000 ;
171- }
172- _mirror_temperature = _mirror_temperature * 0.00001 ; // Degrees C
173- _output [ 'cfh_mirror_temperature' ] = Math . round ( _mirror_temperature * 100000 ) / 100000 ; // 5 DP
174-
175- // Optics voltage
176- _optics_voltage = parseInt ( xdata . substr ( 10 , 6 ) , 16 ) * 0.000001 ; // Volts
177- _output [ 'cfh_optics_voltage' ] = Math . round ( _optics_voltage * 1000000 ) / 1000000 ; // 6 DP
178-
179- // Optics temperature
180- _optics_temperature = parseInt ( xdata . substr ( 16 , 4 ) , 16 ) ;
181- if ( ( _optics_temperature & 0x8000 ) > 0 ) {
182- _optics_temperature = _optics_temperature - 0x10000 ;
183- }
184- _optics_temperature = _optics_temperature * 0.01 ; // Degrees C
185- _output [ 'cfh_optics_temperature' ] = Math . round ( _optics_temperature * 100 ) / 100 ; // 2 DP
186-
187- // CFH battery
188- _battery = parseInt ( xdata . substr ( 20 , 4 ) , 16 ) * 0.01 ; // Volts
189- _output [ 'cfh_battery' ] = Math . round ( _battery * 100 ) / 100 ; // 2 DP
190-
191167 return _output
192168}
193169
@@ -227,37 +203,80 @@ function parseCOBALD(xdata) {
227203 if ( ( _internal_temperature & 0x800 ) > 0 ) {
228204 _internal_temperature = _internal_temperature - 0x1000 ;
229205 }
230- _internal_temperature = _internal_temperature / 8 ; // Degrees C
231- _output [ 'cobald_internal_temperature' ] = Math . round ( _internal_temperature * 10 ) / 10 ; // 1 DP
206+ _internal_temperature = _internal_temperature / 8 ; // Degrees C (-40 - 50)
207+ _output [ 'cobald_internal_temperature' ] = Math . round ( _internal_temperature * 100 ) / 100 ; // 2 DP
232208
233209 // Blue backscatter
234210 _blue_backscatter = parseInt ( xdata . substr ( 10 , 6 ) , 16 ) ;
235211 if ( ( _blue_backscatter & 0x800000 ) > 0 ) {
236212 _blue_backscatter = _blue_backscatter - 0x1000000 ;
237213 }
238- _output [ 'cobald_blue_backscatter' ] = _blue_backscatter ;
214+ _output [ 'cobald_blue_backscatter' ] = _blue_backscatter ; // (0 - 1000000)
239215
240216 // Red backckatter
241217 _red_backscatter = parseInt ( xdata . substr ( 16 , 6 ) , 16 ) ;
242218 if ( ( _red_backscatter & 0x800000 ) > 0 ) {
243219 _red_backscatter = _red_backscatter - 0x1000000 ;
244220 }
245- _output [ 'cobald_red_backscatter' ] = _red_backscatter ;
221+ _output [ 'cobald_red_backscatter' ] = _red_backscatter ; // (0 - 1000000)
246222
247223 // Blue monitor
248224 _blue_monitor = parseInt ( xdata . substr ( 22 , 4 ) , 16 ) ;
249225 if ( ( _blue_monitor & 0x8000 ) > 0 ) {
250226 _blue_monitor = _blue_monitor - 0x10000 ;
251227 }
252- _output [ 'cobald_blue_monitor' ] = _blue_monitor ;
228+ _output [ 'cobald_blue_monitor' ] = _blue_monitor ; // (-32768 - 32767)
253229
254230 // Red monitor
255231 _red_monitor = parseInt ( xdata . substr ( 26 , 4 ) , 16 ) ;
256232 if ( ( _red_monitor & 0x8000 ) > 0 ) {
257233 _red_monitor = _red_monitor - 0x10000 ;
258234 }
259- _output [ 'cobald_red_monitor' ] = _red_monitor ;
235+ _output [ 'cobald_red_monitor' ] = _red_monitor ; // (-32768 - 32767)
236+
237+ return _output
238+ }
239+
240+ function parseSKYDEW ( xdata ) {
241+ // Attempt to parse an XDATA string from a SKYDEW Peltier-based chilled-mirror hygrometer
242+ // Returns an object with parameters to be added to the sondes telemetry.
243+ //
244+ // References:
245+ // https://www.gruan.org/gruan/editor/documents/meetings/icm-12/pres/pres_306_Sugidachi_SKYDEW.pdf
246+ //
247+ // Sample data: 3F0141DF73B940F600150F92FF27D5C8304102 (length = 38 characters)
248+
249+ // Cast to string if not already
250+ xdata = String ( xdata ) ;
251+
252+ // Run some checks over the input
253+ if ( xdata . length != 38 ) {
254+ // Invalid SKYDEW dataset
255+ return { } ;
256+ }
260257
258+ if ( xdata . substr ( 0 , 2 ) !== '3F' ) {
259+ // Not a SKYDEW (shouldn't get here)
260+ return { } ;
261+ }
262+
263+ var _output = { } ;
264+
265+ // Instrument number is common to all XDATA types.
266+ _output [ 'skydew_instrument_number' ] = parseInt ( xdata . substr ( 2 , 2 ) , 16 ) ;
267+
268+ // Other fields may include
269+ // Serial number
270+ // Mirror temperature (-120 - 30)
271+ // Mixing ratio V (ppmV)
272+ // PT100 (Ohm 60 - 120)
273+ // SCA light
274+ // SCA base
275+ // PLT current
276+ // HS temp
277+ // CB temp
278+ // PID
279+ // Battery
261280 return _output
262281}
263282
@@ -269,7 +288,7 @@ function parseXDATA(data, pressure){
269288 // "0501R20234850000006EI"
270289 // "0501034F02CA08B06700#800261FCA6F80012F6F40A75"
271290 // "800262358C080012FE6C0A70#0501035902BA08908400"
272- // "0802AC83D88AB61107A30175 "
291+ // "0501092C000000000000#190214f0df03e82e03660048d73683#0803DC5EF086C244078601A5#3F04475A4B0D415900160D510C270200465900 "
273292
274293 // Split apart any contatenated xdata.
275294 if ( data . includes ( '#' ) ) {
@@ -322,6 +341,7 @@ function parseXDATA(data, pressure){
322341 if ( ! _instruments . includes ( "OPC" ) ) _instruments . push ( 'OPC' ) ;
323342 } else if ( _instrument === '3C' ) {
324343 // PCFH
344+ // SRNO, H0, H1, F0, F1
325345 // 3c010000184b4b5754
326346 // 3c0103ce7b58647a98748befff
327347 // 3c010148719fff8e54b9af627e249fe0
@@ -335,6 +355,8 @@ function parseXDATA(data, pressure){
335355 if ( ! _instruments . includes ( "TRAPS" ) ) _instruments . push ( 'TRAPS' ) ;
336356 } else if ( _instrument === '3F' ) {
337357 // SKYDEW
358+ _xdata_temp = parseSKYDEW ( _current_xdata ) ;
359+ _output = Object . assign ( _output , _xdata_temp ) ;
338360 if ( ! _instruments . includes ( "SKYDEW" ) ) _instruments . push ( 'SKYDEW' ) ;
339361 } else if ( _instrument === '41' ) {
340362 // CICANUM
@@ -351,7 +373,7 @@ function parseXDATA(data, pressure){
351373 }
352374 }
353375
354- _output [ "xdata_instrument" ] = _instruments ;
376+ if ( _instrument . length > 0 ) _output [ "xdata_instrument" ] = _instruments ;
355377
356378 return _output
357379
0 commit comments