基于香橙派和SU-03T 使用Linux实现语音控制刷抖音

2023-09-17 06:08:00

硬件介绍

SU-03T之前在小车的时候使用过,详见:语音小车---6 + 最终整合_mjmmm的博客-CSDN博客

按照下图进行接线:

项目需求 

通过语音指令来控制安卓手机刷抖音,可以实现视频切换和点赞等功能:

1. 开机播报“你好,我是你的刷抖音助手

1. 当说出“你好抖音助手"可以唤醒模块,模块回复“抖音助手在

2. 当超过10s没有指令或说出“退下”时,模块会进入休眠模式,并回复“有需要再叫我

3. 当说出“下一个视频”或“这个不好看”时,模块回复“切换至下一个视频”,并划到下一个视频

4. 当说出“上一个视频”或“刚刚那个挺好看”时,模块回复“切换至上一个视频”,并划回上一个视频

5. 当说出“点个赞”或“这个视频不错”时,模块回复“以为您点赞”,并点赞当前视频

6. 当说出“不想看了”时,模块回复“以为您关闭屏幕”,并关闭手机屏幕

SU-03T的设置和烧写

设置和烧写的详细步骤也参考之前写的博文,此处只展示关键信息:

1. 创建产品:

2. 设置PIN脚为串口模式:

对于SU-03T,串口的RX和TX分别对应B6和B7

并设置相应的波特率:

3.  设置唤醒词:

4.  设置指令语句:

5. 设置控制详情:

参数的设置就是行为的名字 -> 大写字母 -> 16进制ASCII码,已空格分开

 

next -> 4E 45 58 54

pre -> 50 52 45

zan -> 5A 41 4E

guan -> 47 55 41 4E

 6. 其他配置,如声音,开机播报,主动退出等,都是按喜好设置,这里不再详细展示:

 7. 下载SDK并烧写进入SU-03T

详细步骤仍参考之前的博文:

8. 测试:

此时,可以打开串口助手来测试一下,分别说出对应的指令,看看SU-03T是否会向串口发送对应的字符:

我分别说出了四条指令,可见串口输出正确!

编写香橙派代码的框架

SU-03T设置完成后,就可以将SU-03T接到香橙派并进行Linux部分的代码编写:

由于在这个项目中,SU-03T只负责发送,香橙派只负责接收,所以除了电源外,只需要将SU-03T的TX(B7)接到香橙派的RX就可以,算上电源共三根线:

新创建一个“douyin”文件夹,将语音刷抖音项目的代码放在这里面:

然后将一些代码拷贝进来方便修改:

 重新编译一下,并说出4条控制语句:

可见,SU-03T成功识别了指令,香橙派成功的接收了SU-03T通过串口打印的字符!

现在,就需要修改serial_douyin.c中接收的代码,添加数据处理的部分

先简单写一个数据处理的框架:

serial_douyin.c -> void *write_serial(void *arg):

void *write_serial(void *arg)
{
    char readbuf[32] = {'\0'};
    while(1){
        while(serialDataAvail (*((int *)arg))){
            serialGetstring (*((int *)arg),readbuf) ;

            if(strcmp(readbuf,"NEXT") == 0 ){
                printf("收到下一条视频指令\n");
            }else if(strcmp(readbuf,"PRE") == 0){
                printf("收到上一条视频指令\n");
            }else if(strcmp(readbuf,"ZAN") == 0){
                printf("收到点赞指令\n");
            }else if(strcmp(readbuf,"GUAN") == 0){
                printf("收到关闭指令\n");
            }else{
                printf("未知指令\n");
            }

            memset(readbuf,'\0',32);
        }
    }

    pthread_exit(NULL);
}

然后再次编译运行,说出四句指令:

可见,函数框架正确,接下来只需要将printf替换成真正的操作手机的代码就可以了 

将手机接入香橙派

将我破旧的小米5C再次拿出哈哈哈,然后通过 TYPE-C -- USB 连接到香橙派:

然后进行如下操作:

1.  香橙派输入dmesg指令查看手机接入情况:

可见已经成功识别

2.  安装adb:

由于安卓手机的底层也是用Linux系统来操作的,所以可以通过香橙派来直接进入控制手机shell的界面,但需要先安装adb工具,adb是做安卓开发中常用的工具:

sudo apt-get install adb

安装完之后,执行”adb devices“指令:

发现好像权限不太对,因此需要在安卓手机上设置权限

3. 设置手机权限

报错的本质原因是香橙派系统还不支持USB设备的热拔插UDEV的机制

解决办法:在 /etc/udev/rules.d 文件夹下创建规则文件:

