Код пользовательского пространства Linux для связи между платой Linux и каждым узлом, выполняющим пример кода отправителя contiki udp
Я использую Contiki для создания продукта IoT, включающего несколько узлов на основе STM32L152 и плату Linux. У меня есть одна встроенная плата Linux (на основе iMX6), которая получает данные от узлов, отправляет их в Интернет с использованием сотовой связи и 10 узлов, которые определяют различные параметры среды и доставляют на плату Linux. Плата Linux имеет сопроцессор, который выполняет код граничного / граничного маршрутизатора, линии UART2 этого сопроцессора подключены к плате Linux. Я использую инструмент Contiki tunslip6 для создания интерфейса tun0, я могу пинговать каждый узел. Чтобы сделать вопрос более понятным, я объясню настройку оборудования и шаг, который я выполнил.
Я использую пример кода отправителя UDP (STM32CubeExpansion_SUBG1_V3.0.0/Projects/Multi/Applications/Contiki/Udp-sender) на плате STM32L152RE-NUCLEO, на которой установлена плата x-nucleo-ids01a5 (модуль SPSGRF-915).
На второй подобной установке оборудования я запускаю пример кода Border-router. USB-кабель подключен к моей коробке Linux.
после этого; sudo ./tunslip6 –s /dev/ttyACM0 aaaa::1/64
Я могу видеть все соседние узлы на веб-странице, я также могу ping6 каждый узел. Я хочу написать код приложения для Linux, чтобы получать и отправлять данные каждому узлу, я застрял на этом этапе.
sudo ./tunslip6 -s /dev/ttyACM0 aaaa::1/64
********SLIP started on ``/dev/ttyACM0''
opened tun device ``/dev/tun0''
ifconfig tun0 inet `hostname` mtu 1500 up
ifconfig tun0 add aaaa::1/64
ifconfig tun0 add fe80::0:0:0:1/64
ifconfig tun0
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-
00-00-00-00-00
inet addr:127.0.1.1 P-t-P:127.0.1.1 Mask:255.255.255.255
inet6 addr: fe80::1/64 Scope:Link
inet6 addr: aaaa::1/64 Scope:Global
inet6 addr: fe80::8fad:d1a:c8d0:b76f/64 Scope:Link
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
*** Address:aaaa::1 => aaaa:0000:0000:0000
Got configuration message of type P
Setting prefix aaaa::
Server IPv6 addresses:
aaaa::900:f4ff:c3a:f3c5
fe80::900:f4ff:c3a:f3c5
ifconfig
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:127.0.1.1 P-t-P:127.0.1.1 Mask:255.255.255.255
inet6 addr: fe80::1/64 Scope:Link
inet6 addr: aaaa::1/64 Scope:Global
inet6 addr: fe80::8fad:d1a:c8d0:b76f/64 Scope:Link
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:37 errors:0 dropped:0 overruns:0 frame:0
TX packets:67 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:3422 (3.4 KB) TX bytes:5653 (5.6 KB)
ip addr show tun0
3: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 500
link/none
inet 127.0.1.1/32 scope host tun0
valid_lft forever preferred_lft forever
inet6 aaaa::1/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::1/64 scope link
valid_lft forever preferred_lft forever
inet6 fe80::8fad:d1a:c8d0:b76f/64 scope link flags 800
valid_lft forever preferred_lft forever
sudo ip -6 route
aaaa::/64 dev tun0 proto kernel metric 256 pref medium
fe80::/64 dev tun0 proto kernel metric 256 pref medium
Это то, что я вижу на веб-странице, у меня есть один соседний узел, я могу пропинговать это.
ping6 aaaa::fdff:d2fa:2d05
PING aaaa::fdff:d2fa:2d05(aaaa::fdff:d2fa:2d05) 56 data bytes
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=1 ttl=63 time=130 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=2 ttl=63 time=131 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=3 ttl=63 time=130 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=4 ttl=63 time=130 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=6 ttl=63 time=130 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=7 ttl=63 time=130 ms
64 bytes from aaaa::fdff:d2fa:2d05: icmp_seq=8 ttl=63 time=131 ms
^C
--- aaaa::fdff:d2fa:2d05 ping statistics ---
8 packets transmitted, 7 received, 12% packet loss, time 7040ms
rtt min/avg/max/mdev = 130.681/131.068/131.863/0.555 ms
Я не специалист по сетевым технологиям и программированию сокетов, я написал код, который нашел в интернете и попробовал. Я попробовал что-то вроде этого;
import socket
UDP_IP = "aaaa::fdff:d2fa:2d05"
UDP_PORT = 1234
print "UDP target IP:", UDP_IP
print "UDP target port:", UDP_PORT
sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) # UDP
sock.connect((UDP_IP, UDP_PORT))
while True:
data = sock.recv(1024)
print 'Received', repr(data)
Вопрос: В пользовательском пространстве Linux мой коллега хочет написать код приложения, который может читать и писать каждый узел (в этом случае aaaa::fdff:d2fa:2d05
) как мы можем этого добиться? На плате микроконтроллера я могу читать и писать с двух узлов, но не в пространстве Linux. Пожалуйста, помогите мне, как я могу читать и записывать данные из пространства пользователя Linux на каждый узел? Если возможно, поделитесь примером кода. Спасибо!
Обновление - я попытался установить связь между узлом Linux и узлом с помощью другого примера Contiki, contiki/examples/ipv6/rpl-udp/udp-client.c, и мне это удалось, я смог получить данные от узла. Мой код Python является;
import socket, struct
UDP_LOCAL_IP = 'aaaa::1'
UDP_LOCAL_PORT = 5678
UDP_REMOTE_IP = 'fe80::fdff:d2fa:2d05'
UDP_REMOTE_PORT = 8765
try:
socket_rx = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
socket_rx.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
socket_rx.bind((UDP_LOCAL_IP, UDP_LOCAL_PORT))
except Exception:
print "ERROR: Server Port Binding Failed"
print 'UDP server ready: %s'% UDP_LOCAL_PORT
print
while True:
data, addr = socket_rx.recvfrom(1024)
print "address : ", addr
print "received message: ", data
print "\n"
socket_rx.sendto("Hello from serevr\n", (UDP_REMOTE_IP, UDP_REMOTE_PORT))
Над питоном работает код.
1 ответ
Граничный маршрутизатор имеет жестко закодированный адрес IPv6, согласно https://anrg.usc.edu/contiki/index.php/RPL_Border_Router этот адрес fe80:0000:0000:0000:0212:7401:0001:0101
(возможно, запустить ip addr show tun0
-> Ваше редактирование показывает, что назначенный адрес fe80:0000:0000:0000:8fad:d1a:c8d0:b76f
). По этому адресу вы привязываете сокет вашего приложения, для этого в Python нет кода для этого. Потому что вы используете tunslip
вы также можете привязать к localhost с точным портом и протоколом ipv4
Для тестирования вы можете использовать netcat
отправлять UDP-пакеты напрямую на узлы ( http://www.tutorialspoint.com/unix_commands/nc.htm)
Чтобы избавиться от ошибки (комментария) вам необходимо подать заявку inet_pton
для преобразования адреса IPv6 ( http://man7.org/linux/man-pages/man3/inet_pton.3.html)
далее работает код C, который вы можете перевести на python. был написан для использования USB-флешки Raven в качестве граничного маршрутизатора (поиск Contiki Jackdaw, без использования tunslip)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <net/if.h>
int fd = 0; //socket file descriptor
struct sockaddr_in6 server;
/* ipv6 address to in6_addr structure */
const char *ip6str = "fe80::8fad:d1a:c8d0:b76f";
struct in6_addr ravenipv6;
if (inet_pton(AF_INET6, ip6str, &ravenipv6) == 1) // successful
{
printf("%s \n", "ipv6 address ...");
}
/* Create an empty IPv6 socket interface specification */
memset(&server, 0, sizeof(server));
server.sin6_family = AF_INET6;
server.sin6_flowinfo = 0;
server.sin6_port = htons(1234); // port
server.sin6_addr = ravenipv6; <- here the address converted with inet_ptons is inserted
server.sin6_scope_id = if_nametoindex("tun0"); // if your border router is on tun0
/*create socket*/
if ((fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1)
{
printf("%s \n", "failed to create socket");
}
/*bind to socket*/
if(bind(fd, (struct sockaddr_in6*)&server, sizeof(server)) == -1)
{
printf("%s \n", "no binding ! ");
}