Trợ giúp với hoặc gợi ý để giải mã giao thức IR


10

Cách đây một thời gian, tôi đã mua một máy bay trực thăng đồ chơi điều khiển IR nhỏ đơn giản và rẻ tiền (giống như cái này - nó được gọi là "Diamond Gyro" hoặc "Diamond Force"). Để giải trí, tôi đã xem xét việc điều khiển nó thông qua Arduino.

Cập nhật: Đã tìm ra giao thức; xem câu trả lời

Những người khác đã chia sẻ kết quả của họ về việc hack một máy bay trực thăng đồ chơi IR khác và giải mã giao thức IR của nó. Thực sự tuyệt, nhưng thật không may máy bay trực thăng của tôi sử dụng một giao thức khác. Một cái mà tôi không thể tìm ra. (Tôi nên thêm rằng điện tử hoàn toàn là một sở thích đôi khi đối với tôi, vì vậy tôi có thể đã bỏ qua một cái gì đó rõ ràng).

Giống như trong liên kết thứ 2 ở trên, tôi tách bộ điều khiển ra, đặt chân IC điều khiển đèn LED (nhân tiện, các dấu của IC đã bị xóa) và nối một bộ phân tích logic.

Có nhiều dữ liệu tốt, nhưng tôi vẫn không thể tìm ra giao thức. Trang web này là một tài nguyên tuyệt vời, nhưng không có giao thức nào được liệt kê có vẻ phù hợp. Và không có gì khác tôi thấy dường như phù hợp với tín hiệu tôi đã bắt được. Tuy nhiên, tôi phải tưởng tượng rằng đó là một giao thức đơn giản, sẵn có, chỉ vì nó là một món đồ chơi nhỏ rẻ tiền.

Vì vậy, tôi đánh giá cao bất kỳ ý tưởng bạn có thể có. Có lẽ tôi chỉ nhìn nhầm thôi.
(Thêm thông tin bên dưới hình ảnh)

Các mẫu từ kênh A

Đặc điểm tín hiệu / giao thức

Tôi đã bắt được điều này ở 16 MHz với bộ điều khiển được đặt thành kênh A; nên chính xác, đúng lúc (Có 3 kênh IR bạn có thể chọn, nhưng sử dụng hai kênh khác không thay đổi các đặc điểm, chỉ một phần của gói.) Thời gian rất phù hợp (+/- 10 tối đa). Các gói được lặp đi lặp lại với các khoảng thời gian khác nhau nhưng tối thiểu chúng cách nhau khoảng 100ms.

Nhà cung cấp: 38kHz @ 50% chu kỳ thuế

Mức thấp:
- Ngắn: 285 Bước chân
- Dài: 795 Bước

Cao:
- Ngắn: 275 Lời
- Dài: 855 Điên

Luôn luôn 17 mức cao cho mỗi gói.

Điều khiển / đầu vào

Các heli có 3 điều khiển: "Van tiết lưu" (tức là tốc độ nâng / rôto), cao độ (tiến / lùi) và ngáp (xoay quanh trục rôto) đều được điều khiển bằng 2 ngón tay cái. Tất cả chúng đều có một số loại phạm vi (không chỉ bật / tắt) và, theo như tôi có thể nói, tất cả đều được truyền trong một gói duy nhất. Các đầu vào trái / phải chỉ được gửi nếu có thứ gì khác đang được gửi, vì vậy tôi đã áp dụng bướm ga tối đa khi lấy mẫu đó. Đầu vào ga và cường độ trên các gói kích hoạt của chính nó được gửi, ngay khi bạn đẩy ngón tay cái vượt qua ngưỡng / ngưỡng chết (trong biểu đồ bên dưới nhãn "min" là dành cho gói đầu tiên được gửi khi từ từ đẩy điều khiển qua dải chết của nó).

Nó cũng có các nút để cắt trái & phải, vì heli không phải là một công cụ chính xác (hoàn toàn ) và có xu hướng quay chậm. Rất tiếc, các nút cắt trái / phải dường như không gửi tín hiệu tăng / giảm thứ gì đó cho mỗi lần nhấn (sẽ rất hữu ích cho việc tìm ra giao thức); nó dường như chỉ là một mệnh lệnh duy nhất, bảo máy bay trực thăng cắt trái / phải, và sau đó nó theo dõi nó.


Tại sao không chỉ sử dụng dấu vết tín hiệu mà bạn đã phải ghi ra các gói dữ liệu thô?
Ignacio Vazquez-Abrams

@ IgnacioVazquez-Abrams Bạn có nghĩa là chỉ phát lại các tín hiệu được ghi lại cho máy bay trực thăng?
Flambino

Chắc chắn rồi. Không giống như máy bay trực thăng sẽ có thể nói lên sự khác biệt ...
Ignacio Vazquez-Abrams

@ IgnacioVazquez-Abrams Đúng nhưng theo như tôi có thể nói, gói chứa tất cả 3 điều khiển (bướm ga / cao độ / ngáp) trong khi điều khiển của heli, không có gì chỉ bật / tắt. Để điều khiển mọi thứ bằng cách phát lại, tôi phải nắm bắt mọi cấu hình đơn lẻ ... Bên cạnh đó tôi muốn hiểu giao thức
Flambino

@ IgnacioVazquez-Abrams Rất tiếc, bằng cách nào đó tôi đã cắt xén bình luận cuối cùng của mình. Có nghĩa là: "... gói chứa tất cả 3 điều khiển (bướm ga / cao độ / ngáp) và không có cái nào trong số chúng chỉ bật / tắt".
Flambino

Câu trả lời:


8

Tôi có quyền tự do trả lời câu hỏi của chính mình khi tôi hiểu được hầu hết câu hỏi và đây là một cách tốt để chia sẻ những phát hiện của tôi. Tôi cảm ơn Olin Lathrop đã cho tôi một nơi để bắt đầu và một số ý tưởng để thử, nhưng cuối cùng, giao thức hóa ra hoàn toàn khác với dự đoán của Olin, do đó tôi đăng câu trả lời này.


Cập nhật: Tôi đã đăng một câu hỏi tiếp theo liên quan đến 8 bit cuối cùng mà tôi không hiểu hết và Dave Tweed đã tìm ra nó . Tôi sẽ bao gồm các chi tiết ở đây, vì vậy câu trả lời này có thể hoạt động như thông số giao thức đầy đủ, nhưng hãy kiểm tra câu trả lời của Dave.


Tôi đã phải thử một số thứ khác nhau để tìm ra điều này, nhưng tôi khá tự tin rằng tôi đã nhận được nó. Điều kỳ lạ là tôi không tìm thấy bất cứ thứ gì giống với giao thức này ở nơi khác, nhưng nó rất có thể là một giao thức phổ biến mà tôi không biết về nó.

Dù sao, đây là những gì tôi đã tìm thấy:

Giao thức / mã hóa

Cả hai xung và khoảng trắng ở giữa được sử dụng để mã hóa dữ liệu. Xung / không gian dài là nhị phân một (1) và xung ngắn / không gian là nhị phân 0 (0). Các xung được gửi bằng cách sử dụng điều chế 38kHz hồng ngoại tiêu chuẩn @ 50% chu kỳ nhiệm vụ.

Thời gian xung / không gian nằm trong câu hỏi ban đầu, nhưng tôi sẽ lặp lại chúng ở đây cho đầy đủ:

 Bit    Pulse     Space
-----+---------+---------
  0  |  275µs  |  285µs
  1  |  855µs  |  795µs

Tất cả các kiểu chữ tối đa ± 10,, 5 chữ 5 .. Điều này dựa trên các mẫu được chụp bằng bộ phân tích logic ở 16 MHz; Tôi không có máy hiện sóng, vì vậy tôi không biết hồ sơ chính xác (tức là thời gian tăng / giảm).

Các gói được lặp lại miễn là các đầu vào điều khiển được áp dụng và dường như được đặt cách nhau tối thiểu 100ms.

Truyền gói bắt đầu với phần mở đầu "xung 1", được cố định và không phải là một phần của dữ liệu. Không gian sau mã hóa bit dữ liệu đầu tiên của gói và xung cuối cùng mã hóa bit cuối cùng.

Mỗi gói dài 32 bit và chứa mọi đầu vào mà điều khiển từ xa có thể cung cấp. Các giá trị được đọc dưới dạng endian nhỏ, tức là MSB đầu tiên.

Cấu trúc dữ liệu

