freeswitch 折腾了一个星期 lua 实现的 act 程序,抛砖引玉
---上次发帖说用 sip做一个呼叫系统,折腾得好痛苦,如果有意的坛友可以参考一下,节省点时间和表情。肯定可以运行。如果有其中的高手,请指教一下。代码比较精糙。。哈dbh=freeswitch.Dbh("odbc://fwsql");
laststat=""; --最后状态 1.hasline 2.notline 有否空内线 2.5 linenot有空线到最后被用3.linebusy4.lineready 有空线是否能接入
badinline="";
function waittoinc(tmpsession)
local waitTimes = 10;
while tmpsession:ready() == false and waitTimes > 0 do
waitTimes = waitTimes - 1;
end
return tmpsession:ready()
end
function playwavs(tmpsession,wavfiles)
tmpsession:sleep(50);
if tmpsession:ready() then
freeswitch.consoleLog("err", "\n starting play wav");
tmpsession:streamFile(wavfiles);
freeswitch.consoleLog("err", "\n play wav end");
end
end
function getoneinline(notline) --获得一条空闲内线在 inlineinfo 表内
local reinline="";
dbh:query("select top 1 inline from inlineinfo where busy=0 and inline<>'"..notline.."' order by asc,calltime asc"
,function(row) reinline=row.inlineend )
if reinline==nil or reinline=="" then
laststat="notline";
return "";
end
laststat="hasline";
badinline=reinline;
return reinline;
end
function zoneinline(notline,calldh,callid) --获内线后,设置为忙
local reinline;
local revv;
local ktnow=os.date("%Y-%m-%d %H:%M:%S", os.time());
reinline=getoneinline(notline);
if reinline==nil then
reinline="";
return reinline;
end
dbh:query("update inlineinfo set busy=1,outline='"..calldh.."',callid='"..callid.."',calltime='"..ktnow.."' where inline='"..reinline.."' and busy=0");
revv=dbh:affected_rows();
badinline=reinline;
if revv>0 then
return reinline;
else
laststat="linenot";
return "";
end
end
function callinline(notline,calldh,callid)
local reinline=zoneinline(notline,calldh,callid);
if reinline==nil or reinline=="" then
return "",nil;
end
badinline=reinline;
local tmpnum=reinline;
local tmpsession= freeswitch.Session("user/"..tmpnum);
if waittoinc(tmpsession) then
laststat="lineready";
return tmpnum,tmpsession;
else
dbh:query("update inlineinfo set busy=0,=(select isnull(count(*),0) from inlineinfo where busy=0)+1 where inline='"..reinline.."'")
laststat="linebusy";
return "",nil;
end
end
local session1 = session;
local cid=session1:getVariable("caller_id_number");
local dest_num=session1:getVariable("destination_number");
local kt=os.date("%Y-%m-%d %H:%M:%S", os.time());
local ktms=os.time();
dbh:query("insert into new通话(电话,kt,zt)values('"..cid.."','"..kt.."','"..dest_num.."')");
--playwavs(session1,"d:\\ffg\\wel.wav");
--如果座席所在的那条通道还没准备好,则进行等待
--session1:sleep(1800);
--if session1:ready() then
-- session1:answer();
-- end
local session2;
local inline;
local timess=0;
inline,session2=callinline("",dest_num,cid);--toonecall();
if inline=="" then
session1:sleep(50);
if (laststat=='linenot' or laststat=='linebusy') and badinline~='' and session1:ready() then
freeswitch.consoleLog("err", "\n channels2 is not ready, try next. laststat:"..laststat);
inline,session2=callinline(badinline,dest_num,cid);
end
end
if inline=="" then
session1:sleep(50);
if (laststat=='linenot' or laststat=='linebusy') and badinline~='' and session1:ready() then
freeswitch.consoleLog("err", "\n channels2 is not ready, try next. laststat:"..laststat);
inline,session2=callinline(badinline,dest_num,cid);
end
end
ifinline=="" then
-- 接通客户与座席
-- session2:setVariable("destination_number",cid);
freeswitch.consoleLog("err", "\n channels2 is not ready, please check it. laststat:"..laststat);
timess=-1;
playwavs(session1,"d:\\ffg\\busy.wav");
else
session1:sleep(50);
if session1:ready() then
freeswitch.bridge(session1, session2);
else
timess=-2;
end
end
local et=os.date("%Y-%m-%d %H:%M:%S", os.time())
local etms=os.time();
if timess==0 then
timess=etms-ktms;
end
dbh:query("update inlineinfo set busy=0,=(select isnull(count(*),0) from inlineinfo where busy=0)+1 where inline='"..inline.."'")
dbh:query("insert into 通话(电话,kt,zt,st)values('"..cid.."','"..kt.."','"..et.."',"..timess..")")
dbh:release()
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
最后说明,用的是 ms sql上面是代码,下面表结构
USE
GO
/****** Object:Table . Script Date: 07/25/2017 10:32:40 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE .(
IDENTITY(1,1) NOT NULL,
(40) NOT NULL,
(40) NULL,
(20) NULL,
NOT NULL,
NULL,
(40) NOT NULL,
CONSTRAINT PRIMARY KEY CLUSTERED
(
ASC
)WITH (PAD_INDEX= OFF, STATISTICS_NORECOMPUTE= OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS= ON, ALLOW_PAGE_LOCKS= ON) ON
) ON
GO
SET ANSI_PADDING OFF
GO
USE
GO
/****** Object:Table .[通话] Script Date: 07/25/2017 10:33:31 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE .[通话](
IDENTITY(1,1) NOT NULL,
[电话] (20) NULL,
(20) NULL,
(20) NULL,
NULL,
CONSTRAINT PRIMARY KEY CLUSTERED
(
ASC
)WITH (PAD_INDEX= OFF, STATISTICS_NORECOMPUTE= OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS= ON, ALLOW_PAGE_LOCKS= ON) ON
) ON
GO
SET ANSI_PADDING OFF
GO
USE
GO
/****** Object:Table . Script Date: 07/25/2017 10:33:23 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE .(
IDENTITY(1,1) NOT NULL,
[电话] (20) NULL,
(20) NULL,
(20) NULL,
CONSTRAINT PRIMARY KEY CLUSTERED
(
ASC
)WITH (PAD_INDEX= OFF, STATISTICS_NORECOMPUTE= OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS= ON, ALLOW_PAGE_LOCKS= ON) ON
) ON
GO
SET ANSI_PADDING OFF
GO
楼主,论坛有插入代码功能,建议以后发帖使用代码模式,阅读体验会好很多
static void do_xxx(void)
{
} Jmhh247 发表于 2017-7-25 11:30
楼主,论坛有插入代码功能,建议以后发帖使用代码模式,阅读体验会好很多
...
哈,是的是的,代码量不多将就一下 代码比较精糙。。 =精辟+粗糙?哈哈 sql语言,lua部分呢? Excellence 发表于 2017-7-26 16:08
sql语言,lua部分呢?
上面 lua 下面 sql 表结构 daiqx 发表于 2017-7-26 16:15
上面 lua 下面 sql 表结构
谢谢分享。。。。 我最近也在玩这个,从移动要了个IMS固话号码,现在gateway和inbound都配置通了,可以打进来了,就是outbound不知道怎么配置,总打不出去,楼主可吧指导一下么?中国的拨号规则怎么写?Outbound应该怎么配置? 拔号计划会设置么?会的话剩下的就是IMS的网关格式问题了。 snowy 发表于 2017-7-26 23:38
我最近也在玩这个,从移动要了个IMS固话号码,现在gateway和inbound都配置通了,可以打进来了,就是outboun ...
就是使用网关的呼出字串格式,这个对的话就写到拔号计划,不过这个比较简单,所以有可能在getway上,有可能不对。还有你留意一下控制台的输出,应该有提示
daiqx 发表于 2017-7-28 01:25
就是使用网关的呼出字串格式,这个对的话就写到拔号计划,不过这个比较简单,所以有可能在getway上,有可 ...
谢谢 楼主,后来通过抓包分析,问题确实出在网关设置上,Caller ID In From 要设置为false,否则呼出时会使用本地号码和域名invite,IMS是不接受这样的不合法请求。 snowy 发表于 2017-7-28 09:44
谢谢 楼主,后来通过抓包分析,问题确实出在网关设置上,Caller ID In From 要设置为false,否则呼出时会 ...
人生在于折腾,你可以将ims的网关\拔号计划发出来,有人也折腾这个时也可以参考一下。我比较喜欢使用脚本去代替拔号计划的逻辑。编程多于配置。 snowy 发表于 2017-7-28 09:44
谢谢 楼主,后来通过抓包分析,问题确实出在网关设置上,Caller ID In From 要设置为false,否则呼出时会 ...
另外经过一段时间的折腾,fs灵活地用必须用脚本。比如lua。然后用脚本或更熟练地配置文件还是不够的,因为它们都是阻塞执行的不能异步。比如上面的代码其实还有一点问题,比如要整一个欢迎语,一边发送回铃音边桥接就不行了。最后就要折腾esl了。 本帖最后由 snowy 于 2017-7-28 21:24 编辑
daiqx 发表于 2017-7-28 20:26
人生在于折腾,你可以将ims的网关\拔号计划发出来,有人也折腾这个时也可以参考一下。我比较喜欢使用脚本 ...
响应号召,对接移动IMS的主要参数,请根据所在地移动提供的信息修改。拨号计划等玩转了,弄个比较完善的发上来。
<include>
<gateway name="+86***********">
<!--/// account username *required* ///-->
<param name="username" value="+86***********"/>
<!--/// auth username *required* ///-->
<param name="auth-username" value="+86***********@ims.js.chinamobile.com"/>
<!--/// auth realm: *optional* same as gateway name, if blank ///-->
<param name="realm" value="ims.js.chinamobile.com"/>
<!--/// username to use in from: *optional* same asusername, if blank ///-->
<!--<param name="from-user" value="cluecon"/>-->
<!--/// domain to use in from: *optional* same asrealm, if blank ///-->
<!--<param name="from-domain" value="asterlink.com"/>-->
<!--/// account password *required* ///-->
<param name="password" value="**********"/>
<!--/// extension for inbound calls: *optional* same as username, if blank ///-->
<!--<param name="extension" value="cluecon"/>-->
<!--/// proxy host: *optional* same as realm, if blank ///-->
<!--<param name="proxy" value="asterlink.com"/>-->
<!--/// send register to this proxy: *optional* same as proxy, if blank ///-->
<param name="register-proxy" value="sbc.chinamobile.com"/>
<!--/// send outbound data to this proxy: *optional* same as proxy, if blank ///-->
<param name="outbound-proxy" value="sbc.chinamobile.com"/>
<!--/// expire in seconds: *optional* 3600, if blank ///-->
<param name="expire-seconds" value="1800"/>
<!--/// do not register ///-->
<param name="register" value="true"/>
<!-- which transport to use for register -->
<param name="register-transport" value="udp"/>
<!--How many seconds before a retry when a failure or timeout occurs -->
<param name="retry-seconds" value="30"/>
<!--Use the callerid of an inbound call in the from field on outbound calls via this gateway -->
<param name="caller-id-in-from" value="false"/>
<!--extra sip params to send in the contact-->
<!--<param name="contact-params" value="tport=tcp"/>-->
<!--send an options ping every x seconds, failure will unregister and/or mark it down-->
<param name="ping" value="25"/>
<!--</gateway>-->
<!--rfc5626 : Abilitazione rfc5626 ///-->
<!--<param name="rfc-5626" value="true"/>-->
<!--rfc5626 : extra sip params to send in the contact-->
<!--<param name="reg-id" value="1"/>-->
</include>
本帖最后由 snowy 于 2017-7-28 21:30 编辑
daiqx 发表于 2017-7-28 20:37
另外经过一段时间的折腾,fs灵活地用必须用脚本。比如lua。然后用脚本或更熟练地配置文件还是不够的,因 ...
后来我发现了FusionPBX(底层是FreeSwitch,安装这个最好有爱国路由器带着,不然非常慢),这个有比较友好的图形化界面(很好看),而且全部功能都是免费开放的,不像FreePBX很多要付费的组件。您可以试试。 snowy 发表于 2017-7-28 21:27
后来我发现了FusionPBX(底层是FreeSwitch,安装这个最好有爱国路由器带着,不然非常慢),这个有比较友 ...
谢谢分享,如果先知道fusionpbx的话,可能会减少很多时间,我先在ubunut安装fs,很多周折没有成功,就装win版的,安装非常容易,后来发现没有mod_lua模块,找编互联网也没有现成的,再下载源码,又发现只能vs2015才能编译,最后编译成功。linux版的有mod_luawin版的没有,真气死。现在由纯手工配置入门也好应该会扎实很多,哈哈 daiqx 发表于 2017-7-28 21:52
谢谢分享,如果先知道fusionpbx的话,可能会减少很多时间,我先在ubunut安装fs,很多周折没有成功,就装w ...
一般来说LINUX下的开源软件在WIN下编译比LINUX下麻烦多了。
FusionPBX的出局路由:
Tag Type Data Break Inline Group Order
condition destination_number ^(\+?\d{5,15})$ 0 5
长度在5位以上的,直接送到网关出局,4位以内保留给分机,软交换的好处是不像传统交换机那样要加拨数字。
^(\+?\d{5,15})$这个REGEX基本搞定了01088888888075588888888 +8688888888888 10000 10086之类的情况了,如果要拨110之类的,可以加拨区号来解决或者再加条3位数^(\d{3})$ 的优先路由。 封装后拔号规则简洁了,不过本来原装的配置也不复杂 snowy 发表于 2017-7-29 13:47
一般来说LINUX下的开源软件在WIN下编译比LINUX下麻烦多了。
FusionPBX的出局路由:
你好!现在你的freeswitch进展如何了?现在我已经确认用ESL也搞不定自定义 Ringback 的问题。就是别人打入电话时交换机给他播放的回铃音,做成彩铃一样可自定义的。你有搞定这个需求吗? 本帖最后由 snowy 于 2017-8-4 08:50 编辑
你好,基本可以用了,外线的彩铃应该是运营商那边开吧?自己能做的应该只有内线拨内线的彩铃音。我现在拨打出去有些对方手机或电话的彩铃可以听到,有些听不到,不知道为什么,不过这个关系不大。
我遇到一个问题是DID被叫转移到外线,转不出去,看日志是超时。
例如:1. 分机1000拨打10086(其它外线号码都可以),接通后按转移键,输入另一分机号1001,可以呼出转移成功。
2. 分机1000拨打10086(其它外线号码都可以),接通后按转移键,输入另一外线13888888,可以呼出转移成功。
3.分机1001呼叫分机1000,1000接通后按转移键,输入另一外线号1388888,可以呼入转移到外线成功。
4. 外线拨打1000分机的DID号码,1000接通后按转移键,输入另一外线号,转移失败(FreePBX是可以成功的)。
您可以帮忙测试一下第4项的情况么?谢谢!
snowy 发表于 2017-8-4 08:36
你好,基本可以用了,外线的彩铃应该是运营商那边开吧?自己能做的应该只有内线拨内线的彩铃音。我现在拨打 ...
这种情况我都会用脚本实现的,先拨出外线成功后和现在的会话桥接,应该很好实现。用xml配置的不擅长。 daiqx 发表于 2017-8-4 12:42
这种情况我都会用脚本实现的,先拨出外线成功后和现在的会话桥接,应该很好实现。用xml配置的不擅长。 ...
FusionPBX不支持IAX2,我下载一份源码编译试试。 snowy 发表于 2017-8-4 19:58
FusionPBX不支持IAX2,我下载一份源码编译试试。
如果fs可以支持,直接上配置文件就行,一定要Fusionpbx吗?有什么绝对的优势? 我用一个迂回的方法搞定播放自定义的早期媒体了。用execute_on_answer=lua 属性在桥接成功时调用 lua 发送一个自定义事件。 然后在主lua 接收到事件再playback 。 坑了两星期这个问题,因为资料太少纯靠google加折腾。在这过程中我更觉得如果不靠脚本或esl之类的调用,很难使用强大灵活的功能。走了很多弯路,lua->阻塞式,在桥接时居然不能播放语音,然后就想上python的esl , 可惜在win下 esl的库死活编译不过,直接上c#的 socket 控制,发现资料更少。又回到lua,将就使用。 lua虽然 顺序阻塞式执行不能使用状态机等不足。但使用简单,功能足够强。在fs下强烈推荐。 我现在也开始折腾编译FREESWITCH了,主要是想集成进IAX2协议,并且试试自己 写LUA。楼主用的什么版本的LINUX和FREESWITCH的哪个分支?我尝试了一下,遇到不少问题,我用的V1.8和CENTOS7,目前遇到一个怎么也解决不了的问题(不编译这个模块就可以成功了):
making all mod_opus
make: Entering directory `/root/freeswitch.git/src/mod/codecs/mod_opus'
Makefile:899: *** You must install libopus-dev to build mod_opus.Stop.
libopus-dev 这个组件,我用yum install 安装后还是提示这个错误,下载opus的代码编译安装后也还是提示,请问您遇到过没? snowy 发表于 2017-8-22 11:42
我现在也开始折腾编译FREESWITCH了,主要是想集成进IAX2协议,并且试试自己 写LUA。楼主用的什么版本的LINU ...
在实际应用需求的情况下,走的路线总是相似的。我用的是window版的1.68 ,只要是因为windows 版没有 mod_lua才去折腾源码编译。linux 下的安装我都没搞通呢,你这个出错,有可能libopus-dev版本不对,删除后找其它版本再试了。到最后不行换一个linux发行版。在linux的许多组件不同版本真的搞死人。 换成ubuntu一路坑,终于编译通过了,不过IAX2的支持还是不行,先玩玩LUA吧,您有没有相关脚本的集成入门指南? snowy 发表于 2017-8-23 18:54
换成ubuntu一路坑,终于编译通过了,不过IAX2的支持还是不行,先玩玩LUA吧,您有没有相关脚本的集成入门指 ...
我当时在linux 下安装 fs 搞得焦燥,然后用lua也搞得超焦燥,基本是上面代码的几个指令,语法百度一下即可。
一般类似这样
http://blog.csdn.net/u010317005/article/details/51889022
还有 https://www.baidu.com/s?ie=utf-8&f=3&rsv_bp=1&rsv_idx=2&tn=baiduhome_pg&wd=freeswitch%20lua&rsv_spt=1&oq=freeswitch%2520lua&rsv_pq=9b5b9ab700068560&rsv_t=892a1qlxe4r65zZjPCAOOriOfqlSZLzJeS0yts1KLzo68o1aV%2BYRAtlAgQsWca7G8U3U&rqlang=cn&rsv_enter=0&prefixsug=freeswitch%2520lua&rsp=0&rsv_sug=2
还有 google 下freeswitch lua
一边搜索一边踩坑,反正 lua 可以热更新不用 reloadxml ,不断尝试
楼主用的哪个sip协议栈? fengyunyu 发表于 2017-8-25 07:50
楼主用的哪个sip协议栈?
freeswitch 默认的
页:
[1]