int main(void){ uint16_t dat_p; // set the clock speed to 8MHz // set the clock prescaler. First write CLKPCE to enable setting of clock the // next four instructions. CLKPR=(1<<CLKPCE); CLKPR=0; // 8 MHZ _delay_loop_1(0); // 60us //initialize the hardware driver for the enc28j60 enc28j60Init(mymac); //enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz _delay_loop_1(0); // 60us enc28j60PhyWrite(PHLCON,0x476); PORTB = 0xff; DDRB = 0xff; uart_init(); sei(); xfunc_out = (void (*)(char))uart_put; xputs(PSTR("AVR-Ethernet test monitor\n")); xprintf(PSTR("ENC28J60 Rev.%d\n"), enc28j60getrev()); //init the ethernet/ip layer: init_ip_arp_udp_tcp(mymac,myip,MYWWWPORT); while(1){ // read packet, handle ping and wait for a tcp packet: dat_p=packetloop_icmp_tcp(buf,enc28j60PacketReceive(BUFFER_SIZE, buf)); /* dat_p will be unequal to zero if there is a valid * http get */ if(dat_p==0){ // no http request continue; } // tcp port 80 begin if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0){ // head, post and other methods: dat_p=http200ok(); dat_p=fill_tcp_data_p(buf,dat_p,PSTR("<h1>200 OK</h1>")); goto SENDTCP; } // just one web page in the "root directory" of the web server if (strncmp("/ ",(char *)&(buf[dat_p+4]),2)==0){ dat_p=print_webpage(buf); goto SENDTCP; }else{ dat_p=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 401 Unauthorized\r\nContent-Type: text/html\r\n\r\n<h1>401 Unauthorized</h1>")); goto SENDTCP; } SENDTCP: www_server_reply(buf,dat_p); // send web page data // tcp port 80 end } return (0); }
// Perform all processing to resolve a hostname to IP address. // Returns 1 for successful Name resolution, 0 otherwise uint8_t EtherShield::resolveHostname(uint8_t *buf, uint16_t buffer_size, uint8_t *hostname ) { uint16_t dat_p; int plen = 0; long lastDnsRequest = millis(); uint8_t dns_state = DNS_STATE_INIT; boolean gotAddress = false; uint8_t dnsTries = 3; // After 10 attempts fail gracefully so other action can be carried out while( !gotAddress ) { // handle ping and wait for a tcp packet plen = enc28j60PacketReceive(buffer_size, buf); dat_p=packetloop_icmp_tcp(buf,plen); // We have a packet // Check if IP data if (dat_p == 0) { if (client_waiting_gw() ) { // No ARP received for gateway continue; } // It has IP data if (dns_state==DNS_STATE_INIT) { dns_state=DNS_STATE_REQUESTED; lastDnsRequest = millis(); dnslkup_request(buf,hostname); continue; } if (dns_state!=DNS_STATE_ANSWER){ // retry every minute if dns-lookup failed: if (millis() > (lastDnsRequest + 60000L) ){ if( --dnsTries <= 0 ) return 0; // Failed to allocate address dns_state=DNS_STATE_INIT; lastDnsRequest = millis(); } // don't try to use client before // we have a result of dns-lookup continue; } } else { if (dns_state==DNS_STATE_REQUESTED && udp_client_check_for_dns_answer( buf, plen ) ){ dns_state=DNS_STATE_ANSWER; //client_set_wwwip(dnslkup_getip()); client_tcp_set_serverip(dnslkup_getip()); gotAddress = true; } } } return 1; }
// Perform all processing to get an IP address plus other addresses returned, e.g. gw, dns, dhcp server. // Returns 1 for successful IP address allocation, 0 otherwise uint8_t EtherShield::allocateIPAddress(uint8_t *buf, uint16_t buffer_size, uint8_t *mymac, uint16_t myport, uint8_t *myip, uint8_t *mynetmask, uint8_t *gwip, uint8_t *dnsip, uint8_t *dhcpsvrip ) { uint16_t dat_p; int plen = 0; long lastDhcpRequest = millis(); uint8_t dhcpState = 0; boolean gotIp = false; uint8_t dhcpTries = 10; // After 10 attempts fail gracefully so other action can be carried out dhcp_start( buf, mymac, myip, mynetmask,gwip, dnsip, dhcpsvrip ); while( !gotIp ) { // handle ping and wait for a tcp packet plen = enc28j60PacketReceive(buffer_size, buf); dat_p=packetloop_icmp_tcp(buf,plen); if(dat_p==0) { int retstat = check_for_dhcp_answer( buf, plen); dhcpState = dhcp_state(); // we are idle here if( dhcpState != DHCP_STATE_OK ) { if (millis() > (lastDhcpRequest + 10000L) ){ lastDhcpRequest = millis(); if( --dhcpTries <= 0 ) return 0; // Failed to allocate address // send dhcp dhcp_start( buf, mymac, myip, mynetmask,gwip, dnsip, dhcpsvrip ); } } else { if( !gotIp ) { gotIp = true; //init the ethernet/ip layer: init_ip_arp_udp_tcp(mymac, myip, myport); // Set the Router IP client_set_gwip(gwip); // e.g internal IP of dsl router // Set the DNS server IP address if required, or use default dnslkup_set_dnsip( dnsip ); } } } } return 1; }
uint16_t EtherShield::ES_packetloop_icmp_tcp(uint8_t *buf,uint16_t plen) { return packetloop_icmp_tcp(buf,plen); }
int main(void){ uint16_t dat_p,plen; int8_t cmd; // Set the clock speed to "no pre-scaler" (8MHz with internal osc or // full external speed) // set the clock prescaler. First write CLKPCE to enable setting // of clock the next four instructions. // Note that the CKDIV8 Fuse determines the initial // value of the CKKPS bits. CLKPR=(1<<CLKPCE); // change enable CLKPR=0; // "no pre-scaler" _delay_loop_1(0); // 60us /*initialize enc28j60*/ enc28j60Init(mymac); enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz _delay_loop_1(0); // 60us /* Magjack leds configuration, see enc28j60 datasheet, page 11 */ // LEDB=yellow LEDA=green // // 0x476 is PHLCON LEDA=links status, LEDB=receive/transmit // enc28j60PhyWrite(PHLCON,0b0000 0100 0111 01 10); enc28j60PhyWrite(PHLCON,0x476); DDRB|= (1<<DDB1); // LED, enable PB1, LED as output LEDOFF; DDRD&= ~(1<<DDD6); // enable PB6, as input PORTD|= (1<<PIND6); // internal pullup resistor on init_cnt2(); sei(); //init the web server ethernet/ip layer: init_ip_arp_udp_tcp(mymac,myip,MYWWWPORT); // init the web client: client_set_gwip(gwip); // e.g internal IP of dsl router // while(1){ // handle ping and wait for a tcp packet plen=enc28j60PacketReceive(BUFFER_SIZE, buf); dat_p=packetloop_icmp_tcp(buf,plen); if(plen==0){ // we are idle here if (client_waiting_gw() ){ continue; } if (dns_state==0){ sec=0; dns_state=1; dnslkup_request(buf,PSTR(WEBSERVER_VHOST)); continue; } if (dns_state==1 && dnslkup_haveanswer()){ dns_state=2; client_set_wwwip(dnslkup_getip()); } if (dns_state!=2){ // retry every minute if dns-lookup failed: if (sec > 60){ dns_state=0; } // don't try to use web client before // we have a result of dns-lookup continue; } //---------- if (start_web_client==1){ LEDON; start_web_client=2; sec=0; web_client_attempts++; // the identi.ca line is status=Url_encoded_string strcat(statusstr,"status="); // the text to send to identi.ca (append after status=): //urlencode("Meals are ready",&(statusstr[7])); urlencode("I like tuxgraphics eth boards, ",&(statusstr[7])); // append a number: itoa(web_client_attempts,&(statusstr[strlen(statusstr)]),10); // The BLOGGACCOUNT Authorization code can be generated from // username and password of your identi.ca account // by using this encoder: http://tuxgraphics.org/~guido/javascript/base64-javascript.html client_http_post(PSTR("/api/statuses/update.xml"),PSTR(WEBSERVER_VHOST),PSTR(BLOGGACCOUNT),statusstr,&browserresult_callback); } // count how often the switch was triggered at all: if (contact_debounce==0 && bit_is_clear(PIND,PIND6)){ contact_onoff_cnt++; contact_debounce=1; } // we send only a request if we are in the right state (do // not flood with request): if (start_web_client==0 && bit_is_clear(PIND,PIND6)){ resend=1; // resend once if it failed start_web_client=1; } // Reset after a delay of 3 min to prevent email sending. // We reset only if the contact on PD6 was released. if (start_web_client<=3 && sec==180 && !bit_is_clear(PIND,PIND6)){ start_web_client=0; } // Resend the message if it failed: if (start_web_client==2 && sec==7 && resend){ start_web_client=1; resend--; } continue; } if(dat_p==0){ // plen!=0 // check for incomming messages not processed // as part of packetloop_icmp_tcp, e.g udp messages udp_client_check_for_dns_answer(buf,plen); continue; } if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0){ // head, post and other methods: // // for possible status codes see: // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html dat_p=http200ok(); dat_p=fill_tcp_data_p(buf,dat_p,PSTR("<h1>200 OK</h1>")); goto SENDTCP; } cmd=analyse_get_url((char *)&(buf[dat_p+4])); // for possible status codes see: // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html if (cmd==-1){ dat_p=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 401 Unauthorized\r\nContent-Type: text/html\r\n\r\n<h1>401 Unauthorized</h1>")); goto SENDTCP; } if (cmd==1 && start_web_client==4){ // email was off, switch on start_web_client=0; } if (cmd==0 ){ start_web_client=4; // email off } dat_p=http200ok(); dat_p=print_webpage(buf); // SENDTCP: www_server_reply(buf,dat_p); // send data } return (0); }
int main(void){ uint16_t dat_p; int8_t cmd; // Set the clock speed to "no pre-scaler" (8MHz with internal osc or // full external speed) // set the clock prescaler. First write CLKPCE to enable setting // of clock the next four instructions. // Note that the CKDIV8 Fuse determines the initial // value of the CKKPS bits. CLKPR=(1<<CLKPCE); // change enable CLKPR=0; // "no pre-scaler" _delay_loop_1(0); // 60us /*initialize enc28j60*/ enc28j60Init(mymac); enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz _delay_loop_1(0); // 60us /* Magjack leds configuration, see enc28j60 datasheet, page 11 */ // LEDB=yellow LEDA=green // // 0x476 is PHLCON LEDA=links status, LEDB=receive/transmit // enc28j60PhyWrite(PHLCON,0b0000 0100 0111 01 10); enc28j60PhyWrite(PHLCON,0x476); DDRB|= (1<<DDB1); // LED, enable PB1, LED as output LEDOFF; DDRD&= ~(1<<DDD6); // enable PB6, as input PORTD|= (1<<PIND6); // internal pullup resistor on init_cnt2(); sei(); //init the web server ethernet/ip layer: init_ip_arp_udp_tcp(mymac,myip,MYWWWPORT); // init the web client: client_set_gwip(gwip); // e.g internal IP of dsl router client_set_wwwip(websrvip); // while(1){ // handle ping and wait for a tcp packet dat_p=packetloop_icmp_tcp(buf,enc28j60PacketReceive(BUFFER_SIZE, buf)); if(dat_p==0){ if (start_web_client==1){ LEDON; start_web_client=2; sec=0; web_client_attempts++; // the text to send in the body of the mail: urlencode("The door is open",urlvarstr); // The string "test+emailnotify" is the subject line // of the email. A plus sign translates into a space character. // The MMaccountID is gus123, edit and replace by your own. client_browse_url(PSTR("/cgi-bin/mm?a=gus123&s=test+emailnotify&d="),urlvarstr,PSTR(WEBSERVER_VHOST),&browserresult_callback); } // count how often the switch was triggered at all: if (contact_debounce==0 && bit_is_clear(PIND,PIND6)){ contact_onoff_cnt++; contact_debounce=1; } // we send only an email if we are in the right state (do // not flood with email): if (start_web_client==0 && bit_is_clear(PIND,PIND6)){ resend=1; // resend once if it failed start_web_client=1; } // Reset after a delay of 3 min to prevent email sending. // We reset only if the contact on PD6 was released. if (start_web_client<=3 && sec==180 && !bit_is_clear(PIND,PIND6)){ start_web_client=0; } // Resend the email if it failed: if (start_web_client==2 && sec==7 && resend){ start_web_client=1; resend--; } continue; } if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0){ // head, post and other methods: // // for possible status codes see: // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html dat_p=http200ok(); dat_p=fill_tcp_data_p(buf,dat_p,PSTR("<h1>200 OK</h1>")); goto SENDTCP; } cmd=analyse_get_url((char *)&(buf[dat_p+4])); // for possible status codes see: // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html if (cmd==-1){ dat_p=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 401 Unauthorized\r\nContent-Type: text/html\r\n\r\n<h1>401 Unauthorized</h1>")); goto SENDTCP; } if (cmd==1 && start_web_client==4){ // email was off, switch on start_web_client=0; } if (cmd==0 ){ start_web_client=4; // email off } dat_p=http200ok(); dat_p=print_webpage(buf); // SENDTCP: www_server_reply(buf,dat_p); // send data } return (0); }
/** * Handle Modbus requests * Checks for new TCP data and looks for new modbus messages **/ void mb_handleRequest(void) { // read packet, handle ping and wait for a tcp packet uint16_t dat_p = packetloop_icmp_tcp(buf,enc28j60PacketReceive(BUFFER_SIZE, buf)); // check if data was received if (dat_p == 0) return; // make structure pointer to buffer modbusmsg_t* msg = (modbusmsg_t*)&buf[dat_p]; // check for modbus protocol id if (FROM_UINT16(msg->mbap.protoId) > 0) return; uint16_t len; switch (msg->function) { // Modbus read function case MB_FUNC_READREG: { readreg_req_t* req = (readreg_req_t*)&(msg->function); readreg_res_t* res = (readreg_res_t*)&(msg->function); uint16_t amount = FROM_UINT16(req->amount); uint16_t addr = FROM_UINT16(req->start_address); if (amount == 0 || amount > 0x7D) { len = mb_set_error(msg,MB_ERR_DATA); break; } if (addr + amount <= MODBUS_REGISTER_COUNT) { uint16_t *ptr = (uint16_t*)&(res->function); uint16_t cnt = 0; for (; cnt < amount; cnt++) { if (registers[addr+cnt] == NULL) { len = mb_set_error(msg,MB_ERR_PROC); break; } ++ptr; *ptr = TO_UINT16(*(registers[addr+cnt])); } // if an error occurred if (cnt < amount) break; res->bytecount = cnt*sizeof(uint16_t); len = sizeof(readreg_res_t)+cnt*sizeof(uint16_t); } else len = mb_set_error(msg,MB_ERR_ADDR); break; } // Modbus write function case MB_FUNC_WRITEREG: { writereg_req_t* req = (writereg_req_t*)&(msg->function); uint16_t addr = FROM_UINT16(req->start_address); uint16_t value = FROM_UINT16(req->value); if (addr >= MODBUS_REGISTER_COUNT || writecbs[addr] == NULL) { len = mb_set_error(msg,MB_ERR_ADDR); break; } if (writecbs[addr](addr,value)) len = sizeof(writereg_req_t); else len = mb_set_error(msg,MB_ERR_PROC); break; } // Modbus device id function // Not implemented completely case MB_FUNC_DEV_ID: { devid_req_t* req = (devid_req_t*)&(msg->function); devid_res_t* res = (devid_res_t*)&(msg->function); devid_obj_t* obj = (devid_obj_t*)&(res->nextobjid); uint8_t i = req->objid; if (req->type != 0x0E) { len = mb_set_error(msg,MB_ERR_FUNC); break; } if (!req->code || req->code > 4) { len = mb_set_error(msg,MB_ERR_DATA); break; } res->conflevel = 0x01; res->more = 0x00; res->nextobjid = 0x00; res->amount = 3; len = sizeof(devid_res_t); if (i > 2) i = 0; // add requested objects for (; i < 3; i++) { ++obj; obj->id = i; obj->length = 0; len += sizeof(devid_obj_t)+obj->length; } break; } default: // set error len = mb_set_error(msg,MB_ERR_FUNC); break; } msg->mbap.length = TO_UINT16(len+1); // send response www_server_reply(buf,sizeof(mbap_t)+len); }
int main(void){ uint16_t plen; uint16_t dat_p; //uint8_t cmd_pos=0; int8_t cmd; //uint8_t payloadlen=0; //char str[20]; //char cmdval; //char req[16]; //char i; DATA_DAIKIN daikin; // set the clock speed to "no pre-scaler" (8MHz with internal osc or // full external speed) // set the clock prescaler. First write CLKPCE to enable setting // of clock the next four instructions. // Note that the CKDIV8 Fuse determines the initial // value of the CKKPS bits. CLKPR=(1<<CLKPCE); // change enable CLKPR=0; // "no pre-scaler" _delay_loop_1(0); // 60us /*initialize enc28j60*/ enc28j60Init(mymac); //enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz _delay_loop_1(0); // 60us /* Magjack leds configuration, see enc28j60 datasheet, page 11 */ // LEDB=yellow LEDA=green // // 0x476 is PHLCON LEDA=links status, LEDB=receive/transmit // enc28j60PhyWrite(PHLCON,0b0000 0100 0111 01 10); enc28j60PhyWrite(PHLCON,0x476); //DDRB|= (1<<DDB1); // enable PB1, LED as output // the transistor on PD7: //DDRD|= (1<<DDD7); //PORTD &= ~(1<<PORTD7);// transistor off //PORTB = 0xff; //DDRB = 0xff; init_power_settings(); uart_init(); init_ir(); init_airController(&daikin); sei(); xfunc_out = (void (*)(char))uart_put; xputs(PSTR("AVR-Ethernet test monitor\n")); xprintf(PSTR("ENC28J60 Rev.%d\n"), enc28j60getrev()); xprintf(PSTR("PRR=%02X\n"),PRR); //init the web server ethernet/ip layer: init_ip_arp_udp_tcp(mymac,myip,MYWWWPORT); while(1){ // handle ping and wait for a tcp packet plen=enc28j60PacketReceive(BUFFER_SIZE, buf); buf[BUFFER_SIZE]='\0'; dat_p=packetloop_icmp_tcp(buf,plen); if(dat_p==0){ // check if udp otherwise continue goto UDP; } // send data everytime we get a http request xprintf(PSTR("get http request\n")); if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0){ xprintf(PSTR("'GET \n'")); // head, post and other methods: // // for possible status codes see: // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html plen=http200ok(); plen=fill_tcp_data_p(buf,plen,PSTR("<h1>200 OK</h1>")); goto SENDTCP; } if (strncmp("/ ",(char *)&(buf[dat_p+4]),2)==0){ plen=http200ok(); plen=fill_tcp_data_p(buf,plen,PSTR("<p>Usage: http://host_or_ip/pc or m</p>\n")); goto SENDTCP; } if ((strncmp("/pc ",(char *)&(buf[dat_p+4]),4)==0) || (strncmp("/pc/ ",(char *)&(buf[dat_p+4]),5)==0)){ plen=http200ok(); plen=fill_tcp_data_p(buf,plen,pc_html); goto SENDTCP; } if ((strncmp("/m ",(char *)&(buf[dat_p+4]),3)==0) || (strncmp("/m/ ",(char *)&(buf[dat_p+4]),4)==0)){ plen=http200ok(); plen=fill_tcp_data_p(buf,plen,mobile_html); goto SENDTCP; } // GET /ir?power=on&temp=28 if (strncmp("/ir?",(char *)&(buf[dat_p+4]),4)==0){ if(find_key_val( (char *)&(buf[dat_p+8]), gStrbuf, 5, "power" ) ) { xprintf(PSTR("power=%s\n"),gStrbuf); if(strncmp("on", gStrbuf, 2) == 0){ airController_on(&daikin); setData(DAIKIN, daikin.buf, 35*8); }else if(strncmp("off", gStrbuf, 3) == 0){ airController_off(&daikin); setData(DAIKIN, daikin.buf, 35*8); } } if(find_key_val( (char *)&(buf[dat_p+8]), gStrbuf, 4, "temp" ) ) { xprintf(PSTR("temp=%s\n"),gStrbuf); airController_setTemp(&daikin, atoi(gStrbuf)); setData(DAIKIN, daikin.buf, 35*8); } plen=http200ok(); plen=fill_tcp_data_p(buf,plen,PSTR("Done\n")); goto SENDTCP; } cmd=analyse_get_url((char *)&(buf[dat_p+4])); // for possible status codes see: // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html if (cmd==-1){ plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 401 Unauthorized\r\nContent-Type: text/html\r\n\r\n<h1>401 Unauthorized</h1>")); goto SENDTCP; } if (cmd==1){ //PORTD|= (1<<PORTD7);// transistor on } if (cmd==0){ //PORTD &= ~(1<<PORTD7);// transistor off } if (cmd==2){ // favicon: //plen=moved_perm(buf,0); goto SENDTCP; } if (cmd==-2){ // redirect to the right base url (e.g add a trailing slash): plen=moved_perm(buf,1); goto SENDTCP; } // if (cmd==-2) or any other value // just display the status: //plen=print_webpage(buf,/*(PORTD & (1<<PORTD7))*/0); // SENDTCP: www_server_reply(buf,plen); // send data continue; // tcp port www end // ------------------------------- // udp start, we listen on udp port 1200=0x4B0 UDP: // xprintf(PSTR("here is UDP:\n")); // check if ip packets are for us: if(eth_type_is_ip_and_my_ip(buf,plen)==0){ // xprintf(PSTR("here is eth_type_is_ip_andd_my_ip\n")); continue; } /*if (buf[IP_PROTO_P]==IP_PROTO_UDP_V&&buf[UDP_DST_PORT_H_P]==(MYUDPPORT>>8)&&buf[UDP_DST_PORT_L_P]==(MYUDPPORT&0xff)){ payloadlen=buf[UDP_LEN_L_P]-UDP_HEADER_LEN; // you must sent a string starting with v // e.g udpcom version 10.0.0.24 if (verify_password((char *)&(buf[UDP_DATA_P]))){ // find the first comma which indicates // the start of a command: cmd_pos=0; while(cmd_pos<payloadlen){ cmd_pos++; if (buf[UDP_DATA_P+cmd_pos]==','){ cmd_pos++; // put on start of cmd break; } } // a command is one char and a value. At // least 3 characters long. It has an '=' on // position 2: if (cmd_pos<2 || cmd_pos>payloadlen-3 || buf[UDP_DATA_P+cmd_pos+1]!='='){ strcpy(str,"e=no_cmd"); goto ANSWER; } // supported commands are // t=1 t=0 t=? if (buf[UDP_DATA_P+cmd_pos]=='t'){ cmdval=buf[UDP_DATA_P+cmd_pos+2]; if(cmdval=='1'){ PORTD|= (1<<PORTD7);// transistor on strcpy(str,"t=1"); goto ANSWER; }else if(cmdval=='0'){ PORTD &= ~(1<<PORTD7);// transistor off strcpy(str,"t=0"); goto ANSWER; }else if(cmdval=='?'){ if (PORTD & (1<<PORTD7)){ strcpy(str,"t=1"); goto ANSWER; } strcpy(str,"t=0"); goto ANSWER; } } strcpy(str,"e=inv_cmd"); goto ANSWER; } strcpy(str,"e=inv_pw"); ANSWER: make_udp_reply_from_request(buf,str,strlen(str),MYUDPPORT); }*/ } return (0); }