起因:有一台设备需要监听某软件的消息,并及时回复,如果只有一个人办公时,难免有走开的情况,如何在不走远的情况下能监听到这个软件的消息,并给我提醒呢。
设计了一个最简单的方案:电脑麦克风监听声音,如果有声音发出,就向微信公众号发出一条消息
环境:Windows 10
语言:Python
应用程序:IEDA
参考文档:
python获取电脑扬声器是否在发出声音_mob649e81597922的技术博客_51CTO博客
【精选】python3 实现公众号自动发消息_python对接微信发订阅消息_XMYX-0的博客-CSDN博客
Python PyInstaller 模块使用详解(将Python程序制作成可直接运行的 EXE 程序)
一.预览
先给大家看看最后的成品:
功能很简单,代码也很简单,可以调整监听的声音阈值,超过阈值就会发消息提醒
二.配置Python环境
第一步:
打开IDEA,安装Python插件
第二步:
新建python项目
这里的Virtualenv就是虚拟环境的意思,这里的python环境与本机安装的是隔离的,方便可以使用不同的python版本和环境,所以第三方的库也需要重新安装
第三步:
安装第三方库:
启动终端,使用pip安装就可以
因为国内网络环境原因,第三方库经常下载超时,需要更换源
python程序中文件顶部有 import 方式导入第三方库,如果缺失,请使用 pip install 先安装
例如安装网络请求库 requests:pip install requests
第四步:
编写程序
右键创建python文件就可以开始编写了。
三.公众号准备
1.获取测试公众号
直接使用测试公众号,进入微信公众平台,微信扫码登录后,就可获取到测试公众号的相关信息和相关的接口文档。
2.关注测试公众号并创建消息模板
使用自己的微信关注测试公众号,可以获取到已关注的微信好的id
编辑消息模板也非常简单,有一点需要注意,模板中需要展示自定义的参数的话,需要以".DATA"结尾:
因为我这里只展示消息的时间,则定义内容是{{time.DATA}}
页面下面有模板消息的文档,可以参考官方样式
我的消息格式是这样的:
lua
{
"touser": touser,
"template_id": self.template_id,
"topcolor": "#FF0000",
"data": {
"time": {
"value": time,
"color": "#173177"
}
}
}
四.微信发送消息程序
微信公众号实现消息发送功能
直接贴代码
python
# encoding: utf-8
import json
import requests
class AccessToken(object):
# 微信公众测试号账号(填写自己的)
APPID = "wx..........."
# 微信公众测试号密钥(填写自己的)
APPSECRET = "2e........"
def __init__(self, app_id=APPID, app_secret=APPSECRET) -> None:
self.app_id = app_id
self.app_secret = app_secret
def get_access_token(self) -> str:
"""
获取access_token凭证
:return: access_token
"""
url = f"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={self.app_id}&secret={self.app_secret}"
resp = requests.get(url)
result = resp.json()
if 'access_token' in result:
return result["access_token"]
else:
print(result)
class SendMessage(object):
# 消息接收者
TROUSER = 'od1.........', 'od1.........'
# 消息模板id
TEMPLATE_ID = '_BG..........'
def __init__(self, touser=TROUSER, template_id=TEMPLATE_ID) -> None:
"""
构造函数
:param touser: 消息接收者
:param template_id: 消息模板id
"""
self.access_token = AccessToken().get_access_token()
self.trouser = touser
self.template_id = template_id
def send_message(self, time) -> None:
"""
发送消息
:param time: 时间
:return:
"""
# 模板消息请求地址
url = f"https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={self.access_token}"
for Recipient in self.trouser:
if Recipient != '':
data = json.dumps(self.get_send_data(time, Recipient))
response = requests.post(url, data=data)
print(response.text)
def get_send_data(self, time, touser) -> object:
"""
获取发送消息data
:param time: 时间
:return: 发送的消息体
"""
return {
"touser": touser,
"template_id": self.template_id,
"topcolor": "#FF0000",
# json数据对应模板
"data": {
"time": {
"value": time,
"color": "#173177"
}
}
}
流程大概就是:初始化的时候,使用appID和appsecret获取获取accessToken;然后使用accessToke和用户的微信号发送消息。
有以下四个地方需要改成自己的内容
注:Python这个类有个__init__方法,这个方法会在对象初始化时候调用。
五.声音监听程序
python
import time
from datetime import datetime
import numpy as np
import pyaudio
from SendMsg import SendMessage
class SoundListener:
def __init__(self):
self.sm = SendMessage()
self.destroy = True
self.display = False
self.max = 500
def startCheck(self):
self.sound_listener()
def isDestroy(self):
return self.destroy
def setAudioMax(self, maxValue):
self.max = maxValue
print("修改阈值:" + str(maxValue))
def sound_listener(self):
self.destroy = False
CHUNK = 1024 # 每个音频块的大小
FORMAT = pyaudio.paInt16 # 音频格式
CHANNELS = 1 # 声道数量
RATE = 44100 # 采样率
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
while True:
if self.destroy:
break
data = np.frombuffer(stream.read(CHUNK), dtype=np.int16)
if np.abs(data).mean() > self.max: # 设置声音阈值
print("声音正在发出!")
# 在这里编写声音发出时需要执行的代码
if not self.display:
self.display = True
# 发送消息
now_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
self.sm.send_message(now_time)
else:
time.sleep(1)
else:
if self.display:
self.display = False
print("声音结束了!")
stream.stop_stream()
stream.close()
p.terminate()
def stop(self):
self.destroy = True
self.display = False
这里使用了Python的三方库pyaudio,打开麦克风录音,并通过录音数据判断是否有声音。
六.创建UI交互
python
import threading
import tkinter as tk
from SoundListener import SoundListener
class CheckAudio:
def __init__(self):
self.sl = SoundListener()
self.root = tk.Tk()
def button_clicked(self):
if not self.sl.isDestroy():
self.root.label.config(text="未监听!")
self.root.button.config(text="开始监听")
threading.Thread(target=self.stopLis).start()
else:
self.root.label.config(text="监听中!")
self.root.button.config(text="结束监听")
threading.Thread(target=self.startLis).start()
def stopLis(self):
self.sl.stop()
def startLis(self):
self.sl.startCheck()
def setAudioMax(self,v):
self.sl.setAudioMax(float(v))
def close_window(self):
self.sl.stop()
self.root.destroy()
def start(self):
# 创建主窗口
root = self.root
root.title("声音监听小程序") # 设置窗口标题
root.geometry("400x300") # 设置窗口大小
self.root.label = tk.Label(root, text="欢迎使用声音监听程序!", font=("Helvetica", 16)) # 创建标签控件
self.root.label.pack(pady=20)
# 创建按钮控件和回调函数
self.root.button = tk.Button(root, text='开始监听', command=self.button_clicked)
self.root.button.pack()
# 添加一个 Scale 控件,默认垂直方向,步长设置为 100,长度为10000,滑动块的大小为 100,最后使用label参数文本
sc = tk.Scale(root, from_=500, to=10000, orient=tk.HORIZONTAL, resolution=100, length=10000, sliderlength=100,
label="音量阈值控制", command=self.setAudioMax)
sc.pack()
#窗口关闭监听回调
root.protocol("WM_DELETE_WINDOW", self.close_window)
root.mainloop()
if __name__ == '__main__':
CheckAudio().start()
这里使用了Python的UI库tkinter;使用threading创建子线程,防止主线程卡死。
写好似乎就可以运行了,点击IDEA顶部的运行按钮试试看
附:打包exe
调试运行可以,但是给别人使用,最好windows下打包成exe文件。
这里使用 PyInstaller
安装PyInstaller :
pip install pyinstaller
终端运行打包代码:
r
pyinstaller -F -w checkAudio.py
生成的exe在以下路径中,也分享给需要的小伙伴使用吧!