Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reading Messages #17

Closed
robgil opened this issue Sep 15, 2020 · 8 comments
Closed

Reading Messages #17

robgil opened this issue Sep 15, 2020 · 8 comments

Comments

@robgil
Copy link
Contributor

robgil commented Sep 15, 2020

This might be obvious, but I can't seem to parse the messages being sent via LL2->writeData. I haven't written c++ since college, but I don't think its my code, but likely I'm using the library? shrug

The setup is simple.

  • 2x Heltec ESP32 LoRa V2 boards
  • 1 is sender, 1 is receiver
  • Sender is sending temp/humidity data directly to the receiver

Sender Address: c0d3f00d
Receiver Address: c0d3f00c

Receiver Side

void loop() {
  LL2->daemon();

  char routes[128];
  char neighbors[128];
  char config[128];

  LL2->getRoutingTable(routes);
  Serial.println(routes);

  LL2->getNeighborTable(neighbors);
  Serial.println(neighbors);

  LL2->getCurrentConfig(config);
  Serial.println(config);

  struct Packet packet = LL2->readData();
  Serial.print(((char *)packet.datagram.message)); <-- this should print something like '{"temperature: 70.0000, "humidity": 50.000}'

  delay(1000);
}

Output as follows

Routing Table: total routes 8
1 hops from c0d3f00d via c0d3f00d metric 255 <--- This is the sender... yay! Who is everyone else?!
1 hops from ffff00c0 via ffff00c0 metric 254 
2 hops from d3f00d00 via ffff00c0 metric   0 
64 hops from 48ce804b via ffff00c0 metric   7 
255 hops from 00000000 via ffff00c0 metric   0 
1 hops from 444344f8 via 444344f8 metric 254 
2 hops from 13412824 via 444344f8 metric   0 
41 hops from 1159063d via 444344f8 metric  24 

Neighbor Table:
c0d3f00d 255 
ffff00c0 254 
444344f8 254 

Current LoRa Config
Local Addr: c0d3f00c <-- Receiver.. yay!
Initialized: 1
CS, RST, DIO: 18, 14, 26
SPI Freq: 100000
LoRa Freq: 915000000
SF: 9
TxPwr: 20
Routing mode: auto
Routing interval: 10000ms
Duty Cycle: 0.100000

BTW, shocked to see all these other neighbors.

Sender Side

void loop() {
  LL2->daemon();
  char data[128] = {0};
  char counter_str[128] = {0};
  int msglen = 0;
  int packetsize = 0;
  sprintf(counter_str, "%i", counter);

  u8x8.drawString(0, 3, "Packets: ");
  u8x8.drawString(9, 3, counter_str);

  #ifdef ENABLE_DEBUG
  digitalWrite(LED, HIGH);
  #endif

  delay(1000);

  #ifdef ENABLE_DEBUG
  digitalWrite(LED, LOW);
  #endif

  float temperature = dht.readTemperature(true);
  float humidity = dht.readHumidity();

  // Build Packet
  msglen = sprintf(data, "{\"temperature\": %f, \"humidity\": %f}", temperature, humidity);
  #ifdef ENABLE_DEBUG
  Serial.println(data);
  #endif

  struct Datagram packet = buildDatagram((uint8_t *)GATEWAY, 'c', (uint8_t *)data, msglen); <-- GATEWAY in this case is the receiver node (char GATEWAY[9] = "c0d3f00c";)
  packetsize = msglen + HEADER_LENGTH;

  // Send packet
  LL2->writeData(packet, packetsize);  <--
  counter++;

  // After processing, go to sleep
  #ifdef ENABLE_DEBUG
  Serial.println("Going to sleep...");
  #endif

  esp_deep_sleep_start();
}
@paidforby
Copy link
Collaborator

What is happening in buildDatagram? It needs to do something like, based on disaster radio Console.cpp

uint8_t GATEWAY[ADDR_LENGTH] = {0xc0, 0xd3, 0xf0, 0x0c};
struct Datagram datagram;
char msgBuff[128];   // get your temp and humidity data into here, or sprintf it directly into datagram.message
msgLen = sprintf((char *)datagram.message, "%s", msgBuff);
memcpy(datagram.destination, GATEWAY, ADDR_LENGTH);
datagram.type = 'c';

