大学生蓝牙科技论文

大学生蓝牙科技论文,第1张

蓝牙是一种无线技术标准,可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换。下面我给大家分享一些大学生蓝牙科技论文,大家快来跟我一起欣赏吧。

大学生蓝牙科技论文篇一

蓝牙定位测量

[摘要] 该文描述了一种基于蓝牙的无线室内定位测量系统。一般蓝牙工作使用接收信号强度指示器(RSSI),进行自动发射功率控制以保证稳定的信噪比。取消反馈系统,并应用RSSI产生一系列新的测试 方法 。系统使用安装在一个单元内的视距无线传播模型,测算基准发射器和便携式接收机之间的距离。该系统设计、运行和测试结果证实, 在存在多径干扰条件下,测量范围平均绝对误差可以达到12m。

[关键词] 蓝牙 定位测量 RSSI

1 简述

精确度大约1m的蓝牙室内定位测量将有助于扩大新的定位服务(LBS)范围。这些服务包括医用定位服务,具有无线传感器的计算机网络,移动数据探测和跟踪系统,用于安全用途的室内电子地图和具有定位识别的智能装置。

室内定位测量需要发展新技术设备。全球定位系统(GPS)要求视距内有4颗卫星以保证精确3-D定位,因此无法室内应用。无绳电话定位系统精确度只有大约100m。室内短距离(10米半径)内,无线电单元可用于测量位置,基于单元识别,但要求安装许多固定、均距的单元以覆盖给定区域。

蓝牙室内定位测量系统工作描述:在一个室内无线电单元内进行接收功率测量,它常用于跟踪固定基准蓝牙发射器和存在多径干扰的视距信道的便携式接收机之间的距离。

2 接收信号强度指示器(RSSI)定位测量

在蓝牙装置中, 接收信号强度指示器(RSSI)数值通常用于使发射功率最小化,以接收到满意的信噪比的信号。在本系统中反馈系统停止工作,发射机(发射功率PTX)和接收机之间距离能通过使用RSSI测量装置和一个无线电传播模型计算得出。

该方法非常适用于室内定位系统。而 其它 室内无线定位技术都不适用,如到达角度(AOA)法,到达时间(TOA)法,和到达时差(TDOA)法。第一种:AOA法,要求有一个特殊天线阵列用于测量接收信号的角度,成本高昂而且仅适用于专用系统。使用扫描技术要求系统有精确的时钟。便携式设备时钟精确度为1μs,但1m的定位误差要求时钟精确度应达到3ns。

这里使用的无线电波传播模型,其公式如下:

PRX=PTX+GTX+GRX+20log(c/4лf)-10n�(d)(1)

= PTX+GTX+GRX-402-10n�(d)(2)

其中:PRX是接收功率;PTX是发射功率(dB);GRX和GTX是天线增益(dBi);c是光速(30x108m/s);f是中心频率(244GHz);n是衰减因素(在自由空间为2);d是发射器和接收器之间的距离(m)。

蓝牙系统中使用RSSI直接测量接收功率,由一个内置微处理器将数据 报告 数字指示器。使用该装置,RSSI和接收功率之间的关系曲线如图1。

图1 RSSI与接收功率PRX 关系曲线

分析图1,可以得到RSSI和接收功率PRX关系如下:

PRX =-40dBm+RSSI, RSSI>0dB

-60dBm PRX≤-60dBm+RSSI,0>RSSI>-10dB

PRX≤-62dBm,RSSI=-10dB

因此,基准发射器和便携式接收机之间的距离d满足下列公式:

d=10[( PTX-402-PRX +G)/10n](4)

这里,PRX是测得的RSSI值经过公式(3)计算得出,总天线增益G= GTX+GRX

3 系统构成

该定位系统使用商业化的蓝牙开发套件构成。以个人电脑PC作为蓝牙主机,控制蓝牙模块,如图2所示。

定位应用在射频指令行接口(RFCLI)上完成,指令行起到容许用户控制和接入各种蓝牙软件层的作用。软件层分为主计算机界面(HCI)和蓝牙装置。主机通过通用异步接收/发射(UART)进行有线连接控制。板上的UART(HCI硬件接口)控制基带和射频层。

