- Add #domain, #protocol, #utils aliases to package.json imports map - Replace all relative imports (./, ../, ../..) in app/ and database/mongo_migrations/ with the corresponding #alias imports, eliminating relative path traversal across the codebase - Remove dead code: ConfigurationVersionModel.findByConfigurationIdentifier (unused, superseded by paginateVersions) and unused exception classes (NotFoundException, UnprocessableEntityException, DatabaseException) from app/exceptions/index.ts, keeping only BadRequestException - Fix pre-existing syntax error in configuration_version.ts (mismatched parenthesis) that broke tsc - Fix eqeqeq violation in configuration_service.ts and isNaN -> Number.isNaN in configuration_engine.ts / cwmp-1-0.ts / exchange_controller.ts - Fix no-shadow violation in cwmp-1-0.ts EventStruct constructor - Prettier formatting pass on touched files Validated: tsc --noEmit clean, eslint app/ clean, full test suite green.
516 lines
17 KiB
TypeScript
516 lines
17 KiB
TypeScript
// @ts-nocheck — fichier copié de cwmp-connector (papaye)
|
|
import { Cwmp_1_0, FaultStruct } from '#protocol/cwmp-1-0'
|
|
import {
|
|
Cwmp_1_1,
|
|
AutonomousTransferComplete as AutonomousTransferComplete_1_1,
|
|
} from '#protocol/cwmp-1-1'
|
|
|
|
/**
|
|
* CWMP Version 1.2 Protocol Classes
|
|
*
|
|
* Extends CWMP 1.1 with:
|
|
* - ScheduleDownload / ScheduleDownloadResponse
|
|
* - CancelTransfer / CancelTransferResponse
|
|
* - ChangeDUState / ChangeDUStateResponse
|
|
* - DUStateChangeComplete / DUStateChangeCompleteResponse
|
|
* - AutonomousDUStateChangeComplete / AutonomousDUStateChangeCompleteResponse
|
|
* - TimeWindow structures and Software Module Management structures
|
|
*/
|
|
export class Cwmp_1_2 extends Cwmp_1_1 {
|
|
public '@class' = '.Cwmp_1_2'
|
|
|
|
// New RPCs
|
|
public 'ScheduleDownload'?: ScheduleDownload
|
|
public 'ScheduleDownloadResponse'?: ScheduleDownloadResponse
|
|
public 'CancelTransfer'?: CancelTransfer
|
|
public 'CancelTransferResponse'?: CancelTransferResponse
|
|
public 'ChangeDUState'?: ChangeDUState
|
|
public 'ChangeDUStateResponse'?: ChangeDUStateResponse
|
|
public 'DUStateChangeComplete'?: DUStateChangeComplete
|
|
public 'DUStateChangeCompleteResponse'?: DUStateChangeCompleteResponse
|
|
public 'AutonomousDUStateChangeComplete'?: AutonomousDUStateChangeComplete
|
|
public 'AutonomousDUStateChangeCompleteResponse'?: AutonomousDUStateChangeCompleteResponse
|
|
|
|
// Override AutonomousTransferComplete to use TransferCompleteFaultStruct
|
|
public 'AutonomousTransferComplete'?: AutonomousTransferComplete
|
|
|
|
'constructor'(props: any = {}) {
|
|
super(props)
|
|
this.ScheduleDownload = props.ScheduleDownload
|
|
? new ScheduleDownload(props.ScheduleDownload)
|
|
: undefined
|
|
this.ScheduleDownloadResponse = props.ScheduleDownloadResponse
|
|
? new ScheduleDownloadResponse(props.ScheduleDownloadResponse)
|
|
: undefined
|
|
this.CancelTransfer = props.CancelTransfer
|
|
? new CancelTransfer(props.CancelTransfer)
|
|
: undefined
|
|
this.CancelTransferResponse = props.CancelTransferResponse
|
|
? new CancelTransferResponse(props.CancelTransferResponse)
|
|
: undefined
|
|
this.ChangeDUState = props.ChangeDUState ? new ChangeDUState(props.ChangeDUState) : undefined
|
|
this.ChangeDUStateResponse = props.ChangeDUStateResponse
|
|
? new ChangeDUStateResponse(props.ChangeDUStateResponse)
|
|
: undefined
|
|
this.DUStateChangeComplete = props.DUStateChangeComplete
|
|
? new DUStateChangeComplete(props.DUStateChangeComplete)
|
|
: undefined
|
|
this.DUStateChangeCompleteResponse = props.DUStateChangeCompleteResponse
|
|
? new DUStateChangeCompleteResponse(props.DUStateChangeCompleteResponse)
|
|
: undefined
|
|
this.AutonomousDUStateChangeComplete = props.AutonomousDUStateChangeComplete
|
|
? new AutonomousDUStateChangeComplete(props.AutonomousDUStateChangeComplete)
|
|
: undefined
|
|
this.AutonomousDUStateChangeCompleteResponse = props.AutonomousDUStateChangeCompleteResponse
|
|
? new AutonomousDUStateChangeCompleteResponse(props.AutonomousDUStateChangeCompleteResponse)
|
|
: undefined
|
|
|
|
// Override from 1.1 when provided
|
|
this.AutonomousTransferComplete = props.AutonomousTransferComplete
|
|
? new AutonomousTransferComplete(props.AutonomousTransferComplete)
|
|
: this.AutonomousTransferComplete
|
|
}
|
|
}
|
|
|
|
// New/extended Event Codes for 1.2
|
|
export enum EventCode_1_2 {
|
|
BOOTSTRAP = '0 BOOTSTRAP',
|
|
BOOT = '1 BOOT',
|
|
PERIODIC = '2 PERIODIC',
|
|
SCHEDULED = '3 SCHEDULED',
|
|
VALUE_CHANGE = '4 VALUE CHANGE',
|
|
KICKED = '5 KICKED',
|
|
CONNECTION_REQUEST = '6 CONNECTION REQUEST',
|
|
TRANSFER_COMPLETE = '7 TRANSFER COMPLETE',
|
|
DIAGNOSTICS_COMPLETE = '8 DIAGNOSTICS COMPLETE',
|
|
REQUEST_DOWNLOAD = '9 REQUEST DOWNLOAD',
|
|
AUTONOMOUS_TRANSFER_COMPLETE = '10 AUTONOMOUS TRANSFER COMPLETE',
|
|
DU_STATE_CHANGE_COMPLETE = '11 DU STATE CHANGE COMPLETE',
|
|
AUTONOMOUS_DU_STATE_CHANGE_COMPLETE = '12 AUTONOMOUS DU STATE CHANGE COMPLETE',
|
|
REBOOT = 'M Reboot',
|
|
SCHEDULE_INFORM = 'M ScheduleInform',
|
|
DOWNLOAD = 'M Download',
|
|
SCHEDULE_DOWNLOAD = 'M ScheduleDownload',
|
|
UPLOAD = 'M Upload',
|
|
CHANGE_DU_STATE = 'M ChangeDUState',
|
|
X_METHOD = 'M X_',
|
|
X_PATTERN = 'X [0-9A-F]{6} .*',
|
|
}
|
|
|
|
// Time window types used by ScheduleDownload
|
|
export class TimeWindowStruct {
|
|
public '@class' = '.TimeWindowStruct'
|
|
public 'WindowStart': number
|
|
public 'WindowEnd': number
|
|
public 'WindowMode': string
|
|
public 'UserMessage': string
|
|
public 'MaxRetries': number
|
|
|
|
'constructor'(props: any = {}) {
|
|
this.WindowStart = props.WindowStart ?? 0
|
|
this.WindowEnd = props.WindowEnd ?? 0
|
|
this.WindowMode = props.WindowMode ?? ''
|
|
this.UserMessage = props.UserMessage ?? ''
|
|
this.MaxRetries = props.MaxRetries ?? 0
|
|
}
|
|
}
|
|
|
|
export class TimeWindowList {
|
|
public '@class' = '.TimeWindowList'
|
|
public 'TimeWindowStruct': TimeWindowStruct[] = []
|
|
|
|
'constructor'(props: any = {}) {
|
|
this.TimeWindowStruct = (props.TimeWindowStruct || []).map(
|
|
(tw: any) => new TimeWindowStruct(tw)
|
|
)
|
|
}
|
|
}
|
|
|
|
// ScheduleDownload RPC
|
|
export class ScheduleDownload {
|
|
public '@class' = '.ScheduleDownload'
|
|
public 'CommandKey': string
|
|
public 'FileType': string
|
|
public 'URL': string
|
|
public 'Username'?: string
|
|
public 'Password'?: string
|
|
public 'FileSize'?: number
|
|
public 'TargetFileName'?: string
|
|
public 'TimeWindowList': TimeWindowList
|
|
|
|
'constructor'(props: any = {}) {
|
|
this.CommandKey = props.CommandKey || ''
|
|
this.FileType = props.FileType || ''
|
|
this.URL = props.URL || ''
|
|
this.Username = props.Username
|
|
this.Password = props.Password
|
|
this.FileSize = props.FileSize
|
|
this.TargetFileName = props.TargetFileName
|
|
this.TimeWindowList = new TimeWindowList(props.TimeWindowList || {})
|
|
}
|
|
|
|
'getXml'() {
|
|
const tw = this.TimeWindowList?.TimeWindowStruct || []
|
|
const twXml = tw
|
|
.map(
|
|
(w) => `
|
|
<TimeWindowStruct>
|
|
<WindowStart>${w.WindowStart}</WindowStart>
|
|
<WindowEnd>${w.WindowEnd}</WindowEnd>
|
|
<WindowMode>${w.WindowMode}</WindowMode>
|
|
<UserMessage>${w.UserMessage}</UserMessage>
|
|
<MaxRetries>${w.MaxRetries}</MaxRetries>
|
|
</TimeWindowStruct>`
|
|
)
|
|
.join('')
|
|
|
|
return `<cwmp:ScheduleDownload>
|
|
<CommandKey>${this.CommandKey}</CommandKey>
|
|
<FileType>${this.FileType}</FileType>
|
|
<URL>${this.URL}</URL>
|
|
<Username>${this.Username || ''}</Username>
|
|
<Password>${this.Password || ''}</Password>
|
|
<FileSize>${this.FileSize ?? 0}</FileSize>
|
|
<TargetFileName>${this.TargetFileName || ''}</TargetFileName>
|
|
<TimeWindowList soap-enc:arrayType="cwmp:TimeWindowStruct[${tw.length}]">
|
|
${twXml}
|
|
</TimeWindowList>
|
|
</cwmp:ScheduleDownload>`
|
|
}
|
|
}
|
|
|
|
export class ScheduleDownloadResponse {
|
|
public '@class' = '.ScheduleDownloadResponse'
|
|
'constructor'(props: any = {}) {}
|
|
|
|
'getXml'() {
|
|
return `<cwmp:ScheduleDownloadResponse/>`
|
|
}
|
|
}
|
|
|
|
// CancelTransfer RPC
|
|
export class CancelTransfer {
|
|
public '@class' = '.CancelTransfer'
|
|
public 'CommandKey': string
|
|
'constructor'(props: any = {}) {
|
|
this.CommandKey = props.CommandKey || ''
|
|
}
|
|
|
|
'getXml'() {
|
|
return `<cwmp:CancelTransfer>
|
|
<CommandKey>${this.CommandKey}</CommandKey>
|
|
</cwmp:CancelTransfer>`
|
|
}
|
|
}
|
|
|
|
export class CancelTransferResponse {
|
|
public '@class' = '.CancelTransferResponse'
|
|
'constructor'(props: any = {}) {}
|
|
|
|
'getXml'() {
|
|
return `<cwmp:CancelTransferResponse/>`
|
|
}
|
|
}
|
|
|
|
// Software Module Management types
|
|
export type DeploymentUnitState = 'Installed' | 'Uninstalled' | 'Failed'
|
|
|
|
export class OperationStruct {
|
|
// abstract base
|
|
public '@class' = '.OperationStruct'
|
|
}
|
|
|
|
export class InstallOpStruct extends OperationStruct {
|
|
public '@class' = '.InstallOpStruct'
|
|
public 'URL': string
|
|
public 'UUID'?: string
|
|
public 'Username'?: string
|
|
public 'Password'?: string
|
|
public 'ExecutionEnvRef'?: string
|
|
|
|
'constructor'(props: any = {}) {
|
|
super()
|
|
this.URL = props.URL || ''
|
|
this.UUID = props.UUID
|
|
this.Username = props.Username
|
|
this.Password = props.Password
|
|
this.ExecutionEnvRef = props.ExecutionEnvRef
|
|
}
|
|
}
|
|
|
|
export class UpdateOpStruct extends OperationStruct {
|
|
public '@class' = '.UpdateOpStruct'
|
|
public 'UUID'?: string
|
|
public 'Version'?: string
|
|
public 'URL'?: string
|
|
public 'Username'?: string
|
|
public 'Password'?: string
|
|
|
|
'constructor'(props: any = {}) {
|
|
super()
|
|
this.UUID = props.UUID
|
|
this.Version = props.Version
|
|
this.URL = props.URL
|
|
this.Username = props.Username
|
|
this.Password = props.Password
|
|
}
|
|
}
|
|
|
|
export class UninstallOpStruct extends OperationStruct {
|
|
public '@class' = '.UninstallOpStruct'
|
|
public 'UUID': string
|
|
public 'Version'?: string
|
|
public 'ExecutionEnvRef'?: string
|
|
|
|
'constructor'(props: any = {}) {
|
|
super()
|
|
this.UUID = props.UUID || ''
|
|
this.Version = props.Version
|
|
this.ExecutionEnvRef = props.ExecutionEnvRef
|
|
}
|
|
}
|
|
|
|
export class DeploymentUnitFaultStruct {
|
|
public '@class' = '.DeploymentUnitFaultStruct'
|
|
public 'FaultCode': number
|
|
public 'FaultString'?: string
|
|
|
|
'constructor'(props: any = {}) {
|
|
this.FaultCode = props.FaultCode ?? 0
|
|
this.FaultString = props.FaultString
|
|
}
|
|
}
|
|
|
|
export class OpResultStruct {
|
|
public '@class' = '.OpResultStruct'
|
|
public 'UUID': string
|
|
public 'DeploymentUnitRef': string
|
|
public 'Version': string
|
|
public 'CurrentState': DeploymentUnitState
|
|
public 'Resolved': boolean
|
|
public 'ExecutionUnitRefList': string
|
|
public 'StartTime': Date
|
|
public 'CompleteTime': Date
|
|
public 'Fault': DeploymentUnitFaultStruct
|
|
|
|
'constructor'(props: any = {}) {
|
|
this.UUID = props.UUID || ''
|
|
this.DeploymentUnitRef = props.DeploymentUnitRef || ''
|
|
this.Version = props.Version || ''
|
|
this.CurrentState = props.CurrentState || 'Installed'
|
|
this.Resolved = !!props.Resolved
|
|
this.ExecutionUnitRefList = props.ExecutionUnitRefList || ''
|
|
this.StartTime = props.StartTime ? new Date(props.StartTime) : new Date()
|
|
this.CompleteTime = props.CompleteTime ? new Date(props.CompleteTime) : new Date()
|
|
this.Fault = new DeploymentUnitFaultStruct(props.Fault || {})
|
|
}
|
|
}
|
|
|
|
export class AutonOpResultStruct extends OpResultStruct {
|
|
public '@class' = '.AutonOpResultStruct'
|
|
public 'OperationPerformed': string
|
|
|
|
'constructor'(props: any = {}) {
|
|
super(props)
|
|
this.OperationPerformed = props.OperationPerformed || ''
|
|
}
|
|
}
|
|
|
|
// ChangeDUState RPC
|
|
export class ChangeDUState {
|
|
public '@class' = '.ChangeDUState'
|
|
public 'Operations': OperationStruct[] = []
|
|
public 'CommandKey'?: string
|
|
|
|
'constructor'(props: any = {}) {
|
|
this.Operations = (props.Operations || []).map((op: any) => {
|
|
const type = op?.['@class'] || op?.type
|
|
if (type === 'InstallOpStruct' || op?.URL) return new InstallOpStruct(op)
|
|
if (type === 'UpdateOpStruct' || op?.Version || (op?.UUID && !op?.ExecutionEnvRef))
|
|
return new UpdateOpStruct(op)
|
|
if (
|
|
type === 'UninstallOpStruct' ||
|
|
op?.ExecutionEnvRef ||
|
|
(op?.UUID && !op?.URL && !op?.Version)
|
|
)
|
|
return new UninstallOpStruct(op)
|
|
return new OperationStruct()
|
|
})
|
|
this.CommandKey = props.CommandKey
|
|
}
|
|
|
|
'getXml'() {
|
|
const opsXml = this.Operations.map((op) => {
|
|
if (op instanceof InstallOpStruct) {
|
|
return `<Operations xsi:type="cwmp:InstallOpStruct">
|
|
<URL>${op.URL}</URL>
|
|
${op.UUID ? `<UUID>${op.UUID}</UUID>` : ''}
|
|
${op.Username ? `<Username>${op.Username}</Username>` : ''}
|
|
${op.Password ? `<Password>${op.Password}</Password>` : ''}
|
|
${op.ExecutionEnvRef ? `<ExecutionEnvRef>${op.ExecutionEnvRef}</ExecutionEnvRef>` : ''}
|
|
</Operations>`
|
|
}
|
|
if (op instanceof UpdateOpStruct) {
|
|
return `<Operations xsi:type="cwmp:UpdateOpStruct">
|
|
${op.UUID ? `<UUID>${op.UUID}</UUID>` : ''}
|
|
${op.Version ? `<Version>${op.Version}</Version>` : ''}
|
|
${op.URL ? `<URL>${op.URL}</URL>` : ''}
|
|
${op.Username ? `<Username>${op.Username}</Username>` : ''}
|
|
${op.Password ? `<Password>${op.Password}</Password>` : ''}
|
|
</Operations>`
|
|
}
|
|
if (op instanceof UninstallOpStruct) {
|
|
return `<Operations xsi:type="cwmp:UninstallOpStruct">
|
|
<UUID>${op.UUID}</UUID>
|
|
${op.Version ? `<Version>${op.Version}</Version>` : ''}
|
|
${op.ExecutionEnvRef ? `<ExecutionEnvRef>${op.ExecutionEnvRef}</ExecutionEnvRef>` : ''}
|
|
</Operations>`
|
|
}
|
|
return ''
|
|
}).join('')
|
|
|
|
return `<cwmp:ChangeDUState>
|
|
${opsXml}
|
|
${this.CommandKey ? `<CommandKey>${this.CommandKey}</CommandKey>` : ''}
|
|
</cwmp:ChangeDUState>`
|
|
}
|
|
}
|
|
|
|
export class ChangeDUStateResponse {
|
|
public '@class' = '.ChangeDUStateResponse'
|
|
'constructor'(props: any = {}) {}
|
|
|
|
'getXml'() {
|
|
return `<cwmp:ChangeDUStateResponse/>`
|
|
}
|
|
}
|
|
|
|
// DUStateChangeComplete RPCs
|
|
export class DUStateChangeComplete {
|
|
public '@class' = '.DUStateChangeComplete'
|
|
public 'Results': OpResultStruct[]
|
|
public 'CommandKey'?: string
|
|
|
|
'constructor'(props: any = {}) {
|
|
this.Results = (props.Results || []).map((r: any) => new OpResultStruct(r))
|
|
this.CommandKey = props.CommandKey
|
|
}
|
|
|
|
'getXml'() {
|
|
const resultsXml = this.Results.map(
|
|
(r) => `
|
|
<Results>
|
|
<UUID>${r.UUID}</UUID>
|
|
<DeploymentUnitRef>${r.DeploymentUnitRef}</DeploymentUnitRef>
|
|
<Version>${r.Version}</Version>
|
|
<CurrentState>${r.CurrentState}</CurrentState>
|
|
<Resolved>${r.Resolved ? 1 : 0}</Resolved>
|
|
<ExecutionUnitRefList>${r.ExecutionUnitRefList}</ExecutionUnitRefList>
|
|
<StartTime>${r.StartTime.toISOString()}</StartTime>
|
|
<CompleteTime>${r.CompleteTime.toISOString()}</CompleteTime>
|
|
<Fault>
|
|
<FaultCode>${r.Fault.FaultCode}</FaultCode>
|
|
${r.Fault.FaultString ? `<FaultString>${r.Fault.FaultString}</FaultString>` : ''}
|
|
</Fault>
|
|
</Results>`
|
|
).join('')
|
|
|
|
return `<cwmp:DUStateChangeComplete>
|
|
${resultsXml}
|
|
${this.CommandKey ? `<CommandKey>${this.CommandKey}</CommandKey>` : ''}
|
|
</cwmp:DUStateChangeComplete>`
|
|
}
|
|
}
|
|
|
|
export class DUStateChangeCompleteResponse {
|
|
public '@class' = '.DUStateChangeCompleteResponse'
|
|
'constructor'(props: any = {}) {}
|
|
|
|
'getXml'() {
|
|
return `<cwmp:DUStateChangeCompleteResponse/>`
|
|
}
|
|
}
|
|
|
|
export class AutonomousDUStateChangeComplete {
|
|
public '@class' = '.AutonomousDUStateChangeComplete'
|
|
public 'Results': AutonOpResultStruct[]
|
|
|
|
'constructor'(props: any = {}) {
|
|
this.Results = (props.Results || []).map((r: any) => new AutonOpResultStruct(r))
|
|
}
|
|
|
|
'getXml'() {
|
|
const resultsXml = this.Results.map(
|
|
(r) => `
|
|
<Results>
|
|
<UUID>${r.UUID}</UUID>
|
|
<DeploymentUnitRef>${r.DeploymentUnitRef}</DeploymentUnitRef>
|
|
<Version>${r.Version}</Version>
|
|
<CurrentState>${r.CurrentState}</CurrentState>
|
|
<Resolved>${r.Resolved ? 1 : 0}</Resolved>
|
|
<ExecutionUnitRefList>${r.ExecutionUnitRefList}</ExecutionUnitRefList>
|
|
<StartTime>${r.StartTime.toISOString()}</StartTime>
|
|
<CompleteTime>${r.CompleteTime.toISOString()}</CompleteTime>
|
|
<Fault>
|
|
<FaultCode>${r.Fault.FaultCode}</FaultCode>
|
|
${r.Fault.FaultString ? `<FaultString>${r.Fault.FaultString}</FaultString>` : ''}
|
|
</Fault>
|
|
<OperationPerformed>${r.OperationPerformed}</OperationPerformed>
|
|
</Results>`
|
|
).join('')
|
|
|
|
return `<cwmp:AutonomousDUStateChangeComplete>
|
|
${resultsXml}
|
|
</cwmp:AutonomousDUStateChangeComplete>`
|
|
}
|
|
}
|
|
|
|
export class AutonomousDUStateChangeCompleteResponse {
|
|
public '@class' = '.AutonomousDUStateChangeCompleteResponse'
|
|
'constructor'(props: any = {}) {}
|
|
|
|
'getXml'() {
|
|
return `<cwmp:AutonomousDUStateChangeCompleteResponse/>`
|
|
}
|
|
}
|
|
|
|
// TransferComplete-specific fault struct for 1.2
|
|
export class TransferCompleteFaultStruct {
|
|
public '@class' = '.TransferCompleteFaultStruct'
|
|
public 'FaultCode': number
|
|
public 'FaultString': string
|
|
|
|
'constructor'(props: any = {}) {
|
|
this.FaultCode = props.FaultCode ?? 0
|
|
this.FaultString = props.FaultString || ''
|
|
}
|
|
}
|
|
|
|
// Override of 1.1 AutonomousTransferComplete to use TransferCompleteFaultStruct
|
|
export class AutonomousTransferComplete extends AutonomousTransferComplete_1_1 {
|
|
public '@class' = '.AutonomousTransferComplete'
|
|
public 'FaultStruct': TransferCompleteFaultStruct
|
|
|
|
'constructor'(props: any = {}) {
|
|
super(props)
|
|
this.FaultStruct = new TransferCompleteFaultStruct(props.FaultStruct || {})
|
|
}
|
|
|
|
'getXml'() {
|
|
return `<cwmp:AutonomousTransferComplete>
|
|
<AnnounceURL>${this.AnnounceURL}</AnnounceURL>
|
|
<TransferURL>${this.TransferURL}</TransferURL>
|
|
<IsDownload>${this.IsDownload ? 1 : 0}</IsDownload>
|
|
<FileType>${this.FileType}</FileType>
|
|
<FileSize>${this.FileSize}</FileSize>
|
|
<TargetFileName>${this.TargetFileName}</TargetFileName>
|
|
<FaultStruct>
|
|
<FaultCode>${this.FaultStruct.FaultCode}</FaultCode>
|
|
<FaultString>${this.FaultStruct.FaultString}</FaultString>
|
|
</FaultStruct>
|
|
<StartTime>${this.StartTime.toISOString()}</StartTime>
|
|
<CompleteTime>${this.CompleteTime.toISOString()}</CompleteTime>
|
|
</cwmp:AutonomousTransferComplete>`
|
|
}
|
|
}
|