cd /etc/udev/rules.d/
sudo vim 51-android.rules

然后在文件中添加内容:

SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0666" 

 

然后重新拔插手机!!

现在再次执行”adb devices“指令:

没有像刚刚那样报错了,但是仍然显示执行”adb devices“指令:限

解决办法:打开手机,允许调试:

此时,再再次执行”adb devices“指令:

没有任何报错了,此时”adb shell“指令:

连接成功!! 

此时如果“ls”一下:

可以看到很多文件没有权限,因为没有root 

小插曲:什么是udev?

  • udev是一个设备管理工具,udev以守护进程的形式运行,通过侦听内核发出来的uevent来管理/dev目录下的设备文件。udev在用户空间运行,而不在内核空间 运行。它能够根据系统中的硬 件设备的状态动态更新设备文件,包括设备文件的创建,删除等。设备文件通常放在/dev目录下。使用udev后,在/dev目录下就只包含系统中真正存在的设备。

4. 使用shell指令来模拟手滑屏幕

现在可以成功的连入手机内部的系统,关键就在于对于滑动或点击屏幕的指令模拟了:

  • adb shell input swipe <起始x坐标> <起始y坐标> <结束x坐标> <结束y坐标> <滑动持续时间ms>
  • adb shell input keyevent <按键事件的常量>
adb shell input swipe 540 1300 540 500 500 //下滑
adb shell input swipe 540 500 540 1300 500 //上滑
adb shell "seq 3 | while read i;do input tap 350 1050 & input tap 350 1050 &sleep 0.01;done;" //点赞
adb shell input keyevent 26 //锁屏

最终代码的编写

现在有了基本的代码模型,和控制手机的具体指令,接下来的工作就是在数据处理的部分,执行adb指令了,显然,使用system函数就可以:

serial_douyin.c:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include "mjm_uart_tool.h"

void *read_serial(void *arg)
{
	char *sendbuf;
	sendbuf = (char *)malloc(32*sizeof(char));

	while(1){
		memset(sendbuf,'\0',32*sizeof(char));
		fgets(sendbuf,sizeof(sendbuf),stdin);
		serialSendstring (*((int *)arg), sendbuf) ;
	}

	pthread_exit(NULL);

}


void *write_serial(void *arg)
{
	char readbuf[32] = {'\0'};
	while(1){
		while(serialDataAvail (*((int *)arg))){
			serialGetstring (*((int *)arg),readbuf) ;
			//printf("-> %s\n",readbuf);
			
			if(strcmp(readbuf,"NEXT") == 0 ){
				printf("收到下一条视频指令\n");
				system("adb shell input swipe 540 1300 540 500 500");
			}else if(strcmp(readbuf,"PRE") == 0){
				printf("收到上一条视频指令\n");
				system("adb shell input swipe 540 500 540 1300 500");
			}else if(strcmp(readbuf,"ZAN") == 0){
                printf("收到点赞指令\n");
				system("adb shell \"seq 3 | while read i;do input tap 350 1050 & input tap 350 1050 &sleep 0.01;done;\"");
            }else if(strcmp(readbuf,"GUAN") == 0){
                printf("收到关闭指令\n");
				system("adb shell input keyevent 26");
            }else{
				printf("未知指令\n");
			}

			memset(readbuf,'\0',32);
		}
	}

	pthread_exit(NULL);
}



int main ()
{
	int fd ;

	int ret;
	pthread_t read_thread;
	pthread_t write_thread;

	if ((fd = myserialOpen ("/dev/ttyS5", 115200)) < 0) //打开驱动文件,配置波特率
	{
		fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
		return 1 ;
	}

	/*	if (wiringPiSetup () == -1)
		{
		fprintf (stdout, "Unable to start wiringPi: %s\n", strerror (errno)) ;
		return 1 ;
		}*/

	ret = pthread_create(&read_thread,NULL,read_serial,(void *)&fd);
	if(ret != 0){
		printf("read_serial create error\n");
		return 1;
	}
	ret = pthread_create(&write_thread,NULL,write_serial,(void *)&fd);
	if(ret != 0){
		printf("write_serial create error\n");
		return 1;
	}

	pthread_join(read_thread,NULL);
	pthread_join(write_thread,NULL);

	return 0 ;
}

实现效果: 

和项目需求一致,可见,我的手并没有碰到手机屏幕,只是说出了对应的指令,手机就会有所反应:

并且在香橙派终端也可以看到指令历史:

更多推荐

【python】我用python写了一个可以批量查询文章质量分的小项目(纯python、flask+html、打包成exe文件)

