Loading images from FAT into Web Pages

Hello,

I will start my thread with a statement, I’m a newbie :stuck_out_tongue: and I really hope you can help me.

I’m working with an RCM 5400 Develompent Kit. I would like to display an image (bmp) stored on the FAT file system into the web page hosted on the board. The image will be received from a camera module (C3088 with an OV6620 image sensor) and stored on the file system. My problem is how to specify the path in the hosted web page or how to use the zserver (if it is possible to do such a thing with zserver) or RabbitWeb (if it is possible to do such a thing with RabbitWeb).

Thank You,
Square

There are several samples that show how to use zserver with the FAT filesystem to allow web access to both html and image files for serving web pages. Look specifically at files in the samples/tcpip/zserver and samples/tcpip/http/pages directories. The zserver directory has FAT_SETUP.C which copies a set group of files to the FAT filesytem to allow use of the FAT_SERVE.C or FAT_SERVE2.C samples.

These samples use files from the http/pages directory, so here you can see the html required to display an image file, such as rabbit1.gif or alice.jpg files. If the file you upload is to an already known name, then your html could be setup to display it. If it’s coming from the camera with a newly generated name, you would need to write code that could create the html file necessary to embed the image on a web page, or you would have to know the file name so you could state the name of the file directly in the http address. Either way, once you properly setup zserver to mount a FAT volume, any file on the partition is available through the web server, as long as the name and location of the file is known. Subdirectory paths are used in http addresses to access FAT files through zserver.

Hello,

Thanks for your answer. I’ve tried those examples you mentioned and they are working :D. I managed to copy an image and a site on the FAT file system using the FAT_SETUP application and I was able to access them while running the FAT_SERVE program.
But I have another question now. In case the site uploaded to the FAT is an .shtml file which uses .cgi-s how should I bind the .cgi actions to the handler functions from my program? I read in the Dynamic C TCP/IP manual Volume 2 (page 43) that if the HTTP_NO_FLASHSPEC macro is used then there is no point in using static resource tables. The examples I’ve seen define the connection between the .cgi and the handler function using the SSPEC_RESOURCE_FUNCTION(name, addr) inside the static resource table declaration (SSPEC_RESOURCETABLE_START … SSPEC_RESOURCETABLE_END).
And another thing, I couldn’t copy files with extensions longer than 3 characters onto the FAT file system, probably because the FAT12/FAT16 doesn’t support long file names. So how should I save an .shtml file on the file system, what should the extension be ?
I’m so confused :confused:, it would be great if you could help me :slight_smile:

Thanks,
Square

Hello,

I’ve found out some thing since my last post.

So when using the HTTP_NO_FLASHSPEC macro the .cgi should be declared in the dynamic resource table. And for this the sspec_addCGI() function is used. Also for adding the variables (that are used in my shtml site stored on the FAT file system) the sspec_addvariable() function has to be invoked. So far so good. But there appears to be a problem (probably I didn’t do something). My variables are loaded correctly (so I can see their values on the site) but the .cgi-s aren’t working. When I click on either of the links my browser shows the 404 error, not found.
I will put below the code from the .shtml and the .c :

the shtml code:


	
		
			 
			 
				[ ](/upAction.cgi) 
			
			 
		
		
			 
				[ ](/leftAction.cgi) 
			
			 
				
			 
				[](/rightAction.cgi)
			
		
		
			 
			
				[](/downAction.cgi)
			 
		
	
	 Action:  

and the c code:

  
   sspec_addCGI("/upAction.cgi", upAction, SERVER_HTTP);
   sspec_addCGI("/downAction.cgi", downAction, SERVER_HTTP);
   sspec_addCGI("/leftAction.cgi", leftAction, SERVER_HTTP);
   sspec_addCGI("/rightAction.cgi", rightAction, SERVER_HTTP);
   sspec_addvariable("direction", direction, PTR16, "%s", SERVER_HTTP);

I’ve checked the return values of the sspec_addCGI functions, and their are positive, which should mean that they were successfully added to the spec index.

