8000 udp.available() returning -1 x bytes available · Issue #105 · arduino-libraries/MKRGSM · GitHub
[go: up one dir, main page]

Skip to content
udp.available() returning -1 x bytes available #105
@MrWFoulkes

Description

@MrWFoulkes

Calls to udp.available() appear to return -1 x number of bytes available.

My program sends a Network Time Protocol request over UDP and receives a 48 byte response.

Here's the serial output:

Attempting to connect to the modem

Attempting to connect to the GPRS Access Point Name

Packet sent
Awaiting response
udp.parsePacket 0
udp.parsePacket 0
udp.parsePacket 48
udp.available -48 <---expected 48 here

Code (excluding secrets.h) is below. The relevant serial output comes from void loop():

#define LEAP_INDICATOR_NO_WARNING 0
#define LEAP_INDICATOR_61_SECONDS 1
#define LEAP_INDICATOR_59_SECONDS 2
#define LEAP_INDICATOR_UNKNOWN 3
#define LEAP_INDICATOR_Pos 6

#define VERSION_NUMBER_Pos 3

#define MODE_CLIENT 3
#define MODE_Pos 0

#define STRATUM_UNSPECIFIED_OR_INVALID 0

#define NTP_DOMAIN "pool.ntp.org"

const unsigned int NTP_PORT = 123u;
const unsigned int LOCAL_PORT = 2390u;

#include "arduino_secrets.h"
#include <MKRGSM.h>
/*Create the objects needed for internet requests*/
GSM gsm;	//class to connect to the modem
GSMClient gsmClient;	
GPRS gprs;	//class to connect to the internet
GSMUDP udp;


struct NTPPacket {
		unsigned int leapIndicator;
		unsigned int versionNumber;
		unsigned int mode;
		unsigned int stratum;
		int poll;
		int precision;
		unsigned long rootDelay;
		unsigned long rootDispersion;
		unsigned long referenceID;
		unsigned long long referenceTimestamp;
		unsigned long long originTimestamp;
		unsigned long long receiveTimestamp;
		unsigned long long transmitTimestamp;
		//ignoring the remaining fields for now. The example implementation doesn't use them.
	};

void printLongLong(long long value) {
	Serial.print((long)(value >> 32), HEX);
	Serial.println((unsigned long)(value), HEX);
}

void bigEndian(long long input, int sizeOfOutput, unsigned char output[]) {
	for (int i = 0; i < sizeOfOutput; i++) {
		int rightShift = (sizeOfOutput - 1 - i) * 8;
		char nextByte = (char) (input >> rightShift);
		output[i] = nextByte;
	}
}

long long bigEndianToLongLong(unsigned char data[], int sizeOfData) {
	long long output = 0;
	for(int i = 0; i < sizeOfData; i++) {
		output = output << 8;
		output += data[i];
	}
	return output;
}

void sendNTPRequest(unsigned long long referenceTimestamp, unsigned long long originTimestamp) {
	struct NTPPacket packet;
	packet.leapIndicator = LEAP_INDICATOR_UNKNOWN;
	packet.versionNumber = 4;
	packet.mode = MODE_CLIENT;
	packet.stratum = STRATUM_UNSPECIFIED_OR_INVALID;
	packet.poll = 0; //presumably this is set by the server?
	packet.precision = 0; // ditto
	packet.rootDelay = 0;
	packet.rootDispersion = 0;
	packet.referenceID = 0;
	packet.referenceTimestamp = referenceTimestamp;
	packet.originTimestamp = originTimestamp;
	packet.receiveTimestamp = 0;
	packet.transmitTimestamp = 0;

	while(!udp.beginPacket(NTP_DOMAIN, NTP_PORT));
	udp.write(packet.leapIndicator << LEAP_INDICATOR_Pos
		| packet.versionNumber << VERSION_NUMBER_Pos
		| packet.mode << MODE_Pos);
	udp.write(packet.stratum);
	udp.write(packet.poll);
	udp.write(packet.precision);
	byte byteArray[8];	//byte array to be used for multi-byte fields in big endian format
	bigEndian((long long)packet.rootDelay, 4, byteArray);
	udp.write(byteArray, 4);
	bigEndian((long long)packet.rootDispersion, 4, byteArray);
	udp.write(byteArray, 4);
	bigEndian((long long)packet.referenceID, 4, byteArray);
	udp.write(byteArray, 4);
	bigEndian(packet.referenceTimestamp, 8, byteArray);
	udp.write(byteArray, 8);
	bigEndian(packet.originTimestamp, 8, byteArray);
	udp.write(byteArray, 8);
	bigEndian(packet.receiveTimestamp, 8, byteArray);
	udp.write(byteArray, 8);
	bigEndian(packet.transmitTimestamp, 8, byteArray);
	udp.write(byteArray, 8);
	while(!udp.endPacket());
	Serial.println("Packet sent");
}

