From 83785f463fc3a2e36b662ea877317384741ea8b5 Mon Sep 17 00:00:00 2001 From: Nic D Date: Wed, 20 May 2026 10:31:55 -0400 Subject: [PATCH] feat(voip-binding)INITIAL COMMIT: create extension that fetches VLAN VOIP name for given device ID create provision script snippet to find device ID and re-bind VOIP VLANTermination name to X_TP property --- extensions/TPLink-ONU-VOIP-mapping.js | 60 +++++++++++++++++++++++ provisions/TPLink-ONU-VOIP-binding-fix.js | 26 ++++++++++ 2 files changed, 86 insertions(+) create mode 100644 extensions/TPLink-ONU-VOIP-mapping.js create mode 100644 provisions/TPLink-ONU-VOIP-binding-fix.js diff --git a/extensions/TPLink-ONU-VOIP-mapping.js b/extensions/TPLink-ONU-VOIP-mapping.js new file mode 100644 index 0000000..ee800ba --- /dev/null +++ b/extensions/TPLink-ONU-VOIP-mapping.js @@ -0,0 +1,60 @@ +const { create } = require("axios"); +const { writeFileSync } = require("fs"); + +const genieacsapi = create({ + baseURL: process.env.GENIEACS_API_URL || "http://10.5.2.111:7557/", +}); + +function queryByDeviceId(deviceId, projection = undefined) { + return new Promise((resolve, reject) => { + const params = new URLSearchParams(); + params.append("query", `{"_id": "${deviceId}"}`); + if (projection) { + params.append("projection", projection); + } + + genieacsapi + .get("/devices", { params }) + .then((response) => { + resolve(response.data); + }) + .catch((error) => { + reject(error); + }); + }); +} + +async function getVoipVlanTerminationName(args, callback) { + const deviceId = args[0]; + + if (!deviceId) return callback("Device ID is required"); + + // Result should be an array containing a single device that matches DeviceId + const queryResult = await queryByDeviceId(deviceId, "Device.Ethernet.VLANTermination"); + + if (!queryResult) return callback(`No device found for ${deviceId}`); + if (!Array.isArray(queryResult)) return callback(`Invalid response for ${deviceId}`); + if (queryResult.length === 0) return callback(`No VLAN termination data found for ${deviceId}`); + if (queryResult.length > 1) return callback(`Too many results matching ${deviceId}`); + + /** vlanTerminationData will contain a 2D array with all VLANTermination instances. + * Index 0 of each VLANTermination will be the instance number. + * Index 1 will be an object containing all of that VLANTermination's properties. + * The properties themselves are also objects with the following structure: + * "PropertyName": { + "_object": boolean + "_timestamp": timestamp string + "_type": XSD data type + "_value": any + "_writable": boolean + } + */ + const vlanTerminationData = queryResult[0]["Device"]["Ethernet"]["VLANTermination"]; + const VoipData = Object.entries(vlanTerminationData).find((data) => data[1].VLANID._value === 20); + + if (!VoipData) return callback(`No VOIP VLAN termination data found for ${deviceId}`); + + callback(null, VoipData[1].Name._value); +} + +exports.getVoipVlanTerminationName = getVoipVlanTerminationName; \ No newline at end of file diff --git a/provisions/TPLink-ONU-VOIP-binding-fix.js b/provisions/TPLink-ONU-VOIP-binding-fix.js new file mode 100644 index 0000000..91ed343 --- /dev/null +++ b/provisions/TPLink-ONU-VOIP-binding-fix.js @@ -0,0 +1,26 @@ +/** These steps will be performed during the standard inform process of XX230v ONUs: + * 1. Find the Name property of the VLANTermination that has VLANID set to '20' + * 2. Set Device.Services.VoiceService.1.X_TP_BoundIfName and/or + * Device.X_TP_Services.X_TP_VoiceService.1.BoundIfName value to the name found in step 1. + */ + +const now = Date.now(); +const daily = Date.now(86400000); +const username = declare("DeviceID.ID", { value: 1 }).value[0]; + +declare("Device.Ethernet.VLANTermination.*.VLANID", { value: daily }); +declare("Device.Ethernet.VLANTermination.*.Name", { value: daily }); + +const vlanName = ext("vlan-interface-mapping", "getVoipVlanTerminationName", username); + +// Reassign VOIP VLAN termination name to BoundIfName +declare( + `Device.Services.VoiceService.1.X_TP_BoundIfName`, + { value: now }, + { value: vlanName }, +); +declare( + `Device.X_TP_Services.X_TP_VoiceService.1.BoundIfName`, + { value: now }, + { value: vlanName }, +); \ No newline at end of file