Socket
Socket
Sign inDemoInstall

dji_srt_parser

Package Overview
Dependencies
0
Maintainers
1
Versions
80
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.30 to 1.0.31

.circleci/config.yml

534

index.js
function DJI_SRT_Parser() {
this.fileName = "";
this.fileName = '';
this.metadata = {};

@@ -9,29 +9,48 @@ this.rawMetadata = [];

DJI_SRT_Parser.prototype.srtToObject = function(srt) {//convert SRT strings file into array of objects
DJI_SRT_Parser.prototype.srtToObject = function(srt) {
//convert SRT strings file into array of objects
let converted = [];
const timecodeRegEx = /(\d{2}:\d{2}:\d{2},\d{3})\s-->\s/;
const packetRegEx = /^\d+$/;
const arrayRegEx = /\b([A-Za-z]+)\(([-\+\w.,/]+)\)/g;
const valueRegEx = /\b([A-Za-z]+)\s?:[\s\[a-zA-Z\]]?([-\+\d./]+)\w{0,3}\b/g;
const arrayRegEx = /\b([A-Z_a-z]+)\(([-\+\w.,/]+)\)/g;
const valueRegEx = /\b([A-Z_a-z]+)\s?:[\s\[a-z_A-Z\]]?([-\+\d./]+)\w{0,3}\b/g;
const dateRegEx = /\d{4}[-.]\d{1,2}[-.]\d{1,2} \d{1,2}:\d{2}:\d{2}/;
const accurateDateRegex = /(\d{4}[-.]\d{1,2}[-.]\d{1,2} \d{1,2}:\d{2}:\d{2}),(\w{3}),(\w{3})/g;
srt = srt.split(/[\n\r]/);
//Split difficult Phantom4Pro format
srt = srt
.replace(/.*-->.*/g, match => match.replace(/,/g, ':separator:'))
.replace(/\(.*\)/g, match => match.replace(/,/g, ':separator:').replace(/\s/g, ''))
.replace(/,/g, '')
.replace(/\:separator\:/g, ',');
//Split others
srt = srt
.split(/[\n\r]/)
.map(l => l.trim())
.map(l =>
l
.replace(/([a-zA-Z])\s(\d)/g, '$1:$2')
.replace(/([a-zA-Z])\s\(/g, '$1(')
.replace(/([a-zA-Z])\.([a-zA-Z])/g, '$1_$2')
.replace(/([a-zA-Z])\/(\d)/g, '$1:$2')
)
.filter(l => l.length);
srt.forEach(line => {
let match;
if (packetRegEx.test(line)) {//new packet
if (packetRegEx.test(line)) {
//new packet
converted.push({});
} else if (match = timecodeRegEx.exec(line)) {
converted[converted.length-1].TIMECODE = match[1];
} else if ((match = timecodeRegEx.exec(line))) {
converted[converted.length - 1].TIMECODE = match[1];
} else {
while (match = arrayRegEx.exec(line) ) {
converted[converted.length-1][match[1]] = match[2].split(",");
while ((match = arrayRegEx.exec(line))) {
converted[converted.length - 1][match[1]] = match[2].split(',');
}
while (match = valueRegEx.exec(line)) {
converted[converted.length-1][match[1]] = match[2];
while ((match = valueRegEx.exec(line))) {
converted[converted.length - 1][match[1]] = match[2];
}
if (match = accurateDateRegex.exec(line)) {
converted[converted.length-1].DATE = match[1]+":"+match[2]+"."+match[3];
} else if (match = dateRegEx.exec(line)) {
converted[converted.length-1].DATE = match[0];
if ((match = accurateDateRegex.exec(line))) {
converted[converted.length - 1].DATE = match[1] + ':' + match[2] + '.' + match[3];
} else if ((match = dateRegEx.exec(line))) {
converted[converted.length - 1].DATE = match[0];
}

@@ -41,46 +60,60 @@ }

if (converted.length < 1) {
console.log("Error converting object");
console.log('Error converting object');
return null;
}
return converted;
}
};
DJI_SRT_Parser.prototype.interpretMetadata = function(arr,smooth) {
let computeSpeed = function(arr) {//computes 3 types of speed in km/h
let computed = JSON.parse(JSON.stringify(arr));
let measure = function(lat1, lon1, lat2, lon2){ // generally used geo measurement function. Source: https://stackoverflow.com/questions/639695/how-to-convert-latitude-or-longitude-to-meters
if ([lat1, lon1, lat2, lon2].reduce(((acc,val) => !isNum(val) ? true:acc),false)) {
return 0;//set distance to 0 if there are null or nans in positions
DJI_SRT_Parser.prototype.interpretMetadata = function(arr, smooth) {
let computeSpeed = function(arr) {
//computes 3 types of speed in km/h
let computed = JSON.parse(JSON.stringify(arr));
let measure = function(lat1, lon1, lat2, lon2) {
// generally used geo measurement function. Source: https://stackoverflow.com/questions/639695/how-to-convert-latitude-or-longitude-to-meters
if ([lat1, lon1, lat2, lon2].reduce((acc, val) => (!isNum(val) ? true : acc), false)) {
return 0; //set distance to 0 if there are null or nans in positions
}
var R = 6378.137; // Radius of earth in KM
var dLat = lat2 * Math.PI / 180 - lat1 * Math.PI / 180;
var dLon = lon2 * Math.PI / 180 - lon1 * Math.PI / 180;
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var dLat = (lat2 * Math.PI) / 180 - (lat1 * Math.PI) / 180;
var dLon = (lon2 * Math.PI) / 180 - (lon1 * Math.PI) / 180;
var a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos((lat1 * Math.PI) / 180) * Math.cos((lat2 * Math.PI) / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return d * 1000; // meters
}
};
let accDistance = 0;
computed = computed.map((pck,i,cmp) => {
computed = computed.map((pck, i, cmp) => {
let result = JSON.parse(JSON.stringify(pck));
result.SPEED = {
TWOD:0,
VERTICAL:0,
THREED:0
TWOD: 0,
VERTICAL: 0,
THREED: 0
};
result.DISTANCE = 0;
if (i>0) {
let origin2d = [cmp[i-1].GPS.LATITUDE,cmp[i-1].GPS.LATITUDE];
let destin2d = [pck.GPS.LATITUDE,pck.GPS.LATITUDE];
let distance2D = measure(origin2d[0],origin2d[1],destin2d[0],destin2d[1]);
distance2D /= 1000;;
let distanceVert = getElevation(pck) - getElevation(cmp[i-1]);
if (i > 0) {
let origin2d = [cmp[i - 1].GPS.LATITUDE, cmp[i - 1].GPS.LATITUDE];
let destin2d = [pck.GPS.LATITUDE, pck.GPS.LATITUDE];
let distance2D = measure(origin2d[0], origin2d[1], destin2d[0], destin2d[1]);
distance2D /= 1000;
let distanceVert = getElevation(pck) - getElevation(cmp[i - 1]);
distanceVert /= 1000;
let distance3D = Math.hypot(distance2D,distanceVert);
let time = (new Date(pck.DATE).getTime()-new Date(cmp[i-1].DATE).getTime())/1000.0;//seconds
time = time == 0 ? 1 : time;//make sure we are not dividing by zero, not sure why sometimes two packets have the same timestamp
time /= 60*60;
accDistance += distance3D*1000;
let distance3D = Math.hypot(distance2D, distanceVert);
let time = 1; //Fallback time, 1 second
if (pck.DATE) {
time = (new Date(pck.DATE).getTime() - new Date(cmp[i - 1].DATE).getTime()) / 1000.0; //seconds
} else if (pck.TIMECODE) {
const parseTC = /(\d\d):(\d\d):(\d\d),(\d{3})/;
let match = pck.TIMECODE.match(parseTC);
const useDate = new Date(0, 0, 0, match[1], match[2], match[3], match[4]);
match = cmp[i - 1].TIMECODE.match(parseTC);
const prevDate = new Date(0, 0, 0, match[1], match[2], match[3], match[4]);
time = (new Date(useDate).getTime() - new Date(prevDate).getTime()) / 1000.0; //seconds
}
time = time == 0 ? 1 : time; //make sure we are not dividing by zero, not sure why sometimes two packets have the same timestamp
time /= 60 * 60;
accDistance += distance3D * 1000;
result.DISTANCE = accDistance;

@@ -94,5 +127,5 @@ result.SPEED.TWOD = distance2D / time;

return computed;
}
};
let computeStats = function (arr) {
let computeStats = function(arr) {
let statsObject = function(obj) {

@@ -102,11 +135,12 @@ if (obj.constructor === Object && Object.keys(obj).length === 0) return null;

for (let elt in obj) {
if (elt !== "TIMECODE") {//IGNORE TIMECODES FOR STATS
if (typeof obj[elt] === "object" && obj[elt] != null) {
if (elt !== 'TIMECODE') {
//IGNORE TIMECODES FOR STATS
if (typeof obj[elt] === 'object' && obj[elt] != null) {
result[elt] = statsObject(obj[elt]);
} else {
result[elt] = {
min:0,
max:0,
avg:0
}
min: 0,
max: 0,
avg: 0
};
}

@@ -116,101 +150,107 @@ }

return result;
}
};
let recursiveStatsExtraction = function(res, arr) {
let deepEqual = function(a, b) {
if (a === b) return true;
if (a == null || typeof a != "object" ||
b == null || typeof b != "object")
return false;
var propsInA = 0, propsInB = 0;
for (var prop in a)
propsInA += 1;
if (a == null || typeof a != 'object' || b == null || typeof b != 'object') return false;
var propsInA = 0,
propsInB = 0;
for (var prop in a) propsInA += 1;
for (var prop in b) {
propsInB += 1;
if (!(prop in a) || !deepEqual(a[prop], b[prop]))
return false;
if (!(prop in a) || !deepEqual(a[prop], b[prop])) return false;
}
return propsInA == propsInB;
}
};
let result = res;
for (let elt in result) {
let select = arr.map(pck => pck[elt]);
if (elt === "HOME") { //fill fields that do not use standard stats
if (elt === 'HOME') {
//fill fields that do not use standard stats
let allHomes = [];
select.reduce((acc,val) => {//save different homes if present
if (!deepEqual(val,acc)) allHomes.push(val);
select.reduce((acc, val) => {
//save different homes if present
if (!deepEqual(val, acc)) allHomes.push(val);
return val;
},[]);
}, []);
result[elt] = allHomes;
} else if (elt === "DATE") {
} else if (elt === 'DATE') {
result[elt] = select[0];
} else if (elt === "TIMECODE") {
} else if (elt === 'TIMECODE') {
//DO NOTHING
} else if (typeof select[0] === "object" && select[0] != null) {
} else if (typeof select[0] === 'object' && select[0] != null) {
recursiveStatsExtraction(result[elt], select);
} else {
result[elt].min = select.reduce((acc,val) => val < acc && isNum(val) ? val : acc,Infinity);
result[elt].max = select.reduce((acc,val) => val > acc && isNum(val) ? val : acc,-Infinity);
result[elt].avg = select.reduce((acc,val) => isNum(val) ? acc+val : acc ,0)/select.length;
result[elt].min = select.reduce((acc, val) => (val < acc && isNum(val) ? val : acc), Infinity);
result[elt].max = select.reduce((acc, val) => (val > acc && isNum(val) ? val : acc), -Infinity);
result[elt].avg = select.reduce((acc, val) => (isNum(val) ? acc + val : acc), 0) / select.length;
}
}
return result;
}
};
let result = statsObject(arr[0]);
if (result.constructor === Object && Object.keys(result).length === 0) return null;
result = recursiveStatsExtraction(result,arr);
if (arr[arr.length-1].DIFFTIME != undefined) {
result.DURATION = arr[arr.length-1].DIFFTIME; //duration of video in milliseconds
} else if (arr[arr.length-1].DATE != undefined) {
result.DURATION = (new Date(arr[arr.length-1].DATE) - new Date(arr[0].DATE)); //duration of video in milliseconds
result = recursiveStatsExtraction(result, arr);
if (arr[arr.length - 1].DIFFTIME != undefined) {
result.DURATION = arr[arr.length - 1].DIFFTIME; //duration of video in milliseconds
} else if (arr[arr.length - 1].DATE != undefined) {
result.DURATION = new Date(arr[arr.length - 1].DATE) - new Date(arr[0].DATE); //duration of video in milliseconds
}
if (arr[arr.length-1].DISTANCE) {
result.DISTANCE = arr[arr.length-1].DISTANCE ; //dsitance of flight in meters
if (arr[arr.length - 1].DISTANCE != null) {
result.DISTANCE = arr[arr.length - 1].DISTANCE; //dsitance of flight in meters
}
return result;
}
let interpretPacket = function (pck) {
let interpretItem = function (key,datum) {//interprets known values to most useful data type
};
let interpretPacket = function(pck) {
let interpretItem = function(key, datum) {
//interprets known values to most useful data type
let interpretedI = {};
if (key.toUpperCase() === "GPS") {
if (key.toUpperCase() === 'GPS') {
interpretedI = {
LATITUDE:isNum(datum[1]) ? Number(datum[1]) : "n/a",
LONGITUDE:isNum(datum[0]) ? Number(datum[0]) : "n/a",
ALTITUDE:isNum(datum[2]) ? Number(datum[2]) : "n/a"
LATITUDE: isNum(datum[1]) ? Number(datum[1]) : 'n/a',
LONGITUDE: isNum(datum[0]) ? Number(datum[0]) : 'n/a',
ALTITUDE: isNum(datum[2]) ? Number(datum[2]) : 'n/a'
};
} else if (key.toUpperCase() === "HOME") {
} else if (key.toUpperCase() === 'HOME') {
interpretedI = {
LATITUDE:Number(datum[1]),
LONGITUDE:Number(datum[0])
LATITUDE: Number(datum[1]),
LONGITUDE: Number(datum[0])
};
} else if (key.toUpperCase() === "TIMECODE"){
} else if (key.toUpperCase() === 'TIMECODE') {
interpretedI = datum;
} else if (key.toUpperCase() === "DATE") {
} else if (key.toUpperCase() === 'DATE') {
const isoDateRegex = /[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]{3})?Z/;
let date = datum;
if (!isoDateRegex.exec(datum)) date = datum.replace(/\./g,"-").replace(" ","T").replace(/-([0-9](\b|[a-zA-Z]))/g,"-0$1").replace(/:(\w{3})-(\w{3})$/g,".$1");
if (!isoDateRegex.exec(datum))
date = datum
.replace(/\./g, '-')
.replace(' ', 'T')
.replace(/-([0-9](\b|[a-zA-Z]))/g, '-0$1')
.replace(/:(\w{3})-(\w{3})$/g, '.$1');
interpretedI = new Date(date).getTime();
} else if (key.toUpperCase() === "EV") {
} else if (key.toUpperCase() === 'EV') {
interpretedI = eval(datum);
} else if (key.toUpperCase() === "SHUTTER") {
interpretedI = Number(datum.replace("1/", ""));
} else if (key.toUpperCase() === "FNUM" && Number(datum) > 50) { //convert f numbers represented like 280
} else if (key.toUpperCase() === 'SHUTTER') {
interpretedI = Number(datum.replace('1/', ''));
} else if (key.toUpperCase() === 'FNUM' && Number(datum) > 50) {
//convert f numbers represented like 280
interpretedI = Number(datum) / 100;
} else {
interpretedI = Number(datum.replace(/[a-zA-Z]/g, ""));
interpretedI = Number(datum.replace(/[a-zA-Z]/g, ''));
}
if (interpretedI.constructor === Object && Object.keys(interpretedI).length === 0) return null;
return interpretedI;
}
};
let fillMissingFields = function(pckt) {
let replaceKey = function(o,old_key,new_key) {
let replaceKey = function(o, old_key, new_key) {
if (old_key !== new_key) {
Object.defineProperty(o, new_key,
Object.getOwnPropertyDescriptor(o, old_key));
delete o[old_key];
Object.defineProperty(o, new_key, Object.getOwnPropertyDescriptor(o, old_key));
delete o[old_key];
}
}
let references = {//translate keys form various formats
SHUTTER:["TV"],
FNUM:["IR"]
};
let references = {
//translate keys form various formats
SHUTTER: ['TV', 'SS'],
FNUM: ['IR', 'F']
};
for (let key in references) {

@@ -220,3 +260,3 @@ if (pckt[key] == undefined) {

if (pckt[match] != undefined) {
replaceKey(pckt,match,key);
replaceKey(pckt, match, key);
}

@@ -226,12 +266,12 @@ });

}
let latitude = pckt["LATITUDE"]; //Mavic 2 style
let longitude = pckt["LONGITUDE"] || pckt["LONGTITUDE"];
let altitude = pckt["ALTITUDE"] || pckt["BAROMETER"];
if (latitude != undefined && longitude != undefined ) {
let longitude = pckt["LONGITUDE"] || pckt["LONGTITUDE"];
let latitude = pckt['LATITUDE']; //Mavic 2 style
let longitude = pckt['LONGITUDE'] || pckt['LONGTITUDE'];
let altitude = pckt['ALTITUDE'] || pckt['BAROMETER'];
if (latitude != undefined && longitude != undefined) {
let longitude = pckt['LONGITUDE'] || pckt['LONGTITUDE'];
pckt.GPS = {
LONGITUDE:longitude,
LATITUDE:latitude
}
if (altitude != undefined ) {
LONGITUDE: longitude,
LATITUDE: latitude
};
if (altitude != undefined) {
pckt.GPS.ALTITUDE = altitude;

@@ -243,6 +283,6 @@ } else {

return pckt;
}
};
let interpretedP = {};
for (let item in pck) {
interpretedP[item.toUpperCase()] = interpretItem(item,pck[item]);
interpretedP[item.toUpperCase()] = interpretItem(item, pck[item]);
}

@@ -252,12 +292,13 @@ interpretedP = fillMissingFields(interpretedP);

return interpretedP;
}
let smoothenGPS = function(arr,amount) { //averages positions with the specified surrounding seconds. Necessary due to DJI's SRT logs low precision
};
let smoothenGPS = function(arr, amount) {
//averages positions with the specified surrounding seconds. Necessary due to DJI's SRT logs low precision
let smoothArr = JSON.parse(JSON.stringify(arr));
for (let i=0; i<arr.length; i++) {
let start = parseInt(i-amount);
let end = parseInt(i+amount);
for (let i = 0; i < arr.length; i++) {
let start = parseInt(i - amount);
let end = parseInt(i + amount);
let sums = {
LATITUDE:0,
LONGITUDE:0,
ALTITUDE:0
LATITUDE: 0,
LONGITUDE: 0,
ALTITUDE: 0
};

@@ -267,9 +308,9 @@ let latSkips = 0;

let altSkips = 0;
for (let j=start; j<end; j++) {
let k = Math.max(Math.min(j,arr.length-1),0);
for (let j = start; j < end; j++) {
let k = Math.max(Math.min(j, arr.length - 1), 0);
if (isNum(arr[k].GPS.LATITUDE)) {
sums.LATITUDE += arr[k].GPS.LATITUDE
sums.LATITUDE += arr[k].GPS.LATITUDE;
} else {
latSkips++;
};
}
if (isNum(arr[k].GPS.LONGITUDE)) {

@@ -286,21 +327,22 @@ sums.LONGITUDE += arr[k].GPS.LONGITUDE;

}
smoothArr[i].GPS.LATITUDE = sums.LATITUDE/(amount*2-latSkips);
smoothArr[i].GPS.LONGITUDE = sums.LONGITUDE/(amount*2-lonSkips);
smoothArr[i].GPS.ALTITUDE = sums.ALTITUDE/(amount*2-altSkips);
smoothArr[i].GPS.LATITUDE = sums.LATITUDE / (amount * 2 - latSkips);
smoothArr[i].GPS.LONGITUDE = sums.LONGITUDE / (amount * 2 - lonSkips);
smoothArr[i].GPS.ALTITUDE = sums.ALTITUDE / (amount * 2 - altSkips);
}
return smoothArr;
}
};
let newArr = arr.map(pck => interpretPacket(pck));
for (let i = 1; i<newArr.length; i++) {//loop back and forth to fill missing gps data with neighbours
for (let i = 1; i < newArr.length; i++) {
//loop back and forth to fill missing gps data with neighbours
if (newArr[i].GPS) {
if (!isNum(newArr[i].GPS.LATITUDE)) newArr[i].GPS.LATITUDE = newArr[i-1].GPS.LATITUDE;
if (!isNum(newArr[i].GPS.LONGITUDE)) newArr[i].GPS.LONGITUDE = newArr[i-1].GPS.LONGITUDE;
if (newArr[i].GPS.ALTITUDE && !isNum(newArr[i].GPS.ALTITUDE)) ewArr[i].GPS.ALTITUDE = newArr[i-1].GPS.ALTITUDE;
if (!isNum(newArr[i].GPS.LATITUDE)) newArr[i].GPS.LATITUDE = newArr[i - 1].GPS.LATITUDE;
if (!isNum(newArr[i].GPS.LONGITUDE)) newArr[i].GPS.LONGITUDE = newArr[i - 1].GPS.LONGITUDE;
if (newArr[i].GPS.ALTITUDE && !isNum(newArr[i].GPS.ALTITUDE)) ewArr[i].GPS.ALTITUDE = newArr[i - 1].GPS.ALTITUDE;
}
}
for (let i = newArr.length-2; i>=0; i--) {
for (let i = newArr.length - 2; i >= 0; i--) {
if (newArr[i].GPS) {
if (!isNum(newArr[i].GPS.LATITUDE)) newArr[i+1].GPS.LATITUDE;
if (!isNum(newArr[i].GPS.LONGITUDE)) newArr[i+1].GPS.LONGITUDE;
if (newArr[i].GPS.ALTITUDE != null && !isNum(newArr[i].GPS.ALTITUDE)) newArr[i+1].GPS.ALTITUDE;
if (!isNum(newArr[i].GPS.LATITUDE)) newArr[i + 1].GPS.LATITUDE;
if (!isNum(newArr[i].GPS.LONGITUDE)) newArr[i + 1].GPS.LONGITUDE;
if (newArr[i].GPS.ALTITUDE != null && !isNum(newArr[i].GPS.ALTITUDE)) newArr[i + 1].GPS.ALTITUDE;
}

@@ -311,4 +353,4 @@ }

if (newArr[0].GPS) {
if (smoothing !== 0) {
newArr = smoothenGPS(newArr,smoothing);
if (smoothing !== 0) {
newArr = smoothenGPS(newArr, smoothing);
}

@@ -320,12 +362,13 @@ this.smoothened = smoothing;

if (newArr.length < 1) {
console.log("Error intrerpreting metadata");
console.log('Error intrerpreting metadata');
return null;
}
return {
packets:newArr,
stats:stats
}
}
packets: newArr,
stats: stats
};
};
function getElevation(src) {//GPS elevation data is almost useless, so we replace with barometer if available
function getElevation(src) {
//GPS elevation data is almost useless, so we replace with barometer if available
if (src.BAROMETER != undefined) {

@@ -344,48 +387,48 @@ return src.BAROMETER;

DJI_SRT_Parser.prototype.createCSV = function(raw) {
let csvExtract = function(obj,pre,val) {
let prefix = pre ? pre+"_" : "";
let csvExtract = function(obj, pre, val) {
let prefix = pre ? pre + '_' : '';
let results = [];
for (let elt in obj) {
if (typeof obj[elt] === "object" && obj[elt] != null) {
let children = csvExtract(obj[elt],prefix+elt,val);
children.forEach(child => results.push(child));
} else if (val) {
results.push(JSON.stringify(obj[elt]));
} else {
results.push(prefix+elt);
}
if (typeof obj[elt] === 'object' && obj[elt] != null) {
let children = csvExtract(obj[elt], prefix + elt, val);
children.forEach(child => results.push(child));
} else if (val) {
results.push(JSON.stringify(obj[elt]));
} else {
results.push(prefix + elt);
}
}
return results.length ? results : null;
}
};
let rows = [];
let array = raw ? this.rawMetadata : this.metadata.packets;
rows.push(csvExtract(array[0]));
array.forEach(pck => rows.push(csvExtract(pck,"",true)));
if (rows.length <1) return null;
array.forEach(pck => rows.push(csvExtract(pck, '', true)));
if (rows.length < 1) return null;
let csvContent;
csvContent = rows.reduce((acc,rowArray) => {
let row = rowArray.join(",");
return acc + row + "\r\n";
},"");
csvContent = rows.reduce((acc, rowArray) => {
let row = rowArray.join(',');
return acc + row + '\r\n';
}, '');
if (!csvContent) {
console.log("Error creating CSV");
console.log('Error creating CSV');
return null;
}
return csvContent;
}
};
DJI_SRT_Parser.prototype.createGeoJSON = function(raw) {
function GeoJSONExtract(obj,raw) {
let extractProps = function(childObj,pre) {
function GeoJSONExtract(obj, raw) {
let extractProps = function(childObj, pre) {
let results = [];
for (let child in childObj) {
if (typeof childObj[child] === "object" && childObj[child] != null ) {
let children = extractProps(childObj[child],pre + "_" + child);
if (typeof childObj[child] === 'object' && childObj[child] != null) {
let children = extractProps(childObj[child], pre + '_' + child);
children.forEach(child => results.push(child));
} else {
results.push({name: pre + "_" + child, value: childObj[child]});
results.push({ name: pre + '_' + child, value: childObj[child] });
}
}
return results;
}
};
let extractCoordinates = function(coordsObj) {

@@ -403,7 +446,7 @@ let coordResult = [];

return coordResult;
}
};
let result = {
type: "Feature",
type: 'Feature',
geometry: {
type: "Point",
type: 'Point',
coordinates: []

@@ -415,16 +458,16 @@ },

for (let elt in obj) {
if (elt === "DATE") {
if (elt === 'DATE') {
result.properties.timestamp = obj[elt];
} else if (elt === "GPS") {
} else if (elt === 'GPS') {
result.geometry.coordinates = extractCoordinates(obj[elt]);
// } else if (elt === "HOME") {//no, readers don't understand it
// result.properties.HOME = {
// type: "Feature",
// geometry: {
// type: "Point",
// coordinates: extractCoordinates(obj[elt])
// },
// };
} else if (typeof obj[elt] === "object" && obj[elt] != null) {
let children = extractProps(obj[elt],elt);
// } else if (elt === "HOME") {//no, readers don't understand it
// result.properties.HOME = {
// type: "Feature",
// geometry: {
// type: "Point",
// coordinates: extractCoordinates(obj[elt])
// },
// };
} else if (typeof obj[elt] === 'object' && obj[elt] != null) {
let children = extractProps(obj[elt], elt);
children.forEach(child => {

@@ -438,3 +481,4 @@ result.properties[child.name] = child.value;

if (!raw) {//only modify elevation if user does want interpreted data, not raw
if (!raw) {
//only modify elevation if user does want interpreted data, not raw
let bestElevation = getElevation(obj);

@@ -449,18 +493,17 @@ if (bestElevation != null) {

let GeoJSONContent = {
type: "FeatureCollection",
type: 'FeatureCollection',
features: []
}
};
let array = raw ? this.rawMetadata : this.metadata.packets;
array.forEach(pck => GeoJSONContent.features.push(GeoJSONExtract(pck,raw)));
array.forEach(pck => GeoJSONContent.features.push(GeoJSONExtract(pck, raw)));
let createLinestring = function(features) {
let result = {
type: "Feature",
type: 'Feature',
properties: {
"source": "dji-srt-parser",
timestamp: [],
source: 'dji-srt-parser',
timestamp: []
},
geometry: {
type: "LineString",
type: 'LineString',
coordinates: []

@@ -472,3 +515,17 @@ }

for (let prop in props) {
if (!["DATE","TIMECODE","GPS","timestamp","BAROMETER","DISTANCE","SPEED_THREED","SPEED_TWOD","SPEED_VERTICAL","HB","HS"].includes(prop)) {
if (
![
'DATE',
'TIMECODE',
'GPS',
'timestamp',
'BAROMETER',
'DISTANCE',
'SPEED_THREED',
'SPEED_TWOD',
'SPEED_VERTICAL',
'HB',
'HS'
].includes(prop)
) {
result.properties[prop] = props[prop];

@@ -483,3 +540,3 @@ }

return result;
}
};

@@ -489,3 +546,3 @@ GeoJSONContent.features.push(createLinestring(GeoJSONContent.features));

if (!GeoJSONContent.features) {
console.log("Error creating GeoJSON");
console.log('Error creating GeoJSON');
return null;

@@ -495,5 +552,5 @@ }

return JSON.stringify(GeoJSONContent);
}
};
DJI_SRT_Parser.prototype.loadFile = function(data,fileName,preparedData) {
DJI_SRT_Parser.prototype.loadFile = function(data, fileName, preparedData) {
let context = this;

@@ -503,14 +560,17 @@ this.fileName = fileName;

let decode = function(d) {
if (typeof d ==="string" && d.split(",")[0].includes("base64")) {
return atob(d.split(",")[1]);
if (typeof d === 'string' && d.split(',')[0].includes('base64')) {
return atob(d.split(',')[1]);
} else {
return d;
}
}
this.flow(decode(data),preparedData);
}
};
this.flow(
decode(data),
preparedData
);
};
DJI_SRT_Parser.prototype.flow = function(data,preparedData) {
DJI_SRT_Parser.prototype.flow = function(data, preparedData) {
if (preparedData) {
this.rawMetadata = JSON.parse(data);
this.rawMetadata = JSON.parse(preparedData);
} else {

@@ -521,6 +581,6 @@ this.rawMetadata = this.srtToObject(data);

this.loaded = true;
}
};
function notReady() {
console.log("Data not ready");
console.log('Data not ready');
return null;

@@ -533,20 +593,38 @@ }

function toExport(context,file,fileName,preparedData) {
context.loadFile(file,fileName,preparedData);
function toExport(context, file, fileName, preparedData) {
context.loadFile(file, fileName, preparedData);
return {
getSmoothing:function() {return context.loaded ? context.smoothened : notReady()},
setSmoothing:function(smooth) {if (context.loaded) {context.metadata = context.interpretMetadata(context.rawMetadata,smooth)} else {notReady()}},
rawMetadata:function() {return context.loaded ? context.rawMetadata : notReady()},
metadata:function() {return context.loaded ? context.metadata : notReady()},
toCSV:function(raw) {return context.loaded ? context.createCSV(raw) : notReady()},
toGeoJSON:function(raw) {return context.loaded ? context.createGeoJSON(raw) : notReady()},
getFileName:function() {return context.loaded ? context.fileName : notReady()}
}
getSmoothing: function() {
return context.loaded ? context.smoothened : notReady();
},
setSmoothing: function(smooth) {
if (context.loaded) {
context.metadata = context.interpretMetadata(context.rawMetadata, smooth);
} else {
notReady();
}
},
rawMetadata: function() {
return context.loaded ? context.rawMetadata : notReady();
},
metadata: function() {
return context.loaded ? context.metadata : notReady();
},
toCSV: function(raw) {
return context.loaded ? context.createCSV(raw) : notReady();
},
toGeoJSON: function(raw) {
return context.loaded ? context.createGeoJSON(raw) : notReady();
},
getFileName: function() {
return context.loaded ? context.fileName : notReady();
}
};
}
function create_DJI_SRT_Parser(file,fileName,preparedData) {
function create_DJI_SRT_Parser(file, fileName, preparedData) {
try {
var instance = new DJI_SRT_Parser();
return toExport(instance,file,fileName,preparedData);
return toExport(instance, file, fileName, preparedData);
} catch (err) {

@@ -553,0 +631,0 @@ console.log(err);

@@ -104,1 +104,13 @@ function preload(file) {

});
//p4p attempt
data = preload(`./samples/p4p_sample.SRT`);
let p4p = DJISRTParser(data, 'p4p_sample.SRT');
test('p4p Format result should contain metadata', () => {
expect(p4p.metadata()).toBeDefined();
});
test('The max altitude should be readable from the ALTITUDE field', () => {
expect(p4p.metadata().stats.GPS.ALTITUDE.max).toBe(18);
});
test('We should be able to read the aperture in the p4p format', () => {
expect(p4p.metadata().packets[0].FNUM).toBe(3.2);
});
{
"name": "dji_srt_parser",
"version": "1.0.30",
"version": "1.0.31",
"description": "Parses and interprets DJI's drones SRT metadata",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -7,3 +7,2 @@ 'use_strict';

let rawFile = new XMLHttpRequest();
let allText;
rawFile.open('GET', file, true);

@@ -39,3 +38,3 @@ rawFile.onreadystatechange = function() {

let files = ['mavic_pro', 'mavic_air', 'old_format', 'mavic_pro_buggy', 'mavic_2_style'];
let files = ['mavic_pro', 'mavic_air', 'old_format', 'mavic_pro_buggy', 'mavic_2_style', 'p4p_sample'];
let DJISRTParser = require('../index');

@@ -63,2 +62,3 @@ let i = 0;

let elevation;
if (DJIfile.metadata().stats.BAROMETER) {

@@ -65,0 +65,0 @@ elevation = DJIfile.metadata().stats.BAROMETER.max;

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc