Skip to content

Commit e5de3e6

Browse files
authored
Add huawei motree cm parser #139
2 parents 55ec07f + ac0332a commit e5de3e6

File tree

14 files changed

+186
-27
lines changed

14 files changed

+186
-27
lines changed

background/background-process.html

Lines changed: 103 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,32 @@ <h1>Background process</h1>
345345
}
346346

347347

348+
349+
/**
350+
* Clean Huawei GExport files.
351+
*
352+
* sed -i -r "
353+
* s/<MO className="(BSC6900GSM|BSC6900UMTS|BSC6900GU|BSC6910GSM|BSC6910UMTS|BSC6910GU)(.*)/<MO className="\1/ig;
354+
* " /mediation/data/cm/huawei/raw/motree/*.xml
355+
*
356+
* @exportFolder String Folder with the MO Tree dump XML files to be cleaned
357+
*/
358+
cleanHuaweiMOTreeFiles = async (exportFolder) => {
359+
const replaceOptions = {
360+
files: path.join(exportFolder,'*'),
361+
from: [
362+
/<MO className="(BSC6900GSM|BSC6900UMTS|BSC6900GU|BSC6910GSM|BSC6910UMTS|BSC6910GU)/g
363+
],
364+
to: [
365+
"<MO className=\""
366+
],
367+
};
368+
369+
return await replace.sync(replaceOptions)
370+
}
371+
372+
373+
348374
/*Use gnu sed.exe on windows
349375
*
350376
*/
@@ -379,6 +405,42 @@ <h1>Background process</h1>
379405

380406
}
381407

