Skip to content

Remove all dependencies and add data parsing #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions config/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ module.exports = function(config) {
],

preprocessors: {
'**/*.coffee': ['coffee'],
// '**/*.coffee': ['coffee'],
'test/*.js': ['browserify'],
},

Expand Down Expand Up @@ -77,7 +77,7 @@ module.exports = function(config) {
singleRun: false,

browserify: {
extension: ['.coffee'],
//extension: ['.coffee'],
transform: [],
// require: ['native-buffer-browserify'],
watch: true
Expand All @@ -86,7 +86,6 @@ module.exports = function(config) {
plugins: [
'karma-chrome-launcher',
'karma-firefox-launcher',
'karma-phantomjs-launcher',
'karma-browserify',
'karma-mocha'
]
Expand Down
13 changes: 9 additions & 4 deletions grib-cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ const grib = require('./index');

program
.version('0.0.1')
.option('-o, --out [optional]','outfile (else stdout)')
.option('-i, --input <requred>','input file (else stdin)')
.option('-p, --pretty','pretty print output json')
.option('-c, --convert [optional]', 'convert to grib2json format')
.option('-o, --out [optional]', 'outfile (else stdout)')
.option('-i, --input <requred>', 'input file (else stdin)')
.option('-p, --pretty', 'pretty print output json')
.parse(process.argv); // end with parse to parse through the input


Expand All @@ -25,11 +26,15 @@ jBinary.loadData(program.input, function(err, data) {
exit(1);
}

if(program.convert) {
msgs_ = grib.convertData(msgs_)
}

if(program.out) {
fs.writeFileSync(program.out, program.pretty ? JSON.stringify(msgs_, null, 4) : JSON.stringify(msgs_) );
}
else {
console.log(program.pretty ? JSON.stringify(msgs_, null, 4) : JSON.stringify(msgs_));
}
});
});
});
97 changes: 91 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
var gribParse = require('./lib/parser');
var tables = require('./lib/tables');
var jBinary = require('jbinary');
const gribParse = require('./lib/parser');
const tables = require('./lib/tables');
const loadData = require('./load-data');

for(var tableName in tables.tables) {
exports[tableName] = tables.tables[tableName];
}

