最好的电子音响科技diy制作网站

haoDIY创好电子音响电脑科技DIY小制作发明

当前位置: 主页 > 电子DIY > 综合DIY >

基于安卓的视频遥控小车

时间:2022-05-26 14:01来源:mbb.eet-china.com 作者:RoachWZ 点击:
if (faces.length 0){ Log.d(FaceDetection, face detected: + faces.length + Face 1 Location X: + faces[0].rect.centerX() + Y: + faces[0].rect.centerY() ); faceX=faces[0].rect.centerX(); faceY=faces[0].
基于安卓的视频控制小车



目录
一、 创意来源
二、 项目概述
三、 优势
四、 功能
五、 制作材料
六、 详细介绍
一、创意来源

当今在安防监控领域,大多数民用监控设备有几大弊端:

位置固定:大多数设备位置固定,不便移动,即使有一些可以摄像头可以转动,但是仍然无法实现对大部分区域的监控,比如一些存在死角的位置就不会被监控(床底,墙角等等),因此小车的可移动性监控有较为突出的优点。应用在家庭监控领域较为合适,尤其是家中无人的时候。

有线传输,电源线:大多数是有线传输,即使有一些是无线传输,但是仍要被束缚在电源线上。而本小车就不同了,可以直接装个充电宝做备用电源
价格昂贵:当今一套完整的监控设备成本较高。而本小车利用了过时淘汰的手机,大大节约了成本,一定程度上控制了废旧手机的污染。基于当今监控设备这些缺点,构造出了基于安卓的视频控制小车。
 
二、项目概述

本设计是将安卓技术、单片机技术、无线通信技术等相关技术应用到视频监控系统中,可实现视频监控系统的设备移动化,由可移动监控平台、控制软件两部分组成。使用安卓手机作为控制端,通过无线网络对监控平台进行移动方向、速度的控制,平台上的摄像头实时采集视频图像信号并通过无线WiFi网络将视频信号实时传输到手机端观看,然后可实时拍照录像并可实时存储。由于监控端可移动,可以在无人进入的情况下获取危险环境的视频图像。具有控制方便,监控灵活,模块化,可拓展性强等优点,可应用于险情探测、防爆、现场巡视、家庭安防、图像采集等领域。

三、优势:

设计之初不完全是为了DIY,我是希望能够做出一款实用便宜易用的产品,所以没有采用常用的DIY开源硬件方案例如arduino,而是选择了价格便宜,应用广泛的STC89C52RC单片机芯片来做控制方案。当然也相信大家能理解我为什么会选择android手机来做智能小车大脑。

1. 我们制作的智能小车抛开性能低下、操作复杂的单片机,使用移动终端作为控制端,利用移动终端(例如手机,电脑,平板)的高性能处理器和低廉的价格,降低了研发成本和研发难度。

2. 通过移动网络或者本地局域网进行连接,可以在任何地方,使用任何设备即可对小车进行远程遥控,对家庭安全进行防护。

3. 小车可以近距离红外遥控,在可视距离下,对小车进行遥控。

虽然红外的遥控的控制距离只有10m左右,无法绕过障碍物进行遥控。但发射红外遥控信号的手机就架在小车上,可以将手机的红外发射器和红外接收器放在一块固定住。虽然并不是所有的安卓手机都有红外发射器,但都有3.5mm的耳机接口,红外信号的38kHz频率在音频范围内,可以用耳机接口外接的红外发光二极管发射红外遥控信号。如果使用蓝牙来完成对小车的控制,小车上需要配备蓝牙模块与手机进行配对通信。而且并不是所有的手机都支持蓝牙,早期的一些安卓智能手机就不支持蓝牙。而且蓝牙需要配对连接,红外遥控无需配对连接,省去等待时间。相比蓝牙模块,红外模块成本更低。所以采用红外遥控模式。

4. 与WIFI IP camera对比:

1)可以到处跑,因为不需要插着电源线;2)省电,待机长,所以不用担心充电问题。3)监控声音情况。

四、功能:

1)实时视频(android手机摄像头开发)
2)红外遥控车(STC89C52RC )
3)人脸检测追踪(android手机编程)

五、制作材料:

