2019-09-18 08:11:16 +00:00
const utils = require ( './utils' ) ;
const Request = require ( 'request' ) ;
const async = require ( 'async' ) ;
const io = require ( 'socket.io-client' ) ;
const Mumble = require ( './mumble' ) ;
const currentPath = require ( 'path' ) . dirname ( require . main . filename ) ;
const fs = require ( 'fs' ) ;
const lame = require ( 'lame' ) ;
const Speaker = require ( 'speaker' ) ;
const Resampler = require ( 'libsamplerate.js' ) ;
const chunker = require ( 'stream-chunker' ) ;
const Transform = require ( 'stream' ) . Transform ;
const Throttle = require ( 'stream-throttle' ) . Throttle ;
const chalk = require ( 'chalk' ) ;
const OpusEncoder = require ( 'node-opus' ) . OpusEncoder ;
const log = require ( './utils' ) . log
class Asset {
2019-12-05 08:59:13 +00:00
constructor ( id , configs , token ) {
2019-09-18 08:11:16 +00:00
this . id = id ;
2019-12-05 08:59:13 +00:00
this . token = token ;
2019-09-18 08:11:16 +00:00
this . configs = configs
this . _processConfigs ( ) ;
this . pttEndSuccessfully = false ;
2019-09-25 11:02:03 +00:00
this . assetProps = { } ;
2020-08-14 12:01:39 +00:00
this . murmurPassword = '' ;
2021-09-18 07:14:54 +00:00
this . startTime = null ; // Will be set at the initialization of ptt(_start -> on_tt)
this . endTime = + new Date ( ) + ( this . configs . settings . testing _duration * 1000 )
2019-09-25 11:02:03 +00:00
utils . writeLog ( ` Creating asset ${ id } ` )
2019-09-18 08:11:16 +00:00
// Do async work: Init asset.
async . waterfall ( [
this . _getDataFromApi . bind ( this ) ,
this . _connectToHub . bind ( this ) ,
this . _connectToMurmur . bind ( this ) ,
this . _register . bind ( this ) ,
this . _moveToChannel . bind ( this ) ,
] ,
( err , result ) => {
2019-09-25 11:02:03 +00:00
utils . writeLog ( ` Asset ${ this . id } was successfully initialized ` )
2019-10-02 07:38:26 +00:00
2019-09-18 08:11:16 +00:00
if ( err ) {
2022-01-04 14:40:28 +00:00
console . log ( 'err' , err )
2019-10-09 08:26:26 +00:00
utils . writeLog ( ` Asset ${ this . id } was not successfully initialized ` , err ) ;
2019-09-18 08:11:16 +00:00
return ;
}
// Start simulating...
this . _start ( ) ;
} ) ;
}
_processConfigs ( ) {
let apiConfig = this . configs . api ;
this . apiEndpoint = apiConfig . use _secure ? 'https' : 'http' ;
this . apiEndpoint += '://' + apiConfig . host + ( apiConfig . port ? ( ':' + apiConfig . port ) : '' ) ;
}
_getDataFromApi ( callback ) {
2020-06-17 12:13:21 +00:00
utils . writeLog ( ` Get informations about asset ${ this . id } ` ) ;
2019-09-18 08:11:16 +00:00
Request . get (
this . apiEndpoint + '/asset/' + this . id ,
2019-12-05 08:59:13 +00:00
{
headers : {
Authorization : ` Bearer ${ this . token } `
}
} ,
2019-09-18 08:11:16 +00:00
( error , response , body ) => {
if ( ! error && ( response . statusCode === 200 || response . statusCode === 201 ) ) {
let bodyObj = JSON . parse ( body ) ;
// Here are the asset fields.
this . assetProps = bodyObj . data ;
2019-12-11 13:25:24 +00:00
// console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!', this.assetProps)
2020-08-14 12:01:39 +00:00
return this . _getMumblePassword ( callback ) ;
} else {
utils . writeLog ( ` ERROR getting informations about asset ${ this . id } ` , error ) ;
utils . writeErrorLog ( ` ERROR_API ` ) ;
return callback ( error ) ;
}
}
) ;
}
_getMumblePassword ( callback ) {
utils . writeLog ( ` Get Mumble password for asset ${ this . id } ` ) ;
Request . get (
this . apiEndpoint + '/asset/' + this . id + '/account' ,
{
headers : {
Authorization : ` Bearer ${ this . token } `
}
} ,
( error , response , body ) => {
if ( ! error && ( response . statusCode === 200 || response . statusCode === 201 ) ) {
let bodyObj = JSON . parse ( body ) ;
// Here are the asset fields.
this . murmurPassword = bodyObj . data . configuration . mumble _password ;
// console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!', this.assetProps)
2019-09-18 08:11:16 +00:00
return this . _getGroupsFromApi ( callback ) ;
} else {
2019-10-09 08:26:26 +00:00
utils . writeLog ( ` ERROR getting informations about asset ${ this . id } ` , error ) ;
utils . writeErrorLog ( ` ERROR_API ` ) ;
2019-09-18 08:11:16 +00:00
return callback ( error ) ;
}
}
) ;
}
_getGroupsFromApi ( callback ) {
Request . get (
this . apiEndpoint + '/asset/ ' + this . id + '/groups' ,
2019-12-05 08:59:13 +00:00
{
headers : {
Authorization : ` Bearer ${ this . token } `
}
} ,
2019-09-18 08:11:16 +00:00
( error , response , body ) => {
if ( ! error && ( response . statusCode === 200 || response . statusCode === 201 ) ) {
let bodyObj = JSON . parse ( body ) ;
this . groups = bodyObj . data ;
// Find what group this asset is monitoring.
this . groups . forEach ( ( g ) => {
if ( g . is _talk _group && g . monitoring . indexOf ( this . id ) != - 1 ) {
this . groupId = g . id ;
this . groupSipId = g . sip _id ;
this . groupName = g . name ;
}
} ) ;
if ( ! this . groupId ) {
return callback ( 'No talk group assigned to ' + this . id ) ;
}
2019-09-25 11:02:03 +00:00
utils . writeLog ( ` Informations about asset ${ this . id } received ` )
2019-09-18 08:11:16 +00:00
return callback ( ) ;
} else {
2019-10-09 08:26:26 +00:00
utils . writeLog ( ` Error getting informations about asset ${ this . id } ` , error ) ;
utils . writeErrorLog ( ` ERROR_API ` ) ;
2019-09-18 08:11:16 +00:00
return callback ( error ) ;
}
}
) ;
}
_connectToHub ( callback ) {
let hubAddress = this . configs . hub . address ;
let options = { rejectUnauthorized : false , secure : true } ;
let hub = io ( hubAddress , options ) ;
this . hub = hub ;
// Disconnect event
hub . on ( 'disconnect' , ( ) => {
2019-10-09 08:26:26 +00:00
utils . writeLog ( ` Asset ${ this . id } disconnected from HUB ` ) ;
2019-09-18 08:11:16 +00:00
} ) ;
2019-10-09 08:26:26 +00:00
hub . on ( 'connect_timeout' , ( ) => {
utils . writeLog ( ` Asset ${ this . id } connect_timeout from HUB ` ) ;
utils . writeErrorLog ( ` ERROR_HUB ` ) ;
} ) ;
hub . on ( 'connect_error' , ( ) => {
utils . writeLog ( ` Asset ${ this . id } connect_error from HUB ` ) ;
utils . writeErrorLog ( ` ERROR_HUB ` ) ;
} ) ;
2019-09-18 08:11:16 +00:00
hub . once ( 'connect' , ( ) => {
return callback ( ) ;
} ) ;
hub . on ( 'connect' , ( ) => {
2019-10-09 08:26:26 +00:00
utils . writeLog ( ` Asset ${ this . id } connected to HUB ` ) ;
2019-09-18 08:11:16 +00:00
this . _sendArs ( ) ;
} ) ;
hub . on ( 'ptt-press' , data => {
// this._log('ptt-press received');
} ) ;
hub . on ( 'ptt-release' , data => {
// this._log('ptt-release received');
} ) ;
hub . on ( 'reload' , data => {
// this._log('reload received');
} ) ;
}
_sendArs ( ) {
let hub = this . hub ;
if ( hub && hub . connected ) {
2019-09-25 11:02:03 +00:00
utils . writeLog ( ` Asset ${ this . id } sending ARS ` )
2019-09-18 08:11:16 +00:00
hub . emit ( 'ars' , JSON . stringify ( {
ars : true ,
userAgent : 'android' ,
asset _id : this . id ,
account _id : this . assetProps . account _id ,
asset _sip _id : this . assetProps . sip _id ,
fake : false
} ) ) ;
}
}
_connectToMurmur ( callback ) {
2020-08-14 12:01:39 +00:00
this . configs . murmurPassword = this . murmurPassword ;
2019-09-18 08:11:16 +00:00
this . mumble = new Mumble ( this . id , this . configs , ( err ) => {
if ( err ) {
2019-10-09 08:26:26 +00:00
utils . writeLog ( ` Asset ${ this . id } Murmur connection error ` , err ) ;
utils . writeErrorLog ( ` ERROR_MURMUR ` ) ;
2019-10-02 07:38:26 +00:00
return callback ( err ) ;
} else {
2020-06-17 12:13:21 +00:00
// return callback();
setTimeout ( ( ) => {
return callback ( ) ;
2021-09-18 07:14:54 +00:00
} , 400 ) ;
2019-10-02 07:38:26 +00:00
}
2019-09-18 08:11:16 +00:00
} ) ;
}
_register ( callback ) {
Request . post (
this . apiEndpoint + '/audio/register/' + this . id ,
2019-12-05 08:59:13 +00:00
{
headers : {
Authorization : ` Bearer ${ this . token } `
}
} ,
2019-09-18 08:11:16 +00:00
( error , response , body ) => {
if ( ! error && ( response . statusCode === 200 || response . statusCode === 201 ) ) {
2019-09-25 11:02:03 +00:00
utils . writeLog ( ` Asset ${ this . id } audio registered ` ) ;
2019-09-18 08:11:16 +00:00
return callback ( ) ;
} else {
2020-08-05 10:06:35 +00:00
console . log ( '_register--------------------' )
console . log ( 'error---' , error )
console . log ( 'response---' , response )
console . log ( 'body---' , body )
// utils.writeLog(`Asset ${this.id} audio registered error`, error);
// utils.writeErrorLog(`ERROR_API`);
// return callback(error);
2019-09-18 08:11:16 +00:00
}
}
) ;
}
_moveToChannel ( callback ) {
Request . post (
this . apiEndpoint + '/audio/enter-group/' + this . id + '/' + this . groupId ,
2019-12-05 08:59:13 +00:00
{
headers : {
Authorization : ` Bearer ${ this . token } `
}
} ,
2019-09-18 08:11:16 +00:00
( error , response , body ) => {
if ( ! error && ( response . statusCode === 200 || response . statusCode === 201 ) ) {
let hub = this . hub ;
if ( hub && hub . connected ) {
hub . emit ( 'group-monitoring' , JSON . stringify (
{
asset _id : this . id ,
asset _sip _id : this . assetProps . sip _id ,
asset _alias : this . assetProps . name ,
request _ptt _groups _status : false ,
group _sip _id : this . groupSipId ,
group _id : this . groupId ,
group _name : this . groupName ,
scan _group _ids : null
}
) ) ;
2019-09-25 11:02:03 +00:00
utils . writeLog ( ` Asset ${ this . id } mmonitoring group ${ this . groupId } ` )
2022-01-13 15:58:18 +00:00
if ( callback ) return callback ( ) ;
2019-09-18 08:11:16 +00:00
} else {
2022-01-13 15:58:18 +00:00
if ( callback ) return callback ( 'Cannot send group-monitoring: Hub not connected' ) ;
2019-09-18 08:11:16 +00:00
}
} else {
2020-08-05 10:06:35 +00:00
console . log ( '_moveToChannel--------------------' )
2020-08-05 09:44:07 +00:00
console . log ( 'error---' , error )
console . log ( 'response---' , response )
console . log ( 'body---' , body )
2020-08-05 10:06:35 +00:00
// utils.writeLog(`Asset ${this.id} audio enter group error`, error);
// utils.writeErrorLog(`ERROR_API`);
// return callback(error);
2019-09-18 08:11:16 +00:00
}
}
) ;
}
_start ( ) {
2021-09-18 07:14:54 +00:00
this . startTime = + new Date ( ) ;
if ( this . endTime > this . startTime ) {
if ( this . configs . settings . send _voice ) {
this . _makePtt ( ( ) => {
if ( this . pttEndSuccessfully ) {
this . _verifyRecorder ( ) ;
}
} ) ;
}
2019-09-25 11:02:03 +00:00
2021-09-18 07:14:54 +00:00
if ( this . configs . settings . send _gps ) {
this . _sendGPS ( ) ;
}
} else {
const assetIds = this . configs . assets . ids ;
if ( Math . max ( ... assetIds ) == this . id ) {
setTimeout ( ( ) => {
utils . writeLog ( 'STOP' )
. then ( ( ) => {
process . exit ( 0 ) ;
} ) ;
} , 10000 ) ;
}
2019-09-25 11:02:03 +00:00
}
2021-09-18 07:14:54 +00:00
2019-09-18 08:11:16 +00:00
}
_verifyRecorder ( callback ) {
console . log ( chalk . green ( ` Check to see if a record was created for the unit id: ${ this . id } | name: ${ this . assetProps . name } ` ) ) ;
2021-09-18 07:14:54 +00:00
let startDate = parseInt ( this . startTime ) - 3000 ;
2019-12-11 13:25:24 +00:00
let stopDate = parseInt ( + new Date ( ) + 30 * 1000 ) ;
2020-04-09 14:02:44 +00:00
setTimeout ( ( ) => { this . _getRecord ( startDate , stopDate , this . configs ) ; } , 3000 ) ;
2019-09-18 08:11:16 +00:00
}
2020-04-09 14:02:44 +00:00
_getRecord ( startDate , stopDate , configs ) {
2020-02-17 20:25:09 +00:00
console . log ( ` ${ this . apiEndpoint } /asset-history/ ${ this . id } /call-history/ ${ startDate } / ${ stopDate } /10 ` ) ;
// console.log(this.apiEndpoint + `/history-pagination/1/300/${this.id}/${startDate}/${stopDate}/0/0/0/1/null`)
2019-09-18 08:11:16 +00:00
Request . get (
2020-02-17 20:25:09 +00:00
` ${ this . apiEndpoint } /asset-history/ ${ this . id } /call-history/ ${ startDate } / ${ stopDate } /10 ` ,
// this.apiEndpoint + `/history-pagination/1/300/${this.id}/${startDate}/${stopDate}/0/0/0/1/null`,
2019-12-11 13:25:24 +00:00
{
headers : {
Authorization : ` Bearer ${ this . token } `
}
} ,
2019-09-18 08:11:16 +00:00
( error , response , body ) => {
2019-12-11 13:25:24 +00:00
if ( ! error && ( response . statusCode === 200 || response . statusCode === 201 ) ) {
2019-09-18 08:11:16 +00:00
let bodyObj = JSON . parse ( body ) ;
// console.log('bodyObj', bodyObj)
if ( bodyObj . data . length > 0 ) {
// Get the latest record
let latest = { id : 0 }
bodyObj . data . forEach ( e => {
if ( e . id > latest . id ) {
latest = e ;
}
} )
2020-02-17 20:25:09 +00:00
console . log ( chalk . green ( ` [RECORDER] Record found( ${ latest . id } ) for asset ${ this . id } ✓ ` ) ) ;
utils . writeLog ( ` [RECORDER] Record found( ${ latest . id } ) for asset ${ this . id } ` )
2019-09-18 08:11:16 +00:00
} else {
2019-09-25 11:02:03 +00:00
console . log ( chalk . yellow ( ` [RECORDER] for asset ${ this . id } not found ` ) ) ;
2019-09-18 08:11:16 +00:00
}
} else {
2019-12-11 13:25:24 +00:00
utils . writeLog ( ` Error getting record for asset ${ this . id } | ${ error } ` ) ;
2019-10-09 08:26:26 +00:00
utils . writeErrorLog ( ` ERROR_RECORDER ` ) ;
2019-09-25 11:02:03 +00:00
}
2020-06-17 12:13:21 +00:00
let assetIds = configs . assets . ids ;
2021-09-18 07:14:54 +00:00
this . _start ( ) ;
2019-09-25 11:02:03 +00:00
2019-09-18 08:11:16 +00:00
}
) ;
}
_makePtt ( callback ) {
2022-01-04 14:40:28 +00:00
// Sending group monitoring before we make PTT()
// Is used for the HUB load test(_moveToChannel is sent anyway after connecting to murmur-register)
2022-01-13 15:58:18 +00:00
if ( this . configs . settings . send _group _monitoring _before _each _call == 'true' ) {
2022-01-04 14:40:28 +00:00
this . _moveToChannel ( ) ;
}
2019-09-18 08:11:16 +00:00
// Check hub.
let hub = this . hub ;
if ( ! hub || ! hub . connected ) {
return callback ( ) ;
}
// Send ptt-press and wait for it to be accepted.
this . _sendPttPress ( ( isAccepted ) => {
if ( ! isAccepted ) {
return callback ( ) ;
}
2021-09-18 07:14:54 +00:00
// Select a random track from sounds.tracks
this . soundPath = ` ${ currentPath } /sounds/ ${ Math . floor ( Math . random ( ) * ( this . configs . sounds . tracks . length ) + 1 ) } .mp3 `
2019-09-18 08:11:16 +00:00
2021-09-18 07:14:54 +00:00
// Ptt accepted. We can send voice.
2019-09-18 08:11:16 +00:00
// Mp3 read stream.
var mp3 = fs . createReadStream ( this . soundPath ) ;
mp3 . on ( 'error' , ( e ) => {
2021-09-18 07:14:54 +00:00
utils . writeErrorLog ( ` Error _makePtt asset ${ this . id } ` , JSON . stringify ( e ) ) ;
2019-09-18 08:11:16 +00:00
} ) ;
2019-10-09 08:26:26 +00:00
2019-09-18 08:11:16 +00:00
mp3 . on ( 'data' , ( data ) => {
} ) ;
// Decoded mp3.
var lameDecoder = mp3
. pipe ( new lame . Decoder )
. on ( 'data' , ( data ) => {
} )
// On format we continue pipeing in. We need the mp3 format to know what to do next. Eg: To resample the mp3 we need to know the current sample rate.
. on ( 'format' , ( format ) => {
// Create resampler.
var resampler = new Resampler ( {
unsafe : false ,
type : Resampler . Type . ZERO _ORDER _HOLD ,
ratio : 48000 / format . sampleRate ,
channels : format . channels
} )
// Create mumble voice stream.
var voiceStream = this . mumble . client . createVoiceStream ( 0 , format . channels ) ;
// Send ptt-release on voice end.
voiceStream . on ( 'end' , ( ) => {
this . pttEndSuccessfully = true ;
setTimeout ( ( ) => {
this . _sendPttRelease ( ) ;
callback ( ) ;
} , 1500 ) ; // Hangtime
} ) ;
// @TODO: Ugly hack for the voice to work with mp3 (The fix is to remove float32ToInt16 conversion). It is the _transform function from OpusEncoderStream class (mumble-client-codecs-node project).
voiceStream . _readableState . pipes . _transform = function ( chunk , encoding , callback ) {
if ( ! this . _opus ) {
this . _opus = new OpusEncoder ( 48000 , chunk . numberOfChannels ) ;
}
callback ( null , {
target : chunk . target ,
codec : 'Opus' ,
frame : this . _opus . encode ( chunk . pcm ) ,
position : chunk . position
} ) ;
}
// This is used to slow down the mp3 transmision. Murmur will drop packages that are too early. This will make the mp3 transmision real time, just like it is a microphone stream.
var throtler = new Transform ( {
transform ( data , _ , callback ) {
setTimeout ( ( ) => {
callback ( null , data )
} , 16 / format . channels )
} ,
readableObjectMode : true
} ) ;
// Used for converting buffer to float32. Needed for Murmur.
const buffer2Float32Array = new Transform ( {
transform ( data , _ , callback ) {
callback ( null , new Float32Array ( data . buffer , data . byteOffset , data . byteLength / 4 ) )
} ,
readableObjectMode : true
} ) ;
// Pipe on.
lameDecoder
// Make 4096 chunks to be like the microphone stream.
2021-09-18 07:14:54 +00:00
// .pipe(chunker(4096, {flush: true, align: true}))
2019-09-18 08:11:16 +00:00
// Resample to 48000 hz.
. pipe ( resampler )
// Make 4 * 480 chunks for Murmur purposes.
. pipe ( chunker ( 4 * 480 , { flush : true , align : true } ) )
// Slow down the stream.
. pipe ( throtler )
// Convert to float 32.
. pipe ( buffer2Float32Array )
// Used for testing in nodejs speaker.
// .pipe(new Speaker)
// Mumble voice stream.
. pipe ( voiceStream ) ;
} ) ;
} )
}
2019-09-25 11:02:03 +00:00
_sendGPS ( callback ) {
let hub = this . hub ;
if ( hub && hub . connected ) {
2019-09-25 14:31:02 +00:00
let lat = this . configs . settings . gps _lat _start _point ;
let lng = this . configs . settings . gps _lng _start _point ;
2019-09-25 11:02:03 +00:00
2022-01-04 14:40:28 +00:00
setTimeout ( ( ) => {
2019-09-25 11:02:03 +00:00
var new _lat = this . _randomCoordinates ( lat ) ;
var new _lng = this . _randomCoordinates ( lng ) ;
hub . emit ( 'gps' , JSON . stringify (
{
unix _time : 1467126677000 ,
asset _id : this . assetProps . id ,
asset _sip _id : this . assetProps . sip _id ,
speed _kmh : 16 ,
lat : new _lat ,
lng : new _lng ,
accuracy : 20.3 ,
activity _type : "driving" ,
activity _confidence : 90
}
) ) ;
lat = new _lat ;
lng = new _lng ;
2022-03-16 08:25:35 +00:00
if ( ! this . configs . settings . send _voice ) {
this . _start ( ) ;
}
2019-09-25 11:02:03 +00:00
} , this . configs . settings . gps _report _interval ) ;
}
}
_randomCoordinates ( coordinate ) {
if ( Math . round ( Math . random ( ) ) === 0 ) {
return parseFloat ( parseFloat ( coordinate ) - parseFloat ( ( Math . random ( ) * ( 0.01 - 0.005 ) + 0.005 ) . toFixed ( 4 ) ) ) . toFixed ( 6 ) ;
} else {
return parseFloat ( parseFloat ( coordinate ) + parseFloat ( ( Math . random ( ) * ( 0.01 - 0.005 ) + 0.005 ) . toFixed ( 4 ) ) ) . toFixed ( 6 ) ;
}
}
2019-09-18 08:11:16 +00:00
_sendPttPress ( callback ) {
let hub = this . hub ;
if ( hub && hub . connected ) {
var pttAcceptHandler = ( data ) => {
data = JSON . parse ( data ) ;
if ( data . asset _id != this . id ) {
return ;
}
2019-09-25 11:02:03 +00:00
utils . writeLog ( ` Asset ${ this . id } sending PTT-PRESS to group ${ this . groupId } ` )
2019-09-18 08:11:16 +00:00
hub . removeListener ( 'ptt-deny' , pttDenyHandler ) ;
callback ( true ) ;
} ;
hub . once ( 'ptt-accept' , pttAcceptHandler ) ;
var pttDenyHandler = ( data ) => {
data = JSON . parse ( data ) ;
if ( data . asset _id != this . id ) {
return ;
}
2019-09-25 11:02:03 +00:00
utils . writeLog ( ` Asset ${ this . id } received PTT-DENY ` ) ;
2019-09-18 08:11:16 +00:00
hub . removeListener ( 'ptt-accept' , pttAcceptHandler ) ;
callback ( false ) ;
} ;
hub . once ( 'ptt-deny' , pttDenyHandler ) ;
hub . emit ( 'ptt-press' , JSON . stringify (
{
destination _group _id : this . groupId ,
destination _group _sip _id : this . groupSipId ,
destination _asset _id : 0 ,
destination _asset _sip _id : 0 ,
asset _id : this . id ,
asset _sip _id : this . assetProps . sip _id ,
asset _alias : this . assetProps . name ,
priority : this . assetProps . priority ,
portable _asset _id : 0 ,
portable _alias : null ,
}
) ) ;
}
}
_sendPttRelease ( ) {
let hub = this . hub ;
if ( hub && hub . connected ) {
2019-09-25 11:02:03 +00:00
utils . writeLog ( ` Asset ${ this . id } sending PTT-RELEASE to group ${ this . groupId } ` ) ;
2019-09-18 08:11:16 +00:00
hub . emit ( 'ptt-release' , JSON . stringify (
{
destination _group _id : this . groupId ,
destination _group _sip _id : this . groupSipId ,
destination _asset _id : 0 ,
destination _asset _sip _id : 0 ,
asset _id : this . id ,
asset _sip _id : this . assetProps . sip _id ,
asset _alias : this . assetProps . name ,
priority : this . assetProps . priority ,
portable _asset _id : 0 ,
portable _alias : null ,
}
) ) ;
}
}
}
module . exports = Asset ;