Kyle Lemons / Mbed 2 deprecated HvZ

Dependencies:   XBeeLib mbed HvZAlphaNumLib HvZServerLib

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers udp.cpp Source File

udp.cpp

00001 #include "mbed.h"
00002 #include "iHvZ.hpp"
00003 #include "if/net/netudpsocket.h"
00004 
00005 #include "udp.hpp"
00006 
00007 UDP::UDP(iHvZ *game, PinName eth_in) 
00008 :  m_game(game), m_eth(eth_in), m_eth_int(eth_in),
00009    m_pNetUdpSocket(NULL), m_pCbItem(NULL), m_pCbMeth(NULL), m_pCb(NULL),
00010    //conn(IpAddr(192,168,1,2),IpAddr(255,255,255,0), IpAddr(), IpAddr())
00011 {
00012     // Set the game ID
00013     char mac[8];
00014     char macaddr[12+1];
00015     eth.address(mac);
00016     sprintf(macaddr, "%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
00017     m_game->id(macaddr);
00018     
00019     //m_eth_int.rise(this, &UDP::check);
00020     m_eth_chk.attach(this, &UDP::check, 5);
00021     registered = 0;
00022 }
00023  
00024 UDP::~UDP()
00025 {
00026   close();
00027 }
00028 
00029 void UDP::check()
00030 {   
00031     // debounce (if attached to a button)
00032     wait(.1);
00033     //if (m_eth)
00034     //{        
00035     //    usb.printf("- Connection found, starting sync\r\n");
00036         ethlink();
00037     //}
00038     m_eth_chk.attach(this, &UDP::check, 10);
00039 }
00040      
00041 int UDP::sendto(const char* buf, int len, Host* pHost)
00042 {
00043   UDPErr udpSocketErr = checkInst();
00044   if(udpSocketErr)
00045     return udpSocketErr; 
00046   return m_pNetUdpSocket->sendto(buf, len, pHost);  
00047 }
00048 
00049 int UDP::recvfrom(char* buf, int len, Host* pHost)
00050 {
00051   UDPErr udpSocketErr = checkInst();
00052   if(udpSocketErr)
00053     return udpSocketErr;
00054   return m_pNetUdpSocket->recvfrom(buf, len, pHost);
00055 }
00056 
00057 UDPErr UDP::close()
00058 {
00059   if(!m_pNetUdpSocket)
00060     return UDPSOCKET_SETUP;
00061   m_pNetUdpSocket->resetOnEvent();
00062   UDPErr udpSocketErr = (UDPErr) m_pNetUdpSocket->close(); //Close (can already be closed)
00063   Net::releaseUdpSocket(m_pNetUdpSocket); //And release it so it can be freed when properly removed
00064   m_pNetUdpSocket = NULL;
00065   return udpSocketErr;
00066 } 
00067 
00068 void UDP::ethlink()
00069 {
00070     Serial usb(USBTX,USBRX);
00071     usb.printf("Checking for Ethernet connection...\r\n");
00072     
00073     Host game_server(IpAddr(128, 61, 89, 71), HVZ_PORT, HVZ_HOSTNAME);
00074     //Host game_server(IpAddr(192, 168, 1, 1), HVZ_PORT, HVZ_HOSTNAME);
00075     
00076     /* Function to call upon Server response */    
00077     setOnEvent(this, &UDP::read);
00078      
00079     if( !eth.link() ) return;
00080     usb.printf(" - Link active\r\n");
00081     
00082     m_game->alphanumdisplay_device().display('*');
00083       
00084     if( registered == 0 ) {
00085         conn.setup();
00086                       
00087         //Get the MAC address of this device
00088         eth.address((char *)mac.octet);     
00089                                            
00090         // Send to Game Server until receive a response 
00091         // and wait for a response                                                                                                                                 
00092         do {
00093         
00094              register_device(mac, &game_server);
00095              wait(0.1);
00096                            
00097              Net::poll();
00098                              
00099           } while ( memcmp("i",&(srvr_resp[0]),1) );
00100         
00101         printf("srvr_resp = %s\r\n", srvr_resp); 
00102         
00103         // If the response is an acknowledgement
00104         // get the IDs from the response and
00105         // set the game device and tag IDs
00106         if( get_ack_err(srvr_resp,HVZ_REG) ) {
00107             set_ids(srvr_resp); 
00108            //printf( "deviceID = %s\r\n", m_game->id() );
00109            //printf( "tagID = %s\r\n", m_game->tagid() );
00110         
00111             // Clear the response string 
00112             memset(srvr_resp,0,sizeof(srvr_resp));
00113         
00114             // Upon registration there will be no tags or 
00115             // updates for this device, so just return here   
00116             return;
00117         }          
00118         
00119         // Set as already registered
00120         registered = 1;
00121         
00122         // Clear the response string 
00123         memset(srvr_resp,0,sizeof(srvr_resp));
00124     }
00125     
00126     // Submit any tags to the server
00127     // and wait for a response 
00128     do {    
00129         send_tag(&game_server, m_game->get_victims());
00130         wait(0.1);
00131                        
00132         Net::poll();                        
00133     //} while ( memcmp("i",&(srvr_resp[0]),1) );
00134     } while ( 'i' != srvr_resp[0] );
00135     
00136     printf("srvr_resp = %s\r\n", srvr_resp);
00137     
00138     // On successfully reporting tags to Server
00139     // clear the tagged list
00140     if( get_ack_err(srvr_resp,HVZ_TAG) ) 
00141         m_game->clear_victims(); 
00142     
00143     // Clear the response string 
00144     memset(srvr_resp,0,sizeof(srvr_resp));
00145     
00146     // Next request updates to the server 
00147     do {
00148         // If the deviceID is set at update request
00149         send_pull(&game_server);    
00150         
00151         wait(0.1);
00152                        
00153         Net::poll(); 
00154     //} while ( !srvr_resp[0] );
00155     } while ( 'i' != srvr_resp[0] );
00156     
00157     printf("srvr_resp = %s\r\n", srvr_resp);  
00158     
00159     // If pull request ack, update settings of the game
00160     if( get_ack_err(srvr_resp,HVZ_PULL) )  
00161         update_settings(srvr_resp);
00162     
00163     // Clear the response string 
00164     memset(srvr_resp,0,sizeof(srvr_resp));
00165     
00166     // Display a completion mark
00167     m_game->alphanumdisplay_device().display('^');
00168     wait(1);
00169     m_game->alphanumdisplay_device().display(m_game->status()==STATUS_HUMAN?'H':'Z');
00170 }
00171 
00172 void UDP::read(UDPSocketEvent e)
00173 {
00174     Host host(IpAddr(128, 61, 89, 71), HVZ_PORT, HVZ_HOSTNAME);
00175     //Host host(IpAddr(192, 168, 1, 1), HVZ_PORT, HVZ_HOSTNAME);
00176     
00177     if ( e == UDPSOCKET_READABLE )
00178     {
00179         while( int len = recvfrom(srvr_resp, sizeof(srvr_resp), &host) )
00180         {
00181             if( len <= 0 )
00182               break;   
00183         }
00184     }
00185 }
00186 
00187 void UDP::set_ids(char *response)
00188 {
00189     char buf[9];
00190         
00191     /* First set the deviceID */
00192     memcpy(buf,response+13,8);
00193     buf[8] = '\0';
00194     m_game->id(buf);
00195   
00196     /* Next set the tagID */
00197     memcpy(buf,response+22,8);
00198     buf[8] = '\0';
00199     m_game->life(buf);  
00200     
00201     m_game->save(); 
00202 }
00203 
00204 void UDP::update_settings(char *response)
00205 {
00206     char *tok;
00207     // Clear the lives so we can add them all back
00208     m_game->clear_lives();
00209     
00210     // Start tokenizing the response
00211     tok = strtok(response,"\001"); 
00212     
00213     typedef enum { RNONE,RDEV,RLIVES,RSTUN,RINC } readtype;
00214     readtype type = RNONE; 
00215     
00216     while (tok != NULL)
00217     {
00218         //printf ("%s\r\n",tok);
00219         tok = strtok (NULL, "\001");
00220         
00221         if( strcmp(tok,"deviceid") == 0 ) {
00222             type = RDEV;
00223             continue;
00224         }
00225         
00226         else if( strcmp(tok,"tagids") == 0 ) {
00227             type = RLIVES;
00228             continue;
00229         }
00230         
00231         else if( strcmp(tok,"stuntime") == 0 ) {
00232             type = RSTUN;
00233             continue;
00234         }
00235         
00236         else if( strcmp(tok,"incubate") == 0 ) {
00237             type = RINC;
00238             continue;
00239         }
00240         
00241         switch (type)
00242         {
00243         case RDEV:
00244             m_game->id(tok);
00245             break;
00246         case RLIVES:
00247             m_game->life(tok);
00248             continue; // possibility of more than one
00249         case RSTUN:
00250             m_game->stun_duration((unsigned)atoi(tok));
00251             break;
00252         case RINC:
00253             m_game->incubation_time((unsigned)atoi(tok));
00254             break;
00255         }
00256         
00257         // go back to no parsing
00258         type = RNONE;
00259     }  
00260     
00261     m_game->save(); 
00262 }
00263 
00264 void UDP::send_pull(Host *host)
00265 {
00266     char data[64];
00267 //     char buff[12];
00268 //     
00269 //     memset(data,0,sizeof(data));
00270  
00271 //     if( type == PULL_DEV )
00272 //         sprintf(buff, "%c%c%c%c%c%c%c%c", pullId[0], pullId[1], pullId[2],
00273 //             pullId[3], pullId[4], pullId[5], pullId[6], pullId[7]); 
00274  
00275 //     else
00276 //         sprintf(buff, "%02X%02X%02X%02X%02X%02X", pullId[0], pullId[1], pullId[2],
00277 //             pullId[3], pullId[4], pullId[5]); 
00278  
00279 //     strcat(data, "iHvZ\001pull\001");
00280 //     strcat(data, buff);
00281 //     strcat(data, "\001end");
00282 
00283     sprintf(data, "iHvZ\001pull\001%s\001end", m_game->id().c_str());
00284     
00285     sendto(data, strlen(data), host);
00286 }
00287 
00288   inline void UDP::send_tag(Host *host, vector<string> taggedIDs)
00289   {
00290      int totalsize = 32;
00291           
00292      for (int i = 0; i < taggedIDs.size(); i++)
00293      {
00294         totalsize += taggedIDs[i].size();
00295      }
00296      
00297      char tmp[totalsize];
00298      
00299      // Clear out buffers
00300      memset(tmp, 0, sizeof(tmp));
00301      
00302      // Append tagIDs
00303      for (int i = 0; i < taggedIDs.size(); i++)
00304      {
00305         strcat(tmp, taggedIDs[i].c_str());
00306         strcat(tmp, "\001");
00307      }
00308      string tagids = tmp;
00309           
00310      sprintf(tmp, "iHvZ\001tag\001%s\001%send", m_game->id().c_str(), tagids.c_str());
00311 
00312      sendto(tmp, strlen(tmp), host);
00313   }
00314   
00315 void UDP::resetOnEvent() //Disable callback
00316 {
00317   m_pCb = NULL;
00318   m_pCbItem = NULL;
00319   m_pCbMeth = NULL;
00320 }
00321 
00322 void UDP::onNetUdpSocketEvent(NetUdpSocketEvent e)
00323 {
00324   if(m_pCbItem && m_pCbMeth)
00325     (m_pCbItem->*m_pCbMeth)((UDPSocketEvent) e);
00326   else if(m_pCb)
00327     m_pCb((UDPSocketEvent) e);
00328 }
00329 
00330 UDPErr UDP::checkInst()
00331 {
00332   if(!m_pNetUdpSocket)
00333   {
00334     m_pNetUdpSocket = Net::udpSocket();
00335     if(!m_pNetUdpSocket)
00336     {
00337       return UDPSOCKET_IF; //Interface did not return a socket (usually because a default interface does not exist)
00338     }
00339     m_pNetUdpSocket->setOnEvent(this, &UDP::onNetUdpSocketEvent);
00340   }
00341   return UDPSOCKET_OK;
00342 }