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

taskSendReport: Failed to send report #1

Open
chriswant opened this issue Dec 29, 2021 · 5 comments
Open

taskSendReport: Failed to send report #1

chriswant opened this issue Dec 29, 2021 · 5 comments

Comments

@chriswant
Copy link

Hello and Thank You for Your Time and Effort.
I am trying to use your "SmartForestMesh" and I get this Error "taskSendReport: Failed to send report 349_249.log!". Currently, I am using 2x ESP32-CAM's with SD Cards in both. I use the Arduino IDE and copied the Main.cpp to a new .ino file and uploaded it to the ESP32-CAM. I am not using the PIR Motion sensor at the moment. I figured that every NODE on the mesh network would be able to receive and broadcast to each other and show the Logs coming from other NODE's in the Serial Monitor. But I don't think that this program works that way. A question to you is how can I set up a receiver NODE, or is there a way to use the Painlessmesh Android APP to display the Log Reports and Pictures when it connects with the mesh by collecting all NODE's SD card data or something like that. But the main question is how to set up a Receiver NODE to receive the Report Logs and display it via the serial monitor.
Thank You again for your time and effort.

@dkettner
Copy link
Owner

dkettner commented Jan 2, 2022

@chriswant

Hi, sorry for the delayed response.

First of all this project is not finished (for example the PIR sensor and the tensorflow stuff is not working yet) and I am actually working on some other projects right now so there will be no fixes during the next weeks.

But I will try to answer your questions.

I figured that every NODE on the mesh network would be able to receive and broadcast to each other

A question to you is how can I set up a receiver NODE

It is indeed possible to either broadcast to every node or to send messages to specific nodes. As of right now the project sends the message to the node which is specified at the top (so no broadcast). So find out the ID of the receiving node and insert it there (DEST_NODE). You may change this destination ID for each node before uploading. If a node sends a message to itself, it will fail. If a node sends a message to another node which is not currently connected to the mesh, it will also fail.
If you want to broadcast to every node you will have to change the class PictureReportPackage. It inherits the SinglePackage from the painlessmesh-library. You will most likely have to inherit some other class but you should look up the painlessmesh wiki for that. Also in setup() you will have to change the mesh.onPackage()-call. Depending on your usecase you may even use some simpler methods of the mesh and skip the defition of a new class.

and show the Logs coming from other NODE's in the Serial Monitor. But I don't think that this program works that way.

The logs are only meant to be displayed locally via the serial monitor of each node. They are not transmitted via mesh at all. There are two reasons for that. Firstly, the logs should give you hints if everything is working as expected. If the mesh is not working, the log will not reach other nodes, so it would be useless (in my case). Secondly, this would cause a huge overhead of messages floating around the mesh and I wanted to avoid that. Generally I would suggest that you only send messages that you actually need because the mesh (and the esp32s sending/receiving all kinds of messages) might overload and behave weird or take very long for a simple message to reach its destination.

But the main question is how to set up a Receiver NODE to receive the Report Logs and display it via the serial monitor.

I guess I kind of already answered this but I wanted to make clear what my code is actually supposed to do.
It is supposed to take a picture, evaluate it (ideally with tensorflow but thats not working right now), build a report about the evaluation and send this report to the receiving node. This report is not what you see in the serial prints (which are just some logs with information about what is going on).
So if you want to reuse the code for your project you should probably try to modify the report which is being send to include the information that you need instead of making every serial log a broadcast.

I hope this makes sense to you but feel free to ask again if I missed your point.

@dkettner
Copy link
Owner

dkettner commented Jan 2, 2022

is there a way to use the Painlessmesh Android APP to display the Log Reports and Pictures when it connects with the mesh by collecting all NODE's SD card data or something like that.

I never used the app, sorry.

I can tell you something about the pictures though: I did not manage to actually send pictures via mesh to another node (which is why the picuture is supposed to be evaluated on the esp32 and not on some remote server). This is because pictures are just too big. I read somewhere in the painlessmesh-repo that it should be possible to base64-encode the picture, send it via mesh and decode it on the receiving node. However, it simply did not work and I tried a lot. Please do come back to me if you succeed with this.

@chriswant
Copy link
Author

