智能管家(原型)- 语音控制设备
最近研究物联网相关的东西,做了个小原型,称它为智能管家,能用语音控制设备以及手机APP控制设备。
先看看结构图:
功能描述:
- 通过语音控制器,说话,比如说出“帮我开灯”,led灯就量,或者说出“把这个灯给关了”,led灯就灭了
- 手机APP上有手动开关来控制led灯的亮和灭
- 支持全国范围覆盖,既不能局限于家里的LAN
目前为止,用到的设备主要就是ESPDuino。
ESPDuino:WIFI+Arduino
相关:
- ESP8266-01/ESP-01虽然很便宜但是用起来很麻烦,所以弃用
- Arduino Yun/Tian虽然功能强大,但是太贵700、800的节奏,弃用(不过这2个是带操作系统的,linino,基于openwrt)
- ESPDuino: 不带OS,集成WIFI功能,方便还便宜,大概40左右
分别来介绍下,分为:
- OneNet部分
- 手机APP部分
- 语音控制器部分
- 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代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | 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 ]\n", 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#写的下发指令到设备的程序,核心代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | #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 '\0' 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,完工。
有要代码的就找我发给你。
心怀远大理想。
为了家庭幸福而努力。
商业合作请看此处:https://www.magicube.ai
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探