Dưới đây là cấu trúc cơ bản của các gói riêng lẻ. 8 bit cuối cùng đã làm tôi bối rối, nhưng điều đó đã được tìm ra ngay bây giờ (xem bên dưới).

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2
--+---------------------------+-----------+---+-------+-----------
 P|    Yaw    |   Throttle    |   Pitch   | T | Chan. |   Check

P: Preamble (always a pulse-1), T: Trim, Chan.: Channel

Bit    Length    Description (see note below)
-----------------------------------------------
0      1         Preamble. High 1
1-6    6         Yaw. Range 0-36 for left-right, 17 being neutral
7-14   8         Throttle. Range 0-134
15-20  6         Pitch. Range 0-38 for forward-back, 17 being neutral
21-22  2         Trim. Left = 1, right = 2, no trim = 0
23-26  4         Channel. A = 5, B = 2, C = 8
27-32  6         Check bits

Lưu ý: Phạm vi dựa trên các bài đọc cao nhất tôi nhận được. Giao thức có khả năng phạm vi lớn hơn - lên tới 255 cho van tiết lưu, 63 cho cao độ / ngáp - nhưng giới hạn ở khoảng một nửa.
Giá trị cao độ dường như có một dải chết từ 14-21 (đã bao gồm); chỉ các giá trị trên hoặc dưới thực sự làm cho máy bay trực thăng phản ứng. Tôi không biết nó có giống với cái ngáp không (khó nói, vì dù sao máy bay trực thăng không ổn định, và có thể chỉ tự xoay nhẹ).

Đây là về mặt đồ họa (so sánh với đồ họa trong câu hỏi ban đầu)

cấu trúc gói

6 bit kiểm tra được tính bằng cách XOR tất cả các giá trị trước đó. Mỗi giá trị được coi là 6 bit. Điều này có nghĩa là 2 MSB của giá trị bướm ga 8 bit chỉ đơn giản là bị bỏ qua. I E

check = yaw ^ (throttle & 0x3F) ^ pitch ^ trim ^ channel

Ghi chú thực tế

Thời gian tín hiệu và điều chế không cần phải siêu chính xác. Ngay cả thời gian không chính xác của Arduino của tôi cũng hoạt động tốt mặc dù điều chế tinh ranh và một chút nhấn và bỏ lỡ thời lượng xung / không gian so với điều khiển từ xa thực sự.

Tôi tin rằng - nhưng chưa được thử nghiệm - rằng máy bay trực thăng sẽ đơn giản bám vào kênh tín hiệu đầu tiên mà nó tìm thấy. Nếu nó rời đi mà không có tín hiệu quá lâu (vài giây), nó dường như quay trở lại chế độ "tìm kiếm", cho đến khi nhận được tín hiệu một lần nữa.

Máy bay trực thăng sẽ bỏ qua các giá trị cao độ và ngáp nếu bướm ga bằng không.

Các lệnh trim chỉ được gửi một lần cho mỗi lần nhấn nút trên điều khiển từ xa. Có lẽ giá trị cắt chỉ đơn giản là tăng / giảm một giá trị trong bộ điều khiển riêng của máy bay trực thăng; Đó không phải là thứ mà điều khiển từ xa theo dõi. Vì vậy, bất kỳ việc thực hiện nào có lẽ phải tuân theo sơ đồ đó và chỉ gửi giá trị cắt trái / phải thường xuyên, nhưng nếu không thì mặc định là giá trị cắt không trong các gói.

Tôi khuyên bạn nên có một công tắc tiêu diệt mà chỉ cần đặt ga là 0. Điều này sẽ khiến máy bay trực thăng rơi khỏi bầu trời, nhưng nó sẽ chịu ít thiệt hại hơn khi nó không quay động cơ. Vì vậy, nếu bạn sắp gặp sự cố hoặc đâm vào vật gì đó, hãy nhấn nút tắt để tránh tước bánh răng hoặc làm gãy lưỡi dao.

Đèn LED hồng ngoại của điều khiển từ xa ban đầu dường như có bước sóng> 900nm, nhưng tôi không gặp vấn đề gì khi sử dụng đèn LED ~ 850nm.