void receiveNTPPacket() {
	struct NTPPacket packet;
	byte byteArray[8];	//byte array to be used for multi-byte fields in big endian format
	Serial.print((int)udp.available());
	Serial.println(" bytes available");
	Serial.print("First byte: ");
	Serial.println((int)udp.peek(), DEC);
	packet.leapIndicator = (udp.peek() >> LEAP_INDICATOR_Pos) & 0b11;
	packet.versionNumber = (udp.peek() >> VERSION_NUMBER_Pos) & 0b111;
	packet.mode = (udp.read() >> MODE_Pos) & 0b111;
	packet.stratum = udp.read();
	packet.poll = udp.read();
	packet.precision = udp.read();
	udp.read(byteArray, 4);
	packet.rootDelay = bigEndianToLongLong(byteArray, 4);
	udp.read(byteArray, 4);
	packet.rootDispersion = bigEndianToLongLong(byteArray, 4);
	udp.read(byteArray, 4);
	packet.referenceID = bigEndianToLongLong(byteArray, 4);
	udp.read(byteArray, 8);
	packet.referenceTimestamp = bigEndianToLongLong(byteArray, 8);
	udp.read(byteArray, 8);
	packet.originTimestamp = bigEndianToLongLong(byteArray, 8);
	udp.read(byteArray, 8);
	packet.receiveTimestamp = bigEndianToLongLong(byteArray, 8);
	udp.read(byteArray, 8);
	packet.transmitTimestamp = bigEndianToLongLong(byteArray, 8);

	Serial.print("Leap indicator ");
	Serial.println(packet.leapIndicator);
	Serial.print("Version number ");
	Serial.println(packet.versionNumber);
	Serial.print("Mode ");
	Serial.println(packet.mode);
	Serial.print("Stratum ");
	Serial.println(packet.stratum);
	Serial.print("Poll ");
	Serial.println(packet.poll);
	Serial.print("Precision ");
	Serial.println(packet.precision);
	Serial.print("Root delay ");
	Serial.println(packet.rootDelay);
	Serial.print("Root Dispersion ");
	Serial.println(packet.rootDispersion);
	Serial.print("Reference ID ");
	Serial.println(packet.referenceID);
	Serial.print("Reference Timestamp 0x");
	printLongLong(packet.referenceTimestamp);
	Serial.print("Origin Timestamp 0x");
	printLongLong(packet.referenceTimestamp);
	Serial.print("Receive Timestamp 0x");
	printLongLong(packet.receiveTimestamp);
	Serial.print("Transmit Timestamp 0x");
	printLongLong(packet.transmitTimestamp);
}

void setup() {
	// put your setup code here, to run once:
	pinMode(LED_BUILTIN, OUTPUT);
	digitalWrite(LED_BUILTIN, LOW);
	Serial.begin(9600);
	while(!Serial);
	Serial.println("Attempting to connect to the modem");
	while(gsm.begin() != GSM_READY) {
		Serial.print('.');
		delay(100);
	}
	Serial.println();
	Serial.println("Attempting to connect to the GPRS Access Point Name");
	while(gprs.attachGPRS(SECRET_GPRS_APN, SECRET_GPRS_LOGIN, SECRET_GPRS_PASSWORD) != GPRS_READY) {
		Serial.print('.');
		delay(100);
	}
	Serial.println();
	
	while(!udp.begin(LOCAL_PORT));
	sendNTPRequest(0,0);
	Serial.println("Awaiting response");

	int parsePacket;
	do {
		parsePacket = udp.parsePacket();
		Serial.print("udp.parsePacket ");
		Serial.println(parsePacket);
		delay(100);
	}	while (parsePacket < 1);
	
//	Serial.println("Response received");
//	receiveNTPPacket();
//	udp.stop();
	
}

void loop() {
	Serial.print("udp.available ");
	Serial.println(udp.available());
	Serial.print("udp.peek ");
	Serial.println(udp.peek());
	Serial.print("udp.available ");
	Serial.println(udp.available());
	Serial.print("udp.read ");
	Serial.println(udp.read());
	delay(2000);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0