@dkettner
Hello and Thank You for your update on this matter. Yes, you have answered all my questions. I really like your coding style, I wish to be as good as you one day... (Baby-Steps). I am working on a project that uses the Painlessmesh Mesh Network for Sensors data collecting and displaying Graphs or Log txt of that data on a modified Painlessmesh Android APP. I am trying myself to Send the Pictures base64-encode through Json. With no solution yet but when I solve this I will let you know. Other than that your code has helped me a lot in Understanding, Structuring, and setting everything up to work together on these ESP32-CAM boards. Thank You again for your time and effort.

@chriswant
Copy link
Author

@dkettner
Hello, I think I have found a solution for sending images through JSON.
Here is the Link : https://gitlab.com/painlessMesh/painlessMesh/-/issues/426

This is where I found out how to send large data through JSON Packets. He seemed to have some trouble with it though. I made some modifications and got it to work.

Images are at VGA size with 18 Jpeg_quality. Makes a file about 8600 kb file size. It gets broken up into Chucks of 3000 kb and sent out by mesh.sendBroadcast();.

I think we could send larger size files but I think we need to figure out how to space out sending the data. (instead of all at once by a forloop). Maybe by saving all the chunks then putting them in a queue to be sent out over time, or something like that.

Here are the relevant parts to the code. Please if you can see what I have done to the code and see if there is something you would do differently, I would love to know how you would clean this up to work better.
Thank You for your time and effort.

To take the Picture:

`void sendData( String sensorType, long idPacket, int indexPacket, int totalPackets, String dataSensor )
{
String msg;

DynamicJsonDocument jsonBuffer( 1024 + dataSensor.length() );
JsonObject root = jsonBuffer.to< JsonObject >();
root[ "nodeId" ] = nodeID;
root[ "type" ] = "sensor";
JsonObject packet = root.createNestedObject( "packet" );
packet[ "sensor" ] = "sensorType";
packet[ "idPacket" ] = String( idPacket );
packet[ "indexPacket" ] = String( indexPacket );
packet[ "totalPackets" ] = String( totalPackets );
packet[ "data" ] = dataSensor;
serializeJson( root, msg );

Serial.println( msg );
Serial.println( "---> Send " + sensorType + " packet " + String( indexPacket ) + "/" + String( totalPackets ) + " to " );
mesh.sendBroadcast( msg );
}

String encodedString;
#define CFG_MESH_MAX_PACKET_SIZE 3000 //------------------------ This Same to work the best

void takePicture();
Task taskTakePicture(TASK_SECOND * 30, TASK_FOREVER, &takePicture); // -------- For testing set to 30 sec
void takePicture()
{
// Retrieve camera framebuffer
camera_fb_t * fb = NULL;
uint8_t* _jpg_buf = NULL;
size_t _jpg_buf_len = 0;
esp_err_t res = ESP_OK;
Serial.print( "Capturing Image .." );

fb = esp_camera_fb_get();

if ( !fb )
{
Serial.println( "Camera capture failed" );
res = ESP_FAIL;
}
else
{
Serial.println( "Done!" );

  _jpg_buf_len = fb->len;
  _jpg_buf = fb->buf;

int encodedLength = _jpg_buf_len;
Serial.println( "Size of the base64 encoded image..." + String( encodedLength ) );
const String& encodedString = base64::encode((uint8_t *)_jpg_buf,  _jpg_buf_len);
Serial.println( "Encoded string created" );

int tailPacketLength = encodedLength % CFG_MESH_MAX_PACKET_SIZE;
long idPacket = random( LONG_MIN, LONG_MAX );

if ( tailPacketLength == encodedLength )
{
  sendData( "camera", idPacket, 1, 1, String( encodedString ) );
}
else
{
  String photoString( encodedString );
  int numPackets = ( encodedLength / CFG_MESH_MAX_PACKET_SIZE ) + 1;
  String fractPacket;
  int i;

  for ( i = 0; i < ( numPackets ); i++ )  // -----   "numPackets - 1"  THIS DID NOT WORK --------------------------------------   
  {
    fractPacket = photoString.substring( i * CFG_MESH_MAX_PACKET_SIZE, ( i * CFG_MESH_MAX_PACKET_SIZE ) + CFG_MESH_MAX_PACKET_SIZE );
    sendData( "camera", idPacket, i + 1, numPackets, String( fractPacket ) );
    vTaskDelay( 500 / portTICK_PERIOD_MS ); 
    fractPacket = "";
  }

  fractPacket = photoString.substring( i * CFG_MESH_MAX_PACKET_SIZE );
  sendData( "camera", idPacket, i + 1, numPackets, String( fractPacket ) );
  vTaskDelay( 500 / portTICK_PERIOD_MS );
  fractPacket = "";
}

if ( fb)
{
  esp_camera_fb_return( fb );
  fb = NULL;
  _jpg_buf = NULL;
}

}

if ( res != ESP_OK )
{
return;
}
}

//Camera Settings

config.frame_size = FRAMESIZE_VGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
config.jpeg_quality = 18; //10-63 lower number means higher quality
config.fb_count = 1;

// Initialize the Camera
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}

sensor_t * s = esp_camera_sensor_get();
s->set_brightness(s, 0); // -2 to 2
s->set_contrast(s, 1); // -2 to 2
s->set_saturation(s, 0); // -2 to 2
s->set_special_effect(s, 0); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
s->set_whitebal(s, 1); // 0 = disable , 1 = enable
s->set_awb_gain(s, 1); // 0 = disable , 1 = enable
s->set_wb_mode(s, 0); // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
s->set_exposure_ctrl(s, 1); // 0 = disable , 1 = enable
s->set_aec2(s, 0); // 0 = disable , 1 = enable
s->set_ae_level(s, 0); // -2 to 2
s->set_aec_value(s, 300); // 0 to 1200
s->set_gain_ctrl(s, 1); // 0 = disable , 1 = enable
s->set_agc_gain(s, 0); // 0 to 30
s->set_gainceiling(s, (gainceiling_t)0); // 0 to 6
s->set_bpc(s, 0); // 0 = disable , 1 = enable
s->set_wpc(s, 1); // 0 = disable , 1 = enable
s->set_raw_gma(s, 1); // 0 = disable , 1 = enable
s->set_lenc(s, 1); // 0 = disable , 1 = enable
s->set_hmirror(s, 0); // 0 = disable , 1 = enable
s->set_vflip(s, 0); // 0 = disable , 1 = enable
s->set_dcw(s, 1); // 0 = disable , 1 = enable
s->set_colorbar(s, 0); // 0 = disable , 1 = enable
`