Máy thu hồng ngoại của máy bay trực thăng vẫn ổn, nhưng không siêu nhạy, do đó nguồn IR của bạn càng sáng thì càng tốt. Điều khiển từ xa sử dụng 3 đèn LED nối tiếp, ngồi trên đường ray 9V thay vì đường ray 5V được sử dụng bởi logic. Không kiểm tra chính xác mức rút hiện tại của họ, nhưng tôi muốn đặt cược là 50mA.

Dữ liệu mẫu

Dưới đây là một loạt các gói, cho bất kỳ ai quan tâm (vâng, tôi đã viết mã bộ giải mã; tôi không giải mã được tất cả những thứ này). Kênh A gói đến từ cùng một hình chụp với đồ thị trong câu hỏi ban đầu.

Channel A                                                       
Yaw     Throttle  Pitch   Tr  Chan  Check     Description
-----------------------------------------------------------
000100  10000100  000000  00  0101  000101    Left Mid + Throttle
000000  10000110  010001  00  0101  010010    Left Max + Throttle 
100001  10000110  000000  00  0101  100010    Right Mid + Throttle 
100100  10000100  010001  00  0101  110100    Right Max + Throttle
010001  00000000  001011  00  0101  011111    Forward Min 
010001  00000000  000000  00  0101  010100    Forward Max 
010001  00000000  011000  00  0101  001100    Back Min 
010001  00000000  100101  00  0101  110001    Back Max
010001  00000000  010001  01  0101  010101    Left Trim 
010001  00000000  010001  10  0101  100101    Right Trim 
010001  00000011  010001  00  0101  000110    Throttle 01 (min)
010001  00010110  010001  00  0101  010011    Throttle 02
010001  00011111  010001  00  0101  011010    Throttle 03
010001  00101111  010001  00  0101  101010    Throttle 04
010001  00111110  010001  00  0101  111011    Throttle 05
010001  01010101  010001  00  0101  010000    Throttle 06
010001  01011111  010001  00  0101  011010    Throttle 07
010001  01101100  010001  00  0101  101001    Throttle 08
010001  01111010  010001  00  0101  111111    Throttle 09
010001  10000101  010001  00  0101  000000    Throttle 10 (max)

Channel B
Yaw     Throttle  Pitch   Tr  Chan  Check     Description
-----------------------------------------------------------
000000  10000110  010001  00  0010  010101    Left Max + Throttle 
100100  10000110  010001  00  0010  110001    Right Max + Throttle 
010001  00000000  001001  00  0010  011010    Forward Min 
010001  00000000  000000  00  0010  010011    Forward Max 
010001  00000000  010111  00  0010  000100    Back Min 
010001  00000000  100110  00  0010  110101    Back Max
010001  00000000  010001  01  0010  010010    Left Trim 
010001  00000000  010001  10  0010  100010    Right Trim 
010001  00000001  010001  00  0010  000011    Throttle Min 
010001  00110100  010001  00  0010  110110    Throttle Mid 
010001  01100111  010001  00  0010  100101    Throttle High 
010001  10001111  010001  00  0010  001101    Throttle Max 

Channel C
Yaw     Throttle  Pitch   Tr  Chan  Check     Description
-----------------------------------------------------------
000000  10000101  010001  00  1000  011100    Left Max + Throttle 
100100  10000101  010001  00  1000  111000    Right Max + Throttle 
010001  00000000  001010  00  1000  010011    Forward Min 
010001  00000000  000000  00  1000  011001    Forward Max 
010001  00000000  010111  00  1000  001110    Back Min 
010001  00000000  100110  00  1000  111111    Back Max
010001  00000000  010001  01  1000  011000    Left Trim 
010001  00000000  010001  10  1000  101000    Right Trim 
010001  00000001  010001  00  1000  001001    Throttle Min 
010001  00110100  010001  00  1000  111100    Throttle Mid 
010001  01100110  010001  00  1000  101110    Throttle High 
010001  10000101  010001  00  1000  001101    Throttle Max

Như đã đề cập ở trên, 8 bit cuối cùng đã được tìm ra, nhưng chỉ cho hậu thế, đây là những suy nghĩ ban đầu của tôi. Hãy bỏ qua nó hoàn toàn, vì tôi đã sai khá nhiều trong dự đoán của mình.

8 bit cuối cùng

8 bit cuối cùng của gói vẫn còn một chút bí ẩn.

