zoukankan      html  css  js  c++  java
  • 智能管家(原型)- 语音控制设备

    最近研究物联网相关的东西,做了个小原型,称它为智能管家,能用语音控制设备以及手机APP控制设备。

    先看看结构图:

    功能描述:

    1. 通过语音控制器,说话,比如说出“帮我开灯”,led灯就量,或者说出“把这个灯给关了”,led灯就灭了
    2. 手机APP上有手动开关来控制led灯的亮和灭
    3. 支持全国范围覆盖,既不能局限于家里的LAN

    目前为止,用到的设备主要就是ESPDuino。

    ESPDuino:WIFI+Arduino

    相关:

    1. ESP8266-01/ESP-01虽然很便宜但是用起来很麻烦,所以弃用
    2. Arduino Yun/Tian虽然功能强大,但是太贵700、800的节奏,弃用(不过这2个是带操作系统的,linino,基于openwrt)
    3. ESPDuino: 不带OS,集成WIFI功能,方便还便宜,大概40左右

     分别来介绍下,分为:

    1. OneNet部分
    2. 手机APP部分
    3. 语音控制器部分
    4. ESPDuino执行部分

    OneNet部分:

    这里我们的主要工作是建立设备,记录下api_key,产品Id这些,并且我们使用的是MQTT协议进行通信(在产品定义中有)(需要新建产品以及新建设备2个步骤)

     手机APP部分

    由于不会app开发,并且onenet提供了简单的app平台,因此就用onenet的来做,如下,新增一个应用后进入设计app界面:

    上图中代表,此时点击 ON button就会下发指令到设备espduino,并且指令为   开灯  字符串, OFF button则为指令  关灯  字符串。

    然后保存,需要在手机上看的话,需要安装onenet的app,需要自己找找,最终效果截图:

    手机app部分也算完工了,很简陋,但是能控制就好。

    语音控制器部分

    这个部分分成了2个部分:语音解析文本及命令解析、命令下发;

    语音解析文本及命令解析程序:

    用的是讯飞语音api,c代码,我是用MFC做了个GUI程序,把demo代码嵌进去,把文本解析成相应的命令,如“开灯”、“关灯”

    命令下发程序:

    接收MFC发来的命令,比如“开灯”、“关灯”,然后调用onenet的api来下发指令到设备

    这部分是用C#做的,因为有很方便的现成的库,很容易的几行代码就搞定

    由于MFC比较复杂,这部分的我就截几段我认为关键的代码吧:

     MFC代码:

    static void show_result(char *string, char is_over)
    {
    	COORD orig, current;
    	CONSOLE_SCREEN_BUFFER_INFO info;
    	HANDLE w = GetStdHandle(STD_OUTPUT_HANDLE);
    	GetConsoleScreenBufferInfo(w, &info);
    	current = info.dwCursorPosition;
    
    	if (current.X == last_pos.X && current.Y == last_pos.Y) {
    		SetConsoleCursorPosition(w, begin_pos);
    	}
    	else {
    		/* changed by other routines, use the new pos as start */
    		begin_pos = current;
    	}
    	if (is_over)
    		SetConsoleTextAttribute(w, FOREGROUND_GREEN);
    	//printf("Result: [ %s ]
    ", string);
    	printf(string);
    	if (is_over)
    	{
    		CString s = CString(string);
    		//AfxMessageBox(LPCTSTR(s));
    
    		HWND m_hWnd = pFrame->m_hWnd;//->GetMainWnd()->m_hWnd;
    
    		SetDlgItemText(m_hWnd, IDC_STATIC, LPCTSTR(s));
    		SetDlgItemText(m_hWnd, IDC_STATIC_ACTION, LPCTSTR(s));
    
    		CString cmd = CString("C:\Users\Danny\Desktop\research\Windows_iat1220_5c82a0db\samples\mqtt-publish\bin\Debug\mqtt-publish.exe ");
    		if(s.Find(_T("开"))>=0&& s.Find(_T("灯")) >= 0)
    			cmd += "开灯";
    		else if (s.Find(_T("关")) >= 0 && s.Find(_T("灯")) >= 0)
    			cmd += "关灯";
    		else
    			cmd += "UNKNOWN";
    
    		USES_CONVERSION;
    		LPCSTR lpcstr = (LPCSTR)T2A(cmd);
    
    		WinExec(lpcstr, SW_HIDE);
    		
    		//PostMessage(pFrame->GetMainWnd()->m_hWnd, WM_MY_MESSAGE, NULL, NULL);
    	}
    	
    	if (is_over)
    		SetConsoleTextAttribute(w, info.wAttributes);
    
    	GetConsoleScreenBufferInfo(w, &info);
    	last_pos = info.dwCursorPosition;
    }  

     上面的mqtt-publish.exe就是C#写的下发指令到设备的程序,核心代码:

    static void Main(string[] args)
            {
                if (args.Length == 0)
                    return;
    
                string cmd = args[0];
    
                SendCmdRequest request = new SendCmdRequest();
                request.CmdContent = cmd;
                request.DeviceID = 520355898;
                request.IsByte = true;
                request.Protocol = Scheme.HTTP;
    
                DefaultOneNETClient client = new DefaultOneNETClient("api.heclouds.com", "vYKWEtx7jELTP2V4o=s1NgE1EdA=");
                var response=client.Execute(request);
                Console.WriteLine(response.Body);
    
            }
    

    C#很简单,红色部分是需要根据自己的onenet来改的,需要对应上,用到的nuget库:

    ESPDuino部分

    花费的时间最多的地方是这个部分,其次是MFC部分

    #include <ESP8266WiFi.h>
    #include <ESP8266HTTPClient.h>
    #include <PubSubClient.h>
    
     
    const char *ssid = "你的wifi name";
    const char *password = "你的wifi密码";
    
    
    const char* mqtt_server = "183.230.40.39";
    const char* mqtt_device_id="520355898";
    const char* mqtt_product_id="223168";
    const char* mqtt_api_key="vYKWEtx7jELTP2V4o=s1NgE1EdA=";
    
    WiFiClient client;
    PubSubClient mqttClient(client);
    
    long lastMsg = 0;
    char msg_buf[200];
    char dataTemplete[]="{"kq":%d}";
    char msgJson[75];
    char debug_buf[200];
    int i;
    unsigned short json_len=0;
    uint8_t* packet_p;
    uint8_t debug_buffer_start_index = 0;
    
    
    void setup() {
      Serial.begin(115200);
      pinMode(BUILTIN_LED, OUTPUT);
      delay(10);
     
      WifiConnected();
    
      initMQTT();
    }
    
    void initMQTT()
    {
        mqttClient.setServer(mqtt_server, 6002);
        mqttClient.connect(mqtt_device_id,mqtt_product_id,mqtt_api_key);
        mqttClient.setCallback(callback);
    }
    
    void callback(char* topic, byte* payload, unsigned int length) {
        Serial.print("Message arrived [");
        Serial.print(topic);
        Serial.print("] ");
        for (int i = 0; i < length; i++) {
          Serial.print((char)payload[i]);
        }
        Serial.println();
    
        String s_payload=String((char *)payload).substring(0, length);
        Serial.println(s_payload);
    
        //开灯命令?   
        if (s_payload.equals("关灯")||s_payload.equals(""关灯"")) {
          digitalWrite(BUILTIN_LED, LOW);
        } else if (s_payload.equals("开灯")||s_payload.equals(""开灯"")){
          digitalWrite(BUILTIN_LED, HIGH);
        }
     
    }
    
    
    void reconnect() {
      // Loop until we're reconnected
      while (!mqttClient.connected()) {
        Serial.print("Attempting MQTT connection...");
    if (mqttClient.connect(mqtt_device_id,mqtt_product_id,mqtt_api_key)) { //One net user name as product ID , and password as APIKey Serial.println("connected"); // Once connected, publish an announcement... mqttClient.publish("outTopic", "hello world"); // ... and resubscribe mqttClient.subscribe("inTopic"); } else { Serial.print("failed, rc="); Serial.print(mqttClient.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } void loop() { if (!mqttClient.connected()) { reconnect(); } mqttClient.loop(); long now = millis(); if (now - lastMsg > 2000) { lastMsg = now; int kqValue=analogRead(A0); snprintf(msgJson,sizeof(msgJson),dataTemplete,kqValue); json_len=strlen(msgJson); //packet length count the end char '' msg_buf[0]=char(0x03); //palyLoad packet byte 1, one_net mqtt Publish packet payload byte 1, type3 , json type2 msg_buf[1]=char(json_len>>8); //high 8 bits of json_len (16bits as short int type) msg_buf[2]=char(json_len&0xff); //low 8 bits of json_len (16bits as short int type) // snprintf(msg_buf+3,40,dataTemplete,value); memcpy(msg_buf+3,msgJson,strlen(msgJson)); msg_buf[3+strlen(msgJson)] = 0; Serial.print("Publish message: "); Serial.println(msgJson); mqttClient.publish("$dp",(uint8_t*)msg_buf,3+strlen(msgJson),false); } } void WifiConnected() { WiFi.disconnect(); WiFi.mode(WIFI_STA); Serial.println(); Serial.print("Connecting to"); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_DISCONNECTED) { delay(500); Serial.print("."); } randomSeed(micros()); Serial.println(""); Serial.println("WIFI connected"); Serial.println(WiFi.localIP()); }  

    至此,可以语音控制和手机控制了。

    后续扩展命令会较容易,可以move到C#部分来做,如果觉得语音转文本有不准的地方,目前的想法是通过神经网络来做识别,而不是通过目前的这种很挫的判断办法

     OK,完工。

    有要代码的就找我发给你。

      

  • 相关阅读:
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 88怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 81.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 40怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 24.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 21.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下驱动器试运行提示过速度保护怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下驱动器如何执行绝对值清零
    倍福TwinCAT(贝福Beckhoff)基础教程 松下绝对值驱动器如何做初始化设置
    倍福TwinCAT(贝福Beckhoff)基础教程 松下官方软件开启报错伺服未就绪怎么办
    JAVA Eclipse 启动 Eclipse 弹出“Failed to load the JNI shared library jvm_dll”怎么办
  • 原文地址:https://www.cnblogs.com/aarond/p/home-agent.html
Copyright © 2011-2022 走看看