1)控制板包括:
51单片机最小系统
红外遥控接收一体化模块VS1838B
L293D电机驱动模块
2)小车底盘(淘宝上面有非常多的小车底盘卖,自己任选),
3)马达:TT马达 2个
4)轮子:2个
5)锂电池:2200mAH  两节7.4V   + 充电器
6)杜邦线若干

六、详细介绍

1相关技术

Android摄像头自定义相机开发、Android人脸检测(FaceDetector)API开发、Android红外遥控开发、Android网络实时音视频传输开发、单片机红外解码及电机控制 。

2工作方式

基于安卓的视频控制小车利用了能发射红外信号的安卓旧手机作为核心,通过WiFi将手机或电脑监控端与车载手机控制端相连接,继而间接实现手机或电脑监控端对小车的控制。

通过手机或电脑端向手机发送指令,然后手机执行指令向小车发射红外信号进行相应控制,并调用车载手机摄像头将小车前方的图像信息回传给手机或电脑监控端。

另外,小车还可以对人脸进行检测跟随,根据人脸在视频中位置,不断调整小车方向直到人脸位于屏幕中心,增强娱乐性。

3手机应用介绍

1)用手机替代网络摄像头,更智能,更省电;
2)支持红外遥控玩具遥控车; (移动功能,需要配套本设计红外遥控小车)
3)人脸跟随;(娱乐功能,需要配套本设计红外遥控小车)

使用方法:

1、安装应用,分别在两部手机上安装;
2、将两部手机连入同一WIFI网络下,输入对方IP地址;
3、把其中一部手机放到红外遥控玩具车上;
 
下面是视频遥控演示视频:
人脸追踪代码:http://www.pudn.com/Download/item/id/3913500.html
小车端单片机代码 http://www.pudn.com/Download/item/id/3913492.html
安卓手机端代码 http://www.pudn.com/Download/item/id/3913489.html上一篇简单介绍了“基于安卓的视频遥控小车”,这次详细说说此设计的安卓端的红外遥控部分。