图2 主机和蓝牙装置之间硬件连接

一个基准发射器与便携式接收机进行通讯联系。首先应禁止蓝牙芯片对功率的控制功能。这样做将阻止两设备交换功率控制信息而保持接收功率在其限定范围内(将导致RSSI读值结果为0)。

测量在两种不同环境条件下进行:

无回声室测量。

在无回声室的测量中,确定天线增益G。测量装置设计模拟自由空间环境,频率范围为2~40GHz,衰减因素n=20,多径干扰可忽略。天线放置高度为06m,天线之间最大距离3m。

天线增益G见公式(4),因为其他变量已知,通过计算确定G的平均值是-48dBi。

办公环境测量

在办公室环境中,使用两试验基准线进行RSSI测量,距离增量为01m

图3 测量布置图

办公室内存在金属反射波,产生多路干扰。桌椅同样含有金属零部件。

在基线1,天线放置高度恒定为105m。在基线2,天线放置高度恒定为06m。初步测量显示,设备放置距离地板高度不同,对测量数据有一点影响。

两天线放置在固定的方向和高度,两者在视距范围内,按01m分段。利用射频通信(RFCOMM)协议产生一双工无线链路。使用频谱分析仪进行校准11个不同的发射功率:+29,+12,00,-14,-38,-62,-85,-103,-141,-171和-191dBm。

针对以上11个报告的基准发射功率,便携式接收机读出相对应的RSSI数值。 假如RSSI值非0,每个均测量20次RSSI值, 记录RSSI平均值。这些测量数据,每个均有一个随机载频,频率范围分布在蓝牙带宽(24000―24835GHz)之间。假如RSSI数值为0,无接收数据记录,选择不同的发射功率。所有11个发射功率均应进行试验。

分段距离每次递增01m,至最大值68m。

对应11个接收的RSSI值,PRxi在每个分段距离均优化到最大发射功率,PTx1=29dBm。实际发射功率和最大发射功率之间的差异值Pdiff=(PTx1一PTxi)(dB),信道与功率呈线性关系,所以通过增加Pdiff将接收到的RSSI值RRxi优化到一恒定发射功率上。

RRxi=PTxi+ Pdiff=PRxi+(PTX1-PTxi)(5)

使用公式(3)和(5)得出:

-40+RSSIi+(PTX1-PTxi), RSSIi > 0dB

RRxi= -60+RSSIi+(PTX1-PTxi),RSSIi�0dB,(6)

数据为空,RSSIi = 0dB 或RSSIi =-10dB

对于接收功率指示器,RRX对应非0时的RSSI数据,由下式给定

11

RRX= 1/x∑RRxi (7)

i=1

图4 接收功率RRX 与距离d关系曲线

(标准化发射功率=29dBm)

4 结果

41 接收功率和距离

优化后的接收功率数值RRX对应相应分段距

离d,d是基准发射器和便携式接收器之间的距离。基线1和2在办公环境的测量结果如图4。

图4显示了多径衰减的影响结果,两测量曲线的振幅均随距离增加而减少。而基线1和2位于办公室的不同位置,测量定位的衰减干扰是不同的。

通过传播模型预测RRx的理论数值,其中PTx=29dBm, n=2,G=-482 dBi。

距离d的平均绝对误差{公式(4)计算,PTx=29dBm, n=2,G=-482 dBi},对于实际距离和标准偏差如下。

表1 绝对误差和标准偏差

基线1 基线2

平均绝对误差 (m) 091 131

标准偏差 (m) 095 130

42 讨论

基于RSSI的蓝牙定位系统测量精度取决以下三因素:

421 精确的接收功率指示器

蓝牙规格中定义的RSSI值不是专门设计用于测量接收功率(dB)。而RRX作为接收功率指示,可用于距离估算。接收功率测量误差通过利用多路的、优化的发射功率求平均值进行最小化。

422 在传播模型中正确选择衰减因素和天线增益G。