I know I’m missing something and that’s why it isn’t working. I just can’t find out what.

Hope you can help me out.

Thanks,
Square

Sounds like you’re pretty close. To answer an earlier question, we save our shtml files with .ssi extensions. Make sure you have the table for mapping file extensions like this:

SSPEC_MIMETABLE_START
	SSPEC_MIME_FUNC(".ssi", "text/html", shtml_handler),
	SSPEC_MIME(".htm", "text/html"),
	SSPEC_MIME(".cgi", ""),
	SSPEC_MIME(".gif", "image/gif"),
SSPEC_MIMETABLE_END

The other question is are you triggering a page reload within you CGI’s? When you change the variable, you have to force the browser to update the page to be able to display the change in variable. Look at http\pages\ssi2_fat.c and you will see each of the led toggling CGI’s has a call to the cgi_redirectto function.

int led3toggle(HttpState* state)
{
   if (strcmp(led3,LEDON)==0)
      strcpy(led3,LEDOFF);
   else
      strcpy(led3,LEDON);

   add_audit(state, 3);

   cgi_redirectto(state,REDIRECTTO);
   return 0;
}

The macro REDIRECTTO is defined with the path and filename of the .ssi file for the shtml page. This forces an update of the page on the browser window. You can also use the same mechanism that you’re using for displaying your variable in text format to select a dynamic image file. Look at http/pages/ssi.shtml and you can see the 4 img tags which use variable strings in led1 - led4 to select which image file to display. These strings simply hold the path and filename of the .gif file to be shown. Hope this fixes your problem.

Hello,

Thanks for your reply, but I still couldn’t make it work.
I’ve been using the cgi_redirectto() function you mentioned, but I don’t think it even gets to that point. I’m using DHCP so I don’t know my IP address in advance, and I’m using a function (similar to the one in the Browseled example) to generate the link for the redirectto. And each time this function is invoked I print the address that is generated, but when I run my program nothing appears, so I presume the method is never invoked.
I think that the program doesn’t recognize the .cgi actions from my .ssi site and thus can’t call the handler functions.

I was thinking about posting my whole code here in the forum, I know it’s an ugly thing to do, but you’ll probably spot my mistake, I just can’t figure out what’s wrong.

The code for the ssi site:




	Web Server Test



	
		
			 
			 [ ](/upAction.cgi) 
			 
		
		
			 [ ](/leftAction.cgi) 
			 
			 [ ](/rightAction.cgi) 
		
		
			 
			 [ ](/downAction.cgi) 
			 
		
	
	
	 Action:  
	 LED1 frequency: ms on/off
	 LED2 frequency: ms on/off
	

The code for the program:

#class auto

#use "RCM54xxW.lib"

#define DS2 0
#define DS3 1

#define DS2_BIT 2
#define DS3_BIT 3

/***********************************
 * Configuration                   *
 ***********************************/
#define FAT_BLOCK

#define FAT_USE_FORWARDSLASH
#define HTTP_NO_FLASHSPEC			

#define USE_DHCP
#define TCPCONFIG					1
#define _PRIMARY_STATIC_IP    "192.168.1.120"
#define WIFI_USE_WPA
#define WIFI_AES_ENABLED
#define IFC_WIFI_SSID "HRBH"
#define IFC_WIFI_ENCRYPTION IFPARAM_WIFI_ENCR_TKIP
#define IFC_WIFI_WPA_PSK_PASSPHRASE "gretzky6"
#define WIFI_VERBOSE_PASSPHRASE
#define TCP_BUF_SIZE 2048
#define HTTP_MAXSERVERS 1
#define MAX_TCP_SOCKET_BUFFERS 1

/********************************
 * End of configuration section *
 ********************************/

#define REDIRECTTO 		myurl()

#memmap xmem
#use "fat.lib"
#use "dcrtcp.lib"
#use "http.lib"

