|
1 | 1 | /* SondeHub XDATA Parser Library |
2 | 2 | * |
3 | | - * Author: Mark Jessop |
| 3 | + * Authors: Mark Jessop & Luke Prior |
4 | 4 | */ |
5 | 5 |
|
6 | 6 | // Pump Efficiency Correction Parameters for ECC-6A Ozone Sensor, with 3.0cm^3 volume. |
@@ -191,6 +191,76 @@ function parseCFH(xdata) { |
191 | 191 | return _output |
192 | 192 | } |
193 | 193 |
|
| 194 | +function parseCOBALD(xdata) { |
| 195 | + // Attempt to parse an XDATA string from a Compact Optical Backscatter Aerosol Detector |
| 196 | + // Returns an object with parameters to be added to the sondes telemetry. |
| 197 | + // |
| 198 | + // References: |
| 199 | + // https://hobbydocbox.com/Radio/83430839-Cobald-operating-instructions-imet-configuration.html |
| 200 | + // |
| 201 | + // Sample data: 190213fffe005fcf00359943912cca (length = 30 characters) |
| 202 | + |
| 203 | + // Cast to string if not already |
| 204 | + xdata = String(xdata); |
| 205 | + |
| 206 | + // Run some checks over the input |
| 207 | + if(xdata.length != 30){ |
| 208 | + // Invalid COBALD dataset |
| 209 | + return {}; |
| 210 | + } |
| 211 | + |
| 212 | + if(xdata.substr(0,2) !== '19'){ |
| 213 | + // Not a COBALD (shouldn't get here) |
| 214 | + return {}; |
| 215 | + } |
| 216 | + |
| 217 | + _output = {'xdata_instrument': 'COBALD'}; |
| 218 | + |
| 219 | + // Instrument number is common to all XDATA types. |
| 220 | + _output['cobald_instrument_number'] = parseInt(xdata.substr(2,2),16); |
| 221 | + |
| 222 | + // Sonde number |
| 223 | + _output['cobald_sonde_number'] = parseInt(xdata.substr(4,3),16); |
| 224 | + |
| 225 | + // Internal temperature |
| 226 | + _internal_temperature = parseInt(xdata.substr(7,3),16); |
| 227 | + if ((_internal_temperature & 0x800) > 0) { |
| 228 | + _internal_temperature = _internal_temperature - 0x1000; |
| 229 | + } |
| 230 | + _internal_temperature = _internal_temperature/8; // Degrees C |
| 231 | + _output['cobald_internal_temperature'] = Math.round(_internal_temperature * 10) / 10; // 1 DP |
| 232 | + |
| 233 | + // Blue backskatter |
| 234 | + _blue_backskatter = parseInt(xdata.substr(10,6),16); |
| 235 | + if ((_blue_backskatter & 0x800000) > 0) { |
| 236 | + _blue_backskatter = _blue_backskatter - 0x1000000; |
| 237 | + } |
| 238 | + _output['cobald_blue_backskatter'] = _blue_backskatter; |
| 239 | + |
| 240 | + // Red backskatter |
| 241 | + _red_backskatter = parseInt(xdata.substr(16,6),16); |
| 242 | + if ((_red_backskatter & 0x800000) > 0) { |
| 243 | + _red_backskatter = _red_backskatter - 0x1000000; |
| 244 | + } |
| 245 | + _output['cobald_red_backskatter'] = _red_backskatter; |
| 246 | + |
| 247 | + // Blue monitor |
| 248 | + _blue_monitor = parseInt(xdata.substr(22,4),16); |
| 249 | + if ((_blue_monitor & 0x8000) > 0) { |
| 250 | + _blue_monitor = _blue_monitor - 0x10000; |
| 251 | + } |
| 252 | + _output['cobald_blue_monitor'] = _blue_monitor; |
| 253 | + |
| 254 | + // Red monitor |
| 255 | + _red_monitor = parseInt(xdata.substr(26,4),16); |
| 256 | + if ((_red_monitor & 0x8000) > 0) { |
| 257 | + _red_monitor = _red_monitor - 0x10000; |
| 258 | + } |
| 259 | + _output['cobald_red_monitor'] = _red_monitor; |
| 260 | + |
| 261 | + return _output |
| 262 | +} |
| 263 | + |
194 | 264 | function parseXDATA(data, pressure){ |
195 | 265 | // Accept an XDATA string, or multiple XDATA entries, delimited by '#' |
196 | 266 | // Attempt to parse each one, and return an object |
@@ -233,9 +303,10 @@ function parseXDATA(data, pressure){ |
233 | 303 | } else if (_instrument === '10'){ |
234 | 304 | // FPH |
235 | 305 | _output = {'xdata_instrument': 'FPH'}; |
236 | | - } else if (_instrument === '18'){ |
| 306 | + } else if (_instrument === '19'){ |
237 | 307 | // COBALD |
238 | | - _output = {'xdata_instrument': 'COBALD'}; |
| 308 | + _xdata_temp = parseCOBALD(_current_xdata); |
| 309 | + _output = Object.assign(_output,_xdata_temp); |
239 | 310 | } else if (_instrument === '28'){ |
240 | 311 | // SLW |
241 | 312 | _output = {'xdata_instrument': 'SLW'}; |
|
0 commit comments