线性调节分析用于决定衰减因素n和天线增益G,(n=215,G=-534dBi)。这些校正过的数据用在传播模型中,位置精确度将提高约10%。

423 减小多径干涉的影响

接收功率和距离关系曲线(见图4),显示两测量设备测试值对理论值的波动和偏差。该图显示了进行时域、频率和发射功率平均后的测量结果。

5 结论

在视距(LOS)无线传播模型中,利用一个简单单元,通过禁止蓝牙(自动)传播功率控制的功能,实现蓝牙接收信号强度指示器RSSI值应用于定位测量。

该技术表明可降低平均绝对定位误差到12m。这适合于大多室内定位服务。不过,需要注意的是,在强烈的多径干扰下,定位误差仍然存在。绝对位置估算需要平均一系列接近的空间位置以增加可信度。

将来工作可能包括在非LOS条件下完成评价系统。利用三角测量可给出在二维平面上的精确定位信息。

参考文献

[1] A Harder, L Song and Y Wang, Towards an indoor location system using RF singnal strengh in IEEE80211,(April 2005)

[2] Sheng Zhou and John Pollard, Position Measurement Using Bluetooth in IEEE0098/3036/06,(May 2006)

点击下页还有更多>>>大学生蓝牙科技论文

开发前提介绍  : 1 XCode  2蓝牙手环(60)  3苹果手机一部(1000)

规矩我懂 先上图

2014122 蓝牙技术联盟发布

具备更低功耗, 更高的传输速度。 唤醒速度可以和zigbee媲美

蓝牙20 需要MIFI 认证,这个大家都知道 。 MIFI : Make for ipad , iphone , itouch  专门为苹果设备制作的设备

蓝牙40 : 本文章的主讲

开发框架 : CoreBluetooth

           

central: 中心,连接硬件设备(手机端连接蓝牙手环 等等智能设备)

peripheral: 外设, 被连接的设备(仅当外设在不断广播的时候 才能被发现)

service: 服务

characteristic: 特征

               

_manager = [[CBCentralManager alloc] initWithDelegate: self queue: nil];

在调用这个方法的时候 带来会调用

- (void)centralManagerDidUpdataState:(CBCentralManager )central

返回 :

当前蓝牙的状态 :

if (centralstate != CBManagerStatePoweredOn) // 就代表返回失败了  当然自己看一下这个枚举

