语言控制风扇开关

import threading

import websocket

import hashlib

import base64

import hmac

import json

from urllib.parse import urlencode

import time

# 该模块为客户端和服务器端的网络套接字提供对传输层安全性(通常称为“安全套接字层”)

# 的加密和对等身份验证功能的访问。

import ssl

from wsgiref.handlers import format_date_time

from datetime import datetime

from time import mktime

import _thread as thread

import pyaudio

from modbus_tk import modbus_rtu

import serial

from modbus_tk.defines import READ_INPUT_REGISTERS, READ_HOLDING_REGISTERS, WRITE_SINGLE_COIL

import re, string

from zhon.hanzi import punctuation


 

def ConnectRelay(PORT):

    try:

        # 创建串口对象

        ser = serial.Serial(port=PORT, baudrate=9600, bytesize=8, parity='E', stopbits=serial.STOPBITS_ONE)

        # 创建 Modbus RTU 主站对象

        master = modbus_rtu.RtuMaster(ser)

        master.set_timeout(5.0)  # 设置超时时间

        master.set_verbose(True)  # 设置详细输出

        # 尝试读取输入寄存器来验证连接

        master.execute(2, READ_INPUT_REGISTERS, 0, 2)

        # 您可能想要在这里添加一些错误处理,来检查读取操作是否成功

        # 返回连接成功的标志和主站对象

        return 1, master

    #链接失败

    except Exception as e:

        print(f"Connection failed: {e}")

        return -1, None

#对继电器设置语音控制

def Switch(master, ACTION):

    if master is None:

        return -1  # 如果主站对象无效,则直接返回失败

    try:

        if "开风扇" in ACTION.lower():

            # 继电器闭合,输出值设为1

            master.execute(2, WRITE_SINGLE_COIL, 0, output_value=1)

        elif "关风扇" in ACTION.lower():

            # 继电器断开,输出值设为0

            master.execute(2, WRITE_SINGLE_COIL, 0, output_value=0)

        else:

            print("Invalid action. Use '开风扇' or '关风扇'.")

            return -1

        return 1  # 操作成功

    except Exception as e:

        print(f"Switch operation failed: {e}")

        return -1  # 操作失败


 

STATUS_FIRST_FRAME = 0  # 第一帧的标识

STATUS_CONTINUE_FRAME = 1  # 中间帧标识

STATUS_LAST_FRAME = 2  # 最后一帧的标识


 

class Ws_Param(object):

    # 初始化一些公共参数,以便后续使用

    def __init__(self, APPID, APIKey, APISecret):

        self.APPID = '32b83bae'

        self.APIKey = 'f07840bbdd48079b30c8f41a23b01dbb'

        self.APISecret = 'M2I2N2NiMDc2YzQyYWZjNWI2ZDk5MGRk'

        # 公共参数(common)

        self.CommonArgs = {"app_id": self.APPID}

        # 业务参数(business),更多个性化参数可在官网查看

        self.BusinessArgs = {"domain": "iat", "language": "zh_cn", "accent": "mandarin", "vinfo": 1, "vad_eos": 10000}

    # 生成url

    def create_url(self):

        url = 'wss://ws-api.xfyun.cn/v2/iat'

        # 生成RFC1123格式的时间戳

        now = datetime.now()

        date = format_date_time(mktime(now.timetuple()))

        # 拼接字符串

        signature_origin = "host: " + "ws-api.xfyun.cn" + "\n"

        signature_origin += "date: " + date + "\n"

        signature_origin += "GET " + "/v2/iat " + "HTTP/1.1"

        # 进行hmac-sha256进行加密

        signature_sha = hmac.new(self.APISecret.encode('utf-8'), signature_origin.encode('utf-8'),

                                 digestmod=hashlib.sha256).digest()

        signature_sha = base64.b64encode(signature_sha).decode(encoding='utf-8')

        authorization_origin = "api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"" % (

            self.APIKey, "hmac-sha256", "host date request-line", signature_sha)

        authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')

        # 将请求的鉴权参数组合为字典

        v = {

            "authorization": authorization,

            "date": date,

            "host": "ws-api.xfyun.cn"

        }

        # 拼接鉴权参数,生成url

        url = url + '?' + urlencode(v)

        # print("date: ",date)

        # print("v: ",v)

        # 此处打印出建立连接时候的url,参考本demo的时候可取消上方打印的注释,比对相同参数时生成的url与自己代码生成的url是否一致

        # print('websocket url :', url)

        return url


 

