資料介紹
描述
呼呼呼……圣誕老人來了!
每年平安夜圣誕老人都會踏上環(huán)游世界的旅程,為全世界的孩子們送出禮物。但是知道那天圣誕老人在哪里會很酷嗎?
MKR1000 圣誕老人追蹤器來救援!
您可能已經(jīng)知道我們可以從兩個地方獲取圣誕老人的位置信息,一個來自NORAD ,一個來自Google 。雖然 NORAD 是發(fā)起圣誕老人追蹤傳統(tǒng)的原始組織,但谷歌為圣誕老人追蹤提供了一個開發(fā)人員友好的(未記錄的)API 。使用此 API,您將能夠跟蹤實時圣誕老人信息,包括位置、到達和離開時間、在該位置發(fā)送的禮物,與在 Google 的圣誕老人跟蹤網(wǎng)站上相同。所以在這個項目中我選擇使用谷歌圣誕老人數(shù)據(jù)來實現(xiàn)我的圣誕老人追蹤器。
這個項目的想法很簡單:使用 LED 顯示圣誕老人去過的地方以及圣誕老人在世界地圖上的當前位置。這是我在項目結(jié)束時得到的:
系統(tǒng)架構(gòu)
總體而言,該設(shè)計使用一個樹莓派和一個 MKR1000 來處理和可視化從 Google Santa Tracker API 獲取的圣誕老人數(shù)據(jù)。

如您所見,從 Google Santa Tracker API 獲取的數(shù)據(jù)首先通過 Raspberry PI 放置。原因是 API 響應(yīng) JSON 大約為 20M,這太大而無法放入 MKR1000 的內(nèi)存(我的草圖加載后有 18M 可用)進行處理。所以我使用 Raspberry Pi 3 首先使用數(shù)據(jù),并生成一個更小的數(shù)據(jù)格式,這是為我的應(yīng)用程序量身定做的。之后的數(shù)據(jù)通過托管在 Raspberry Pi 上的 REST API 服務(wù)器公開。MKR1000 開發(fā)板將每 10 秒調(diào)用一次 REST API 以獲取當前圣誕老人的位置。
電路設(shè)計
MKR1000 連接到具有 30 個 WS2812B RGB NeoPixel LED 的定制 PCB。每個 LED 代表一個地理位置。這個想法是讓離圣誕老人當前位置最近的 LED 燈閃爍,然后打開圣誕老人過去所在位置的所有 LED 燈。
PCB 針對由 Othermill 生產(chǎn)的雙面 PCB 進行了優(yōu)化,但也應(yīng)該可以通過 OSH Park 等在線 PCB 服務(wù)輕松生產(chǎn)。
我在PCB上鋪了30個NeoPixels,形成了一張世界地圖。您可能現(xiàn)在看不到它,但是在涂上負片掩模和擴散器后,它會更容易識別。

使這種家庭銑削友好的主要考慮因素是通孔的位置。由于過孔是在 PCB 板上鉆的,因此兩側(cè)未連接。因此,您需要通過電線將它們的兩側(cè)焊接在一起。正因為如此,通孔不能像在商業(yè) PCB 中通常那樣放置在 SMT 組件下方。
PCB 文件背后有一些設(shè)計注意事項:
- 電源通過粗干線傳輸并下沉到另一根粗地線中。這是因為 30 個 NeoPixel 會消耗相當多的電流。
- NeoPixels 盡可能靠近主干電源線連接。這是為了減少多個 NeoPixel 之間的壓降。不同的電壓會導(dǎo)致亮度和顏色略有不同。
- 靠近電源連接一個 1000 uF 電容器。這是使用 NeoPixels的推薦最佳實踐。
- 過孔放置在其他 SMT 組件之外,因為它們將通過手動焊接兩側(cè)連接,焊點不會適合另一個 SMT 組件。這在商業(yè)服務(wù)生產(chǎn)的 PCB 上不是問題,但在家庭制作 PCM 時應(yīng)考慮在內(nèi)。
- 確保在電線之間留出足夠的空間。 焊接后很容易短路,因為自制的PCB沒有絕緣層。這可以在 Otherplan 應(yīng)用程序中通過將跡線間隙設(shè)置為比默認值 0.006 英寸更大的值(例如 0.06 英寸應(yīng)該足夠好)來完成。我發(fā)現(xiàn)我的第一塊完全焊接的電路板因為短路而無法正常工作,而且修復(fù)起來比制作另一塊電路板更難。
- 如果您要處理大量 SMT 組件,熱風返修站將為您節(jié)省大量焊接時間。雖然這是可行的,但真的不值得一個一個地手工焊接組件。熱風也會使組件自動對齊到準確的位置。