web效果预览:文章目录一、API分析1.1质量分查询1.2文章url获取二、代码实现2.1Python2.11分步实现2.12一步完成2.13完整代码2.2python+html2.21在本地运行2.22打打包成exe文件2.23部署到服务器一、API分析1.1质量分查询先去质量查询地址:https://www.cs

Python垃圾回收机制详解:引用计数与循环垃圾收集器

文章目录Python垃圾回收机制引用计数机制循环垃圾收集器小结详细讲解及实操1.程序中的垃圾问题2.垃圾的定义3.自动垃圾回收机制4.示例:使用del方法删除垃圾对象5.手动处理垃圾回收6.结束程序7.垃圾回收的自动处理8.结束程序python精品专栏推荐python基础知识(0基础入门)python爬虫知识Pytho

MySQL与ES数据同步的四种方案及实践演示

文章目录一、同步双写优点缺点双写失败风险项目演示二、异步双写(MQ方式)优点缺点项目演示三、基于Datax同步核心组件架构图支持的数据源及操作项目演示四、基于Binlog实时同步实现原理优点缺点项目演示一、同步双写也就是同步调用,这是一种最为简单的方式,在将数据写到mysql时,同时将数据写到ES。优点1.业务逻辑简单

14:00面试,14:06就出来了,问的问题有点变态。。。

从小厂出来,没想到在另一家公司又寄了。到这家公司开始上班,加班是每天必不可少的,看在钱给的比较多的份上,就不太计较了。没想到5月一纸通知,所有人不准加班,加班费不仅没有了,薪资还要降40%,这下搞的饭都吃不起了。还在有个朋友内推我去了一家互联网公司,兴冲冲见面试官,没想到一道题把我给问死了:如果模块请求http改为了h

每日练习-7

目录一、选择题二、算法题1、两种排序方法2、求最小公倍数一、选择题1、解析:指针和引用是C++中两种不同的变量类型,它们都可以用来访问或修改其他变量的值,但是它们有以下几个区别:引用必须在定义时初始化,而指针可以在任何时候初始化。例如,int&r=a;是合法的,但是int&r;是不合法的。而int*p;和int*p=&

02_elasticsearch 核心概念

02_elasticsearch核心概念1、lucene和elasticsearch的前世今生2、elasticsearch的核心概念1、lucene和elasticsearch的前世今生1、lucene和elasticsearch的前世今生lucene:最先进、功能最强大的搜索库。但是直接基于lucene开发,非常复

【Vue】模板语法,插值、指令、过滤器、计算属性及监听属性(内含面试题及毕设等实用案例)上篇

一、引言1、什么是模板语法?Vue的模板语法是一种用于在HTML中声明式地渲染Vue组件的语法。它基于HTML,并通过特定的模板语法扩展了HTML。Vue使用了一种称为“Mustache”语法的模板插值来绑定数据到HTML元素上。在Vue的模板语法中,你可以使用双大括号({{}})将数据绑定到HTML元素上,这样数据的

隔山打牛:金融大崩溃

当2004-2006年美联储主席格林斯潘在任期的末尾一鼓作气把联邦利率从1%拉高到5%,然后把美联储主席的位子交给继任者伯南克的时候,没有人意识到接下来将要发生何等巨变。图:美国联邦利率伯南克把利率稳定在5.3%附近的高位一年左右时间,直到2007年年中。美股从2003年底开始的牛市,一直狂飙到2007年底。标普500

【数据仓库设计基础1】关系数据模型理论与数据仓库Inmon方法论

文章目录一.关系数据模型中的结构1.关系2.属性3.属性域4.元组5.关系数据库6.关系表的属性7.关系数据模型中的键二.关系完整性1.空值(NULL)2.关系完整性规则3.业务规则4.关系数据库语言三.规范化四.关系数据模型与数据仓库关系模型被广泛应用于数据处理和数据存储,尤其是在数据库领域,现在主流的数据库管理系统

HTML5的新特性有哪些?

HTML5是近年来Web开发标准最巨大的飞跃。与以前的版本不同,HTML5并非仅仅用来表示Web内容,它的新使命是将Web带入一个成熟的应用平台,在HTML5平台上,视频、音频、图像、动画,以及同计算机的交互都被标准化。HTML5在以前浏览器发展的基础上对标记进行了简化。另外,HTML5中对标记从语法上也进行了分类。(

nextTick 解析

🎬岸边的风:个人主页🔥个人专栏:《VUE》《javaScript》⛺️生活的理想,就是为了理想的生活!目录JS执行机制#运行机制nextTickqueueJobandqueuePostFlushCbqueueFlushflushJobs为什么要nextTick总结看完是不是有一堆问号?我们从中找出来产生问号的关键词

热文推荐