手机和小车之间的通信我用的不是蓝牙是红外遥控,虽然红外的遥控的控制距离只有10m左右,无法绕过障碍物进行遥控。但发射红外遥控信号的手机就架在小车上,可以将手机的红外发射器和红外接收器放在一块固定住。虽然并不是所有的安卓手机都有红外发射器,但都有3.5mm的耳机接口,红外信号的38kHz频率在音频范围内,可以用耳机接口外接的红外发光二极管发射红外遥控信号。如果使用蓝牙来完成对小车的控制,小车上需要配备蓝牙模块与手机进行配对通信。而且并不是所有的手机都支持蓝牙,早期的一些安卓智能手机就不支持蓝牙。而且蓝牙需要配对连接,红外遥控无需配对连接,省去等待时间。相比蓝牙模块,红外模块成本更低。所以采用红外遥控模式。
上边说的都是后话了,当初之所以用红外,是因为我一开始用的不是OPPO A51 ,用的是酷派8076D。那会儿A51还用着呢,这个酷派手机有WiFi但没有蓝牙,所以手机和单片机之间的通信就成了问题。
当时的小车还是这个样子
#p#分页标题#e# 
我从网上搜了好多解决方案,智能手机是开发完成的产品,留出的接口不多,也只有USB口和耳机口:
一,用手机的USB口,但我发现酷派8076D不支持OTG,然后又从网上搜说是厂家只是删除了配置文件,我试了试,还是不行,它硬件上应该也没有升压电路(手机电池一般3.7V,USB是5V供电)。这部分参考使用android IOIO和安卓手机制作视频遥控小车(控制灯的开关、实时视频传输、方向控制)
二,用耳机口,这个网上也有例子一文读懂Android/iOS手机如何通过音频接口与外设通信,他这种方案是双工通信,但这个吧,涉及到信号处理,和数学打交道,鄙人数学渣渣。再者得买个这种外设,no money啊。然后我之前研究过遥控精灵(ZaZaRemote),不支持红外遥控的手机,在耳机孔插个红外发射头(smart zaza)就行了。这种方案是单工通信,小车配套上红外一体化接收头就可以遥控小车移动。不过不同手机的耳机口驱动力不一样,有的驱动不了红外发光二极管(压降1.4V左右),我的酷派就驱动不了,我直接把二极管接在手机喇叭上。
最后,选择了音频口发射红外信号这种方案。其实造车之前,就开始在研究红外了,那会儿考四六级和期末英语考试都是用的红外耳机,就想着期末英语怎么作弊(^_−)☆,因为听力就是课本上的。教室有个红外发射器,后来查了些资料发现就是音频范围,把喇叭拆了接上红外发光二极管,就能用红外耳机听到声音。不过没用在作弊上,因为功率太小了(酷派手机喇叭改的),盖不过教室的。
音频转红外这块,我还没做好,我只是录了红外遥控信号的音频文件,然后播放。但我发现准确率大概只有八成,感觉这东西涉及到傅里叶变换,音频是正弦波,红外信号是方波,直接用音频驱动是有误差的吧,我也不是很懂,数学不好。网上我搜到这篇是用安卓实现的安卓手把手教你学习并实现 安卓耳机口音频转红外发射,但我是用底层C语言实现的,用的C4droid写的在手机上运行,参考的这篇 OpenSL ES范例,无java代码,纯C
再后来,OPPO A51不用了,就把它用在小车上。OPPO A51支持红外遥控,所以不用那么麻烦。参考这篇Android编程红外编程——红外码详析
单片机红外解码程序参考Android遥控器开发,这个后边有单片机红外解码程序。
因为Android4.4及以上才有ConsumerIrManager类用来操控红外设备,所以以下程序是基于Android 5.1系统的OPPO A51手机开发和测试的。
首先从系统服务中获取到ConsumerIrManager服务。
IR=(ConsumerIrManager)getSystemService(CONSUMER_IR_SERVICE);
然后将要发送的红外码存入数组中
//0x73    int[] pattern2 = { 9000, 4500,             560, 560,     560, 560,     560, 560,     560, 560,     560,560,     560, 560,     560, 560,     560, 560,             560, 1690,     560, 1690,     560, 1690,    560, 1690,     560, 1690,     560, 1690,     560, 1690,     560, 1690, /*0001 1000*/560, 560,    560, 560,     560, 560,     560, 1690,     560, 1690,     560, 560,     560, 560,     560, 560,             560, 1690,     560, 1690,     560, 1690,     560, 560,     560, 560,     560, 1690,     560, 1690,     560, 1690,             560, 42020, 9000, 2250, 560, 98190 };
一种交替的载波序列模式,通过毫秒测量
引导码,地址码,地址码,数据码,数据反码
第三行数据码反置,比如0x12=0001 0010反置为 0100 1000
可能和接收有关系,只有反置了之后才能接收正常
最后通过如下方法最终发送红外信号。
mCIR.transmit(hz, pattern2);//后 
transmit(int carrierFrequency, int[] pattern)  :此方法控制手机产生 carrierFrequency为频率的,以pattern为红外开关的时间数组,发送红外信号。(例如:transmit(38000,{100,200,300,400})    将会产生一个频率为38KHz的红外信号,信号的电平高低为 100us高电平,200us低电平,300us高电平,400us低电平。注意pattern的数据个数要为偶数个,不然报错。)。
手机端红外发射功能的程序流程图如下图所示。
还可以参考以下链接
我也DIY一个Android遥控器-全部开源
手机当万能遥控器-自制“遥控精灵”外设
http://compeition-excute.oss-cn-beijing.aliyuncs.com/webFile/2019512/600c821e61d811e9bb8a00163e040299/9qkYa1X9_1557635749829.mp4
基于安卓的视频遥控小车的安卓程序能够使用手机后置摄像头实时地将手机拍到的图像传送到电脑端,同时接收电脑端发出的指令。根据电脑的指令手机再发送相应的红外遥控信号给小车,手机安卓程序主要是实现自定义相机、实时视频传输和红外信号传输等功能。
开发环境用的是ADT Bundle,集成了Eclipse、ADT插件和SDK Tools,安装好JDK即可开始开发,方便使用者进行相关的应用开发。
  