世界地圖面具和擴散器
因為 Othermill 可以直接從 SVG 進行銑削,所以我只使用從 wikimedia.org 找到的世界地圖。
我還創(chuàng)建了另一個包含鉆孔的鷹文件。這些孔用于將掩模安裝到電路板上。
因為我想獲得盡可能高的銑削精度,所以最好的方法是使用對齊支架。但是輪廓肯定會和括號重疊。我找到的解決方案是首先只切割地圖而不切割輪廓。然后在不告訴軟件的情況下取下支架。然后開始銑削以鉆孔并切割輪廓。該軟件將使用相同的刀具路徑在您想要的精確位置切割輪廓。

組裝非常簡單。我使用了 4 個 M3 尼龍長螺釘、4 個支架和 4 個螺母。

樹莓派預(yù)處理服務(wù)器
Google Santa Tracker API 的響應(yīng)是一個巨大的 JSON 文件。這對 MKR1000 來說可能是個問題,但對 Raspberry Pi 3 來說根本不是問題。所以我設(shè)置了一個 HTTP 服務(wù)器來預(yù)處理 JSON 文件并為 MKR1000 生成較小的數(shù)據(jù)。
Raspberry Pi 服務(wù)器還將位置直接映射到相應(yīng) LED 的索引,以進一步減少 MKR1000 上的計算。為此,我首先手動為每個 LED 分配一個坐標,然后計算圣誕老人路徑中的每個位置與 LED 坐標之間的距離,找到最近的 LED 來表示該位置。
服務(wù)器是用 Python 編寫的,并使用 Flask 網(wǎng)絡(luò)框架將 REST 端點公開給 MKR1000。
from flask import Flask
import requests
import json
import math
import sys
app = Flask(__name__)
# Google's Santa API. Only updates on Dec 24.
# santa_api_url = 'https://santa-api.appspot.com/info?client=web&language=en&fingerprint=&routeOffset=0&streamOffset=0'
# My Fake Santa API.
santa_api_url = 'http://localhost:1224/info'
# LEDs metadata.
leds = [
{'name': 'North Pole', 'location': {'lat': 90.0, 'lng': 30.0}},
{'name': 'Alaska (US)', 'location': {'lat': 64.536117, 'lng': -151.258768}},
{'name': 'Alberta (Canada)', 'location': {'lat': 48.9202307, 'lng': -93.69738}},
{'name': 'Ontario (Canada)', 'location': {'lat': 50.956252, 'lng': -87.369255}},
{'name': 'Utah (US)', 'location': {'lat': 40.7765868, 'lng': -111.9905244}},
{'name': 'Tennessee (US)', 'location': {'lat': 36.1865589, 'lng': -86.9253274}},
{'name': 'Mexico City (Mexico)', 'location': {'lat': 19.39068, 'lng': -99.2836957}},
{'name': 'Bogota (Columbia)', 'location': {'lat': 4.6482837, 'lng': -74.2478905}},
{'name': 'Brasilia (Brazil)', 'location': {'lat': -15.721751, 'lng': -48.0082759}},
{'name': 'Santiago (Chile)', 'location': {'lat': -33.4727092, 'lng': -70.7699135}},
{'name': 'Greenland', 'location': {'lat': 70.8836652, 'lng': -59.6665893}},
{'name': 'UK', 'location': {'lat': 64.6748061, 'lng': -7.9869018}},
{'name': 'Spain', 'location': {'lat': 40.4379332, 'lng': -3.749576}},
{'name': 'Mali', 'location': {'lat': 17.5237416, 'lng': -8.4791157}},
{'name': 'Finland', 'location': {'lat': 64.6479136, 'lng': 17.1440256}},
{'name': 'Greece', 'location': {'lat': 38.2540419, 'lng': 21.56707}},
{'name': 'Libya', 'location': {'lat': 21.520733, 'lng': 23.237173}},
{'name': 'Central African Republic', 'location': {'lat': 6.2540984, 'lng': -0.2809593}},
{'name': 'Botswana', 'location': {'lat': -22.327399, 'lng': 22.4437318}},
{'name': 'Saudi Arabia', 'location': {'lat': 24.0593214, 'lng': 40.6158589}},
{'name': 'Turkmenistan', 'location': {'lat': 38.9423384, 'lng': 57.3349508}},
{'name': 'Xinjiang (China)', 'location': {'lat': 42.0304225, 'lng': 77.3185349}},
{'name': 'India', 'location': {'lat': 20.8925986, 'lng': 73.7613366}},
{'name': 'Henan (China)', 'location': {'lat': 33.8541479, 'lng': 111.2634555}},
{'name': 'Cambodia', 'location': {'lat': 12.2978202, 'lng': 103.8594626}},
{'name': 'Japan', 'location': {'lat': 34.452585, 'lng': 125.382845}},
{'name': 'Australia', 'location': {'lat': -25.0340388, 'lng': 115.2378468}},
{'name': 'New Zealand', 'location': {'lat': -43.0225411, 'lng': 163.4767905}},
{'name': 'South Pole', 'location': {'lat': -90.0, 'lng': 30.0}},
]
@app.route('/santa')
def santa():
santa_info = requests.get(santa_api_url).json()
santa_time = santa_info['now']
response = []
for dest_json in santa_info['destinations']:
if santa_time < dest_json['arrival']:
break
dist, led, led_index = closest_led(dest_json['location'])
response.append({
'i': led_index,
'd': int(dist),
'n': dest_json['city'],
'p': dest_json['presentsDelivered']
})
return app.response_class(json.dumps(response).replace(' ',''), content_type='application/json')
def distance(loc1, loc2, unit='M'):
lat1 = loc1['lat']
lng1 = loc1['lng']
lat2 = loc2['lat']
lng2 = loc2['lng']
radlat1 = math.pi * lat1 / 180
radlat2 = math.pi * lat2 / 180
theta = lng1-lng2
radtheta = math.pi * theta / 180
dist = (math.sin(radlat1) * math.sin(radlat2) +
math.cos(radlat1) * math.cos(radlat2) * math.cos(radtheta));
dist = math.acos(dist)
dist = dist * 180 / math.pi
dist = dist * 60 * 1.1515
if unit == 'K':
return dist * 1.609344
if unit == 'N':
return dist * 0.8684
return dist
def closest_led(loc):
min_dist = sys.float_info.max
min_led = None
min_index = 0
for index, led in enumerate(leds):
led_loc = led['location']
dist = distance(loc, led_loc)
if dist < min_dist:
min_dist = dist
min_led = led
min_index = index
return min_dist, min_led, min_index
if __name__ == '__main__':
app.run(host='0.0.0.0', port=2412)
由于 Google Santa Tracker API 一年中只有一天(12 月 24 日)更新,為了測試整個系統(tǒng),我還編寫了一個模擬真實圣誕老人追蹤器 API 服務(wù)器的假圣誕老人追蹤器 API 服務(wù)器。有了這個假的 API 服務(wù)器,我還可以控制行進速度并根據(jù)需要重置。該服務(wù)器也是一個 Flask Python 服務(wù)器,在 Raspberry Pi 3 的不同端口上運行。
from flask import Flask, request
import json
import time
app = Flask(__name__)
fake_start_time = 0 # initialized to first arrival time from json
real_start_time = 0 # set to start time
speed_factor = 100 # fake clock speed
all_destinations = None
current_info = {
'status': 'OK',
'language': 'en',
'now': None, # Will be set to fake time
'timeOffset': 120000,
'fingerprint': '3b8835bc354c6d5018344b289b833402f7079844',
'refresh': 51449,
'switchOff': False,
'clientSpecific': {
'DisableEarth': False,
'DisableTracker': False,
'DisableWikipedia': False,
'DisablePhotos': False,
'HighResolutionPhotos': False,
'EarthAltitudeMultiplier': 1
},
'routeOffset': 0,
'destinations': None # Will only have destinations up to two towns ahead
}
@app.route('/info')
def info():
if real_start_time != 0:
advance_fake_time()
return app.response_class(json.dumps(current_info), content_type='application/json')
@app.route('/start')
def start():
global real_start_time, speed_factor
real_start_time = real_now()
speed_factor = int(request.args.get('speed', '100'))
print(u'fake clock stated at speed {0}'.format(speed_factor))
return 'ok'
@app.route('/reset')
def reset():
global real_start_time
real_start_time = 0
current_info['destinations'] = all_destinations[:3]
return 'ok'
def index_of_current_destination(ts):
for i, dest in enumerate(all_destinations):
if dest['departure'] > ts:
return i
return 0
def current_destinations():
index = index_of_current_destination(fake_now()) + 3
return all_destinations[:index]
def advance_fake_time():
current_info['now'] = fake_now()
current_info['destinations'] = current_destinations()
def real_now():
return int(time.time() * 100)
def fake_now():
return (real_now() - real_start_time) * speed_factor + fake_start_time
def arrival(d):
return d['arrival']
def load_json():
with open('santa2016.json') as data_file:
data = json.load(data_file)
global all_destinations, fake_start_time
all_destinations = sorted(data['destinations'], key=arrival)
fake_start_time = all_destinations[1]['arrival']
reset()
print(u'{0} destinations loaded, fake_start_time={1}'.format(len(all_destinations), fake_start_time))
if __name__ == '__main__':
load_json()
app.run(host='0.0.0.0', port=1224)
MKR1000 固件
現(xiàn)在 MKR1000 已準備好從 Raspberry Pi 服務(wù)器獲取數(shù)據(jù),并打開和關(guān)閉 LED。
#include
#include
#include
#include "JsonStreamingParser.h"
#include "JsonListener.h"
#define LED_PIN 6
#define LED_NUM 30
#define BRIGHTNESS 50
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LED_NUM, LED_PIN, NEO_GRB + NEO_KHZ800);
char ssid[] = "YOUR_SSID"; // your network SSID (name)
char pass[] = "YOUR_PWRD"; // your network password
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
IPAddress server(192, 168, 1, 120); // numeric IP for RPI server
//char server[] = "rpi3.local"; // name address for RPI server
char endpoint[] = "/santa";
int port = 2412;
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
WiFiClient client;
class Led {
public:
String name;
int distance;
int presents;
boolean on;
};
Led leds[30];
class LedSwitcher: public JsonListener {
public:
void whitespace(char c) {}
void startDocument() {}
void key(String key) {
Serial.println(key);
currentKey = key;
}
void value(String value) {
Serial.println(value);
if (currentKey == "i") {
ledIndex = value.toInt();
} else if (currentKey == "p") {
presents = value.toInt();
} else if (currentKey == "d") {
distance = value.toInt();
} else {
name = value;
}
}
void endArray() {}
void endObject() {
Serial.println("End of Object");
Serial.print(ledIndex);
Serial.print(":");
Serial.print(name.c_str());
Serial.print(",");
Serial.print(presents);
Serial.print(",");
Serial.print(distance);
leds[ledIndex].on = true;
leds[ledIndex].name = name;
leds[ledIndex].presents = presents;
leds[ledIndex].distance = distance;
}
void endDocument() {}
void startArray() {}
void startObject() {}
int lastLed() {
return ledIndex;
}
private:
String currentKey;
int ledIndex;
int presents;
int distance;
String name;
};
LedSwitcher ledSwitcher;
void connectToWifi() {
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while (true);
}
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Connected to wifi");
printWifiStatus();
}
boolean connectToSantaServer() {
Serial.println("Starting connection to server...");
return client.connect(server, port);
}
void ensureConnected() {
if (!client.connected()) {
while (!connectToSantaServer()) {
Serial.println("Failed to connect to server. Retry in 5 seconds");
delay(5000);
}
Serial.println("connected to server");
}
}
void fetchSantaInfo() {
ensureConnected();
// Make a HTTP request:
client.print("GET ");
client.print(endpoint);
client.println(" HTTP/1.1");
client.print("Host: ");
client.println(server);
client.println("Connection: close");
client.println();
int bytes = 0;
boolean isBody = false;
JsonStreamingParser parser;
parser.setListener(&ledSwitcher);
Serial.println();
Serial.println("Received response:");
Serial.println();
while (client.connected()) {
while (client.available()) {
char c = client.read();
++bytes;
//Serial.write(c);
if (isBody || c == '[') {
isBody = true;
parser.parse(c);
}
}
}
Serial.println();
Serial.println();
Serial.println("Disconnecting from server.");
client.stop();
Serial.print("Received: ");
Serial.print(bytes);
Serial.println(" Bytes.");
}
void flashLastLed() {
strip.setPixelColor(ledSwitcher.lastLed(), strip.Color(0, 0, 0));
strip.show();
delay(500);
strip.setPixelColor(ledSwitcher.lastLed(), strip.Color(255, 0, 0));
strip.show();
delay(500);
}
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
strip.setBrightness(BRIGHTNESS);
strip.begin();
strip.show(); // Initialize all pixels to 'off'.
connectToWifi();
fetchSantaInfo();
for (int i = 0; i < 30; ++i) {
if (leds[i].on) {
strip.setPixelColor(i, strip.Color(255, 0, 0));
} else {
strip.setPixelColor(i, strip.Color(0, 0, 0));
}
}
strip.show();
}
void loop() {
fetchSantaInfo();
delay(1000);
for (int i = 0; i < 10; ++i) {
flashLastLed();
}
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
由于大部分工作都是在 Raspberry Pi 上完成的,所以這里的代碼很簡單。它連接到 WiFi,每 10 秒從 Raspberry Pi 獲取圣誕老人數(shù)據(jù),并相應(yīng)地更新 NeoPixels。
現(xiàn)在讓我們啟動它:
結(jié)論
MKR1000 是一款非常強大的物聯(lián)網(wǎng)應(yīng)用板,但它也有其自身的局限性。借助更強大的 SBC(單板計算機),如 Raspberry Pi 3,我們將能夠與具有更復(fù)雜 API 的任何服務(wù)進行交互。
希望你喜歡這個項目作為一個小小的節(jié)日驚喜。
- 圣誕老人探測器開源分享
- 基于M5Stack的圣誕老人照相館 0次下載
- Arduino圣誕老人之路
- 使用M5StickC Plus進行M5Stack圣誕節(jié)的圣誕老人追蹤器
- Arduino在辦公室地圖上繪制汽車路線
- pcb制作的圣誕老人圣誕別針
- PCB圣誕老人的音序器徽章
- RC Tractor Guy的圣誕老人拖拉機
- 用PCB創(chuàng)建圣誕老人
- 帶領(lǐng)圣誕老人的PCB開發(fā)
- 紅色圣誕物聯(lián)網(wǎng)卡魯?shù)婪?/a>
- 基于LoRa無線射頻信號的行走追蹤系統(tǒng) 8次下載
- 分布式硬件輔助追蹤物聯(lián)網(wǎng)測試平臺HATBED 3次下載
- 物聯(lián)網(wǎng)是什么?現(xiàn)在物聯(lián)網(wǎng)通信標準和協(xié)議有哪些?物聯(lián)網(wǎng)應(yīng)用的概述
- 老人GPS定位監(jiān)護系統(tǒng)相關(guān)技術(shù)與功能介紹 13次下載
- LED圣誕燈電路圖 LED圣誕燈的工作原理和特點 1807次閱讀
- 物聯(lián)網(wǎng)的體系架構(gòu) 1438次閱讀
- 物聯(lián)網(wǎng)是什么和物聯(lián)網(wǎng)基本架構(gòu) 6087次閱讀
- cps物聯(lián)網(wǎng)技術(shù)的應(yīng)用案例 1.3w次閱讀
- 未來物聯(lián)網(wǎng)發(fā)展的方向有哪些 6501次閱讀
- 如何為物聯(lián)網(wǎng)打造神奇的無線世界 987次閱讀
- 如何利用物聯(lián)網(wǎng)技術(shù)來追蹤藥品 1760次閱讀
- 物聯(lián)網(wǎng)的關(guān)鍵技術(shù)你都掌握了嗎 1446次閱讀
- 6DOF追蹤的進化:從標識追蹤到SLAM定位,帶給AR體驗質(zhì)的飛越 9855次閱讀
- 物聯(lián)網(wǎng)安全隱患有哪些 物聯(lián)網(wǎng)安全如何防控 1.7w次閱讀
- 物聯(lián)網(wǎng)技術(shù)研究與應(yīng)用案例分析 1.5w次閱讀
- 高精地圖在無人駕駛領(lǐng)域的作用,高精地圖與普通導(dǎo)航地圖的區(qū)別 2.2w次閱讀
- 傳感器和物聯(lián)網(wǎng)的介紹和“極端物聯(lián)網(wǎng)”的詳細資料概述 3917次閱讀
- 互聯(lián)網(wǎng)、物聯(lián)網(wǎng)、車聯(lián)網(wǎng)這三者有密不可分的關(guān)系 并把整個世界趨于一體 2.4w次閱讀
- 應(yīng)對物聯(lián)網(wǎng)安全的五大對策 1194次閱讀
下載排行
本周
- 1山景DSP芯片AP8248A2數(shù)據(jù)手冊
- 1.06 MB | 532次下載 | 免費
- 2RK3399完整板原理圖(支持平板,盒子VR)
- 3.28 MB | 339次下載 | 免費
- 3TC358743XBG評估板參考手冊
- 1.36 MB | 330次下載 | 免費
- 4DFM軟件使用教程
- 0.84 MB | 295次下載 | 免費
- 5元宇宙深度解析—未來的未來-風口還是泡沫
- 6.40 MB | 227次下載 | 免費
- 6迪文DGUS開發(fā)指南
- 31.67 MB | 194次下載 | 免費
- 7元宇宙底層硬件系列報告
- 13.42 MB | 182次下載 | 免費
- 8FP5207XR-G1中文應(yīng)用手冊
- 1.09 MB | 178次下載 | 免費
本月
- 1OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費
- 2555集成電路應(yīng)用800例(新編版)
- 0.00 MB | 33566次下載 | 免費
- 3接口電路圖大全
- 未知 | 30323次下載 | 免費
- 4開關(guān)電源設(shè)計實例指南
- 未知 | 21549次下載 | 免費
- 5電氣工程師手冊免費下載(新編第二版pdf電子書)
- 0.00 MB | 15349次下載 | 免費
- 6數(shù)字電路基礎(chǔ)pdf(下載)
- 未知 | 13750次下載 | 免費
- 7電子制作實例集錦 下載
- 未知 | 8113次下載 | 免費
- 8《LED驅(qū)動電路設(shè)計》 溫德爾著
- 0.00 MB | 6656次下載 | 免費
總榜
- 1matlab軟件下載入口
- 未知 | 935054次下載 | 免費
- 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
- 78.1 MB | 537798次下載 | 免費
- 3MATLAB 7.1 下載 (含軟件介紹)
- 未知 | 420027次下載 | 免費
- 4OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費
- 5Altium DXP2002下載入口
- 未知 | 233046次下載 | 免費
- 6電路仿真軟件multisim 10.0免費下載
- 340992 | 191187次下載 | 免費
- 7十天學會AVR單片機與C語言視頻教程 下載
- 158M | 183279次下載 | 免費
- 8proe5.0野火版下載(中文版免費下載)
- 未知 | 138040次下載 | 免費
評論