It's a a little weird because the address needs to be raw bytes, not ASCII chars, which can be difficult because arduino wants to make everything strings. But if the destination address is wrong, then the packet will appear to never be received by the receiver, since it's the address in the datagram does not match its local address. This reminds me that I need to write some sender/receiver example code.

And don't get too excited about all those neighbors, its a known bug reported here, sudomesh/disaster-radio#81 (comment), I'll take a look at that as soon as I get a chance.

@robgil
Copy link
Contributor Author

robgil commented Sep 16, 2020

@paidforby Thanks! I figured it out and am now receiving messages on the receiver.

Turns out I had to set the following for it to work.

char MAC[9] = "c0d3f00c";
uint8_t LOCAL_ADDRESS[ADDR_LENGTH] = {0xc0, 0xd3, 0xf0, 0x0c}; <-- Datagram wants the hex here.
uint8_t GATEWAY[ADDR_LENGTH] = {0xc0, 0xd3, 0xf0, 0x0c};

LL2->setLocalAddress(MAC); <-- was looking for char here

It would be handy if the Datagram accepted the char array vs. the raw. I see there are a bunch of functions for converting this already. This will definitely hang other folks up, so I'm glad we figured it out. I'll give a swing at writing a simple client (I already did most of it!)

@robgil
Copy link
Contributor Author

robgil commented Sep 16, 2020

Added #18 :)

@robgil robgil closed this as completed Sep 16, 2020
@paidforby
Copy link
Collaborator

Great! Glad you figured it out. Yeah, it's a funny mix of chars and bytes. The reason the Datagram struct takes bytes is because it's actually the datagram that is copied into the packet so making it take individual chars for each hex character would waste bytes. I guess, some conversion could be done in the LL2->writeData function. I was actually thinking of changing that writeData function so it doesn't take a datagram, but instead takes the inputs to a datagram, something like, LL2->writeData(char *destination, char type, char * message). That would make sense, right?

And thanks for that pull request, I'll review and merge it (i looked good to me and is certainly better than nothing).

@robgil
Copy link
Contributor Author

robgil commented Sep 16, 2020

@paidforby yeah, I think the change to of LL2->writeData makes sense. Especially as a higher level function.

@paidforby
Copy link
Collaborator

I also noticed another issue, not sure if it is possible cause of your routing table being filled imprroperly, but you should not use delay() in the loop, this is a blocking function that prevent the LL2 daemon from polling often enough. Instead of delay(), write a poll that waits for a certain timeout to execute its function, like what is done inside of LL2->daemon() here, https://github.com/sudomesh/LoRaLayer2/blob/master/src/LoRaLayer2.cpp#L671

@paidforby
Copy link
Collaborator

I made a number of changes in these two recent commits including,

  1. Updated to latest LoRaLayer2 commit in the platformio.ini for both examples

  2. Added LL2->init() that was missing, I'm not sure it this was causing many problems because all it does is initialize some timeout counters, but still it should be called.

  3. Corrected the packetsize length to be the datagramsize, you were adding HEADER_LENGTH (i.e. the LL2 packet header) instead of DATAGRAM_HEADER (just the datagram portion header), so there was extra data appended to the end of your hello messages.

  4. Both the sender and receiver had the same local address, I corrected this by changing the receiver to something more distinct.

These changes seem to have fixed the issue with the routing table filling with garbage, though it's difficult to prove the negative, so all I can say is that I haven't observed that problem since making these changes (specifically, updating LL2 seemed to fix most of the routing table weirdness).

Sorry that I didn't take a look at this sooner.

@robgil
Copy link
Contributor Author

robgil commented Sep 21, 2020

@paidforby excellent thanks! Good catch on the packetsize and init bits. I'll try updating these and see if I still get a mess of random neighbors.

Delay/Loop

I see your point about using delay(). The example you mentioned makes perfect sense when running in active mode all the time. I'll open a separate issue / example for doing deep sleep which is really where that comes from. I used delay() to emulate an ESP32 deep sleep. This unfortunately prevents packets from being sent since they seem to be getting sent asyncronously. We may need a way to flush the packet buffer before going to sleep.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants