Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Development
  3. Sending image-data over the MySensors network.

Sending image-data over the MySensors network.

Scheduled Pinned Locked Moved Development
27 Posts 9 Posters 15.8k Views 11 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • OitzuO Oitzu

    The Perl-Script i'm using instead of a controller, because obviously no controller supports this yet.

    #!/usr/bin/perl
    use Device::SerialPort;
    use POSIX qw(strftime);
    use Data::Dumper;
    use Time::HiRes qw (sleep);
    use Time::HiRes qw(time);
    my $port = Device::SerialPort->new("/dev/ttyUSB1");
    $| = 1;
    use Time::HiRes qw(time);
    
    $port->baudrate(115200);
    $port->databits(8);
    $port->parity("none");
    $port->stopbits(1);
    
    my $buffer;
    my %transfers;
    
    print "Waiting for incoming transfers...\n";
    
    while (1) {
    	my ($count,$saw)=$port->read(256);
    	if($count > 0 || length($buffer) > 0)
    	{
    		$buffer .= $saw;
    		my ($cmd, $rest) = split(/\n/, $buffer, 2);
    		if(defined($rest))
    		{
    			if(@m = $cmd =~ /([0-9]*);([0-9]*);([0-9]*);([0-9]*);([0-9]*);(.*)/g)
    			{
    				my ($node_id, $child_sensor_id, $message_type, $ack, $sub_type, $payload) = @m;
    		#		print "node_id: $node_id, child_sensor_id: $child_sensor_id, message_type: $child_sensor_id, ack: $ack, sub_type: $sub_type, payload: $payload \n";
    				if($sub_type eq "25")
    				{
    					if($payload eq "START" && $transfers{$node_id}{'state'} == 0)
    					{
    						print "New transfer incoming from node $node_id.\n";
    						$transfers{$node_id}{'start_time'} = time();
    						$transfers{$node_id}{'state'} = 1;
    						$transfers{$node_id}{'count'} = 0;
    						my $time = strftime("%Y-%m-%d-%H-%M-%S", localtime);
    						open ($transfers{$node_id}{'FH'}, ">>node-".$node_id."-".$time.".jpg");
    						binmode($transfers{$node_id}{'FH'});
    					}
    					
    					if($payload eq "END" && $transfers{$node_id}{'state'} == 1)
    					{
    						close($transfers{$node_id}{'FH'});
    						$transfers{$node_id}{'state'} = 0;
    						my $duration = time() - $transfers{$node_id}{'start_time'};
    						my $bps = $transfers{$node_id}{'count'} * 24 / $duration;
    						my $pps = $transfers{$node_id}{'count'} / $duration;
    						print "Transfer from $node_id finished.\n";
    						print "$duration seconds, $bps Bytes/s, $pps Packets/s\n";
    					}
    				}
    				elsif($sub_type eq "24")
    				{
    					if($transfers{$node_id}{'state'} == 1)
    					{
    						$transfers{$node_id}{'count'}++;
    						print { $transfers{$node_id}{'FH'} } pack('H*',$payload);
    					}
    				}
    			}
    			$buffer = $rest;
    		}
    	}
            #Check for timeout
            while(($node_id) = each %transfers)
            {
    	        my $duration = time() - $transfers{$node_id}{'start_time'};
                   	if($duration > 120 && $transfers{$node_id}{'state'} == 1)
                    {
                    	close($transfers{$node_id}{'FH'});
                            $transfers{$node_id}{'state'} = 0;
                            print "Warning: Timeout from node $node_id. Transfer cancelled.\n";
                    }
    	}
    	sleep (0.001);
    }
    

    The sketch:

    #include <MySensor.h>
    #include <SPI.h>
    #include <Adafruit_VC0706.h>
    #include <SoftwareSerial.h>
    
    #undef DEBUG
    
    SoftwareSerial cameraConnection = SoftwareSerial(6,7);
    
    Adafruit_VC0706 cam = Adafruit_VC0706(&cameraConnection);
    
    #define CHILD_ID 3
    
    MySensor gw;
    MyMessage msg(CHILD_ID,V_VAR1);
    MyMessage msg2(CHILD_ID,V_VAR2);
    
    void setup()  
    {  
      gw.begin();
    
      gw.present(CHILD_ID, S_CUSTOM);  
      
      if (cam.begin()){}
      else { return; } //Abort the transfer if camera does not initialize
    
      cam.setImageSize(VC0706_640x480);
      delay(3000);
      snapAndSend();
      cam.reset();
    }
    
    //Do nothing.
    void loop() 
    {
    
    }
    
    void snapAndSend()
    {
      cam.takePicture();
      uint16_t jpgLen = cam.frameLength();
      Serial.print("Sending Picture of ");
      Serial.print(jpgLen, DEC);
      Serial.println(" Bytes.");
      gw.send(msg2.set("START"));
      while (jpgLen > 0)
      {                     //Send off 24 bytes of data at a time
        uint8_t *buffer;
        uint8_t bytesToRead = min(24, jpgLen);
        buffer = cam.readPicture(bytesToRead);
        gw.send(msg.set(buffer, bytesToRead));
        jpgLen -= bytesToRead;
      }
      Serial.println("Done.");
      gw.send(msg2.set("END"));
    }
    

    Hardware:
    Typical MySensors-Node and a Serial TTL Camera like this:
    http://aliexpress.com/item/NEW-RS232-TTL-JPEG-Digital-Serial-Port-CCTV-Camera-Module-SCB-1-with-video-out-Support/1975852463.html

    2015-07-30 19.38.29 - Kopie.jpg

    tekkaT Offline
    tekkaT Offline
    tekka
    Admin
    wrote on last edited by
    #14

    @Oitzu nice, I'll think about implementing this in MYSController for testing purposes.

    1 Reply Last reply
    0
    • OitzuO Offline
      OitzuO Offline
      Oitzu
      wrote on last edited by Oitzu
      #15

      @hek said:

      Yes, would be nice to free up some payload space for this type of data.

      Just a bit worried about allocating things (dynamically or statically) for the stream information (beside the extra code). Pretty cramped already.

      I think by deactivating not used features with pre-compile directives this problem could be solved. Need to look into this again. But i remember there are large chunks of unused code compiled in if you, by example, only want to use the lib for a "pure" node.

      What happens if you just increase the RF24 datarate in MyConfig? Do you lose much data?

      Didn't tried yet. The target for this application is a long range communication. So i keeped the datarate low in my tests.
      BUT i need to note: Most of the 40 seconds, at this moment, is probably a result of the slow UART connection to the camera. The camera-chip has spi but it isn't breaked out on the board. There are boards out there with the same chip + SPI! Users reported the transfer over SPI to the MCU takes about 1 second!

      @tekka nice to hear. :) Let me know if i can support somehow.

      1 Reply Last reply
      0
      • OitzuO Offline
        OitzuO Offline
        Oitzu
        wrote on last edited by
        #16

        Update!
        I changed the camera to a faster SPI model.
        http://de.aliexpress.com/item/ArduCAM-M-2MP-Camera-Shield-OV2640-2MP-SPI-Camera-module/32307177889.html?ws_ab_test=201407_5,201444_5,201409_3

        The camera delivers a 2MP picture in under 1 seconds over SPI.

        But i'm running in a dead end, with MySensors not supporting proper streams.
        A 2MP (100kb) takes about 20 seconds with MySensors.
        Main problem atm is IMHO with the mysensors transmitting style:

        	rf24.powerUp();
        	rf24.stopListening();
        	rf24.openWritingPipe(TO_ADDR(to));
        	bool ok = rf24.write(data, len, to == BROADCAST_ADDRESS);
        	rf24.startListening();
        	return ok;
        

        would be more effective to do something like:

        	rf24.powerUp();
        	rf24.stopListening();
        	rf24.openWritingPipe(TO_ADDR(to));
        ///loop here over more than 1 packet
        
        rf24.writeFast(data, len, to == BROADCAST_ADDRESS);
        
        //end of loop
        	rf24.startListening();
        	return ok;
        

        The stopListening -> openWritingPipe -> startListening just takes to much time.

        Unfortunately i failed a try to implement this... it seems i'm just not experienced enough.

        1 Reply Last reply
        0
        • T Offline
          T Offline
          thomas1412
          wrote on last edited by
          #17

          Hi,

          I'm currently trying to use your solution, @Oitzu.
          The Node-part is working fine. Have a little problem on the Pi-side.
          The RF-device is directly connected to the Pi, so I'm using a Serial Gateway script on the Pi (https://github.com/mysensors/Raspberry). The serial data is then send over /dev/ttyUSB20, that is working fine.
          I know that I need to adjust the following lines of the Perl script:

          use Device::SerialPort;
          use POSIX qw(strftime);
          use Data::Dumper;
          use Time::HiRes qw (sleep);
          use Time::HiRes qw(time);
          my $port = Device::SerialPort->new("/dev/ttyUSB1");
          

          But it seems I'm just to stupid to do this by myself :grin:
          I would suggest that I can delete the first line and change the last line to something like this:

          my $port = "/dev/ttyUSB20";
          

          Can someone help me with the right syntax?

          Thanks!

          1 Reply Last reply
          0
          • OitzuO Offline
            OitzuO Offline
            Oitzu
            wrote on last edited by Oitzu
            #18

            @thomas1412 said:

            Hi,

            I'm currently trying to use your solution, @Oitzu.
            The RF-device is directly connected to the Pi, so I'm using a Serial Gateway script on the Pi (https://github.com/mysensors/Raspberry). The serial data is then send over /dev/ttyUSB20, that is working fine.
            I know that I need to adjust the following lines of the Perl script:

            use Device::SerialPort;
            use POSIX qw(strftime);
            use Data::Dumper;
            use Time::HiRes qw (sleep);
            use Time::HiRes qw(time);
            my $port = Device::SerialPort->new("/dev/ttyUSB1");
            

            But it seems I'm just to stupid to do this by myself :grin:
            I would suggest that I can delete the first line and change the last line to something like this:

            my $port = "/dev/ttyUSB20";
            

            Can someone help me with the right syntax?

            The RPi Serial Gateway creates a symlink "/dev/ttyMySensorsGateway" you should use that as Device for more consistent results.

            I srsly don't know why you would delete the first line. I'm pretty sure you need to use the Device::Serialport Perl-Module. ;)

            Also try to run the script as root. The created device files tend to have root-only access rights.

            1 Reply Last reply
            0
            • T Offline
              T Offline
              thomas1412
              wrote on last edited by
              #19

              Hi,

              thanks for the quick reply and your help
              It turned out my problem was the not installed serialport perl library.. Now I'm a step further.
              Unfortunately there's another problem now.. :smile:
              After sending three or four packages the next six packages are failing to send. And this over and over again.
              Seems that the SerialGateway is too slow in some way..

              send: 254-254-0-0 s=255,c=0,t=17,pt=0,l=5,sg=0,st=ok:1.5.1
              send: 254-254-0-0 s=255,c=3,t=6,pt=1,l=1,sg=0,st=ok:0
              sensor started, id=254, parent=0, distance=1
              send: 254-254-0-0 s=3,c=0,t=23,pt=0,l=0,sg=0,st=ok:
              Sending Picture of 13048 Bytes.
              send: 254-254-0-0 s=3,c=1,t=25,pt=0,l=5,sg=0,st=ok:START
              send: 254-254-0-0 s=3,c=1,t=24,pt=6,l=24,sg=0,st=ok:FFD8FFFE00244900020D0000000000000000000000000000
              send: 254-254-0-0 s=3,c=1,t=24,pt=6,l=24,sg=0,st=ok:00F0004001070032120B510451040000FFDB008400020101
              send: 254-254-0-0 s=3,c=1,t=24,pt=6,l=24,sg=0,st=ok:020101020201020202020203040303020203050404030406
              send: 254-254-0-0 s=3,c=1,t=24,pt=6,l=24,sg=0,st=fail:0607070606060607080A0907070A080606090C090A0A0B0B
              send: 254-254-0-0 s=3,c=1,t=24,pt=6,l=24,sg=0,st=fail:0B0B07080C0D0C0B0D0A0B0B0B0102020203020305030305
              send: 254-254-0-0 s=3,c=1,t=24,pt=6,l=24,sg=0,st=fail:0B0706070B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
              send: 254-254-0-0 s=3,c=1,t=24,pt=6,l=24,sg=0,st=fail:0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B
              send: 254-254-0-0 s=3,c=1,t=24,pt=6,l=24,sg=0,st=fail:0B0B0B0B0B0BFFFE0005000000FFC000110800F001400301
              send: 254-254-0-0 s=3,c=1,t=24,pt=6,l=24,sg=0,st=fail:2100021101031101FFC401A2000001050101010101010000```
              1 Reply Last reply
              0
              • hekH Offline
                hekH Offline
                hek
                Admin
                wrote on last edited by
                #20

                Might be a powering issue of the radio. Put a bigger cap on it.

                1 Reply Last reply
                0
                • T Offline
                  T Offline
                  thomas1412
                  wrote on last edited by
                  #21

                  Adding a capacitor hasn't helped.
                  I changed the setup using now a serial gateway on a separate Arduino instead of having it directly on the Pi. This is working fine. So it seems that the serial gateway on the Pi was the problem..

                  OitzuO 1 Reply Last reply
                  1
                  • T thomas1412

                    Adding a capacitor hasn't helped.
                    I changed the setup using now a serial gateway on a separate Arduino instead of having it directly on the Pi. This is working fine. So it seems that the serial gateway on the Pi was the problem..

                    OitzuO Offline
                    OitzuO Offline
                    Oitzu
                    wrote on last edited by Oitzu
                    #22

                    @thomas1412 said:

                    This is working fine. So it seems that the serial gateway on the Pi was the problem..

                    I tested this, and yes, the Pi serial gateway seems to be the problem, clogging up on some point and stops.
                    The problem itself seems to be in the pseudo terminal created. If i rewrite the gateway that the data with type 24 (image data) is not written to the pseudo terminal the sending works fine.

                    The Pi serial gateway has atm afaik no maintainer and needs some love.

                    1 Reply Last reply
                    0
                    • Zied BEN HAMMOUDZ Offline
                      Zied BEN HAMMOUDZ Offline
                      Zied BEN HAMMOUD
                      wrote on last edited by
                      #23

                      Hello, this is my first arduino project: sending a file (jpeg, pdf, txt) from an arduino sd card module to android phone using arduino uno and bluetooth module HC-05
                      It's possible with this hardware?

                      If it's possible can someone please send me the source code and android app use it to receive the file
                      thank you

                      hekH 1 Reply Last reply
                      0
                      • Zied BEN HAMMOUDZ Zied BEN HAMMOUD

                        Hello, this is my first arduino project: sending a file (jpeg, pdf, txt) from an arduino sd card module to android phone using arduino uno and bluetooth module HC-05
                        It's possible with this hardware?

                        If it's possible can someone please send me the source code and android app use it to receive the file
                        thank you

                        hekH Offline
                        hekH Offline
                        hek
                        Admin
                        wrote on last edited by
                        #24

                        @Zied-BEN-HAMMOUD

                        I doubt anyone has the sourcecode ready for an app/sketch shuffling data over bluetooth. The MySensors library doesn't handle bluetooth communication so you should probably look elsewhere.

                        1 Reply Last reply
                        1
                        • D Offline
                          D Offline
                          dimi59
                          wrote on last edited by
                          #25

                          Hello,
                          It’s possible to use à esp32-cam and add a module for transmit one photo ?
                          Thanks a lot

                          1 Reply Last reply
                          0
                          • rejoe2R Offline
                            rejoe2R Offline
                            rejoe2
                            wrote on last edited by
                            #26

                            I've been looking around a bit, but beside the example Perl script provided by @thomas1412 and the STREAM type usage in the OTA feature, there seems not to exist any working solution using really the stream type message structure. But this is more or less receiving only on the node side afai understood.

                            As I'm about to do some renovation work on the FHEM integration (also written in Perl), I'd be interested in some guidelines about the best way to transfer e.g. jpeg data as stream from node side.
                            The sample sketch @thomas1412 provided uses not stream type, but V_VAR1 (data) and V_VAR2 (signalizing start and end).

                            I'd be happy if someone could provide a sample sketch using the newer (?) stream type sending style or a link to the relevant parts in the MySensors codebase...

                            Controller: FHEM; MySensors: 2.3.1, RS485,nRF24,RFM69, serial Gateways

                            1 Reply Last reply
                            0
                            • OitzuO Oitzu

                              The Perl-Script i'm using instead of a controller, because obviously no controller supports this yet.

                              #!/usr/bin/perl
                              use Device::SerialPort;
                              use POSIX qw(strftime);
                              use Data::Dumper;
                              use Time::HiRes qw (sleep);
                              use Time::HiRes qw(time);
                              my $port = Device::SerialPort->new("/dev/ttyUSB1");
                              $| = 1;
                              use Time::HiRes qw(time);
                              
                              $port->baudrate(115200);
                              $port->databits(8);
                              $port->parity("none");
                              $port->stopbits(1);
                              
                              my $buffer;
                              my %transfers;
                              
                              print "Waiting for incoming transfers...\n";
                              
                              while (1) {
                              	my ($count,$saw)=$port->read(256);
                              	if($count > 0 || length($buffer) > 0)
                              	{
                              		$buffer .= $saw;
                              		my ($cmd, $rest) = split(/\n/, $buffer, 2);
                              		if(defined($rest))
                              		{
                              			if(@m = $cmd =~ /([0-9]*);([0-9]*);([0-9]*);([0-9]*);([0-9]*);(.*)/g)
                              			{
                              				my ($node_id, $child_sensor_id, $message_type, $ack, $sub_type, $payload) = @m;
                              		#		print "node_id: $node_id, child_sensor_id: $child_sensor_id, message_type: $child_sensor_id, ack: $ack, sub_type: $sub_type, payload: $payload \n";
                              				if($sub_type eq "25")
                              				{
                              					if($payload eq "START" && $transfers{$node_id}{'state'} == 0)
                              					{
                              						print "New transfer incoming from node $node_id.\n";
                              						$transfers{$node_id}{'start_time'} = time();
                              						$transfers{$node_id}{'state'} = 1;
                              						$transfers{$node_id}{'count'} = 0;
                              						my $time = strftime("%Y-%m-%d-%H-%M-%S", localtime);
                              						open ($transfers{$node_id}{'FH'}, ">>node-".$node_id."-".$time.".jpg");
                              						binmode($transfers{$node_id}{'FH'});
                              					}
                              					
                              					if($payload eq "END" && $transfers{$node_id}{'state'} == 1)
                              					{
                              						close($transfers{$node_id}{'FH'});
                              						$transfers{$node_id}{'state'} = 0;
                              						my $duration = time() - $transfers{$node_id}{'start_time'};
                              						my $bps = $transfers{$node_id}{'count'} * 24 / $duration;
                              						my $pps = $transfers{$node_id}{'count'} / $duration;
                              						print "Transfer from $node_id finished.\n";
                              						print "$duration seconds, $bps Bytes/s, $pps Packets/s\n";
                              					}
                              				}
                              				elsif($sub_type eq "24")
                              				{
                              					if($transfers{$node_id}{'state'} == 1)
                              					{
                              						$transfers{$node_id}{'count'}++;
                              						print { $transfers{$node_id}{'FH'} } pack('H*',$payload);
                              					}
                              				}
                              			}
                              			$buffer = $rest;
                              		}
                              	}
                                      #Check for timeout
                                      while(($node_id) = each %transfers)
                                      {
                              	        my $duration = time() - $transfers{$node_id}{'start_time'};
                                             	if($duration > 120 && $transfers{$node_id}{'state'} == 1)
                                              {
                                              	close($transfers{$node_id}{'FH'});
                                                      $transfers{$node_id}{'state'} = 0;
                                                      print "Warning: Timeout from node $node_id. Transfer cancelled.\n";
                                              }
                              	}
                              	sleep (0.001);
                              }
                              

                              The sketch:

                              #include <MySensor.h>
                              #include <SPI.h>
                              #include <Adafruit_VC0706.h>
                              #include <SoftwareSerial.h>
                              
                              #undef DEBUG
                              
                              SoftwareSerial cameraConnection = SoftwareSerial(6,7);
                              
                              Adafruit_VC0706 cam = Adafruit_VC0706(&cameraConnection);
                              
                              #define CHILD_ID 3
                              
                              MySensor gw;
                              MyMessage msg(CHILD_ID,V_VAR1);
                              MyMessage msg2(CHILD_ID,V_VAR2);
                              
                              void setup()  
                              {  
                                gw.begin();
                              
                                gw.present(CHILD_ID, S_CUSTOM);  
                                
                                if (cam.begin()){}
                                else { return; } //Abort the transfer if camera does not initialize
                              
                                cam.setImageSize(VC0706_640x480);
                                delay(3000);
                                snapAndSend();
                                cam.reset();
                              }
                              
                              //Do nothing.
                              void loop() 
                              {
                              
                              }
                              
                              void snapAndSend()
                              {
                                cam.takePicture();
                                uint16_t jpgLen = cam.frameLength();
                                Serial.print("Sending Picture of ");
                                Serial.print(jpgLen, DEC);
                                Serial.println(" Bytes.");
                                gw.send(msg2.set("START"));
                                while (jpgLen > 0)
                                {                     //Send off 24 bytes of data at a time
                                  uint8_t *buffer;
                                  uint8_t bytesToRead = min(24, jpgLen);
                                  buffer = cam.readPicture(bytesToRead);
                                  gw.send(msg.set(buffer, bytesToRead));
                                  jpgLen -= bytesToRead;
                                }
                                Serial.println("Done.");
                                gw.send(msg2.set("END"));
                              }
                              

                              Hardware:
                              Typical MySensors-Node and a Serial TTL Camera like this:
                              http://aliexpress.com/item/NEW-RS232-TTL-JPEG-Digital-Serial-Port-CCTV-Camera-Module-SCB-1-with-video-out-Support/1975852463.html

                              2015-07-30 19.38.29 - Kopie.jpg

                              G Offline
                              G Offline
                              Guillermo Schimmel
                              wrote on last edited by
                              #27

                              @Oitzu Great work. Looking forward to use it. I have a use for this (some remote roof drain that gets clogged with leaves). Thanks!

                              1 Reply Last reply
                              0
                              Reply
                              • Reply as topic
                              Log in to reply
                              • Oldest to Newest
                              • Newest to Oldest
                              • Most Votes


                              16

                              Online

                              11.7k

                              Users

                              11.2k

                              Topics

                              113.1k

                              Posts


                              Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                              • Login

                              • Don't have an account? Register

                              • Login or register to search.
                              • First post
                                Last post
                              0
                              • MySensors
                              • OpenHardware.io
                              • Categories
                              • Recent
                              • Tags
                              • Popular