call.go 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046
  1. package action
  2. import (
  3. "errors"
  4. "fmt"
  5. "pbx-api-gin/internal/app/stc/active"
  6. "pbx-api-gin/internal/app/stc/priority"
  7. alstatus "pbx-api-gin/internal/app/stc/sendstatus"
  8. "pbx-api-gin/pkg/lfshook"
  9. "pbx-api-gin/pkg/utils"
  10. "strings"
  11. "sync"
  12. "time"
  13. )
  14. var Pads = []string{"2413", "2414", "2415", "2421", "2422", "2423", "2424", "2425", "2431", "2432", "2433", "2434", "2435", "2441", "2442", "2443", "2444",
  15. "2445", "2451", "2452", "2453", "2454", "2455", "2461", "2462", "2463", "2464", "2465", "2471", "2472", "2473", "2474", "2475", "2481", "2482", "2483",
  16. "2484", "2485", "2411", "2412"}
  17. var Pacus = []string{"2111", "2121", "2131", "2141", "2151", "2161", "2171", "2181"}
  18. var Speakers = []string{"2111", "2121", "2131", "2141", "2151", "2161", "2171", "2181", "2311", "2381"}
  19. // Function triggered before no cab occupied signal interrupt
  20. func InActiveHangup() {
  21. if active.ActivedCab == "" {
  22. HangupTask("PA")
  23. HangupTask("CPA")
  24. HangupTask("VOL")
  25. //HangupTask("PAD-OCC")
  26. } else {
  27. HangupTask("PA")
  28. HangupTask("PAD-OCC")
  29. HangupTask("CPA")
  30. HangupTask("EMG")
  31. HangupTask("SPC")
  32. HangupTask("DCS")
  33. HangupTask("STN")
  34. HangupTask("CHK")
  35. HangupTask("VOL")
  36. Hangup("2311") //hangup cabcab
  37. }
  38. }
  39. // Hangup 挂断指定分机或通道
  40. func Hangup(channel string) {
  41. lfshook.NewLogger().Infof("Hangup extensions/channel :%s", channel)
  42. if !utils.IsChannel(channel) {
  43. channel = fmt.Sprintf(`/^(PJ)?SIP\/%s-.*$/`, channel)
  44. }
  45. action := map[string]string{
  46. "Action": "hangup",
  47. "Channel": channel,
  48. }
  49. //lfshook.NewLogger().Infof("hangup action :%+v", action)
  50. if _, _, err := AminInstance.Send(action); err != nil {
  51. lfshook.NewLogger().Errorf("Hangup %+v", err)
  52. }
  53. }
  54. // Hangup 挂断所有分机,除指定分机和PAD
  55. func HangupAllExcept(caller string) {
  56. //all PACU
  57. for _, ret := range Pacus {
  58. Hangup(ret)
  59. }
  60. switch caller {
  61. case "2311":
  62. Hangup("1411") //IO1
  63. Hangup("1481") //IO8
  64. //Hangup("2311") //ICP1
  65. Hangup("2381") //ICP8
  66. case "2381":
  67. Hangup("1411") //IO1
  68. Hangup("1481") //IO8
  69. Hangup("2311") //ICP1
  70. //Hangup("2381") //ICP8
  71. case "1411":
  72. //Hangup("1411") //IO1
  73. Hangup("1481") //IO8
  74. Hangup("2311") //ICP1
  75. Hangup("2381") //ICP8
  76. case "1481":
  77. Hangup("1411") //IO1
  78. //Hangup("1481") //IO8
  79. Hangup("2311") //ICP1
  80. Hangup("2381") //ICP8
  81. case "":
  82. Hangup("1411") //IO1
  83. Hangup("1481") //IO8
  84. Hangup("2311") //ICP1
  85. Hangup("2381") //ICP8
  86. }
  87. }
  88. // Hangup task
  89. func HangupTask(TaskName string) {
  90. lfshook.NewLogger().Infof("HangupTask Check TaskName:%s ", TaskName)
  91. if TaskName == "PAD-OCC" {
  92. resCaller, err := QueueStatus("0301", "") // check OCC queue, get entries
  93. if err != nil {
  94. lfshook.NewLogger().Infof("QueueStatus err:%+v", err)
  95. return
  96. }
  97. //lfshook.NewLogger().Infof("============QueueStatus ret :%+v", resCaller)
  98. if resCaller != nil {
  99. //lfshook.NewLogger().Infof("===QueueStatus=entry=%+v", resCaller.Entrys)
  100. if resCaller.Entrys != nil {
  101. for _, caller := range resCaller.Entrys {
  102. //lfshook.NewLogger().Infof("===QueueStatus=entry=%+v", caller)
  103. time.Sleep(time.Millisecond * 50)
  104. RedirectInQueue(caller.CallerIDNum, "0300", "queues-icp-redirect", caller.CallerIDNum) // redirect All PAD redirect to ICP queue
  105. }
  106. }
  107. }
  108. priority.OCCAnswer = 0
  109. }
  110. taskInfo, ok := priority.RegistryTask.Get(TaskName)
  111. if ok {
  112. HangupAllLocalChan()
  113. ConfbridgeKick(taskInfo.ConfbridgeID, "all")
  114. Hangup(taskInfo.RunChannel)
  115. }
  116. }
  117. // interrupt the running task
  118. func InterruptRunningTask(toRunTask string) string {
  119. utils.LoggerDebug.Printf("InterruptRunningTask TorunType:%s", toRunTask)
  120. var task priority.TaskInfo
  121. var taskName string
  122. var ok bool
  123. lfshook.NewLogger().Infof("InterruptRunningTask toRuntask:%s ", toRunTask)
  124. if toRunTask != "PA" && toRunTask != "PAD-ICP" && toRunTask != "PAD-TMS" { // ignore C2C
  125. taskName, task, ok = priority.RegistryTask.HighestPriorityRunningTask1()
  126. if !ok {
  127. return ""
  128. }
  129. } else { // have to check C2C
  130. taskName, task, ok = priority.RegistryTask.HighestPriorityRunningTask()
  131. if !ok {
  132. return ""
  133. }
  134. }
  135. utils.LoggerDebug.Printf("InterruptRunningTask RunningTask:%+v", taskName)
  136. //lfshook.NewLogger().Infof("InterruptRunningTask RunningTask:%+v ", task)
  137. //same type return
  138. if toRunTask == taskName {
  139. if toRunTask == "PAD-ICP" || toRunTask == "PAD-TMS" || toRunTask == "PAD-OCC" {
  140. //Auto Answer PAD-OCC one by one, clean the old confbridge and channels before answer a new PAD .
  141. if toRunTask == "PAD-OCC" {
  142. Hangup(task.RunChannel) //pad
  143. ConfbridgeKick(task.ConfbridgeID, "all")
  144. //HangupIO() //io
  145. //interrupt OCC-PAD Hangup OI
  146. if active.ActivedCab == "1" {
  147. Hangup("1411")
  148. } else if active.ActivedCab == "8" {
  149. Hangup("1481")
  150. } else {
  151. if active.ActivedCabDelay == "1" {
  152. Hangup("1411")
  153. } else if active.ActivedCabDelay == "8" {
  154. Hangup("1481")
  155. } else {
  156. Hangup("1411")
  157. }
  158. }
  159. //lfshook.NewLogger().Infof("===InterruptRunningTask=ret==== ")
  160. }
  161. return taskName
  162. }
  163. }
  164. //pad all reset
  165. if toRunTask == "AlarmHoldResetAll" {
  166. HangupAllLocalChan()
  167. return taskName
  168. }
  169. switch task.RunType {
  170. case "SPC":
  171. if toRunTask == "C2C" {
  172. HangupICP()
  173. } else {
  174. ConfbridgeKick(task.ConfbridgeID, "all")
  175. }
  176. time.Sleep(time.Millisecond * 200)
  177. case "CHK":
  178. if toRunTask == "C2C" {
  179. HangupICP()
  180. } else {
  181. ConfbridgeKick(task.ConfbridgeID, "all")
  182. }
  183. time.Sleep(time.Millisecond * 200)
  184. case "DCS":
  185. if toRunTask == "STN" {
  186. return taskName
  187. } else if toRunTask == "C2C" {
  188. HangupICP()
  189. } else {
  190. ConfbridgeKick(task.ConfbridgeID, "all")
  191. }
  192. time.Sleep(time.Millisecond * 200)
  193. case "STN":
  194. if toRunTask == "DCS" {
  195. return taskName
  196. } else if toRunTask == "C2C" {
  197. HangupICP()
  198. } else {
  199. ConfbridgeKick(task.ConfbridgeID, "all")
  200. }
  201. time.Sleep(time.Millisecond * 200)
  202. case "CPA":
  203. //kick CPA members
  204. if toRunTask != "C2C" {
  205. CPAConfbridgeKick(task)
  206. //alstatus.PaStatus("", "CPA", "end")
  207. } else if toRunTask == "C2C" {
  208. HangupICP()
  209. }
  210. time.Sleep(time.Millisecond * 200)
  211. case "EMG":
  212. //kick EMG members
  213. if toRunTask == "EMG" {
  214. ConfbridgeKick(task.ConfbridgeID, "all")
  215. } else if toRunTask != "C2C" {
  216. EMGConfbridgeKick(task)
  217. //alstatus.PaStatus("", "EMG", "end")
  218. } else if toRunTask == "C2C" {
  219. HangupICP()
  220. }
  221. time.Sleep(time.Millisecond * 200)
  222. case "C2C": // Interrupt C2C task running,
  223. if toRunTask == "PA" || toRunTask == "PAD-ICP" || toRunTask == "PAD-TMS" {
  224. HangupICP()
  225. return taskName
  226. }
  227. case "PAD-ICP", "PAD-TMS": // Interrupt PAD task running,
  228. if toRunTask == "PAD-ICP" || toRunTask == "PAD-TMS" {
  229. break
  230. }
  231. priority.InterruptedPad = "PAD-ICP"
  232. //lfshook.NewLogger().Infof("InterruptRunningTask interrupt PAD-ICP/PAD-TMS ,Running type :%s !", task.RunType)
  233. chans, err := CoreShowChannels()
  234. if err != nil {
  235. lfshook.NewLogger().Infof("InterruptRunningTask CoreShowChannels err:%+v", err)
  236. return taskName
  237. }
  238. //1. Redirect the connected PAD to 0300,hangup the other pad channel
  239. for _, ret := range chans {
  240. // Redirect the connected PAD to 0300
  241. if utils.IsPAIU(ret.CallerIDNum) {
  242. //lfshook.NewLogger().Infof("====interrupt PAD ==== %+v ", ret)
  243. if ret.ConnectedLineNum == "<unknown>" { //redirect pad chanspy channel
  244. err := Redirect(ret.Channel, "0300", "queues-icp-redirect", "", "PAD")
  245. if err != nil {
  246. lfshook.NewLogger().Infof("InterruptRunningTask Redirect err:%+v", err)
  247. return taskName
  248. }
  249. //lfshook.NewLogger().Infof("====interrupt PAD =1111=== %+v ", ret)
  250. number := strings.Split(strings.Split(ret.Channel, "-")[0], "/")[1]
  251. active.NotifyPaiu(number, "hold")
  252. //HangupAllLocalChan()
  253. }
  254. }
  255. }
  256. for _, ret := range chans {
  257. //hangup pad call ICP channel
  258. if utils.IsPAIU(ret.CallerIDNum) {
  259. if utils.IsPAIU(ret.CallerIDNum) && ret.ChannelStateDesc == "Up" && utils.IsICP(ret.ConnectedLineNum) {
  260. //lfshook.NewLogger().Infof("Hangup PAD Channel :%+v", ret.Channel)
  261. Hangup(ret.Channel)
  262. }
  263. }
  264. }
  265. alstatus.PaStatus("", "PAD", "end")
  266. priority.RegistryTask.StopAndUnregister("PAD-ICP")
  267. priority.RegistryTask.StopAndUnregister("PAD-TMS")
  268. //2. hangup task channel (ICP + PACU)
  269. //lfshook.NewLogger().Infof("===InterruptRunningTask=2. hangup task channel === ")
  270. HangupAllLocalChan()
  271. HangupICP()
  272. case "PAD-OCC": // Interrupt PAD-OCC task running,
  273. if toRunTask == "C2C" {
  274. HangupICP()
  275. break
  276. } else {
  277. priority.InterruptedPad = "PAD-OCC"
  278. priority.OCCAnswer = 0
  279. resCaller, err := QueueStatus("0301", "") // check OCC queue, get entries
  280. if err != nil {
  281. lfshook.NewLogger().Infof("QueueStatus err:%+v", err)
  282. return taskName
  283. }
  284. if resCaller == nil {
  285. return taskName
  286. }
  287. if resCaller.Entrys != nil {
  288. for _, caller := range resCaller.Entrys {
  289. //lfshook.NewLogger().Infof("===QueueStatus=entry=%+v", caller)
  290. time.Sleep(time.Millisecond * 50)
  291. RedirectInQueue(caller.CallerIDNum, "0300", "queues-icp-redirect", caller.CallerIDNum) // redirect All PAD redirect to ICP queue
  292. }
  293. }
  294. priority.RegistryTask.StopAndUnregister("PAD-OCC")
  295. //2. Hangup connected PAD
  296. //lfshook.NewLogger().Infof("===InterruptRunningTask=Hangup connected PAD=== ")
  297. Hangup(task.RunChannel)
  298. //3. interrupt OCC-PAD Hangup OI
  299. if active.ActivedCab == "1" {
  300. Hangup("1411")
  301. } else if active.ActivedCab == "8" {
  302. Hangup("1481")
  303. } else {
  304. if active.ActivedCabDelay == "1" {
  305. Hangup("1411")
  306. } else if active.ActivedCabDelay == "8" {
  307. Hangup("1481")
  308. } else {
  309. Hangup("1411")
  310. }
  311. }
  312. HangupAllLocalChan()
  313. ConfbridgeKick(task.ConfbridgeID, "all")
  314. //occ pad end
  315. if priority.PADOccStart == 1 {
  316. alstatus.OccPad("end")
  317. alstatus.PaStatus("", "PAD", "end")
  318. priority.PADOccStart = 0
  319. priority.OCCAnswer = 0
  320. }
  321. }
  322. default:
  323. lfshook.NewLogger().Infof("InterruptRunningTask goto default !")
  324. //if !strings.Contains(priority.RunningPATaskChan, "0502@default") {
  325. // Hangup(priority.RunningPATaskChan)
  326. //}
  327. if toRunTask != "C2C" && task.RunType != "PA" {
  328. Hangup(task.RunChannel)
  329. ConfbridgeKick(task.ConfbridgeID, "all")
  330. }
  331. }
  332. return taskName
  333. }
  334. // Hangup all ICP
  335. func HangupICP() {
  336. Hangup("2311") //ICP1
  337. Hangup("2381") //ICP8
  338. }
  339. // Hangup all IO
  340. func HangupIO() {
  341. Hangup("1411") //IO1
  342. Hangup("1481") //IO8
  343. }
  344. // Hangup all PACU
  345. func HangupAllPACU() {
  346. //all PACU
  347. for _, ret := range Pacus {
  348. Hangup(ret)
  349. }
  350. }
  351. func HangupAllLocalChan() {
  352. chans, err := CoreShowChannels()
  353. if err != nil {
  354. lfshook.NewLogger().Infof("CoreShowChannels %+v", err)
  355. return
  356. }
  357. for _, ret := range chans {
  358. if strings.Contains(ret.Channel, "Local") && !strings.Contains(ret.Channel, "0502@default") {
  359. //lfshook.NewLogger().Infof("HangupAllLocalChan=====hangup========= %+v", ret)
  360. Hangup(ret.Channel)
  361. }
  362. }
  363. }
  364. // Hangup all PACU
  365. func HangupAllPAD() {
  366. //all PAD
  367. for _, ret := range Pads {
  368. Hangup(ret)
  369. }
  370. }
  371. // Hangup all calls
  372. func HangupAll() {
  373. utils.ExecCmdAsync("/usr/sbin/asterisk", "-rx", "hangup request all")
  374. }
  375. // Dial 拨打号码
  376. func Dial(src, dst, dialrule, callerID, callerName string, callType string) {
  377. chanel := fmt.Sprintf("%s/%s@default", "Local", src)
  378. action := map[string]string{
  379. "Action": "Originate",
  380. "Channel": chanel,
  381. "Exten": dst,
  382. "Context": dialrule,
  383. "CallerID": fmt.Sprintf("%s<%s>", callerName, callerID),
  384. "Priority": "1",
  385. "Variable": fmt.Sprintf("CAB=%s", callType),
  386. "async": "true",
  387. }
  388. //lfshook.NewLogger().Infof("================dial action %+v", action)
  389. res, _, err := AminInstance.Send(action)
  390. if err != nil {
  391. lfshook.NewLogger().Errorf("%+v", err)
  392. }
  393. lfshook.NewLogger().Info(res)
  394. }
  395. // Dial 拨打号码
  396. func DialICP(src, dst, dialrule, callerID, callerName string) {
  397. chanel := fmt.Sprintf("%s/%s@call-icp", "Local", src)
  398. action := map[string]string{
  399. "Action": "Originate",
  400. "Channel": chanel,
  401. "Exten": dst,
  402. "Context": dialrule,
  403. "CallerID": fmt.Sprintf("%s<%s>", callerName, callerID),
  404. "Priority": "1",
  405. "Variable": fmt.Sprintf("CBID=%s", callerID),
  406. "async": "true",
  407. }
  408. lfshook.NewLogger().Infof("dial action %+v", action)
  409. res, _, err := AminInstance.Send(action)
  410. if err != nil {
  411. lfshook.NewLogger().Errorf("%+v", err)
  412. }
  413. lfshook.NewLogger().Info(res)
  414. }
  415. // 获取分机状态
  416. func ExtenStatus(exten string) (Status string) {
  417. action := map[string]string{
  418. "Action": "ExtensionState",
  419. "Exten": exten,
  420. "Context": "default",
  421. }
  422. res, _, err := AminInstance.Send(action)
  423. if err != nil {
  424. lfshook.NewLogger().Errorf("%+v", err)
  425. return ""
  426. }
  427. //lfshook.NewLogger().Infof("================ExtensionState:res %+v", res)
  428. return res["StatusText"]
  429. }
  430. // PACU ChanSpy
  431. func ChanSpy(src, dst string, whisper, bargein bool) {
  432. lfshook.NewLogger().Infof("chan spy src:%s dst:%s", src, dst)
  433. //channel := fmt.Sprintf("%s/%s", utils.DialPrefix, dst)
  434. channel := fmt.Sprintf("Local/%s@aio-rule", dst)
  435. data := fmt.Sprintf("%s/%s,qBE", utils.DialPrefix, src)
  436. /*
  437. if whisper {
  438. data = fmt.Sprintf("%s,w", data)
  439. }
  440. if bargein {
  441. data = fmt.Sprintf("%s,B", data)
  442. }
  443. */
  444. action := map[string]string{
  445. "Action": "Originate",
  446. "Channel": channel, // 不存在的通话
  447. "Application": "ChanSpy",
  448. "Data": data, // 存在的通话
  449. "CallerID": dst,
  450. "Async": "true",
  451. }
  452. lfshook.NewLogger().Infof("PACU ChanSpy action %+v", action)
  453. _, _, err := AminInstance.Send(action)
  454. if err != nil {
  455. lfshook.NewLogger().Errorf("%+v", err)
  456. }
  457. }
  458. // Redirect 转接
  459. func RedirectInQueue(channel, dst, dialrule, callerID string) (err error) {
  460. //callerID := "redirect"
  461. //lfshook.NewLogger().Infof("redirect src %s to dst %s", channel, dst)
  462. if !utils.IsChannel(channel) {
  463. //callerID = channel
  464. if channel, err = GetChannelByExtenNotBridged(channel); err != nil {
  465. return err
  466. }
  467. }
  468. action := map[string]string{
  469. "Action": "Redirect",
  470. "Channel": channel,
  471. "Exten": dst,
  472. "Context": dialrule,
  473. "CallerID": callerID,
  474. "Priority": "1",
  475. "async": "true",
  476. }
  477. lfshook.NewLogger().Infof("RedirectInQueue: %+v", action)
  478. res, _, err := AminInstance.Send(action)
  479. if err != nil {
  480. lfshook.NewLogger().Error(err)
  481. }
  482. lfshook.NewLogger().Info(res)
  483. return err
  484. }
  485. // Redirect 转接
  486. func Redirect(channel, dst, dialrule, callerID, callerName string) (err error) {
  487. //callerID := "redirect"
  488. //lfshook.NewLogger().Infof("redirect src %s to dst %s", channel, dst)
  489. if !utils.IsChannel(channel) {
  490. callerID = channel
  491. if channel, err = GetChannelByExten(channel); err != nil {
  492. return err
  493. }
  494. }
  495. action := map[string]string{
  496. "Action": "Redirect",
  497. "Channel": channel,
  498. "Exten": dst,
  499. "Context": dialrule,
  500. "CallerID": fmt.Sprintf("%s<%s>", callerName, callerID),
  501. "Priority": "1",
  502. "async": "true",
  503. }
  504. lfshook.NewLogger().Infof("Redirect: %+v", action)
  505. res, _, err := AminInstance.Send(action)
  506. if err != nil {
  507. lfshook.NewLogger().Error(err)
  508. }
  509. lfshook.NewLogger().Info(res)
  510. return err
  511. }
  512. func SetPadTimer() {
  513. //toRunPadpriority := priority.GetPriorityByKey(priority.InterruptedPad) //Get PAD priori 获取之前打断的报警优先级
  514. toRunPadpriority := priority.GetPriorityByKey("PAD-ICP")
  515. _, taskTmp, ok := priority.RegistryTask.HighestPriorityRunningTask()
  516. if ok {
  517. if taskTmp.Priority < toRunPadpriority { //higher priority task running ,do not set timer
  518. utils.LoggerDebug.Printf("PAD SetPadTimer runing priority:%d toRun priority:%d , return !", taskTmp.Priority, toRunPadpriority)
  519. return
  520. }
  521. }
  522. utils.LoggerDebug.Printf("PAD SetPadTimer check 0300")
  523. res, err := QueueStatus("0300", "")
  524. if err != nil {
  525. lfshook.NewLogger().Infof("QueueStatus err%+v", err)
  526. return
  527. }
  528. if res == nil {
  529. return
  530. }
  531. if res.Calls != "0" {
  532. utils.LoggerDebug.Printf("PAD SetPadTimer Set QueueTimer timeout %ds !", active.PADTimeout)
  533. //active.SetTimer = true
  534. //lfshook.NewLogger().Logger.Infof("=========Start PAD timer !=============")
  535. if active.QueueTimer != nil {
  536. if active.QueueTimer.Stop() {
  537. //lfshook.NewLogger().Logger.Infof("=========Release PAD timer true !============")
  538. } else {
  539. //lfshook.NewLogger().Logger.Infof("=========Release PAD timer false ! ============")
  540. }
  541. }
  542. //lfshook.NewLogger().Logger.Infof("=========Start PAD timer !======%d=======", active.PADTimeout)
  543. active.QueueTimer = time.AfterFunc(time.Duration(active.PADTimeout)*time.Second, func() { // check the PAD 30s timeout
  544. //active.QueueTimer = time.AfterFunc(30*time.Second, func() { // check the PAD 30s timeout
  545. //if both not active , return
  546. if active.ActivedCab == "" {
  547. return
  548. }
  549. res, err := QueueStatus("0301", "") // check OCC queue , if empty OCC-PAD start
  550. if err != nil {
  551. lfshook.NewLogger().Infof("OCC QueueStatus err:%+v", err)
  552. return
  553. }
  554. if res == nil {
  555. return
  556. }
  557. if res.Calls == "0" { // OCC queue empty
  558. priority.ICPAnswer = 0
  559. for _, ret := range alstatus.PadQueues {
  560. //utils.LoggerDebug.Printf("PAD to OCC exten:%s", ret.Exten)
  561. //order by pos
  562. RedirectInQueue(ret.Exten, "0301", "queues-occ", ret.Exten) // redirect All ICP-PAD redirect to OCC queue
  563. time.Sleep(time.Millisecond * 100)
  564. }
  565. }
  566. })
  567. }
  568. }
  569. func ConfbridgeKick(confnum, channel string) (res map[string]string, err error) {
  570. action := map[string]string{
  571. "Action": "ConfbridgeKick",
  572. "Conference": confnum,
  573. "Channel": channel,
  574. }
  575. res, _, err = AminInstance.Send(action)
  576. if err != nil {
  577. return nil, err
  578. }
  579. lfshook.NewLogger().Infof("ConfbridgeKick res:%+v", res)
  580. if res["Response"] != "Success" {
  581. return nil, errors.New(res["Message"])
  582. }
  583. return res, nil
  584. }
  585. func CPAConfbridgeKick(confInfo priority.TaskInfo) (res map[string]string, err error) {
  586. if !confInfo.Running {
  587. utils.LoggerDebug.Printf("CPA CPAConfbridgeKick , not running, return .")
  588. return
  589. }
  590. utils.LoggerDebug.Printf("CPA CPAConfbridgeKick , kick all members .")
  591. chans, err := ConfbridgeList(confInfo.ConfbridgeID)
  592. if err != nil {
  593. return nil, errors.New(res["Message"])
  594. }
  595. for _, confChan := range chans {
  596. if active.TrainDevide == 1 {
  597. if active.CabNum == "1" { //在1车车厢内
  598. if !strings.Contains(confChan, "PJSIP/1411") {
  599. ConfbridgeKick(confInfo.ConfbridgeID, confChan)
  600. }
  601. } else { //在8车车厢内
  602. if !strings.Contains(confChan, "PJSIP/1481") {
  603. ConfbridgeKick(confInfo.ConfbridgeID, confChan)
  604. }
  605. }
  606. } else {
  607. if active.ActivedCab != "1" {
  608. if !strings.Contains(confChan, "PJSIP/1411") {
  609. ConfbridgeKick(confInfo.ConfbridgeID, confChan)
  610. }
  611. } else {
  612. if !strings.Contains(confChan, "PJSIP/1481") {
  613. ConfbridgeKick(confInfo.ConfbridgeID, confChan)
  614. }
  615. }
  616. }
  617. }
  618. if confInfo.Running {
  619. alstatus.PaStatus("", "CPA", "end")
  620. }
  621. priority.RegistryTask.UpdateStatus("CPA", false)
  622. return res, nil
  623. }
  624. func CPAConfbridgeReinvite(task priority.TaskInfo) bool {
  625. if task.Running {
  626. utils.LoggerDebug.Printf("CPA CPAConfbridgeReinvite , already running, return .")
  627. return false
  628. }
  629. time.Sleep(time.Millisecond * 100)
  630. utils.LoggerDebug.Printf("CPA CPAConfbridgeReinvite , resume CPA .")
  631. chans, err := ConfbridgeList(task.ConfbridgeID)
  632. if len(chans) > 1 || err != nil {
  633. utils.LoggerDebug.Printf("CPA CPAConfbridgeReinvite , return . ConfbridgeList chans > 1 or err !")
  634. return false
  635. }
  636. if priority.PAInterrupt == 1 { // PA 打断标签判断
  637. utils.LoggerDebug.Printf("CPA ConfbridgeReinvite , PA ready to go , return !")
  638. return false
  639. } else if priority.CABInterrupt == 1 { //CABCAB 打断标签判断
  640. priority.TaskCreating = "CPA"
  641. for _, ext := range Speakers { //高优先级被cabcab打断,或者高优先级直接挂断
  642. if utils.IsICP(ext) {
  643. if priority.CABInterrupt == 1 {
  644. utils.LoggerDebug.Printf("CPA ConfbridgeReinvite , Get CABCAB Interrupt resume CPA , ignore %s continue .", ext)
  645. continue
  646. }
  647. }
  648. ConfbridgeReinvite(ext, "call-speakers-cpa", task.ConfbridgeID)
  649. }
  650. //task.Running = true
  651. priority.RegistryTask.UpdateStatus("CPA", true)
  652. time.Sleep(time.Millisecond * 200) //等待通道建立
  653. priority.TaskCreating = ""
  654. alstatus.PaStatus("", "CPA", "start")
  655. priority.CPAActived = 0
  656. } else if priority.TaskCreating != "" {
  657. utils.LoggerDebug.Printf("CPA ConfbridgeReinvite , other PA ready to go , return !")
  658. return false
  659. } else {
  660. priority.TaskCreating = "CPA"
  661. for _, ext := range Speakers {
  662. ConfbridgeReinvite(ext, "call-speakers-cpa", task.ConfbridgeID)
  663. }
  664. //task.Running = true
  665. priority.RegistryTask.UpdateStatus("CPA", true)
  666. time.Sleep(time.Millisecond * 200) //等待通道建立
  667. priority.TaskCreating = ""
  668. alstatus.PaStatus("", "CPA", "start")
  669. priority.CPAActived = 0
  670. }
  671. return true
  672. }
  673. func EMGConfbridgeKick(confInfo priority.TaskInfo) (res map[string]string, err error) {
  674. if !confInfo.Running {
  675. utils.LoggerDebug.Printf("EMG EMGConfbridgeKick , not running, return .")
  676. return
  677. }
  678. utils.LoggerDebug.Printf("EMG EMGConfbridgeKick , kick all members .")
  679. chans, err := ConfbridgeList(confInfo.ConfbridgeID)
  680. if err != nil {
  681. return nil, errors.New(res["Message"])
  682. }
  683. for _, confChan := range chans {
  684. if !strings.Contains(confChan, "0502@default") {
  685. ConfbridgeKick(confInfo.ConfbridgeID, confChan)
  686. }
  687. }
  688. if confInfo.Running {
  689. alstatus.PaStatus("", "EMG", "end")
  690. }
  691. //confInfo.Running = false
  692. priority.RegistryTask.UpdateStatus("EMG", false)
  693. return res, nil
  694. }
  695. func EMGConfbridgeReinvite(task priority.TaskInfo) {
  696. if priority.CPAActived == 1 && priority.AllTasks.EMG.Priority > priority.AllTasks.CPA.Priority {
  697. utils.LoggerDebug.Printf("EMG ConfbridgeReinvite , CPA actived , return .")
  698. return
  699. }
  700. //if priority.CABInterrupt != 1 {
  701. // time.Sleep(time.Millisecond * 100)
  702. //} else {
  703. //time.Sleep(time.Second * 1) //wait cpa start first
  704. //}
  705. utils.LoggerDebug.Printf("EMG ConfbridgeReinvite , resume EMG .")
  706. if task.Running {
  707. utils.LoggerDebug.Printf("EMG ConfbridgeReinvite , already running ,return .")
  708. return
  709. }
  710. if priority.PAInterrupt == 1 { // PA 打断标签判断
  711. utils.LoggerDebug.Printf("EMG ConfbridgeReinvite , PA ready to go , return !")
  712. return
  713. } else if priority.CABInterrupt == 1 { //CABCAB 打断标签判断
  714. priority.TaskCreating = "EMG"
  715. for _, ext := range Speakers { //高优先级被cabcab打断,或者高优先级直接挂断
  716. if utils.IsICP(ext) {
  717. if priority.CABInterrupt == 1 {
  718. utils.LoggerDebug.Printf("EMG ConfbridgeReinvite , Get CABCAB Interrupt resume EMG , ignore %s continue .", ext)
  719. continue
  720. }
  721. }
  722. ConfbridgeReinvite(ext, "call-speakers-emg", task.ConfbridgeID)
  723. }
  724. //task.Running = true
  725. priority.RegistryTask.UpdateStatus("EMG", true)
  726. time.Sleep(time.Millisecond * 200) //等待通道建立
  727. priority.TaskCreating = ""
  728. alstatus.PaStatus("", "EMG", "start")
  729. } else if priority.TaskCreating != "" {
  730. utils.LoggerDebug.Printf("EMG ConfbridgeReinvite , other PA ready to go , return !")
  731. return
  732. } else {
  733. priority.TaskCreating = "EMG"
  734. for _, ext := range Speakers {
  735. ConfbridgeReinvite(ext, "call-speakers-emg", task.ConfbridgeID)
  736. }
  737. //task.Running = true
  738. priority.RegistryTask.UpdateStatus("EMG", true)
  739. time.Sleep(time.Millisecond * 200) //等待通道建立
  740. priority.TaskCreating = ""
  741. alstatus.PaStatus("", "EMG", "start")
  742. }
  743. }
  744. func ConfbridgeList(confnum string) (chans []string, err error) {
  745. action := map[string]string{
  746. "Action": "ConfbridgeList",
  747. "Conference": confnum,
  748. }
  749. res, events, err := AminInstance.Send(action)
  750. if err != nil {
  751. return nil, err
  752. }
  753. lfshook.NewLogger().Infof("ConfbridgeList res:%+v", res)
  754. if res["Response"] == "Success" {
  755. for _, event := range events {
  756. if event.Data["Event"] == "ConfbridgeList" {
  757. chans = append(chans, event.Data["Channel"])
  758. }
  759. }
  760. return chans, nil
  761. } else {
  762. return nil, errors.New(res["Message"])
  763. }
  764. }
  765. func ConfbridgeReinvite(src, context, confID string) {
  766. if ExtenStatus(src) != "Idle" {
  767. lfshook.NewLogger().Infof(" ConfbridgeReinvite ext:%s Not Idle !", src)
  768. return
  769. }
  770. chanel := fmt.Sprintf("Local/%s@%s", src, context)
  771. action := map[string]string{
  772. "Action": "Originate",
  773. "Channel": chanel,
  774. "Exten": "000",
  775. "Context": "confbridge-join",
  776. "CallerID": fmt.Sprintf("%s<%s>", "", ""),
  777. "Priority": "1",
  778. "Variable": fmt.Sprintf("CBID=%s", confID),
  779. "async": "true",
  780. }
  781. lfshook.NewLogger().Infof("dial action %+v", action)
  782. res, _, err := AminInstance.Send(action)
  783. if err != nil {
  784. lfshook.NewLogger().Errorf("%+v", err)
  785. }
  786. lfshook.NewLogger().Info(res)
  787. }
  788. func ICPConfbridgeReinvite(confID, paType string) {
  789. if priority.CABInterrupt == 1 || priority.CABInterrupt == 1 {
  790. utils.LoggerDebug.Printf("ICPConfbridgeReinvite, Get PA/CABCAB Interrupt resume %s faild .", paType)
  791. return
  792. }
  793. switch paType {
  794. case "PAD-OCC":
  795. go DialICP("8", "2311", "confbridge-join", confID, "1") //ICP1---call
  796. go DialICP("8", "2381", "confbridge-join", confID, "8") //ICP8---call
  797. case "CPA":
  798. go DialICP("2", "2311", "confbridge-join", confID, "1") //ICP1---call
  799. go DialICP("2", "2381", "confbridge-join", confID, "8") //ICP8---call
  800. case "EMG":
  801. go DialICP("3", "2311", "confbridge-join", confID, "1") //ICP1---call
  802. go DialICP("3", "2381", "confbridge-join", confID, "8") //ICP8---call
  803. case "SPC":
  804. go DialICP("6", "2311", "confbridge-join", confID, "1") //ICP1---call
  805. go DialICP("6", "2381", "confbridge-join", confID, "8") //ICP8---call
  806. case "STN":
  807. go DialICP("4", "2311", "confbridge-join", confID, "1") //ICP1---call
  808. go DialICP("4", "2381", "confbridge-join", confID, "8") //ICP8---call
  809. case "DCS":
  810. go DialICP("5", "2311", "confbridge-join", confID, "1") //ICP1---call
  811. go DialICP("5", "2381", "confbridge-join", confID, "8") //ICP8---call
  812. case "CHK":
  813. go DialICP("10", "2311", "confbridge-join", confID, "1") //ICP1---call
  814. go DialICP("10", "2381", "confbridge-join", confID, "8") //ICP8---call
  815. case "VOL":
  816. go DialICP("11", "2311", "confbridge-join", confID, "1") //ICP1---call
  817. go DialICP("11", "2381", "confbridge-join", confID, "8") //ICP8---call
  818. }
  819. }
  820. var waitMutex sync.Mutex
  821. // 设置全局变量控制任务创建过程,避免被其他任务打乱任务创建过程
  822. func WaitTaskCreate(task string, args ...string) { //arg1(task chan)
  823. utils.LoggerDebug.Printf("%s check task creating ..... ,TaskCreating = %s", task, priority.TaskCreating)
  824. waitMutex.Lock()
  825. defer waitMutex.Unlock()
  826. switch priority.TaskCreating {
  827. case "C2C":
  828. if /*task == "PA" ||*/ task == "CPA" {
  829. //获取正在创建的任务的优先级
  830. //priorityC2C := priority.GetPriorityByKey("C2C")
  831. //获取将要创建的任务的优先级
  832. //priorityTask := priority.GetPriorityByKey(task)
  833. //比较优先级,确定是否终止正在创建的任务
  834. /*if priorityC2C < priorityTask {
  835. utils.LoggerDebug.Printf("%s check task C2C creating , hangup CPA %s ", task, args[0])
  836. //结束task(CPA)
  837. if len(args) > 0 {
  838. Hangup(args[0])
  839. goto DELAY
  840. }
  841. } else {
  842. //结束C2C,PA 则不需要挂断ICP(由ICP自行处理优先级)
  843. utils.LoggerDebug.Printf("%s check task C2C creating , hangup C2C ICPs ", task)
  844. HangupICP()
  845. goto DELAY
  846. }*/
  847. } else {
  848. goto DEFAULT
  849. }
  850. return
  851. case "CPA":
  852. if task == "PA" /*|| task == "C2C"*/ {
  853. //获取正在创建的任务的优先级
  854. priorityCPA := priority.GetPriorityByKey("CPA")
  855. //获取将要创建的任务的优先级
  856. priorityTask := priority.GetPriorityByKey(task)
  857. //比较优先级,确定是否终止正在创建的任务
  858. if priorityCPA < priorityTask {
  859. utils.LoggerDebug.Printf("%s check task CPA creating , hangup %s %s", task, task, args[0])
  860. //结束task(PA,CPA)
  861. if len(args) > 0 {
  862. Hangup(args[0])
  863. goto DELAY
  864. }
  865. } else {
  866. //结束CPA,获取CPA通道
  867. if active.ActivedCab == "1" {
  868. utils.LoggerDebug.Printf("%s check task creating , hangup CPA %s ", task, args[0])
  869. Hangup("1481")
  870. goto DELAY
  871. } else if active.ActivedCab == "8" {
  872. utils.LoggerDebug.Printf("%s check task C2C creating , hangup CPA %s ", task, args[0])
  873. Hangup("1411")
  874. goto DELAY
  875. }
  876. }
  877. } else {
  878. goto DEFAULT
  879. }
  880. return
  881. case "PA":
  882. if task == "CPA" /*|| task == "C2C"*/ {
  883. //获取正在创建的任务的优先级
  884. priorityPA := priority.GetPriorityByKey("PA")
  885. //获取将要创建的任务的优先级
  886. priorityTask := priority.GetPriorityByKey(task)
  887. //比较优先级,确定是否终止正在创建的任务
  888. if priorityPA < priorityTask {
  889. utils.LoggerDebug.Printf("%s check task PA creating , hangup CPA %s ", task, args[0])
  890. //结束task(CPA)
  891. if len(args) > 0 {
  892. Hangup(args[0])
  893. goto DELAY
  894. }
  895. } else {
  896. //结束PA,获取PA通道
  897. if active.ActivedCab == "1" {
  898. utils.LoggerDebug.Printf("%s check task PA creating , hangup PA %s ", task, "2311")
  899. Hangup("2311")
  900. goto DELAY
  901. } else if active.ActivedCab == "8" {
  902. utils.LoggerDebug.Printf("%s check task PA creating , hangup PA %s ", task, "2381")
  903. Hangup("2381")
  904. goto DELAY
  905. }
  906. }
  907. } else {
  908. goto DEFAULT
  909. }
  910. return
  911. }
  912. DEFAULT:
  913. //utils.LoggerDebug.Printf("%s waiting trd=============previous task:%s creating ..... ", task, priority.TaskCreating)
  914. for i := 0; i < 20; i++ {
  915. if priority.TaskCreating != "" {
  916. utils.LoggerDebug.Printf("%s waiting previous task:%s creating ..... ", task, priority.TaskCreating)
  917. time.Sleep(time.Millisecond * 100)
  918. } else {
  919. utils.LoggerDebug.Printf("TaskCreating is nill, Set TaskCreating=%s", task)
  920. priority.TaskCreating = task
  921. return
  922. }
  923. }
  924. priority.TaskCreating = task
  925. utils.LoggerDebug.Printf("%s waiting previous task:%s creating timeout ! Set TaskCreating=%s", task, priority.TaskCreating, task)
  926. DELAY:
  927. time.Sleep(100 * time.Millisecond)
  928. }