shiyuan_jssip
v1.2.0
Published
jssip wrapper, use for emicnet callcenter
Downloads
10
Readme
对 jssip 的包 装
易米电话工具条基于 jssip,通过 WebRTC 网关对接易米 sip 服务器。工具条主要封装了对易米 sip 服务器的消息处理,让用户通过浏览器直接使用易米 sip 服务器提供的服务。 推荐使用 Chrome 68+浏览器;IE 浏览器不支持 WebRTC,所以工具条不能在 IE 中使用。
如何安装使用
我们当前代码不能在 node 环境下执行: localstorage
& fetch
都是浏览器方法,因此我们没有在 package.json设置 main 字段而是设置 browser 字段。因为没有设置 main, 所以引用时候不能直接写 require...
使用时在 html 页面中通过 CDN 引用打包后的代码,比起通过 npm i
安装更方便。如果用 npm 安装,引用时候需要写 node_modules
路径, <script src='.\node_modules\...'
不然浏览器无法处理。
注:根据这个SO 讨论 我们在 package.json 用 "//"添加几个要点,但重要的东西还是都这里详述。
如何打包
我们提供两种打包方式 webpack
和 gulp(4.0)
方式,webpack 通过 npm script 执行;
webpack 打包命令npm run bundle
; gulp 打包直接在命令行执行 gulp bundle
webpack 打包需要对 css 准备处理,见下面描述。
使用 webpack 打包的一个好处是方便断点调试,gulp 即便有 sourcemap 也很难定位到源文件在打包后的实际位置,而且 webpack 打包速度远比 gulp+browserify 快。
gulp 4.0 和 3.0 主要不同是引入 gulp.series & gulp.parallel
(vinyl-source-stream 要升级到 2.0),网上很多文章还是用 3.0(看他们定义 task 的依赖关系可判断),所以我们使用 4.0 带有一定学习目的。
.bablerc 设置
development 下只设置 target 是 chrome 和 firefox,production 才设置支持 IE
为了让代码能直接在 IE 里运行(然后弹出警告工具条不支持 IE :$).bablerc
设置增加了"transform-runtime"
插件,它的几个设置含义还没仔细研究,但可以注意到如果 target 不设置 IE,打包出来的代码是一样的。
babel 的环境变量是这样设置:
Default: process.env.BABEL_ENV || process.env.NODE_ENV || "development"
目前我们设置 BABEL_ENV
而不是 NODE_ENV
让意图更明确,同时确实不设置 development 减少跨平台的代码
怎么起服务器
我们一共尝试过三种 http 服务器:
live-server (主要是针对 http-server 不能重刷页面)
webpack 带的webpack-dev-server
没有别的原因,不会再引入别的服务器(比如 express,或者自己再写一个)。
网页刷新重连有几种做法:
- webpack 的 devServer 做更新重连,devServer 使用"webpack-cli",这其实是一个bug所以造成目前没法用
webpack-command
- 用 webpack-command + live-server 做更新重连。但要再引入live-server 这个包上一次更新是两年前,远不如webpack-dev-server 活跃。所以已经把 live-server 相关代码去掉了
- 用 gulp 时使用 browser-sync
断点调试
和微软工程师讨论了 6 天 vscode-chrome-debug,才终于发现原来是 webpack.config.js 没有设置devtool: 'source-map'
造成在 vscode 里断点停不下来。
断点调试大家一定熟练起来
dependencies 设置
- 如果 jssip 里用的我们就不在列出,比如 debug
- events, 这是模拟 node.js EventEmitter 在浏览器的实现,因为 jssip 已经设置所以也没在我们的 dependencies 列出
- 不使用 jQuery,网络请求使用 fetch
发布 es6 module 注意事项
- 我们所有用到 es6 功能 Chrome 66+ 都支持,所以不需要把 babel 转成 es5,
.bablerc
设置好 target 确保不必要的转码。 - 我们代码里既有 commonjs 的 require 又有 es6 import 所以需要 babel 统一转成 commonjs。
- mocha 单元测试还没有完全支持 es6 所以需要对单元测试代码做转码
如何在回调函数里正确使用 this
首先,只有回调函数里才可能会用到 that , 不是回调函数不需let that = this
(之前代码有这个问题)
其次 ,不要在每个回调函数前都习惯性的加 let that = this
并在函数体里用that
, 这样代码很难维护。
建议一下几个方法:
- 首选用箭头函数
- 多层回调里,二级回调通过 .bind(this) 保证 this 值正确,参见
Phone.init(params,callbackMap)
注:
Ephone 类加了一个类变量 self 和 webpack-dev-server 发生冲突
Uncaught TypeError: self.postMessage is not a function at sendMsg (webpack:///(:9000/webpack)-dev-server/client?:61:10)'
别的类也不能再设置 self,因为设置也最终也还是指向 Ephone(原因还是 100%确认)
参考 How to access the correct this
inside a callback?
如何让 mocha 运行 es6 代码
mocha 单元测试
localstorage
&fetch
都是浏览器方法,所以我们测试代码需要浏览器执行- npm run unit
- 用浏览器打开 test 文件夹下面的 index.html
- http://127.0.0.1:9999/?grep=
key
比如http://127.0.0.1:9999/?grep=web
只跑相关用例
浏览器 mocha 测试步骤
- 使 mocha 运行在浏览器端
- 将 mocha 测试代码转成浏览器可识别的代码(使用了 webpack + babel) 参考如何让浏览器支持 ES6 中的 import 和 export 语法
- 因为浏览器无法处理 node_modules 目录下的代码,所以想使用浏览器的
script type="module"
必须写全路径,借助 webpack 把所有 import 的文件打包成一个文件是最简单的方法,参见 - For browsers, you need to use Webpack or Browserify to compile all test files.
css 文件处理
- 按钮图标使用阿里云矢量图标,没有使用而外图片,所以 css 打包处理就是做最小化。
- 通过 webpack 打包处理 css,但 webpack 需要在 js 文件 import css,这是 webpack 特定语法;而且这样做如果用 gulp 打包就还要引入
browserify-css
参见 - sass 没有相应的 browserify 插件,但其实处理简单(css 也一样)就是把那行代码删了在 browserify。可以用两种方法,<1> 'gulp-replace' 生成一个临时文件再交给 browserify 处理 <2> 'browserify-replace'相对简单, 但帮助文档不详,查看源代码找到调用方法。
更新
在 js 文件 import css 这个做法始终让我很不安,在 SO 问了很久 都没答复,结果在 google webpack entry css
这三个关键字时候偶然发现答案。其实当时是在调查如何让 HtmlWebPackPlugin 不要对 index.html 加 css,保证 webpack 和 gulp 打包的东西都能正确显示。
做法就是一个 entry,但是设置文件名数组
entry:{
index: [
'./src/ui/index.js',
'./resources/css/phone.scss'
]
},
output:{
path: path.resolve(__dirname, './dist'),
filename: '[name].js'
},
选择哪种 font-face
阿里字体图标库有多种格式下载,因为我们已经限定了浏览器的版本 ,选用 woff 对我们最合适。
TTF, OTF, WOFF, EOT, SVG 字体文件对浏览器的支持
EOT 仅支持 IE8-11
OTF/TTF 支持 [ IE9-11, Edge12-14, Firefox 40-45, Chrome 43-49, Safari 8-9, Opera 32-35, iOS Sarfari 8.4-9.1, Android 4.4-44, Chrome for Android 46 ]
WOFF 支持[ IE9-11, Edge12-14, Firefox 40-45, Chrome 43-49, Safari 8-9, Opera 32-35, iOS Sarfari 8.4-9.1, Android 4.4-44, Chrome for Android 46 ]
WOFF2 支持[ Firefox 40-45, Chrome 43-49, Opera 32-35, Chrome for Android 46 ]
SVG 支持 [ Safari 8-9, iOS Sarfari 8.4-9.1 ]
统一文件 tab,引号,结尾分号设置
格式化工具Beautify 和 Prettier, 经过比较选择 Prettier Prettier 只能格式化 js 文件,其他文件用 vscode 自带 format document
通过 Prettier 统一文件 tab 设置,4 个空格;js 代码都用单引号,利用 Prettier 对 js 的ASI,注意前置括号会因此被加一个分号。
安装 Prettier 的 vscode 插件,设置 vscode format on save
true 以及 Ignore Trim Whitespace
false
以后合代码再发生此类问题一定查到原因。关于 Prettier 的其他叙述参见 文件格式修改.md
开发工具
开发人员需要标配以下几个工具:
vscode 2018 的版本,并安装vscode-chrome-debug
Prettier
Markdown 编辑器
使用
//首先创建一个实例
//具体配置信息和字段和 jssip 一样,除了 socekts 不需要配置
var ua = new JsSIPWrap(config)
创建完成后,需要登录
登录
ua.login();
登录成功后就可以监听各类事件.目前定义有如下:
// 注册登录相关
connecting
connected
disconnected
registered
unregistered
registrationFailed
//会话相关
newRTCSession
// 收到新的消息
newMessage
由于消息都是 xml ,且 PBX 的消息种类比较多,后面需要对每个不同的消息分别定义不同事件,外层使用不用关心 PBX 消息类型
拨打电话
ua.call(target, type)
// target 的是呼叫号码 ,type 是呼叫的类型 1:外线直接呼叫 2:回拨 3:内线互拨
挂断
ua.stop()
发送 xml 消息
ua.sendMessage(target, text)
//target 消息接受人,需要加企业和分机号拼接
// 如果发给 PBX 的事件,需要单独函数处理,上层不需要关系各种 PBX 事件
注意
- 不管是发出 invite 或者收到 invite 消息,session 相关的事件都通过原生 RTCSession 来监听
后续
需要把 ring 相关的封装写进来
发出的 PBX 消息事件接口完善
收到的 PBX 消息事件接口完善
注,对 jssip 使用参考tryit
http 对外接口封装使用说明
可参见单元测试代码
- 获取初始化数据接口 getLoginData(un, pwd, switchNumber, callintype)
该接口会获取登录所需的所有参数
- 调用示例
getLoginData('1006','1006','02566699734',4)
- 参数说明
参数名 | 说明 |类型
un | 分机号 | string
pwd | 密码 |string
switchNumber | 总机号 |string
callintype | 呼叫模式 | number
- web 接口统一调用接口 webApiHandler(functionName, webParam)
参数名 | 说明 |类型
functionName | 请求方法名 |string
webParam | 请求参数体 | object
webApiHandler 对外 function 的参数定义
getEpProfile 获取企业属性
- 调用示例
webApiHandler("getEpProfile",{un:'1006','pwd:1006',eid:65656})
* 参数说明
un | 分机号 | string
pwd | 密码 |string
eid | 企业 id |string
getMemberInfo 获取用户信息
- 调用示例
webApiHandler("getMemberInfo",{un:'1006','pwd:1006',eid:65656})
- 参数说明
un | 分机号 | string
pwd | 密码 |string
eid | 企业 id |string
getGroups 获取所有技能组
- 调用示例
webApiHandler("getGroups",{un:'1006','pwd:1006',eid:65656,needMembers:1})
- 参数说明
un | 分机号 | string
pwd | 密码 |string
eid | 企业 id |string
needMembers | 不传或传空则不返回属于组的用户信息,传 1 返回 mids| number
updateInfo 更新用户呼叫模式
- 调用示例
webApiHandler("updateInfo",{un:'1006','pwd:1006',eid:65656,jsonStr:{ "data": { "callintype": 2 } }}})
- 参数说明
un | 分机号 | string
pwd | 密码 |string
eid | 企业 id |string
\*jsonStr| 用户新的信息 json 内容【或者 post 一个 json 文件】|object
searchEpMembers 获取技能组包含坐席
- 调用示例
webApiHandler("searchEpMembers",{un:'1006','pwd:1006',eid:65656,searchGid:'2050',searchServiceControl:1})
- 参数说明
un | 分机号 | string
pwd | 密码 |string
eid | 企业 id |string
start | 起始记录数 默认 0 |string
length | 获取记录数,默认 10 |number
searchGid | 组 id (筛选未分组时传-1) | string
searchServiceControl |状态筛选 0-离线 1-空闲 2-暂离 3-消息请求 4-呼叫请求 5-通话中 6-话后处理| string
getMemberCallStates 获取坐席状态
- 调用示例
webApiHandler("getMemberCallStates",{un:'1006','pwd:1006',eid:65656,uid:'234'})
- 参数说明
un | 分机号 | string
pwd | 密码 |string
eid | 企业 id |string
uid | 用户 id |string