Một số mẹo cho việc phát triển ứng dụng hệ thống nhúng
Bài viết được sự cho phép của tác giả Nguyễn Hồng Quân
Trong quá trình phát triển ứng dụng cho hệ thống nhúng, do sự hạn chế của thiết bị, đôi khi có những việc lắt nhắt làm tốn mớ thời gian. Sau đây mình liệt kê một số mẹo để đi tắt, giúp tiết kiệm thời gian cho công việc. Các hướng dẫn này chỉ dành cho hệ điều hành Linux (như Ubuntu).
1. Chia sẻ Internet từ laptop cho máy tính nhúng
Đây là tình huống mà bạn đang phát triển ứng dụng cho máy tính mini (NUC, Raspberry Pi, Beagle Bone…) và chủ yếu dùng mạng dây (chưa setup wifi hoặc máy đó không có card wifi). Đôi lúc bạn cần phải xách nó đi đâu đó (để trình diễn demo, để cài đặt lại chẳng hạn) mà chỗ đó không có router để cấp mạng, bạn có thể chia sẻ Internet từ laptop (laptop đang kết nối Internet qua wifi) cho nó. Để cho ngắn gọn, mình sẽ gọi máy tính nhúng là RPi trong bài này.
Nguyên lý của việc này là biến laptop của bạn thành một thiết bị router mạng đơn sơ, tạo một mạng con với RPi, do laptop của bạn quản lý.
Với Ubuntu 20.04+ thì việc này rất đơn giản. Sau khi dùng dây LAN nối giữa RPi với laptop, bạn chỉ việc mở phần mềm tên là “Settings”, tìm đến mục “Network”, bấm vào nút “chỉnh sửa” (có hình bánh răng) cho mạng dây (Wired):
Ở màn hình kế tiếp, chọn tab “IPv4” rồi chọn “Shared to other computers”.
Sau khi lưu lại cấu hình này, bấm vào tab “Details”, bạn sẽ thấy địa chỉ IP của laptop trong mạng con mới tạo này. Thông thường là 10.42.0.1
. Tuy nhiên, đó chỉ là địa chỉ của laptop, còn địa chỉ của RPi là gì, làm sao truy cập đến nó? Có các cách sau đây:
a) Dùng mDNS
Cách này áp dụng khi cả laptop và RPi của bạn đều đã cài đặt phần mềm avahi-daemon
và bạn nhớ tên hostname của RPi. Khi đó địa chỉ của RPi sẽ có dạng [hostname].local
, ví dụ raspberrypi.local
. Thử ping vào địa chỉ đó, bạn sẽ thấy RPi trả lời:
$ ping raspberrypi.local PING raspberrypi.local (10.42.0.95) 56(84) bytes of data. 64 bytes from 10.42.0.95 (10.42.0.95): icmp_seq=1 ttl=64 time=1.05 ms 64 bytes from 10.42.0.95 (10.42.0.95): icmp_seq=2 ttl=64 time=0.844 ms 64 bytes from 10.42.0.95 (10.42.0.95): icmp_seq=3 ttl=64 time=1.21 ms
Với mDNS thì thật ra bạn không cần dùng đến địa IP nữa, có thể dùng địa chỉ “*.local” này để truy cập bằng bất cứ phương thức nào, như SSH, FTP, HTTP:
b) Dùng nmap
để quét
Nếu lỡ quên cài avahi-daemon
cho RPi thì ta dùng nmap
để quét trong mạng con:
$ sudo nmap -sn 10.42.0.0/24 [sudo] password for quan: Starting Nmap 7.80 ( https://nmap.org ) at 2020-08-06 12:15 +07 Nmap scan report for 10.42.0.95 Host is up (0.0011s latency). MAC Address: B8:27:EB:D1:AB:91 (Raspberry Pi Foundation) Nmap scan report for Fossa (10.42.0.1) Host is up. Nmap done: 256 IP addresses (2 hosts up) scanned in 3.89 seconds
Địa chỉ của mạng con được xác định bằng cách thay số cuối của địa chỉ laptop bằng số 0 rồi gắn thêm /24
vào, ví dụ 10.42.0.1
-> 10.42.0.0/24
.
nmap
không được cài sẵn trong Ubuntu, bạn phải cài bằng cách:
sudo apt install nmap
c) Xem trong danh sách địa chỉ IP đã cấp
Tìm trong thư mục /var/lib/NetworkManager/ (cần quyền sudo
), coi có file nào có tên dạng dnsmasq-[ifname].leases
, ví dụ, vì card mạng của tôi có tên enp2s0
nên sẽ có file dnsmasq-enp2s0.leases. Mở nội dung file đó sẽ thấy địa chỉ nào được cấp cho RPi:
$ sudo cat /var/lib/NetworkManager/dnsmasq-enp2s0.leases 1596695111 b8:27:eb:d1:ab:91 10.42.0.95 raspberrypi 01:b8:27:eb:d1:ab:91
Giải thích thêm, NetworkManager
là chương trình quản lý mạng phổ biến trên hệ điều hành Linux dành cho desktop (và smartphone) (còn có các chương trình khác dành cho bối cảnh sử dụng khác). Khi dùng nó để tạo mạng con, nó sẽ gọi thêm một chương trình tên là dnsmasq
lên để đảm nhiệm chức năng DHCP server và DNS server cho mạng con đó.
Với một số phiên bản Ubuntu cũ hơn (khoảng 18.10 đến 19.10), bạn sẽ không thấy lựa chọn “Shared to other computers”. Đó chỉ là thiếu sót của giao diện “Settings”, bạn vẫn có thể cấu hình chia sẻ mạng trong một ứng dụng khác, tên là “Advanced Network Configuration”. Ứng dụng này có thể tìm thấy trong màn hình Dash (ấn phím Super/Windows để mở). Với Ubuntu 19.04 và 19.10 thì ứng dụng này bị giấu khỏi Dash, bạn phải mở bằng dòng lệnh:
nm-connection-editor
Sau khi mở “Advanced Network Configuration”, bạn có thể chọn để sửa một cấu hình mạng dây đang có, tương tự với chương trình “Settings” phía trên.
Mẹo nhỏ:
Để đưa “Advanced Network Configuration” trở lại màn hình Dash thì sửa file /usr/share/applications/nm-connection-editor.desktop và xóa dòng “NotShowIn=GNOME;
” đi.
[Desktop Entry] Name=Advanced Network Configuration Comment=Manage and change your network connection settings Icon=preferences-system-network Exec=nm-connection-editor Terminal=false StartupNotify=true Type=Application X-GNOME-Bugzilla-Bugzilla=GNOME X-GNOME-Bugzilla-Product=NetworkManager X-GNOME-Bugzilla-Component=nm-connection-editor Categories=GNOME;GTK;Settings;X-GNOME-NetworkSettings;X-GNOME-Utilities; NotShowIn=GNOME; # <~~ Xóa dòng này, hoặc comment lại. X-Ubuntu-Gettext-Domain=nm-applet
Xem embedded tuyển dụng đãi ngộ tốt trên TopDev
2. Tạo cổng serial ảo
Tình huống này có liên quan đến bài Áp dụng quy trình hiện đại khi làm phần mềm cho hệ thống nhúng. Đó là khi mình cần cho phần mềm server giao tiếp với một thiết bị kết nối qua cổng serial (bên Windows gọi là cổng COM). Như đã kể, trong khi phát triển ứng dụng IoT thì mình luôn viết phần mềm mô phỏng để thay mặt thiết bị, khi thiết bị chưa được chế tạo xong, chưa được viết code nhúng. Cả phần mềm server lẫn phần mềm mô phỏng cùng chạy trên PC mà lại cần giao tiếp qua cổng serial thì phải làm sao? Đó là lúc cần phải tạo một cổng serial ảo để phần mềm server nắm một đầu, phần mềm mô phỏng nắm một đầu. Phần mềm này ghi dữ liệu vào đầu này thì tại đầu kia, phần mềm kia sẽ đọc được.
Để tạo cổng serial ảo thì mình dùng socat. Cách tạo như sau:
Mở một tab của Terminal, gõ lệnh:
socat -d -d PTY,link=writer PTY,link=reader
Khi đó, socat
sẽ tạo ra hai file, writer
và reader
. Hai tên này thích đặt sao cũng được, không nhất thiết phải là writer và reader.
Trong lúc vẫn giữ socat
chạy, mở một tab khác của Terminal lên, chạy phần mềm mô phỏng, truyền tên của một trong hai file kia vào, giống với cách bạn truyền tên cổng serial thật vào, ví dụ:
./device-emulator writer
Và ở một Terminal khác thì bạn cấu hình cho phần mềm server truy cập vào file còn lại, thay cho cổng serial thật.
Lưu ý là tên file đặt là gì không quan trọng, nên tại đầu “reader” bạn vẫn có thể ghi, để đầu “writer” đọc được.
Bạn cũng có thể bỏ tham số “link” khỏi socat
, ví dụ:
socat -d -d PTY PTY
Nhìn vào thông báo của socat
để lấy tên file tương ứng với cổng serial ảo, ví dụ:
2017/10/06 17:09:49 socat[6828] N PTY is /dev/pts/5 2017/10/06 17:09:49 socat[6828] N PTY is /dev/pts/6 2017/10/06 17:09:49 socat[6828] N starting data transfer loop with FDs [5,5] and [7,7]
Tuy nhiên, đây là cách rất không được khuyến khích, vì mỗi lần tắt socat
mở lại, socat
sẽ phải tạo file mới với con số mới (để tránh đụng với các file pseudo-terminal sinh ra mỗi khi bạn mở một tab Terminal mới), ứng dụng của bạn sẽ phải cấu hình lại, nếu không sẽ vô tình ghi vào file pts
của một Terminal nào đó.
Sau đây là minh họa:
Với cổng serial ảo tạo bởi socat
, bạn có thể truy cập, theo dõi bằng hầu hết các phần mềm giao tiếp serial, ngoại trừ các phần mềm viết bằng Qt như CuteCom. Cụ thể, nếu cần phần mềm có giao diện đồ họa thì nên dùng GtkTerm:
Nếu thấy thoải mái với dòng lệnh thì bạn nên dùng thư viện PySerial của Python, khởi chạy công cụ dòng lệnh của nó bằng cách:
$ python3 -m serial.tools.miniterm /tên/port
PySerial
cũng là thư viện đảm nhiệm tính năng truy cập serial trong các bộ công cụ lập trình nhúng sau:
- IDF của Espressif (tương tác với ESP32/8266)
- PlatformIO (tương tác với tất cả các loại board mà PlatformIO hỗ trợ).
(và tất nhiên, cùng với các thư viện Python khác, đã đóng góp phần rất lớn trong các sản phẩm của AgriConnect).
Trên đây mình đã kể xong hai mẹo. Không biết có tầm thường không, nhưng với mình thì nó đã tiết kiệm rất nhiều thời gian làm việc, và từ đó cũng thấy Linux có nhiều đồ chơi hay thật.
Bài viết gốc được đăng tải tại quan.hoabinh.vn
Xem thêm:
- Các Công Ty IT Tại TPHCM
- Tuyển tập “cheatsheet” bộ câu hỏi cho anh em developer trước buổi phỏng vấn
- Sách hay nhất dành cho lập trình viên (2022)
Đừng bỏ lỡ tin tuyển dụng IT mới nhất trên TopDev
- G Giải Quyết Bài Toán Kinh Doanh Bằng Big Data và AI
- B BenQ RD Series – Dòng Màn Hình Lập Trình 4k+ Đầu Tiên Trên Thế Giới
- F Framework nào tốt nhất cho dự án của bạn? – Checklist chi tiết
- K Kinh nghiệm xử lý responsive table hiệu quả
- S Stackoverflow là gì? Bí kíp tận dụng Stack Overflow hiệu quả
- 7 7 kinh nghiệm hữu ích khi làm việc với GIT trong dự án
- B Bài tập Python từ cơ bản đến nâng cao (có lời giải)
- B Bảo mật API là gì? Một số nguyên tắc và kỹ thuật cần biết
- H Hướng dẫn cài đặt và tự học lập trình Python cơ bản từ A-Z
- C Chinh Phục Phân Tích Dữ Liệu Với Pandas Trong Python: Hướng Dẫn Từng Bước