Код пользовательского пространства Linux для связи между платой Linux и каждым узлом, выполняющим пример кода отправителя contiki udp - PullRequest
0 голосов
/ 20 октября 2018

Я использую Contiki для создания продукта IoT, включающего несколько узлов на основе STM32L152 и плату Linux.У меня есть одна встроенная плата Linux (на основе iMX6), которая получает данные от узлов, отправляет их в Интернет с использованием сотовой связи и 10 узлов, которые определяют различные параметры среды и доставляют на плату Linux.Плата Linux имеет сопроцессор, который выполняет код пограничного / граничного маршрутизатора, линии UART2 этого сопроцессора подключены к плате Linux.Я использую инструмент Contiki tunslip6 для создания интерфейса tun0, я могу пинговать каждый узел.Чтобы сделать этот вопрос более понятным, я объясню настройку оборудования и шаг, который я выполнил.

  1. Я использую пример кода отправителя UDP (STM32CubeExpansion_SUBG1_V3.0.0 / Projects / Multi / Applications / Contiki/ Udp-sender) на плате STM32L152RE-NUCLEO с платой x-nucleo-ids01a5 (модуль SPSGRF-915), расположенной сверху.

  2. На второй аналогичной настройке оборудования я запускаю BorderПример кода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))

Над кодом Python работает.

1 Ответ

0 голосов
/ 20 октября 2018

Маршрутизатор границы имеет жестко закодированный 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 ! ");
}
...