libraries / Mitov / Mitov_ESP8266.hon commit Added link to project report (97a3ba0)
   1////////////////////////////////////////////////////////////////////////////////
   2//                                                                            //
   3//     This software is supplied under the terms of a license agreement or    //
   4//     nondisclosure agreement with Mitov Software and may not be copied      //
   5//     or disclosed except in accordance with the terms of that agreement.    //
   6//         Copyright(c) 2002-2016 Mitov Software. All Rights Reserved.        //
   7//                                                                            //
   8////////////////////////////////////////////////////////////////////////////////
   9
  10#ifndef _MITOV_ESP8266_h
  11#define _MITOV_ESP8266_h
  12
  13#include <Mitov.h>
  14#include <Mitov_BasicEthernet.h>
  15#include <Mitov_StringPrint.h>
  16
  17//#define __ESP8266__DEBUG__
  18
  19namespace Mitov
  20{
  21        class ESP8266;
  22//---------------------------------------------------------------------------
  23        class ESP8266RemoteAccessPoint
  24        {
  25        public:
  26                bool    Enabled = true;
  27                String  SSID;
  28            String      Password;
  29        };
  30//---------------------------------------------------------------------------
  31        class ESP8266Encription
  32        {
  33        public:
  34                bool    WPA = false;
  35                bool    WPA2 = false;
  36        };
  37//---------------------------------------------------------------------------
  38        class ESP8266AccessPoint
  39        {
  40        public:
  41                bool    Enabled = true;
  42                String  SSID;
  43                String  Password;
  44
  45                unsigned long           Channel = 1;
  46                ESP8266Encription       Encription;
  47        };
  48//---------------------------------------------------------------------------
  49        class BasicESP8266Socket : public Mitov::BasicSocket
  50        {
  51                typedef Mitov::BasicSocket inherited;
  52
  53        protected:
  54                ESP8266 &FModule;
  55                bool    FRunning = false;
  56
  57        protected:
  58                BufferPrint     FStringPrint;
  59
  60        public:
  61                virtual bool IsEnabled()
  62                {
  63                        return Enabled && FRunning; //FModule.Enabled;
  64                }
  65
  66                virtual Print *GetPrint()
  67                {
  68                        return &FStringPrint;
  69                }
  70
  71                virtual void BeginPacket()
  72                {
  73                        FStringPrint.Value.clear();
  74                }
  75
  76                virtual void DataReceived( int connectionId, unsigned char AData ) = 0;
  77
  78        public:
  79                BasicESP8266Socket( ESP8266 &AModule );
  80        };
  81//---------------------------------------------------------------------------
  82        class ESP8266 : public OpenWire::Component
  83        {
  84                typedef OpenWire::Component inherited;
  85
  86        public:
  87                OpenWire::SourcePin     AccessPointAddressOutputPin;
  88                OpenWire::SourcePin     AccessPointMACOutputPin;
  89
  90                OpenWire::SourcePin     StationAddressOutputPin;
  91                OpenWire::SourcePin     StationMACOutputPin;
  92
  93        public:
  94                ESP8266AccessPoint      AccessPoint;
  95                Mitov::SimpleObjectList<ESP8266RemoteAccessPoint*>      RemoteAccessPoints;
  96
  97        public:
  98                Mitov::SimpleList<BasicESP8266Socket*>  Sockets;
  99
 100        protected:
 101                Mitov::BasicSerialPort &FSerial;
 102
 103        protected:
 104                Mitov::BasicESP8266Socket       *FServerInstance;
 105
 106        public:
 107                Mitov::BasicESP8266Socket       *FConnections[ 4 ];
 108
 109                int     FReadLength = 0;
 110                int FReadConnectionId = 0;
 111
 112        public:
 113                bool AssignServerID( BasicESP8266Socket *ASocket )
 114                {
 115                        bool AResult = false;
 116                        for( int i = 0; i < 4; ++i )
 117                                if( ! FConnections[ i ] )
 118                                {
 119                                        FConnections[ i ] = ASocket;
 120                                        FServerInstance = ASocket;
 121                                        AResult = true;
 122                                }
 123
 124                        return AResult;
 125                }
 126
 127                void ReleaseServerID( BasicESP8266Socket *ASocket )
 128                {
 129                        if( FServerInstance == ASocket )
 130                                FServerInstance = NULL;
 131
 132                        for( int i = 0; i < 4; ++i )
 133                                if( FConnections[ i ] == ASocket )
 134                                        FConnections[ i ] = NULL;
 135                }
 136
 137                bool AssignConnectionID( BasicESP8266Socket *ASocket, int &AID )
 138                {
 139                        for( int i = 0; i < 4; ++i )
 140                                if( ! FConnections[ i ] )
 141                                {
 142                                        FConnections[ i ] = ASocket;
 143                                        AID = i;
 144                                        return true;
 145                                }
 146
 147                        return false;
 148                }
 149
 150                void ReleaseConnectionID( int AID )
 151                {
 152                        FConnections[ AID ] = FServerInstance;
 153                }
 154
 155                void SendDirect(String data )
 156                {
 157#ifdef __ESP8266__DEBUG__
 158                        Serial.println( data );
 159#endif
 160                        FSerial.GetStream().print( data );
 161                        WaitSentOK( 2000 );
 162                }
 163
 164                void SendDirect( uint8_t *AData, int ASize )
 165                {
 166#ifdef __ESP8266__DEBUG__
 167                        Serial.write( AData, ASize );
 168#endif
 169                        FSerial.GetStream().write( AData, ASize );
 170                        WaitSentOK( 2000 );
 171                }
 172
 173                void WaitSentOK( const int timeout )
 174                {
 175                        String response = "";
 176                        long int time = millis();
 177                         
 178                        while( timeout > millis() - time)
 179                        {
 180                          while(FSerial.GetStream().available())
 181                          {     
 182                                // The esp has data so collecti it 
 183                                char c = FSerial.GetStream().read(); // read the next character.
 184                                response += c;
 185                          }  
 186
 187                          if( response.indexOf( "SEND OK\r\n" ) >= 0 )
 188                                  break;
 189
 190                        }
 191                }
 192
 193                String SendData(String command, String response_key, const int timeout)
 194                {
 195                        String response = "";
 196    
 197#ifdef __ESP8266__DEBUG__
 198                        Serial.println( command );
 199#endif
 200                        FSerial.GetStream().print( command + "\r\n" ); // send the read character to the esp8266
 201    
 202                        long int time = millis();
 203    
 204                        while( timeout > millis() - time)
 205                        {
 206                          while(FSerial.GetStream().available())
 207                          {     
 208                                // The esp has data so collecti it 
 209                                char c = FSerial.GetStream().read(); // read the next character.
 210                                response += c;
 211                          }  
 212
 213                          if( response.indexOf( response_key ) >= 0 )
 214                                  break;
 215
 216                        }
 217    
 218#ifdef __ESP8266__DEBUG__
 219                        Serial.println( response );
 220#endif
 221                        return response;
 222                }
 223
 224                bool SendData(String command, const int timeout, String &AResponse )
 225                {
 226                        AResponse = "";
 227    
 228#ifdef __ESP8266__DEBUG__
 229                        Serial.println( command );
 230#endif
 231
 232                        FSerial.GetStream().print( command + "\r\n" ); // send the read character to the esp8266
 233    
 234                        long int time = millis();
 235    
 236                        while( timeout > millis() - time)
 237                        {
 238                                while(FSerial.GetStream().available())
 239                                {     
 240                                        // The esp has data so collecti it 
 241                                        char c = FSerial.GetStream().read(); // read the next character.
 242                                        AResponse += c;
 243                                }  
 244
 245                                if( AResponse.indexOf( "\r\nOK\r\n" ) >= 0 )
 246                                {
 247#ifdef __ESP8266__DEBUG__
 248                                        Serial.println( AResponse );
 249#endif
 250                                        return true;
 251                                }
 252
 253                                if( AResponse.indexOf( "\r\nERROR\r\n" ) >= 0 )
 254                                {
 255#ifdef __ESP8266__DEBUG__
 256                                        Serial.println( AResponse );
 257#endif
 258                                        return false;
 259                                }
 260
 261                                if( AResponse.indexOf( "\r\nFAIL\r\n" ) >= 0 )
 262                                {
 263#ifdef __ESP8266__DEBUG__
 264                                        Serial.println( AResponse );
 265#endif
 266                                        return false;
 267                                }
 268
 269                        }
 270    
 271#ifdef __ESP8266__DEBUG__
 272                        Serial.println( AResponse );
 273#endif
 274                        return false;
 275                }
 276
 277                bool SendData( String command, const int timeout )
 278                {
 279                        String AResponse;
 280                        return SendData( command, timeout, AResponse );
 281                }
 282
 283        protected:
 284                virtual void SystemStart()
 285                {
 286                        inherited::SystemStart();
 287
 288#ifdef __ESP8266__DEBUG__
 289                        Serial.println( "SystemStart" );
 290#endif
 291                        SendData( "AT+RST", "\r\nready\r\n", 5000 );
 292//                      String AResponse = SendData( "AT+RST", "\r\nready\r\n", 5000 );
 293//                      Serial.println( AResponse );
 294
 295#ifdef __ESP8266__DEBUG__
 296                        Serial.println( "INIT" );
 297#endif
 298
 299                        int AMode = 0;
 300
 301                        for( Mitov::SimpleObjectList<ESP8266RemoteAccessPoint*>::iterator Iter = RemoteAccessPoints.begin(); Iter != RemoteAccessPoints.end(); ++Iter )
 302                                if((* Iter)->Enabled )
 303                                {
 304                                        AMode = 1;
 305                                        break;
 306                                }
 307
 308                        if( AMode == 0 || AccessPoint.Enabled )
 309                                AMode |= 2; // Set it as access point so others can connect
 310
 311//                      AMode = 3;
 312                        SendData( "AT+CWMODE=" + String( AMode ), 5000 );
 313
 314//                      Serial.println( "TTT" );
 315//                      return;
 316
 317                        if( AccessPoint.Enabled )
 318//                              if( AccessPoint.Encription )
 319                        {
 320                                String ASSID;
 321                                if( AccessPoint.SSID != "" )
 322                                        ASSID = AccessPoint.SSID;
 323
 324                                else
 325                                        ASSID = "Arduino";
 326
 327                                String AEncoding;
 328                                if( AccessPoint.Encription.WPA )
 329                                {
 330                                        if( AccessPoint.Encription.WPA2 )
 331                                                AEncoding = "4";
 332
 333                                        else
 334                                                AEncoding = "2";
 335                                }
 336
 337                                else
 338                                {
 339                                        if( AccessPoint.Encription.WPA2 )
 340                                                AEncoding = "3";
 341
 342                                        else
 343                                                AEncoding = "0";
 344                                }
 345
 346                                SendData( "AT+CWSAP=\"" + ASSID + "\",\"" + AccessPoint.Password + "\"," + AccessPoint.Channel + "," + AEncoding, 1000 );
 347                        }
 348
 349                        for( Mitov::SimpleObjectList<ESP8266RemoteAccessPoint*>::iterator Iter = RemoteAccessPoints.begin(); Iter != RemoteAccessPoints.end(); ++Iter )
 350                                if((* Iter)->Enabled )
 351                                        if((* Iter)->SSID != "" )
 352                                                if( SendData( "AT+CWJAP=\"" + (* Iter)->SSID + "\",\"" + (* Iter)->Password + "\"", 20000 ))
 353                                                        break;  
 354
 355                        if( AccessPointAddressOutputPin.IsConnected() || AccessPointMACOutputPin.IsConnected() || StationAddressOutputPin.IsConnected() || StationMACOutputPin.IsConnected() )
 356                        {
 357//                              Serial.println( "ADDRESS:" );
 358                                String AResponse = SendData( "AT+CIFSR", "\r\nOK\r\n",1000 );
 359#ifdef __ESP8266__DEBUG__
 360                                Serial.println( AResponse );
 361#endif
 362
 363                                int AAddressPos = AResponse.indexOf( "+CIFSR:APIP,\"" );
 364
 365                                int AAddressEndPos;
 366                                if( AAddressPos >= 0 )
 367                                {
 368                                        AAddressEndPos = AResponse.indexOf( "\"", AAddressPos + 13 );
 369                                        if( AAddressEndPos >= 0 )
 370                                        {
 371                                                String Addresses = AResponse.substring( AAddressPos + 13, AAddressEndPos );
 372                                                AccessPointAddressOutputPin.Notify( (void *)Addresses.c_str() );
 373                                        }
 374
 375                                        else
 376                                                AAddressEndPos = 0;
 377
 378                                }
 379
 380                                else
 381                                        AAddressEndPos = 0;
 382
 383                                AAddressPos = AResponse.indexOf( "+CIFSR:APMAC,\"", AAddressEndPos );
 384                                if( AAddressPos >= 0 )
 385                                {
 386                                        AAddressEndPos = AResponse.indexOf( "\"", AAddressPos + 14 );
 387                                        if( AAddressEndPos >= 0 )
 388                                        {
 389                                                String Addresses = AResponse.substring( AAddressPos + 14, AAddressEndPos );
 390                                                AccessPointMACOutputPin.Notify( (void *)Addresses.c_str() );
 391                                        }
 392
 393                                        else
 394                                                AAddressEndPos = 0;
 395
 396                                }                               
 397                                else
 398                                        AAddressEndPos = 0;
 399
 400                                AAddressPos = AResponse.indexOf( "+CIFSR:STAIP,\"", AAddressEndPos );
 401                                if( AAddressPos >= 0 )
 402                                {
 403                                        AAddressEndPos = AResponse.indexOf( "\"", AAddressPos + 14 );
 404                                        if( AAddressEndPos >= 0 )
 405                                        {
 406                                                String Addresses = AResponse.substring( AAddressPos + 14, AAddressEndPos );
 407                                                StationAddressOutputPin.Notify( (void *)Addresses.c_str() );
 408                                        }
 409
 410                                        else
 411                                                AAddressEndPos = 0;
 412
 413                                }                               
 414                                else
 415                                        AAddressEndPos = 0;
 416
 417                                AAddressPos = AResponse.indexOf( "+CIFSR:STAMAC,\"", AAddressEndPos );
 418                                if( AAddressPos >= 0 )
 419                                {
 420                                        AAddressEndPos = AResponse.indexOf( "\"", AAddressPos + 15 );
 421                                        if( AAddressEndPos >= 0 )
 422                                        {
 423                                                String Addresses = AResponse.substring( AAddressPos + 15, AAddressEndPos );
 424                                                StationMACOutputPin.Notify( (void *)Addresses.c_str() );
 425                                        }
 426
 427                                        else
 428                                                AAddressEndPos = 0;
 429
 430                                }                               
 431                                else
 432                                        AAddressEndPos = 0;
 433
 434                        }
 435
 436                        SendData( "AT+CIPMUX=1",1000 );
 437                }
 438
 439                virtual void SystemLoopBegin( unsigned long currentMicros ) 
 440                {
 441                        if( FSerial.GetStream().available() )
 442                        {
 443#ifdef __ESP8266__DEBUG__
 444//                              Serial.println( "AVALIABLE" );
 445#endif
 446                                if( ! FReadLength )
 447                                        if(FSerial.GetStream().find("+IPD,"))
 448                                        {
 449#ifdef __ESP8266__DEBUG__
 450                                Serial.println( "DATA" );
 451#endif
 452//                                      int connectionId = FSerial.GetStream().read() - '0';
 453                                                String AIDStr = FSerial.GetStream().readStringUntil( ',' );
 454                                                FReadConnectionId = AIDStr.toInt();
 455#ifdef __ESP8266__DEBUG__
 456                                                Serial.println( AIDStr );
 457                                                Serial.println( FReadConnectionId );
 458#endif
 459//                                      FSerial.GetStream().find("," ); // Skip ','
 460//                                      FSerial.GetStream().read(); // Skip ','
 461                                                String ALengthStr = FSerial.GetStream().readStringUntil( ':' );
 462#ifdef __ESP8266__DEBUG__
 463                                                Serial.println( "Length = " + ALengthStr );
 464#endif
 465                                                FReadLength = ALengthStr.toInt();
 466                                        }
 467
 468                                if( FReadLength )
 469                                        if( FReadConnectionId >= 0 && FReadConnectionId < 4 )
 470                                        {
 471                                                while( FReadLength )
 472                                                {
 473                                                        if( ! FSerial.GetStream().available() )
 474                                                                break;
 475
 476                                                        int AData = FSerial.GetStream().read();
 477//#ifdef __ESP8266__DEBUG__
 478//                                                      Serial.println( (char)AData );
 479//#endif
 480                                                        if( FConnections[ FReadConnectionId ] )
 481                                                                FConnections[ FReadConnectionId ]->DataReceived( FReadConnectionId, AData );
 482
 483                                                        --FReadLength;
 484                                                }
 485                                        }
 486
 487                        }
 488
 489                        inherited::SystemLoopBegin( currentMicros );
 490                }
 491
 492        public:
 493                ESP8266( Mitov::BasicSerialPort &ASerial ) :
 494                        FSerial( ASerial )
 495                {
 496                        memset( FConnections, 0, 4 * sizeof( FConnections[ 0 ] ) );
 497                }
 498
 499        };
 500//---------------------------------------------------------------------------
 501        class ESP8266TCPServerSocket : public BasicESP8266Socket
 502        {
 503                typedef BasicESP8266Socket inherited;
 504
 505//              EthernetServer  *FServer;
 506//              EthernetClient  FClient;
 507
 508                int     FClientCurrentID = -1;
 509
 510        protected:
 511                virtual void StartSocket()
 512                {
 513#ifdef __ESP8266__DEBUG__
 514                                Serial.println( "SERVER::StartSocket" );
 515#endif
 516//                      if( FModule.AssignConnectionID( this ) )
 517                        if( FModule.AssignServerID( this ) )
 518                        {
 519                                FModule.SendData( "AT+CIPSERVER=1," + String( Port ), 2000 );
 520                                FRunning = true;
 521                        }
 522
 523                }
 524
 525/*
 526                virtual void SystemLoopBegin( unsigned long currentMicros ) 
 527                {
 528                        inherited::SystemLoopBegin( currentMicros );
 529                }
 530*/
 531                virtual void DataReceived( int connectionId, unsigned char AData )
 532                {
 533#ifdef __ESP8266__DEBUG__
 534                                Serial.print( "RECEIVED: " );
 535                                Serial.println( connectionId );
 536#endif
 537                        FClientCurrentID = connectionId;
 538                        OutputPin.Notify( &AData );
 539//                      FClientCurrentID = -1;
 540                }
 541
 542        public:
 543                virtual void EndPacket()
 544                {
 545                        if( FStringPrint.Value.size() == 0 )
 546                                return;
 547
 548                        if( FClientCurrentID >= 0 )
 549                        {
 550                                if( FModule.SendData( "AT+CIPSEND=" + String( FClientCurrentID ) + "," + String( FStringPrint.Value.size()), "\r\n> ", 2000 ))
 551                                        FModule.SendDirect( (uint8_t *)FStringPrint.Value, FStringPrint.Value.size() );
 552
 553//                              Serial.println( FStringPrint.Value );
 554                        }
 555
 556                        else
 557                        {
 558/*
 559                                for( int i = 0; i < 4; ++ i )
 560                                        if( FModule.FConnections[ i ] == this )
 561                                        {
 562                                                if( FModule.SendData( "AT+CIPSEND=" + String( i ) + "," + String( FStringPrint.Value.size()), "\r\n> ", 2000 ))
 563                                                        FModule.SendDirect( (uint8_t *)FStringPrint.Value, FStringPrint.Value.size() );
 564
 565                                        }
 566*/
 567                        }
 568
 569//                      FStringPrint.Value.clear();
 570                }
 571
 572        public:
 573                virtual void StopSocket()
 574                {
 575                        if( FRunning )
 576                        {
 577                                FModule.SendData( "AT+CIPSERVER=0," + String( Port ), 2000 );
 578                                FModule.ReleaseServerID( this );
 579                                FRunning = false;
 580                        }
 581                }
 582
 583        public:
 584                using inherited::inherited;
 585
 586        };
 587//---------------------------------------------------------------------------
 588        class ESP8266TCPClientSocket : public BasicESP8266Socket
 589        {
 590                typedef BasicESP8266Socket inherited;
 591
 592        public:
 593                String          URL;
 594                int                     FID;
 595
 596        protected:
 597                virtual void StartSocket()
 598                {
 599#ifdef __ESP8266__DEBUG__
 600                                Serial.println( "CLIENT::StartSocket" );
 601#endif
 602                        if( FModule.AssignConnectionID( this, FID ) )
 603                        {
 604                                FModule.SendData( "AT+CIPSTART=" + String( FID ) +",\"TCP\",\"" + URL + "\"," + String( Port ), 2000 );
 605                                FRunning = true;
 606                        }
 607
 608//                      Serial.println( "StartSocket" );
 609                }
 610
 611                virtual void StopSocket()
 612                {
 613                        if( FRunning )
 614                        {
 615                                FModule.ReleaseConnectionID( FID );
 616                                FModule.SendData( "AT+CIPCLOSE=" + String( FID ), 2000 );
 617                                FRunning = false;
 618                        }
 619//                      FClient.stop();
 620                }
 621
 622                virtual void DataReceived( int connectionId, unsigned char AData )
 623                {
 624                        OutputPin.Notify( &AData );
 625                }
 626
 627        public:
 628                virtual void EndPacket()
 629                {
 630                        if( FStringPrint.Value.size() == 0 )
 631                                return;
 632
 633                        if( FModule.SendData( "AT+CIPSEND=" + String( FID ) + "," + String( FStringPrint.Value.size()), "\r\n> ", 2000 ))
 634                                FModule.SendDirect( (uint8_t *)FStringPrint.Value, FStringPrint.Value.size() );
 635
 636//                      FStringPrint.Value.clear();
 637                }
 638
 639        public:
 640/*
 641                virtual void SystemLoopBegin( unsigned long currentMicros ) 
 642                {
 643                        inherited::SystemLoopBegin( currentMicros );
 644                }
 645*/
 646        public:
 647                using inherited::inherited;
 648
 649        };
 650//---------------------------------------------------------------------------
 651//---------------------------------------------------------------------------
 652//---------------------------------------------------------------------------
 653//---------------------------------------------------------------------------
 654        BasicESP8266Socket::BasicESP8266Socket( ESP8266 &AModule ) :
 655                FModule( AModule )
 656        {
 657                AModule.Sockets.push_back( this );
 658        }
 659//---------------------------------------------------------------------------
 660}
 661
 662#endif