Tất cả 4 bit từ bit 23 đến 26 dường như được xác định hoàn toàn bởi cài đặt kênh của điều khiển từ xa. Thay đổi kênh trên điều khiển từ xa không làm thay đổi giao thức hoặc điều chế theo bất kỳ cách nào; nó chỉ thay đổi 4 bit đó.

Nhưng 4 bit là gấp đôi những gì thực sự cần thiết để mã hóa cài đặt kênh; chỉ có ba kênh, vì vậy 2 bit là nhiều. Do đó, trong phần mô tả cấu trúc ở trên, tôi chỉ gắn nhãn 2 bit đầu tiên là "Kênh" và để lại hai phần còn lại được gắn nhãn là "X", nhưng đây là một phỏng đoán.

Dưới đây là mẫu các bit có liên quan cho từng cài đặt kênh.

Chan.   Bits 23-26
-----+-------------
  A  |  0  1  0  1
  B  |  0  0  1  0
  C  |  1  0  0  0

Về cơ bản, có nhiều hơn 2 bit cần thiết để truyền cài đặt kênh. Có thể giao thức có 4 bit được đặt sang một bên để cho phép nhiều kênh hơn sau đó, hoặc vì vậy giao thức có thể được sử dụng trong các đồ chơi hoàn toàn khác nhau, nhưng tôi đơn giản là không biết. Đối với các giá trị lớn hơn, giao thức không sử dụng các bit thừa có thể bị bỏ sót (yaw / thr ga / pitch có thể nhận được với ít hơn một chút), nhưng đối với trim - cũng có 3 trạng thái - chỉ sử dụng 2 bit. Vì vậy, người ta có thể nghi ngờ rằng kênh cũng chỉ là 2 bit, nhưng điều đó khiến cho 2 phần tiếp theo không được tính.

Khả năng khác là tổng kiểm tra của gói dài 8 bit, bắt đầu bằng "bit X" và - thông qua ma thuật kiểm tra - chúng chỉ xảy ra bằng cách nào đó luôn phản ánh cài đặt kênh. Nhưng một lần nữa: tôi không biết.

Và nói về: Tôi không biết làm thế nào những bit kiểm tra được hình thành. Ý tôi là, chúng các bit kiểm tra, vì chúng không tương ứng với bất kỳ đầu vào điều khiển nào và máy bay trực thăng dường như không phản hồi nếu tôi mân mê chúng. Tôi đoán đó là một loại CRC nào đó, nhưng tôi không thể tìm ra nó. Việc kiểm tra dài 6-8 bit, tùy thuộc vào cách bạn diễn giải "bit X", do đó, có rất nhiều cách có thể được đặt cùng nhau.


6

Điều này trông không tệ lắm. Đầu tiên lưu ý rằng tất cả các tin nhắn chứa chính xác 17 xung. Điều này ngay lập tức cho chúng ta một manh mối mạnh mẽ rằng các khoảng trống ngắn trong một tin nhắn là không liên quan. Dường như dữ liệu được mã hóa bởi các xung là ngắn hoặc dài và một số khoảng cách giữa các xung này là chấp nhận được.

Rõ ràng, mọi thông điệp đều bắt đầu bằng một xung dài như một bit start. Điều đó để lại 16 bit dữ liệu. Có lẽ một vài bit đầu là opcode, có thể có độ dài thay đổi. Nếu tôi đang làm điều này, một vài bit kết thúc sẽ là một tổng kiểm tra. Hình các kỹ sư đã viết phần sụn muốn giữ mọi thứ đơn giản cho chính họ, vì vậy bạn có thể bắt đầu bằng cách giả sử có 8 bit dữ liệu ở đó ở đâu đó. Bây giờ xem nếu bất kỳ thông điệp có ý nghĩa.

Chúng ta hãy gọi dài 1 và ngắn 0. Nó có thể là cách khác, nhưng chúng ta phải bắt đầu ở đâu đó. Tước lá bit bắt đầu:

1010001101011010 phút ga
1010011101011000 ga tối đa
1010000001011111 phút trước
1010000000011110 tối đa chuyển tiếp
Tối đa 1010000011011101
1010000100011010 phút trở lại
0000010101011100 max trái + ga tối đa
0100010101011110 max phải + ga tối đa
1010000101111111 cắt trái
1010000101011011 cắt đúng

