FreeSWITCH 1.10.10 简单图形化界面13 - Python-ESL
0、 界面预览
http://myfs.f3322.net:8020/
用户名:admin,密码:admin
FreeSWITCH界面安装参考:https://blog.csdn.net/jia198810/article/details/137820796
1、简介
Python ESL 模块提供了与 FreeSWITCH 之间的本地交互,通过事件套接字接口实现。它允许发送命令、接收输出,并从 FreeSWITCH 服务器发送和接收事件及交互。
2、安装python-esl
当前python版本:
Python 3.10.13 (main, Oct 21 2023, 22:46:22) [GCC 8.5.0 20210514 (Red
Hat 8.5.0-18)] on linux
yum install swig
pip3 install python-ESL
# 2024年4月26日,更新此博客
#直接yum安装swig最新版本后,在安装python-ESL时,可能会出现报错(和swig相关的报错),可以卸载掉swig,安装旧版本的swig。
wget https://jaist.dl.sourceforge.net/project/swig/swig/swig-3.0.12/swig-3.0.12.tar.gz
tar zxvf swig-3.0.12.tar.gz
./configure
make
make install
# 再次安装python-ESL
pip3 install python-ESL
安装后,当前ESL版本:
root@localhost ~# /usr/local/python310/bin/pip3 list |grep ESL
python-ESL 1.4.18
3、简单使用
# test.py
# 导入esl
import ESL
# 连接mod_event_socket
con = ESL.ESLconnection("127.0.0.1", "8021", "ClueCon")
# 接收事件
con.recvEvent()
# 执行fs api
con.api("status")
# 执行拨号应用
con.execute("anster")
详细方法和属性可参考此链接
4、示例
使用python-ESL 连接mod_event_socket,获取分机注册、通话、离线及会议状态并推送到mqtt。
#!/usr/local/python310/bin/python
import threading
import queue
import multiprocessing
import requests
import logging
from pathlib import Path
import re
import ESL
import json
import atexit
import os
from mqtt import mqtt_client,phone_status_topic,conference_status_topic,all_status_topic
from time import sleep
# 日志开始
log_file = Path(Path(__file__).parent.parent.as_posix(), "log/events.log").as_posix()
print(log_file)
logger = logging.getLogger(__name__)
logger.setLevel(level=logging.INFO)
header = logging.FileHandler(log_file)
header.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
header.setFormatter(formatter)
logger.addHandler(header)
# 日志结束
# 连接fscli
esl_con = ESL.ESLconnection('127.0.0.1', '8021', 'fs8021')
esl_con_connected = False
# process 事件控制
process_event = threading.Event()
# PID文件
pidfile = Path("/var/run/fsevent.pid")
# 消息队列
event_queue = queue.Queue()
# 通道存储,存储多路通话状态,一路结束,恢复到上一个状态,并不会真正的删除通话
channel_list = []
# 添加通道
def add_channel(uuid,caller_number,callee_number):
channels = [channel for channel in channel_list if channel["uuid"] == uuid]
if not channels:
channel_list.append(dict(uuid=uuid,caller_number=caller_number,callee_number=callee_number))
print("当前通道数量:",channel_list)
# 删除通道
def del_channel(uuid):
print("删除uuid:",uuid)
for channel in channel_list:
if (channel["uuid"] == uuid):
channel_list.remove(channel)
print("删除后的通道列表:",channel_list)
# 删除所有通道
def del_all_channels():
for channel in channel_list:
channel_list.remove(channel)
# 获取通道
def get_channel_by_caller_number(number):
channels = [channel for channel in channel_list if channel["caller_number"] == number]
return channels[0] if channels else None
def get_channel_by_callee_number(number):
channels = [channel for channel in channel_list if channel["callee_number"] == number]
return channels[0] if channels else None
# 为分机状态获取主叫号码
def get_phone_status_caller_number(e):
caller_number=None
# 第一次获取主叫
if e.getHeader("Caller-ANI"):
result = re.search(r'(\d+)',e.getHeader("Caller-ANI"))
if result:
caller_number = result.group(1)
# 第二次获取主叫
if not caller_number and e.getHeader("Caller-Caller-ID-Number"):
result = re.search(r'(\d+)',e.getHeader("Caller-Caller-ID-Number"))
if result:
caller_number = result.group(1)
if not caller_number:
del_all_channels()
print("分机状态:主叫号码获取异常Caller-ANI Caller-Caller-ID-Number,数据:",e.serialize("json"))
return caller_number
# 为分机状态获取被叫号码
def get_phone_status_callee_number(e):
callee_number= None
# 第一次获取被叫
if e.getHeader("Caller-Destination-Number"):
result = re.search(r'(\d+)',e.getHeader("Caller-Destination-Number"))
if result:
callee_number = result.group(1)
# 第二次获取被叫
if not callee_number and e.getHeader("Caller-Callee-ID-Number"):
result = re.search(r'(\d+)',e.getHeader("Caller-Callee-ID-Number"))
if result:
callee_number = result.group(1)
if not callee_number :
del_all_channels()
print("分机状态:被叫号码获取异常Caller-Destination-Number Caller-Callee-ID-Number,数据:",e.serialize("json"))
return callee_number
# 为会议状态获取主叫号码
def get_conference_status_caller_number(e):
caller_number = None
if e.getHeader("Caller-ANI"):
result = re.search(r'(\d+)$',e.getHeader("Caller-ANI"))
if result:
caller_number = result.group(1)
if not caller_number:
del_all_channels()
print("会议状态:主叫号码获取异常Caller-ANI,数据:",e.serialize("json"))
return caller_number
# 为会议状态获取被叫号码
def get_conference_status_callee_number(e):
callee_number = None
if e.getHeader("Caller-RDNIS"):
result = re.search(r'(\d+)$', e.getHeader("Caller-RDNIS"))
if result:
callee_number = result.group(1)
if not callee_number :
del_all_channels()
print("会议状态:被叫号码获取异常Caller-RDNIS,数据:",e.serialize("json"))
return callee_number
def handle_event(e):
#print(e.serialize("json"))
name = e.getHeader("Event-Name")
subclass = e.getHeader("Event-Subclass")
datetime=e.getHeader("Event-Date-Local")
seq=e.getHeader("Event-Sequence")
# 分机状态初默认值
phone_status_dict = dict(type="phone_status",datetime=datetime,seq=seq)
# 会议室状态默认值
conference_status_dict = dict(type="conference_status",datetime=datetime,seq=seq)
# 分机注销
if subclass == "sofia::unregister":
phone_status_dict.update(
number=e.getHeader("username").split('-')[0] if e.getHeader("username") else e.getHeader("from-user").split('-')[0],
status=0,
description="离线"
)
event_queue.put(phone_status_dict)
# 分机注册
elif subclass == "sofia::register":
number=e.getHeader("username").split('-')[0]
phone_status_dict.update(
number=number,
status=1,
description="空闲"
)
# 如果分机即没有呼叫,也没有被呼叫,则发布状态
if not get_channel_by_caller_number(number) and not get_channel_by_callee_number(number):
event_queue.put(phone_status_dict)
# 分机振铃
elif name == "CHANNEL_PROGRESS":
#print(e.serialize("json"))
caller_number = get_phone_status_caller_number(e)
callee_number = get_phone_status_callee_number(e)
uuid = e.getHeader("Channel-Call-UUID")
add_channel(uuid,caller_number,callee_number)
if e.getHeader("Call-Direction") == "outbound":
# 主叫分机状态
phone_status_dict.update(
number=caller_number,
direction="OUTBOUND",
caller_number=caller_number,
callee_number=callee_number,
status=10,
description=f"正在呼叫{callee_number}"
)
event_queue.put(phone_status_dict)
elif e.getHeader("Call-Direction") == "inbound":
# 被叫分机状态
phone_status_dict.update(
number=callee_number,
direction="INBOUND",
caller_number=caller_number,
callee_number=callee_number,
status=11,
description=f"等待接听{caller_number}的来电"
)
event_queue.put(phone_status_dict)
# 分机应答
elif name == "CHANNEL_ANSWER":
#print(e.serialize("json"))
caller_number = get_phone_status_caller_number(e)
callee_number = get_phone_status_callee_number(e)
# 有的分机没有PROCESS,同样需要加到通道存储中
uuid = e.getHeader("Channel-Call-UUID")
add_channel(uuid,caller_number,callee_number)
if e.getHeader("Call-Direction") == "outbound":
# 主叫分机状态
phone_status_dict.update(
number=caller_number,
direction="OUTBOUND",
caller_number=caller_number,
callee_number=callee_number,
status=20,description=f"和{callee_number}通话中"
)
event_queue.put(phone_status_dict)
elif e.getHeader("Call-Direction") == "inbound":
# 被叫分机状态
phone_status_dict.update(
number=callee_number,
direction="INBOUND",
caller_number=caller_number,
callee_number=callee_number,
status=21,
description=f"和{caller_number}通话中"
)
event_queue.put(phone_status_dict)
# # 分机挂断
elif name == "CHANNEL_HANGUP_COMPLETE" :
caller_number = get_phone_status_caller_number(e)
callee_number = get_phone_status_callee_number(e)
uuid = e.getHeader("Channel-Call-UUID")
# 先删除本次的uuid,如果还有通话则恢复状态
del_channel(uuid)
if e.getHeader("Call-Direction") == "outbound":
# 主叫分机状态
phone_status_dict.update(
number=caller_number,
status=1,
description="空闲"
)
event_queue.put(phone_status_dict)
# 主叫挂机后,如果还有通话,则恢复到上一次的通话状态
other_channel = get_channel_by_caller_number(caller_number)
print(f"OUT剩余通道中主叫是{caller_number}的通道",other_channel)
if other_channel:
# 主叫分机状态
phone_status_dict.update(
number=caller_number,
direction="OUTBOUND",
caller_number=caller_number,
callee_number=other_channel["callee_number"],
status=20,description=f"和{other_channel['callee_number']}通话中"
)
event_queue.put(phone_status_dict)
other_channel = get_channel_by_callee_number(caller_number)
print(f"OUT剩余通道中被叫是{caller_number}的通道",other_channel)
if other_channel:
# 主叫分机状态
phone_status_dict.update(
number=caller_number,
direction="OUTBOUND",
caller_number=caller_number,
callee_number=other_channel["callee_number"],
status=20,description=f"和{other_channel['callee_number']}通话中"
)
event_queue.put(phone_status_dict)
elif e.getHeader("Call-Direction") == "inbound":
# 被叫分机状态
# 如果呼叫ivr,可能获取不到号码
# print(e.serialize("json"))
phone_status_dict.update(
number=callee_number,
status=1,
description="空闲"
)
event_queue.put(phone_status_dict)
# 被叫挂机后,如果还有通话,则恢复到上一次的通话状态
other_channel = get_channel_by_caller_number(callee_number)
print(f"IN剩余通道中主叫是{callee_number}的通道",other_channel)
if other_channel:
# 主叫分机状态
phone_status_dict.update(
number=callee_number,
direction="OUTBOUND",
caller_number=callee_number,
callee_number=other_channel["callee_number"],
status=20,description=f"和{other_channel['callee_number']}通话中"
)
event_queue.put(phone_status_dict)
other_channel = get_channel_by_callee_number(callee_number)
print(f"IN剩余通道中被叫是{callee_number}的通道",other_channel)
if other_channel:
# 主叫分机状态
phone_status_dict.update(
number=callee_number,
direction="INBOUND",
caller_number=other_channel["caller_number"],
callee_number=callee_number,
status=20,description=f"和{other_channel['caller_number']}通话中"
)
event_queue.put(phone_status_dict)
# 分机状态结束
# 会议开始
elif subclass == "conference::maintenance":
#print(e.serialize("json"))
action = e.getHeader("Action")
number=e.getHeader("Conference-Name")
count=int(e.getHeader("Conference-Size"))
conference_status_dict.update(number=number,count=count,action=action)
# 开始会议
if action == "conference-create":
conference_status_dict.update(
status=1,
description="会议室开始"
)
event_queue.put(conference_status_dict)
# 结束会议
elif action == "conference-destroy":
# 如果还有通话继续删除
uuid = e.getHeader("Channel-Call-UUID")
del_channel(uuid)
conference_status_dict.update(
status=0,
description="会议室结束"
)
event_queue.put(conference_status_dict)
# 布局改变
elif action == "floor-change" or action == "video-floor-change":
conference_status_dict.update(
old_id=None if e.getHeader("Old-ID") == "none" else int(e.getHeader("Old-ID")),
new_id=None if e.getHeader("New-ID") == "none" else int(e.getHeader("New-ID")),
description="会议室改变布局"
)
event_queue.put(conference_status_dict)
# 添加成员
elif action == "add-member":
caller_number = get_conference_status_caller_number(e)
callee_number = get_conference_status_callee_number(e)
print(f"会议号码{caller_number},成员号码是:{callee_number}")
state = e.getHeader("Answer-State")
if state == "answered" or state == "early":
conference_status_dict.update(
member_number=callee_number,
member_status=dict(
member_id = int(e.getHeader("Member-ID")),
member_type = e.getHeader("Member-Type"),
video = True if e.getHeader("Video") == "true" else False,
hear = True if e.getHeader("Hear") == "true" else False,
see = True if e.getHeader("See") == "true" else False,
speak = True if e.getHeader("Speak") == "true" else False,
talking = True if e.getHeader("Talking") == "true" else False,
mute = True if e.getHeader("Mute-Detect") == "true" else False,
),
description="会议室增加成员"
)
event_queue.put(conference_status_dict)
phone_status_dict.update(
number=callee_number,
direction="INBOUND",
caller_number=caller_number,
callee_number=callee_number,
status=3,
description=f"在会议室{caller_number}中"
)
event_queue.put(phone_status_dict)
# 禁止发言
elif action == "mute-member":
caller_number = get_conference_status_caller_number(e)
callee_number = get_conference_status_callee_number(e)
state = e.getHeader("Answer-State")
if state == "answered":
conference_status_dict.update(
member_number=callee_number,
member_status=dict(
member_id = int(e.getHeader("Member-ID")),
member_type = e.getHeader("Member-Type"),
video = True if e.getHeader("Video") == "true" else False,
hear = True if e.getHeader("Hear") == "true" else False,
see = True if e.getHeader("See") == "true" else False,
speak = True if e.getHeader("Speak") == "true" else False,
talking = True if e.getHeader("Talking") == "true" else False,
mute = True if e.getHeader("Mute-Detect") == "true" else False,
),
description="会议室成员禁止发言"
)
event_queue.put(conference_status_dict)
# 允许发言
elif action == "unmute-member":
caller_number = get_conference_status_caller_number(e)
callee_number = get_conference_status_callee_number(e)
state = e.getHeader("Answer-State")
if state == "answered":
conference_status_dict.update(
member_number=callee_number,
member_status=dict(
member_id = int(e.getHeader("Member-ID")),
member_type = e.getHeader("Member-Type"),
video = True if e.getHeader("Video") == "true" else False,
hear = True if e.getHeader("Hear") == "true" else False,
see = True if e.getHeader("See") == "true" else False,
speak = True if e.getHeader("Speak") == "true" else False,
talking = True if e.getHeader("Talking") == "true" else False,
mute = True if e.getHeader("Mute-Detect") == "true" else False,
),
description="会议室成员允许发言"
),
event_queue.put(conference_status_dict)
# 关闭视频
elif action == "vmute-member":
caller_number = get_conference_status_caller_number(e)
callee_number = get_conference_status_callee_number(e)
state = e.getHeader("Answer-State")
if state == "answered":
conference_status_dict.update(
member_number=callee_number,
member_status=dict(
member_id = int(e.getHeader("Member-ID")),
member_type = e.getHeader("Member-Type"),
video = True if e.getHeader("Video") == "true" else False,
hear = True if e.getHeader("Hear") == "true" else False,
see = True if e.getHeader("See") == "true" else False,
speak = True if e.getHeader("Speak") == "true" else False,
talking = True if e.getHeader("Talking") == "true" else False,
mute = True if e.getHeader("Mute-Detect") == "true" else False,
),
description="会议室成员关闭视频"
)
event_queue.put(conference_status_dict)
# 开启视频
elif action == "unvmute-member":
caller_number = get_conference_status_caller_number(e)
callee_number = get_conference_status_callee_number(e)
state = e.getHeader("Answer-State")
if state == "answered":
conference_status_dict.update(
member_number=callee_number,
member_status=dict(
member_id = int(e.getHeader("Member-ID")),
member_type = e.getHeader("Member-Type"),
video = True if e.getHeader("Video") == "true" else False,
hear = True if e.getHeader("Hear") == "true" else False,
see = True if e.getHeader("See") == "true" else False,
speak = True if e.getHeader("Speak") == "true" else False,
talking = True if e.getHeader("Talking") == "true" else False,
mute = True if e.getHeader("Mute-Detect") == "true" else False,
),
description="会议室成员开启视频"
),
event_queue.put(conference_status_dict)
# 开启禁音
elif action == "deaf-member":
caller_number = get_conference_status_caller_number(e)
callee_number = get_conference_status_callee_number(e)
state = e.getHeader("Answer-State")
if state == "answered":
conference_status_dict.update(
member_number=callee_number,
member_status=dict(
member_id = int(e.getHeader("Member-ID")),
member_type = e.getHeader("Member-Type"),
video = True if e.getHeader("Video") == "true" else False,
hear = True if e.getHeader("Hear") == "true" else False,
see = True if e.getHeader("See") == "true" else False,
speak = True if e.getHeader("Speak") == "true" else False,
talking = True if e.getHeader("Talking") == "true" else False,
mute = True if e.getHeader("Mute-Detect") == "true" else False,
),
description="会议室成员开启禁音"
)
event_queue.put(conference_status_dict)
# 关闭禁音
elif action == "undeaf-member":
caller_number = get_conference_status_caller_number(e)
callee_number = get_conference_status_callee_number(e)
state = e.getHeader("Answer-State")
if state == "answered":
conference_status_dict.update(
member_number=callee_number,
member_status=dict(
member_id = int(e.getHeader("Member-ID")),
member_type = e.getHeader("Member-Type"),
video = True if e.getHeader("Video") == "true" else False,
hear = True if e.getHeader("Hear") == "true" else False,
see = True if e.getHeader("See") == "true" else False,
speak = True if e.getHeader("Speak") == "true" else False,
talking = True if e.getHeader("Talking") == "true" else False,
mute = True if e.getHeader("Mute-Detect") == "true" else False,
),
description="会议室成员关闭禁音"
),
event_queue.put(conference_status_dict)
# 踢出成员
elif action == "kick-member":
caller_number = get_conference_status_caller_number(e)
callee_number = get_conference_status_callee_number(e)
state = e.getHeader("Answer-State")
if state == "answered":
conference_status_dict.update(
member_number=callee_number,
member_status=dict(
member_id = int(e.getHeader("Member-ID")),
member_type = e.getHeader("Member-Type"),
video = True if e.getHeader("Video") == "true" else False,
hear = True if e.getHeader("Hear") == "true" else False,
see = True if e.getHeader("See") == "true" else False,
speak = True if e.getHeader("Speak") == "true" else False,
talking = True if e.getHeader("Talking") == "true" else False,
mute = True if e.getHeader("Mute-Detect") == "true" else False,
),
description="会议室踢出成员"
)
event_queue.put(conference_status_dict)
# 删除成员
elif action == "del-member":
caller_number = get_conference_status_caller_number(e)
callee_number = get_conference_status_callee_number(e)
conference_status_dict.update(
member_number=callee_number,
member_status=dict(
member_id = int(e.getHeader("Member-ID")),
member_type = e.getHeader("Member-Type"),
video = True if e.getHeader("Video") == "true" else False,
hear = True if e.getHeader("Hear") == "true" else False,
see = True if e.getHeader("See") == "true" else False,
speak = True if e.getHeader("Speak") == "true" else False,
talking = True if e.getHeader("Talking") == "true" else False,
mute = True if e.getHeader("Mute-Detect") == "true" else False,
),
description="会议室删除成员"
)
event_queue.put(conference_status_dict)
phone_status_dict.update(
number=callee_number,
direction="INBOUND",
caller_number=caller_number,
callee_number=callee_number,
status=1,
description=f"空闲"
)
event_queue.put(phone_status_dict)
# 挂断成员
elif action == "hup-member":
caller_number = get_conference_status_caller_number(e)
callee_number = get_conference_status_callee_number(e)
state = e.getHeader("Answer-State")
if state == "answered":
conference_status_dict.update(
member_number=callee_number,
member_status=dict(
member_id = int(e.getHeader("Member-ID")),
member_type = e.getHeader("Member-Type"),
video = True if e.getHeader("Video") == "true" else False,
hear = True if e.getHeader("Hear") == "true" else False,
see = True if e.getHeader("See") == "true" else False,
speak = True if e.getHeader("Speak") == "true" else False,
talking = True if e.getHeader("Talking") == "true" else False,
mute = True if e.getHeader("Mute-Detect") == "true" else False,
),
description="会议室挂断成员"
)
event_queue.put(conference_status_dict)
# 邀请成员
elif action == "bgdial-result":
state = e.getHeader("Answer-State")
conference_status_dict.update(
result=e.getHeader("Result"),
description="会议室邀请成员结果",
)
event_queue.put(conference_status_dict)
# 正在发言就会触发此事件
elif action == "start-talking":
caller_number = get_conference_status_caller_number(e)
callee_number = get_conference_status_callee_number(e)
state = e.getHeader("Answer-State")
if state == "answered":
conference_status_dict.update(
member_number=callee_number,
member_status=dict(
member_id = int(e.getHeader("Member-ID")),
member_type = e.getHeader("Member-Type"),
video = True if e.getHeader("Video") == "true" else False,
hear = True if e.getHeader("Hear") == "true" else False,
see = True if e.getHeader("See") == "true" else False,
speak = True if e.getHeader("Speak") == "true" else False,
talking = True if e.getHeader("Talking") == "true" else False,
mute = True if e.getHeader("Mute-Detect") == "true" else False,
),
description="会议室成员正在发言"
)
event_queue.put(conference_status_dict)
# 发言完毕后触发
elif action == "stop-talking":
caller_number = get_conference_status_caller_number(e)
callee_number = get_conference_status_callee_number(e)
state = e.getHeader("Answer-State")
if state == "answered":
conference_status_dict.update(
member_number=callee_number,
member_status=dict(
member_id = int(e.getHeader("Member-ID")),
member_type = e.getHeader("Member-Type"),
video = True if e.getHeader("Video") == "true" else False,
hear = True if e.getHeader("Hear") == "true" else False,
see = True if e.getHeader("See") == "true" else False,
speak = True if e.getHeader("Speak") == "true" else False,
talking = True if e.getHeader("Talking") == "true" else False,
mute = True if e.getHeader("Mute-Detect") == "true" else False,
),
description="会议室成员发言完毕"
)
event_queue.put(conference_status_dict)
# 开始录音/录像
# start-recording
elif action == "start-recording":
conference_status_dict.update(
path=e.getHeader("Path"),
error=e.getHeader("Error"),
description="会议室开始录音/录像"
)
event_queue.put(conference_status_dict)
# 暂停录音/录像
elif action == "pause-recording":
conference_status_dict.update(
path=e.getHeader("Path"),
description="会议室暂停录音/录像"
)
event_queue.put(conference_status_dict)
# 暂停录音/录像
elif action == "resume-recording":
conference_status_dict.update(
path=e.getHeader("Path"),
description="会议室恢复录音/录像"
)
event_queue.put(conference_status_dict)
# 结束录音/录像
elif action == "stop-recording":
conference_status_dict.update(
path=e.getHeader("Path"),
description="会议室结束录音/录像"
)
event_queue.put(conference_status_dict)
# 锁定会议室
elif action == "lock":
conference_status_dict.update(
description="会议室锁定"
)
event_queue.put(conference_status_dict)
# 解锁定会议室
elif action == "unlock":
conference_status_dict.update(
description="会议室解锁"
)
event_queue.put(conference_status_dict)
# 播放文件
elif action == "play-file":
conference_status_dict.update(
file=e.getHeader("File"),
sync = True if e.getHeader("Async") == "true" else False,
description="会议室播放文件开始"
)
event_queue.put(conference_status_dict)
# 结束文件
elif action == "play-file-done":
conference_status_dict.update(
file=e.getHeader("File"),
description="会议室播放文件完毕"
)
event_queue.put(conference_status_dict)
# 会议状态结束
# 提交状态到其他目的
def status_to_post(status_data):
url = "https://example.com/submit-status"
# 替换为您要提交状态的目标URL
print("POST提交到URL:",status_data)
try:
response = requests.post(url, json=status_data,timeout=10)
if response.status_code == 200:
print("提交成功")
else:
print("提交失败:", response.status_code)
except requests.exceptions.RequestException as e:
print("其他错误",e)
pass
# 推送事件到mqtt
def status_to_mqtt(status_data):
print("推送到MQTT:",status_data)
logger.info(status_data)
payload=json.dumps(status_data)
# 推送分机状态
if status_data["type"] == "phone_status":
mqtt_client.publish(topic=phone_status_topic,payload=payload,qos=2)
# 推送会议状态
elif status_data["type"] == "conference_status":
mqtt_client.publish(topic=conference_status_topic,payload=payload,qos=2)
# 推送所有状态
mqtt_client.publish(topic=all_status_topic,payload=payload,qos=2)
# 接收freeswitch事件
def recv_event():
global esl_con,esl_con_connected, process_event
while True:
while process_event.wait():
esl_con.events('json', 'all')
event = esl_con.recvEvent()
if event.getHeader("Event-Name") == "SERVER_DISCONNECTED":
print("FreeSWITCH已断开,停止发送和接收")
process_event.clear()
if event:
handle_event(event)
sleep(5)
# 发送freeswitch事件
def send_event():
while True:
print("发送",process_event.is_set())
while process_event.wait():
event_data = event_queue.get()
status_to_mqtt(event_data)
#status_to_post(event_data)
event_queue.task_done()
sleep(5)
# 连接FreeSWITCH ESL
def connect_esl():
global esl_con,esl_con_connected, process_event
while True:
if esl_con.connected():
process_event.set()
print("心跳:FreeSWITCH ESL连接中,正在发送和接收")
sleep(10)
else:
print("连接FreeSWITCH ESL失败,停止发送和接收")
print("连接FreeSWITCH ESL失败,重新连接中")
process_event.clear()
esl_con = ESL.ESLconnection('127.0.0.1', '8021', 'fs8021')
if esl_con.connected():
print("连接FreeSWITCH ESL成功")
print("连接FreeSWITCH ESL成功,开始发送和接收")
process_event.set()
sleep(30)
# 主进程
def main():
# 创建连接ESL的进程
connect_process = threading.Thread(target=connect_esl)
connect_process.start()
# 创建接收freeswitch事件的进程
recv_process = threading.Thread(target=recv_event)
recv_process.start()
# 创建发送freeswitch事件的进程
send_process = threading.Thread(target=send_event)
send_process.start()
# 结束进程时处理
atexit.register(on_exit)
# 创建PID文件
pid = str(os.getpid())
pidfile.write_text(pid)
print("mqtt开始循环")
mqtt_client.loop_forever()
# 清理相关线程
def on_exit():
# 结束mqtt
mqtt_client.disconnect()
# 删除PID
if pidfile.exists():
pidfile.unlink()
if __name__ == "__main__":
main()