# 收到websocket消息的处理

def on_message(ws, message):

    try:

        code = json.loads(message)["code"]#从message中解析出code并转为python对象

        sid = json.loads(message)["sid"]

        if code != 0:

            errMsg = json.loads(message)["message"]

            print("sid:%s call error:%s code is:%s" % (sid, errMsg, code))

        else:

            data = json.loads(message)["data"]["result"]["ws"]#从message中解析出data并转为python对象,这里就是语音识别的结果了

            result = ""

            for i in data:

                for w in i["cw"]:#cw是i中的一个键,对应的值是一个列表,其中每个元素都包含一个键为w的字典,这个字典的值就是一个识别出来的词语。

                    result += w["w"]

            #例如,如果data包含两个元素,每个元素的"cw"值分别为[{"w": "开"}]和[{"w": "风"}, {"w": "扇"}],

            #那么经过遍历和拼接后,result的值将变为"开风扇",这就是最终的识别结果。

            if result == '。' or result == '.。' or result == ' .。' or result == ' 。':

                pass

            else:

                # t.insert(END, result)  # 把上边的标点插入到result的最后

                print("翻译结果: %s。" % (result))

                status, master = ConnectRelay('COM6')#调用ConnectRelay函数,连接到串口设备COM5,并将返回的状态和主设备对象分别赋给status和master

                #调用Switch函数,传递主设备对象和经过正则表达式处理的识别结果,将返回的开关状态赋给switch_status

                switch_status = Switch(master, re.sub(r"[%s]+" % punctuation, "", result))



 

    except Exception as e:

        print("receive msg,but parse exception:", e)


 

# 收到websocket错误的处理

def on_error(ws, error):

    print("### error:", error)

    run()


 

# 收到websocket关闭的处理

def on_close(ws):

    pass


 

# 收到websocket连接建立的处理

def on_open(ws):

    def run(*args):

        status = STATUS_FIRST_FRAME  # 音频的状态信息,标识音频是第一帧,还是中间帧、最后一帧

        CHUNK = 520  # 定义数据流块

        FORMAT = pyaudio.paInt16  # 16bit编码格式

        CHANNELS = 1  # 单声道

        RATE = 16000  # 16000采样频率

        # 实例化pyaudio对象

        p = pyaudio.PyAudio()  # 录音

        # 创建音频流

        # 使用这个对象去打开声卡,设置采样深度、通道数、采样率、输入和采样点缓存数量

        stream = p.open(format=FORMAT,  # 音频流wav格式

                        channels=CHANNELS,  # 单声道

                        rate=RATE,  # 采样率16000

                        input=True,#打开音频输入流

                        frames_per_buffer=CHUNK)#定义每个数据块的大小,CHUNK的值为520,表示每个数据块包含520个采样点。

        print("- - - - - - - Start Recording ...- - - - - - - ")

        # 添加开始表示 ——start recording——

        #使用WebSocket将从麦克风获取的音频数据发送到语音识别API,并将API返回的识别结果发送回来

        global text

        tip = "——start recording——"

        #循环60秒,每次循环读取CHUNK大小的音频数据,并将其发送到语音识别API进行处理

        for i in range(0, int(RATE / CHUNK * 60)):

            # # 读出声卡缓冲区的音频数据

            buf = stream.read(CHUNK)

            #如果音频数据为空,则将状态设置为最后一帧。

            if not buf:

                status = STATUS_LAST_FRAME

            #如果当前是第一帧,则将音频数据打包成JSON格式,并发送到语音识别API。打包时需要提供一些参数,如common、business和data。

            #其中,common和business参数是API的公共参数和业务参数,data参数包含音频数据的格式、状态和编码方式等信息

            if status == STATUS_FIRST_FRAME:

                d = {"common": wsParam.CommonArgs,

                     "business": wsParam.BusinessArgs,

                     "data": {"status": 0, "format": "audio/L16;rate=16000",

                              "audio": str(base64.b64encode(buf), 'utf-8'),

                              "encoding": "raw"}}

                d = json.dumps(d)

                ws.send(d)

                status = STATUS_CONTINUE_FRAME

                # 中间帧处理

                #如果当前是中间帧,则将音频数据打包成JSON格式,并发送到语音识别API。与第一帧不同的是,中间帧不需要提供common和business参数

            elif status == STATUS_CONTINUE_FRAME:

                d = {"data": {"status": 1, "format": "audio/L16;rate=16000",

                              "audio": str(base64.b64encode(buf), 'utf-8'),

                              "encoding": "raw"}}

                ws.send(json.dumps(d))

            # 最后一帧处理

            #如果当前是最后一帧,则将音频数据打包成JSON格式,并发送到语音识别API。

            #与中间帧不同的是,最后一帧需要将status参数设置为2,并在发送完最后一帧后等待1秒钟,以确保API有足够的时间进行识别

            elif status == STATUS_LAST_FRAME:

                d = {"data": {"status": 2, "format": "audio/L16;rate=16000",

                              "audio": str(base64.b64encode(buf), 'utf-8'),

                              "encoding": "raw"}}

                ws.send(json.dumps(d))

                time.sleep(1)

                break

    #启动一个新线程,运行run函数,该函数用于从麦克风获取音频数据并发送到语音识别API,同时接收API返回的识别结果

    thread.start_new_thread(run, ())


 