exports.readData = function(data, cb) {
var msgs;
var dataView = new jBinary(data).view;

// Write the contents of the buffer catching any parse errors
try {
msgs = gribParse.parseDataView(dataView);
msgs = gribParse.parseDataView(data);
} catch(e) {
return cb(e, null);
}
Expand All @@ -24,8 +23,94 @@ exports.readData = function(data, cb) {
}

exports.readUrl = function(url, cb) {
jBinary.loadData(url, function(err, data) {
loadData(url, function(err, data) {
if(err) return cb(err);
exports.readData(data, cb);
});
}

exports.convertData = function(data) {
getGridUnits = function(templateNumber) {
switch (templateNumber) {
case 0:
case 1:
case 2:
case 3:
case 40:
case 41:
case 42:
case 43:
return "degrees";

case 10:
case 20:
case 30:
case 31:
return "m";

default:
return "";
}
}

const msgs_ = []
for (var msgs of data) {
const header = {
discipline: msgs.fields[0].indicator.discipline.value,
disciplineName: msgs.fields[0].indicator.discipline.name,
gribEdition: msgs.fields[0].indicator.edition,
gribLength: msgs.fields[0].indicator.length,
center: msgs.originatingCenter.value,
centerName: msgs.originatingCenter.name,
subcenter: msgs.originatingSubCenter,
refTime: msgs.referenceTime,
significanceOfRT: msgs.referenceTimeSignificance.value,
significanceOfRTName: msgs.referenceTimeSignificance.value,
productStatus: msgs.productionStatus.value,
productStatusName: msgs.productionStatus.name,
productType: msgs.type.value,
productTypeName: msgs.type.name,
productDefinitionTemplate: msgs.fields[0].product.templateNumber.value,
productDefinitionTemplateName: msgs.fields[0].product.templateNumber.name,
parameterCategory: msgs.fields[0].product.details.category.value,
parameterCategoryName: msgs.fields[0].product.details.category.name,
parameterNumber: msgs.fields[0].product.details.parameter.value,
parameterNumberName: msgs.fields[0].product.details.parameter.name,
parameterUnit: msgs.fields[0].product.details.parameter.unit,
genProcessType: msgs.fields[0].product.details.generatingProcessType.value,
genProcessTypeName: msgs.fields[0].product.details.generatingProcessType.name,
forecastTime: msgs.fields[0].product.details.forecastTime,
surface1Type: msgs.fields[0].product.details.surfaceType.value,
surface1TypeName: msgs.fields[0].product.details.surfaceType.name,
surface1Value: msgs.fields[0].product.details.surfaceTypeValue,
surface2Type: msgs.fields[0].product.details.secondSurfaceType.value,
surface2TypeName: msgs.fields[0].product.details.secondSurfaceType.name,
surface2Value: msgs.fields[0].product.details.secondSurfaceTypeValue,
gridDefinitionTemplate: msgs.fields[0].grid.templateNumber,
gridDefinitionTemplateName: msgs.fields[0].grid.definition.name,
numberPoints: msgs.fields[0].grid.dataPointCount,
shape: msgs.fields[0].grid.definition.earthShape.value,
shapeName: msgs.fields[0].grid.definition.earthShape.name,
gridUnits: getGridUnits(msgs.fields[0].grid.templateNumber),
resolution: msgs.fields[0].grid.definition.resolutionAndComponentFlags,
winds: !!(msgs.fields[0].grid.definition.resolutionAndComponentFlags & (1 << 4)),
scanMode: msgs.fields[0].grid.definition.scanningMode,
nx: msgs.fields[0].grid.definition.ni,
ny: msgs.fields[0].grid.definition.nj,
basicAngle: msgs.fields[0].grid.definition.basicAngle,
lo1: msgs.fields[0].grid.definition.lo1,
la1: msgs.fields[0].grid.definition.la1,
lo2: msgs.fields[0].grid.definition.lo2,
la2: msgs.fields[0].grid.definition.la2,
dx: msgs.fields[0].grid.definition.di,
dy: msgs.fields[0].grid.definition.dj,
}
const gribdata = msgs.fields[0].data
msgs_.push({
header,
data: gribdata,
})
}

return msgs_
}
145 changes: 145 additions & 0 deletions lib/BinaryDataView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
class BinaryDataView {
/**
*
* @param {Buffer} buffer
*/
constructor(byteArray) {
if (byteArray instanceof Buffer) {
this.view = new DataView(byteArray.buffer, byteArray.byteOffset, byteArray.byteLength);
}
else {
this.view = new DataView(byteArray);
}
this.view.getUnsigned = this.getUnsigned.bind(this);
this.offset = 0;
this.bOffset = 0;
}
seek(offset) {
this.offset = offset;
}
skip(n) {
this.offset += n;
}
tell() {
return this.offset;
}
incrByte() {
if (this.bOffset > 0) {
this.offset++;
this.bOffset = 0;
}
}
read(type, offset) {
if (offset) {
const current = this.offset;
this.offset = offset;
const val = this[type]();
this.offset = current;
return val;
}
return this[type]();
}
readArray(type, size) {
const val = new Array(size);
for (let i = 0; i < size; i++) {
val[i] = this[type]();
}
return val;
}
readBlob(size) {
const val = this.view.buffer.slice(this.offset, this.offset + size);
this.offset += size;
return val;
}
grib32() {
const raw = this.uint32();
const sign = raw >>> 31;
const value = raw & 0x7fffffff;
return 1 === sign ? -value : value
}
grib16() {
const raw = this.uint16();
const sign = raw >>> 15;
const value = raw & 0x7fff;
return 1 === sign ? -value : value
}
grib8() {
const raw = this.uint8();
const sign = raw >>> 7;
const value = raw & 0x7f;
return 1 === sign ? -value : value
}
int8() {
const val = this.view.getInt8(this.offset);
this.offset++;
return val;
}
int16() {
const val = this.view.getInt16(this.offset);
this.offset += 2;
return val;
}
int32() {
const val = this.view.getInt32(this.offset);
this.offset += 4;
return val;
}
uint8() {
const val = this.view.getUint8(this.offset);
this.offset++;
return val;

}
uint16() {
const val = this.view.getUint16(this.offset);
this.offset += 2;
return val;

}
uint32() {
const val = this.view.getUint32(this.offset);
this.offset += 4;
return val;
}
uint64() {
return {
hi: this.uint32(),
lo: this.uint32()
}
}
float32() {
const val = this.view.getFloat32(this.offset);
this.offset += 4;
return val;
}
getUnsigned(n) {
const m = this.bOffset + n;
const bytes = Math.ceil(m / 8);
let val;
switch (bytes) {
case 1:
val = (this.view.getUint8(this.offset) & (0xff >>> this.bOffset)) >>> (8 - m);
break;
case 2:
val = (this.view.getUint16(this.offset) & (0xffff >>> this.bOffset)) >>> (16 - m);
break;
case 3:
case 4:
val = (this.view.getUint32(this.offset) & (0xffffffff >>> this.bOffset)) >>> (32 - m);
break;
case 5:
case 6:
case 7:
case 8:
val = (this.view.getBigUInt64(this.offset) & (0xffffffffffffffffn >> BigInt(this.bOffset))) >> BigInt(64 - m);
break;
default:
console.error("Can't read more than 8 bytes at a time");
break;
}
this.bOffset = m % 8;
this.offset += Math.floor(m / 8);
return val;
}
}
module.exports = BinaryDataView;
Loading