408+
409+
/*
410+
* Clean Huawei MO Tree XML files.
411+
* @param string inputFolder
412+
*/
413+
cleanHuaweiMOTreeWithSed = (inputFolder) => {
414+
let libPath = app.getAppPath();
415+
416+
if (!isDev) {
417+
libPath = process.resourcesPath;
418+
}
419+
420+
let files = fs.readdirSync(inputFolder, { withFileTypes: true }).filter(dirent => !dirent.isDirectory()).map(dirent => dirent.name);
421+
422+
const sedScript = path.join(libPath,'libraries', 'motree_cleanup.sed');
423+
const sed = path.join(libPath,'libraries','sed.exe');
424+
425+
for (let i=0; i<files.length; i++) {
426+
f = files[i];
427+
inputFile = path.join(inputFolder,f);
428+
429+
log.info(`Cleaning ${f}...`);
430+
sendLogToUI('parse_data','info', `Cleaning ${f}...`);
431+
432+
const child = spawnSync(sed, ['-i', '-r', '-f', sedScript, inputFile]);
433+
log.info(`${sed} -i -r -f ${sedScript} ${inputFile}`);
434+
435+
if(child.error){
436+
log.info(`[parse_cm_job] error:${child.error.toString()}`);
437+
throw child.error.toString();
438+
}
439+
}
440+
441+
}
442+
443+
382444
/*
383445
* Take the latest file when there is more than one file from the same node .
384446
*
@@ -460,7 +522,7 @@ <h1>Background process</h1>
460522
removeDublicateHuaweiGExportFiles(inputFolder)
461523

462524
log.info(`[parse_cm_job] Uncompressing files GExport XML files...`)
463-
sendLogToUI('parse_data','info',`Uncompressing files GExport XML files...` );
525+
sendLogToUI('parse_data','info',"Uncompressing files GExport XML files...");
464526

465527
uncompressFolder(inputFolder);
466528

@@ -488,17 +550,53 @@ <h1>Background process</h1>
488550
}
489551

490552
}
553+
554+
//Clean Huawei MOTree files
555+
else if(vendor === 'HUAWEI' && format === 'MOTREE_XML'){
556+
try{
557+
558+
log.info(`Uncompressing files MOTree XML files...`);
559+
sendLogToUI('parse_data','info', "Uncompressing files MOTree XML files...");
560+
561+
uncompressFolder(inputFolder);
562+
563+
log.info(`Uncompressing files MOTree XML files...`)
564+
sendLogToUI('parse_data','info',"Cleaning MOTree XML files...");
565+
566+
if(process.platform === "win32"){
567+
//If windows test, with sed.exe
568+
cleanHuaweiMOTreeWithSed(inputFolder);
569+
}else{
570+
await cleanHuaweiMOTreeFiles(inputFolder);
571+
}
572+
573+
log.info(`Cleanup of MOTree XML files completed.`);
574+
sendLogToUI('parse_data','info',"Cleanup of MOTree XML files completed.");
575+
576+
}catch(error){
577+
log.error('Error occurred:', error);
578+
if(typeof error === 'undefined'){
579+
sendLogToUI('parse_data','error', 'Error occured.');
580+
return;
581+
}
582+
sendLogToUI('parse_data','error',error.toString());
583+
return;
584+
}
585+
586+
}
587+
588+
491589
//Uncompress files for other vendor format combinations except huawei gexport
492590
//The reason for this is we want to first remove the duplicates in the dumps, before wasting time
493591
//uncompressing what does not need to be uncompressed
494-
//else if(vendor !== 'HUAWEI' && format !== 'GEXPORT_XML'){
592+
//else if(vendor !== 'HUAWEI' && (format !== 'GEXPORT_XML' || format !== 'MOTREE_XML')){
495593
else{
496-
sendLogToUI('parse_data','info',`Uncompressing files...` );
497-
log.info(`Uncompressing files...`)
594+
sendLogToUI('parse_data','info',"Uncompressing files...");
595+
log.info("Uncompressing files...")
498596
uncompressFolder(inputFolder);
499597
}
500598

501-
sendLogToUI('parse_data','info', `Parsing files...`);
599+
sendLogToUI('parse_data','info', "Parsing files...");
502600
log.info("Parsing files...")
503601

504602

background/boda-cell-file.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ const BCF_4G_PARAMS = {
8080
longitude: {required: true},
8181
height: {},
8282
vendor: {},
83-
cell_type: {}
83+
cell_type: {},
84+
localcellid: {}
8485
};
8586

8687
const BCF_5G_PARAMS = {

background/tems.js

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,10 @@ function generateParameterInsertQuery(fields, values){
181181

182182
paramNames.forEach((p, i) => {
183183

184-
185184
//Skip parameter that are not there
186185
if(fields.indexOf(p) === -1 ) return;
187186

188-
paramValues[i] = values[fields.indexOf(p)];
187+
paramValues[i] = values[fields.indexOf(p)] === undefined ? "" : values[fields.indexOf(p)];
189188
updatePhrase.push(`${p} = EXCLUDED.${p}`);
190189
});
191190

@@ -197,8 +196,7 @@ function generateParameterInsertQuery(fields, values){
197196
SET
198197
${updatePhrase.join(",")}
199198
`;
200-
201-
//console.log(sql)
199+
202200
return sql;
203201

204202
}
@@ -429,7 +427,9 @@ async function loadXMLFile(fileName){ //@TODO: Confirm file is XML
429427
"longitude",
430428
"height",
431429
"vendor",
432-
"cell_type"
430+
"cell_type",
431+
"ci",
432+
"localcellid"
433433
]
434434

435435
//GSM_CELL
@@ -647,7 +647,10 @@ async function loadXMLFile(fileName){ //@TODO: Confirm file is XML
647647

648648
if(child.nodeName === 'LOCALCELLID') paramValues['localcellid'] = child.firstChild.data;
649649

650+
//pci
650651
if(child.nodeName === 'PCI') paramValues['pci'] = child.firstChild.data;
652+
if(child.nodeName === 'PHYSICAL_LAYER_CELL_ID') paramValues['pci'] = child.firstChild.data;
653+
651654

652655
if(child.nodeName === 'EARFCN_DL') paramValues['euarfcn'] = child.firstChild.data;
653656

@@ -668,6 +671,22 @@ async function loadXMLFile(fileName){ //@TODO: Confirm file is XML
668671

669672
if(child.nodeName === 'ENODE_B_STATUS') paramValues['status'] = child.firstChild.data;
670673

674+
//CGI
675+
if(child.nodeName === 'LTE_CGI'){
676+
const children2 = child.childNodes;
677+
for(var j =0; j < children2.length; j++){
678+
const child2 = children2[j];
679+
680+
if( typeof child2.localName === 'undefined') continue;
681+
682+
if(child2.nodeName === 'MCC') paramValues['mcc'] = child2.firstChild.data;
683+
if(child2.nodeName === 'MNC') paramValues['mnc'] = child2.firstChild.data;
684+
if(child2.nodeName === 'TAC') paramValues['tac'] = child2.firstChild.data;
685+
}
686+
687+
paramValues['cgi'] = `${paramValues["mcc"]}-${paramValues["mnc"]}-${paramValues["lac"]}-${paramValues["ci"]}`
688+
}
689+
671690
//POSITION
672691
if(child.nodeName === 'POSITION'){
673692
const children2 = child.childNodes;
@@ -699,10 +718,14 @@ async function loadXMLFile(fileName){ //@TODO: Confirm file is XML
699718
paramValues['technology'] = 'lte';
700719
paramValues['node'] = paramValues['siteid'] || "ENODEB";
701720

702-
const bcfLTEValues = lteBcfFields.map(v => paramValues[v] || '');
721+
paramValues['ci'] = paramValues['ci'] || paramValues['pci'];
722+
paramValues['localcellid'] = paramValues['localcellid'] === undefined ? "0" : '';
703723

704-
const InsertQry = generateParameterInsertQuery(lteBcfFields, bcfLTEValues);
705-
await queryHelper.runQuery(InsertQry);
724+
const bcfLTEValues = lteBcfFields.map(v => paramValues[v] === undefined ? "" : paramValues[v]);
725+
726+
const insertQry = generateParameterInsertQuery(lteBcfFields, bcfLTEValues);
727+
728+
await queryHelper.runQuery(insertQry);
706729

707730
node = nodes.iterateNext()
708731
}

background/vendor-formats.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const VENDOR_CM_FORMATS = {
22
'ERICSSON': ['BULKCM','CNAIV2','BSM','EAW'],
3-
'HUAWEI': ['GEXPORT_XML','NBI_XML','CFGMML', 'AUTOBAK_XML'],
3+
'HUAWEI': ['GEXPORT_XML','NBI_XML','CFGMML', 'AUTOBAK_XML', 'MOTREE_XML'],
44
'ZTE': ['BULKCM','XLS'],
55
'NOKIA': ['RAML'],
66
'BODASTAGE': ['BCF_CSV']
@@ -35,7 +35,8 @@ const VENDOR_CM_PARSERS = {
3535
'GEXPORT_XML': 'boda-huaweicmobjectparser.jar',
3636
'CFGMML': 'boda-huaweimmlparser.jar',
3737
'NBI_XML': 'boda-huaweicmxmlparser.jar',
38-
'AUTOBAK_XML': 'boda-huaweicfgsynparser.jar'
38+
'AUTOBAK_XML': 'boda-huaweicfgsynparser.jar',
39+
'MOTREE_XML': 'boda-huaweicmmotreeparser.jar'
3940
},
4041
'ZTE': {
4142
'BULKCM': 'boda-bulkcmparser.jar',
748 KB
Binary file not shown.

libraries/motree_cleanup.sed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
s/<MO className="(BSC6900GSM|BSC6900UMTS|BSC6900GU|BSC6910GSM|BSC6910UMTS|BSC6910GU)(.*)/<MO className="\2/g;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "Boda-Lite",
3-
"version": "0.4.2",
3+
"version": "0.4.3",
44
"description": "Boda-Lite is a telecommunication network management application",
55
"private": true,
66
"homepage": "./",

src/modules/cm/VendorFormats.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export const VENDOR_CM_FORMATS = {
22
'ERICSSON': ['BULKCM','CNAIV2','BSM','EAW'],
3-
'HUAWEI': ['GEXPORT_XML','NBI_XML','CFGMML', 'AUTOBAK_XML'],
3+
'HUAWEI': ['GEXPORT_XML','NBI_XML','CFGMML', 'AUTOBAK_XML', "MOTREE_XML"],
44
'ZTE': ['BULKCM','XLS'],
55
'NOKIA': ['RAML'],
66
'MOTOROLA': ['CELL_X_EXPORT'],

src/modules/reports/ReportsTree.jsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,8 @@ class ReportsTree extends React.Component{
102102
<Menu>
103103
<MenuItem icon="th" text="View report" onClick={(ev) => {ev.preventDefault(); this.showReportDataTab(node.label, node.reportId);}}/>
104104
{node.inBuilt === true ? "" : <MenuItem icon="graph-remove" text="Delete report" onClick={(ev) => {ev.preventDefault(); this.removeReport(node.reportId);}}/> }
105-
{node.inBuilt === true || node.type === 'composite' ?
106-
<MenuItem icon="edit" text="Edit report" onClick={(ev) => {ev.preventDefault(); this.createCompositeReport(node.reportId)}} /> :
107-
<MenuItem icon="edit" text="Edit report" onClick={(ev) => {ev.preventDefault(); this.showEditTab(node.reportId)}} /> }
105+
{ node.inBuilt === false && node.type === 'composite' ? <MenuItem icon="edit" text="Edit report" onClick={(ev) => {ev.preventDefault(); this.createCompositeReport(node.reportId)}} /> : "" }
106+
{ node.inBuilt === false && node.type !== 'composite' ? <MenuItem icon="edit" text="Edit report" onClick={(ev) => {ev.preventDefault(); this.createCompositeReport(node.reportId)}} /> : "" }
108107

109108
</Menu>,
110109
{ left: e.clientX, top: e.clientY },

src/modules/utilities/KMLGenerator.jsx

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,25 @@ class KMLGenerator extends React.Component {
12471247
Specify the fields to show in the details popup dialog when each cell is clicked.
12481248
</div>
12491249
);
1250+
1251+
1252+
const radiusHelpContent = (
1253+
<div>
1254+
Specifiy the coverage radius in this section. The radius value can be <br/>
1255+
manaully in-put, selected from a column in the data file or can depend a series of conditions
1256+
</div>
1257+
);
1258+
1259+
const colorHelpContent = (
1260+
<div>
1261+
Pick or provide the color to use for the cell. If the color is manually <br />
1262+
provided, a <b>hexadecimal</b> color value of the form "<code>#FFFFFF</code>" is <br />
1263+
expected.
1264+
</div>
1265+
);
1266+
1267+
1268+
//
12501269

12511270
const processing = this.state.processing || this.props.processing;
12521271

@@ -1437,7 +1456,14 @@ class KMLGenerator extends React.Component {
14371456
<div>
14381457
<h6 className="horizontal-line">
14391458
<span className="horizontal-line-text">
1440-
Radius <Icon icon="chevron-right" />
1459+
Radius &nbsp;
1460+
<AntPopover
1461+
content={radiusHelpContent}
1462+
title={"? Radius"}
1463+
>
1464+
<Icon icon="info-sign" />
1465+
</AntPopover>
1466+
<Icon icon="chevron-right" />
14411467
</span>
14421468
</h6>
14431469
</div>
@@ -1454,7 +1480,16 @@ class KMLGenerator extends React.Component {
14541480
<div>
14551481
<h6 className="horizontal-line">
14561482
<span className="horizontal-line-text">
1457-
Colors <Icon icon="chevron-right" />
1483+
1484+
Colors &nbsp;
1485+
<AntPopover
1486+
content={colorHelpContent}
1487+
title={"? Color"}
1488+
>
1489+
<Icon icon="info-sign" />
1490+
</AntPopover>
1491+
<Icon icon="chevron-right" />
1492+
14581493
</span>
14591494
</h6>
14601495
</div>

0 commit comments

Comments
 (0)