一、摄像头
手机端的摄像头采集到的原始数据数据是YUV格式。建立YuvImage对象image用来存储YUV格式的原始数据。原始数据太大,需要再通过调用image.compressToJpeg()将YUV格式图像数据转为jpg格式。然后启动发送线程,通过socket将每一帧的图像发送到电脑端接收,电脑窗体再一帧一帧播放,形成视频效果。
由于时间不足,所以没有再花时间去学习相关的视频流处理原理和技术。在此使用的是动画播放原理。在基于安卓的视频遥控小车——电脑端开发也说到了,实时视频是通过电脑窗体一帧一帧播放图片,形成视频动画效果。摄像头采集到的是最低分辨率,这样每一帧图像的数据量就小了,延迟也就下去了。
手机端实时视频功能的程序流程图如下图所示。
下面来对主要步骤进行详细介绍。
对于摄像头的操作实际上是安卓自定义相机开发。直接控制相机,比调用系统相机要难一些。首先要访问相机资源,打开摄像头的语句如下。
Camera.open(id);
Id表示摄像头的编号,后置摄像头为0,前置摄像头为1。在调用open()时不传入参数指定打开哪个摄像头,默认是0。
摄像头采集到的原始数据是YUV格式的数据,结构如下,其参数作用如下表所示。
YuvImage image = new YuvImage(byte[] yuv,
int format,
int width,
int height,
int[] strides);

参数
类型
作用
yuv
byte
YUV数据。在多个图像平面的情况下,所有平面必须连接成单个字节数组。
format
int
YUV数据格式,如ImageFormat。
width
int
YuvImage的宽度。
height
int
YuvImage的高度。
strides
int
(可选)每个图像平面的行字节。如果yuv包含填充,则必须提供每个图像的步幅。如果strides为null,则该方法假定没有填充,并按格式和宽度本身派生行字节。
#p#分页标题#e#
调用image.compressToJpeg()将YUV格式图像数据转为jpg格式代码如下,其参数作用如下表所示。
image.compressToJpeg(Rect rectangle,
int quality,
OutputStream stream);

参数
类型
作用
rectangle
Rect
要压缩的矩形区域。方法检查矩形是否在图像内。此外,如果矩形中的色度像素与其中的亮度像素不匹配,则该方法修改矩形。
quality
int
提示压缩机,范围0-100。0表示压缩小尺寸,100表示压缩以获得最高质量。
stream
OutputStream
OutputStream写入压缩数据。
预览一般用SurfaceView显示摄像头采集到的画面内容。需要用到preview class。这个类需要实现android.view.SurfaceHolder.Callback接口,并用此接口把摄像头采集到的画面送到当前的预览界面。
当应用调用完摄像头之后,必须进行清理释放资源的操作。必须释放Camera对象,不然的话可能会引起其他应用程序使用Camera实例的时候发生崩溃。相应代码如下。
if (mCamera != null) {
        mCamera.stopPreview();//停止预览
        //调用release()以释放相机以供其他应用程序使用。应用程序应在onPause()期间 //立即释放相机,并在onResume()期间重新open()。
        mCamera.release();
        mCamera = null;
    }

二、红外遥控
详见基于安卓的视频遥控小车红外遥控部分

此部分代码
http://www.pudn.com/Download/item/id/3913496.html


参考文献的链接(可以点击访问)
感谢以下博主的文章
Google Android官方培训课程中文版——控制相机硬件
Android音视频-视频采集(Camera预览)
android实时视频网络传输方案总结(一共有五套)
android闪关灯的开启和关闭方法代码实例
关于降低android手机摄像头预览分辨率 - 莹波&微步
Android摄像头自定义相机拍照流程 - 景兄弟的博客
基于Socket的Android手机视频实时传输
Android Studio+Eclipse 利用socket实现视频的实时传输与接收

 
 
回复
 
 
本帖最后由 RoachWZ 于 2019-7-9 14:14 编辑

基于安卓的视频遥控小车的电脑端程序采用Java语言编写,Java可以做到一次编译到处运行,因为Java程序是在Java虚拟机中运行的,和平台无关,只要平台上有相应的Java虚拟机。
 
本设计中安卓手机是客户端,电脑是服务器端。采用ServerSocket类与多线程技术相互配合共同完成服务器端与客户端的程序开发。
Socket通信步骤如下图所示。手机采集到的图像通过Socket一帧一帧发送,电脑通过Socket接收每一帧图像。
电脑端Java程序主要代码
  1.  
  2. /**
  3. *在服务器开启情况下,启动客户端,创建套接字接收图像
  4. */
  5.  
  6. public class ImageServer {        
  7.     public static ServerSocket ss = null;
  8.    
  9.     public static void main(String args[]) throws Exception,IOException{   
  10.             ss = new ServerSocket(6000);
  11.         
  12.         final ImageFrame frame = new ImageFrame(ss);
  13.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  14.         frame.setVisible(true);
  15.       
  16.         while(true){
  17.                 frame.panel.getimage();
  18.             frame.repaint();
  19.         }        
  20.     }
  21.       
  22. }

