mediamtx/client/messages/message-types.js

207 lines
5.3 KiB
JavaScript

// Message Types for MQTT Communication
/**
* Signaling Message Types
*/
const SignalingType = {
REQUEST: 'request', // Initial request from client
OFFER: 'offer', // SDP Offer from camera/NVR
ANSWER: 'answer', // SDP Answer from client
DENY: 'deny', // Connection denied (max clients reached)
CCU: 'ccu', // Concurrent user count update
ICE_CANDIDATE: 'ice-candidate' // ICE candidate exchange
};
/**
* Data Channel Commands
*/
const DataChannelCommand = {
STREAM: 'Stream',
ONVIF_STATUS: 'OnvifStatus'
};
/**
* Result Codes
*/
const ResultCode = {
SUCCESS: 100,
FAIL: 103,
STREAM_SUCCESS: 0
};
/**
* Create Signaling Request Message
* @param {string} serial - Camera/NVR serial number
* @param {string} clientId - Unique client identifier
* @returns {object} - Signaling request message
*/
function createSignalingRequest(serial, clientId) {
return {
Method: 'ACT',
MessageType: 'Signaling',
Serial: serial,
Data: {
Type: SignalingType.REQUEST,
ClientId: clientId
},
Timestamp: Math.floor(Date.now() / 1000)
};
}
/**
* Create SDP Answer Message
* @param {string} serial - Camera/NVR serial number
* @param {string} clientId - Unique client identifier
* @param {string} sdp - SDP Answer string
* @returns {object} - SDP Answer message
*/
function createAnswerMessage(serial, clientId, sdp) {
return {
Method: 'ACT',
MessageType: 'Signaling',
Serial: serial,
Data: {
Type: SignalingType.ANSWER,
Sdp: sdp,
ClientId: clientId
},
Timestamp: Math.floor(Date.now() / 1000),
Result: {
Ret: ResultCode.SUCCESS,
Message: 'Success'
}
};
}
/**
* Create ICE Candidate Message
* @param {string} serial - Camera/NVR serial number
* @param {string} clientId - Unique client identifier
* @param {RTCIceCandidate} candidate - ICE candidate
* @returns {object} - ICE candidate message
*/
function createIceCandidateMessage(serial, clientId, candidate) {
return {
Method: 'ACT',
MessageType: 'Signaling',
Serial: serial,
Data: {
Type: SignalingType.ICE_CANDIDATE,
ClientId: clientId,
Candidate: {
candidate: candidate.candidate,
sdpMid: candidate.sdpMid,
sdpMLineIndex: candidate.sdpMLineIndex
}
},
Timestamp: Math.floor(Date.now() / 1000)
};
}
/**
* Create Credential Message
* @param {string} serial - Camera/NVR serial number
* @param {string} username - Camera username
* @param {string} password - Camera password
* @param {string} ip - Camera IP address (optional, will be discovered via ONVIF if not provided)
* @returns {object} - Credential message
*/
function createCredentialMessage(serial, username, password, ip = '') {
const data = {
Username: username,
Password: password
};
// Only include IP if provided
if (ip) {
data.IP = ip;
}
return {
Method: 'ACT',
MessageType: 'Credential',
Serial: serial,
Data: data,
Timestamp: Math.floor(Date.now() / 1000)
};
}
/**
* Create Stream Request for Data Channel
* @param {string} nvrSerial - NVR serial number
* @param {number} channelMask - 64-bit bitmask for channel enable (bit0=CH1...bit15=CH16)
* @param {number} resolutionMask - 64-bit bitmask for stream type (0=sub, 1=main)
* @returns {object} - Stream request message
*/
function createStreamRequest(nvrSerial, channelMask, resolutionMask) {
return {
Id: nvrSerial,
Command: DataChannelCommand.STREAM,
Type: 'Request',
Content: {
ChannelMask: channelMask,
ResolutionMask: resolutionMask
}
};
}
/**
* Create ONVIF Status Request for Data Channel
* @param {string} nvrSerial - NVR serial number
* @returns {object} - ONVIF status request message
*/
function createOnvifStatusRequest(nvrSerial) {
return {
Id: nvrSerial,
Command: DataChannelCommand.ONVIF_STATUS,
Type: 'Request',
Content: {}
};
}
/**
* Parse Signaling Response
* @param {object} message - Received message
* @returns {object} - Parsed response with type and data
*/
function parseSignalingResponse(message) {
const result = {
success: false,
type: null,
data: null,
error: null
};
try {
if (message.Result && message.Result.Ret !== ResultCode.SUCCESS) {
result.error = message.Result.Message || 'Unknown error';
return result;
}
if (message.Data) {
result.type = message.Data.Type;
result.data = message.Data;
result.success = true;
}
} catch (e) {
result.error = e.message;
}
return result;
}
// Export for module usage
if (typeof module !== 'undefined' && module.exports) {
module.exports = {
SignalingType,
DataChannelCommand,
ResultCode,
createSignalingRequest,
createAnswerMessage,
createIceCandidateMessage,
createCredentialMessage,
createStreamRequest,
createOnvifStatusRequest,
parseSignalingResponse
};
}