[_manager scanForPeripheralsWithServices:#你的特征值# options: nil];

# : 如果特征值写的是nil  那么当前所以可以被连接管理的蓝牙都可以扫描到

但是这里有个坑 , 已经连接上的蓝牙 不会在代理里面被返回

对应代理 :

处理 :

centralManager: (CBCentralManager )central didDiscoverPeripheral: (CBPeripheral )peripheral advertisementData: (NSDictionar id)advertisementData RSSI: (NSNumber )RSSI{

if(peripheralname != nil && ![_perilist containsObject: peripheral]){

[_perilist addObject: peripheral];

}

}

连接外设失败 : disFailToConnectPeripheral

连接断开: didDisconnectPeripheral

连接成功: didConectPeripheral

蓝牙定位基于RSSI(Received Signal Strength Indication,信号场强指示)定位原理。搭建方式很简单,借助蓝牙网关或者是蓝牙Beacon就可以实现。

蓝牙室内定位方案的实现必然是建立在蓝牙室内定位产品的基础上,主要定位硬件包括蓝牙网关、蓝牙Beacon、手环、手表等蓝牙标签以及智能手机、无线局域网及后端数据服务器等。根据定位端的不同,蓝牙定位方式分为网络侧定位和终端侧定位。

终端侧定位以蓝牙Beacon(VG01/VG02)主导,主要依托于蓝牙技术;网络侧定位以蓝牙网关(TD05/TD05A)为主导,集成了WiFi和蓝牙BLE两种无线通信方式;

蓝牙室内定位方案工作原理:

终端侧定位是蓝牙Beacon室内定位设备作为蓝牙信标不断的向周围广播信号和数据包。当终端设备进入Beacon设备信号覆盖的范围,测出其在不同信标(不同ID号的Beacon硬件设备)下的RSSI值,然后再通过手机内置的定位算法测算出具体位置(一般至少需要3个信标点的RSSI);

网络侧定位是蓝牙网关(TD03/TD05)里面的蓝牙模块收集蓝牙终端的蓝牙设备信息,包括Mac地址、RSSI等信息,通过UART串口发给蓝牙网关里面的WiFi模块,WiFi模块把信息传输到指定的UDP服务器,并能接收服务器返回的信息。UDP服务器接收到来自某个IP的蓝牙网关数据后,通过数据解析和计算,得到蓝牙信标的位置信息。希望能够帮助到您!

21首先获取BluetoothManager

复制代码 代码如下:

BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(ContextBLUETOOTH_SERVICE);

22获取BluetoothAdapter

复制代码 代码如下:

BluetoothAdapter mBluetoothAdapter = bluetoothManagergetAdapter();

23创建BluetoothAdapterLeScanCallback

private BluetoothAdapterLeScanCallback mLeScanCallback = new BluetoothAdapterLeScanCallback() {

@Override

public void onLeScan(final BluetoothDevice device, int rssi, final byte[] scanRecord) {

runOnUiThread(new Runnable() {

@Override

public void run() {

try {

String struuid = NumberUtilsbytes2HexString(NumberUtilsreverseBytes(scanRecord))replace("-", "")toLowerCase();

if (device!=null && struuidcontains(DEVICE_UUID_PREFIXtoLowerCase())) {

mBluetoothDevicesadd(device);

}

} catch (Exception e) {

eprintStackTrace();

}

}

});

}

};

24开始搜索设备。

复制代码 代码如下:

mBluetoothAdapterstartLeScan(mLeScanCallback);

25BluetoothDevice 描述了一个蓝牙设备 提供了getAddress()设备Mac地址,getName()设备的名称。

26开始连接设备

/

Connects to the GATT server hosted on the Bluetooth LE device

@param address

The device address of the destination device

@return Return true if the connection is initiated successfully The

connection result is reported asynchronously through the

{@code BluetoothGattCallback#onConnectionStateChange(androidbluetoothBluetoothGatt, int, int)}

callback

/

public boolean connect(final String address) {

if (mBluetoothAdapter == null || address == null) {

Logw(TAG, "BluetoothAdapter not initialized or unspecified address");

return false;

}

// Previously connected device Try to reconnect (先前连接的设备。 尝试重新连接)

if (mBluetoothDeviceAddress != null && addressequals(mBluetoothDeviceAddress) && mBluetoothGatt != null) {

Logd(TAG, "Trying to use an existing mBluetoothGatt for connection");

if (mBluetoothGattconnect()) {

mConnectionState = STATE_CONNECTING;

return true;

} else {

return false;

}

}

final BluetoothDevice device = mBluetoothAdaptergetRemoteDevice(address);

if (device == null) {

Logw(TAG, "Device not found Unable to connect");

return false;

}

// We want to directly connect to the device, so we are setting the

// autoConnect

// parameter to false

mBluetoothGatt = deviceconnectGatt(this, false, mGattCallback);

Logd(TAG, "Trying to create a new connection");

mBluetoothDeviceAddress = address;

mConnectionState = STATE_CONNECTING;

return true;

}

27连接到设备之后获取设备的服务(Service)和服务对应的Characteristic。

// Demonstrates how to iterate through the supported GATT

// Services/Characteristics

// In this sample, we populate the data structure that is bound to the

// ExpandableListView

// on the UI

private void displayGattServices(List<BluetoothGattService> gattServices) {

if (gattServices == null)

return;

String uuid = null;

ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<>();

ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData = new ArrayList<>();

mGattCharacteristics = new ArrayList<>();

// Loops through available GATT Services

for (BluetoothGattService gattService : gattServices) {

HashMap<String, String> currentServiceData = new HashMap<>();

uuid = gattServicegetUuid()toString();

if (uuidcontains("ba11f08c-5f14-0b0d-1080")) {//服务的uuid

//Systemoutprintln("this gattService UUID is:" + gattServicegetUuid()toString());

currentServiceDataput(LIST_NAME, "Service_OX100");

currentServiceDataput(LIST_UUID, uuid);

gattServiceDataadd(currentServiceData);

ArrayList<HashMap<String, String>> gattCharacteristicGroupData = new ArrayList<>();

List<BluetoothGattCharacteristic> gattCharacteristics = gattServicegetCharacteristics();

ArrayList<BluetoothGattCharacteristic> charas = new ArrayList<>();

// Loops through available Characteristics

for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {

charasadd(gattCharacteristic);

HashMap<String, String> currentCharaData = new HashMap<>();

uuid = gattCharacteristicgetUuid()toString();

if (uuidtoLowerCase()contains("cd01")) {

currentCharaDataput(LIST_NAME, "cd01");

} else if (uuidtoLowerCase()contains("cd02")) {

currentCharaDataput(LIST_NAME, "cd02");

} else if (uuidtoLowerCase()contains("cd03")) {

currentCharaDataput(LIST_NAME, "cd03");

} else if (uuidtoLowerCase()contains("cd04")) {

currentCharaDataput(LIST_NAME, "cd04");

} else {

currentCharaDataput(LIST_NAME, "write");

}

currentCharaDataput(LIST_UUID, uuid);

gattCharacteristicGroupDataadd(currentCharaData);

}

mGattCharacteristicsadd(charas);

gattCharacteristicDataadd(gattCharacteristicGroupData);

mCharacteristicCD01 = gattServicegetCharacteristic(UUIDfromString("0000cd01-0000-1000-8000-00805f9b34fb"));

mCharacteristicCD02 = gattServicegetCharacteristic(UUIDfromString("0000cd02-0000-1000-8000-00805f9b34fb"));

mCharacteristicCD03 = gattServicegetCharacteristic(UUIDfromString("0000cd03-0000-1000-8000-00805f9b34fb"));

mCharacteristicCD04 = gattServicegetCharacteristic(UUIDfromString("0000cd04-0000-1000-8000-00805f9b34fb"));

mCharacteristicWrite = gattServicegetCharacteristic(UUIDfromString("0000cd20-0000-1000-8000-00805f9b34fb"));

//Systemoutprintln("=======================Set Notification==========================");

// 开始顺序监听,第一个:CD01

mBluetoothLeServicesetCharacteristicNotification(mCharacteristicCD01, true);

mBluetoothLeServicesetCharacteristicNotification(mCharacteristicCD02, true);

mBluetoothLeServicesetCharacteristicNotification(mCharacteristicCD03, true);

mBluetoothLeServicesetCharacteristicNotification(mCharacteristicCD04, true);

}

}

}

28获取到特征之后,找到服务中可以向下位机写指令的特征,向该特征写入指令。

public void wirteCharacteristic(BluetoothGattCharacteristic characteristic) {

if (mBluetoothAdapter == null || mBluetoothGatt == null) {

Logw(TAG, "BluetoothAdapter not initialized");

return;

}

mBluetoothGattwriteCharacteristic(characteristic);

}

29写入成功之后,开始读取设备返回来的数据。

private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {

@Override

public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

String intentAction;

//Systemoutprintln("=======status:" + status);

if (newState == BluetoothProfileSTATE_CONNECTED) {

intentAction = ACTION_GATT_CONNECTED;

mConnectionState = STATE_CONNECTED;

broadcastUpdate(intentAction);

Logi(TAG, "Connected to GATT server");

// Attempts to discover services after successful connection

Logi(TAG, "Attempting to start service discovery:" + mBluetoothGattdiscoverServices());

} else if (newState == BluetoothProfileSTATE_DISCONNECTED) {

intentAction = ACTION_GATT_DISCONNECTED;

mConnectionState = STATE_DISCONNECTED;

Logi(TAG, "Disconnected from GATT server");

broadcastUpdate(intentAction);

}

}

@Override

public void onServicesDiscovered(BluetoothGatt gatt, int status) {

if (status == BluetoothGattGATT_SUCCESS) {

broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);

} else {

Logw(TAG, "onServicesDiscovered received: " + status);

}

}

//从特征中读取数据

@Override

public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {

//Systemoutprintln("onCharacteristicRead");

if (status == BluetoothGattGATT_SUCCESS) {

broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);

}

}