建立好连接后,getimage()负责接收手机端传过来的图像,repaint()负责将接收到的图像绘制在窗体组件上。在此使用的是动画播放原理,实时视频是通过电脑窗体一帧一帧播放图片,形成视频动画效果。没有采用主流的视频压缩分包技术,而是选择牺牲画质。摄像头采集到的是最低画质,这样每一帧图像的数据量就小了,延迟也就下去了。
对小车的控制放在另一个线程中,监听按键的状态来判断要发送的命令。
主要代码如下所示
  1. jb.addKeyListener(new KeyAdapter() {
  2.                 ServerSocket ss;
  3.                 boolean sendFlag = false;//设置标志位,按下时只执行一次,不连续发送
  4.                 public void keyPressed(KeyEvent e) {
  5.                         int KeyCode = e.getKeyCode(); // 返回所按键对应的整数值
  6.                         String s = KeyEvent.getKeyText(KeyCode); // 返回按键的字符串描述
  7.                         System.out.print("输入的内容为:" + s + ",");
  8.                         System.out.println("对应的KeyCode为:" + KeyCode);
  9.                         if(!sendFlag) {
  10.                         try{
  11.                                 ss = new ServerSocket(7788);
  12.                                 send(KeyCode);
  13.                                 ss.close();
  14.                                 sendFlag=true;
  15.                         }catch (Exception e1) {
  16. #p#分页标题#e#
  17.  
  18.                                 e1.printStackTrace();
  19.                         }
  20.                         }
  21.                         
  22.                 }
  23.                 public void keyReleased(KeyEvent e) {
  24.                         int KeyCode = e.getKeyCode(); // 返回所按键对应的整数值
  25.                         if(KeyCode==38||KeyCode==40||KeyCode==37||KeyCode==39) {
  26.                                 try {
  27.                                         ss = new ServerSocket(7788);
  28.                                                 stop();
  29.                                                 sendFlag=false;
  30.                                         } catch (Exception e1) {
  31.                                                 e1.printStackTrace();
  32.                                         }
  33.                         }
  34.                 }
  35.  
  36.                         public void send(int i) throws Exception{
  37.                                         @SuppressWarnings("resource")
  38.                                         ServerSocket serverSocket = ss;//new ServerSocket(7788); // 创建ServerSocket对象
  39.                                         Socket client = serverSocket.accept(); // 调用ServerSocket的accept()方法接收数据
  40.                                         OutputStream os = client.getOutputStream();// 获取客户端的输出流
  41.                                         System.out.println("开始与客户端交互数据");
  42.                                         switch (i) {
  43.                                 case 38:os.write(("01").getBytes());break;//上
  44.                                 case 40:os.write(("02").getBytes());break;//下
  45.                                 case 37:os.write(("03").getBytes());break;//左
  46.                                 case 39:os.write(("04").getBytes());break;//右
  47.                                 }                        
  48.                                        
  49.                                         System.out.println("结束与客户端交互数据");
  50.                                         os.close();
  51.                                         client.close();
  52.                         }
  53.                         protected void stop() throws Exception {
  54.                                 ServerSocket serverSocket = ss;// 创建ServerSocket对象
  55.                                 Socket client = serverSocket.accept(); // 调用ServerSocket的accept()方法接收数据
  56.                                 OutputStream os = client.getOutputStream();// 获取客户端的输出流
  57.                                 os.write(("05").getBytes());//停止
  58.                                 os.close();
  59.                                 client.close();
  60.                                 ss.close();
  61.                         }
  62.         });
注意:

此部分源码链接http://www.pudn.com/Download/item/id/3913494.html

参考的文献感谢以下博主的文章
基于Socket的Android手机视频实时传输
camera拍摄视频并在电脑上显示
Android Studio+Eclipse 利用so基于安卓的视频遥控小车实现人脸跟随看起来好像高大上,其实是用的安卓自带的人脸检测API(FaceDetector),将其和红外发射代码结合起来,实现了小车人脸跟随功能。
 
