Rene Fichtmueller 1c1b8e1e9d feat: Huawei OEM transceiver seed + scheduler
Add 43 Huawei OEM PIDs covering CloudEngine/NetEngine platform:
SFP-GE/SFP+-10G/SFP28-25G/QSFP+-40G/QSFP28-100G/QSFP56-200G/
QSFP-DD-400G/OSFP-800G + DAC. Includes BOM alias codes.
Scheduler: daily 05:00.
2026-04-26 19:16:16 +02:00

155 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Huawei OEM Transceiver Catalog Seed
*
* Seeds Huawei-branded transceiver PIDs into the transceivers table.
* Huawei uses descriptive part numbers (SFP-GE-SX-MM850-A, etc.)
* and numeric codes (02315658, etc.).
*
* Sources:
* - Huawei Optical Module Compatibility List (public)
* - CloudEngine/NetEngine/S-series hardware compatibility guides
* - enterprise.huawei.com product pages
*
* Run: tsx packages/scraper/src/scrapers/huawei-oem.ts
* Cron: daily at 05:00
*/
import { pool, ensureVendor } from "../utils/db";
interface HuaweiPID {
pid: string;
alias?: string; // numeric BOM code
formFactor: string;
speedGbps: number;
speed: string;
reachMeters: number;
reachLabel: string;
fiberType: string;
connector: string;
wavelengths?: string;
standard?: string;
notes?: string;
}
const HUAWEI_PIDS: HuaweiPID[] = [
// ── 1G SFP ──────────────────────────────────────────────────────────────
{ pid: "SFP-GE-SX-MM850-A", alias: "02315658", formFactor: "SFP", speedGbps: 1, speed: "1G", reachMeters: 550, reachLabel: "SX", fiberType: "MMF", connector: "LC", wavelengths: "850nm", standard: "1000BASE-SX" },
{ pid: "SFP-GE-LX-SM1310-A", alias: "02315659", formFactor: "SFP", speedGbps: 1, speed: "1G", reachMeters: 10000, reachLabel: "LX", fiberType: "SMF", connector: "LC", wavelengths: "1310nm", standard: "1000BASE-LX" },
{ pid: "SFP-GE-LH-SM1310", alias: "02315661", formFactor: "SFP", speedGbps: 1, speed: "1G", reachMeters: 40000, reachLabel: "LH40", fiberType: "SMF", connector: "LC", wavelengths: "1310nm" },
{ pid: "SFP-GE-LH-SM1550", alias: "02315662", formFactor: "SFP", speedGbps: 1, speed: "1G", reachMeters: 80000, reachLabel: "ZX", fiberType: "SMF", connector: "LC", wavelengths: "1550nm", standard: "1000BASE-ZX" },
{ pid: "SFP-GE-T", alias: "02315663", formFactor: "SFP", speedGbps: 1, speed: "1G", reachMeters: 100, reachLabel: "T", fiberType: "DAC", connector: "RJ45", standard: "1000BASE-T" },
{ pid: "SFP-GE-SX-MM850-E", formFactor: "SFP", speedGbps: 1, speed: "1G", reachMeters: 550, reachLabel: "SX", fiberType: "MMF", connector: "LC", wavelengths: "850nm", notes: "Extended temp" },
// ── 10G SFP+ ────────────────────────────────────────────────────────────
{ pid: "SFP+-10G-SR-MM850", alias: "02310YMU", formFactor: "SFP+", speedGbps: 10, speed: "10G", reachMeters: 300, reachLabel: "SR", fiberType: "MMF", connector: "LC", wavelengths: "850nm", standard: "10GBASE-SR" },
{ pid: "SFP+-10G-LR-SM1310", alias: "02310YMT", formFactor: "SFP+", speedGbps: 10, speed: "10G", reachMeters: 10000, reachLabel: "LR", fiberType: "SMF", connector: "LC", wavelengths: "1310nm", standard: "10GBASE-LR" },
{ pid: "SFP+-10G-ER-SM1550", alias: "02310YMV", formFactor: "SFP+", speedGbps: 10, speed: "10G", reachMeters: 40000, reachLabel: "ER", fiberType: "SMF", connector: "LC", wavelengths: "1550nm", standard: "10GBASE-ER" },
{ pid: "SFP+-10G-ZR-SM1550", formFactor: "SFP+", speedGbps: 10, speed: "10G", reachMeters: 80000, reachLabel: "ZR", fiberType: "SMF", connector: "LC", wavelengths: "1550nm", standard: "10GBASE-ZR" },
{ pid: "SFP+-10G-LRM", formFactor: "SFP+", speedGbps: 10, speed: "10G", reachMeters: 220, reachLabel: "LRM", fiberType: "MMF", connector: "LC", wavelengths: "1310nm", standard: "10GBASE-LRM" },
// ── 25G SFP28 ───────────────────────────────────────────────────────────
{ pid: "SFP28-25G-SR-MM850", alias: "02312KYP", formFactor: "SFP28", speedGbps: 25, speed: "25G", reachMeters: 100, reachLabel: "SR", fiberType: "MMF", connector: "LC", wavelengths: "850nm", standard: "25GBASE-SR" },
{ pid: "SFP28-25G-LR-SM1310", alias: "02312KYQ", formFactor: "SFP28", speedGbps: 25, speed: "25G", reachMeters: 10000, reachLabel: "LR", fiberType: "SMF", connector: "LC", wavelengths: "1310nm", standard: "25GBASE-LR" },
{ pid: "SFP28-25G-ER-SM1310", formFactor: "SFP28", speedGbps: 25, speed: "25G", reachMeters: 30000, reachLabel: "ER", fiberType: "SMF", connector: "LC", wavelengths: "1310nm" },
// ── 40G QSFP+ ───────────────────────────────────────────────────────────
{ pid: "QSFP+-40G-SR4-MM850", alias: "02310YLQ", formFactor: "QSFP+", speedGbps: 40, speed: "40G", reachMeters: 150, reachLabel: "SR4", fiberType: "MMF", connector: "MPO", wavelengths: "850nm", standard: "40GBASE-SR4" },
{ pid: "QSFP+-40G-LR4-SM1310", alias: "02310YLR", formFactor: "QSFP+", speedGbps: 40, speed: "40G", reachMeters: 10000, reachLabel: "LR4", fiberType: "SMF", connector: "LC", wavelengths: "1310nm", standard: "40GBASE-LR4" },
{ pid: "QSFP+-40G-ER4-SM1310", formFactor: "QSFP+", speedGbps: 40, speed: "40G", reachMeters: 40000, reachLabel: "ER4", fiberType: "SMF", connector: "LC", wavelengths: "1310nm", standard: "40GBASE-ER4" },
{ pid: "QSFP+-4X10G-SR-MM850", formFactor: "QSFP+", speedGbps: 40, speed: "40G", reachMeters: 300, reachLabel: "4x10G-SR",fiberType:"MMF",connector: "MPO", notes: "4×10G breakout" },
// ── 100G QSFP28 ─────────────────────────────────────────────────────────
{ pid: "QSFP28-100G-SR4-MM850", alias: "02312XKT", formFactor: "QSFP28",speedGbps: 100, speed: "100G", reachMeters: 100, reachLabel: "SR4", fiberType: "MMF", connector: "MPO", wavelengths: "850nm", standard: "100GBASE-SR4" },
{ pid: "QSFP28-100G-LR4-SM1310", alias: "02312XKU", formFactor: "QSFP28",speedGbps: 100, speed: "100G", reachMeters: 10000, reachLabel: "LR4", fiberType: "SMF", connector: "LC", wavelengths: "1295-1310nm", standard: "100GBASE-LR4" },
{ pid: "QSFP28-100G-ER4-SM1310", formFactor: "QSFP28",speedGbps: 100, speed: "100G", reachMeters: 30000, reachLabel: "ER4", fiberType: "SMF", connector: "LC", wavelengths: "1295-1310nm" },
{ pid: "QSFP28-100G-CWDM4", formFactor: "QSFP28",speedGbps: 100, speed: "100G", reachMeters: 2000, reachLabel: "CWDM4",fiberType: "SMF", connector: "LC", wavelengths: "1271-1331nm", standard: "100GBASE-CWDM4" },
{ pid: "QSFP28-100G-PSM4", formFactor: "QSFP28",speedGbps: 100, speed: "100G", reachMeters: 500, reachLabel: "PSM4", fiberType: "SMF", connector: "MPO", wavelengths: "1310nm" },
{ pid: "QSFP28-100G-DR", formFactor: "QSFP28",speedGbps: 100, speed: "100G", reachMeters: 500, reachLabel: "DR", fiberType: "SMF", connector: "LC", wavelengths: "1310nm", standard: "100GBASE-DR" },
{ pid: "QSFP28-100G-FR", formFactor: "QSFP28",speedGbps: 100, speed: "100G", reachMeters: 2000, reachLabel: "FR", fiberType: "SMF", connector: "LC", wavelengths: "1310nm", standard: "100GBASE-FR" },
{ pid: "QSFP28-100G-ZR4-SM1550", formFactor: "QSFP28",speedGbps: 100, speed: "100G", reachMeters: 80000, reachLabel: "ZR4", fiberType: "SMF", connector: "LC", wavelengths: "C-band", notes: "Coherent DWDM" },
// ── 200G QSFP56 ─────────────────────────────────────────────────────────
{ pid: "QSFP56-200G-SR4", formFactor: "QSFP56",speedGbps: 200, speed: "200G", reachMeters: 100, reachLabel: "SR4", fiberType: "MMF", connector: "MPO", wavelengths: "850nm" },
{ pid: "QSFP56-200G-FR4", formFactor: "QSFP56",speedGbps: 200, speed: "200G", reachMeters: 2000, reachLabel: "FR4", fiberType: "SMF", connector: "LC", wavelengths: "1271-1331nm" },
{ pid: "QSFP56-200G-LR4", formFactor: "QSFP56",speedGbps: 200, speed: "200G", reachMeters: 10000, reachLabel: "LR4", fiberType: "SMF", connector: "LC", wavelengths: "1295-1310nm" },
// ── 400G QSFP-DD ────────────────────────────────────────────────────────
{ pid: "QSFP-DD-400G-SR8", alias: "02313FHB", formFactor: "QSFP-DD",speedGbps: 400, speed: "400G", reachMeters: 100, reachLabel: "SR8", fiberType: "MMF", connector: "MPO", wavelengths: "850nm", standard: "400GBASE-SR8" },
{ pid: "QSFP-DD-400G-DR4", alias: "02313FHC", formFactor: "QSFP-DD",speedGbps: 400, speed: "400G", reachMeters: 500, reachLabel: "DR4", fiberType: "SMF", connector: "MPO", wavelengths: "1310nm", standard: "400GBASE-DR4" },
{ pid: "QSFP-DD-400G-FR4", formFactor: "QSFP-DD",speedGbps: 400, speed: "400G", reachMeters: 2000, reachLabel: "FR4", fiberType: "SMF", connector: "LC", wavelengths: "1271-1331nm", standard: "400GBASE-FR4" },
{ pid: "QSFP-DD-400G-LR4", formFactor: "QSFP-DD",speedGbps: 400, speed: "400G", reachMeters: 10000, reachLabel: "LR4", fiberType: "SMF", connector: "LC", wavelengths: "1295-1310nm", standard: "400GBASE-LR4" },
{ pid: "QSFP-DD-400G-ZR", formFactor: "QSFP-DD",speedGbps: 400, speed: "400G", reachMeters: 80000, reachLabel: "ZR", fiberType: "SMF", connector: "LC", wavelengths: "C-band", standard: "400ZR" },
// ── 800G OSFP ───────────────────────────────────────────────────────────
{ pid: "OSFP-800G-SR8", formFactor: "OSFP", speedGbps: 800, speed: "800G", reachMeters: 100, reachLabel: "SR8", fiberType: "MMF", connector: "MPO", wavelengths: "850nm", standard: "800GBASE-SR8" },
{ pid: "OSFP-800G-DR8", formFactor: "OSFP", speedGbps: 800, speed: "800G", reachMeters: 500, reachLabel: "DR8", fiberType: "SMF", connector: "MPO", wavelengths: "1310nm" },
{ pid: "OSFP-800G-FR8", formFactor: "OSFP", speedGbps: 800, speed: "800G", reachMeters: 2000, reachLabel: "FR8", fiberType: "SMF", connector: "LC", wavelengths: "1271-1331nm" },
// ── DAC ─────────────────────────────────────────────────────────────────
{ pid: "SFP+-10G-DAC-1M", formFactor: "SFP+", speedGbps: 10, speed: "10G", reachMeters: 1, reachLabel: "DAC-1M",fiberType:"DAC", connector: "SFP+" },
{ pid: "SFP+-10G-DAC-3M", formFactor: "SFP+", speedGbps: 10, speed: "10G", reachMeters: 3, reachLabel: "DAC-3M",fiberType:"DAC", connector: "SFP+" },
{ pid: "QSFP+-40G-DAC-1M", formFactor: "QSFP+", speedGbps: 40, speed: "40G", reachMeters: 1, reachLabel: "DAC-1M",fiberType:"DAC", connector: "QSFP+" },
{ pid: "QSFP+-40G-DAC-3M", formFactor: "QSFP+", speedGbps: 40, speed: "40G", reachMeters: 3, reachLabel: "DAC-3M",fiberType:"DAC", connector: "QSFP+" },
{ pid: "QSFP28-100G-DAC-1M", formFactor: "QSFP28",speedGbps: 100, speed: "100G", reachMeters: 1, reachLabel: "DAC-1M",fiberType:"DAC", connector: "QSFP28" },
{ pid: "QSFP28-100G-DAC-3M", formFactor: "QSFP28",speedGbps: 100, speed: "100G", reachMeters: 3, reachLabel: "DAC-3M",fiberType:"DAC", connector: "QSFP28" },
];
export async function scrapeHuaweiOem(): Promise<void> {
console.log("=== Huawei OEM Transceiver Seed ===\n");
const vendorId = await ensureVendor(
"Huawei",
"oem",
"https://enterprise.huawei.com",
undefined
);
let inserted = 0;
let updated = 0;
let errors = 0;
for (const p of HUAWEI_PIDS) {
const slug = `huawei-${p.pid.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`;
const notes = [p.notes, p.alias ? `BOM: ${p.alias}` : null].filter(Boolean).join(" | ") || null;
try {
const res = await pool.query(
`INSERT INTO transceivers
(slug, part_number, vendor_id, form_factor, speed, speed_gbps,
reach_meters, reach_label, fiber_type, connector, wavelengths,
dom_support, ieee_reference, market_status, category, notes)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,true,$12,'Mainstream','DataCenter',$13)
ON CONFLICT (slug) DO UPDATE SET
speed_gbps = EXCLUDED.speed_gbps,
reach_meters = CASE WHEN EXCLUDED.reach_meters > 0 THEN EXCLUDED.reach_meters ELSE transceivers.reach_meters END,
fiber_type = CASE WHEN EXCLUDED.fiber_type <> '' THEN EXCLUDED.fiber_type ELSE transceivers.fiber_type END,
wavelengths = COALESCE(EXCLUDED.wavelengths, transceivers.wavelengths),
updated_at = NOW()
RETURNING (xmax = 0) as was_inserted`,
[slug, p.pid, vendorId, p.formFactor, p.speed, p.speedGbps,
p.reachMeters, p.reachLabel, p.fiberType, p.connector,
p.wavelengths ?? null, p.standard ?? null, notes]
);
if (res.rows[0]?.was_inserted) inserted++; else updated++;
} catch (err) {
console.warn(` Skip ${p.pid}: ${(err as Error).message.slice(0, 80)}`);
errors++;
}
}
console.log(`\n=== Huawei OEM Seed Complete ===`);
console.log(` Inserted: ${inserted}`);
console.log(` Updated: ${updated}`);
console.log(` Errors: ${errors}`);
console.log(` Total PIDs: ${HUAWEI_PIDS.length}\n`);
}
if (require.main === module) {
scrapeHuaweiOem()
.then(() => pool.end())
.catch((err) => {
console.error("Fatal:", err);
pool.end();
process.exit(1);
});
}