Một vài điều bật ra ngay lập tức. Rõ ràng bit 0 là bit chẵn lẻ. Mặt khác, dường như có trường 3 bit <15:13>, giá trị dữ liệu 8 bit <12: 5> và trường 4 bit khác <4: 1>.

Có vẻ như giá trị dữ liệu đang được gửi theo thứ tự từ thấp đến cao, vì vậy có lẽ sẽ hợp lý hơn khi diễn giải toàn bộ 16 bit được lật từ những gì tôi hiển thị.

Tôi không cảm thấy muốn dành nhiều thời gian hơn cho việc này, nhưng hy vọng điều này đã cho bạn một sự khởi đầu. Tôi sẽ tiến hành bằng cách viết lại danh sách ở trên với bit chẵn lẻ bị loại bỏ, toàn bộ số đã chuyển LSB sang MSB và mỗi trường giả định được hiển thị riêng biệt với một khoảng trắng giữa nó và trường tiếp giáp. Điều đó có thể cho phép nhiều hơn để bật ra ở bạn. Ngoài ra, hãy nhớ rằng chúng ta có thể có ý nghĩa 1/0 của mỗi bit ngược. Có lẽ viết ra bảng mới mỗi cách và xem nếu một cái gì đó có ý nghĩa hơn một cách.


Cảm ơn bạn, điều này là tuyệt vời! Tôi sẽ hiểu đúng về nó và xem những gì tôi tìm thấy. Sau khi xem xét các giao thức khác, tôi đã bắt đầu nghĩ rằng có thể các không gian là không liên quan, nhưng vì chúng có hai thời gian rất nhất quán, tôi không chắc lắm. Tôi hình dung họ sẽ thay đổi nhiều hơn nếu họ không quan trọng. Dù sao, tôi sẽ thử nó. Cảm ơn một lần nữa
Flambino

Huh ... theo như tôi có thể nói, không gian vấn đề. Tôi tập trung vào van tiết lưu và chụp thêm một số mẫu ở 10 vị trí bướm ga khác nhau. Không bao gồm không gian cho tôi không có con số có ý nghĩa bất kể tôi đã thực hiện chuyển đổi như thế nào. Nhưng bao gồm chúng dài = 1, short = 0 mang lại sự tiến triển thuận lợi của giá trị bướm ga từ 1 đến 134 (ít endian). Vẫn hoạt động trên các tham số khác
Flambino 23/12/13

Tôi đã có giao thức gần như hoàn toàn tìm ra, nhưng vẫn còn một chút bí ẩn. Đã thêm một tấn công cụ vào câu hỏi của tôi, nếu bạn muốn thay đổi nó. Dù sao, cảm ơn bạn đã giúp đỡ cho đến nay! Có tôi làm việc đúng hướng.
Flambino

@Flambino: Có vẻ như bạn đang đi trước những gì tôi đã bắt đầu, điều này hóa ra hầu hết là những dự đoán sai trong nhận thức muộn màng. Tôi đã đọc câu hỏi cập nhật của bạn nhưng vẫn không hiểu chính xác độ dài của khoảng trắng được sử dụng. Có phải chỉ là sự trùng hợp rằng tất cả các mẫu bạn đã hiển thị có chính xác 17 xung và lần cuối cùng xảy ra để biểu thị tính chẵn lẻ nếu chỉ các xung được lấy là 0 hoặc 1?
Olin Lathrop

Thành thật mà nói, phần lớn là bản dùng thử và lỗi. Vì 2 thời gian được sử dụng cho các không gian chính xác như thời gian xung, tôi cho rằng chúng có thể có ý nghĩa. Và, khi bỏ qua các khoảng trắng không mang lại dữ liệu nhị phân hữu ích, tôi chỉ giả sử xung dài = 1 không gian dài = 1 (và không gian ngắn / xung = 0), ngay lập tức cung cấp cho tôi dữ liệu rất hữu ích. Vì vậy, không gian đầu tiên sau xung mở đầu là bit đầu tiên (biểu đồ bướm ga max phải + tối đa hiển thị "khoảng trắng 1" là bit đầu tiên) theo sau là 16 xung, có thêm 15 khoảng trắng ở giữa; 32 bit.
Flambino
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.