//向特征中写入数据

@Override

public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {

//Systemoutprintln("--------write success----- status:" + status);

}

/

when connected successfully will callback this method this method can

dealwith send password or data analyze

当连接成功将回调该方法

/

@Override

public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {

broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);

if (characteristicgetValue() != null) {

//Systemoutprintln(characteristicgetStringValue(0));

}

//Systemoutprintln("--------onCharacteristicChanged-----");

}

@Override

public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {

//Systemoutprintln("onDescriptorWriteonDescriptorWrite = " + status + ", descriptor =" + descriptorgetUuid()toString());

UUID uuid = descriptorgetCharacteristic()getUuid();

if (uuidequals(UUIDfromString("0000cd01-0000-1000-8000-00805f9b34fb"))) {

broadcastUpdate(ACTION_CD01NOTIDIED);

} else if (uuidequals(UUIDfromString("0000cd02-0000-1000-8000-00805f9b34fb"))) {

broadcastUpdate(ACTION_CD02NOTIDIED);

} else if (uuidequals(UUIDfromString("0000cd03-0000-1000-8000-00805f9b34fb"))) {

broadcastUpdate(ACTION_CD03NOTIDIED);

} else if (uuidequals(UUIDfromString("0000cd04-0000-1000-8000-00805f9b34fb"))) {

broadcastUpdate(ACTION_CD04NOTIDIED);

}

}

