├── .travis.yml ├── CHANGES.txt ├── LICENSE ├── README.md ├── examples ├── ConnectWithWPA │ └── ConnectWithWPA.ino ├── MQTT_Publish │ └── MQTT_Publish.ino ├── UDP_Multicast_Receiver │ └── UDP_Multicast_Receiver.ino ├── UDP_Multicast_Transmitter │ └── UDP_Multicast_Transmitter.ino ├── UdpNTPClient │ └── UdpNTPClient.ino ├── WiFiWebClient │ └── WiFiWebClient.ino └── WiFiWebClientSSL │ └── WiFiWebClientSSL.ino ├── keywords.txt ├── library.properties └── src ├── WiFiSpi.cpp ├── WiFiSpi.h ├── WiFiSpiClient.cpp ├── WiFiSpiClient.h ├── WiFiSpiServer.cpp ├── WiFiSpiServer.h ├── WiFiSpiUdp.cpp ├── WiFiSpiUdp.h ├── config.h └── utility ├── debug.cpp ├── debug.h ├── espspi_drv.cpp ├── espspi_drv.h ├── espspi_proxy.cpp ├── espspi_proxy.h ├── srvspi_drv.cpp ├── srvspi_drv.h ├── wifi_spi.h ├── wifispi_drv.cpp ├── wifispi_drv.h ├── wl_definitions.h └── wl_types.h /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | before_install: 4 | - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16" 5 | - sleep 3 6 | - export DISPLAY=:1.0 7 | - wget http://downloads.arduino.cc/arduino-1.8.5-linux64.tar.xz 8 | - tar xf arduino-1.8.5-linux64.tar.xz 9 | - sudo mv arduino-1.8.5 /usr/local/share/arduino 10 | - sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino 11 | 12 | install: 13 | - ln -s $PWD /usr/local/share/arduino/libraries/WiFiSpi 14 | 15 | script: 16 | - arduino --verify --board ${BOARD} $PWD/examples/ConnectWithWPA/ConnectWithWPA.ino 17 | 18 | notifications: 19 | email: 20 | on_success: change 21 | on_failure: change 22 | 23 | env: 24 | - BOARD=arduino:avr:uno 25 | # - BOARD=arduino:avr:yun 26 | # - BOARD=arduino:avr:diecimila:cpu=atmega168 27 | # - BOARD=arduino:avr:diecimila:cpu=atmega328 28 | # - BOARD=arduino:avr:nano:cpu=atmega168 29 | # - BOARD=arduino:avr:nano:cpu=atmega328 30 | # - BOARD=arduino:avr:mega:cpu=atmega1280 31 | # - BOARD=arduino:avr:mega:cpu=atmega2560 32 | # - BOARD=arduino:avr:megaADK 33 | # - BOARD=arduino:avr:leonardo 34 | # - BOARD=arduino:avr:micro 35 | # - BOARD=arduino:avr:esplora 36 | # - BOARD=arduino:avr:mini:cpu=atmega168 37 | # - BOARD=arduino:avr:mini:cpu=atmega328 38 | # - BOARD=arduino:avr:ethernet 39 | # - BOARD=arduino:avr:bt:cpu=atmega168 40 | # - BOARD=arduino:avr:bt:cpu=atmega328 41 | # - BOARD=arduino:avr:lilypad:cpu=atmega168 42 | # - BOARD=arduino:avr:lilypad:cpu=atmega328 43 | # - BOARD=arduino:avr:pro:cpu=atmega168 44 | # - BOARD=arduino:avr:pro:cpu=atmega328 45 | # - BOARD=arduino:sam:arduino_due_x -------------------------------------------------------------------------------- /CHANGES.txt: -------------------------------------------------------------------------------- 1 | 0.3.0 (2021-13-05) 2 | * BearSSL engine, protocol 0.3.0 3 | * UDP Multicast support 4 | 0.2.3 (2019-02-18) 5 | * SSL Client connection, verifySSL function, protocol 0.2.3 6 | 0.2.0 (2019-01-27) 7 | * Protocol changed. Status shortened to 2 bytes, added XOR check. Data messages checked by a CRC8. 8 | * Developed mechanism of confirming and repeating messages. 9 | * Added hardware reset support (hardReset command) 10 | * Added support for external 8266 circuit guarding the GPIO15 (SS pin) on reset 11 | 0.1.4 (2019-01-24) 12 | * Fixed delays in SPI protocol 13 | * Added softReset and protocolVersion commands (might be added earlier) 14 | 0.1.1 (2018-07-03) 15 | * Added parameter to init function (SPI max speed) 16 | * Enabled STM32F1 architecture although there will be a lot of work yet 17 | 0.1.0 (2017-03-14) 18 | * First version for testing 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | WiFiSpi 2 | ======= 3 | 4 | This library connects Arduino to ESP8266 module and uses it as a dedicated WiFi device. The SPI interface is used because of its strictly master/slave nature. 5 | 6 | The library allows Arduino to be client or server on the WiFi network. 7 | 8 | ## News 9 | 10 | #### 2021-01-25 11 | 12 | Added UDP Multicast support 13 | 14 | #### 2021-01-02 15 | 16 | Fixed a bug with closing server connection when closing asynchronously opened another client. 17 | Changed deprecated boolean type to bool. 18 | 19 | #### 2019-02-18 20 | 21 | Added SSL connection to WiFiClient class. Added verifySSL function. 22 | 23 | #### 2019-01-27 24 | 25 | Enhanced communications protocol (added CRC-8 and confirmation of message reception). Shortened the status message from 4 bytes to 2 bytes and added XOR check. The protocol version is now 0.2.0 and is incompatible with the former one. 26 | 27 | Added support for hardware circuit removing the problems with ESP8266 reset by pulling GPIO15 (SS) pin to GND on reset. 28 | 29 | ## Requirements 30 | 31 | ### ESP8266 device 32 | 33 | The ESP8266 has two SPI interfaces. The first is connected to the flash memory, the second (named HSPI) can be used by user. The HSPI signals are multiplexed with GPIO12-15. Suitable device for the slave is ESP-12. On the ESP device must be run a custom firmware - see WifiESPSPI project. 34 | 35 | ### Wiring 36 | 37 | The library uses hardware SPI on Arduino so most of the signals are fixed to certain pins. 38 | 39 | The wiring is as follows: 40 | 41 | Name | Uno | STM32F103C8 | ESP8266 42 | | | SPI1 SPI2 | GPIO NodeMCU 43 | -------+---------+--------------------------------- 44 | SS | D10 | PA4 PB12 | 15 D8 45 | MOSI | D11 | PA7 PB15 | 13 D7 46 | MISO | D12 | PA6 PB14 | 12 D6 47 | SCK | D13 | PA5 PB13 | 14 D5 48 | 49 | The SS pin is the only pin the user can change. Changing SS to another pin enables more devices on one SPI interface. 50 | 51 | Please be careful, the ESP8266 chip ports are **NOT** 5V tolerant, if you're connecting to a 5V device you have to use a level converter. 52 | 53 | ## Library Reference 54 | 55 | The library implements almost the same functions as the [Arduino WiFi library](https://www.arduino.cc/en/Reference/WiFi). 56 | 57 | ### Setup 58 | 59 | All the important defines are in file **config.h**. The user can comment and/or uncomment them and modify the behaviour of the library. 60 | 61 | ### WiFiSpiClass 62 | 63 | After including *WiFiSpi.h* header the *WiFiSpi* variable is automatically instantiated. Use the variable to perform the following calls. 64 | 65 | - **void init(int8_t pin, uint32_t max_speed = 0, SPIClass \*in_spi = &SPI, int8_t hwResetPin = -1)** 66 | Initializes the library and the Arduino SPI interface. Must be called on beginning of the communication. The parameter *max_speed* limits the SPI speed. Tests on STM32F1 show that speeds as high as 9 Mhz are usable. The parameter *in_spi* allows to use another SPI port (if there are more present in the MCU). Refer to a particular implementation of SPIClass. The optional parameter *hwResetPin* defines the pin which is connected to reset pin on ESP8266 for hardware reset. Then this parameter is present, master resets the ESP8266 on start. 67 | 68 | - **char\* firmwareVersion()** 69 | Returns version of custom firmware loaded into ESP8266. 70 | 71 | - **char\* protocolVersion()** 72 | Returns version of protocol the ESP8266 firmware operates with. 73 | 74 | - **char\* masterProtocolVersion()** 75 | Returns version of protocol the master runs. 76 | 77 | - **uint8_t checkProtocolVersion()** 78 | Checks master and ESP protocol version. If they match, returns 1, otherwise 0. 79 | 80 | - **uint8_t begin(const char\* ssid)** 81 | Connects to an open (unencrypted) wifi. Returns a value from *wl_status_t* enum(when connected returns WL_CONNECTED). Establishing of the connection may last several seconds. 82 | 83 | - **uint8_t begin(const char\* ssid, const char \*passphrase)** 84 | Connects to a WPA/WPA2 encrypted wifi. Returns status from *wl_status_t* type (when connected returns WL_CONNECTED). Establishing of the connection may last several seconds. 85 | 86 | - **int disconnect(void)** 87 | Disconnects from the WiFi network. Returns a value from *wl_status_t* enum(when disconnected returns WL_DISCONNECTED). 88 | 89 | - **uint8_t status()** 90 | Returns the connection status of the WiFi interface. The returned value is one of the enum *wl_status_t*. 91 | 92 | - **int8_t hostByName(const char\* aHostname, IPAddress& aResult)** 93 | Resolves the given hostname to an IP address. Returns 1 for Ok else error code. 94 | 95 | - **void softReset(void)** 96 | Sends reset command to ESP8266. The ESP8266 then resets itself. The command is performed only if the connection between the host and ESP8266 is not broken. 97 | 98 | - **void hardReset(void)** 99 | Resets the ESP8266. One pin on master unit must be wired to reset pin on ESP8266. The pin is defined in **init** function. 100 | 101 | ---------- 102 | 103 | 104 | - **bool config(IPAddress local_ip)** 105 | Changes IP configuration, sets local IP address and disables DHCP client. 106 | 107 | - **bool config(IPAddress local_ip, IPAddress dns_server)** 108 | Changes IP configuration, sets local IP address, primary DNS server and disables DHCP client. 109 | 110 | - **bool config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway)** 111 | Changes IP configuration, sets local IP address, primary DNS server, static gateway address and disables DHCP client. 112 | 113 | - **bool config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet)** 114 | Changes IP configuration, sets local IP address, primary DNS server, static gateway address, subnet mask and disables DHCP client. 115 | 116 | - **bool setDNS(IPAddress dns_server1)** 117 | Changes IP configuration, sets primary DNS server IP address. 118 | 119 | - **bool setDNS(IPAddress dns_server1, IPAddress dns_server2)** 120 | Changes IP configuration, sets primary and secondary DNS server IP addresses. 121 | 122 | - **uint8_t\* macAddress(uint8_t\* mac)** 123 | Returns MAC address value of the WiFi interface. The MAC address is copiend to the array *mac* and also returned as a pointer to this array. The array size must be at least 6 bytes. 124 | 125 | - **IPAddress localIP()** 126 | Returns local IP address value. 127 | 128 | - **IPAddress subnetMask()** 129 | Returns interface subnet mask value. 130 | 131 | - **IPAddress gatewayIP()** 132 | Returns interface gateway address value. 133 | 134 | - **char\* SSID()** 135 | Returns the current SSID associated with the network. 136 | 137 | - **uint8_t\* BSSID()** 138 | Returns the current BSSID associated with the network. It is in fact the MAC address of the Access Point. Returns a pointer to byte array of 6 byte length. 139 | 140 | - **int32_t RSSI()** 141 | Returns the currect RSSI (signal strength in dBm) as a signed value. 142 | 143 | 144 | ---------- 145 | 146 | 147 | - **int8_t scanNetworks()** 148 | Scans the WiFi network. Returns the number of networks found or error value (WL_FAILURE). The call may last several seconds. 149 | 150 | - **char\* SSID(uint8_t networkItem)** 151 | Returns the current SSID associated with the discovered network during the network scan. Parameter *networkItem* is the index into a discovered networks array. 152 | 153 | - **uint8_t encryptionType(uint8_t networkItem)** 154 | Returns the encryption type of the discovered network during the network scan. The returned value is one of the enum *wl_enc_type*. Parameter *networkItem* is the index into a discovered networks array. 155 | 156 | - **int32_t RSSI(uint8_t networkItem)** 157 | Returns the signal strength in dBm of the discovered network during the network scan. The returned value is signed 32 bit integer. Parameter *networkItem* is the index into a discovered networks array. 158 | 159 | ---------- 160 | 161 | - **uint8_t setSSLFingerprint(uint8_t\* fingerprint)** 162 | Loads server certificate SHA-1 fingerprint into BearSSL engine. Subsequent connections are checked against 163 | this fingerprint. The fingerprint is an array of type *uint8_t[20]*. 164 | Note that without checking the fingerprint the TLS connection is insecure and prone to MITM attacks. 165 | 166 | 167 | ### WiFiSpiClient 168 | 169 | The WiFiSpiClient class performs data communication between your program and the remote site. It is used not only with client connections (where Arduino acts as a client) but also in server connections (sending responses to a web request) and udp connections. 170 | The library has a pool of 4 sockets and after exhausting all the sockets no more connection is available. Therefore it is important to close the socket (i. e. stop the client) when it is no longer used. 171 | 172 | - **WiFiSpiClient()** 173 | Default constructor, creates a closed connection. Use it for client side of communication. 174 | 175 | - **WiFiSpiClient(uint8_t sock)** 176 | Creates client for open server connection. Called by the library in when server connection has data. 177 | 178 | - **int connect(IPAddress ip, uint16_t port)** 179 | Connects to the specified IP address and port. Returns a value from enum *wl_tcp_state* (for open connection returns ESTABLISHED). 180 | 181 | - **int connect(const char \*host, uint16_t port)** 182 | Connects to the specified host and port. Returns a value from enum *wl_tcp_state* (for open connection returns ESTABLISHED). 183 | 184 | - **int connectSSL(IPAddress ip, uint16_t port)** 185 | Connects using SSL to the specified IP address and port. Returns a value from enum *wl_tcp_state* (for open connection returns ESTABLISHED). If there is a previously loaded certificate fingerprint, the server certificate is checked against the fingerprint, otherwise the connection is insecure (prone to MITM attacks). 186 | 187 | - **int connectSSL(const char \*host, uint16_t port)** 188 | Connects using SSL to the specified host and port. Returns a value from enum *wl_tcp_state* (for open connection returns ESTABLISHED). If there is a previously loaded certificate fingerprint, the server certificate is checked against the fingerprint, otherwise the connection is insecure (prone to MITM attacks). 189 | 190 | - **uint8_t connected()** 191 | Returns connection state as a logic value: 1 = connected, 0 = error. Note that the connection could be closed by a server when ESP8266 reads all data in its internal buffer although the master haven't read it yet. 192 | 193 | - **uint8_t status()** 194 | Returns connection state as a value from enum *wl_tcp_state* (for open connection returns ESTABLISHED). 195 | 196 | - **void stop()** 197 | Stops the client (disconnects from the remote server if still connected) and frees the socket used for the client. 198 | 199 | - **operator bool()** 200 | Returns true when the client is associated with a socket. 201 | 202 | ---------- 203 | 204 | - **int available()** 205 | Returns available bytes in the input queue (data received from the network) for reading. 206 | 207 | - **int read()** 208 | Reads one byte from the input queue. Returns -1 for an error. 209 | 210 | - **int read(uint8_t \*buf, size_t size)** 211 | Reads *size* bytes into an input buffer *buf*. Returns 0 on success, -1 on error or insufficient data in the input queue. 212 | 213 | - **int peek()** 214 | Peeks into the input queue and returns the first byte in the queue. On error returns -1. 215 | 216 | - **size_t write(uint8_t)** 217 | Sends one byte to the network. Returns 1 on success, 0 on error. 218 | 219 | - **size_t write(const void \*buf, size_t size)** 220 | Sends the buffer to the network. Returns number of bytes transmitted. 221 | 222 | - **size_t write(const char \*str)** 223 | Sends the character string to the network. Returns number of bytes transmitted. 224 | 225 | - **IPAddress remoteIP()** 226 | Returns the IP address of the host who sent the current incoming packet. When there is no incoming connection returns 0.0.0.0. 227 | 228 | - **uint16_t remotePort()** 229 | Returns the port of the host who sent the current incoming packet. When there is no incoming connection returns 0. 230 | 231 | ### WiFiSpiServer 232 | 233 | The library has a pool of 4 sockets and after exhausting all the sockets no more connection is available. Therefore it is important to close the socket (i. e. stop the server) when it is no longer used. This version of the library is further constrained to one client connection per server. 234 | 235 | - **WiFiSpiServer(uint16_t port)** 236 | Constructor. Does not open a connection. 237 | 238 | - **void begin()** 239 | Creates and starts the server listener on specified *port*. 240 | 241 | - **uint8_t status()** 242 | Returns the server's status. Return 1 for opened connection, 0 for closed or error. 243 | 244 | - **void stop()** 245 | Stops the listener, stops the associated client (if any) and frees the socket. 246 | 247 | - **WiFiSpiClient available(uint8_t\* status = NULL)** 248 | Returns WiFiSpiClient instance for communication with remote client. Returns opened WiFiSpiClient instance when there is a remote client connected. When there is no connection the function returns closed client. Use the WiFiSpiClient's bool operator on the return value to test it. 249 | When pointer *status* is not null, loads it with the remote client's status. 250 | 251 | - **size_t write(uint8_t)** 252 | Writes a byte to the output queue. Returns 1 on success, 0 on error. 253 | 254 | - **size_t write(const uint8_t \*buf, size_t size)** 255 | Writes a buffer to the output queue. Returns number of bytes written. 256 | Note: transmitting data can be also achieved using a WiFiSpiClient object returned by the *WiFiSpiServer::available()* function. 257 | 258 | ### WiFiSpiUDP 259 | 260 | - **WiFiSpiUdp()** 261 | Default constuctor. 262 | 263 | - **uint8_t begin(uint16_t port)** 264 | Initializes the instance, starts listening on specified *port*. Returns 1 if successful, 0 on error. 265 | 266 | - **uint8_t begin(uint16_t multicastIP, uint16_t port)** 267 | Initializes the instance, starts listening on specified *port* for multicast messages from *multicastIP* address. Returns 1 if successful, 0 on error. 268 | 269 | - **void stop()** 270 | Stops listening on the UDP port, frees the UDP socket used. 271 | 272 | - **int beginPacket(IPAddress ip, uint16_t port)** 273 | Starts building up a packet to send to the remote host specific in *ip* and *port*. Returns 1 if successful, 0 if there was a problem with the connection. This function works for both unicast and multicast communication. 274 | 275 | - **int endPacket()** 276 | Finishes the packet and sends it. Returns 1 if the packet was sent successfully, 0 if there was an error. 277 | 278 | - **size_t write(uint8_t)** 279 | Writes a single byte into the packet. Returns 1 on sucesss, 0 on error. 280 | 281 | - **size_t write(const uint8_t \*buffer, size_t size)** 282 | Writes *size* bytes from buffer into the packet. Returns number of bytes written, on error returns 0. 283 | 284 | - **int parsePacket();** 285 | Starts processing the next available incoming packet. Returns the size of the packet in bytes, or 0 if no packets are available. 286 | 287 | - **int available()** 288 | Returns the number of bytes remaining in the current packet. 289 | 290 | - **int read()** 291 | Reads a single byte from the current packet. 292 | 293 | - **int read(unsigned char\* buffer, size_t len)** 294 | - **int read(char\* buffer, size_t len)** 295 | Reads up to *len* bytes from the current packet and places them into *buffer*. Returns the number of bytes read, or 0 if none are available or an error occurred. 296 | 297 | - **int peek()** 298 | Returns the next byte from the current packet without moving on to the next byte. 299 | 300 | - **IPAddress remoteIP()** 301 | Returns the IP address of the host who sent the current incoming packet. When there is no incoming connection returns 0.0.0.0. 302 | 303 | - **uint16_t remotePort()** 304 | Returns the port of the host who sent the current incoming packet. When there is no incoming connection returns 0. 305 | 306 | ## Examples 307 | 308 | - **ConnectWithWPA** 309 | Connects to the network and prints out some information. 310 | 311 | - **WiFiWebClient** 312 | Connects to the google.com site and transmits the http response. 313 | 314 | - **MQTT_Publish** 315 | Simple mqtt messaging. 316 | 317 | - **UdpNTPClient** 318 | Reads current time and date from a NTP server. 319 | 320 | - **UDP_Multicast_Transmitter** 321 | Peridically transmits a short messaage via UDP multicast. 322 | 323 | - **UDP_Multicast_Receiver** 324 | Listens for multicast messages, reads them and prints them out. 325 | 326 | More examples to come soon. But you can easily use the ones from WiFi library. Don't forget to add a line *WiFiSpi.init();* before using other library functions. 327 | 328 | ## Debugging 329 | 330 | For some debugging information on Serial output uncomment line 23 (#define _DEBUG) in file espspi_srv.cpp. 331 | 332 | ## ToDo and Wish Lists 333 | 334 | - more SPI protocol optimization 335 | - TLS: loading and checking server certificate chain instead of the fingerprint 336 | 337 | ## Credits 338 | 339 | The protocol running on SPI interface was inspired by protocol used in Arduino WiFi library. The code structure and some code is taken from this library, too. 340 | 341 | The SPI master code was inspired and parts were taken from the [ESPSlave example](https://github.com/esp8266/Arduino/tree/master/libraries/SPISlave) of the ESP8266 Arduino project. 342 | 343 | 344 | -------------------------------------------------------------------------------- /examples/ConnectWithWPA/ConnectWithWPA.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This example connects to an unencrypted Wifi network. 4 | Then it prints the MAC address of the Wifi module, 5 | the IP address obtained, and other network details. 6 | 7 | Circuit: 8 | 1. On ESP8266 must be running (flashed) WiFiSPIESP application. 9 | 10 | 2. Connect the master (Arduino or STM32F103) to the following pins on the esp8266: 11 | 12 | ESP8266 | | 13 | GPIO NodeMCU Name | Uno | STM32F103 14 | =============================================== 15 | 15 D8 SS | D10 | PA4 16 | 13 D7 MOSI | D11 | PA7 17 | 12 D6 MISO | D12 | PA6 18 | 14 D5 SCK | D13 | PA5 19 | 20 | Note: If the ESP is booting at a moment when the SPI Master (i.e. Arduino) has the Select line HIGH (deselected) 21 | the ESP8266 WILL FAIL to boot! 22 | 23 | original sketch for WiFi library created 13 July 2010 24 | by dlf (Metodo2 srl) 25 | modified 31 May 2012 26 | by Tom Igoe 27 | 28 | modified for WiFiSpi library 14 Mar 2017 29 | by Jiri Bilek 30 | */ 31 | 32 | #include 33 | 34 | // WiFi credentials 35 | char ssid[] = "yourNetwork"; // your network SSID (name) 36 | char pass[] = "secretPassword"; // your network password 37 | 38 | void setup() { 39 | //Initialize serial and wait for port to open: 40 | Serial.begin(9600); 41 | while (!Serial) { 42 | ; // wait for serial port to connect. Needed for native USB port only 43 | } 44 | 45 | // Initialize the WifiSpi library 46 | WiFiSpi.init(); 47 | 48 | // check for the presence of the ESP module: 49 | if (WiFiSpi.status() == WL_NO_SHIELD) { 50 | Serial.println("WiFi module not present"); 51 | // don't continue: 52 | while (true); 53 | } 54 | 55 | if (!WiFiSpi.checkProtocolVersion()) { 56 | Serial.println("Protocol version mismatch. Please upgrade the firmware"); 57 | // don't continue: 58 | while (true); 59 | } 60 | 61 | // attempt to connect to Wifi network: 62 | int status; // the Wifi radio's status 63 | 64 | do { 65 | Serial.print("Attempting to connect to WPA SSID: "); 66 | Serial.println(ssid); 67 | // Connect to WPA/WPA2 network: 68 | status = WiFiSpi.begin(ssid, pass); 69 | } while (status != WL_CONNECTED); 70 | 71 | // you're connected now, so print out the data: 72 | Serial.println("You're connected to the network"); 73 | printCurrentNet(); 74 | printWifiData(); 75 | } 76 | 77 | void loop() { 78 | // check the network connection once every 10 seconds: 79 | delay(10000); 80 | printCurrentNet(); 81 | } 82 | 83 | void printWifiData() { 84 | // print your WiFi module's IP address: 85 | IPAddress ip = WiFiSpi.localIP(); 86 | Serial.print("IP Address: "); 87 | Serial.println(ip); 88 | 89 | // print your MAC address: 90 | byte mac[6]; 91 | WiFiSpi.macAddress(mac); 92 | Serial.print("MAC address: "); 93 | Serial.print(mac[5], HEX); 94 | Serial.print(":"); 95 | Serial.print(mac[4], HEX); 96 | Serial.print(":"); 97 | Serial.print(mac[3], HEX); 98 | Serial.print(":"); 99 | Serial.print(mac[2], HEX); 100 | Serial.print(":"); 101 | Serial.print(mac[1], HEX); 102 | Serial.print(":"); 103 | Serial.println(mac[0], HEX); 104 | } 105 | 106 | void printCurrentNet() { 107 | // print the SSID of the network you're attached to: 108 | Serial.print("SSID: "); 109 | Serial.println(WiFiSpi.SSID()); 110 | 111 | // print the MAC address of the router you're attached to: 112 | byte *bssid = WiFiSpi.BSSID(); 113 | Serial.print("BSSID: "); 114 | Serial.print(bssid[5], HEX); 115 | Serial.print(":"); 116 | Serial.print(bssid[4], HEX); 117 | Serial.print(":"); 118 | Serial.print(bssid[3], HEX); 119 | Serial.print(":"); 120 | Serial.print(bssid[2], HEX); 121 | Serial.print(":"); 122 | Serial.print(bssid[1], HEX); 123 | Serial.print(":"); 124 | Serial.println(bssid[0], HEX); 125 | 126 | // print the received signal strength: 127 | long rssi = WiFiSpi.RSSI(); 128 | Serial.print("signal strength (RSSI):"); 129 | Serial.println(rssi); 130 | } 131 | -------------------------------------------------------------------------------- /examples/MQTT_Publish/MQTT_Publish.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Publishing in the callback 3 | 4 | Uses the PubSubClient library 5 | 6 | - connects to an MQTT server (broker.hivemq.com) 7 | - subscribes to the topic "EspSpi/inTopic" 8 | - when a message is received, republishes it to "EspSpi/outTopic" 9 | - every 5 seconds writes number in sequence from 1 to "EspSpi/outTopic/msg" 10 | 11 | This example shows how to publish messages within the 12 | callback function. The callback function header needs to 13 | be declared before the PubSubClient constructor and the 14 | actual callback defined afterwards. 15 | This ensures the client reference in the callback function 16 | is valid. 17 | 18 | The result could be viewed online on http://www.hivemq.com/demos/websocket-client/ 19 | 20 | Circuit: 21 | 1. On ESP8266 must be running (flashed) WiFiSPIESP application. 22 | 23 | 2. Connect the master (Arduino or STM32F103) to the following pins on the esp8266: 24 | 25 | ESP8266 | | 26 | GPIO NodeMCU Name | Uno | STM32F103 27 | =============================================== 28 | 15 D8 SS | D10 | PA4 29 | 13 D7 MOSI | D11 | PA7 30 | 12 D6 MISO | D12 | PA6 31 | 14 D5 SCK | D13 | PA5 32 | 33 | Note: If the ESP is booting at the moment when the SPI Master (i.e. Arduino) has the Select line HIGH (deselected) 34 | the ESP8266 WILL FAIL to boot! 35 | */ 36 | 37 | #include 38 | #include 39 | 40 | // WiFi credentials 41 | char ssid[] = "yourNetwork"; // your network SSID (name) 42 | char pass[] = "secretPassword"; // your network password (use for WPA) 43 | 44 | // MQTT Broker Address 45 | //IPAddress server(18, 185, 232, 233); // broker.hivemq.com (check it if the client does not connect, the IP address may change) 46 | const char *server = "broker.hivemq.com"; 47 | 48 | // Callback function header 49 | void callback(char* topic, byte* payload, unsigned int length); 50 | 51 | WiFiSpiClient wifiClient; 52 | PubSubClient client(server, 1883, callback, wifiClient); 53 | 54 | // Callback function 55 | void callback(char* topic, byte* payload, unsigned int length) { 56 | // In order to republish this payload, a copy must be made 57 | // as the orignal payload buffer will be overwritten whilst 58 | // constructing the PUBLISH packet. 59 | 60 | // Allocate the correct amount of memory for the payload copy 61 | byte* p = (byte*)malloc(length); 62 | // Copy the payload to the new buffer 63 | memcpy(p, payload, length); 64 | client.publish("EspSpi/outTopic", p, length); 65 | // Free the memory 66 | free(p); 67 | } 68 | 69 | void setup() { 70 | //Initialize serial and wait for port to open: 71 | Serial.begin(9600); 72 | while (!Serial) { 73 | ; // wait for serial port to connect. Needed for native USB port only 74 | } 75 | 76 | // Initialize the WifiSpi library 77 | WiFiSpi.init(); 78 | 79 | // check for the presence of the shield: 80 | if (WiFiSpi.status() == WL_NO_SHIELD) { 81 | Serial.println("WiFi shield not present"); 82 | // don't continue: 83 | while (true); 84 | } 85 | 86 | if (!WiFiSpi.checkProtocolVersion()) { 87 | Serial.println("Protocol version mismatch. Please upgrade the firmware"); 88 | // don't continue: 89 | while (true); 90 | } 91 | 92 | // attempt to connect to Wifi network 93 | int status; // the Wifi radio's status 94 | 95 | do { 96 | Serial.print("Attempting to connect to SSID: "); 97 | Serial.println(ssid); 98 | // Connect to WPA/WPA2 network 99 | status = WiFiSpi.begin(ssid, pass); 100 | } while (status != WL_CONNECTED); 101 | 102 | Serial.println("Connected to wifi"); 103 | 104 | // Connect to mqtt broker 105 | if (client.connect("arduinoTest")) { 106 | client.publish("EspSpi/outTopic","hello world"); 107 | client.subscribe("EspSpi/inTopic"); 108 | } 109 | } 110 | 111 | void reconnect() { 112 | // Loop until we're reconnected 113 | while (!client.connected()) { 114 | Serial.print(F("Attempting MQTT connection...")); 115 | 116 | // Attempt to connect 117 | if (client.connect("arduinoTest")) { 118 | Serial.println(F("reconnected")); 119 | 120 | // Once connected, publish an announcement... 121 | client.publish("EspSpi/outTopic", "reconnected"); 122 | 123 | // ... and resubscribe 124 | client.subscribe("EspSpi/inTopic"); 125 | } else { 126 | Serial.print(F("failed, rc=")); 127 | Serial.println(client.state()); 128 | } 129 | } 130 | } 131 | 132 | unsigned long lastMillis = millis(); 133 | unsigned int number = 1; 134 | 135 | void loop() { 136 | client.loop(); 137 | 138 | // Sending every 5 seconds 139 | if (lastMillis < millis()) { 140 | if (!client.connected()) 141 | reconnect(); 142 | 143 | char payload[10]; 144 | sprintf(payload, "%u", number); 145 | client.publish("EspSpi/outTopic/msg", payload); 146 | ++number; 147 | 148 | lastMillis = millis() + 5000; 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /examples/UDP_Multicast_Receiver/UDP_Multicast_Receiver.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Receive multicast UDP packets 3 | 4 | This sketch receives multicast UDP packets from address 239.1.74.74, port 7474 5 | Uses WiFi ESP8266 module. 6 | 7 | This example is written for a network using WPA encryption. 8 | 9 | Circuit: 10 | 1. On ESP8266 must be running (flashed) WiFiSPIESP application. 11 | 12 | 2. Connect the Arduino to the following pins on the esp8266: 13 | 14 | ESP8266 | 15 | GPIO NodeMCU Name | STM32F103 16 | =================================== 17 | 15 D8 SS | PA4 18 | 13 D7 MOSI | PA7 19 | 12 D6 MISO | PA6 20 | 14 D5 SCK | PA5 21 | RESET | PB12 22 | 23 | Note: If the ESP is booting at the moment when the SPI Master (i.e. Arduino) has the Select line HIGH (deselected) 24 | the ESP8266 WILL FAIL to boot! 25 | 26 | */ 27 | 28 | #include 29 | 30 | char ssid[] = "your ssid here"; // your network SSID (name) 31 | char pass[] = "your password here"; // your network password 32 | 33 | #if defined(MCU_STM32F103C8) 34 | const uint8_t RESET_PIN = PB12; // For STM32F103 35 | #endif 36 | 37 | // Note: remoteIP is a multicast address, it should begin with 239.x.x.x or some other 38 | // appropriate multicast address. 39 | // It's not the same as your local IP address (192.168.x.x, for example)! 40 | IPAddress remoteIP(239, 1, 74, 74); 41 | 42 | // The remote port must be otherwise unused on any machine that is receiving these packets 43 | int remotePort = 7474; 44 | 45 | // Create the UDP object 46 | WiFiSpiUdp udp; 47 | 48 | void setup() { 49 | #if defined(MCU_STM32F103C8) 50 | // Reset PIN 51 | pinMode(RESET_PIN, OUTPUT); 52 | digitalWrite(RESET_PIN, HIGH); 53 | #endif 54 | 55 | //Initialize serial and wait for port to open: 56 | Serial.begin(115200); 57 | while (!Serial.available()) { 58 | ; // wait for serial port to connect. Needed for native USB port only 59 | } 60 | 61 | Serial.println("Reset ESP8266"); 62 | 63 | #if defined(MCU_STM32F103C8) 64 | // Reset the ESP 65 | digitalWrite(RESET_PIN, LOW); 66 | delay(100); 67 | digitalWrite(RESET_PIN, HIGH); 68 | delay(500); 69 | #endif 70 | 71 | // Initialize the library 72 | WiFiSpi.init(SS, 100000); 73 | 74 | // check for the presence of the shield: 75 | if (WiFiSpi.status() == WL_NO_SHIELD) { 76 | Serial.println("Error in communication with the ESP board, halted"); 77 | WiFiSpi.status(); 78 | // don't continue: 79 | while (true); 80 | } 81 | 82 | if (! WiFiSpi.checkProtocolVersion()) 83 | Serial.println("Please upgrade the firmware"); 84 | 85 | // attempt to connect to Wifi network: 86 | uint8_t status; 87 | do { 88 | Serial.print("Attempting to connect to SSID: "); 89 | Serial.println(ssid); 90 | // Connect to WPA/WPA2 network. 91 | status = WiFiSpi.begin(ssid, pass); 92 | } while (status != WL_CONNECTED); 93 | 94 | Serial.println("Connected to wifi"); 95 | 96 | // Start listening for multicast messages 97 | udp.beginMulticast(remoteIP, remotePort); 98 | } 99 | 100 | void loop() { 101 | // If there's data available, read a packet 102 | int packetSize = udp.parsePacket(); 103 | 104 | // If there's data, read them and print them 105 | if (packetSize > 0) { 106 | Serial.print("Incoming packet, size="); Serial.println(packetSize); 107 | while (udp.available()) { 108 | int inp = udp.read(); 109 | if (inp >= ' ' && inp <= 0x7f) 110 | Serial.print(char(inp)); 111 | else { 112 | Serial.print(inp); Serial.print(' '); 113 | } 114 | } 115 | Serial.println(); 116 | } 117 | 118 | delay(100); 119 | } 120 | 121 | 122 | void printWifiStatus() { 123 | // print the SSID of the network you're attached to: 124 | Serial.print("SSID: "); 125 | Serial.println(WiFiSpi.SSID()); 126 | 127 | // print your WiFi shield's IP address: 128 | IPAddress ip = WiFiSpi.localIP(); 129 | Serial.print("IP Address: "); 130 | Serial.println(ip); 131 | 132 | // print the received signal strength: 133 | long rssi = WiFiSpi.RSSI(); 134 | Serial.print("signal strength (RSSI): "); 135 | Serial.print(rssi); 136 | Serial.println(" dBm"); 137 | } 138 | -------------------------------------------------------------------------------- /examples/UDP_Multicast_Transmitter/UDP_Multicast_Transmitter.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Transmit multicast UDP packets 3 | 4 | This sketch transmits multicast UDP packets to address 239.1.74.74, port 7474 5 | Uses WiFi ESP8266 module. 6 | 7 | This example is written for a network using WPA encryption. 8 | 9 | Circuit: 10 | 1. On ESP8266 must be running (flashed) WiFiSPIESP application. 11 | 12 | 2. Connect the Arduino to the following pins on the esp8266: 13 | 14 | ESP8266 | 15 | GPIO NodeMCU Name | STM32F103 16 | =================================== 17 | 15 D8 SS | PA4 18 | 13 D7 MOSI | PA7 19 | 12 D6 MISO | PA6 20 | 14 D5 SCK | PA5 21 | RESET | PB12 22 | 23 | Note: If the ESP is booting at the moment when the SPI Master (i.e. Arduino) has the Select line HIGH (deselected) 24 | the ESP8266 WILL FAIL to boot! 25 | 26 | */ 27 | 28 | #include 29 | 30 | char ssid[] = "your ssid here"; // your network SSID (name) 31 | char pass[] = "your password here"; // your network password 32 | 33 | #if defined(MCU_STM32F103C8) 34 | const uint8_t RESET_PIN = PB12; 35 | #endif 36 | 37 | // Note: remoteIP is a multicast address, it should begin with 239.x.x.x or some other 38 | // appropriate multicast address. 39 | // It's not the same as your local IP address (192.168.x.x, for example)! 40 | IPAddress remoteIP(239, 1, 74, 74); 41 | 42 | // The remote port must be otherwise unused on any machine that is receiving these packets 43 | int remotePort = 7474; 44 | 45 | // Create the UDP object 46 | WiFiSpiUdp udp; 47 | 48 | void setup() { 49 | #if defined(MCU_STM32F103C8) 50 | // Reset PIN 51 | pinMode(RESET_PIN, OUTPUT); 52 | digitalWrite(RESET_PIN, HIGH); 53 | #endif 54 | 55 | //Initialize serial and wait for port to open: 56 | Serial.begin(115200); 57 | while (!Serial.available()) { 58 | ; // wait for serial port to connect. Needed for native USB port only 59 | } 60 | 61 | Serial.println("Reset ESP8266"); 62 | 63 | #if defined(MCU_STM32F103C8) 64 | // Reset the ESP 65 | digitalWrite(RESET_PIN, LOW); 66 | delay(100); 67 | digitalWrite(RESET_PIN, HIGH); 68 | delay(500); 69 | #endif 70 | 71 | // Initialize the library 72 | WiFiSpi.init(SS, 100000); 73 | 74 | // check for the presence of the shield: 75 | if (WiFiSpi.status() == WL_NO_SHIELD) { 76 | Serial.println("Error in communication with the ESP board, halted"); 77 | WiFiSpi.status(); 78 | // don't continue: 79 | while (true); 80 | } 81 | 82 | if (! WiFiSpi.checkProtocolVersion()) 83 | Serial.println("Please upgrade the firmware"); 84 | 85 | // attempt to connect to Wifi network: 86 | uint8_t status; 87 | do { 88 | Serial.print("Attempting to connect to SSID: "); 89 | Serial.println(ssid); 90 | // Connect to WPA/WPA2 network. 91 | status = WiFiSpi.begin(ssid, pass); 92 | } while (status != WL_CONNECTED); 93 | 94 | Serial.println("Connected to wifi"); 95 | 96 | // Start UDP communication. No IP needed, because we are transmitting data 97 | udp.begin(0); 98 | } 99 | 100 | void loop() { 101 | static uint16_t counter = 0; // The payload is only a simple counter 102 | 103 | // via multicast we send the counter as the UDP message 104 | if (udp.beginPacket(remoteIP, remotePort) == 1) { 105 | uint8_t buffer[2]; 106 | 107 | ++counter; 108 | buffer[0] = counter >> 8; 109 | buffer[1] = (counter && 0xff); 110 | 111 | // Write the payload 112 | udp.write(buffer, sizeof(buffer)); 113 | 114 | // Send the packet 115 | if (udp.endPacket() == 1) { 116 | // Success 117 | Serial.println(counter); 118 | } 119 | else { 120 | Serial.println("send failed"); 121 | } 122 | } 123 | else { 124 | Serial.println("open failed"); 125 | } 126 | 127 | delay(1000); 128 | } 129 | 130 | 131 | void printWifiStatus() { 132 | // print the SSID of the network you're attached to: 133 | Serial.print("SSID: "); 134 | Serial.println(WiFiSpi.SSID()); 135 | 136 | // print your WiFi shield's IP address: 137 | IPAddress ip = WiFiSpi.localIP(); 138 | Serial.print("IP Address: "); 139 | Serial.println(ip); 140 | 141 | // print the received signal strength: 142 | long rssi = WiFiSpi.RSSI(); 143 | Serial.print("signal strength (RSSI):"); 144 | Serial.print(rssi); 145 | Serial.println(" dBm"); 146 | } 147 | -------------------------------------------------------------------------------- /examples/UdpNTPClient/UdpNTPClient.ino: -------------------------------------------------------------------------------- 1 | /* 2 | WiFiSPI example: UdpNTPClient 3 | 4 | Gets the time from a Network Time Protocol (NTP) time server. 5 | Demonstrates the use of UDP to send and receive data packets 6 | For more on NTP time servers and the messages needed to communicate with them, 7 | see http://en.wikipedia.org/wiki/Network_Time_Protocol 8 | 9 | This example is written for a network using WPA encryption. 10 | 11 | Circuit: 12 | 1. On ESP8266 must be running (flashed) WiFiSPIESP application. 13 | 14 | 2. Connect the master (Arduino or STM32F103) to the following pins on the esp8266: 15 | 16 | ESP8266 | | 17 | GPIO NodeMCU Name | Uno | STM32F103 18 | =============================================== 19 | 15 D8 SS | D10 | PA4 20 | 13 D7 MOSI | D11 | PA7 21 | 12 D6 MISO | D12 | PA6 22 | 14 D5 SCK | D13 | PA5 23 | 24 | Note: If the ESP is booting at the moment when the SPI Master (i.e. Arduino) has the Select line HIGH (deselected) 25 | the ESP8266 WILL FAIL to boot! 26 | 27 | modified for WiFiSpi library 25 Nov 2017 28 | by Jiri Bilek 29 | */ 30 | 31 | #include "WiFiSpi.h" 32 | #include "WiFiSpiUdp.h" 33 | 34 | // WiFi credentials 35 | char ssid[] = "yourNetwork"; // your network SSID (name) 36 | char pass[] = "secretPassword"; // your network password (use for WPA) 37 | 38 | int status = WL_IDLE_STATUS; // the Wifi radio's status 39 | 40 | char timeServer[] = "time.nist.gov"; // NTP server 41 | unsigned int localPort = 2390; // local port to listen for UDP packets 42 | 43 | const int NTP_PACKET_SIZE = 48; // NTP timestamp is in the first 48 bytes of the message 44 | const int UDP_TIMEOUT = 2000; // timeout in miliseconds to wait for an UDP packet to arrive 45 | 46 | byte packetBuffer[NTP_PACKET_SIZE]; // buffer to hold incoming and outgoing packets 47 | 48 | // A UDP instance to let us send and receive packets over UDP 49 | WiFiSpiUdp Udp; 50 | 51 | void setup() 52 | { 53 | // initialize serial for debugging 54 | Serial.begin(115200); 55 | while (!Serial) { 56 | ; // wait for serial port to connect. Needed for native USB port only 57 | } 58 | 59 | // initialize the ESP module 60 | WiFiSpi.init(); 61 | 62 | // check for the presence of the shield 63 | if (WiFiSpi.status() == WL_NO_SHIELD) { 64 | Serial.println("WiFi shield not present"); 65 | // don't continue 66 | while (true); 67 | } 68 | 69 | if (!WiFiSpi.checkProtocolVersion()) { 70 | Serial.println("Protocol version mismatch. Please upgrade the firmware"); 71 | // don't continue: 72 | while (true); 73 | } 74 | 75 | // attempt to connect to WiFi network 76 | while (status != WL_CONNECTED) { 77 | Serial.print("Attempting to connect to WPA SSID: "); 78 | Serial.println(ssid); 79 | // Connect to WPA/WPA2 network 80 | status = WiFiSpi.begin(ssid, pass); 81 | } 82 | 83 | // you're connected now, so print out the data 84 | Serial.println("You're connected to the network"); 85 | 86 | Udp.begin(localPort); 87 | } 88 | 89 | void loop() 90 | { 91 | sendNTPpacket(timeServer); // send an NTP packet to a time server 92 | 93 | // wait for a reply for UDP_TIMEOUT miliseconds 94 | unsigned long startMs = millis(); 95 | while (!Udp.parsePacket() && (millis() - startMs) < UDP_TIMEOUT) {} 96 | 97 | // when there should be a packet do not call parsePacket() once more, call available() instead 98 | if (Udp.available()) { 99 | Serial.println("packet received"); 100 | // We've received a packet, read the data from it into the buffer 101 | Udp.read(packetBuffer, NTP_PACKET_SIZE); 102 | 103 | // the timestamp starts at byte 40 of the received packet and is four bytes, 104 | // or two words, long. First, extract the two words: 105 | 106 | unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); 107 | unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); 108 | // combine the four bytes (two words) into a long integer 109 | // this is NTP time (seconds since Jan 1 1900): 110 | unsigned long secsSince1900 = highWord << 16 | lowWord; 111 | Serial.print("Seconds since Jan 1 1900 = "); 112 | Serial.println(secsSince1900); 113 | 114 | // now convert NTP time into everyday time: 115 | Serial.print("Unix time = "); 116 | // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: 117 | const unsigned long seventyYears = 2208988800UL; 118 | // subtract seventy years: 119 | unsigned long epoch = secsSince1900 - seventyYears; 120 | // print Unix time: 121 | Serial.println(epoch); 122 | 123 | 124 | // print the hour, minute and second: 125 | Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT) 126 | Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day) 127 | Serial.print(':'); 128 | if (((epoch % 3600) / 60) < 10) { 129 | // In the first 10 minutes of each hour, we'll want a leading '0' 130 | Serial.print('0'); 131 | } 132 | Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute) 133 | Serial.print(':'); 134 | if ((epoch % 60) < 10) { 135 | // In the first 10 seconds of each minute, we'll want a leading '0' 136 | Serial.print('0'); 137 | } 138 | Serial.println(epoch % 60); // print the second 139 | } 140 | 141 | // wait ten seconds before asking for the time again 142 | delay(10000); 143 | } 144 | 145 | // send an NTP request to the time server at the given address 146 | void sendNTPpacket(char *ntpSrv) 147 | { 148 | // set all bytes in the buffer to 0 149 | memset(packetBuffer, 0, NTP_PACKET_SIZE); 150 | // Initialize values needed to form NTP request 151 | // (see URL above for details on the packets) 152 | 153 | packetBuffer[0] = 0b11100011; // LI, Version, Mode 154 | packetBuffer[1] = 0; // Stratum, or type of clock 155 | packetBuffer[2] = 6; // Polling Interval 156 | packetBuffer[3] = 0xEC; // Peer Clock Precision 157 | // 8 bytes of zero for Root Delay & Root Dispersion 158 | packetBuffer[12] = 49; 159 | packetBuffer[13] = 0x4E; 160 | packetBuffer[14] = 49; 161 | packetBuffer[15] = 52; 162 | 163 | // all NTP fields have been given values, now 164 | // you can send a packet requesting a timestamp: 165 | Udp.beginPacket(ntpSrv, 123); //NTP requests are to port 123 166 | 167 | Udp.write(packetBuffer, NTP_PACKET_SIZE); 168 | 169 | Udp.endPacket(); 170 | } 171 | -------------------------------------------------------------------------------- /examples/WiFiWebClient/WiFiWebClient.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Web client 3 | 4 | This sketch connects to a website (http://www.example.com) 5 | using a WiFi ESP8266 module. 6 | 7 | This example is written for a network using WPA encryption. 8 | 9 | Circuit: 10 | 1. On ESP8266 must be running (flashed) WiFiSPIESP application. 11 | 12 | 2. Connect the master (Arduino or STM32F103) to the following pins on the esp8266: 13 | 14 | ESP8266 | | 15 | GPIO NodeMCU Name | Uno | STM32F103 16 | =============================================== 17 | 15 D8 SS | D10 | PA4 18 | 13 D7 MOSI | D11 | PA7 19 | 12 D6 MISO | D12 | PA6 20 | 14 D5 SCK | D13 | PA5 21 | 22 | Note: If the ESP is booting at the moment when the SPI Master (i.e. Arduino) has the Select line HIGH (deselected) 23 | the ESP8266 WILL FAIL to boot! 24 | 25 | original sketch for WiFi library created 13 July 2010 26 | by dlf (Metodo2 srl) 27 | modified 31 May 2012 28 | by Tom Igoe 29 | 30 | modified for WiFiSpi library 14 Mar 2017 31 | by Jiri Bilek 32 | */ 33 | 34 | 35 | #include 36 | 37 | // WiFi credentials 38 | char ssid[] = "yourNetwork"; // your network SSID (name) 39 | char pass[] = "secretPassword"; // your network password (use for WPA) 40 | 41 | // if you don't want to use DNS (and reduce your sketch size) 42 | // use the numeric IP instead of the name for the server: 43 | //IPAddress server(93,184,216,34); // numeric IP for www.example.com (no DNS) 44 | char server[] = "www.example.com"; // name address using DNS 45 | 46 | // Initialize the Ethernet client library 47 | // with the IP address and port of the server 48 | // that you want to connect to (port 80 is default for HTTP): 49 | WiFiSpiClient client; 50 | 51 | void setup() { 52 | //Initialize serial and wait for port to open: 53 | Serial.begin(9600); 54 | while (!Serial) { 55 | ; // wait for serial port to connect. Needed for native USB port only 56 | } 57 | 58 | // Initialize the WifiSpi library 59 | WiFiSpi.init(); 60 | 61 | // check for the presence of the shield: 62 | if (WiFiSpi.status() == WL_NO_SHIELD) { 63 | Serial.println("WiFi shield not present"); 64 | // don't continue: 65 | while (true); 66 | } 67 | 68 | if (!WiFiSpi.checkProtocolVersion()) { 69 | Serial.println("Protocol version mismatch. Please upgrade the firmware"); 70 | // don't continue: 71 | while (true); 72 | } 73 | 74 | // attempt to connect to Wifi network: 75 | Serial.print("Attempting to connect to SSID: "); 76 | Serial.println(ssid); 77 | // Connect to WPA/WPA2 network. Change this line if using open network: 78 | int status = WiFiSpi.begin(ssid, pass); 79 | 80 | if (status != WL_CONNECTED) { 81 | Serial.println("Cannot connect to AP. Stop."); 82 | // don't continue if connection failed 83 | while (true); 84 | } 85 | 86 | Serial.println("Connected to wifi"); 87 | printWifiStatus(); 88 | 89 | Serial.println("\nStarting connection to server..."); 90 | // if you get a connection, report back via serial: 91 | if (client.connect(server, 80)) { 92 | Serial.println("connected to server"); 93 | // Make a HTTP request: 94 | // Note: client.print() is transmitting one char per a message that is awfully wasting the SPI bus bandwidth 95 | // client.write(char*) is optimized and has minimum overhead 96 | client.write("GET / HTTP/1.1\r\n" 97 | "Host: www.example.com\r\n" 98 | "Connection: close\r\n\r\n"); 99 | } 100 | } 101 | 102 | void loop() { 103 | // if there are incoming bytes available 104 | // from the server, read them and print them: 105 | while (client.available()) { 106 | char c = client.read(); 107 | Serial.write(c); 108 | } 109 | 110 | // if the server's disconnected, stop the client: 111 | if (!client.connected()) { 112 | Serial.println(); 113 | Serial.println("disconnecting from server."); 114 | client.stop(); 115 | 116 | // do nothing forevermore: 117 | while (true); 118 | } 119 | } 120 | 121 | 122 | void printWifiStatus() { 123 | // print the SSID of the network you're attached to: 124 | Serial.print("SSID: "); 125 | Serial.println(WiFiSpi.SSID()); 126 | 127 | // print your WiFi shield's IP address: 128 | IPAddress ip = WiFiSpi.localIP(); 129 | Serial.print("IP Address: "); 130 | Serial.println(ip); 131 | 132 | // print the received signal strength: 133 | long rssi = WiFiSpi.RSSI(); 134 | Serial.print("signal strength (RSSI):"); 135 | Serial.print(rssi); 136 | Serial.println(" dBm"); 137 | } 138 | -------------------------------------------------------------------------------- /examples/WiFiWebClientSSL/WiFiWebClientSSL.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SSL Web client 3 | 4 | This sketch connects to a website (https://www.example.com) 5 | using a WiFi ESP8266 module and checks the validity of the server certificate. 6 | 7 | This example is written for a network using WPA encryption. 8 | 9 | Circuit: 10 | 1. On ESP8266 must be running (flashed) WiFiSPIESP application. 11 | 12 | 2. Connect the master (Arduino or STM32F103) to the following pins on the esp8266: 13 | 14 | ESP8266 | | 15 | GPIO NodeMCU Name | Uno | STM32F103 16 | =============================================== 17 | 15 D8 SS | D10 | PA4 18 | 13 D7 MOSI | D11 | PA7 19 | 12 D6 MISO | D12 | PA6 20 | 14 D5 SCK | D13 | PA5 21 | 22 | Note: If the ESP is booting at the moment when the SPI Master (i.e. Arduino) has the Select line HIGH (deselected) 23 | the ESP8266 WILL FAIL to boot! 24 | 25 | original sketch for WiFi library created 13 July 2010 26 | by dlf (Metodo2 srl) 27 | modified 31 May 2012 28 | by Tom Igoe 29 | 30 | modified for WiFiSpi library 14 Mar 2017 31 | by Jiri Bilek 32 | */ 33 | 34 | 35 | #include 36 | 37 | // WiFi credentials 38 | char ssid[] = "yourNetwork"; // your network SSID (name) 39 | char pass[] = "secretPassword"; // your network password (use for WPA) 40 | 41 | // if you don't want to use DNS (and reduce your sketch size) 42 | // use the numeric IP instead of the name for the server: 43 | //IPAddress server(93,184,216,34); // numeric IP for www.example.com (no DNS) 44 | char server[] = "www.example.com"; // name address using DNS 45 | 46 | // Initialize the Ethernet client library 47 | // with the IP address and port of the server 48 | // that you want to connect to (port 80 is default for HTTP): 49 | WiFiSpiClient client; 50 | 51 | void setup() { 52 | //Initialize serial and wait for port to open: 53 | Serial.begin(9600); 54 | while (!Serial) { 55 | ; // wait for serial port to connect. Needed for native USB port only 56 | } 57 | 58 | // Initialize the WifiSpi library 59 | WiFiSpi.init(); 60 | 61 | // check for the presence of the shield: 62 | if (WiFiSpi.status() == WL_NO_SHIELD) { 63 | Serial.println("WiFi shield not present"); 64 | // don't continue: 65 | while (true); 66 | } 67 | 68 | if (!WiFiSpi.checkProtocolVersion()) { 69 | Serial.println("Protocol version mismatch. Please upgrade the firmware"); 70 | // don't continue: 71 | while (true); 72 | } 73 | 74 | // attempt to connect to Wifi network: 75 | int status; 76 | 77 | do { 78 | Serial.print("Attempting to connect to SSID: "); 79 | Serial.println(ssid); 80 | // Connect to WPA/WPA2 network. Change this line if using open network: 81 | status = WiFiSpi.begin(ssid, pass); 82 | } while (status != WL_CONNECTED); 83 | 84 | Serial.println("Connected to wifi"); 85 | printWifiStatus(); 86 | 87 | // Set the server certificate SHA-1 fingerprint 88 | // Please check the correctness of the fingerprint - this certificate expires on 12-26-2021 89 | uint8_t fingerprint[] = {0x0A,0x28,0xA6,0xEB,0x17,0x6E,0xA9,0xCC,0x59,0x6F, 90 | 0x4C,0x73,0xFD,0x89,0x7E,0xFB,0xD3,0x2D,0xCA,0x2A}; 91 | WiFiSpi.setSSLFingerprint(fingerprint); 92 | 93 | Serial.println("\nStarting connection to server..."); 94 | // if you get a connection, report back via serial: 95 | if (client.connectSSL(server, 443)) { 96 | Serial.println("connected to server"); 97 | 98 | // Make a HTTP request: 99 | // Note: client.print() is transmitting one char per a message that is awfully wasting the SPI bus bandwidth 100 | // client.write(char*) is optimized and has minimum overhead 101 | client.write("GET / HTTP/1.1\r\n" 102 | "Host: www.example.com\r\n" 103 | "Connection: close\r\n\r\n"); 104 | } 105 | } 106 | 107 | void loop() { 108 | // if there are incoming bytes available 109 | // from the server, read them and print them: 110 | while (client.available()) { 111 | char c = client.read(); 112 | Serial.write(c); 113 | } 114 | 115 | // if the server's disconnected, stop the client: 116 | if (!client.connected()) { 117 | Serial.println(); 118 | Serial.println("disconnecting from server."); 119 | client.stop(); 120 | 121 | // do nothing forevermore: 122 | while (true); 123 | } 124 | } 125 | 126 | 127 | void printWifiStatus() { 128 | // print the SSID of the network you're attached to: 129 | Serial.print("SSID: "); 130 | Serial.println(WiFiSpi.SSID()); 131 | 132 | // print your WiFi shield's IP address: 133 | IPAddress ip = WiFiSpi.localIP(); 134 | Serial.print("IP Address: "); 135 | Serial.println(ip); 136 | 137 | // print the received signal strength: 138 | long rssi = WiFiSpi.RSSI(); 139 | Serial.print("signal strength (RSSI):"); 140 | Serial.print(rssi); 141 | Serial.println(" dBm"); 142 | } 143 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For WiFiSpi 3 | ####################################### 4 | 5 | ####################################### 6 | # Library (KEYWORD3) 7 | ####################################### 8 | 9 | 10 | ####################################### 11 | # Datatypes (KEYWORD1) 12 | ####################################### 13 | 14 | WiFiSpi KEYWORD1 15 | WiFiSpiClient KEYWORD1 16 | WiFiSpiServer KEYWORD1 17 | WiFiSpiUDP KEYWORD1 18 | 19 | ####################################### 20 | # Methods and Functions (KEYWORD2) 21 | ####################################### 22 | 23 | firmwareVersion KEYWORD2 24 | status KEYWORD2 25 | connect KEYWORD2 26 | write KEYWORD2 27 | available KEYWORD2 28 | config KEYWORD2 29 | setDNS KEYWORD2 30 | read KEYWORD2 31 | flush KEYWORD2 32 | stop KEYWORD2 33 | connected KEYWORD2 34 | begin KEYWORD2 35 | disconnect KEYWORD2 36 | macAddress KEYWORD2 37 | localIP KEYWORD2 38 | subnetMask KEYWORD2 39 | gatewayIP KEYWORD2 40 | scanNetworks KEYWORD2 41 | SSID KEYWORD2 42 | BSSID KEYWORD2 43 | RSSI KEYWORD2 44 | encryptionType KEYWORD2 45 | getResult KEYWORD2 46 | getSocket KEYWORD2 47 | beginPacket KEYWORD2 48 | endPacket KEYWORD2 49 | parsePacket KEYWORD2 50 | remoteIP KEYWORD2 51 | remotePort KEYWORD2 52 | softReset KEYWORD2 53 | hardReset KEYWORD2 54 | protocolVersion KEYWORD2 55 | masterProtocolVersion KEYWORD2 56 | checkProtocolVersion KEYWORD2 57 | 58 | 59 | ####################################### 60 | # Constants (LITERAL1) 61 | ####################################### 62 | 63 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=WiFiSpi 2 | version=0.3.0 3 | author=JiriBilek 4 | maintainer=Jiri Bilek 5 | sentence=Arduino WiFi library connecting ESP8266 via SPI protocol 6 | paragraph=Arduino WiFi library for connecting with ESP8266. Uses SPI protocol for communication. 7 | category=Communication 8 | url=https://github.com/JiriBilek/WiFiSpi 9 | architectures=avr,STM32F1,stm32 -------------------------------------------------------------------------------- /src/WiFiSpi.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WiFiSPI.cpp - Library for Arduino SPI connection to ESP8266 3 | Copyright (c) 2017 Jiri Bilek. All rights reserved. 4 | 5 | ----- 6 | 7 | Based on WiFi.cpp - Library for Arduino Wifi shield. 8 | Copyright (c) 2011-2014 Arduino LLC. All right reserved. 9 | 10 | This library is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU Lesser General Public 12 | License as published by the Free Software Foundation; either 13 | version 2.1 of the License, or (at your option) any later version. 14 | 15 | This library is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with this library; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 | */ 24 | 25 | #include "WiFiSpi.h" 26 | #include "utility/wifispi_drv.h" 27 | #include "utility/espspi_proxy.h" 28 | 29 | extern "C" { 30 | #include "utility/wl_definitions.h" 31 | #include "utility/wl_types.h" 32 | /// #include "utility/debug.h" 33 | } 34 | 35 | // Protocol version 36 | const char *WiFiSpiClass::protocolVer = "0.3.0"; 37 | 38 | // Hardware reset pin 39 | int8_t WiFiSpiClass::hwResetPin = -1; 40 | 41 | // No assumptions about the value of MAX_SOCK_NUM 42 | int16_t WiFiSpiClass::_state[MAX_SOCK_NUM]; 43 | uint16_t WiFiSpiClass::_server_port[MAX_SOCK_NUM]; 44 | 45 | WiFiSpiClass::WiFiSpiClass() 46 | { 47 | } 48 | 49 | void WiFiSpiClass::init(int8_t pin, uint32_t max_speed, SPIClass *in_spi, int8_t hwResetPin) 50 | { 51 | // Initialize the connection arrays 52 | for (uint8_t i = 0; i < MAX_SOCK_NUM; ++i) 53 | { 54 | _state[i] = NA_STATE; 55 | _server_port[i] = 0; 56 | } 57 | 58 | if (pin < 0) 59 | pin = SS; 60 | 61 | WiFiSpiDrv::wifiDriverInit(pin, max_speed, in_spi); 62 | 63 | WiFiSpiClass::hwResetPin = hwResetPin; 64 | hardReset(); 65 | } 66 | 67 | uint8_t WiFiSpiClass::getSocket() 68 | { 69 | for (uint8_t i = 0; i < MAX_SOCK_NUM; ++i) 70 | { 71 | if (WiFiSpiClass::_state[i] == NA_STATE) // _state is for both server and client 72 | return i; 73 | } 74 | return SOCK_NOT_AVAIL; 75 | } 76 | 77 | /* 78 | * 79 | */ 80 | const char* WiFiSpiClass::firmwareVersion() 81 | { 82 | return WiFiSpiDrv::getFwVersion(); 83 | } 84 | 85 | /* 86 | * 87 | */ 88 | uint8_t WiFiSpiClass::begin(const char* ssid) 89 | { 90 | uint8_t status = WL_IDLE_STATUS; 91 | uint8_t attempts = WL_MAX_ATTEMPT_CONNECTION; 92 | 93 | if (WiFiSpiDrv::wifiSetNetwork(ssid, strlen(ssid)) != WL_FAILURE) 94 | { 95 | do 96 | { 97 | delay(WL_DELAY_START_CONNECTION); 98 | status = WiFiSpiDrv::getConnectionStatus(); 99 | } 100 | while (((status == WL_IDLE_STATUS) || (status == WL_SCAN_COMPLETED) || (status == WL_DISCONNECTED)) && (--attempts > 0)); 101 | } else 102 | status = WL_CONNECT_FAILED; 103 | 104 | return status; 105 | } 106 | 107 | /* 108 | * 109 | */ 110 | uint8_t WiFiSpiClass::begin(const char* ssid, const char *passphrase) 111 | { 112 | uint8_t status = WL_IDLE_STATUS; 113 | uint8_t attempts = WL_MAX_ATTEMPT_CONNECTION; 114 | 115 | // SSID and passphrase for WPA connection 116 | if (WiFiSpiDrv::wifiSetPassphrase(ssid, strlen(ssid), passphrase, strlen(passphrase)) != WL_FAILURE) 117 | { 118 | do 119 | { 120 | delay(WL_DELAY_START_CONNECTION); 121 | status = WiFiSpiDrv::getConnectionStatus(); 122 | } 123 | while (((status == WL_IDLE_STATUS) || (status == WL_SCAN_COMPLETED) || (status == WL_DISCONNECTED)) && (--attempts > 0)); 124 | } else 125 | status = WL_CONNECT_FAILED; 126 | 127 | return status; 128 | } 129 | 130 | /* 131 | * 132 | */ 133 | bool WiFiSpiClass::config(IPAddress local_ip) 134 | { 135 | return WiFiSpiDrv::config((uint32_t)local_ip, 0, 0, 0, 0); 136 | } 137 | 138 | /* 139 | * 140 | */ 141 | bool WiFiSpiClass::config(IPAddress local_ip, IPAddress dns_server) 142 | { 143 | return WiFiSpiDrv::config((uint32_t)local_ip, 0, 0, (uint32_t)dns_server, 0); 144 | } 145 | 146 | /* 147 | * 148 | */ 149 | bool WiFiSpiClass::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway) 150 | { 151 | return WiFiSpiDrv::config((uint32_t)local_ip, (uint32_t)gateway, 0, (uint32_t)dns_server, 0); 152 | } 153 | 154 | /* 155 | * 156 | */ 157 | bool WiFiSpiClass::config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) 158 | { 159 | return WiFiSpiDrv::config((uint32_t)local_ip, (uint32_t)gateway, (uint32_t)subnet, (uint32_t)dns_server, 0); 160 | } 161 | 162 | /* 163 | * 164 | */ 165 | bool WiFiSpiClass::setDNS(IPAddress dns_server1) 166 | { 167 | return WiFiSpiDrv::config(0, 0, 0, (uint32_t)dns_server1, 0); 168 | } 169 | 170 | /* 171 | * 172 | */ 173 | bool WiFiSpiClass::setDNS(IPAddress dns_server1, IPAddress dns_server2) 174 | { 175 | return WiFiSpiDrv::config(0, 0, 0, (uint32_t)dns_server1, (uint32_t)dns_server2); 176 | } 177 | 178 | /* 179 | * 180 | */ 181 | int WiFiSpiClass::disconnect() 182 | { 183 | return WiFiSpiDrv::disconnect(); 184 | } 185 | 186 | /* 187 | * 188 | */ 189 | uint8_t* WiFiSpiClass::macAddress(uint8_t* mac) 190 | { 191 | uint8_t* _mac = WiFiSpiDrv::getMacAddress(); 192 | memcpy(mac, _mac, WL_MAC_ADDR_LENGTH); 193 | return mac; 194 | } 195 | 196 | /* 197 | * 198 | */ 199 | IPAddress WiFiSpiClass::localIP() 200 | { 201 | IPAddress ret; 202 | WiFiSpiDrv::getIpAddress(ret); 203 | return ret; 204 | } 205 | 206 | /* 207 | * 208 | */ 209 | IPAddress WiFiSpiClass::subnetMask() 210 | { 211 | IPAddress ret; 212 | WiFiSpiDrv::getSubnetMask(ret); 213 | return ret; 214 | } 215 | 216 | /* 217 | * 218 | */ 219 | IPAddress WiFiSpiClass::gatewayIP() 220 | { 221 | IPAddress ret; 222 | WiFiSpiDrv::getGatewayIP(ret); 223 | return ret; 224 | } 225 | 226 | /* 227 | * 228 | */ 229 | char* WiFiSpiClass::SSID() 230 | { 231 | return WiFiSpiDrv::getCurrentSSID(); 232 | } 233 | 234 | /* 235 | * 236 | */ 237 | uint8_t* WiFiSpiClass::BSSID() 238 | { 239 | return WiFiSpiDrv::getCurrentBSSID(); 240 | } 241 | 242 | /* 243 | * 244 | */ 245 | int32_t WiFiSpiClass::RSSI() 246 | { 247 | return WiFiSpiDrv::getCurrentRSSI(); 248 | } 249 | 250 | /*///uint8_t WiFiSpiClass::encryptionType() 251 | { 252 | return WiFiSpiDrv::getCurrentEncryptionType(); 253 | }*/ 254 | 255 | /* 256 | * 257 | */ 258 | int8_t WiFiSpiClass::scanNetworks() 259 | { 260 | #define WIFI_SCAN_RUNNING (-1) 261 | #define WIFI_SCAN_FAILED (-2) 262 | 263 | uint8_t attempts = 10; 264 | int8_t numOfNetworks = 0; 265 | 266 | if (WiFiSpiDrv::startScanNetworks() == WIFI_SCAN_FAILED) 267 | return WL_FAILURE; 268 | 269 | do 270 | { 271 | delay(2000); 272 | numOfNetworks = WiFiSpiDrv::getScanNetworks(); 273 | 274 | if (numOfNetworks == WIFI_SCAN_FAILED) 275 | return WL_FAILURE; 276 | } 277 | while ((numOfNetworks == WIFI_SCAN_RUNNING) && (--attempts > 0)); 278 | 279 | return numOfNetworks; 280 | } 281 | 282 | /* 283 | * 284 | */ 285 | char* WiFiSpiClass::SSID(uint8_t networkItem) 286 | { 287 | return WiFiSpiDrv::getSSIDNetworks(networkItem); 288 | } 289 | 290 | /* 291 | * 292 | */ 293 | int32_t WiFiSpiClass::RSSI(uint8_t networkItem) 294 | { 295 | return WiFiSpiDrv::getRSSINetworks(networkItem); 296 | } 297 | 298 | /* 299 | * 300 | */ 301 | uint8_t WiFiSpiClass::encryptionType(uint8_t networkItem) 302 | { 303 | return WiFiSpiDrv::getEncTypeNetworks(networkItem); 304 | } 305 | 306 | /* 307 | * 308 | */ 309 | uint8_t WiFiSpiClass::status() 310 | { 311 | return WiFiSpiDrv::getConnectionStatus(); 312 | } 313 | 314 | /* 315 | * 316 | */ 317 | int8_t WiFiSpiClass::hostByName(const char* aHostname, IPAddress& aResult) 318 | { 319 | return WiFiSpiDrv::getHostByName(aHostname, aResult); 320 | } 321 | 322 | /* 323 | * Perform remote software reset of the ESP8266 module. 324 | * The reset succeedes only if the SPI communication is not broken. 325 | * The function does not wait for the ESP8266. 326 | */ 327 | void WiFiSpiClass::softReset(void) { 328 | WiFiSpiDrv::softReset(); 329 | } 330 | 331 | /* 332 | * 333 | */ 334 | const char* WiFiSpiClass::protocolVersion() 335 | { 336 | return WiFiSpiDrv::getProtocolVersion(); 337 | } 338 | 339 | /* 340 | * 341 | */ 342 | const char* WiFiSpiClass::masterProtocolVersion() 343 | { 344 | return protocolVer; 345 | } 346 | 347 | /* 348 | * 349 | */ 350 | uint8_t WiFiSpiClass::checkProtocolVersion() 351 | { 352 | const char* s = WiFiSpiDrv::getProtocolVersion(); 353 | for (const char* p = protocolVer; *p; ++p, ++s) 354 | if (*p != *s) 355 | return 0; 356 | 357 | return (*s == 0); 358 | } 359 | 360 | /* 361 | * 362 | */ 363 | void WiFiSpiClass::hardReset(void) 364 | { 365 | if (hwResetPin <= 0) 366 | return; // no reset pin 367 | 368 | pinMode(hwResetPin, OUTPUT); 369 | 370 | espSpiProxy.hardReset(hwResetPin); 371 | } 372 | 373 | /* 374 | * 375 | */ 376 | 377 | uint8_t WiFiSpiClass::setSSLFingerprint(uint8_t* fingerprint) 378 | { 379 | return WiFiSpiDrv::setSSLFingerprint(fingerprint); 380 | } 381 | 382 | 383 | WiFiSpiClass WiFiSpi; 384 | -------------------------------------------------------------------------------- /src/WiFiSpi.h: -------------------------------------------------------------------------------- 1 | /* 2 | WiFiSPI.h - Library for Arduino SPI connection to ESP8266 3 | Copyright (c) 2017 Jiri Bilek. All rights reserved. 4 | 5 | Circuit: 6 | 1. On ESP8266 must be running (flashed) WiFiSPIESP application. 7 | 8 | 2. Connect the Arduino to the following pins on the esp8266: 9 | 10 | ESP8266 | 11 | GPIO NodeMCU Name | Uno 12 | =================================== 13 | 15 D8 SS | D10 14 | 13 D7 MOSI | D11 15 | 12 D6 MISO | D12 16 | 14 D5 SCK | D13 17 | 18 | Note: If the ESP is booting at a moment when the SPI Master (i.e. Arduino) has the Select line HIGH (deselected) 19 | the ESP8266 WILL FAIL to boot! 20 | 21 | ----- 22 | 23 | Based on WiFi.h - Library for Arduino Wifi shield. 24 | Copyright (c) 2011-2014 Arduino LLC. All right reserved. 25 | 26 | This library is free software; you can redistribute it and/or 27 | modify it under the terms of the GNU Lesser General Public 28 | License as published by the Free Software Foundation; either 29 | version 2.1 of the License, or (at your option) any later version. 30 | 31 | This library is distributed in the hope that it will be useful, 32 | but WITHOUT ANY WARRANTY; without even the implied warranty of 33 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 34 | Lesser General Public License for more details. 35 | 36 | You should have received a copy of the GNU Lesser General Public 37 | License along with this library; if not, write to the Free Software 38 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 39 | */ 40 | 41 | #ifndef _WIFISPI_H_INCLUDED 42 | #define _WIFISPI_H_INCLUDED 43 | 44 | #include 45 | #include 46 | 47 | extern "C" { 48 | #include "utility/wl_definitions.h" 49 | #include "utility/wl_types.h" 50 | } 51 | 52 | #include "utility/wifi_spi.h" 53 | #include "IPAddress.h" 54 | 55 | #include "WiFiSpiClient.h" 56 | #include "WiFiSpiServer.h" 57 | #include "WiFiSpiUdp.h" 58 | 59 | 60 | class WiFiSpiClass 61 | { 62 | public: 63 | /* 64 | * Initialization of the library. 65 | * 66 | * param pin: SS pin, default value get default pin 67 | * param max_speed: maximum speed of SPI interface 68 | * param in_spi: pointer to SPI Class 69 | * param hwResetPin: number of the PIN connected to ESP's RESET or -1 70 | */ 71 | static void init(int8_t pin = -1, uint32_t max_speed = 0, SPIClass *in_spi = &SPI, int8_t hwResetPin = -1); 72 | 73 | private: 74 | static int16_t _state[MAX_SOCK_NUM]; 75 | static uint16_t _server_port[MAX_SOCK_NUM]; 76 | 77 | static int8_t hwResetPin; 78 | 79 | static const char *protocolVer; 80 | 81 | public: 82 | WiFiSpiClass(); 83 | 84 | /* 85 | * Get the first socket available 86 | */ 87 | static uint8_t getSocket(); 88 | 89 | /* 90 | * Get firmware version 91 | */ 92 | static const char* firmwareVersion(); 93 | 94 | 95 | /* Start Wifi connection for OPEN networks 96 | * 97 | * param ssid: Pointer to the SSID string. 98 | */ 99 | uint8_t begin(const char* ssid); 100 | 101 | /* Start Wifi connection with WEP encryption. 102 | * Configure a key into the device. The key type (WEP-40, WEP-104) 103 | * is determined by the size of the key (5 bytes for WEP-40, 13 bytes for WEP-104). 104 | * 105 | * param ssid: Pointer to the SSID string. 106 | * param key_idx: The key index to set. Valid values are 0-3. 107 | * param key: Key input buffer. 108 | */ 109 | /// uint8_t begin(const char* ssid, uint8_t key_idx, const char* key); 110 | 111 | /* Start Wifi connection with passphrase 112 | * the most secure supported mode will be automatically selected 113 | * 114 | * param ssid: Pointer to the SSID string. 115 | * param passphrase: Passphrase. Valid characters in a passphrase 116 | * must be between ASCII 32-126 (decimal). 117 | */ 118 | uint8_t begin(const char* ssid, const char *passphrase); 119 | 120 | /* Change Ip configuration settings disabling the dhcp client 121 | * 122 | * param local_ip: Static ip configuration 123 | */ 124 | bool config(IPAddress local_ip); 125 | 126 | /* Change Ip configuration settings disabling the dhcp client 127 | * 128 | * param local_ip: Static ip configuration 129 | * param dns_server: IP configuration for DNS server 1 130 | */ 131 | bool config(IPAddress local_ip, IPAddress dns_server); 132 | 133 | /* Change Ip configuration settings disabling the dhcp client 134 | * 135 | * param local_ip: Static ip configuration 136 | * param dns_server: IP configuration for DNS server 1 137 | * param gateway : Static gateway configuration 138 | */ 139 | bool config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway); 140 | 141 | /* Change Ip configuration settings disabling the dhcp client 142 | * 143 | * param local_ip: Static ip configuration 144 | * param dns_server: IP configuration for DNS server 1 145 | * param gateway: Static gateway configuration 146 | * param subnet: Static Subnet mask 147 | */ 148 | bool config(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); 149 | 150 | /* Change DNS Ip configuration 151 | * 152 | * param dns_server1: ip configuration for DNS server 1 153 | */ 154 | bool setDNS(IPAddress dns_server1); 155 | 156 | /* Change DNS Ip configuration 157 | * 158 | * param dns_server1: ip configuration for DNS server 1 159 | * param dns_server2: ip configuration for DNS server 2 160 | * 161 | */ 162 | bool setDNS(IPAddress dns_server1, IPAddress dns_server2); 163 | 164 | /* 165 | * Disconnect from the network 166 | * 167 | * return: one value of wl_status_t enum 168 | */ 169 | int disconnect(void); 170 | 171 | /* 172 | * Get the interface MAC address. 173 | * 174 | * return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH 175 | */ 176 | uint8_t* macAddress(uint8_t* mac); 177 | 178 | /* 179 | * Get the interface IP address. 180 | * 181 | * return: Ip address value 182 | */ 183 | IPAddress localIP(); 184 | 185 | /* 186 | * Get the interface subnet mask address. 187 | * 188 | * return: subnet mask address value 189 | */ 190 | IPAddress subnetMask(); 191 | 192 | /* 193 | * Get the gateway ip address. 194 | * 195 | * return: gateway ip address value 196 | */ 197 | IPAddress gatewayIP(); 198 | 199 | /* 200 | * Return the current SSID associated with the network 201 | * 202 | * return: ssid string 203 | */ 204 | char* SSID(); 205 | 206 | /* 207 | * Return the current BSSID associated with the network. 208 | * It is the MAC address of the Access Point 209 | * 210 | * return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH 211 | */ 212 | uint8_t* BSSID(); 213 | 214 | /* 215 | * Return the current RSSI /Received Signal Strength in dBm) 216 | * associated with the network 217 | * 218 | * return: signed value 219 | */ 220 | int32_t RSSI(); 221 | 222 | /* 223 | * Return the Encryption Type associated with the network 224 | * 225 | * return: one value of wl_enc_type enum 226 | */ 227 | ///uint8_t encryptionType(); 228 | 229 | /* 230 | * Start scan WiFi networks available 231 | * 232 | * return: Number of discovered networks 233 | */ 234 | int8_t scanNetworks(); 235 | 236 | /* 237 | * Return the SSID discovered during the network scan. 238 | * 239 | * param networkItem: specify from which network item want to get the information 240 | * 241 | * return: ssid string of the specified item on the networks scanned list 242 | */ 243 | char* SSID(uint8_t networkItem); 244 | 245 | /* 246 | * Return the encryption type of the networks discovered during the scanNetworks 247 | * 248 | * param networkItem: specify from which network item want to get the information 249 | * 250 | * return: encryption type (enum wl_enc_type) of the specified item on the networks scanned list 251 | */ 252 | uint8_t encryptionType(uint8_t networkItem); 253 | 254 | /* 255 | * Return the RSSI of the networks discovered during the scanNetworks 256 | * 257 | * param networkItem: specify from which network item want to get the information 258 | * 259 | * return: signed value of RSSI of the specified item on the networks scanned list 260 | */ 261 | int32_t RSSI(uint8_t networkItem); 262 | 263 | /* 264 | * Return Connection status. 265 | * 266 | * return: one of the value defined in wl_status_t 267 | */ 268 | uint8_t status(); 269 | 270 | /* 271 | * Resolve the given hostname to an IP address. 272 | * param aHostname: Name to be resolved 273 | * param aResult: IPAddress structure to store the returned IP address 274 | * result: 1 if aIPAddrString was successfully converted to an IP address, 275 | * else error code 276 | */ 277 | int8_t hostByName(const char* aHostname, IPAddress& aResult); 278 | 279 | /* 280 | * Perform software reset of the ESP8266 module. 281 | * The reset succeedes only if the SPI communication is not broken. 282 | * After the reset wait for the ESP8266 to came to life again. Typically, the ESP8266 boots within 100 ms, 283 | * but with the WifiManager installed on ESP it can be a couple of seconds. 284 | */ 285 | static void softReset(void); 286 | 287 | /* 288 | * Perform hardware reset of the ESP8266 module. The PIN connected to ESP's reset must be declared in init() 289 | * After the reset wait for the ESP8266 to came to life again. Typically, the ESP8266 boots within 100 ms, 290 | * but with the WifiManager installed on ESP it can be a couple of seconds. 291 | * This function waits for 200 ms. 292 | */ 293 | static void hardReset(void); 294 | 295 | /* 296 | * Get slave protocol version 297 | */ 298 | static const char* protocolVersion(); 299 | 300 | /* 301 | * Get master protocol version 302 | */ 303 | static const char* masterProtocolVersion(); 304 | 305 | /* 306 | * Check protocol version 307 | * result: 1 if protocol version of both master and slave match 308 | * 0 otherwise 309 | */ 310 | static uint8_t checkProtocolVersion(); 311 | 312 | /* 313 | */ 314 | static uint8_t setSSLFingerprint(uint8_t* fingerprint); 315 | 316 | /* 317 | * The following classes need r/w access to private arrays 318 | */ 319 | friend class WiFiSpiClient; 320 | friend class WiFiSpiServer; 321 | friend class WiFiSpiUdp; 322 | }; 323 | 324 | extern WiFiSpiClass WiFiSpi; 325 | 326 | #endif 327 | -------------------------------------------------------------------------------- /src/WiFiSpiClient.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WiFiSpiClient.cpp - Library for Arduino SPI connection to ESP8266 3 | Copyright (c) 2017 Jiri Bilek. All rights reserved. 4 | 5 | ----- 6 | 7 | Based on WiFiClient.cpp - Library for Arduino Wifi shield. 8 | Copyright (c) 2011-2014 Arduino LLC. All right reserved. 9 | 10 | This library is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU Lesser General Public 12 | License as published by the Free Software Foundation; either 13 | version 2.1 of the License, or (at your option) any later version. 14 | 15 | This library is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with this library; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 | */ 24 | 25 | extern "C" { 26 | #include "utility/wl_definitions.h" 27 | #include "utility/wl_types.h" 28 | #include 29 | #include "utility/debug.h" 30 | } 31 | 32 | #include "WiFiSpi.h" 33 | #include "WiFiSpiClient.h" 34 | #include "utility/wifi_spi.h" 35 | #include "utility/srvspi_drv.h" 36 | #include "utility/wifispi_drv.h" 37 | 38 | WiFiSpiClient::WiFiSpiClient() : _sock(SOCK_NOT_AVAIL) { 39 | } 40 | 41 | WiFiSpiClient::WiFiSpiClient(uint8_t sock) : _sock(sock) { 42 | } 43 | 44 | /* 45 | * 46 | */ 47 | int WiFiSpiClient::connect(const char* host, uint16_t port) 48 | { 49 | IPAddress remote_addr; 50 | if (WiFiSpi.hostByName(host, remote_addr)) 51 | { 52 | return _connect(remote_addr, port, false); 53 | } 54 | return 0; 55 | } 56 | 57 | /* 58 | * 59 | */ 60 | int WiFiSpiClient::connect(IPAddress ip, uint16_t port) 61 | { 62 | return _connect(ip, port, false); 63 | } 64 | 65 | /* 66 | * 67 | */ 68 | int WiFiSpiClient::connectSSL(const char* host, uint16_t port) 69 | { 70 | IPAddress remote_addr; 71 | if (WiFiSpi.hostByName(host, remote_addr)) 72 | { 73 | return _connect(remote_addr, port, true); 74 | } 75 | return 0; 76 | } 77 | 78 | /* 79 | * 80 | */ 81 | int WiFiSpiClient::connectSSL(IPAddress ip, uint16_t port) 82 | { 83 | return _connect(ip, port, true); 84 | } 85 | 86 | /* 87 | * 88 | */ 89 | int WiFiSpiClient::_connect(IPAddress ip, uint16_t port, bool isSSL) 90 | { 91 | _sock = WiFiSpiClass::getSocket(); 92 | if (_sock != SOCK_NOT_AVAIL) 93 | { 94 | if (! ServerSpiDrv::startClient(uint32_t(ip), port, _sock, (isSSL ? TCP_MODE_WITH_TLS : TCP_MODE))) 95 | return 0; // unsuccessfull 96 | 97 | WiFiSpiClass::_state[_sock] = _sock; 98 | } 99 | else 100 | { 101 | Serial.println("No Socket available"); 102 | return 0; 103 | } 104 | return 1; 105 | } 106 | 107 | /* 108 | * 109 | */ 110 | size_t WiFiSpiClient::write(const uint8_t *buf, size_t size) 111 | { 112 | if (_sock >= MAX_SOCK_NUM || size == 0) 113 | { 114 | setWriteError(); 115 | return 0; 116 | } 117 | 118 | if (!ServerSpiDrv::sendData(_sock, buf, size)) 119 | { 120 | setWriteError(); 121 | return 0; 122 | } 123 | 124 | return size; 125 | } 126 | 127 | /* 128 | * 129 | */ 130 | int WiFiSpiClient::available() 131 | { 132 | if (_sock == SOCK_NOT_AVAIL) 133 | return 0; 134 | else 135 | return ServerSpiDrv::availData(_sock); 136 | } 137 | 138 | /* 139 | * 140 | */ 141 | int WiFiSpiClient::read() 142 | { 143 | int16_t b; 144 | ServerSpiDrv::getData(_sock, &b); // returns -1 when error 145 | return b; 146 | } 147 | 148 | /* 149 | Reads data into a buffer. 150 | Return: 0 = success, size bytes read 151 | -1 = error (either no data or communication error) 152 | */ 153 | int WiFiSpiClient::read(uint8_t* buf, size_t size) { 154 | // sizeof(size_t) is architecture dependent 155 | // but we need a 16 bit data type here 156 | uint16_t _size = size; 157 | if (!ServerSpiDrv::getDataBuf(_sock, buf, &_size)) 158 | return -1; 159 | return 0; 160 | } 161 | 162 | /* 163 | * 164 | */ 165 | int WiFiSpiClient::peek() 166 | { 167 | int16_t b; 168 | ServerSpiDrv::getData(_sock, &b, 1); // returns -1 when error 169 | return b; 170 | } 171 | 172 | /* 173 | * 174 | */ 175 | void WiFiSpiClient::flush() { 176 | // TODO: a real check to ensure transmission has been completed 177 | } 178 | 179 | /* 180 | * 181 | */ 182 | void WiFiSpiClient::stop() { 183 | if (_sock == SOCK_NOT_AVAIL) 184 | return; 185 | 186 | ServerSpiDrv::stopClient(_sock); 187 | 188 | int count = 0; 189 | // wait maximum 5 secs for the connection to close 190 | while (status() != CLOSED && ++count < 500) 191 | delay(10); 192 | 193 | if (WiFiSpiClass::_server_port[_sock] == 0) 194 | WiFiSpiClass::_state[_sock] = NA_STATE; // Close only if it isn't server connection 195 | 196 | _sock = SOCK_NOT_AVAIL; 197 | } 198 | 199 | /* 200 | * 201 | */ 202 | uint8_t WiFiSpiClient::connected() 203 | { 204 | if (_sock == SOCK_NOT_AVAIL) 205 | return 0; 206 | else 207 | return (status() == ESTABLISHED); 208 | } 209 | 210 | /* 211 | * 212 | */ 213 | uint8_t WiFiSpiClient::status() 214 | { 215 | if (_sock == SOCK_NOT_AVAIL) 216 | return CLOSED; 217 | else 218 | return ServerSpiDrv::getClientState(_sock); 219 | } 220 | 221 | /* 222 | * 223 | */ 224 | WiFiSpiClient::operator bool() { 225 | return (_sock != SOCK_NOT_AVAIL); 226 | } 227 | 228 | /* 229 | * 230 | */ 231 | uint8_t WiFiSpiClient::verifySSL(uint8_t* fingerprint, const char *host) { 232 | if (_sock == SOCK_NOT_AVAIL || host[0] == 0) 233 | return 0; 234 | 235 | return ServerSpiDrv::verifySSLClient(_sock, fingerprint, host); 236 | } 237 | 238 | /* 239 | * 240 | */ 241 | IPAddress WiFiSpiClient::remoteIP() 242 | { 243 | uint8_t _remoteIp[4]; 244 | uint16_t _remotePort; 245 | 246 | if (WiFiSpiDrv::getRemoteData(_sock, _remoteIp, &_remotePort)) 247 | return IPAddress(_remoteIp); 248 | else 249 | return IPAddress(0UL); 250 | } 251 | 252 | /* 253 | * 254 | */ 255 | uint16_t WiFiSpiClient::remotePort() 256 | { 257 | uint8_t _remoteIp[4]; 258 | uint16_t _remotePort; 259 | 260 | if (WiFiSpiDrv::getRemoteData(_sock, _remoteIp, &_remotePort)) 261 | return _remotePort; 262 | else 263 | return 0; 264 | } 265 | -------------------------------------------------------------------------------- /src/WiFiSpiClient.h: -------------------------------------------------------------------------------- 1 | /* 2 | WiFiSpiClient.h - Library for Arduino with ESP8266 as slave. 3 | Copyright (c) 2017 Jiri Bilek. All right reserved. 4 | 5 | --- 6 | 7 | Based on WiFiClient.h - Library for Arduino Wifi shield. 8 | Copyright (c) 2011-2014 Arduino LLC. All right reserved. 9 | 10 | This library is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU Lesser General Public 12 | License as published by the Free Software Foundation; either 13 | version 2.1 of the License, or (at your option) any later version. 14 | 15 | This library is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with this library; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 | */ 24 | 25 | #ifndef _WIFISPICLIENT_H_INCLUDED 26 | #define _WIFISPICLIENT_H_INCLUDED 27 | 28 | #include "Arduino.h" 29 | #include "Print.h" 30 | #include "Client.h" 31 | #include "IPAddress.h" 32 | 33 | class WiFiSpiClient : public Client { 34 | 35 | private: 36 | uint8_t _sock; //not used 37 | 38 | public: 39 | WiFiSpiClient(); 40 | WiFiSpiClient(uint8_t sock); 41 | virtual ~WiFiSpiClient() {}; 42 | 43 | uint8_t status(); 44 | virtual int connect(IPAddress ip, uint16_t port); 45 | virtual int connect(const char *host, uint16_t port); 46 | virtual int connectSSL(IPAddress ip, uint16_t port); 47 | virtual int connectSSL(const char *host, uint16_t port); 48 | 49 | uint8_t verifySSL(uint8_t* fingerprint, const char *host); 50 | 51 | virtual size_t write(const uint8_t *buf, size_t size); 52 | virtual size_t write(uint8_t b) 53 | { return write(&b, 1); } 54 | virtual size_t write(const char *str) 55 | { return write(reinterpret_cast(str), strlen(str)); } 56 | virtual size_t write(const void *str, size_t size) 57 | { return write(reinterpret_cast(str), size); } 58 | virtual int available(); 59 | virtual int read(); 60 | virtual int read(uint8_t *buf, size_t size); 61 | virtual int peek(); 62 | virtual void flush(); 63 | virtual void stop(); 64 | virtual uint8_t connected(); 65 | virtual operator bool(); 66 | 67 | using Print::write; 68 | 69 | // Return the IP address of the host who sent the current incoming packet 70 | IPAddress remoteIP(); 71 | 72 | // Return the port of the host who sent the current incoming packet 73 | uint16_t remotePort(); 74 | 75 | private: 76 | int _connect(IPAddress ip, uint16_t port, bool isSSL); 77 | 78 | }; 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /src/WiFiSpiServer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WiFiSPIServer.cpp - Library for Arduino Wifi SPI connection with ESP8266. 3 | Copyright (c) 2017 Jiri Bilek. All right reserved. 4 | 5 | --- 6 | 7 | Based on WiFiServer.cpp - Library for Arduino Wifi shield. 8 | Copyright (c) 2011-2014 Arduino LLC. All right reserved. 9 | 10 | This library is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU Lesser General Public 12 | License as published by the Free Software Foundation; either 13 | version 2.1 of the License, or (at your option) any later version. 14 | 15 | This library is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with this library; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 | */ 24 | 25 | #include 26 | #include "utility/srvspi_drv.h" 27 | 28 | extern "C" { 29 | #include "utility/debug.h" 30 | } 31 | 32 | #include "WiFiSpi.h" 33 | #include "WiFiSpiClient.h" 34 | #include "WiFiSpiServer.h" 35 | 36 | WiFiSpiServer::WiFiSpiServer(uint16_t port) 37 | { 38 | _port = port; 39 | } 40 | 41 | /* 42 | * 43 | */ 44 | void WiFiSpiServer::begin() 45 | { 46 | uint8_t sock = WiFiSpiClass::getSocket(); 47 | 48 | if (sock != SOCK_NOT_AVAIL) 49 | { 50 | _sock = sock; 51 | ServerSpiDrv::startServer(_port, _sock); 52 | WiFiSpiClass::_server_port[_sock] = _port; 53 | WiFiSpiClass::_state[_sock] = _sock; 54 | } 55 | } 56 | 57 | /* 58 | * 59 | */ 60 | WiFiSpiClient WiFiSpiServer::available(uint8_t* status) 61 | { 62 | WiFiSpiClient client(_sock); 63 | 64 | uint8_t _client_status = client.status(); // creates Client object on ESP side if there is established connection 65 | // uint8_t _server_status = this->status(); removed, may be related with the comment below, running fine without it 66 | 67 | if (status != NULL) 68 | *status = _client_status; 69 | 70 | // TODO: If server is not in listen state, restart it (code present in original WiFiServer.h). I think it is useless. 71 | 72 | if (_client_status == ESTABLISHED) 73 | return client; 74 | 75 | return WiFiSpiClient(SOCK_NOT_AVAIL); // closed Client 76 | } 77 | 78 | /* 79 | * 80 | */ 81 | uint8_t WiFiSpiServer::status() { 82 | return ServerSpiDrv::getServerState(0); 83 | } 84 | 85 | /* 86 | * 87 | */ 88 | size_t WiFiSpiServer::write(uint8_t b) 89 | { 90 | return write(&b, 1); 91 | } 92 | 93 | /* 94 | * 95 | */ 96 | size_t WiFiSpiServer::write(const uint8_t *buffer, size_t size) 97 | { 98 | size_t n = 0; 99 | WiFiSpiClient client(_sock); 100 | 101 | if (client.status() == ESTABLISHED) 102 | n = client.write(buffer, size); 103 | 104 | return n; 105 | } 106 | 107 | /* 108 | * 109 | */ 110 | void WiFiSpiServer::stop() 111 | { 112 | ServerSpiDrv::stopServer(_sock); 113 | 114 | WiFiSpiClass::_server_port[_sock] = 0; 115 | WiFiSpiClass::_state[_sock] = NA_STATE; 116 | } 117 | 118 | -------------------------------------------------------------------------------- /src/WiFiSpiServer.h: -------------------------------------------------------------------------------- 1 | /* 2 | WiFiSPIServer.h - Library for Arduino Wifi SPI connection with ESP8266. 3 | Copyright (c) 2017 Jiri Bilek. All right reserved. 4 | 5 | --- 6 | 7 | Based on WiFiServer.h - Library for Arduino Wifi shield. 8 | Copyright (c) 2011-2014 Arduino LLC. All right reserved. 9 | 10 | This library is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU Lesser General Public 12 | License as published by the Free Software Foundation; either 13 | version 2.1 of the License, or (at your option) any later version. 14 | 15 | This library is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with this library; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 | */ 24 | 25 | #ifndef _WIFISPISERVER_H_INCLUDED 26 | #define _WIFISPISERVER_H_INCLUDED 27 | 28 | extern "C" { 29 | #include "utility/wl_definitions.h" 30 | } 31 | 32 | #include "Server.h" 33 | 34 | class WiFiSpiClient; 35 | 36 | class WiFiSpiServer : public Server { 37 | private: 38 | uint16_t _port; 39 | void* pcb; 40 | uint8_t _sock; 41 | 42 | public: 43 | WiFiSpiServer(uint16_t port); 44 | WiFiSpiClient available(uint8_t* status = NULL); 45 | 46 | void begin(); 47 | virtual size_t write(uint8_t); 48 | virtual size_t write(const uint8_t *buf, size_t size); 49 | uint8_t status(); 50 | 51 | void stop(); 52 | 53 | using Print::write; 54 | }; 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/WiFiSpiUdp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WiFiSPIUdp.cpp - Library for Arduino Wifi SPI connection with ESP8266. 3 | Copyright (c) 2017 Jiri Bilek. All right reserved. 4 | 5 | --- 6 | 7 | Based on WiFiUdp.cpp - Library for Arduino Wifi shield. 8 | Copyright (c) 2011-2014 Arduino LLC. All right reserved. 9 | 10 | This library is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU Lesser General Public 12 | License as published by the Free Software Foundation; either 13 | version 2.1 of the License, or (at your option) any later version. 14 | 15 | This library is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with this library; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 | */ 24 | 25 | extern "C" { 26 | #include "utility/debug.h" 27 | #include "utility/wifi_spi.h" 28 | } 29 | #include 30 | #include "utility/srvspi_drv.h" 31 | #include "utility/wifispi_drv.h" 32 | 33 | #include "WiFiSpi.h" 34 | #include "WiFiSpiUdp.h" 35 | 36 | 37 | /* Constructor */ 38 | WiFiSpiUdp::WiFiSpiUdp() : _sock(SOCK_NOT_AVAIL) {} 39 | 40 | /* 41 | * Starts WiFiSpiUdp socket, listening at local port PORT 42 | */ 43 | uint8_t WiFiSpiUdp::begin(uint16_t port) 44 | { 45 | uint8_t sock = WiFiSpiClass::getSocket(); 46 | if (sock != SOCK_NOT_AVAIL) 47 | { 48 | if (ServerSpiDrv::startServer(port, sock, UDP_MODE)) 49 | { 50 | WiFiSpiClass::_server_port[sock] = port; 51 | WiFiSpiClass::_state[sock] = sock; 52 | _sock = sock; 53 | _port = port; 54 | return 1; 55 | } 56 | } 57 | return 0; 58 | } 59 | 60 | /* 61 | * Starts WiFiSpiUdp socket, listening at port PORT for multicast messages from IP 62 | * Returns 1 if successful, 0 on failure 63 | */ 64 | uint8_t WiFiSpiUdp::beginMulticast(IPAddress ip, uint16_t port) 65 | { 66 | uint8_t sock = WiFiSpiClass::getSocket(); 67 | if (sock != SOCK_NOT_AVAIL) 68 | { 69 | if (ServerSpiDrv::startServerMulticast(uint32_t(ip), port, sock)) 70 | { 71 | WiFiSpiClass::_server_port[sock] = port; 72 | WiFiSpiClass::_state[sock] = sock; 73 | _sock = sock; 74 | _port = port; 75 | return 1; 76 | } 77 | } 78 | return 0; 79 | } 80 | 81 | /* 82 | * Returns number of bytes available in the current packet 83 | */ 84 | int WiFiSpiUdp::available() 85 | { 86 | if (_sock != SOCK_NOT_AVAIL) 87 | return ServerSpiDrv::availData(_sock); 88 | 89 | return 0; 90 | } 91 | 92 | /* 93 | * Releases any resources being used by this WiFiSpiUdp instance 94 | */ 95 | void WiFiSpiUdp::stop() 96 | { 97 | ServerSpiDrv::stopServer(_sock); 98 | 99 | WiFiSpiClass::_server_port[_sock] = 0; 100 | WiFiSpiClass::_state[_sock] = NA_STATE; 101 | } 102 | 103 | /* 104 | * 105 | */ 106 | int WiFiSpiUdp::beginPacket(const char *host, uint16_t port) 107 | { 108 | // Look up the host first 109 | IPAddress remote_addr; 110 | if (WiFiSpi.hostByName(host, remote_addr)) 111 | return beginPacket(remote_addr, port); 112 | else 113 | return 0; 114 | } 115 | 116 | /* 117 | * 118 | */ 119 | int WiFiSpiUdp::beginPacket(IPAddress ip, uint16_t port) 120 | { 121 | if (_sock == SOCK_NOT_AVAIL) 122 | return 0; // No socket available 123 | 124 | if (! ServerSpiDrv::beginUdpPacket(uint32_t(ip), port, _sock)) 125 | return 0; // Client not opened 126 | else 127 | return 1; 128 | } 129 | 130 | /* 131 | * 132 | */ 133 | int WiFiSpiUdp::endPacket() 134 | { 135 | return ServerSpiDrv::sendUdpData(_sock); 136 | } 137 | 138 | /* 139 | * 140 | */ 141 | size_t WiFiSpiUdp::write(uint8_t byte) 142 | { 143 | return write(&byte, 1); 144 | } 145 | 146 | /* 147 | * 148 | */ 149 | size_t WiFiSpiUdp::write(const uint8_t *buffer, size_t size) 150 | { 151 | if (ServerSpiDrv::insertDataBuf(_sock, buffer, size)) 152 | return size; 153 | else 154 | return 0; 155 | } 156 | 157 | /* 158 | * 159 | */ 160 | int WiFiSpiUdp::parsePacket() 161 | { 162 | return ServerSpiDrv::parsePacket(_sock); 163 | } 164 | 165 | /* 166 | * 167 | */ 168 | int WiFiSpiUdp::read() 169 | { 170 | int16_t b; 171 | ServerSpiDrv::getData(_sock, &b); // returns -1 when error 172 | return b; 173 | } 174 | 175 | /* 176 | * 177 | */ 178 | int WiFiSpiUdp::read(unsigned char* buffer, size_t len) 179 | { 180 | // sizeof(size_t) is architecture dependent 181 | // but we need a 16 bit data type here 182 | uint16_t _size = len; 183 | 184 | if (!ServerSpiDrv::getDataBuf(_sock, buffer, &_size)) 185 | return -1; 186 | else 187 | return 0; 188 | } 189 | 190 | /* 191 | * 192 | */ 193 | int WiFiSpiUdp::peek() 194 | { 195 | int16_t b; 196 | ServerSpiDrv::getData(_sock, &b, 1); // returns -1 when error 197 | return b; 198 | } 199 | 200 | /* 201 | * 202 | */ 203 | void WiFiSpiUdp::flush() 204 | { 205 | // TODO: a real check to ensure transmission has been completed 206 | } 207 | 208 | /* 209 | * 210 | */ 211 | IPAddress WiFiSpiUdp::remoteIP() 212 | { 213 | uint8_t _remoteIp[4]; 214 | uint16_t _remotePort; 215 | 216 | if (WiFiSpiDrv::getRemoteData(_sock, _remoteIp, &_remotePort)) 217 | return IPAddress(_remoteIp); 218 | else 219 | return IPAddress(0UL); 220 | } 221 | 222 | /* 223 | * 224 | */ 225 | uint16_t WiFiSpiUdp::remotePort() 226 | { 227 | uint8_t _remoteIp[4]; 228 | uint16_t _remotePort; 229 | 230 | if (WiFiSpiDrv::getRemoteData(_sock, _remoteIp, &_remotePort)) 231 | return _remotePort; 232 | else 233 | return 0; 234 | } 235 | 236 | -------------------------------------------------------------------------------- /src/WiFiSpiUdp.h: -------------------------------------------------------------------------------- 1 | /* 2 | WiFiSPIUdp.h - Library for Arduino Wifi SPI connection with ESP8266. 3 | Copyright (c) 2017 Jiri Bilek. All right reserved. 4 | 5 | --- 6 | 7 | Based on WiFiUdp.h - Library for Arduino Wifi shield. 8 | Copyright (c) 2011-2014 Arduino LLC. All right reserved. 9 | 10 | This library is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU Lesser General Public 12 | License as published by the Free Software Foundation; either 13 | version 2.1 of the License, or (at your option) any later version. 14 | 15 | This library is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with this library; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 | */ 24 | 25 | #ifndef _WIFISPIUDP_H_INCLUDED 26 | #define _WIFISPIUDP_H_INCLUDED 27 | 28 | #include 29 | 30 | #define UDP_TX_PACKET_MAX_SIZE 24 31 | 32 | class WiFiSpiUdp : public UDP { 33 | private: 34 | uint8_t _sock; // socket ID for Wiz5100 35 | uint16_t _port; // local port to listen on 36 | 37 | public: 38 | WiFiSpiUdp(); // Constructor 39 | virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use 40 | virtual uint8_t beginMulticast(IPAddress, uint16_t); // initialize, start listening on specified multicast IP address and port. Returns 1 if successful, 0 on failure 41 | virtual void stop(); // Finish with the UDP socket 42 | 43 | // Sending UDP packets 44 | 45 | // Start building up a packet to send to the remote host specific in ip and port 46 | // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port 47 | virtual int beginPacket(IPAddress ip, uint16_t port); 48 | 49 | // Start building up a packet to send to the remote host specific in host and port 50 | // Returns 1 if successful, 0 if there was a problem resolving the hostname or port 51 | virtual int beginPacket(const char *host, uint16_t port); 52 | 53 | // Finish off this packet and send it 54 | // Returns 1 if the packet was sent successfully, 0 if there was an error 55 | virtual int endPacket(); 56 | 57 | // Write a single byte into the packet 58 | virtual size_t write(uint8_t); 59 | 60 | // Write size bytes from buffer into the packet 61 | virtual size_t write(const uint8_t *buffer, size_t size); 62 | 63 | using Print::write; 64 | 65 | // Start processing the next available incoming packet 66 | // Discards current packet, if any is present! 67 | // Returns the size of the packet in bytes, or 0 if no packets are available 68 | virtual int parsePacket(); 69 | 70 | // Number of bytes remaining in the current packet 71 | virtual int available(); 72 | 73 | // Read a single byte from the current packet 74 | virtual int read(); 75 | 76 | // Read up to len bytes from the current packet and place them into buffer 77 | // Returns the number of bytes read, or 0 if none are available 78 | virtual int read(unsigned char* buffer, size_t len); 79 | 80 | // Read up to len characters from the current packet and place them into buffer 81 | // Returns the number of characters read, or 0 if none are available 82 | virtual int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); }; 83 | 84 | // Return the next byte from the current packet without moving on to the next byte 85 | virtual int peek(); 86 | 87 | virtual void flush(); // Finish reading the current packet 88 | 89 | // Return the IP address of the host who sent the current incoming packet 90 | virtual IPAddress remoteIP(); 91 | 92 | // Return the port of the host who sent the current incoming packet 93 | virtual uint16_t remotePort(); 94 | }; 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | config.h - Library for Arduino SPI connection to ESP8266 3 | Copyright (c) 2019 Jiri Bilek. All rights reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | ----------------------------------------------------- 20 | 21 | This file is a "center of configuration options". All important options for the 22 | library are concentrated here. 23 | */ 24 | 25 | #ifndef _CONFIG_H_INCLUDED 26 | #define _CONFIG_H_INCLUDED 27 | 28 | // Uncomment the following define if the safe reset circuit (https://github.com/JiriBilek/WiFiSpiESP/issues/6) 29 | // is connected to SS pin on ESP8266. This allows the SS signal to behave exactly 30 | // according SPI specification (goes low before transmission and high after) 31 | #define ESP8266_SAFE_RESET_IMPLEMENTED 32 | 33 | // Allow debugging information to be print on Serial 34 | #define ESPSPI_DEBUG_OPTION 35 | 36 | // Print information about received bad message on Serial 37 | //#define ESPSPI_DEBUG_OPTION_BAD_MESSAGE 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/utility/debug.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | debug.c - Library for Arduino Wifi shield. 3 | Copyright (c) 2011-2014 Arduino. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | //*********************************************/ 20 | // 21 | // File: debug.c 22 | // 23 | // Author: Jiri Bilek 24 | // 25 | //********************************************/ 26 | 27 | #include "debug.h" 28 | 29 | #if defined(ESPSPI_DEBUG_OPTION) 30 | 31 | #include 32 | 33 | // Only filename without path 34 | const char *DbgFileName(const char *s) 35 | { 36 | const char *p = s + strlen(s); 37 | while (--p > s) 38 | { 39 | if (*p == '/' || *p == '\\') 40 | return p + 1; 41 | } 42 | 43 | return s; 44 | } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/utility/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | debug.h - Library for Arduino Wifi shield. 3 | Copyright (c) 2011-2014 Arduino. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | //*********************************************/ 20 | // 21 | // File: debug.h 22 | // 23 | // Author: dlf (Metodo2 srl) 24 | // 25 | //********************************************/ 26 | 27 | 28 | #ifndef _DEBUG_H_INCLUDED 29 | #define _DEBUG_H_INCLUDED 30 | 31 | #define DBGOUT Serial 32 | 33 | #include 34 | #include 35 | #include "../config.h" 36 | 37 | const char *DbgFileName(const char *s); 38 | 39 | 40 | #define PRINT_FILE_LINE() do { \ 41 | DBGOUT.print("[");DBGOUT.print(DbgFileName(__FILE__)); \ 42 | DBGOUT.print(":");DBGOUT.print(__LINE__);DBGOUT.print("]");\ 43 | }while (0); 44 | 45 | #if defined(ESPSPI_DEBUG_OPTION) 46 | 47 | #define INFO(format, args...) do { \ 48 | char buf[250]; \ 49 | sprintf(buf, format, args); \ 50 | DBGOUT.println(buf); \ 51 | } while(0); 52 | 53 | #define INFO1(x) do { PRINT_FILE_LINE() DBGOUT.print(" I: ");\ 54 | DBGOUT.println(x); \ 55 | }while (0); 56 | 57 | 58 | #define INFO2(x,y) do { PRINT_FILE_LINE() DBGOUT.print(" I: ");\ 59 | DBGOUT.print(x,16);DBGOUT.print(",");DBGOUT.println(y,16); \ 60 | }while (0); 61 | 62 | 63 | #else 64 | #define INFO1(x) do {} while(0); 65 | #define INFO2(x,y) do {} while(0); 66 | #define INFO(format, args...) do {} while(0); 67 | #endif 68 | 69 | #if defined(ESPSPI_DEBUG_OPTION) 70 | #define WARN(args) do { PRINT_FILE_LINE() \ 71 | DBGOUT.print(" W: "); DBGOUT.println(args); \ 72 | }while (0); 73 | #define WARN2(arg1,args) do { PRINT_FILE_LINE() \ 74 | DBGOUT.print(" W: "); DBGOUT.print(arg1); DBGOUT.println(args); \ 75 | }while (0); 76 | #else 77 | #define WARN(args) do {} while (0); 78 | #define WARN2(arg1,args) do {} while (0); 79 | #endif 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /src/utility/espspi_drv.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | espspi_drv.cpp - Library for Arduino SPI connection with ESP8266 3 | 4 | Copyright (c) 2017 Jiri Bilek. All right reserved. 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include "../config.h" 22 | #include "espspi_drv.h" 23 | 24 | // Read and check one byte from the input 25 | #if defined(ESPSPI_DEBUG_OPTION_BAD_MESSAGE) 26 | #define READ_AND_CHECK_BYTE(c, err) \ 27 | do { \ 28 | uint8_t _b = espSpiProxy.readByte(); \ 29 | if (_b != (c)) { \ 30 | Serial.print(err); \ 31 | Serial.print(" exp:"); Serial.print(c, HEX); \ 32 | Serial.print(", got:"); Serial.print(_b, HEX); \ 33 | return 0; \ 34 | } \ 35 | } while (false) 36 | #else 37 | #define READ_AND_CHECK_BYTE(c, err) \ 38 | do { \ 39 | if (espSpiProxy.readByte() != (c)) \ 40 | return 0; \ 41 | } while (false) 42 | #endif 43 | 44 | /* 45 | Sends a command to ESP. If numParam == 0 ends the command otherwise keeps it open. 46 | 47 | Cmd Struct Message 48 | _______________________________________________________________________ 49 | | START CMD | C/R | CMD | N.PARAM | PARAM LEN | PARAM | .. | END CMD | 50 | |___________|______|______|_________|___________|________|____|_________| 51 | | 8 bit | 1bit | 7bit | 8bit | 8bit | nbytes | .. | 8bit | 52 | |___________|______|______|_________|___________|________|____|_________| 53 | 54 | The last byte (position 31) is crc8. 55 | */ 56 | void EspSpiDrv::sendCmd(const uint8_t cmd, const uint8_t numParam) 57 | { 58 | WAIT_FOR_SLAVE_RX_READY(); 59 | 60 | // Send Spi START CMD 61 | espSpiProxy.writeByte(START_CMD); 62 | 63 | // Send Spi C + cmd 64 | espSpiProxy.writeByte(cmd & ~(REPLY_FLAG)); 65 | 66 | // Send Spi numParam 67 | espSpiProxy.writeByte(numParam); 68 | 69 | // If numParam == 0 send END CMD and flush 70 | if (numParam == 0) 71 | endCmd(); 72 | } 73 | 74 | /* 75 | Ends a command and flushes the buffer 76 | */ 77 | void EspSpiDrv::endCmd() 78 | { 79 | espSpiProxy.writeByte(END_CMD); 80 | espSpiProxy.flush(MESSAGE_FINISHED); 81 | } 82 | 83 | /* 84 | Sends a parameter. 85 | param ... parameter value 86 | param_len ... length of the parameter 87 | */ 88 | void EspSpiDrv::sendParam(const uint8_t* param, const uint8_t param_len) 89 | { 90 | // Send paramLen 91 | espSpiProxy.writeByte(param_len); 92 | 93 | // Send param data 94 | for (int i=0; i> 8); 121 | 122 | // Send param data 123 | for (uint16_t i=0; i 0) 215 | { 216 | for (uint8_t i=0; i 44 | #include "debug.h" 45 | 46 | // The command codes are fixed by ESP8266 hardware 47 | #define CMD_WRITESTATUS 0x01 48 | #define CMD_WRITEDATA 0x02 49 | #define CMD_READDATA 0x03 50 | #define CMD_READSTATUS 0x04 51 | 52 | // Message indicators 53 | #define MESSAGE_FINISHED 0xDF 54 | #define MESSAGE_CONTINUES 0xDC 55 | 56 | // SPI Status 57 | enum { 58 | SPISLAVE_RX_BUSY, 59 | SPISLAVE_RX_READY, 60 | SPISLAVE_RX_CRC_PROCESSING, 61 | SPISLAVE_RX_ERROR 62 | }; 63 | enum { 64 | SPISLAVE_TX_NODATA, 65 | SPISLAVE_TX_READY, 66 | SPISLAVE_TX_PREPARING_DATA, 67 | SPISLAVE_TX_WAITING_FOR_CONFIRM 68 | }; 69 | 70 | // How long we will wait for slave to be ready 71 | #define SLAVE_RX_READY_TIMEOUT 3000UL 72 | #define SLAVE_TX_READY_TIMEOUT 3000UL 73 | 74 | // How long will be SS held high when starting transmission 75 | //#define SS_PULSE_DELAY_MICROSECONDS 50 76 | 77 | 78 | class EspSpiProxy 79 | { 80 | private: 81 | SPIClass *spi_obj; 82 | 83 | uint8_t _ss_pin; 84 | uint8_t buffer[32]; 85 | uint8_t buflen; 86 | uint8_t bufpos; 87 | 88 | void _pulseSS(bool start) 89 | { 90 | if (_ss_pin >= 0) 91 | { 92 | 93 | #if defined(ESP8266_SAFE_RESET_IMPLEMENTED) 94 | if (start) { 95 | digitalWrite(_ss_pin, LOW); 96 | delayMicroseconds(20); // 10us is low (some errors), 15 is ok, 25 us is safe for speeds > 4MHz 97 | } 98 | else { 99 | digitalWrite(_ss_pin, HIGH); 100 | } 101 | #else 102 | if (start) { // tested ok: 5, 15 / 5 103 | digitalWrite(_ss_pin, HIGH); 104 | delayMicroseconds(5); 105 | 106 | digitalWrite(_ss_pin, LOW); 107 | delayMicroseconds(20); // 10us is low (some errors), 15 is ok, 25 us is safe for speeds > 4MHz 108 | } 109 | else { 110 | digitalWrite(_ss_pin, HIGH); 111 | delayMicroseconds(5); 112 | digitalWrite(_ss_pin, LOW); 113 | } 114 | #endif 115 | 116 | } 117 | } 118 | 119 | public: 120 | EspSpiProxy() 121 | { 122 | _ss_pin = -1; 123 | buflen = 0; 124 | } 125 | 126 | void begin(uint8_t pin, SPIClass *in_spi) 127 | { 128 | spi_obj = in_spi; 129 | 130 | _ss_pin = pin; 131 | pinMode(_ss_pin, OUTPUT); 132 | #if defined(ESP8266_SAFE_RESET_IMPLEMENTED) 133 | digitalWrite(_ss_pin, HIGH); 134 | #else 135 | digitalWrite(_ss_pin, LOW); // Safe value for ESP8266 GPIO15 136 | #endif 137 | } 138 | 139 | uint16_t readStatus() 140 | { 141 | _pulseSS(true); 142 | 143 | spi_obj->transfer(CMD_READSTATUS); 144 | uint16_t status = (spi_obj->transfer(0) | ((uint16_t)(spi_obj->transfer(0)) << 8)); 145 | 146 | _pulseSS(false); 147 | 148 | return status; 149 | } 150 | 151 | void writeStatus(uint8_t status) 152 | { 153 | _pulseSS(true); 154 | 155 | spi_obj->transfer(CMD_WRITESTATUS); 156 | spi_obj->transfer(status); 157 | spi_obj->transfer(status ^ 0xff); // byte inverted value as a check 158 | 159 | _pulseSS(false); 160 | } 161 | 162 | void readData(uint8_t* buf) 163 | { 164 | _pulseSS(true); 165 | 166 | spi_obj->transfer(CMD_READDATA); 167 | spi_obj->transfer(0x00); 168 | for(uint8_t i=0; i<32; i++) { 169 | buf[i] = spi_obj->transfer(0); // the value is not important 170 | } 171 | 172 | _pulseSS(false); 173 | } 174 | 175 | void writeData(uint8_t * data) 176 | { 177 | _pulseSS(true); 178 | 179 | spi_obj->transfer(CMD_WRITEDATA); 180 | spi_obj->transfer(0x00); 181 | 182 | for (uint8_t i = 0; i < 32; ++i) 183 | spi_obj->transfer(data[i]); 184 | 185 | _pulseSS(false); 186 | } 187 | 188 | 189 | void flush(uint8_t indicator) 190 | { 191 | // Is buffer empty? 192 | if (buflen == 0) 193 | return; 194 | 195 | // Message state indicator 196 | buffer[0] = indicator; 197 | 198 | // Pad the buffer with zeroes 199 | while (buflen < 30) 200 | buffer[++buflen] = 0; 201 | 202 | // Compute CRC8 203 | buffer[31] = crc8(buffer, 31); 204 | 205 | // Wait for slave ready 206 | // TODO: move the waiting loop to writeByte (defer waiting) 207 | uint8_t s = waitForSlaveRxReady(); 208 | if (s == SPISLAVE_RX_READY || s == SPISLAVE_RX_ERROR) // Error state can't be recovered, we can send new data 209 | { 210 | // Try to send the buffer 10 times, we may not be stuck in an endless loop 211 | for (uint8_t i=0; i<10; ++i) 212 | { 213 | // Send the buffer 214 | writeData(buffer); 215 | 216 | if (waitForSlaveRxConfirmation()) 217 | break; 218 | else 219 | WARN("Bad CRC, retransmitting"); 220 | } 221 | } 222 | 223 | buflen = 0; 224 | } 225 | 226 | void writeByte(uint8_t b) 227 | { 228 | bufpos = 0; // discard input data in the buffer 229 | 230 | if (buflen >= 30) 231 | flush(MESSAGE_CONTINUES); 232 | 233 | buffer[++buflen] = b; 234 | } 235 | 236 | uint8_t readByte() 237 | { 238 | buflen = 0; // discard output data in the buffer 239 | 240 | if (bufpos >= 31) // the buffer segment was read 241 | { 242 | if (buffer[0] != MESSAGE_CONTINUES) 243 | return 0; 244 | 245 | bufpos = 0; // read next chunk 246 | 247 | // Wait for the slave 248 | waitForSlaveTxReady(); 249 | } 250 | 251 | if (bufpos == 0) // buffer empty 252 | { 253 | uint32_t thisTime = millis(); 254 | 255 | do { 256 | readData(buffer); 257 | 258 | if (buffer[31] == crc8(buffer, 31)) 259 | break; 260 | 261 | WARN("Bad CRC, request repeated"); 262 | 263 | } while (millis() - thisTime < 200); // repeat until crc is ok or 200 ms elapsed 264 | 265 | // Send confirmation to the slave (done through querying a status) 266 | readStatus(); 267 | 268 | // Check the buffer for correctness 269 | if (buffer[0] != MESSAGE_FINISHED && buffer[0] != MESSAGE_CONTINUES) 270 | return 0; // incorrect message (should not happen) 271 | 272 | bufpos = 1; 273 | } 274 | return buffer[bufpos++]; 275 | } 276 | 277 | /* 278 | Waits for slave receiver ready status. 279 | Return: receiver status 280 | */ 281 | int8_t waitForSlaveRxReady() 282 | { 283 | uint32_t startTime = millis(); 284 | uint16_t status = 0; 285 | 286 | do 287 | { 288 | status = readStatus(); 289 | 290 | if ((status & 0xff) == ((status >> 8) ^ 0xff)) // check the xor 291 | { 292 | uint16_t s = (status >> 4) & 0x0f; 293 | if (s == SPISLAVE_RX_READY || s == SPISLAVE_RX_ERROR) // From the perspective of rx state the error is the same as ready 294 | return ((status >> 4) & 0x0f); // status 295 | } 296 | 297 | yield(); 298 | } while (millis() - startTime < SLAVE_RX_READY_TIMEOUT); 299 | 300 | WARN2("Slave rx is not ready, status ", (status >> 4) & 0x0f); 301 | 302 | return ((status >> 4) & 0x0f); // timeout 303 | } 304 | 305 | 306 | 307 | /* 308 | Waits for slave transmitter ready status. 309 | Return: transmitter status 310 | */ 311 | int8_t waitForSlaveTxReady() 312 | { 313 | uint32_t startTime = millis(); 314 | uint16_t status = 0; 315 | 316 | do 317 | { 318 | status = readStatus(); 319 | 320 | if ((status & 0xff) == ((status >> 8) ^ 0xff)) // check the xor 321 | { 322 | if ((status & 0x0f) == SPISLAVE_TX_READY) 323 | return (status & 0x0f); // status 324 | } 325 | 326 | yield(); 327 | } while (millis() - startTime < SLAVE_TX_READY_TIMEOUT); 328 | 329 | WARN2("Slave tx is not ready, status ", status & 0x0f); 330 | 331 | return (status & 0x0f); // timeout 332 | } 333 | 334 | /* 335 | Waits for slave receiver read confirmation or rejection status. 336 | Status SPISLAVE_RX_CRC_PROCESSING holds the loop, SPISLAVE_RX_ERROR exits with error, other exits ok 337 | Return: receiver read data ok 338 | */ 339 | int8_t waitForSlaveRxConfirmation() 340 | { 341 | uint32_t startTime = millis(); 342 | uint16_t status = 0; 343 | 344 | do 345 | { 346 | status = readStatus(); 347 | 348 | if ((status & 0xff) == ((status >> 8) ^ 0xff)) // check the xor 349 | { 350 | uint8_t stat = (status >> 4) & 0x0f; 351 | 352 | if (stat == SPISLAVE_RX_ERROR) 353 | return false; // Error status 354 | else if (stat != SPISLAVE_RX_CRC_PROCESSING) 355 | return true; // OK status 356 | 357 | // Slave is still processing the CRC 358 | } 359 | 360 | yield(); 361 | } while (millis() - startTime < SLAVE_RX_READY_TIMEOUT); 362 | 363 | WARN2("Slave rx (confirm) is not ready, status ", (status >> 4) & 0x0f); 364 | 365 | return true; // timeout - we can't retransmit in order not to replay old data, assume everything is ok 366 | } 367 | 368 | /* 369 | * Compute crc8 with polynom 0x107 (x^8 + x^2 + x + 1) 370 | * Lookup table idea: https://lentz.com.au/blog/tag/crc-table-generator 371 | */ 372 | uint8_t crc8(uint8_t *buffer, uint8_t bufLen) 373 | { 374 | static const uint8_t PROGMEM tableLow[] = { 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 375 | 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D }; 376 | static const uint8_t PROGMEM tableHigh[] = { 0x00, 0x70, 0xE0, 0x90, 0xC7, 0xB7, 0x27, 0x57, 377 | 0x89, 0xF9, 0x69, 0x19, 0x4E, 0x3E, 0xAE, 0xDE }; 378 | 379 | uint8_t crcValue = 0x00; 380 | 381 | for (int i = 0; i < bufLen; ++i) { 382 | crcValue ^= buffer[i]; 383 | crcValue = pgm_read_byte(tableLow + (crcValue & 0x0f)) ^ 384 | pgm_read_byte(tableHigh +((crcValue >> 4) & 0x0f)); 385 | } 386 | 387 | return crcValue; 388 | } 389 | 390 | /* 391 | * Puts the SS low (required for successfull boot) and resets the ESP 392 | */ 393 | void hardReset(int8_t hwResetPin) 394 | { 395 | #if !defined(ESP8266_SAFE_RESET_IMPLEMENTED) 396 | digitalWrite(_ss_pin, LOW); // Safe value for ESP8266 GPIO15 397 | #endif 398 | digitalWrite(hwResetPin, LOW); 399 | delay(50); 400 | digitalWrite(hwResetPin, HIGH); 401 | delay(200); 402 | } 403 | 404 | }; 405 | 406 | extern EspSpiProxy espSpiProxy; 407 | 408 | #endif 409 | 410 | -------------------------------------------------------------------------------- /src/utility/srvspi_drv.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | srvspi_drv.cpp - Library for Arduino Wifi SPI connection with ESP8266. 3 | Copyright (c) 2017 Jiri Bilek. All right reserved. 4 | 5 | --- 6 | 7 | Based on server_drv.cpp - Library for Arduino Wifi shield. 8 | Copyright (c) 2011-2014 Arduino. All right reserved. 9 | 10 | This library is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU Lesser General Public 12 | License as published by the Free Software Foundation; either 13 | version 2.1 of the License, or (at your option) any later version. 14 | 15 | This library is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with this library; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 | */ 24 | 25 | #include "srvspi_drv.h" 26 | 27 | #include "Arduino.h" 28 | #include "espspi_drv.h" 29 | 30 | extern "C" { 31 | #include "wl_types.h" 32 | #include "debug.h" 33 | } 34 | 35 | #define FPSTR(pstr_pointer) (reinterpret_cast(pstr_pointer)) 36 | 37 | /* 38 | Start server TCP / UDP on port specified 39 | */ 40 | bool ServerSpiDrv::startServer(uint16_t port, uint8_t sock, uint8_t protMode) 41 | { 42 | // Send Command 43 | EspSpiDrv::sendCmd(START_SERVER_TCP_CMD, PARAM_NUMS_3); 44 | EspSpiDrv::sendParam(reinterpret_cast(&port), sizeof(port)); 45 | EspSpiDrv::sendParam(sock); 46 | EspSpiDrv::sendParam(protMode); 47 | EspSpiDrv::endCmd(); 48 | 49 | uint8_t _data = 0; 50 | uint8_t _dataLen = sizeof(_data); 51 | if (!EspSpiDrv::waitResponseCmd(START_SERVER_TCP_CMD, PARAM_NUMS_1, &_data, &_dataLen)) 52 | { 53 | WARN(FPSTR(WiFiSpiDrv::ERROR_WAITRESPONSE)); 54 | _data = 0; 55 | } 56 | 57 | return (_data == 1); // return value 1 means ok 58 | } 59 | 60 | /* 61 | Start server UDP Multicast on port specified listening given ip address 62 | */ 63 | bool ServerSpiDrv::startServerMulticast(const uint32_t ipAddress, const uint16_t port, const uint8_t sock) 64 | { 65 | // Send Command 66 | EspSpiDrv::sendCmd(START_SERVER_MULTICAST_CMD, PARAM_NUMS_3); 67 | EspSpiDrv::sendParam(reinterpret_cast(&ipAddress), sizeof(ipAddress)); 68 | EspSpiDrv::sendParam(reinterpret_cast(&port), sizeof(port)); 69 | EspSpiDrv::sendParam(sock); 70 | EspSpiDrv::endCmd(); 71 | 72 | uint8_t _data = 0; 73 | uint8_t _dataLen = sizeof(_data); 74 | if (!EspSpiDrv::waitResponseCmd(START_SERVER_MULTICAST_CMD, PARAM_NUMS_1, &_data, &_dataLen)) 75 | { 76 | WARN(FPSTR(WiFiSpiDrv::ERROR_WAITRESPONSE)); 77 | _data = 0; 78 | } 79 | 80 | return (_data == 1); // return value 1 means ok 81 | } 82 | 83 | /* 84 | * 85 | */ 86 | void ServerSpiDrv::stopServer(uint8_t sock) 87 | { 88 | // Send Command 89 | EspSpiDrv::sendCmd(STOP_SERVER_TCP_CMD, PARAM_NUMS_1); 90 | EspSpiDrv::sendParam(sock); 91 | EspSpiDrv::endCmd(); 92 | 93 | if (!EspSpiDrv::waitResponseCmd(STOP_SERVER_TCP_CMD, PARAM_NUMS_0, NULL, NULL)) 94 | { 95 | WARN(FPSTR(WiFiSpiDrv::ERROR_WAITRESPONSE)); 96 | } 97 | } 98 | 99 | /* 100 | Start client TCP on port specified 101 | Note: protMode is ignored 102 | */ 103 | bool ServerSpiDrv::startClient(uint32_t ipAddress, uint16_t port, uint8_t sock, uint8_t protMode) 104 | { 105 | // Send Command 106 | EspSpiDrv::sendCmd(START_CLIENT_TCP_CMD, PARAM_NUMS_4); 107 | EspSpiDrv::sendParam(reinterpret_cast(&ipAddress), sizeof(ipAddress)); 108 | EspSpiDrv::sendParam(reinterpret_cast(&port), sizeof(port)); 109 | EspSpiDrv::sendParam(sock); 110 | EspSpiDrv::sendParam(protMode); 111 | EspSpiDrv::endCmd(); 112 | 113 | // Wait for reply 114 | 115 | // Extended waiting time for status SPISLAVE_TX_PREPARING_DATA 116 | for (int i=1; i<10; ++i) 117 | { 118 | if (espSpiProxy.waitForSlaveTxReady() != SPISLAVE_TX_PREPARING_DATA) 119 | break; // The state is either SPISLAVE_TX_READY or SPISLAVE_TX_NODATA with timeout 120 | WARN(F("Status: Preparing data")); 121 | } 122 | 123 | uint8_t _data = 0; 124 | uint8_t _dataLen = sizeof(_data); 125 | if (!EspSpiDrv::waitResponseCmd(START_CLIENT_TCP_CMD, PARAM_NUMS_1, &_data, &_dataLen)) 126 | { 127 | WARN(FPSTR(WiFiSpiDrv::ERROR_WAITRESPONSE)); 128 | _data = 0; 129 | } 130 | 131 | return (_data == 1); // return value 1 means ok 132 | } 133 | 134 | /* 135 | * 136 | */ 137 | void ServerSpiDrv::stopClient(uint8_t sock) 138 | { 139 | // Send Command 140 | EspSpiDrv::sendCmd(STOP_CLIENT_TCP_CMD, PARAM_NUMS_1); 141 | EspSpiDrv::sendParam(sock); 142 | EspSpiDrv::endCmd(); 143 | 144 | uint8_t _data = 0; 145 | uint8_t _dataLen = sizeof(_data); 146 | if (!EspSpiDrv::waitResponseCmd(STOP_CLIENT_TCP_CMD, PARAM_NUMS_1, &_data, &_dataLen)) 147 | { 148 | WARN(FPSTR(WiFiSpiDrv::ERROR_WAITRESPONSE)); 149 | } 150 | } 151 | 152 | /* 153 | * 154 | */ 155 | uint8_t ServerSpiDrv::getServerState(uint8_t sock) 156 | { 157 | // Send Command 158 | EspSpiDrv::sendCmd(GET_STATE_TCP_CMD, PARAM_NUMS_1); 159 | EspSpiDrv::sendParam(sock); 160 | EspSpiDrv::endCmd(); 161 | 162 | uint8_t _data = 0; 163 | uint8_t _dataLen = sizeof(_data); 164 | if (!EspSpiDrv::waitResponseCmd(GET_STATE_TCP_CMD, PARAM_NUMS_1, &_data, &_dataLen)) 165 | { 166 | WARN(FPSTR(WiFiSpiDrv::ERROR_WAITRESPONSE)); 167 | _data = CLOSED; 168 | } 169 | 170 | return (_data ? ESTABLISHED : CLOSED); 171 | } 172 | 173 | /* 174 | * 175 | */ 176 | uint8_t ServerSpiDrv::getClientState(const uint8_t sock) 177 | { 178 | // Send Command 179 | EspSpiDrv::sendCmd(GET_CLIENT_STATE_TCP_CMD, PARAM_NUMS_1); 180 | EspSpiDrv::sendParam(sock); 181 | EspSpiDrv::endCmd(); 182 | 183 | // Wait for reply 184 | uint8_t _data = -1; 185 | uint8_t _dataLen = sizeof(_data); 186 | if (!EspSpiDrv::waitResponseCmd(GET_CLIENT_STATE_TCP_CMD, PARAM_NUMS_1, &_data, &_dataLen)) 187 | { 188 | WARN(FPSTR(WiFiSpiDrv::ERROR_WAITRESPONSE)); 189 | _data = 0; 190 | } 191 | 192 | return (_data ? ESTABLISHED : CLOSED); 193 | } 194 | 195 | /* 196 | * 197 | */ 198 | uint16_t ServerSpiDrv::availData(const uint8_t sock) 199 | { 200 | // Send Command 201 | EspSpiDrv::sendCmd(AVAIL_DATA_TCP_CMD, PARAM_NUMS_1); 202 | EspSpiDrv::sendParam(sock); 203 | EspSpiDrv::endCmd(); 204 | 205 | // Wait for reply 206 | uint16_t _data16; 207 | uint8_t _dataLen = sizeof(_data16); 208 | if (!EspSpiDrv::waitResponseCmd(AVAIL_DATA_TCP_CMD, PARAM_NUMS_1, reinterpret_cast(&_data16), &_dataLen)) 209 | { 210 | WARN(FPSTR(WiFiSpiDrv::ERROR_WAITRESPONSE)); 211 | _data16 = 0; 212 | } 213 | 214 | return _data16; 215 | } 216 | 217 | /* 218 | * 219 | */ 220 | bool ServerSpiDrv::getData(const uint8_t sock, int16_t *data, const uint8_t peek) 221 | { 222 | // Send Command 223 | EspSpiDrv::sendCmd(GET_DATA_TCP_CMD, PARAM_NUMS_2); 224 | EspSpiDrv::sendParam(sock); 225 | EspSpiDrv::sendParam(peek); 226 | EspSpiDrv::endCmd(); 227 | 228 | // Wait for reply 229 | int16_t _data16 = -1; // -1 is error indicator 230 | uint8_t _dataLen = sizeof(_data16); 231 | if (!EspSpiDrv::waitResponseCmd(GET_DATA_TCP_CMD, PARAM_NUMS_1, reinterpret_cast(&_data16), &_dataLen)) 232 | { 233 | WARN(FPSTR(WiFiSpiDrv::ERROR_WAITRESPONSE)); 234 | _dataLen = 0; 235 | } 236 | else 237 | *data = _data16; 238 | 239 | return (_dataLen == sizeof(_data16)); 240 | } 241 | 242 | /* 243 | Reads data into a buffer. There must be enough data for the whole buffer or the return code is false (error). 244 | It is not very clever but it is how the original WiFi library works. 245 | */ 246 | bool ServerSpiDrv::getDataBuf(const uint8_t sock, uint8_t *_data, uint16_t *_dataLen) 247 | { 248 | // Send Command 249 | EspSpiDrv::sendCmd(GET_DATABUF_TCP_CMD, PARAM_NUMS_2); 250 | EspSpiDrv::sendParam(sock); 251 | EspSpiDrv::sendParam(reinterpret_cast(_dataLen), sizeof(*_dataLen)); 252 | EspSpiDrv::endCmd(); 253 | 254 | // Wait for reply (length is 16 bit integer) 255 | uint16_t _dataLenRead = *_dataLen; 256 | if (!EspSpiDrv::waitResponseCmd16(GET_DATABUF_TCP_CMD, PARAM_NUMS_1, _data, &_dataLenRead)) 257 | { 258 | WARN(FPSTR(WiFiSpiDrv::ERROR_WAITRESPONSE)); 259 | _dataLenRead = 0; 260 | } 261 | 262 | if (_dataLenRead != *_dataLen) 263 | return false; 264 | 265 | return true; 266 | } 267 | 268 | /* 269 | Works for UDP connection only 270 | */ 271 | bool ServerSpiDrv::insertDataBuf(uint8_t sock, const uint8_t *data, uint16_t _len) 272 | { 273 | // Send Command 274 | EspSpiDrv::sendCmd(INSERT_DATABUF_CMD, PARAM_NUMS_2); 275 | EspSpiDrv::sendParam(sock); 276 | EspSpiDrv::sendBuffer(data, _len); 277 | EspSpiDrv::endCmd(); 278 | 279 | // Wait for reply 280 | uint16_t _data16; 281 | uint8_t _dataLen = sizeof(_data16); 282 | if (!EspSpiDrv::waitResponseCmd(INSERT_DATABUF_CMD, PARAM_NUMS_1, reinterpret_cast(&_data16), &_dataLen)) 283 | { 284 | WARN(FPSTR(WiFiSpiDrv::ERROR_WAITRESPONSE)); 285 | _data16 = 0; 286 | } 287 | return (_dataLen == sizeof(_data16) && _data16 == _len); 288 | } 289 | 290 | /* 291 | * 292 | */ 293 | bool ServerSpiDrv::sendUdpData(uint8_t sock) 294 | { 295 | // Send Command 296 | EspSpiDrv::sendCmd(SEND_DATA_UDP_CMD, PARAM_NUMS_1); 297 | EspSpiDrv::sendParam(sock); 298 | EspSpiDrv::endCmd(); 299 | 300 | // Wait for reply 301 | uint8_t _data = 0; 302 | uint8_t _dataLen = sizeof(_data); 303 | if (!EspSpiDrv::waitResponseCmd(SEND_DATA_UDP_CMD, PARAM_NUMS_1, &_data, &_dataLen)) 304 | { 305 | WARN(FPSTR(WiFiSpiDrv::ERROR_WAITRESPONSE)); 306 | _data = 0; 307 | } 308 | 309 | return (_data == 1); 310 | } 311 | 312 | /* 313 | * 314 | */ 315 | bool ServerSpiDrv::sendData(const uint8_t sock, const uint8_t *data, const uint16_t len) 316 | { 317 | // Send Command 318 | EspSpiDrv::sendCmd(SEND_DATA_TCP_CMD, PARAM_NUMS_2); 319 | EspSpiDrv::sendParam(sock); 320 | EspSpiDrv::sendBuffer(data, len); 321 | EspSpiDrv::endCmd(); 322 | 323 | // Wait for reply 324 | uint16_t _data16; 325 | uint8_t _dataLen = sizeof(_data16); 326 | if (!EspSpiDrv::waitResponseCmd(SEND_DATA_TCP_CMD, PARAM_NUMS_1, reinterpret_cast(&_data16), &_dataLen)) 327 | { 328 | WARN(FPSTR(WiFiSpiDrv::ERROR_WAITRESPONSE)); 329 | _data16 = 0; 330 | } 331 | return (_dataLen == sizeof(_data16) && _data16 == len); 332 | } 333 | 334 | /* 335 | Opens UDP communication on defined IP address and port 336 | */ 337 | bool ServerSpiDrv::beginUdpPacket(uint32_t ipAddress, uint16_t port, uint8_t sock) 338 | { 339 | // Send Command 340 | EspSpiDrv::sendCmd(BEGIN_UDP_PACKET_CMD, PARAM_NUMS_3); 341 | EspSpiDrv::sendParam(reinterpret_cast(&ipAddress), sizeof(ipAddress)); 342 | EspSpiDrv::sendParam(reinterpret_cast(&port), sizeof(port)); 343 | EspSpiDrv::sendParam(sock); 344 | EspSpiDrv::endCmd(); 345 | 346 | // Wait for reply 347 | 348 | // Extended waiting time for status SPISLAVE_TX_PREPARING_DATA 349 | for (int i=1; i<10; ++i) 350 | { 351 | if (espSpiProxy.waitForSlaveTxReady() != SPISLAVE_TX_PREPARING_DATA) 352 | break; // The state is either SPISLAVE_TX_READY or SPISLAVE_TX_NODATA with timeout 353 | WARN(F("Status: Preparing data")); /// 354 | } 355 | 356 | uint8_t _data = 0; 357 | uint8_t _dataLen = sizeof(_data); 358 | if (!EspSpiDrv::waitResponseCmd(BEGIN_UDP_PACKET_CMD, PARAM_NUMS_1, &_data, &_dataLen)) 359 | { 360 | WARN(FPSTR(WiFiSpiDrv::ERROR_WAITRESPONSE)); 361 | _data = 0; 362 | } 363 | 364 | return (_data == 1); // return value 1 means ok 365 | } 366 | 367 | /* 368 | * 369 | */ 370 | uint16_t ServerSpiDrv::parsePacket(const uint8_t sock) 371 | { 372 | // Send Command 373 | EspSpiDrv::sendCmd(UDP_PARSE_PACKET_CMD, PARAM_NUMS_1); 374 | EspSpiDrv::sendParam(sock); 375 | EspSpiDrv::endCmd(); 376 | 377 | // Wait for reply 378 | uint16_t _data16; 379 | uint8_t _dataLen = sizeof(_data16); 380 | if (!EspSpiDrv::waitResponseCmd(UDP_PARSE_PACKET_CMD, PARAM_NUMS_1, reinterpret_cast(&_data16), &_dataLen)) 381 | { 382 | WARN(FPSTR(WiFiSpiDrv::ERROR_WAITRESPONSE)); 383 | _data16 = 0; 384 | } 385 | 386 | return _data16; 387 | } 388 | 389 | /* 390 | * Sends verifySSL command 391 | * fingerprint - SHA1 of server certificate - must be 20 bytes (not character string!) 392 | * host - host name 393 | */ 394 | uint8_t ServerSpiDrv::verifySSLClient(const uint8_t sock, uint8_t *fingerprint, const char *host) 395 | { 396 | // Send Command 397 | EspSpiDrv::sendCmd(VERIFY_SSL_CLIENT_CMD, PARAM_NUMS_3); 398 | EspSpiDrv::sendParam(fingerprint, 20); 399 | EspSpiDrv::sendParam(reinterpret_cast(host), strlen(host)); 400 | EspSpiDrv::sendParam(sock); 401 | EspSpiDrv::endCmd(); 402 | 403 | // Wait for reply 404 | 405 | uint8_t _data = 0; 406 | uint8_t _dataLen = sizeof(_data); 407 | if (!EspSpiDrv::waitResponseCmd(VERIFY_SSL_CLIENT_CMD, PARAM_NUMS_1, &_data, &_dataLen)) 408 | { 409 | WARN(FPSTR(WiFiSpiDrv::ERROR_WAITRESPONSE)); 410 | _data = 0; 411 | } 412 | 413 | return _data; // return value 1 means ok 414 | } 415 | -------------------------------------------------------------------------------- /src/utility/srvspi_drv.h: -------------------------------------------------------------------------------- 1 | /* 2 | srvspi_drv.h - Library for Arduino Wifi SPI connection with ESP8266. 3 | Copyright (c) 2017 Jiri Bilek. All right reserved. 4 | 5 | --- 6 | 7 | Based on server_drv.h - Library for Arduino Wifi shield. 8 | Copyright (c) 2011-2014 Arduino. All right reserved. 9 | 10 | This library is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU Lesser General Public 12 | License as published by the Free Software Foundation; either 13 | version 2.1 of the License, or (at your option) any later version. 14 | 15 | This library is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with this library; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 | */ 24 | 25 | #ifndef _SRVSPI_DRV_H_INCLUDED 26 | #define _SRVSPI_DRV_H_INCLUDED 27 | 28 | #include 29 | #include "wifi_spi.h" 30 | 31 | typedef enum eProtMode { 32 | TCP_MODE, 33 | UDP_MODE, 34 | TCP_MODE_WITH_TLS } 35 | tProtMode; 36 | 37 | class ServerSpiDrv 38 | { 39 | public: 40 | 41 | // Start server TCP / UDP on port specified 42 | static bool startServer(const uint16_t port, const uint8_t sock, const uint8_t protMode=TCP_MODE); 43 | 44 | // Start server UDP Multicast on port specified listening given ip address 45 | static bool startServerMulticast(const uint32_t ipAddress, const uint16_t port, const uint8_t sock); 46 | 47 | static void stopServer(const uint8_t sock); 48 | 49 | static bool startClient(const uint32_t ipAddress, const uint16_t port, const uint8_t sock, const uint8_t protMode=TCP_MODE); 50 | 51 | static void stopClient(const uint8_t sock); 52 | 53 | static uint8_t getServerState(const uint8_t sock); 54 | 55 | static uint8_t getClientState(const uint8_t sock); 56 | 57 | static bool getData(const uint8_t sock, int16_t *data, uint8_t peek = 0); 58 | 59 | static bool getDataBuf(const uint8_t sock, uint8_t *data, uint16_t *len); 60 | 61 | static bool sendData(const uint8_t sock, const uint8_t *data, const uint16_t len); 62 | 63 | static bool sendUdpData(const uint8_t sock); 64 | 65 | static bool insertDataBuf(const uint8_t sock, const uint8_t *_data, const uint16_t _dataLen); 66 | 67 | static uint16_t availData(const uint8_t sock); 68 | 69 | /// static uint8_t checkDataSent(uint8_t sock); 70 | 71 | static bool beginUdpPacket(uint32_t ip, uint16_t port, uint8_t sock); 72 | 73 | static uint16_t parsePacket(const uint8_t sock); 74 | 75 | static uint8_t verifySSLClient(const uint8_t sock, uint8_t *fingerprint, const char *host); 76 | }; 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /src/utility/wifi_spi.h: -------------------------------------------------------------------------------- 1 | /* 2 | wifi_spi.h - Library for Arduino Wifi SPI connection with ESP8266. 3 | Copyright (c) 2017 Jiri Bilek. All right reserved. 4 | 5 | --- 6 | 7 | Based on wifi_spi.h - Library for Arduino Wifi shield. 8 | Copyright (c) 2011-2014 Arduino. All right reserved. 9 | 10 | This library is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU Lesser General Public 12 | License as published by the Free Software Foundation; either 13 | version 2.1 of the License, or (at your option) any later version. 14 | 15 | This library is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with this library; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 | */ 24 | 25 | #ifndef _WIFI_SPI_H_INCLUDED 26 | #define _WIFI_SPI_H_INCLUDED 27 | 28 | #include 29 | #include "wl_definitions.h" 30 | 31 | #define REPLY_FLAG 1<<7 32 | 33 | #define START_CMD 0xE0 34 | #define END_CMD 0xEE 35 | //#define ERR_CMD 0xEF 36 | 37 | enum { 38 | SET_NET_CMD = 0x10, 39 | SET_PASSPHRASE_CMD = 0x11, 40 | SET_KEY_CMD = 0x12, 41 | // TEST_CMD = 0x13, 42 | SET_IP_CONFIG_CMD = 0x14, 43 | // SET_DNS_CONFIG_CMD = 0x15, 44 | 45 | GET_CONN_STATUS_CMD = 0x20, 46 | GET_IPADDR_CMD = 0x21, 47 | GET_MACADDR_CMD = 0x22, 48 | GET_CURR_SSID_CMD = 0x23, 49 | GET_CURR_BSSID_CMD = 0x24, 50 | GET_CURR_RSSI_CMD = 0x25, 51 | GET_CURR_ENCT_CMD = 0x26, 52 | SCAN_NETWORKS = 0x27, 53 | START_SERVER_TCP_CMD = 0x28, 54 | GET_STATE_TCP_CMD = 0x29, 55 | DATA_SENT_TCP_CMD = 0x2A, 56 | AVAIL_DATA_TCP_CMD = 0x2B, 57 | GET_DATA_TCP_CMD = 0x2C, 58 | START_CLIENT_TCP_CMD = 0x2D, 59 | STOP_CLIENT_TCP_CMD = 0x2E, 60 | GET_CLIENT_STATE_TCP_CMD = 0x2F, 61 | DISCONNECT_CMD = 0x30, 62 | GET_IDX_SSID_CMD = 0x31, 63 | GET_IDX_RSSI_CMD = 0x32, 64 | GET_IDX_ENCT_CMD = 0x33, 65 | REQ_HOST_BY_NAME_CMD = 0x34, 66 | GET_HOST_BY_NAME_CMD = 0x35, 67 | START_SCAN_NETWORKS = 0x36, 68 | GET_FW_VERSION_CMD = 0x37, 69 | GET_TEST_CMD = 0x38, 70 | SEND_DATA_UDP_CMD = 0x39, 71 | GET_REMOTE_DATA_CMD = 0x3A, 72 | 73 | // Not present in original protocol, added for ESP8266 74 | STOP_SERVER_TCP_CMD = 0x3B, 75 | GET_SCANNED_DATA_CMD = 0x3C, 76 | BEGIN_UDP_PACKET_CMD = 0x3D, 77 | UDP_PARSE_PACKET_CMD = 0x3E, 78 | SOFTWARE_RESET_CMD = 0x3F, 79 | 80 | GET_PROTOCOL_VERSION_CMD = 0x50, 81 | VERIFY_SSL_CLIENT_CMD = 0x51, 82 | START_SERVER_MULTICAST_CMD = 0x52, 83 | SET_SSL_FINGERPRINT_CMD = 0x53, 84 | 85 | // All command with DATA_FLAG 0x40 send a 16bit Len 86 | 87 | SEND_DATA_TCP_CMD = 0x44, 88 | GET_DATABUF_TCP_CMD = 0x45, 89 | INSERT_DATABUF_CMD = 0x46, 90 | }; 91 | 92 | 93 | enum wl_tcp_state { 94 | CLOSED = 0, 95 | ESTABLISHED = 4 96 | }; 97 | 98 | /*enum wl_tcp_state { 99 | CLOSED = 0, 100 | LISTEN = 1, 101 | SYN_SENT = 2, 102 | SYN_RCVD = 3, 103 | ESTABLISHED = 4, 104 | FIN_WAIT_1 = 5, 105 | FIN_WAIT_2 = 6, 106 | CLOSE_WAIT = 7, 107 | CLOSING = 8, 108 | LAST_ACK = 9, 109 | TIME_WAIT = 10 110 | };*/ 111 | 112 | 113 | enum numParams{ 114 | PARAM_NUMS_0, 115 | PARAM_NUMS_1, 116 | PARAM_NUMS_2, 117 | PARAM_NUMS_3, 118 | PARAM_NUMS_4, 119 | PARAM_NUMS_5, 120 | MAX_PARAM_NUMS 121 | }; 122 | 123 | #define MAX_PARAMS MAX_PARAM_NUMS-1 124 | #define PARAM_LEN_SIZE 1 125 | 126 | typedef struct __attribute__((__packed__)) 127 | { 128 | uint8_t paramLen; 129 | char* param; 130 | } tParam; 131 | 132 | #endif 133 | -------------------------------------------------------------------------------- /src/utility/wifispi_drv.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | wifispi_drv.cpp - Library for Arduino SPI connection to ESP8266 3 | Copyright (c) 2017 Jiri Bilek. All right reserved. 4 | 5 | --- 6 | 7 | Based on wifi_drv.cpp - Library for Arduino Wifi shield. 8 | Copyright (c) 2011-2014 Arduino. All right reserved. 9 | 10 | This library is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU Lesser General Public 12 | License as published by the Free Software Foundation; either 13 | version 2.1 of the License, or (at your option) any later version. 14 | 15 | This library is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with this library; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include "Arduino.h" 30 | 31 | #include "espspi_proxy.h" 32 | #include "espspi_drv.h" 33 | #include "wifispi_drv.h" 34 | 35 | extern "C" { 36 | #include "wl_types.h" 37 | #include "debug.h" 38 | } 39 | 40 | #define FPSTR(pstr_pointer) (reinterpret_cast(pstr_pointer)) 41 | 42 | SPIClass *WiFiSpiDrv::spi_obj; 43 | 44 | // Array of data to cache the information related to the networks discovered 45 | char WiFiSpiDrv::_networkSsid[] = {0}; 46 | int32_t WiFiSpiDrv::_networkRssi = 0; 47 | uint8_t WiFiSpiDrv::_networkEncr = 0; 48 | 49 | // Cached values of retrieved data 50 | char WiFiSpiDrv::_ssid[] = {0}; 51 | uint8_t WiFiSpiDrv::_bssid[] = {0}; 52 | uint8_t WiFiSpiDrv::_mac[] = {0}; 53 | uint8_t WiFiSpiDrv::_localIp[] = {0}; 54 | uint8_t WiFiSpiDrv::_subnetMask[] = {0}; 55 | uint8_t WiFiSpiDrv::_gatewayIp[] = {0}; 56 | 57 | // Firmware and protocol version 58 | char WiFiSpiDrv::fwVersion[] = {0}; 59 | char WiFiSpiDrv::protocolVersion[] = {0}; 60 | 61 | // Static private class members 62 | const char WiFiSpiDrv::ERROR_WAITRESPONSE[] PROGMEM = "Error waitResponse"; 63 | const char WiFiSpiDrv::ERROR_BADREPLY[] PROGMEM = "Error badReply"; 64 | 65 | // Private Methods 66 | 67 | /* 68 | * 69 | */ 70 | int8_t WiFiSpiDrv::getNetworkData(uint8_t *ip, uint8_t *mask, uint8_t *gwip) 71 | { 72 | tParam params[PARAM_NUMS_3] = { {WL_IPV4_LENGTH, (char*)ip}, {WL_IPV4_LENGTH, (char*)mask}, {WL_IPV4_LENGTH, (char*)gwip}}; 73 | 74 | // Send Command 75 | EspSpiDrv::sendCmd(GET_IPADDR_CMD, PARAM_NUMS_0); 76 | 77 | if (!EspSpiDrv::waitResponseParams(GET_IPADDR_CMD, PARAM_NUMS_3, params)) 78 | { 79 | WARN(FPSTR(ERROR_WAITRESPONSE)); 80 | return WL_FAILURE; 81 | } 82 | 83 | return WL_SUCCESS; 84 | } 85 | 86 | /* 87 | * 88 | */ 89 | int8_t WiFiSpiDrv::getScannedData(uint8_t networkItem, char *ssid, int32_t *rssi, uint8_t *encr) 90 | { 91 | tParam params[PARAM_NUMS_3] = { {WL_SSID_MAX_LENGTH, (char*)ssid}, {sizeof(*rssi), (char*)rssi}, {sizeof(*encr), (char*)encr}}; 92 | 93 | // Send Command 94 | EspSpiDrv::sendCmd(GET_SCANNED_DATA_CMD, PARAM_NUMS_1); 95 | EspSpiDrv::sendParam(networkItem); 96 | EspSpiDrv::endCmd(); 97 | 98 | ssid[0] = 0; // Default is empty SSID 99 | 100 | if (!EspSpiDrv::waitResponseParams(GET_SCANNED_DATA_CMD, PARAM_NUMS_3, params)) 101 | { 102 | WARN(FPSTR(ERROR_WAITRESPONSE)); 103 | return WL_FAILURE; 104 | } 105 | 106 | ssid[params[0].paramLen] = 0; // end of string 107 | 108 | return WL_SUCCESS; 109 | } 110 | 111 | /* 112 | * 113 | */ 114 | bool WiFiSpiDrv::getRemoteData(uint8_t sock, uint8_t *ip, uint16_t *port) 115 | { 116 | tParam params[PARAM_NUMS_2] = { {4, (char*)ip}, {sizeof(*port), (char*)port} }; 117 | 118 | // Send Command 119 | EspSpiDrv::sendCmd(GET_REMOTE_DATA_CMD, PARAM_NUMS_1); 120 | EspSpiDrv::sendParam(sock); 121 | EspSpiDrv::endCmd(); 122 | 123 | if (!EspSpiDrv::waitResponseParams(GET_REMOTE_DATA_CMD, PARAM_NUMS_2, params)) 124 | { 125 | WARN(FPSTR(ERROR_WAITRESPONSE)); 126 | return false; 127 | } 128 | 129 | return true; 130 | } 131 | 132 | 133 | // Public Methods 134 | 135 | /* 136 | * 137 | */ 138 | void WiFiSpiDrv::wifiDriverInit(uint8_t pin, uint32_t max_speed, SPIClass *in_spi) 139 | { 140 | spi_obj = in_spi; 141 | spi_obj->begin(); 142 | 143 | if (max_speed != 0) 144 | spi_obj->beginTransaction(SPISettings(max_speed, MSBFIRST, SPI_MODE0)); 145 | 146 | espSpiProxy.begin(pin, spi_obj); 147 | } 148 | 149 | /* 150 | * 151 | */ 152 | int8_t WiFiSpiDrv::wifiSetNetwork(const char* ssid, uint8_t ssid_len) 153 | { 154 | // Test the input 155 | if (ssid_len > WL_SSID_MAX_LENGTH) 156 | return WL_FAILURE; 157 | 158 | // Send Command 159 | EspSpiDrv::sendCmd(SET_NET_CMD, PARAM_NUMS_1); 160 | EspSpiDrv::sendParam(reinterpret_cast(ssid), ssid_len); 161 | EspSpiDrv::endCmd(); 162 | 163 | // Wait for reply 164 | uint8_t _data = -1; 165 | uint8_t _dataLen = sizeof(_data); 166 | if (!EspSpiDrv::waitResponseCmd(SET_NET_CMD, PARAM_NUMS_1, &_data, &_dataLen)) 167 | { 168 | WARN(FPSTR(ERROR_WAITRESPONSE)); 169 | _data = WL_FAILURE; 170 | } 171 | 172 | return _data; 173 | } 174 | 175 | /* 176 | * Connects to AP with given parameters 177 | * Returns: status - see getConnectionStatus() 178 | */ 179 | uint8_t WiFiSpiDrv::wifiSetPassphrase(const char* ssid, const uint8_t ssid_len, const char *passphrase, const uint8_t len) 180 | { 181 | // Test the input 182 | if (ssid_len > WL_SSID_MAX_LENGTH || len > WL_WPA_KEY_MAX_LENGTH) 183 | return WL_FAILURE; 184 | 185 | // Send Command 186 | EspSpiDrv::sendCmd(SET_PASSPHRASE_CMD, PARAM_NUMS_2); 187 | EspSpiDrv::sendParam(reinterpret_cast(ssid), ssid_len); 188 | EspSpiDrv::sendParam(reinterpret_cast(passphrase), len); 189 | EspSpiDrv::endCmd(); 190 | 191 | // Wait for reply 192 | uint8_t _data = -1; 193 | uint8_t _dataLen = sizeof(_data); 194 | if (!EspSpiDrv::waitResponseCmd(SET_PASSPHRASE_CMD, PARAM_NUMS_1, &_data, &_dataLen)) 195 | { 196 | WARN(FPSTR(ERROR_WAITRESPONSE)); 197 | _data = WL_FAILURE; 198 | } 199 | 200 | return _data; 201 | } 202 | 203 | /* 204 | * 205 | */ 206 | bool WiFiSpiDrv::config(uint32_t local_ip, uint32_t gateway, uint32_t subnet, uint32_t dns_server1, uint32_t dns_server2) 207 | { 208 | // Send Command 209 | EspSpiDrv::sendCmd(SET_IP_CONFIG_CMD, PARAM_NUMS_5); 210 | EspSpiDrv::sendParam(reinterpret_cast(&local_ip), sizeof(local_ip)); 211 | EspSpiDrv::sendParam(reinterpret_cast(&gateway), sizeof(gateway)); 212 | EspSpiDrv::sendParam(reinterpret_cast(&subnet), sizeof(subnet)); 213 | EspSpiDrv::sendParam(reinterpret_cast(&dns_server1), sizeof(dns_server1)); 214 | EspSpiDrv::sendParam(reinterpret_cast(&dns_server2), sizeof(dns_server2)); 215 | EspSpiDrv::endCmd(); 216 | 217 | // Wait for reply 218 | uint8_t _data = false; 219 | uint8_t _dataLen = sizeof(_data); 220 | if (!EspSpiDrv::waitResponseCmd(SET_IP_CONFIG_CMD, PARAM_NUMS_1, &_data, &_dataLen)) 221 | { 222 | WARN(FPSTR(ERROR_WAITRESPONSE)); 223 | _data = false; 224 | } 225 | 226 | return _data; 227 | } 228 | 229 | /* 230 | * 231 | */ 232 | uint8_t WiFiSpiDrv::disconnect() 233 | { 234 | // Send Command 235 | EspSpiDrv::sendCmd(DISCONNECT_CMD, PARAM_NUMS_0); 236 | 237 | // Wait for reply 238 | uint8_t _data = -1; 239 | uint8_t _dataLen = sizeof(_data); 240 | if (!EspSpiDrv::waitResponseCmd(DISCONNECT_CMD, PARAM_NUMS_1, &_data, &_dataLen)) 241 | { 242 | WARN(FPSTR(ERROR_WAITRESPONSE)); 243 | _data = WL_FAILURE; 244 | } 245 | 246 | return _data; 247 | } 248 | 249 | /* 250 | * 251 | */ 252 | uint8_t WiFiSpiDrv::getConnectionStatus() 253 | { 254 | // Send Command 255 | EspSpiDrv::sendCmd(GET_CONN_STATUS_CMD, PARAM_NUMS_0); 256 | 257 | // Wait for reply 258 | uint8_t _data = -1; 259 | uint8_t _dataLen = sizeof(_data); 260 | if (!EspSpiDrv::waitResponseCmd(GET_CONN_STATUS_CMD, PARAM_NUMS_1, &_data, &_dataLen)) 261 | { 262 | WARN(FPSTR(ERROR_WAITRESPONSE)); 263 | } 264 | 265 | return _data; 266 | } 267 | 268 | /* 269 | * 270 | */ 271 | uint8_t* WiFiSpiDrv::getMacAddress() 272 | { 273 | // Send Command 274 | EspSpiDrv::sendCmd(GET_MACADDR_CMD, PARAM_NUMS_0); 275 | 276 | // Wait for reply 277 | uint8_t _dataLen = WL_MAC_ADDR_LENGTH; 278 | if (!EspSpiDrv::waitResponseCmd(GET_MACADDR_CMD, PARAM_NUMS_1, _mac, &_dataLen)) 279 | { 280 | WARN(FPSTR(ERROR_WAITRESPONSE)); 281 | } 282 | 283 | if (_dataLen != WL_MAC_ADDR_LENGTH) 284 | { 285 | WARN(FPSTR(ERROR_BADREPLY)); 286 | } 287 | 288 | return _mac; 289 | } 290 | 291 | /* 292 | * 293 | */ 294 | int8_t WiFiSpiDrv::getIpAddress(IPAddress& ip) 295 | { 296 | int8_t status = getNetworkData(_localIp, _subnetMask, _gatewayIp); 297 | if (status == WL_SUCCESS) 298 | ip = _localIp; 299 | 300 | return status; 301 | } 302 | 303 | /* 304 | * 305 | */ 306 | int8_t WiFiSpiDrv::getSubnetMask(IPAddress& mask) 307 | { 308 | int8_t status = getNetworkData(_localIp, _subnetMask, _gatewayIp); 309 | if (status == WL_SUCCESS) 310 | mask = _subnetMask; 311 | 312 | return status; 313 | } 314 | 315 | /* 316 | * 317 | */ 318 | int8_t WiFiSpiDrv::getGatewayIP(IPAddress& ip) 319 | { 320 | int8_t status = getNetworkData(_localIp, _subnetMask, _gatewayIp); 321 | if (status == WL_SUCCESS) 322 | ip = _gatewayIp; 323 | 324 | return status; 325 | } 326 | 327 | /* 328 | * 329 | */ 330 | char* WiFiSpiDrv::getCurrentSSID() 331 | { 332 | // Send Command 333 | EspSpiDrv::sendCmd(GET_CURR_SSID_CMD, PARAM_NUMS_0); 334 | 335 | // Wait for reply 336 | uint8_t _dataLen = WL_SSID_MAX_LENGTH; 337 | if (!EspSpiDrv::waitResponseCmd(GET_CURR_SSID_CMD, PARAM_NUMS_1, reinterpret_cast(_ssid), &_dataLen)) 338 | { 339 | WARN(FPSTR(ERROR_WAITRESPONSE)); 340 | } 341 | 342 | _ssid[_dataLen] = 0; // terminate the string 343 | 344 | return _ssid; 345 | } 346 | 347 | /* 348 | * 349 | */ 350 | uint8_t* WiFiSpiDrv::getCurrentBSSID() 351 | { 352 | // Send Command 353 | EspSpiDrv::sendCmd(GET_CURR_BSSID_CMD, PARAM_NUMS_0); 354 | 355 | // Wait for reply 356 | uint8_t _dataLen = WL_MAC_ADDR_LENGTH; 357 | if (!EspSpiDrv::waitResponseCmd(GET_CURR_BSSID_CMD, PARAM_NUMS_1, _bssid, &_dataLen)) 358 | { 359 | WARN(FPSTR(ERROR_WAITRESPONSE)); 360 | } 361 | 362 | if (_dataLen != WL_MAC_ADDR_LENGTH) 363 | { 364 | WARN(FPSTR(ERROR_BADREPLY)); 365 | } 366 | 367 | return _bssid; 368 | } 369 | 370 | /* 371 | * 372 | */ 373 | int32_t WiFiSpiDrv::getCurrentRSSI() 374 | { 375 | // Send Command 376 | EspSpiDrv::sendCmd(GET_CURR_RSSI_CMD, PARAM_NUMS_0); 377 | 378 | // Wait for reply 379 | int32_t _rssi; 380 | uint8_t _dataLen = sizeof(_rssi); 381 | if (!EspSpiDrv::waitResponseCmd(GET_CURR_RSSI_CMD, PARAM_NUMS_1, reinterpret_cast(&_rssi), &_dataLen)) 382 | { 383 | WARN(FPSTR(ERROR_WAITRESPONSE)); 384 | _dataLen = 0; 385 | } 386 | 387 | if (_dataLen != sizeof(_rssi)) 388 | { 389 | WARN(FPSTR(ERROR_BADREPLY)); 390 | } 391 | 392 | return _rssi; 393 | } 394 | 395 | /* 396 | * 397 | */ 398 | int8_t WiFiSpiDrv::startScanNetworks() 399 | { 400 | // Send Command 401 | EspSpiDrv::sendCmd(START_SCAN_NETWORKS, PARAM_NUMS_0); 402 | 403 | int8_t _data = -1; 404 | uint8_t _dataLen = sizeof(_data); 405 | if (!EspSpiDrv::waitResponseCmd(START_SCAN_NETWORKS, PARAM_NUMS_1, reinterpret_cast(&_data), &_dataLen)) 406 | { 407 | WARN(FPSTR(ERROR_WAITRESPONSE)); 408 | } 409 | 410 | return _data; 411 | } 412 | 413 | /* 414 | * 415 | */ 416 | int8_t WiFiSpiDrv::getScanNetworks() 417 | { 418 | // Send Command 419 | EspSpiDrv::sendCmd(SCAN_NETWORKS, PARAM_NUMS_0); 420 | 421 | int8_t _data = -1; 422 | uint8_t _dataLen = sizeof(_data); 423 | if (!EspSpiDrv::waitResponseCmd(SCAN_NETWORKS, PARAM_NUMS_1, reinterpret_cast(&_data), &_dataLen)) 424 | { 425 | WARN(FPSTR(ERROR_WAITRESPONSE)); 426 | } 427 | 428 | return _data; 429 | } 430 | 431 | /* 432 | * 433 | */ 434 | char* WiFiSpiDrv::getSSIDNetworks(uint8_t networkItem) 435 | { 436 | int8_t status = getScannedData(networkItem, _networkSsid, &_networkRssi, &_networkEncr); 437 | if (status != WL_SUCCESS) 438 | _networkSsid[0] = 0; // Empty string 439 | 440 | return _networkSsid; 441 | } 442 | 443 | /* 444 | * 445 | */ 446 | uint8_t WiFiSpiDrv::getEncTypeNetworks(uint8_t networkItem) 447 | { 448 | int8_t status = getScannedData(networkItem, _networkSsid, &_networkRssi, &_networkEncr); 449 | if (status != WL_SUCCESS) 450 | return 0; 451 | 452 | return _networkEncr; 453 | } 454 | 455 | /* 456 | * 457 | */ 458 | int32_t WiFiSpiDrv::getRSSINetworks(uint8_t networkItem) 459 | { 460 | int8_t status = getScannedData(networkItem, _networkSsid, &_networkRssi, &_networkEncr); 461 | if (status != WL_SUCCESS) 462 | return 0; 463 | 464 | return _networkRssi; 465 | } 466 | 467 | /* 468 | * 469 | */ 470 | int8_t WiFiSpiDrv::getHostByName(const char* aHostname, IPAddress& aResult) 471 | { 472 | // Send Command 473 | EspSpiDrv::sendCmd(GET_HOST_BY_NAME_CMD, PARAM_NUMS_1); 474 | EspSpiDrv::sendParam(reinterpret_cast(aHostname), strlen(aHostname)); 475 | EspSpiDrv::endCmd(); 476 | 477 | // Wait for reply 478 | uint8_t _ipAddr[WL_IPV4_LENGTH]; 479 | uint8_t _status; 480 | 481 | tParam params[PARAM_NUMS_2] = { {sizeof(_status), (char*)&_status}, {sizeof(_ipAddr), (char*)_ipAddr}}; 482 | 483 | // Extended waiting time for status SPISLAVE_PREPARING_DATA 484 | for (int i=1; i<10; ++i) 485 | { 486 | if (espSpiProxy.waitForSlaveTxReady() != SPISLAVE_TX_PREPARING_DATA) 487 | break; // The state is either SPISLAVE_TX_READY or SPISLAVE_TX_NODATA with timeout 488 | WARN(F("Status: Preparing data")); 489 | } 490 | 491 | if (!EspSpiDrv::waitResponseParams(GET_HOST_BY_NAME_CMD, PARAM_NUMS_2, params)) 492 | { 493 | WARN(FPSTR(ERROR_WAITRESPONSE)); 494 | return WL_FAILURE; 495 | } 496 | 497 | if (params[0].paramLen != sizeof(_status) || params[1].paramLen != sizeof(_ipAddr)) 498 | { 499 | WARN(FPSTR(ERROR_BADREPLY)); 500 | return 0; 501 | } 502 | 503 | aResult = _ipAddr; 504 | 505 | return _status; 506 | } 507 | 508 | /* 509 | * 510 | */ 511 | const char* WiFiSpiDrv::getFwVersion() 512 | { 513 | // Send Command 514 | EspSpiDrv::sendCmd(GET_FW_VERSION_CMD, PARAM_NUMS_0); 515 | 516 | // Wait for reply 517 | uint8_t _dataLen = WL_FW_VER_LENGTH; 518 | if (!EspSpiDrv::waitResponseCmd(GET_FW_VERSION_CMD, PARAM_NUMS_1, (uint8_t*)fwVersion, &_dataLen)) 519 | { 520 | WARN(FPSTR(ERROR_WAITRESPONSE)); 521 | } 522 | 523 | return fwVersion; 524 | } 525 | 526 | /* 527 | * Perform remote software reset of the ESP8266 module. 528 | * The reset succeedes only if the SPI communication is not broken. 529 | * The function does not wait for the ESP8266. 530 | */ 531 | void WiFiSpiDrv::softReset(void) { 532 | // Send Command 533 | EspSpiDrv::sendCmd(SOFTWARE_RESET_CMD, PARAM_NUMS_0); 534 | 535 | // Wait for reply 536 | if (!EspSpiDrv::waitResponseCmd(SOFTWARE_RESET_CMD, PARAM_NUMS_0, NULL, NULL)) 537 | { 538 | WARN(FPSTR(ERROR_WAITRESPONSE)); 539 | } 540 | } 541 | 542 | /* 543 | * 544 | */ 545 | const char* WiFiSpiDrv::getProtocolVersion() 546 | { 547 | // Send Command 548 | EspSpiDrv::sendCmd(GET_PROTOCOL_VERSION_CMD, PARAM_NUMS_0); 549 | 550 | // Wait for reply 551 | uint8_t _dataLen = WL_PROTOCOL_VER_LENGTH; 552 | if (!EspSpiDrv::waitResponseCmd(GET_PROTOCOL_VERSION_CMD, PARAM_NUMS_1, (uint8_t*)protocolVersion, &_dataLen)) 553 | { 554 | WARN(FPSTR(ERROR_WAITRESPONSE)); 555 | } 556 | 557 | return protocolVersion; 558 | } 559 | 560 | uint8_t WiFiSpiDrv::setSSLFingerprint(uint8_t *fingerprint) 561 | { 562 | // Send Command 563 | if (fingerprint == nullptr) // clear the saved fingerprint 564 | { 565 | EspSpiDrv::sendCmd(SET_SSL_FINGERPRINT_CMD, PARAM_NUMS_0); 566 | } 567 | else // set the fingerprint 568 | { 569 | EspSpiDrv::sendCmd(SET_SSL_FINGERPRINT_CMD, PARAM_NUMS_1); 570 | EspSpiDrv::sendParam(fingerprint, 20); 571 | EspSpiDrv::endCmd(); 572 | } 573 | 574 | // Wait for reply 575 | 576 | uint8_t _data = 0; 577 | uint8_t _dataLen = sizeof(_data); 578 | if (!EspSpiDrv::waitResponseCmd(SET_SSL_FINGERPRINT_CMD, PARAM_NUMS_1, &_data, &_dataLen)) 579 | { 580 | WARN(FPSTR(WiFiSpiDrv::ERROR_WAITRESPONSE)); 581 | _data = 0; 582 | } 583 | 584 | return _data; // return value 1 means ok 585 | } 586 | 587 | 588 | WiFiSpiDrv wiFiSPIDrv; 589 | 590 | -------------------------------------------------------------------------------- /src/utility/wifispi_drv.h: -------------------------------------------------------------------------------- 1 | /* 2 | wifispi_drv.h - Library for Arduino SPI connection to ESP8266 3 | Copyright (c) 2017 Jiri Bilek. All right reserved. 4 | 5 | --- 6 | 7 | Based on: wifi_drv.h - Library for Arduino Wifi shield. 8 | Copyright (c) 2011-2014 Arduino. All right reserved. 9 | 10 | This library is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU Lesser General Public 12 | License as published by the Free Software Foundation; either 13 | version 2.1 of the License, or (at your option) any later version. 14 | 15 | This library is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with this library; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 | */ 24 | 25 | #ifndef _WIFISPI_DRV_H_INCLUDED 26 | #define _WIFISPI_DRV_H_INCLUDED 27 | 28 | #include 29 | #include "wifi_spi.h" 30 | #include "IPAddress.h" 31 | #include 32 | 33 | // Key index length 34 | ///#define KEY_IDX_LEN 1 35 | // 100 ms secs of delay to test if the connection is established 36 | #define WL_DELAY_START_CONNECTION 100 37 | // Firmware version string length (format a.b.c) 38 | #define WL_FW_VER_LENGTH 6 39 | // Protocol version string length (format a.b.c) 40 | #define WL_PROTOCOL_VER_LENGTH 6 41 | 42 | #define DUMMY_DATA 0xFF 43 | 44 | 45 | class WiFiSpiDrv 46 | { 47 | private: 48 | // SPI object 49 | static SPIClass *spi_obj; 50 | 51 | // settings of requested network 52 | static char _networkSsid[WL_SSID_MAX_LENGTH+1]; 53 | static int32_t _networkRssi; 54 | static uint8_t _networkEncr; 55 | 56 | // firmware version string in the format a.b.c 57 | static char fwVersion[WL_FW_VER_LENGTH]; 58 | // protocol version string in the format a.b.c 59 | static char protocolVersion[WL_PROTOCOL_VER_LENGTH]; 60 | 61 | // settings of current selected network 62 | static char _ssid[WL_SSID_MAX_LENGTH+1]; 63 | static uint8_t _bssid[WL_MAC_ADDR_LENGTH]; 64 | static uint8_t _mac[WL_MAC_ADDR_LENGTH]; 65 | static uint8_t _localIp[WL_IPV4_LENGTH]; 66 | static uint8_t _subnetMask[WL_IPV4_LENGTH]; 67 | static uint8_t _gatewayIp[WL_IPV4_LENGTH]; 68 | 69 | /* 70 | * Get network Data information 71 | */ 72 | static int8_t getNetworkData(uint8_t *ip, uint8_t *mask, uint8_t *gwip); 73 | 74 | /* 75 | * Get scanned data information 76 | */ 77 | static int8_t getScannedData(uint8_t networkItem, char *ssid, int32_t *rssi, uint8_t *encr); 78 | 79 | static uint8_t reqHostByName(const char* aHostname); 80 | 81 | static int getHostByName(IPAddress& aResult); 82 | 83 | public: 84 | // Public constant strings 85 | static const char ERROR_WAITRESPONSE[] PROGMEM; // "Error waitResponse" 86 | static const char ERROR_BADREPLY[] PROGMEM; // "Error badReply" 87 | 88 | /* 89 | * Driver initialization, pin is GPIO port number used as SS 90 | */ 91 | static void wifiDriverInit(uint8_t pin, uint32_t max_speed = 0, SPIClass *in_spi = &SPI); 92 | 93 | /* 94 | * Set the desired network which the connection manager should try to 95 | * connect to. 96 | * 97 | * The ssid of the desired network should be specified. 98 | * 99 | * param ssid: The ssid of the desired network. 100 | * param ssid_len: Lenght of ssid string. 101 | * return: WL_SUCCESS or WL_FAILURE 102 | */ 103 | static int8_t wifiSetNetwork(const char* ssid, uint8_t ssid_len); 104 | 105 | /* Start Wifi connection with passphrase 106 | * the most secure supported mode will be automatically selected 107 | * 108 | * param ssid: Pointer to the SSID string. 109 | * param ssid_len: Length of ssid string. 110 | * param passphrase: Passphrase. Valid characters in a passphrase 111 | * must be between ASCII 32-126 (decimal). 112 | * param len: Length of passphrase string. 113 | * return: WL_SUCCESS or WL_FAILURE 114 | */ 115 | static uint8_t wifiSetPassphrase(const char* ssid, const uint8_t ssid_len, const char *passphrase, const uint8_t len); 116 | 117 | /* Start Wifi connection with WEP encryption. 118 | * Configure a key into the device. The key type (WEP-40, WEP-104) 119 | * is determined by the size of the key (5 bytes for WEP-40, 13 bytes for WEP-104). 120 | * 121 | * param ssid: Pointer to the SSID string. 122 | * param ssid_len: Lenght of ssid string. 123 | * param key_idx: The key index to set. Valid values are 0-3. 124 | * param key: Key input buffer. 125 | * param len: Lenght of key string. 126 | * return: WL_SUCCESS or WL_FAILURE 127 | */ 128 | /// static int8_t wifiSetKey(const char* ssid, uint8_t ssid_len, uint8_t key_idx, const void *key, const uint8_t len); 129 | 130 | /* Set ip configuration disabling dhcp client 131 | * 132 | * param local_ip: Static ip configuration 133 | * param gateway: Static gateway configuration 134 | * param subnet: Static subnet mask configuration 135 | * param dns_server1: Static DNS server1 configuration 136 | * param dns_server2: Static DNS server2 configuration 137 | */ 138 | static bool config(uint32_t local_ip, uint32_t gateway, uint32_t subnet, uint32_t dns_server1, uint32_t dns_server2); 139 | 140 | /* Set DNS ip configuration 141 | * 142 | * param validParams: set the number of parameters that we want to change 143 | * i.e. validParams = 1 means that we'll change only dns_server1 144 | * validParams = 2 means that we'll change dns_server1 and dns_server2 145 | * param dns_server1: Static DNS server1 configuration 146 | * param dns_server2: Static DNS server2 configuration 147 | */ 148 | /// static void setDNS(uint8_t validParams, uint32_t dns_server1, uint32_t dns_server2); 149 | 150 | /* 151 | * Disconnect from the network 152 | * 153 | * return: WL_SUCCESS or WL_FAILURE 154 | */ 155 | static uint8_t disconnect(); 156 | 157 | /* 158 | * Disconnect from the network 159 | * 160 | * return: one value of wl_status_t enum 161 | */ 162 | static uint8_t getConnectionStatus(); 163 | 164 | /* 165 | * Get the interface MAC address. 166 | * 167 | * return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH 168 | */ 169 | static uint8_t* getMacAddress(); 170 | 171 | /* 172 | * Get the interface IP address. 173 | * 174 | * return: copy the ip address value in IPAddress object 175 | */ 176 | static int8_t getIpAddress(IPAddress& ip); 177 | 178 | /* 179 | * Get the interface subnet mask address. 180 | * 181 | * return: copy the subnet mask address value in IPAddress object 182 | */ 183 | static int8_t getSubnetMask(IPAddress& mask); 184 | 185 | /* 186 | * Get the gateway ip address. 187 | * 188 | * return: copy the gateway ip address value in IPAddress object 189 | */ 190 | static int8_t getGatewayIP(IPAddress& ip); 191 | 192 | /* 193 | * Return the current SSID associated with the network 194 | * 195 | * return: ssid string 196 | */ 197 | static char* getCurrentSSID(); 198 | 199 | /* 200 | * Return the current BSSID associated with the network. 201 | * It is the MAC address of the Access Point 202 | * 203 | * return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH 204 | */ 205 | static uint8_t* getCurrentBSSID(); 206 | 207 | /* 208 | * Return the current RSSI /Received Signal Strength in dBm) 209 | * associated with the network 210 | * 211 | * return: signed value 212 | */ 213 | static int32_t getCurrentRSSI(); 214 | 215 | /* 216 | * Return the Encryption Type associated with the network 217 | * 218 | * return: one value of wl_enc_type enum 219 | */ 220 | /// static uint8_t getCurrentEncryptionType(); 221 | 222 | /* 223 | * Start scan WiFi networks available 224 | * 225 | * return: Number of discovered networks 226 | */ 227 | static int8_t startScanNetworks(); 228 | 229 | /* 230 | * Get the networks available 231 | * 232 | * return: Number of discovered networks 233 | */ 234 | static int8_t getScanNetworks(); 235 | 236 | /* 237 | * Return the SSID discovered during the network scan. 238 | * 239 | * param networkItem: specify from which network item want to get the information 240 | * 241 | * return: ssid string of the specified item on the networks scanned list 242 | */ 243 | static char* getSSIDNetworks(uint8_t networkItem); 244 | 245 | /* 246 | * Return the RSSI of the networks discovered during the scanNetworks 247 | * 248 | * param networkItem: specify from which network item want to get the information 249 | * 250 | * return: signed value of RSSI of the specified item on the networks scanned list 251 | */ 252 | static int32_t getRSSINetworks(uint8_t networkItem); 253 | 254 | /* 255 | * Return the encryption type of the networks discovered during the scanNetworks 256 | * 257 | * param networkItem: specify from which network item want to get the information 258 | * 259 | * return: encryption type (enum wl_enc_type) of the specified item on the networks scanned list 260 | */ 261 | static uint8_t getEncTypeNetworks(uint8_t networkItem); 262 | 263 | /* 264 | * Resolve the given hostname to an IP address. 265 | * param aHostname: Name to be resolved 266 | * param aResult: IPAddress structure to store the returned IP address 267 | * result: 1 if aIPAddrString was successfully converted to an IP address, 268 | * 0 error, hostname not found 269 | * -1 error, command was not performed 270 | */ 271 | static int8_t getHostByName(const char* aHostname, IPAddress& aResult); 272 | 273 | /* 274 | * Get the firmware version 275 | * result: version as string with this format a.b.c 276 | */ 277 | static const char* getFwVersion(); 278 | 279 | /* 280 | * Get remote Data information on UDP socket 281 | */ 282 | static bool getRemoteData(uint8_t sock, uint8_t *ip, uint16_t *port); 283 | 284 | /* 285 | * Perform software reset of the ESP8266 module. 286 | * The reset succeedes only if the SPI communication is not broken. 287 | * After the reset wait for the ESP8266 to came to life again. Typically, the ESP8266 boots within 100 ms, 288 | * but with the WifiManager installed on ESP it can be a couple of seconds. 289 | */ 290 | static void softReset(void); 291 | 292 | /* 293 | * Get the SPI protocol version 294 | * result: version as string with this format a.b.c 295 | */ 296 | static const char* getProtocolVersion(); 297 | 298 | /* 299 | * Sets or clears the certificate fingerprint for SSL connection 300 | * fingerprint - SHA1 of server certificate - must be 20 bytes (not character string!) 301 | */ 302 | static uint8_t setSSLFingerprint(uint8_t *fingerprint); 303 | 304 | }; 305 | 306 | extern WiFiSpiDrv wiFiSpiDrv; 307 | 308 | #endif 309 | -------------------------------------------------------------------------------- /src/utility/wl_definitions.h: -------------------------------------------------------------------------------- 1 | /* 2 | wl_definitions.h - Library for Arduino Wifi shield. 3 | Copyright (c) 2011-2014 Arduino. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | /* 20 | * wl_definitions.h 21 | * 22 | * Created on: Mar 6, 2011 23 | * Author: dlafauci 24 | */ 25 | 26 | #ifndef _WL_DEFINITIONS_H_INCLUDED 27 | #define _WL_DEFINITIONS_H_INCLUDED 28 | 29 | // Maximum size of a SSID 30 | #define WL_SSID_MAX_LENGTH 32 31 | // Length of passphrase. Valid lengths are 8-63. 32 | #define WL_WPA_KEY_MAX_LENGTH 63 33 | // Length of key in bytes. Valid values are 5 and 13. 34 | #define WL_WEP_KEY_MAX_LENGTH 13 35 | // Size of a MAC-address or BSSID 36 | #define WL_MAC_ADDR_LENGTH 6 37 | // Size of a MAC-address or BSSID 38 | #define WL_IPV4_LENGTH 4 39 | // Maximum size of a SSID list 40 | #define WL_NETWORKS_LIST_MAXNUM 10 41 | // Maxmium number of socket 42 | #define MAX_SOCK_NUM 4 43 | // Socket not available constant 44 | #define SOCK_NOT_AVAIL 255 45 | // Default state value for Wifi state field 46 | #define NA_STATE -1 47 | // Maximum waiting time to establish wifi connection is 10 s (in WL_DELAY_START_CONNECTION = 100 ms) 48 | #define WL_MAX_ATTEMPT_CONNECTION 100 49 | 50 | typedef enum { 51 | WL_NO_SHIELD = 255, 52 | WL_IDLE_STATUS = 0, 53 | WL_NO_SSID_AVAIL, 54 | WL_SCAN_COMPLETED, 55 | WL_CONNECTED, 56 | WL_CONNECT_FAILED, 57 | WL_CONNECTION_LOST, 58 | WL_DISCONNECTED 59 | } wl_status_t; 60 | 61 | /* Encryption modes */ 62 | /*enum wl_enc_type { // Values map to 802.11 encryption suites... 63 | ENC_TYPE_WEP = 5, 64 | ENC_TYPE_TKIP = 2, 65 | ENC_TYPE_CCMP = 4, 66 | // ... except these two, 7 and 8 are reserved in 802.11-2007 67 | ENC_TYPE_NONE = 7, 68 | ENC_TYPE_AUTO = 8 69 | };*/ 70 | 71 | 72 | #endif /* WL_DEFINITIONS_H_ */ 73 | -------------------------------------------------------------------------------- /src/utility/wl_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | wl_types.h - Library for Arduino Wifi shield. 3 | Copyright (c) 2011-2014 Arduino. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | /* 20 | * wl_types.h 21 | * 22 | * Created on: Jul 30, 2010 23 | * Author: dlafauci 24 | */ 25 | 26 | 27 | #ifndef _WL_TYPES_H_INCLUDED 28 | #define _WL_TYPES_H_INCLUDED 29 | 30 | #include 31 | 32 | typedef enum { 33 | WL_FAILURE = -1, 34 | WL_SUCCESS = 1, 35 | } wl_error_code_t; 36 | 37 | /* Authentication modes */ 38 | enum wl_auth_mode { 39 | AUTH_MODE_INVALID, 40 | AUTH_MODE_AUTO, 41 | AUTH_MODE_OPEN_SYSTEM, 42 | AUTH_MODE_SHARED_KEY, 43 | AUTH_MODE_WPA, 44 | AUTH_MODE_WPA2, 45 | AUTH_MODE_WPA_PSK, 46 | AUTH_MODE_WPA2_PSK 47 | }; 48 | 49 | #endif //_WL_TYPES_H_ 50 | --------------------------------------------------------------------------------