Final 350 project
Dependencies: uzair Camera_LS_Y201 F7_Ethernet LCD_DISCO_F746NG NetworkAPI SDFileSystem mbed
Diff: main.cpp
- Revision:
- 0:791a779d6220
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Jul 31 09:16:35 2017 +0000 @@ -0,0 +1,653 @@ +#include "mbed.h" +#include "SDFileSystem.h" +#include <jpeglib.h> //convert +#include <stdio.h> //convert +#include <stdlib.h> //convert +#include <string.h> //convert +#include "LCD_DISCO_F746NG.h" //screen +#include "EthernetInterface.h" //lan +#define EnDebugMSG false //true-> print debug message +#include "filelib.h" +#define IP "192.168.240.100" +#define MASK "255.255.255.0" +#define GATEWAY "192.168.240.1" +#define PORT 80 +#define DEBMSG printf +#define NEWLINE() printf("\r\n") +#if USE_SDCARD +#define FILENAME "/sd/IMG_%04d.jpg" +#else +#define FILENAME "/sd/IMG_%04d.jpg" +SDFileSystem sd("sd"); +#endif + + +DigitalIn pb(USER_BUTTON); +LCD_DISCO_F746NG lcd; + + +//lan module +char sMethod[7]; +char sURL[250]; +char sProtocol[8]; +EthernetInterface eth; +TCPSocketServer svr; +bool serverIsListened = false; +TCPSocketConnection client; +bool clientIsConnected = false; +char sentBuffer[1072] = {}; // 2*536=1072, 3*536=1608, 4*536=2144 +char line_response[256]= {0}; +char file_path[256] = {0}; +DigitalOut led1(LED1); //server listning status +DigitalOut led2(LED2); //socket connecting status +Ticker ledTick; +//~lan module + +//convert module +unsigned char *raw_image = NULL; + +typedef struct work +{ + FILE *fp; +} work_t; +work_t work; + +void callback_func(int done, int total, uint8_t *buf, size_t siz) +{ + fwrite(buf, siz, 1, work.fp); + static int n = 0; + int tmp = done * 100 / total; + if (n != tmp) + { + n = tmp; + DEBMSG("Writing...: %3d%%", n); + NEWLINE(); + } +} + +/* dimensions of the image we want to write */ +int width; +int height; +int bytes_per_pixel; + +/* or 1 for GRACYSCALE images */ +int color_space; /* or JCS_GRAYSCALE for grayscale images */ + +typedef struct{ + long filesize; + char reserved[2]; + long headersize; + long infoSize; + long width; + long depth; + short biPlanes; + short bits; + long biCompression; + long biSizeImage; + long biXPelsPerMeter; + long biYPelsPerMeter; + long biClrUsed; + long biClrImportant; +} BMPHEAD; +// ~convertjpegtobmp + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// convert .jpeg image to .bmp image // +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int Convert_output(char *filename) +{ + sd.mount(); + + BMPHEAD bh; + + memset((char *)&bh, 0, sizeof(BMPHEAD)); /* sets everything to 0 */ + bh.headersize = 54L; //for 24 bit images) + bh.infoSize = 0x28L; //for 24 bit images) + bh.width = width; //in pixels of your image + bh.depth = height; // in pixels of your image + bh.biPlanes = 1; //for 24 bit images) + bh.bits = 24; //for 24 bit images) + bh.biCompression = 0L;; //no compression) + + int bytesPerLine; + + bytesPerLine = width * 3; /* (for 24 bit images) */ + /* round up to a dword boundary */ + if (bytesPerLine & 0x0003) + { + bytesPerLine |= 0x0003; + ++bytesPerLine; + } + bh.filesize = bh.headersize + (long)bytesPerLine*bh.depth; + + FILE * bmpfile; + + printf("Bytes per line : %d\n", bytesPerLine); + + bmpfile = fopen(filename, "wb"); + if (bmpfile == NULL) + { + printf("Error opening output file\n"); + /* -- close all open files and free any allocated memory -- */ + exit(1); + } + fwrite("BM", 1, 2, bmpfile); + fwrite((char *)&bh, 1, sizeof(bh), bmpfile); + + char *linebuf; + + linebuf = (char *)calloc(1, bytesPerLine); + if (linebuf == NULL) + { + printf("Error allocating memory\n"); + free(raw_image); + /* -- close all open files and free any allocated memory -- */ + exit(1); + } + + + int line, x; + + for (line = height - 1; line >= 0; line--) + { + /* fill line linebuf with the image data for that line */ + for (x = 0; x < width; x++) + { + *(linebuf + x*bytes_per_pixel) = *(raw_image + (x + line*width)*bytes_per_pixel + 2); + *(linebuf + x*bytes_per_pixel + 1) = *(raw_image + (x + line*width)*bytes_per_pixel + 1); + *(linebuf + x*bytes_per_pixel + 2) = *(raw_image + (x + line*width)*bytes_per_pixel + 0); + } + fwrite(linebuf, 1, bytesPerLine, bmpfile); + } + free(linebuf); + fclose(bmpfile); + printf("bytes writing process complete"); +} + + +int Convert_input(char *filename) +{ + /* these are standard libjpeg structures for reading(decompression) */ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + /* libjpeg data structure for storing one row, that is, scanline of an image */ + JSAMPROW row_pointer[1]; + + FILE *infile = fopen(filename,"rb"); + unsigned long location = 0; + int i = 0; + + if (!infile) + { + printf("Error opening jpeg file %s\n!", filename); + return -1; + } + + /* here we set up the standard libjpeg error handler */ + cinfo.err = jpeg_std_error(&jerr); + /* setup decompression process and source, then read JPEG header */ + jpeg_create_decompress(&cinfo); + /* this makes the library read from infile */ + jpeg_stdio_src(&cinfo, infile); + /* reading the image header which contains image information */ + jpeg_read_header(&cinfo, TRUE); + /* Uncomment the following to output image information, if needed. */ + + printf("JPEG File Information: \n"); + printf("Image width and height: %d pixels and %d pixels.\n", width = cinfo.image_width, height = cinfo.image_height); + printf("Color components per pixel: %d.\n", bytes_per_pixel = cinfo.num_components); + printf("Color space: %d.\n", cinfo.jpeg_color_space); + + /* Start decompression jpeg here */ + jpeg_start_decompress(&cinfo); + + /* allocate memory to hold the uncompressed image */ + raw_image = (unsigned char*)malloc(cinfo.output_width*cinfo.output_height*cinfo.num_components); + /* now actually read the jpeg into the raw buffer */ + row_pointer[0] = (unsigned char *)malloc(cinfo.output_width*cinfo.num_components); + /* read one scan line at a time */ + while (cinfo.output_scanline < cinfo.image_height) + { + jpeg_read_scanlines(&cinfo, row_pointer, 1); + for (i = 0; i<cinfo.image_width*cinfo.num_components; i++) + raw_image[location++] = row_pointer[0][i]; + } + + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + free(row_pointer[0]); + fclose(infile); + return 1; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ~convert .jpeg image to .bmp image // +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// HTTP File SERVER // +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +void ledTickfunc() +{ + if(serverIsListened) + { + led1 = !led1; + } + else + { + led1 = false; + } +} + +void send_HTTP_header(char* protocol, int code, char* title, char* mime_type, long long lengthBody) +{ + snprintf(line_response, sizeof(line_response),"%s %d %s\r\n", protocol, code, title ); + snprintf(sentBuffer, sizeof(sentBuffer),"%s",line_response); + + if ( mime_type != NULL ) + { + snprintf(line_response, sizeof(line_response), "Content-Type: %s\r\n", mime_type ); + snprintf(sentBuffer, sizeof(sentBuffer), "%s%s",sentBuffer,line_response); //append to sentBuffer + } + if ( lengthBody >= 0 ) + { + snprintf(line_response, sizeof(line_response), "Content-Length: %lld\r\n", lengthBody ); + snprintf(sentBuffer, sizeof(sentBuffer), "%s%s",sentBuffer,line_response); //append to sentBuffer + } + snprintf(line_response, sizeof(line_response), "Connection: close\r\n" ); + snprintf(sentBuffer, sizeof(sentBuffer),"%s%s\r\n",sentBuffer,line_response); //append to sentBuffer + + if (EnDebugMSG) + printf("\r\n-->sent Header--\r\n"); + + client.send_all(sentBuffer,strlen(sentBuffer)); + + if (EnDebugMSG) + { + printf(sentBuffer); + printf("\r\n--end Header-- bytes:%d",strlen(sentBuffer)); + } + wait(0.2); //200ms important for browser! +} + +void send_HTML_line(char* line, unsigned int length_line) +{ + client.send_all(line,length_line); + if (EnDebugMSG) + printf("\r\n-->send HTML line:\r\n%s ...Ok!",line); + wait(0.01); +} + +void send_HTML_error( int status_code, char* title, char* body_text) +{ + send_HTTP_header("HTTP/1.1", status_code, title, "text/html", -1); + if (EnDebugMSG) + printf("\r\n-->send_error...\r\n"); + sentBuffer[0]=NULL; //clear buffer + sprintf(line_response, "<!DOCTYPE html>\r\n<html>\r\n<head>\r\n<title>%d %s</title>\r\n</head>\r\n", status_code, title); + snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer + sprintf(line_response, "<body><center><h2><center>%d %s</center></h2>\r\n",status_code, title ); + snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer + sprintf(line_response, "%s\r\n", body_text ); + snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer + sprintf(line_response, "<p>mbed HTTP File Server</p>\r\n</center></body></html>\r\n"); + snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer + send_HTML_line(sentBuffer, strlen(sentBuffer)); +} + + +int send_file(char *path_file) +{ + char *mime_type = {0}; + unsigned int bytes_for_send=0; + long long filesize, all_send_bytes = 0; + + mime_type = get_mime_type( path_file ); + snprintf(file_path, sizeof(file_path),"/sd/%s",path_file); + + if (EnDebugMSG) + { + printf("\r\n-->from send_file:%s",file_path); + printf("\r\n-->from send_file mime type:%s",mime_type); + } + + if (Mystat(path_file, &myStatBuf)) + { + //fault with file + send_HTML_error( 403, "Forbidden", "403 - File access forbidden."); + return 403; + } + + FILE* fp = NULL; + fp = fopen(file_path,"r"); + + if (fp==NULL ) + { + send_HTML_error( 403, "Forbidden", "403 - File access forbidden."); + return 403; + } + + filesize = myStatBuf.st_size; + send_HTTP_header("HTTP/1.1", 200, "Ok", mime_type, myStatBuf.st_size); + + //binary send + all_send_bytes=0; + + while(filesize) + { + //check for EOF !feof(fp) + bytes_for_send = filesize; + if (bytes_for_send > sizeof(sentBuffer)) + { + bytes_for_send = sizeof(sentBuffer); + } + fread (sentBuffer,1,bytes_for_send,fp); + filesize -= bytes_for_send; + if (EnDebugMSG) + printf("\r\n---bytes_for_send...%d",bytes_for_send); + client.send_all(sentBuffer,bytes_for_send); + sentBuffer[0]=NULL; //clear buffer + //Thread::wait(10); + all_send_bytes += bytes_for_send; + } + if (EnDebugMSG) + printf("\r\n---buffer fill end - all ...%lld", all_send_bytes); + //binary send + + sprintf(line_response, "\r\n"); + client.send_all(line_response,strlen(line_response)); + if ( fp != NULL ) + fclose(fp); + //Thread::wait(10); + return 0; +} + +int send_directory(char *path) +{ + char process_name[64]= {0}; + char posOfLastSlash; + char *pLS; + struct dirent *p; + struct sMystat sb; + struct tm *timeinfo; + char timeBuf[40]; + + if (EnDebugMSG) + printf("\n-->from send_directory:%s",path); + snprintf(file_path,sizeof(file_path),"/sd%s",path); + DIR *d = opendir(file_path); + if (EnDebugMSG && d!=NULL) + printf("\n-->from send_directory:%s ...open OK",file_path); + if (d==NULL) + { + //error open dir + send_HTML_error( 403, "Forbidden", "403 - Directory access forbidden."); + return -1; + } + send_HTTP_header("HTTP/1.1", 200, "Ok",NULL, -1); + sentBuffer[0]=NULL; + sprintf(line_response,"<!DOCTYPE html>\r\n<html>\n<head><title>Index of %s</title>\n",path); + snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer + sprintf(line_response,"<meta content=\"text/html; charset=iso-8859-1\" http-equiv=\"Content-Type\"></head>\n"); + snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer + sprintf(line_response,"<body><center>\n<h3>Index of %s</h3>\n", path); + snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer + send_HTML_line(sentBuffer, strlen(sentBuffer)); + //begin table + sentBuffer[0]=NULL; //clear buffer + sprintf(line_response,"<table border=\"0\">\n"); + snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer + sprintf(line_response,"<tr><th align=\"left\" width=\"200\">Name</th><th align=\"right\" width=\"100\">Size(bytes)</th><th align=\"right\" width=\"200\">Date/Time</th></tr>\n"); + snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer + //begin table + pLS=strrchr(path,'/'); + posOfLastSlash=pLS-path+1; + if (EnDebugMSG) + printf("\r\n>>posOfLastSlash=%d",posOfLastSlash); + snprintf(process_name,posOfLastSlash+1,"%s",path); + if (EnDebugMSG) + printf("\r\n>>process_name=%s",process_name); + //sprintf(line_response,"<tr><td align=\"left\"><a href=\"%s\">../</a></td></tr>\n",process_name); + snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer + d= opendir("/sd/"); + while((p = readdir(d)) != NULL) + { + printf("\n inside while loop p = readdir(d)\n" ); + if (EnDebugMSG) + printf("\n :%s",p->d_name); + sprintf(file_path,"%s/%s",path,p->d_name); + Mystat( file_path, &sb ); + if (get_dirInfo(file_path)==0 ) + { + //this is directory path + if (EnDebugMSG) + printf("\nDIR"); + sprintf(line_response, "<tr><td align=\"left\"><a href=\"%s\">%s</a><br></td></tr>\n",file_path,p->d_name); + if (strlen(line_response)>(sizeof(sentBuffer)-strlen(sentBuffer))) + { + //buffer must be sent + send_HTML_line(sentBuffer, strlen(sentBuffer)); + sentBuffer[0]=NULL; //clear buffer + } + snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer + + } + else + { //this is file + if (EnDebugMSG) + printf("\nFILE"); + timeinfo = localtime (&sb.st_mtime); + //strftime(timeBuf,40, "%I:%M:%S %p (%Y/%m/%d)\r\n", localtime(&sb.st_mtime)); + strftime(timeBuf, 40, "%c", timeinfo); + sprintf(line_response, "<tr><td align=\"left\"><a href=\"%s\">%s</a></td><td align=\"right\">%lld</td><td align=\"right\">%s</td></tr>\n", file_path, p->d_name,(long long) sb.st_size,timeBuf); // asctime(timeinfo) ); + + if (strlen(line_response)>(sizeof(sentBuffer)-strlen(sentBuffer))) + { + //buffer must be sent + send_HTML_line(sentBuffer, strlen(sentBuffer)); + sentBuffer[0]=NULL; //clear buffer + } + snprintf(&(sentBuffer[strlen(sentBuffer)]),sizeof(sentBuffer),"%s",line_response); //append to buffer + } + } + send_HTML_line(sentBuffer, strlen(sentBuffer)); + closedir(d); + + sprintf(line_response, "</table>\n<br><h4>mbed HTTP File Server</h4>\n</center></body></html>\n"); + send_HTML_line(line_response, strlen(line_response)); + + return 0; +} + +void parseHTTPRequest(char* buffer) +{ + sd.mount(); + char spacePos; + char *tmpBuffer; + spacePos = strcspn(buffer, " ") + 1; //position of first space character + snprintf(sMethod, spacePos,"%s", buffer); + + //get Protocol + tmpBuffer=&(buffer[spacePos]); //move pointer to buffer (delete Method) + spacePos = strcspn(tmpBuffer, "\r\n") + 1; + tmpBuffer[spacePos]='\0'; //set end of string ...cut + sprintf(sProtocol, "%s", strrchr(tmpBuffer,' ')); //get string after last (space ) + printf("\r\nsProtocol:%s", tmpBuffer); + buffer = &(sProtocol[1]); //cut first character (space) + sprintf(sProtocol, "%s", buffer); + + //get URL + snprintf(sURL,strlen(tmpBuffer)-strlen(sProtocol),"%s\r\n", tmpBuffer); //URL is between Method and Protocol + + printf("\nParse Method:%s",sMethod); + printf("\nParse URL:%s",sURL); + printf("\nParse PROTOCOL:%s",sProtocol); + printf("\n\r\n"); +} + +int processHTTP(char* sMethod, char* sURL, char* sProtocol) +{ + int gdi, gfi; //status of get_dir_info(xxx), and get_file_info(xxx) + + if (strcmp(sMethod,"GET")!=0) + { + send_HTML_error( 501, "501 Not Implemented", "501 - The server either does not recognize the request method"); + return 501; + } + if (sURL[0]!= '/') + { + send_HTML_error( 400, "Bad Request", "400 - The request cannot be fulfilled due to bad syntax."); + return 400; + } + if (sURL[strlen(sURL)-1]=='/') + { + sURL[strlen(sURL)-1]=sURL[strlen(sURL)]; //delete last symbol + if (EnDebugMSG) + printf("\n delete last:%s",sURL); + } + // send_file(sURL); + + gdi= get_dirInfo(sURL); + gfi= get_fileInfo(sURL); + + if (gfi!=0) + { + //!=0 file not found + if (gdi==0) + { + //0-ok this is directory + return send_directory(sURL); + } + if (EnDebugMSG) + printf("\n404-br File not found or...(Fresult is:%d)",gfi); + send_HTML_error( 404, "Not Found","404 - The requested resource could not be found."); + return 404; + } + else + { + //==0 found + if (gdi==0) //0-ok this is directory + return send_directory(sURL); + else + return send_file(sURL); + } +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// HTTP File SERVER // +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Main // +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +int main() +{ + + int check=1; + int newcheck=10; + int insidecondition=0; + + while(1) + { + pb.mode(PullUp); + newcheck=pb; + if(check==newcheck) + { + eth.init("192.168.240.100","255.255.255.0","192.168.240.1"); + eth.connect(); + printf("IP Address is %s\n\r", eth.getIPAddress()); + + //setup tcp socket + if(svr.bind(PORT)< 0) + { + printf("tcp server bind failed.\n\r"); + return -1; + } + else + { + printf("tcp server bind successed.\n\r"); + serverIsListened = true; + } + + if(svr.listen(1) < 0) + { + printf("tcp server listen failed.\n\r"); + return -1; + } + else + { + sd.mount(); + char Input_Filename[] = "/sd/IMG_0000.jpg \n"; + char Output_Filename[] = "/sd/Output.bmp \n"; + Convert_input(Input_Filename); + Convert_output(Output_Filename); + free(raw_image); + printf("\n image convertion process complete \n"); + printf("\n waiting for WEB file request \n"); + } + + while (serverIsListened) + { + //blocking mode(never timeout) + if(svr.accept(client)<0) + { + printf("failed to accept connection.\n\r"); + } + else + { + if(insidecondition==2) + { + lcd.DrawBitmap(0,0,(uint8_t *)"/sd/new.bmp"); //displaying pic to lcd + } + + printf("connection success!\n\rIP: %s\n\r",client.get_address()); + clientIsConnected = true; + led2 = true; + while(clientIsConnected) + { + char buffer[512] = {}; + switch(client.receive(buffer, 511)) + { + case 0: + printf("recieved buffer is empty.\n\r"); + clientIsConnected = false; + break; + case -1: + printf("failed to read data from client.\n\r"); + clientIsConnected = false; + break; + default: + printf("Recieved Data: %d\n\r\n\r%.*s\n\r",strlen(buffer),strlen(buffer),buffer); + parseHTTPRequest(buffer); + + if (strcmp(sMethod, "GET" ) == 0 ) + { + printf("GET request incomming.\n\r"); + processHTTP(sMethod, sURL, sProtocol); + clientIsConnected = false; + } + break; + } + + } + printf("close connection.\n\rHTTP server is listening...\n\r\n"); + insidecondition=insidecondition+1; + client.close(); + wait(1); + led2 = false; + } + } + } + else + { + printf("Press button to start FS and Convert \n"); + } + + } + + +}