SSPEC_MIMETABLE_START
   SSPEC_MIME_FUNC(".ssi", "text/html", shtml_handler),
	SSPEC_MIME( ".html", "text/html"),
	SSPEC_MIME( ".png", "image/png"),
	SSPEC_MIME( ".bmp", "image/bmp"),
	SSPEC_MIME( ".cgi", ""),
SSPEC_MIMETABLE_END

char direction[15];
char cf1[10];
char cf2[10];

int f1;
int f2;

char *myurl() {
	static char URL[64];
   char tmpstr[32];
   long ipval;

   ifconfig(IF_DEFAULT, IFG_IPADDR, &ipval, IFS_END);
   sprintf(URL, "http://%s/A/index.ssi", inet_ntoa(tmpstr, ipval));
   printf("
 My URL: %s", URL);
   return URL;
}

void pbledon(int led)
{
	if(led == DS2)
   	BitWrPortI(PBDR, &PBDRShadow, 0, DS2_BIT);
	else
   	BitWrPortI(PBDR, &PBDRShadow, 0, DS3_BIT);
}

void pbledoff(int led)
{
	if(led == DS2)
   	BitWrPortI(PBDR, &PBDRShadow, 1, DS2_BIT);
	else
   	BitWrPortI(PBDR, &PBDRShadow, 1, DS3_BIT);
}

int upAction(HttpState* state)
{
   strcpy(direction, "up");
   if (f1 <= 500) {
   	f1 += 50;
   }
	cgi_redirectto(state,REDIRECTTO);
   return 0;
}

int leftAction(HttpState* state)
{
   strcpy(direction, "left");
   if (f2 <= 500) {
   	f2 += 50;
   }
  	cgi_redirectto(state,REDIRECTTO);
	return 0;
}

int rightAction(HttpState* state)
{
	strcpy(direction, "right");
	if (f2 >= 100) {
   	f2 -= 50;
   }
	cgi_redirectto(state,REDIRECTTO);
   return 0;
}

int downAction(HttpState* state)
{
	strcpy(direction, "down");
	if (f1 >= 100) {
   	f1 -= 50;
   }
	cgi_redirectto(state,REDIRECTTO);
	return 0;
}

void main()
{
   int rc;
   char buf[20];
   int myspec;

   strcpy(direction, "n/a");

   f1 = 300;
   f2 = 300;

   brdInit();

   sspec_addCGI("/upAction.cgi", upAction, SERVER_HTTP);
   sspec_addCGI("/downAction.cgi", downAction, SERVER_HTTP);
   sspec_addCGI("/leftAction.cgi", leftAction, SERVER_HTTP);
   sspec_addCGI("/rightAction.cgi", rightAction, SERVER_HTTP);

   sspec_addvariable("direction", direction, PTR16, "%s", SERVER_HTTP);
   sspec_addvariable("cf1", cf1, PTR16, "%s", SERVER_HTTP);
   sspec_addvariable("cf2", cf2, PTR16, "%s", SERVER_HTTP);

   printf("Initializing filesystem...
");

   rc = sspec_automount(SSPEC_MOUNT_ANY, NULL, NULL, NULL);
   if (rc)
   	printf("Failed to initialize, rc=%d
Proceeding anyway...
", rc);

   printf ("Configuring interface for DHCP
");
   ifconfig(IF_WIFI0, IFS_DHCP, 3, IFS_END);

   sock_init_or_exit(1);
   http_init();
   http_set_path("/A/", "index.ssi");

   tcp_reserveport(80);

   printf("Your IP://%s/
", inet_ntoa(buf, MY_ADDR(IF_DEFAULT)));
   printf("
Press any key to bring down the server cleanly.
");

   while (1) {

      http_handler();

      if (kbhit())
      {
         fat_UnmountDevice(sspec_fatregistered(0)->dev);
         exit(0);
      }

      sprintf(cf1, "%d", f1);
      sprintf(cf2, "%d", f2);

      costate
      {
         pbledon(DS2);
         waitfor(DelayMs(f1));
         pbledoff(DS2);
         waitfor(DelayMs(f1));
      }

      costate
      {
         pbledon(DS3);
         waitfor(DelayMs(f2));
         pbledoff(DS3);
         waitfor(DelayMs(f2));
      }
   }
}

The main idea of the program is to flash the LEDs of the board and change the frequency in case one of the buttons is pushed (buttons up and down control one LED and buttons left and right control the other led). The index.ssi file and the images used in the site are copied on the FAT file system. And the most interesting part (at least for me :p) is that the value of my variables (direction, cf1, cf2) are displayed, they are recognized, but the .cgi actions don’t work.

Sorry for this mess :stuck_out_tongue: but I’m desperate.

Thanks,
Square

When you use the http_set_path function, it declares the directory path given as the root of your http server. Therefore, addresses on the web side know nothing of the internal path on your file system. Your problem is that in your myurl function, you use the ‘A’ directory, which is not valid, it already is the root of the file structure hosted by the http server. So your myurl function should look like this:

char *myurl() {
	static char URL[64];
   char tmpstr[32];
   long ipval;

   ifconfig(IF_DEFAULT, IFG_IPADDR, &ipval, IFS_END);
   sprintf(URL, "http://%s/index.ssi", inet_ntoa(tmpstr, ipval));
   printf("
 My URL: %s", URL);
   return URL;
}

Hello,

Thanks for your reply. Unfortunately it doesn’t seem to work with the URL correction.
I think it doesn’t even get to that point to call the myurl() function or the cgi handler functions (If I add a simple printf() into the body of one of the handler functions nothing is shown in the stdio). I don’t think it recognizes the cgis coming from the website, or the cgi are not bound to the handler functions properly (maybe due to the run time binding?, I haven’t found any examples in which they use the sspec_addCGI() function).

I hope you can help me out.
Thanks,
Square

Try changing the tags referencing your cgi’s to include a period before the slash. For example:

Since you’re not restating the numerical address, use the period to make the new URL relative to the prior URL. Which browser are you using to test this?

Thanks for the fast answer. Do I have to change anything else besides the tag in the shtml code, because it’s still not working :frowning:
I’ve tried it in Mozilla Firefox (3.0.10) and in Internet Explorer (7.0.6).

Thanks,
Square

I didn’t put together when I saw your path declaration that this would make CGI’s impossible. Your root declaration is “/A/” not “/” which only gives the html server access to files on the FAT directory mounted as A. The CGI’s appear on the root directory that contains the A subdirectory, which allows access to a particular FAT partition. So your real problem is in the call to http_set_path. It should be:

http_set_path(“/”, “A/index.ssi”);

You will also need to change your myUrl function to include the A subdirectory as you originally had it.

Hi,

Thanks for the answers, it finally works. I didn’t have time lately working on this part of my project (I had some difficulties interfacing my C3088 camera module with the rabbit board through the I2C bus), but I managed correct the path issue today.
Although I’ve made some other changes in order to make it work and I don’t understand entirely why does it work this way, but the essence is that it works :). I had to comment the this define #define HTTP_NO_FLASHSPEC (I don’t know why I needed it in the first place, why did I need to have a dynamic resource table :slight_smile: ), I had to add a static resource table for my variables and my cgi-s, and I made another change in the myurl function. The URL which should be returned should not contain the /A/index.ssi at the end, it has to return only my IP address. All in all it works :slight_smile:

But now I have another question :). As I mentioned previously I would like to connect a camera module to the microcontroller and display the image in my website hosted on the flash of the rabbit mcu. Since the flash can be written only for a limited number of times (which may be quite high, but still limited) I would like to know if it is possible to display the image onto the website directly from the memory (SRAM) or somehow without writing to the flash. So I will receive the 8 bit image data, create the structure of a bmp image from the data onto a specific memory location, and display the image in the site from there.

Thanks again,
Square

Hi

I’ve found a solution to my previous problem, if anybody interested :P. I will save the image file in the extended memory and I will be able to include it into the website from there. This way I won’t need the files stored on the FAT file system.

Square