Inviare Pacchetti UDP in modo corretto

Buongiorno,

Sto utilizzando un Arduino Mega, un Ethernet Shield basata sull'integrato W5100 e un ulteriore Shield per l'RS485.

Sto realizzando un progetto che prevede la richiesta di un dato tramite Modbus RTU RS485, se la risposta ha un esito positivo, lo stesso dato viene inviato in rete tramite protocollo UDP.

Ammetto che inizialmente, utilizzando WireShark, mi sono accorto che il dato UDP non veniva ben interpretato:
veniva trasmesso, ma non veniva riconosciuto come UDP, infatti l'ascoltatore non riceveva niente.
Per la risoluzione di questo piccolo problema ho utilizzato la patch proposta su: Roeften's thoughts: Multicast communication between Arduino (Ethernet library W5100) and a Java application

Ok a questo punto sono in grado di riceve il mio dato tramite Modbus RTU e spedirlo via Ethernet col protocollo UDP. E Sarei già soddisfatto cosi: il mio progetto funziona ed è sufficiente a raggiungere il mio scopo.

Il problema dove sta allora?
L'Arduino è collegato in rete.
Quando il mio Laptop è collegato alla rete tramite cavo Ethernet, il dato UDP è presente e pronto all'uso.
Quando invece il mio Laptop è collegato alla rete tramite Wifi, il dato UDP non viene più ricevuto.

Sembrerebbe che il modem non ritrasmetta il pacchetto UDP, da me inviato con Arduino, sulla WIFI.

Ho notato una cosa:
Nelle circostanze in cui tutto funziona, mi sono accorto che Arduino quando manda un pacchetto di dati UDP, la porta "Sorgente" è uguale alla porta di "Destinazione". Potrebbe essere questo il problema?

Saluti
Maurizio

