import { randomBytes } from 'node:crypto' import { Cwmp_1_0, Download, FactoryReset, type FaultCodeType, FaultDetail, FaultStruct, Fault, GetParameterAttributes, GetParameterNames, GetParameterValues, InformResponse, ParameterValueList, Reboot, ScheduleInform, SetParameterAttributes, SetParameterAttributesList, SetParameterAttributesStruct, AccessList, SetParameterValues, TransferCompleteResponse, Upload, } from '../cwmp-1-0.js' import { CwmpID, NAMESPACES, SoapEnvelope, type SoapEnvelopeAttribute, SoapEnvelopeHeader, } from '../soap_envelope.js' import type { DownloadTaskPayload, UploadTaskPayload, SetParameterValuesTaskPayload, SetParameterAttributesTaskPayload, } from '../tr069_types.js' function generateCwmpID(): string { return randomBytes(4).toString('hex') } function makeEnvelope(cwmpId?: string): SoapEnvelope { const enve = new SoapEnvelope() enve.$ = NAMESPACES['1.0'] as SoapEnvelopeAttribute enve.Header = new SoapEnvelopeHeader() enve.Header.ID = new CwmpID({ $: { MustUnderstand: '1' }, _: cwmpId || generateCwmpID(), }) enve.Body = new Cwmp_1_0() return enve } export class CWMPMessageBuilder { static informResponse(cwmpId?: string): string { const enve = makeEnvelope(cwmpId) enve.Body.InformResponse = new InformResponse({ MaxEnvelopes: 1 }) return enve.getXml() } static getParameterNames( cwmpId: string | undefined, parameterPath: string, nextLevel: boolean = true ): string { const enve = makeEnvelope(cwmpId) enve.Body.GetParameterNames = new GetParameterNames({ ParameterPath: parameterPath, NextLevel: nextLevel, }) return enve.getXml() } static getParameterValues(cwmpId: string | undefined, parameterNames: string[]): string { const enve = makeEnvelope(cwmpId) enve.Body.GetParameterValues = new GetParameterValues({ ParameterNames: parameterNames }) return enve.getXml() } static setParameterValues( cwmpId: string | undefined, parameters: Array<{ name: string; value: string; type: string }> ): string { const pvStructs = parameters.map((p) => ({ Name: p.name, Value: { _: p.value, $: { Type: p.type } }, })) const pvList = new ParameterValueList({ $: { ArrayType: `cwmp:ParameterValueStruct[${pvStructs.length}]` }, ParameterValueStruct: pvStructs, }) const enve = makeEnvelope(cwmpId) enve.Body.SetParameterValues = new SetParameterValues({ ParameterValueList: pvList, ParameterKey: 'papaye-v2', }) return enve.getXml() } static setParameterValuesFromPayload( cwmpId: string | undefined, payload: SetParameterValuesTaskPayload ): string { const params = (payload.parameterValueList || []).map((p) => ({ name: p.Name, value: String(p.Value?._ ?? ''), type: p.Value?.$?.Type || 'xsd:string', })) return CWMPMessageBuilder.setParameterValues(cwmpId, params) } static download(cwmpId: string | undefined, params: DownloadTaskPayload): string { const enve = makeEnvelope(cwmpId) enve.Body.Download = new Download({ CommandKey: params.commandKey || '', FileType: params.fileType || '1 Firmware Upgrade Image', URL: params.url, Username: params.username || '', Password: params.password || '', FileSize: params.fileSize || 0, TargetFileName: params.targetFileName || '', DelaySeconds: params.delaySeconds || 0, SuccessURL: params.successUrl || '', FailureURL: params.failureUrl || '', }) return enve.getXml() } static upload(cwmpId: string | undefined, params: UploadTaskPayload): string { const enve = makeEnvelope(cwmpId) enve.Body.Upload = new Upload({ CommandKey: params.commandKey || '', FileType: params.fileType || '3 Vendor Configuration File', URL: params.url, Username: params.username || '', Password: params.password || '', DelaySeconds: params.delaySeconds || 0, }) return enve.getXml() } static reboot(cwmpId?: string, commandKey?: string): string { const enve = makeEnvelope(cwmpId) enve.Body.Reboot = new Reboot({ CommandKey: commandKey || '' }) return enve.getXml() } static factoryReset(cwmpId?: string): string { const enve = makeEnvelope(cwmpId) enve.Body.FactoryReset = new FactoryReset({}) return enve.getXml() } static scheduleInform( cwmpId: string | undefined, delaySeconds: number, commandKey?: string ): string { const enve = makeEnvelope(cwmpId) enve.Body.ScheduleInform = new ScheduleInform({ DelaySeconds: delaySeconds, CommandKey: commandKey || '', }) return enve.getXml() } static getParameterAttributes(cwmpId: string | undefined, parameterNames: string[]): string { const enve = makeEnvelope(cwmpId) enve.Body.GetParameterAttributes = new GetParameterAttributes({ ParameterNames: parameterNames, }) return enve.getXml() } static setParameterAttributes( cwmpId: string | undefined, attributes: SetParameterAttributesTaskPayload[] ): string { const structs = attributes.map( (a) => new SetParameterAttributesStruct({ Name: a.name, NotificationChange: a.notificationChange, Notification: a.notification, AccessListChange: a.accessListChange, AccessList: new AccessList({ string: a.accessList }), }) ) const list = new SetParameterAttributesList({ SetParameterAttributesStruct: structs }) const enve = makeEnvelope(cwmpId) enve.Body.SetParameterAttributes = new SetParameterAttributes({ ParameterList: list }) return enve.getXml() } static transferCompleteResponse(cwmpId?: string): string { const enve = makeEnvelope(cwmpId) enve.Body.TransferCompleteResponse = new TransferCompleteResponse({}) return enve.getXml() } static soapFault(faultCode: FaultCodeType, reason: string): string { const fault = new Fault() fault.Faultcode = 'Server' fault.Faultstring = reason fault.Detail = new FaultDetail({ Fault: new FaultStruct({ FaultCode: faultCode, FaultString: reason }), }) return fault.getXml() } static emptyResponse(): string { return '' } }