def run():

    global wsParam

    # 讯飞接口编码

    wsParam = Ws_Param(APPID='6fb193a0',

                       APIKey='OTdlYmRjMzZiNWQwZjY1NmM1MWVkOTZi',

                       APISecret='3cd748062e105eb13441f5afb0ec5d65')

    #禁用websocket的调试信息输出

    websocket.enableTrace(False)

    #根据wsParam参数生成websocket连接的URL

    wsUrl = wsParam.create_url()

    #创建一个websocket应用程序实例,并指定连接的URL、收到消息时的回调函数on_message、出错时的回调函数on_error和关闭连接时的回调函数on_close

    ws = websocket.WebSocketApp(wsUrl, on_message=on_message, on_error=on_error, on_close=on_close)

    #将连接成功时的回调函数on_open绑定到websocket实例的on_open属性上

    ws.on_open = on_open

    #启动websocket连接,使用run_forever方法保持连接,sslopt参数用于指定SSL选项,

    #这里将cert_reqs设置为ssl.CERT_NONE,表示不验证服务器证书;ping_timeout参数用于指定心跳超时时间,这里设置为2秒

    ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE}, ping_timeout=2)


 

def runc():

    run()

#用于控制一个线程的暂停、恢复和停止操作

class Job(threading.Thread):

    def __init__(self, *args, **kwargs):

        super(Job, self).__init__(*args, **kwargs)

        self.__flag = threading.Event()  # 用于暂停线程的标识

        self.__flag.set()  # 设置为True

        self.__running = threading.Event()  # 用于停止线程的标识

        self.__running.set()  # 将running设置为True

    #定义了线程执行的run方法

    def run(self):

        while self.__running.isSet():

            self.__flag.wait()  # 为True时立即返回, 为False时阻塞直到内部的标识位为True后返回

            runc()

            time.sleep(1)

    #定义了暂停线程的方法pause()

    def pause(self):

        self.__flag.clear()  # 设置为False, 让线程阻塞

    #定义了恢复线程的方法resume()

    def resume(self):

        self.__flag.set()  # 设置为True, 让线程停止阻塞

    #定义了停止线程的方法stop()

    def stop(self):

        self.__flag.set()  # 将线程从暂停状态恢复, 如何已经暂停的话

        self.__running.clear()  # 设置为False

#创建一个Job对象a,并调用start()方法启动线程

a = Job()

a.start()


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值