人脸检测的接口为FaceDetectionListener,
  1. private class MyFaceDetectionListener implements Camera.FaceDetectionListener {
  2.  
  3.         @Override
  4.         public void onFaceDetection(Camera.Face[] faces, Camera camera) {
  5.             if (faces.length > 0){
  6.                 Log.d("FaceDetection", "face detected: "+ faces.length +
  7.                         " Face 1 Location X: " + faces[0].rect.centerX() +
  8.                         "Y: " + faces[0].rect.centerY() );
  9.             }
  10.         }
  11.     }

通过Camera的setFaceDetedtionListener方法来接受底层检测到脸的回掉。
  1. mCamera.setFaceDetectionListener(new MyFaceDetectionListener());



在摄像机开始预览了之后调用开始检测方法
  1. private void startFaceDetection(){
  2.         // Try starting Face Detection
  3.         Camera.Parameters params = mCamera.getParameters();
  4.  
  5.         // start face detection only *after* preview has started
  6.         if (params.getMaxNumDetectedFaces() > 0){
  7.             // camera supports face detection, so can start it:
  8.             mCamera.startFaceDetection();
  9.         }
  10.     }
以上为通用步骤,我对MyFaceDetectionListener进行了改造,
将其和红外发射代码transmit()方法结合起来,代码如下
  1. private class MyFaceDetectionListener implements Camera.FaceDetectionListener{
  2.                           private int faceX=0;
  3.                     private int faceY=0;
  4.                     boolean fMoveFlag = false;//设置标志位,只执行一次,不连续发送
  5.                     boolean bMoveFlag = false;
  6.                     boolean lMoveFlag = false;
  7.                     boolean rMoveFlag = false;
  8.                     Camera.Parameters parameters;
  9.                     public MyFaceDetectionListener(Camera.Parameters parameters) {
  10.                                 this.parameters=parameters;
  11.                         }
  12.                 @Override
  13.                 public void onFaceDetection(Camera.Face[] faces, Camera camera) {#p#分页标题#e#
  14.                     if (faces.length > 0){
  15.                            
  16.                         Log.d("FaceDetection", "face detected: "+ faces.length +
  17.                                 " Face 1 Location X: " + faces[0].rect.centerX() +
  18.                                 "Y: " + faces[0].rect.centerY() );
  19.  
  20.  
  21.                         faceX=faces[0].rect.centerX();
  22.                         faceY=faces[0].rect.centerY();
  23.                                          if(faceY<-100&&!fMoveFlag){
  24.                                         
  25.                                                  mCIR.transmit(38000, pattern1);
  26.                                                 fMoveFlag=true;
  27.                                                 bMoveFlag=false;
  28.                                  }
  29.                                  if(faceY>100&&!bMoveFlag){
  30.                                         
  31.                                             mCIR.transmit(38000, pattern2);
  32.                                             bMoveFlag=true;
  33.                                             fMoveFlag=false;
  34.                                  }
  35.                                  if(faceX<-100&&!lMoveFlag){
  36.                                         
  37.                                             mCIR.transmit(38000, pattern3);
  38.                                             lMoveFlag=true;
  39.                                             rMoveFlag=false;
  40.                                  }
  41.                                  if(faceX>100&&!rMoveFlag){
  42.                                                                       
  43.                                                        
  44.                                             mCIR.transmit(38000, pattern4);
  45.                                             rMoveFlag=true;
  46.                                             lMoveFlag=false;
  47.                                  }
  48.                     }else{
  49.                            
  50.                     }
  51.                 }
  52.             }


红外发射部分详见基于安卓的视频遥控小车红外遥控部分
人脸追踪代码:http://www.pudn.com/Download/item/id/3913500.html
参考文献感谢以下文章的博主的分享
Android音视频-视频采集(Camera预览) - LymanYe的博客
Android自带人脸识别
Adnroid 使用安卓自带的人脸识别API - 风飞飘扬的专栏cket实现视频的实时传输与接收
 

(责任编辑:admin)
织梦二维码生成器
顶一下
(0)
0%
踩一下
(0)
0%
相关文章
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
广告位API接口通信错误,查看德得广告获取帮助
推荐内容
广告位API接口通信错误,查看德得广告获取帮助