• 【FreeSwitch开发实践】在nodejs中用ESL连接FreeSwitch


    系列文章目录

    【FreeSwitch开发实践】centos7下编译安装freeswitch及常见编译问题的解决
    【FreeSwitch开发实践】freeswitch配置wss
    【FreeSwitch开发实践】freeswitch配置wss证书问题 Encrypted Alert/Certification Unknown
    【FreeSwitch开发实践】ESL简介
    【FreeSwitch开发实践】ESL配置



    前言

    前文对ESL作了简介和配置的说明,本文将介绍在NodeJS中使用ESL,通过一些简单的例子,对如何在NodeJS使用ESL作了一个说明。
    在NodeJS中ESL的实现,是modesl模块,这个模块需要下载安装。


    一、modesl安装

    modesl是nodejs下ESL的实现模块,下载命令:

    npm install modesl
    
    • 1

    效果

    在这里插入图片描述

    二、nodejs中引用modesl

    const esl=require('F:/02_test/NodeJsDemo/ESL-test/node_modules/modesl');
    
    • 1

    代码解释:

    F:/02_test/NodeJsDemo/ESL-test/node_modules/modeslmodesl的安装目录, 作者安装到了项目的当前目录,读者实验的时候需要改成自己安装modesl的目录。


    三、modesl连接FreeSwitch

    const http=require('http');
    const server=http.createServer();
    server.on('request',function(request,response){
    	const url=request.url;	
    	if(url === '/'){
    		const esl=require('F:/02_test/NodeJsDemo/ESL-test/node_modules/modesl');
            console.log(esl);
    
    		const conn=new esl.Connection('152.136.12.38', 8021, 'ClueCon',function(){
    			conn.api('version',function(response){
    				console.log(response);
    			})
    		})
    		
    	}else if(url === '/index'){
    		response.end('/index');
    	}else{
    		response.end("

    404 Not Found

    "
    ); } }) server.listen(3001,function(){ console.info('server is running...'); })
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    代码解释:

    1 const conn=new esl.Connection('152.136.12.38', 8021, 'ClueCon' 是ESL连接,参数分别是FreeSwitch服务器的IP端口密码,具体配置见FreeSwitch的配置文件event_socket.conf.xml(可参考《【FreeSwitch开发实践】ESL配置》)。
    2 conn.api('version' 执行api version 命令, 此命令是FreeSwitch的versionapi, 用途是获取FreeSwitch的版本(在《【FreeSwitch开发实践】ESL简介》有介绍)。

    运行:

    执行ESL连接的方法是:
    打开浏览器,在地址栏输入: localhost:3001 , 回车

    输出:
    在这里插入图片描述
    目录结构:
    在这里插入图片描述

    四、ESL事件订阅

    ESL除了可以直接”执行"FreeSwitch的内部api或app,还可以通过事件订阅,获取几乎所有FreeSwitch的事件,两者结合,ESL可以达到像在FreeSwitch命令行上运行内部api或app几样的效果。
    下面通originate命令拨打软电话,订阅answer(接听)事件和hangup(挂断)事件,来演示ESL订阅事件流程。

    const http=require('http');
    const server=http.createServer();
    server.on('request',function(request,response){
    	const url=request.url;	
    	if(url === '/'){
    		const esl=require('F:/02_test/NodeJsDemo/ESL-test/node_modules/modesl');
            console.log(esl);
         
    		const conn=new esl.Connection('152.136.12.39', 8021, 'ClueCon',function(){
    			conn.api('version',function(response){
    				console.log(response);
    			})
    			
    			conn.bgapi('originate user/1000 &echo',function(response){
    				//console.log(response);
    			})
    			
                conn.subscribe([
                    'CHANNEL_ANSWER',
                    'CHANNEL_HANGUP_COMPLETE' 
                ], function(evt) {
                    //console.log(evt)    
                });
            
                conn.on('esl::event::CHANNEL_ANSWER::*', function(evt) {
                    console.log(evt);
                });
            
                conn.on('esl::event::CHANNEL_HANGUP_COMPLETE::*', function(evt) {
                    console.log(evt);
                });
    		})
    		
    	}else if(url === '/index'){
    		response.end('/index');
    	}else{
    		response.end("

    404 Not Found

    "
    ); } }) server.listen(3001,function(){ console.info('server is running...'); })
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    代码解释:

    1 conn.bgapiapi命令的异步版本, 都用于执行FreeSwitch的api或app
    2 originate user/1000 &echo 是给软电话用户1000通话, echo 是FreeSwitch自带的回音app,接通之后你和说什么,它就原样回过来
    3 conn.subscribe 事件订阅 是本节的重点, 参数是事件名称
    4 CHANNEL_ANSWER 用户接听电话事件
    5 CHANNEL_HANGUP_COMPLETE 挂断事件
    6 conn.on('esl::event::CHANNEL_ANSWER::*' 对事件CHANNEL_ANSWER监听
    7 conn.on('esl::event::CHANNEL_HANGUP_COMPLETE::*' 对事CHANNEL_HANGUP_COMPLETE监听

    输出结果:
    answer部分:

    {
      headers: [
        { name: 'Event-Name', value: 'CHANNEL_ANSWER' },
        {
          name: 'Core-UUID',
          value: 'e2232c8b-7e79-4404-8a91-54e0f94b96ca'
        },
        { name: 'FreeSWITCH-Hostname', value: 'VM-8-10-centos' },
        { name: 'FreeSWITCH-Switchname', value: 'VM-8-10-centos' },
        { name: 'FreeSWITCH-IPv4', value: '10.0.8.1' },
        { name: 'FreeSWITCH-IPv6', value: 'fe80::5054:ff:fe58:28ea' },
        { name: 'Event-Date-Local', value: '2022-07-10 17:07:27' },
        { name: 'Event-Date-GMT', value: 'Sun, 10 Jul 2022 09:07:27 GMT' },
        { name: 'Event-Date-Timestamp', value: '1657444047428307' },
        { name: 'Event-Calling-File', value: 'switch_channel.c' },
        {
          name: 'Event-Calling-Function',
          value: 'switch_channel_perform_mark_answered'
        },
        { name: 'Event-Calling-Line-Number', value: '3884' },
        { name: 'Event-Sequence', value: '343988' },
        { name: 'Channel-State', value: 'CS_CONSUME_MEDIA' },
        { name: 'Channel-Call-State', value: 'RINGING' },
        { name: 'Channel-State-Number', value: '7' },
        {
          name: 'Channel-Name',
          value: 'sofia/internal/1000@61.149.73.243:4446'
        },
        {
          name: 'Unique-ID',
          value: '91eafbfe-e998-4b30-bfaa-8e06c93915a3'
        },
        { name: 'Call-Direction', value: 'outbound' },
        { name: 'Presence-Call-Direction', value: 'outbound' },
        { name: 'Channel-HIT-Dialplan', value: 'false' },
        { name: 'Channel-Presence-ID', value: '1000@10.0.8.1' },
        {
          name: 'Channel-Call-UUID',
          value: '91eafbfe-e998-4b30-bfaa-8e06c93915a3'
        },
        { name: 'Answer-State', value: 'answered' },
        { name: 'Channel-Read-Codec-Name', value: 'PCMU' },
        { name: 'Channel-Read-Codec-Rate', value: '8000' },
        { name: 'Channel-Read-Codec-Bit-Rate', value: '64000' },
        { name: 'Channel-Write-Codec-Name', value: 'PCMU' },
        { name: 'Channel-Write-Codec-Rate', value: '8000' },
        { name: 'Channel-Write-Codec-Bit-Rate', value: '64000' },
        { name: 'Caller-Direction', value: 'outbound' },
        { name: 'Caller-Logical-Direction', value: 'outbound' },
        { name: 'Caller-Caller-ID-Number', value: '0000000000' },
        { name: 'Caller-Orig-Caller-ID-Number', value: '0000000000' },
        { name: 'Caller-Callee-ID-Name', value: 'Outbound Call' },
        { name: 'Caller-Callee-ID-Number', value: '1000' },
        { name: 'Caller-Network-Addr', value: '61.149.73.243' },
        { name: 'Caller-ANI', value: '0000000000' },
        { name: 'Caller-Destination-Number', value: '1000' },
        {
          name: 'Caller-Unique-ID',
          value: '91eafbfe-e998-4b30-bfaa-8e06c93915a3'
        },
        { name: 'Caller-Source', value: 'src/switch_ivr_originate.c' },
        { name: 'Caller-Context', value: 'default' },
        {
          name: 'Caller-Channel-Name',
          value: 'sofia/internal/1000@61.149.73.243:4446'
        },
        { name: 'Caller-Profile-Index', value: '1' },
        { name: 'Caller-Profile-Created-Time', value: '1657444039428319' },
        { name: 'Caller-Channel-Created-Time', value: '1657444039428319' },
        { name: 'Caller-Channel-Answered-Time', value: '1657444047428307' },
        { name: 'Caller-Channel-Progress-Time', value: '1657444039508312' },
        { name: 'Caller-Channel-Progress-Media-Time', value: '0' },
        { name: 'Caller-Channel-Hangup-Time', value: '0' },
        { name: 'Caller-Channel-Transfer-Time', value: '0' },
        { name: 'Caller-Channel-Resurrect-Time', value: '0' },
        { name: 'Caller-Channel-Bridged-Time', value: '0' },
        { name: 'Caller-Channel-Last-Hold', value: '0' },
        { name: 'Caller-Channel-Hold-Accum', value: '0' },
        { name: 'Caller-Screen-Bit', value: 'true' },
        { name: 'Caller-Privacy-Hide-Name', value: 'false' },
        { name: 'Caller-Privacy-Hide-Number', value: 'false' },
        { name: 'variable_direction', value: 'outbound' },
        { name: 'variable_is_outbound', value: 'true' },
        {
          name: 'variable_uuid',
          value: '91eafbfe-e998-4b30-bfaa-8e06c93915a3'
        },
        {
          name: 'variable_call_uuid',
          value: '91eafbfe-e998-4b30-bfaa-8e06c93915a3'
        },
        { name: 'variable_session_id', value: '8893' },
        { name: 'variable_sip_profile_name', value: 'internal' },
        { name: 'variable_text_media_flow', value: 'disabled' },
        {
          name: 'variable_channel_name',
          value: 'sofia/internal/1000@61.149.73.243:4446'
        },
        {
          name: 'variable_sip_destination_url',
          value: 'sip:1000@61.149.73.243:4446'
        },
        { name: 'variable_dialed_user', value: '1000' },
        { name: 'variable_dialed_domain', value: '10.0.8.1' },
        { name: 'variable_sip_invite_domain', value: '10.0.8.1' },
        { name: 'variable_presence_id', value: '1000@10.0.8.1' },
        { name: 'variable_originate_early_media', value: 'true' },
        { name: 'variable_audio_media_flow', value: 'sendrecv' },
        { name: 'variable_local_video_ip', value: '10.0.8.1' },
        { name: 'variable_local_video_port', value: '20014' },
        { name: 'variable_video_media_flow', value: 'sendrecv' },
        {
          name: 'variable_rtp_local_sdp_str',
          value: 'v=0\r\n' +
            'o=FreeSWITCH 1657424125 1657424126 IN IP4 10.0.8.1\r\n' +
            's=FreeSWITCH\r\n' +
            'c=IN IP4 10.0.8.1\r\n' +
            't=0 0\r\n' +
            'm=audio 19914 RTP/AVP 9 0 8 101\r\n' +
            'a=rtpmap:9 G722/8000\r\n' +
            'a=rtpmap:0 PCMU/8000\r\n' +
            'a=rtpmap:8 PCMA/8000\r\n' +
            'a=rtpmap:101 telephone-event/8000\r\n' +
            'a=fmtp:101 0-15\r\n' +
            'a=ptime:20\r\n' +
            'a=sendrecv\r\n' +
            'm=video 20014 RTP/AVP 102\r\n' +
            'b=AS:3072\r\n' +
            'a=rtpmap:102 VP8/90000\r\n' +
            'a=sendrecv\r\n' +
            'a=rtcp-fb:102 ccm fir\r\n' +
            'a=rtcp-fb:102 ccm tmmbr\r\n' +
            'a=rtcp-fb:102 nack\r\n' +
            'a=rtcp-fb:102 nack pli\r\n'
        },
        {
          name: 'variable_sip_outgoing_contact_uri',
          value: ''
        },
        { name: 'variable_sip_req_uri', value: '1000@61.149.73.243:4446' },
        { name: 'variable_sofia_profile_name', value: 'internal' },
        { name: 'variable_recovery_profile_name', value: 'internal' },
        {
          name: 'variable_sofia_profile_url',
          value: 'sip:mod_sofia@152.136.12.39:5060'
        },
        {
          name: 'variable_sip_local_network_addr',
          value: '152.136.12.39'
        },
        { name: 'variable_sip_reply_host', value: '61.149.73.243' },
        { name: 'variable_sip_reply_port', value: '4446' },
        { name: 'variable_sip_network_ip', value: '61.149.73.243' },
        { name: 'variable_sip_network_port', value: '4446' },
        { name: 'variable_sip_user_agent', value: 'YATE/4.2.0' },
        {
          name: 'variable_sip_allow',
          value: 'ACK, INVITE, BYE, CANCEL, OPTIONS, INFO'
        },
        {
          name: 'variable_sip_recover_contact',
          value: ''
        },
        {
          name: 'variable_sip_full_via',
          value: 'SIP/2.0/UDP 10.0.8.1;branch=z9hG4bKyK8tvgppgrgae;received=10.0.8.1;rport=5060'
        },
        {
          name: 'variable_sip_recover_via',
          value: 'SIP/2.0/UDP 10.0.8.1;branch=z9hG4bKyK8tvgppgrgae;received=10.0.8.1;rport=5060'
        },
        {
          name: 'variable_sip_full_from',
          value: ';tag=6eDFUy11rrNaB'
        },
        {
          name: 'variable_sip_full_to',
          value: ';tag=102329003'
        },
        { name: 'variable_sip_from_user', value: '0000000000' },
        { name: 'variable_sip_from_uri', value: '0000000000@10.0.8.1' },
        { name: 'variable_sip_from_host', value: '10.0.8.1' },
        { name: 'variable_sip_to_user', value: '1000' },
        { name: 'variable_sip_to_port', value: '4446' },
        { name: 'variable_sip_to_uri', value: '1000@61.149.73.243:4446' },
        ... 38 more items
      ],
      hPtr: null,
      type: 'CHANNEL_ANSWER',
      subclass: undefined,
      body: ''
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192

    *hangup部分:

    {
      headers: [
        { name: 'Event-Name', value: 'CHANNEL_HANGUP_COMPLETE' },
        {
          name: 'Core-UUID',
          value: 'e2232c8b-7e79-4404-8a91-54e0f94b96ca'
        },
        { name: 'FreeSWITCH-Hostname', value: 'VM-8-10-centos' },
        { name: 'FreeSWITCH-Switchname', value: 'VM-8-10-centos' },
        { name: 'FreeSWITCH-IPv4', value: '10.0.8.1' },
        { name: 'FreeSWITCH-IPv6', value: 'fe80::5054:ff:fe58:28ea' },
        { name: 'Event-Date-Local', value: '2022-07-10 17:09:22' },
        { name: 'Event-Date-GMT', value: 'Sun, 10 Jul 2022 09:09:22 GMT' },
        { name: 'Event-Date-Timestamp', value: '1657444162368312' },
        {
          name: 'Event-Calling-File',
          value: 'switch_core_state_machine.c'
        },
        {
          name: 'Event-Calling-Function',
          value: 'switch_core_session_reporting_state'
        },
        { name: 'Event-Calling-Line-Number', value: '943' },
        { name: 'Event-Sequence', value: '344222' },
        { name: 'Hangup-Cause', value: 'WRONG_CALL_STATE' },
        { name: 'Channel-State', value: 'CS_REPORTING' },
        { name: 'Channel-Call-State', value: 'HANGUP' },
        { name: 'Channel-State-Number', value: '11' },
        {
          name: 'Channel-Name',
          value: 'sofia/internal/7770015213612938@10.0.8.1'
        },
        {
          name: 'Unique-ID',
          value: '16adc43d-cd80-4dd2-aa6c-234256984688'
        },
        { name: 'Call-Direction', value: 'inbound' },
        { name: 'Presence-Call-Direction', value: 'inbound' },
        { name: 'Channel-HIT-Dialplan', value: 'true' },
        {
          name: 'Channel-Call-UUID',
          value: '16adc43d-cd80-4dd2-aa6c-234256984688'
        },
        { name: 'Answer-State', value: 'hangup' },
        { name: 'variable_direction', value: 'inbound' },
        {
          name: 'variable_uuid',
          value: '16adc43d-cd80-4dd2-aa6c-234256984688'
        },
        {
          name: 'variable_call_uuid',
          value: '16adc43d-cd80-4dd2-aa6c-234256984688'
        },
        { name: 'variable_session_id', value: '8895' },
        { name: 'variable_sip_from_user', value: '7770015213612938' },
        {
          name: 'variable_sip_from_uri',
          value: '7770015213612938@10.0.8.1'
        },
        { name: 'variable_sip_from_host', value: '10.0.8.1' },
        { name: 'variable_video_media_flow', value: 'disabled' },
        { name: 'variable_audio_media_flow', value: 'disabled' },
        { name: 'variable_text_media_flow', value: 'disabled' },
        {
          name: 'variable_channel_name',
          value: 'sofia/internal/7770015213612938@10.0.8.1'
        },
        {
          name: 'variable_sip_call_id',
          value: '2025548018-1584820887-1068544171'
        },
        {
          name: 'variable_ep_codec_string',
          value: 'CORE_PCM_MODULE.pcmu@8000h@20i@64000b,CORE_PCM_MODULE.PCMA@8000h@20i@64000b'
        },
        { name: 'variable_hangup_cause', value: 'WRONG_CALL_STATE' },
        { name: 'variable_hangup_cause_q850', value: '101' }
      ],
      hPtr: null,
      type: 'CHANNEL_HANGUP_COMPLETE',
      subclass: undefined,
      body: ''
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83


    总结

    好了, 以上就是今天的内容, 本文主要对nodejs中如何安装modesl、连接FreeSwitch、执行FreeSwitch的api或app、及事件订阅作了介绍。如果觉得不错,可以给博主点个关注,你们的支持,是我持续写作的动力。

  • 相关阅读:
    【DSPF8003x】 Enhanced Pulse Width Modulator (ePWM)
    基于springboot的在线电子商城系统设计与实现
    科学家首次为地球“全面体检”;国产光刻机或系误传;推特或将按月收费丨RTE开发者日报 Vol.52
    springboot防止表单重复提交
    React 使用合成事件(SyntheticEvent)
    数学建模之时间序列分析模型
    vue页面批量引入组件
    SpringBoot集成阿里云OSS存储服务(普通上传、服务端签名上传)
    倾斜摄影三维模型根节点合并技术方法探讨
    2023年软件测试常见面试题
  • 原文地址:https://blog.csdn.net/xxm524/article/details/125711038