(myKeyBuffer), myKeyLength) > -1) {
// We found animation
DEBUG_PRINTLN_TXT("Found animation");
myReadStatus = 20; // End search, we found our animation
}else{
DEBUG_PRINTLN_TXT("No animation found");
if (_animationEndPos > _animationStartPos ) {
// Goto next frame
myProjectFile.seek(_animationEndPos);
myReadStatus = 0;
}
}
// clear buffer
myIntBufferLength = 0;
}
break;
case 6:
if( myC == lc_newline ) { // uncomplete keyline or no animation found
// check for values
if ( _animationEndPos > 0 && _animationStartPos > 0 && _animationSpeed > 0 ) {
DEBUG_PRINTLN_TXT("Anim key found");
}else{
DEBUG_PRINTLN_TXT("--keyline failed--");
// Reset everything
myReadStatus = 0;
myKeyLength = 0;
myIntBufferLength = 0;
clearSavedAnimation();
}
}
break;
}
}
}
myProjectFile.close();
}
boolean readAnimationSD() {
unsigned char myC;
unsigned char myBytes = 0;
// Read SD Card
File myProjectFile = SD.open(ANIM_FILE_NAME, FILE_READ);
// Goto start position
if ( myProjectFile.available() ) {
unsigned long _animationPos = _animationStartPos + _animationActFrame * 65; // startPos + offset
if ( _animationPos < _animationEndPos ) {
myProjectFile.seek(_animationPos);
}else{
_animationActFrame = 0; // Start at the first frame again
myProjectFile.seek(_animationStartPos);
}
}
// Read one frame
while ( myProjectFile.available() && myBytes < 64 ) {
myC = myProjectFile.read();
myReceiveBuffer[myBytes] = myC;
myBytes++;
}
// close the file:
myProjectFile.close();
// If we have complete frame, return true
if ( myBytes > 63 ) {
// read successfull
_animationActFrame++;
return true;
}else{
return false;
}
}
unsigned long byte2Long(unsigned char* byteArray) {
// little endian conversion
unsigned long retval;
retval = (unsigned long) byteArray[3] << 24 | (unsigned long) byteArray[2] << 16;
retval |= (unsigned long) byteArray[1] << 8 | byteArray[0];
return retval;
}
void writeAnimationSDCard(EthernetClient client) {
// Send answer
unsigned char readBuffer[4];
// First 10 bytes is a key, following by the length
readBuffer[0] = myReadBuffer[10];
readBuffer[1] = myReadBuffer[11];
readBuffer[2] = myReadBuffer[12];
readBuffer[3] = myReadBuffer[13];
unsigned long fileSize = byte2Long(readBuffer);
// DEBUG_PRINT_TXT("fileSizeBuffer: ");
for (unsigned char i=0; i<4; i++ ) {
client.write(readBuffer[i]);
// DEBUG_PRINT(readBuffer[i]);
}
client.write(lc_return);
client.write(lc_newline);
// DEBUG_PRINTLN_TXT(" ");
// DEBUG_PRINT_TXT("Filesize expected:");
// DEBUG_PRINTLN(fileSize);
// Blocking mode to write receiving data to file
if (client) {
// Remove file if exists
if ( SD.exists(ANIM_FILE_NAME) ) {
SD.remove(ANIM_FILE_NAME);
}
File myProjectFile = SD.open(ANIM_FILE_NAME, FILE_WRITE);
unsigned long receivedBytes = 0;
if (myProjectFile) {
while (client.connected() && receivedBytes < fileSize) {
if (client.available()) {
unsigned char c = client.read();
//writing bytes
myProjectFile.write(c);
receivedBytes++;
}
}
}
/*
if ( receivedBytes == fileSize ) {
DEBUG_PRINTLN_TXT("Complete data received\n");
}else{
DEBUG_PRINTLN_TXT("Data incomplete\n");
}
DEBUG_PRINT_TXT("Expected:");
DEBUG_PRINTLN(fileSize);
DEBUG_PRINT_TXT("Received:");
DEBUG_PRINTLN(receivedBytes);
*/
myProjectFile.close();
}
}
void displaySavedAnimation() {
if ( _animationLength > 0 ) { // Animation was set
unsigned long currentMillis = millis();
// Display animation set over the network
if ( currentMillis < _animationLength ) { // __animationLength = startTime + animLengthTime
if ( _animationStartPos > 0 && _animationEndPos > 0 && _animationSpeed > 0){ // validity check
if ( _animationEndPos > _animationStartPos ) {
//DEBUG_PRINTLN_TXT("Setting mode to 2");
setServerMode(2); // Switch the server mode
if ( currentMillis - _previousMillis >= _animationSpeed ) { // Sent data with the set speed
// save the last time you sent frame
_previousMillis = currentMillis;
// Fill Buffer
if ( true == readAnimationSD() ) {
// Send buffered frame
sendBufferedFrame();
}
}
}
}
}else{
// End the stream mode
setServerMode(0);
}
}
}
void keepAliveFrame() {
// Check if we need to send a keep alive frame
if ( millis() - _lastTimeFrameSent > MY_STREAM_KEEPALIVE_TIME ) {
// Send buffered frame
sendBufferedFrame();
}
}
// --------- MAIN ---------- //
void setup() {
// put your setup code here, to run once:
Wire.begin();
#ifdef DEBUG
Serial.begin(9600);
#endif
DEBUG_PRINTLN_TXT("Sender1");
DEBUG_PRINTLN_TXT("Init SD card...");
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work.
// disable w5100 SPI
//pinMode(10, OUTPUT);
//digitalWrite(10,HIGH);
if (!SD.begin(4)) {
DEBUG_PRINTLN_TXT("init failed!");
// TODO: deny some functions
}else{
DEBUG_PRINTLN_TXT("init done.");
}
// start the Ethernet connection:
Ethernet.begin(mac, ip, gateway, subnet);
// ----------------------
// Sorry, but had to drop DHCP support due to missing memory
// If you have a MEGA, feel free to use it
/* if (Ethernet.begin(mac) == 0) {
DEBUG_PRINTLN_TXT("Failed to configure Ethernet using DHCP");
DEBUG_PRINTLN_TXT("Using defaults 192.168.1.79");
// initialize the ethernet device not using DHCP:
Ethernet.begin(mac, ip, gateway, subnet);
}
*/
// -----------------------
#ifdef DEBUG
// print your local IP address:
DEBUG_PRINTLN_TXT("My IP: ");
for (byte thisByte = 0; thisByte < 4; thisByte++) {
// print the value of each byte of the IP address:
DEBUG_PRINT2(Ethernet.localIP()[thisByte], DEC);
DEBUG_PRINT(".");
}
DEBUG_PRINTLN_TXT("");
#endif
// Print free memory
//DEBUG_PRINT("freeMemory()=");
//DEBUG_PRINTLN(freeMemory());
}
void loop() {
// Process Server requests
// listen for incoming clients
EthernetClient client = server.available();
if (client) { // Client connected and sending data
DEBUG_PRINTLN_TXT("Client attached");
// Init status
unsigned char readState = 0;
unsigned char lastChar = 0; // Make sure you never check for 0-value !!!
int bufferSize = 0;
// If we receive data, interrupt other states
setServerMode(0);
// Read incoming data
while (client.connected()) {
if (client.available()) {
// get incoming byte
unsigned char c = client.read();
// check for server mode
switch (serverMode) {
case 0:
// Checking incoming requests
readState = checkRequest(c, readState);
// Processing if request is recognized
if ( readState == 7 ) { // HTTP GET recognized
processRequest(client);
// process only one time
readState = 0;
myReadBufferCount = 0;
}
break;
case 1:
// Streaming frames
bufferSize = sendFrameCached(c, bufferSize);
// Check for streaming end
if ( c == lc_S && lastChar == lc_s ) { // "sS" received
//sendEndFrameStream();
setServerMode(0);
bufferSize = 0;
}
break;
}
// if we got whole HTTP Head and still waiting for commands,
// send HTTP answer
if ( serverMode == 0 && c == lc_newline && lastChar == lc_return ) { // \r\n was send
// send a standard http response header
//client.println(F("HTTP/1.1 200 OK\nContent-Type: text/html\r\n\nRainbowduino Webserver
Rainbowduino Webserver 1.0
Functions:
Blink:
| |
Frametest
| |
Streamtest
| |
Print file to serial
| |
"));
client.println(F("HTTP/1.1 200 OK"));
// Close the connection
client.stop();
}
lastChar = c;
}
// If we are in the streaming mode and don't receive any frames,
// check for timeout
if ( serverMode == 1 ) {
// keep the connection to the Rainbowduino alive
keepAliveFrame();
}
}
// give web browser time to receive the data
delay(1);
// close the connection
client.stop();
}
if ( serverMode == 1 && client == false) {
// If client closed the connection and we are still in the
// stream mode, reset to normal operation
setServerMode(0);
}
// ------------------------------------------------//
// Display Animation
displaySavedAnimation();
}