@Override

public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {

//Systemoutprintln("rssi = " + rssi);

}

};

----------------------------------------------

//从特征中读取数据

@Override

public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {

//Systemoutprintln("onCharacteristicRead");

if (status == BluetoothGattGATT_SUCCESS) {

broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);

}

}

您是想用苹果手机的蓝牙来实现室内定位吗?现在是可以的,但是需要借助蓝牙ibeacon来实现。

蓝牙定位基于RSSI(Received Signal Strength Indication,信号场强指示)定位原理。一套完整的终端侧蓝牙定位系统是由已嵌入或下载好SDK软件包的智能终端设备(安卓/iOS手机、平板电脑等)和蓝牙beacon设备组成。

当终端设备进入Beacon设备信号覆盖的范围,测出其在不同信标(不同ID号的Beacon硬件设备)下的RSSI值,然后再通过手机内置的定位算法测算出具体位置(一般至少需要3个信标点的RSSI)。

移动终端设备通过下载到手机的定位算法和地图,以及和后台地图引擎数据库的交互,就可以再终端设备的地图上标记出当前位置。

在需要定位的室内环境内布局蓝牙Beacon,至少要3个,蓝牙beacon开始广播数据包,广播间隔时间可以根据实际需求设置!

具体布局思路如下:水平间距控制在5-10m,部署要尽量均匀、竖直高度控制在3m左右;

6

适用场景:商超、景点、停车场定位导航(反向寻车)、医院、养老院、展会、机场火车站、展馆博物馆等。

inquiry_mode_standard:应该是根据搜索到的蓝牙设备的时间顺序来统计设备数量名字等等;

inquiry_mode_rssi:AT命令写得很清楚了,根据搜索到蓝牙设备的信号强度RSSI来排序统计;

inquiry_mode_eir:(eir)Enhanced Inquiry Response 增强的查询响应 (参考蓝牙核心规范v21+EDR人机交互部分),这个没用过,我猜想是不是根据人机交互的方便性排序统计。

看你需要使用呗,你需要按照什么要求来查找蓝牙设备就选哪个呗

以上就是关于大学生蓝牙科技论文全部的内容,包括:大学生蓝牙科技论文、iOS蓝牙开发实战、怎么搭建简易蓝牙定位系统等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9789121.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-02
下一篇2023-05-02

发表评论

登录后才能评论

评论列表(0条)

    保存