To Receive the Picture:

`void receivedCallback( uint32_t from, String &msg ) {
// Serial.printf("Received from %u msg=%s\n", from, msg.c_str());

DynamicJsonDocument jsonBufferFrom( 1024 + msg.length() );
DeserializationError error = deserializeJson( jsonBufferFrom, msg );
if ( error )
{
Serial.print( F( "DeserializeJson() failed: " ) );
Serial.println( error.c_str() );
return;
}
JsonObject rootFrom = jsonBufferFrom.as< JsonObject >();

if ( rootFrom.containsKey( "type" ) && String( "sensor" ).equals( rootFrom[ "type" ].as< String >() ) )
{
String msgTo;

  DynamicJsonDocument jsonBufferTo( 1024 + msg.length() );
  JsonObject rootTo = jsonBufferTo.to< JsonObject >();
  rootTo[ "nodeId" ] = rootFrom;
  rootTo[ "sensor" ] = rootFrom[ "packet" ][ "sensor" ].as< String >();
  rootTo[ "idPacket" ] = rootFrom[ "packet" ][ "idPacket" ].as< String >();
  rootTo[ "indexPacket" ] = rootFrom[ "packet" ][ "indexPacket" ].as< String >();
  rootTo[ "totalPackets" ] = rootFrom[ "packet" ][ "totalPackets" ].as< String >();
  rootTo[ "data" ] = rootFrom[ "packet" ][ "data" ].as< String >();
  serializeJson( rootTo, msgTo );

  Serial.println( msgTo );

}

}`

@chriswant
Copy link
Author

Sorry, Still a NOOB at Posting. I hope you can still understand what I'm trying to get across.

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