libraries / Mitov / Mitov_BasicEthernet.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_BASIC_ETHERNET_h
  11#define _MITOV_BASIC_ETHERNET_h
  12
  13#include <Mitov.h>
  14//#include <Ethernet.h>
  15
  16namespace Mitov
  17{
  18//---------------------------------------------------------------------------
  19        class TMACAddress
  20        {
  21        public:
  22                byte FMacAddress[6];
  23
  24        public:
  25                TMACAddress(
  26                                uint8_t mac_0, 
  27                                uint8_t mac_1, 
  28                                uint8_t mac_2, 
  29                                uint8_t mac_3, 
  30                                uint8_t mac_4, 
  31                                uint8_t mac_5 )
  32                {
  33                        FMacAddress[ 0 ] = mac_0;
  34                        FMacAddress[ 1 ] = mac_1;
  35                        FMacAddress[ 2 ] = mac_2;
  36                        FMacAddress[ 3 ] = mac_3;
  37                        FMacAddress[ 4 ] = mac_4;
  38                        FMacAddress[ 5 ] = mac_5;
  39                }
  40
  41                TMACAddress()
  42                {
  43                        memset( FMacAddress, 0, sizeof( FMacAddress ) );
  44                }
  45        };
  46//---------------------------------------------------------------------------
  47        inline String MACAdressToString( uint8_t *AMACAddress )
  48        {
  49                char AMACString[ 6 * 3 + 1 ];
  50                sprintf( AMACString, "%02X-%02X-%02X-%02X-%02X-%02X", AMACString[ 0 ], AMACString[ 1 ], AMACString[ 2 ], AMACString[ 3 ], AMACString[ 4 ], AMACString[ 5 ] );
  51                return AMACString;
  52//              MACOutputPin.Notify( AMACString );
  53        }
  54//---------------------------------------------------------------------------
  55        inline String IPAdressToString( ::IPAddress AIPAddress )
  56        {
  57                char AIPString[ 4 * 4 + 1 ];
  58                sprintf( AIPString, "%u.%u.%u.%u", AIPAddress[ 0 ], AIPAddress[ 1 ], AIPAddress[ 2 ], AIPAddress[ 3 ] );
  59                return AIPString;
  60        }
  61//---------------------------------------------------------------------------
  62        class BasicShieldIPAddress
  63        {
  64        public:
  65                bool            Enabled = false;
  66                ::IPAddress     IP;
  67
  68        };
  69//---------------------------------------------------------------------------
  70        class ShieldGatewayAddress : public BasicShieldIPAddress
  71        {
  72        public:
  73                BasicShieldIPAddress    Subnet;
  74        };
  75//---------------------------------------------------------------------------
  76        class ShieldDNSAddress : public BasicShieldIPAddress
  77        {
  78        public:
  79                ShieldGatewayAddress    Gateway;
  80        };
  81//---------------------------------------------------------------------------
  82        class ShieldIPAddress : public BasicShieldIPAddress
  83        {
  84        public:
  85                ShieldDNSAddress        DNS;
  86        };
  87//---------------------------------------------------------------------------
  88        class ShieldIPDNS2Address : public ShieldIPAddress
  89        {
  90        public:
  91                BasicShieldIPAddress    DNS2;
  92        };
  93//---------------------------------------------------------------------------
  94        class BasicSocket : public OpenWire::Component
  95        {
  96                typedef OpenWire::Component inherited;
  97
  98        public:
  99//              OpenWire::SinkPin       InputPin;
 100                OpenWire::SourcePin     OutputPin;
 101
 102        public:
 103                bool                    Enabled = true;
 104                unsigned int    Port = 80;
 105
 106        protected:
 107                virtual void StartSocket() = 0;
 108
 109        public:
 110                void SetEnabled( bool AValue )
 111                {
 112            if( Enabled == AValue )
 113                return;
 114
 115            Enabled = AValue;
 116                        if( IsEnabled() )
 117                                StartSocket();
 118
 119                        else
 120                                StopSocket();
 121
 122                }
 123
 124        public:
 125                virtual bool IsEnabled()
 126                {
 127                        return Enabled;
 128                }
 129
 130                virtual bool CanSend()
 131                {
 132                        return Enabled;
 133                }
 134
 135                virtual void BeginPacket()
 136                {
 137                }
 138
 139                virtual void EndPacket()
 140                {
 141                }
 142
 143                virtual void StopSocket() = 0;
 144
 145        public:
 146                virtual void SystemStart()
 147                {
 148//                      Serial.println( Enabled );
 149                        if( Enabled )
 150                                StartSocket();
 151
 152                        inherited::SystemStart();
 153                }
 154
 155        };
 156//---------------------------------------------------------------------------
 157        template<typename T_OWNER> class BasicEthernetSocket : public Mitov::BasicSocket
 158        {
 159                typedef Mitov::BasicSocket inherited;
 160
 161        protected:
 162                T_OWNER &FOwner;
 163
 164        public:
 165                virtual bool IsEnabled()
 166                {
 167                        return Enabled && FOwner.Enabled;
 168                }
 169
 170                virtual bool CanSend()
 171                {
 172                        return Enabled && FOwner.Enabled;
 173                }
 174
 175                virtual Print *GetPrint() = 0;
 176
 177        public:
 178                BasicEthernetSocket( T_OWNER &AOwner ) :
 179                        FOwner( AOwner )
 180                {
 181                        AOwner.Sockets.push_back( this );
 182                }
 183
 184        };
 185//---------------------------------------------------------------------------
 186        template<typename T_OWNER, typename T_CLIENT> class BasicEthernetConnectSocket : public Mitov::BasicEthernetSocket<T_OWNER>
 187        {
 188                typedef Mitov::BasicEthernetSocket<T_OWNER> inherited;
 189
 190        public:
 191                OpenWire::TypedSourcePin<bool>  ConnectedOutputPin;
 192
 193                OpenWire::SinkPin       FlushInputPin;
 194                OpenWire::SinkPin       DisconnectInputPin;
 195
 196        protected:
 197                T_CLIENT        FClient;
 198
 199        protected:
 200                void DoDisconnect( void *_Data )
 201                {
 202                        FClient.flush();
 203                        FClient.stop();
 204                        ConnectedOutputPin.SetValue( false, true );
 205//                      Serial.println( "DoDisconnect" );
 206//                      Serial.println( FClient.connected() );
 207                }
 208
 209                void DoFlush( void *_Data )
 210                {
 211                        FClient.flush();
 212                }
 213
 214        public:
 215                virtual Print *GetPrint()
 216                {
 217                        return &FClient;
 218                }
 219
 220        public:
 221                virtual void SystemInit()
 222                {
 223                        ConnectedOutputPin.SetValue( false, false );
 224                        inherited::SystemInit();
 225                }
 226
 227        public:
 228                BasicEthernetConnectSocket( T_OWNER &AOwner ) :
 229                        inherited( AOwner )
 230                {
 231                        FlushInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&BasicEthernetConnectSocket::DoFlush );
 232
 233                        DisconnectInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&BasicEthernetConnectSocket::DoDisconnect );
 234                }
 235
 236        };
 237//---------------------------------------------------------------------------
 238        template<typename T_OWNER, typename T_CLIENT> class TCPClientSocket : public BasicEthernetConnectSocket<T_OWNER, T_CLIENT>
 239        {
 240                typedef BasicEthernetConnectSocket<T_OWNER, T_CLIENT> inherited;
 241
 242        public:
 243                String          URL;
 244                ::IPAddress     IPAddress;
 245
 246        protected:
 247                virtual void StartSocket()
 248                {
 249//                      Serial.println( "StartSocket" );
 250                        if( URL.length() )
 251                                inherited::FClient.connect( URL.c_str(), inherited::Port );
 252
 253                        else
 254                        {
 255//                              IPAddress.printTo( Serial );
 256                                inherited::FClient.connect( IPAddress, inherited::Port );
 257                        }
 258                }
 259
 260                virtual void StopSocket()
 261                {
 262                        inherited::FClient.flush();
 263                        inherited::FClient.stop();
 264                        inherited::ConnectedOutputPin.SetValue( false, true );
 265                }
 266
 267        public:
 268                virtual void SystemLoopBegin( unsigned long currentMicros ) 
 269                {
 270                        if ( inherited::FClient.available() )
 271                        {
 272                                unsigned char AByte = inherited::FClient.read();
 273                                inherited::OutputPin.SendValue( Mitov::TDataBlock( 1, &AByte ));
 274//                              inherited::OutputPin.Notify( &AByte );
 275                        }
 276
 277                        inherited::ConnectedOutputPin.SetValue( inherited::FClient.connected(), true );
 278
 279                        if (! inherited::FClient.connected()) 
 280                        {
 281                                inherited::FClient.stop(); // Do we need this?
 282                                inherited::ConnectedOutputPin.SetValue( false, true );
 283                        }
 284
 285                        inherited::SystemLoopBegin( currentMicros );
 286                }
 287
 288        public:
 289                TCPClientSocket( T_OWNER &AOwner, ::IPAddress AIPAddress ) :
 290                        inherited( AOwner ),
 291                        IPAddress( AIPAddress )
 292                {
 293                }
 294        };
 295//---------------------------------------------------------------------------
 296        template<typename T_OWNER, typename T_SERVER, typename T_CLIENT> class TCPServerSocket : public BasicEthernetConnectSocket<T_OWNER, T_CLIENT>
 297        {
 298                typedef BasicEthernetConnectSocket<T_OWNER, T_CLIENT> inherited;
 299
 300        protected:
 301                T_SERVER        *FServer;
 302
 303        protected:
 304                virtual void StartSocket()
 305                {
 306//                      Serial.println( "StartSockect" );
 307                        if( FServer )
 308                                return;
 309
 310//                      Serial.println( Port );
 311                        FServer = new T_SERVER( inherited::Port );
 312                        FServer->begin();
 313//                      Serial.println( "Start Server Sockect" );
 314//                      Serial.println( inherited::Port );
 315                }
 316
 317                virtual void SystemLoopBegin( unsigned long currentMicros ) 
 318                {
 319                        if( FServer )
 320                        {
 321                                if( ! inherited::FClient )
 322                                {
 323//                                      Serial.println( inherited::Port );
 324//                                      Serial.println( "TRY CLIENT" );
 325                                        inherited::FClient = FServer->available();
 326
 327//                                      if( inherited::FClient )
 328//                                              Serial.println( "CLIENT" );
 329
 330//                                      Serial.println( "TRY CLIENT OUT" );
 331                                }
 332
 333/*
 334                                if( inherited::FClient )
 335                                        if (! inherited::FClient.connected()) 
 336                                        {
 337                                                Serial.println( "STOP" );
 338                                                inherited::FClient.stop(); // Do we need this?
 339                                        }
 340*/
 341                                if( inherited::FClient )
 342                                {
 343//                                      Serial.println( "CLIENT" );
 344                                        if( inherited::FClient.available() )
 345                                        {
 346                                                unsigned char AByte = inherited::FClient.read();
 347//                              Serial.println( "RECEIVED" );
 348                                                inherited::OutputPin.SendValue( Mitov::TDataBlock( 1, &AByte ));
 349//                                              inherited::OutputPin.Notify( &AByte );
 350                                        }
 351
 352                                        if( ! inherited::FClient.connected() ) 
 353                                        {
 354//                                              Serial.println( "STOP" );
 355                                                inherited::FClient.stop(); // Do we need this?
 356                                                inherited::ConnectedOutputPin.SetValue( false, true );
 357                                        }
 358                                }
 359                        }
 360
 361//                      Serial.println( inherited::FClient.connected() );
 362
 363                        inherited::ConnectedOutputPin.SetValue( inherited::FClient.connected(), true );
 364//                      Serial.println( "SYSTEM_LOOP" );
 365                        inherited::SystemLoopBegin( currentMicros );
 366//                      Serial.println( "SYSTEM_LOOP_OUT" );
 367                }
 368
 369        public:
 370                virtual bool CanSend()
 371                {
 372                        return inherited::Enabled && inherited::FOwner.Enabled && inherited::FClient;
 373                }
 374
 375                virtual void StopSocket()
 376                {
 377                        if( FServer )
 378                        {
 379                                delete FServer;
 380                                FServer = NULL;
 381                        }
 382                }
 383
 384/*
 385                virtual void EndPacket()
 386                {
 387                        Serial.println( "EndPacket" );
 388//                      inherited::FClient.flush();
 389//                      delay(1000);
 390//                      inherited::FClient.stop();
 391                }
 392*/
 393        public:
 394                TCPServerSocket( T_OWNER &AOwner ) :
 395                        inherited( AOwner ),
 396                        FServer( NULL )
 397                {
 398                }
 399
 400/*
 401                virtual ~TCPServerSocket()
 402                {
 403                        if( FServer )
 404                                delete FServer;
 405                }
 406*/
 407        };
 408//---------------------------------------------------------------------------
 409        template<typename T_OWNER, typename T_UDP> class UDPSocket : public BasicEthernetSocket<T_OWNER>
 410        {
 411                typedef BasicEthernetSocket<T_OWNER> inherited;
 412
 413        public:
 414                OpenWire::SourcePin     RemoteIPOutputPin;
 415                OpenWire::SourcePin     RemotePortOutputPin;
 416
 417        public:
 418                unsigned int    RemotePort = 80;
 419                ::IPAddress             RemoteIPAddress;
 420
 421        protected:
 422                T_UDP FSocket;
 423                String FHostName;
 424                bool   FResolved;
 425
 426        public:
 427                virtual bool CanSend()
 428                {
 429                        return FResolved && inherited::CanSend();
 430                }
 431
 432        protected:
 433                virtual void StartSocket()
 434                {
 435                        if( FHostName != "" )
 436                        {
 437//                              Serial.println( "TEST1" );
 438                                FResolved = inherited::FOwner.GetIPFromHostName( FHostName, RemoteIPAddress );
 439                        }
 440
 441//                      Serial.print( "StartSocket: " );
 442//                      Serial.println( inherited::Port );
 443                        FSocket.begin( inherited::Port );
 444                }
 445
 446        public:
 447                virtual void BeginPacket()
 448                {
 449//                      Serial.print( "BeginPacket: " );
 450//                      Serial.print( RemoteIPAddress );
 451//                      Serial.print( " " );
 452//                      Serial.println( RemotePort );
 453                        FSocket.beginPacket( RemoteIPAddress, RemotePort );
 454////  FSocket.beginPacket( RemoteIPAddress, 8888 );
 455//  FSocket.println( "Hello1" );
 456////  FSocket.endPacket();
 457                }
 458
 459                virtual void EndPacket()
 460                {
 461//                      Serial.println( "EndPacket" );
 462//                      FSocket.println( "Hello" );
 463                        FSocket.endPacket();
 464//                      delay( 1000 );
 465                }
 466
 467                virtual void StopSocket()
 468                {
 469//                      Serial.println( "StopSocket" );
 470                        FSocket.stop();
 471                }
 472
 473                virtual Print *GetPrint()
 474                {
 475//  FSocket.println( "Hello2" );
 476//                      return &Serial;
 477//                      Serial.println( "GetPrint" );
 478                        return &FSocket;
 479                }
 480
 481        public:
 482                virtual void SystemLoopBegin( unsigned long currentMicros ) 
 483                {
 484                        int APacketSize = FSocket.parsePacket();
 485                        if( APacketSize )
 486                        {
 487//                              Serial.println( APacketSize );
 488                                byte *Adata = new byte[ APacketSize ];
 489                                FSocket.read( Adata, APacketSize );
 490
 491                                inherited::OutputPin.SendValue( Mitov::TDataBlock( APacketSize, Adata ));
 492                                RemoteIPOutputPin.SendValue( IPAdressToString( FSocket.remoteIP() ));
 493                                RemotePortOutputPin.SendValue( FSocket.remotePort() );
 494
 495                                delete []Adata;
 496                        }
 497/*
 498                        if ( FSocket.available() )
 499                        {
 500                                unsigned char AByte = FSocket.read();
 501                                inherited::OutputPin.Notify( &AByte );
 502                        }
 503*/
 504                        inherited::SystemLoopBegin( currentMicros );
 505                }
 506
 507        public:
 508                UDPSocket( T_OWNER &AOwner, ::IPAddress ARemoteIPAddress ) :
 509                        inherited( AOwner ),
 510                        RemoteIPAddress( ARemoteIPAddress ),
 511                        FResolved( true )
 512                {
 513                }
 514
 515                UDPSocket( T_OWNER &AOwner, String AHostName ) :
 516                        inherited( AOwner ),
 517                        FHostName( AHostName ),
 518                        FResolved( false )
 519                {
 520                }
 521        };
 522//---------------------------------------------------------------------------
 523        class BasicEthernetShield : public OpenWire::Component
 524        {
 525                typedef OpenWire::Component inherited;
 526
 527        public:
 528                Mitov::SimpleList<BasicEthernetSocket<BasicEthernetShield>*>    Sockets;
 529
 530        public:
 531                bool    Enabled = true;
 532
 533        public:
 534                void SetEnabled( bool AValue )
 535                {
 536            if( Enabled == AValue )
 537                return;
 538
 539            Enabled = AValue;
 540                        if( Enabled )
 541                                StartEthernet();
 542
 543                        else
 544                                StopEthernet();
 545
 546                }
 547
 548        public:
 549                virtual bool GetIPFromHostName( String AHostName, ::IPAddress &AAdress ) = 0;
 550
 551        protected:
 552                virtual void SystemInit()
 553                {
 554                        if( Enabled )
 555                                StartEthernet();
 556
 557                        inherited::SystemInit();
 558                }
 559
 560                virtual void StopEthernet()
 561                {
 562                        for( int i = 0; i < Sockets.size(); ++i )
 563                                Sockets[ i ]->StopSocket();
 564                }
 565
 566        void RestartEthernet()
 567                {
 568                        if( ! Enabled )
 569                                return;
 570
 571//                      T_SERIAL->end();
 572//                      Ethernet.end();
 573                        StartEthernet();
 574                }
 575
 576                virtual void StartEthernet() = 0;
 577
 578        };
 579//---------------------------------------------------------------------------
 580        template<typename T_ROOT, T_ROOT *T_INSTANCE, typename T> class EthernetSocketInput : public Mitov::CommonSink
 581        {
 582                typedef Mitov::CommonSink       inherited;
 583
 584        protected:
 585                virtual void DoReceive( void *_Data )
 586                {
 587//                      Serial.print( "DoReceive" );
 588                        if( T_INSTANCE->CanSend() )
 589                        {
 590                                T_INSTANCE->BeginPacket();
 591
 592//                              Serial.print( "PRINT: " );
 593//                              Serial.println( *(T*)_Data );
 594
 595                                T_INSTANCE->GetPrint()->println( *(T*)_Data );
 596                                T_INSTANCE->EndPacket();
 597                        }
 598                }
 599        };
 600//---------------------------------------------------------------------------
 601        template<typename T_ROOT, T_ROOT *T_INSTANCE> class EthernetSocketBinaryInput : public Mitov::CommonSink
 602        {
 603                typedef Mitov::CommonSink       inherited;
 604
 605        protected:
 606                virtual void DoReceive( void *_Data )
 607                {
 608                        if( T_INSTANCE->CanSend() )
 609                        {
 610                                T_INSTANCE->BeginPacket();
 611                                Mitov::TDataBlock ADataBlock = *(Mitov::TDataBlock*)_Data;
 612
 613//                              Serial.println( ADataBlock.Size );
 614                                T_INSTANCE->GetPrint()->write((uint8_t *) ADataBlock.Data, ADataBlock.Size );
 615//                              T_INSTANCE->GetPrint()->write( *(unsigned char*)_Data );
 616                                T_INSTANCE->EndPacket();
 617                        }
 618                }
 619        };
 620//---------------------------------------------------------------------------
 621        template<typename T_ROOT, T_ROOT *T_INSTANCE> class EthernetSocketStringInput : public Mitov::CommonSink
 622        {
 623                typedef Mitov::CommonSink       inherited;
 624
 625        protected:
 626                virtual void DoReceive( void *_Data )
 627                {
 628                        if( T_INSTANCE->CanSend() )
 629                        {
 630                                T_INSTANCE->BeginPacket();
 631                                T_INSTANCE->GetPrint()->println( (char*)_Data );
 632                                T_INSTANCE->EndPacket();
 633                        }
 634                }
 635        };
 636//---------------------------------------------------------------------------
 637        template<typename T_ROOT, T_ROOT *T_INSTANCE, typename T_OBJECT> class EthernetSocketObjectInput : public Mitov::CommonSink
 638        {
 639                typedef Mitov::CommonSink       inherited;
 640
 641        protected:
 642                virtual void DoReceive( void *_Data )
 643                {
 644                        if( T_INSTANCE->CanSend() )
 645                        {
 646                                T_INSTANCE->BeginPacket();
 647                                Print *APrint = T_INSTANCE->GetPrint();
 648                                APrint->println( ((T_OBJECT *)_Data)->ToString().c_str() );
 649                                T_INSTANCE->EndPacket();
 650                        }
 651                }
 652        };
 653//---------------------------------------------------------------------------
 654}       
 655#endif