Buongiorno,
essendo il tuo primo post, nel rispetto del regolamento (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con MOLTA attenzione il su citato REGOLAMENTO ... Grazie.

Guglielmo

P.S.: Qui una serie di link utili, NON necessariamente inerenti alla tua domanda:
- serie di schede by xxxPighi per i collegamenti elettronici vari: ABC - Arduino Basic Connections
- pinout delle varie schede by xxxPighi: Pinout
- link generali utili: Link Utili

Credo di avere un'idea, ma prima di risponderti devi fare quello che richiede il regolamento una volta fatto, scrivi qui qualche informazione sul tuo modem-router (marca, modello) e spiega intanto cosa intendi con "il dato UDP non veniva ben interpretato" ossia che significa che "non veniva riconosciuto come UDP"? Un pacchetto del protocollo UDP è un pacchetto UDP, c'è poco da interpretare". E dicci anche perché usi il Multicast invece di un pacchetto diretto (ma devi conoscere l'IP del destinatario) o un broadcast (se non conosci l'IP destinatario o se vuoi mandarlo anche a più riceventi).

Buonasera,

Inizialmente il dato Udp tramite WireShark veniva interpretato come "ARP", se non ricordo male, inoltre non vi era nessun indirizzo di destinazione, quindi ho dedotto che non era un dato UDP.

Un apparato navale, può essere configurato per mettersi in ascolto su un determinato indirizzo e porta, e devo realizzare un interfaccia che recupera un dato su ModBus Rs485 RTU e trasmetterlo verso quest'apparato, di cui conosco l'indirizzo IP.
Stando alla mia esperienza, in ambito navale un dato viene trasmesso in rete e chi vuole lo recupera.
Per cui ho pensato di utilizzare il protocollo UDP in Multicast.

Allora, intanto la ARP request è un'altra cosa, lascia stare altrimenti ti invischi in questioni di basso livello di rete.

Poi se il ricevente è nella stessa subnet evita il Multicast perché non è detto che vada dove te lo aspetti se qualche apparato non lo gestisce o lo tronca.

Fai prima con i broadcast ovvero come destinatario metti la subnet seguita da 255 (ossia tutti i bit a 1 nella parte "libera" della subnet es. per la rete 192.168.1.0/24 metterai come destinatario 192.168.1.255, per 10.20.0.0/16 sarà 10.20.255.255 eccetera). Questo pacchetto, che manderai su una porta specifica che puoi definire liberamente, lo riceveranno tutti gli apparati nella stessa subnet (i broadcast non passano i router), ed ognuno potrà decidere cosa farne.

Io ho usato questa tecnica per il ripetitore di telecomando Sky, un Arduino (nel mio caso in realtà due WeMos D1 WiFi) riceve ed identifica il tasto, e via UDP manda il suo codice all'altro, che quando lo riceve lo trasmette. Non ho bisogno di configurare gli IP perché il broadcast lo ricevono tutti, e nel payload del pacchetto ho aggiunto un byte che indica l'ID del device (cos' se volessi in futuro avere più ripetitori di telecomando separati posso farlo cambiando l'ID).

Ti metto qualche spezzone di codice e funzioni che ho creato, così se ti serve li adatti.

Trasmettitore:

WiFiUDP udp;
const unsigned int IRS_PORT = 2001;  // porta per i pacchetti UDP
const int IRS_PACKET_SIZE = 8;      // Il pacchetto è composto da massimo 8 byte
byte packetBuffer[IRS_PACKET_SIZE]; // buffer
IPAddress ipLocal, ipBroadcast;
  ...
  // Calcolo l'indirizzo broadcast
  IPAddress subnet = WiFi.subnetMask();
  // Calcola l'indirizzo broadcast
  ipBroadcast = ipLocal;
  for (int i=3; i>=0; i--)
    if ( subnet[i] == 0 )
      ipBroadcast[i] = 255;

  ...

void initKeyPkt(int key)
{
  // Header
  packetBuffer[0] = 'I';  // IRS Packet marker
  packetBuffer[1] = 1;  // IRS server = 1
  // Payload (comando)
  packetBuffer[2] = 'K';  // IRS function (K=key)
  packetBuffer[3] = key;    // Codice tasto
}

// send a request to the server at the given address
void sendPacket()
{
  Serial.print("Sending packet: ");
  for (int i=0; i<IRS_PACKET_SIZE; i++) {
	if (packetBuffer[i] >= ' ' )
		Serial.write(packetBuffer[i]);
	else
		Serial.print(packetBuffer[i], HEX);
    Serial.write(' ');
  }
  Serial.println();
  // Invia il pacchetto
  udp.beginPacket(ipBroadcast, IRS_PORT);
  udp.write(packetBuffer, IRS_PACKET_SIZE);
  udp.endPacket();
  resetPacket();
}

void resetPacket()
{  // set all bytes in the buffer to 0
    memset(packetBuffer, 0, IRS_PACKET_SIZE);
}

Ricevitore:

WiFiUDP udp;
const unsigned int IRS_PORT = 2001;
const int IRS_PACKET_SIZE = 8;      // Il pacchetto è composto da massimo 8 byte
byte pkt[IRS_PACKET_SIZE]; // buffer
   ...
  udp.begin(IRS_PORT);
   ...
// receive udp messages
bool udpReceive(void)
{
  int packetSize = udp.parsePacket();
  if(packetSize) {
    // read the packet into packetBufffer
    udp.read(pkt,IRS_PACKET_SIZE);
    return true;
  } else
    return false;
}
   ...
  if ( udpReceive() ) {
    // Leggo il pacchetto
    if ( pkt[0] == 'I' ) {  // Pacchetto IRS
      if ( pkt[1] == 1 ) {  // Server 1
        switch ( pkt[2] ) {
          case 'K':
            sendKey(pkt[3]);
            break;
          default:
            Serial.print("Pacchetto sconosciuto!");
            break;
        }
        Serial.println();
      }
    }