Code Monkey home page Code Monkey logo

soapesp32's Introduction

SoapESP32

This Arduino library provides basic UPnP/SOAP functionality, enabling an ESP32 device to scan the local network for DLNA media servers, browse their content and finally download files.

Motivation for writing it was the missing capability of an existing ESP32-Radio (based on Ed Smallenburg's code) to play audio content stored on the various NAS devices in the local network at home (most of them running a DLNA server).

The library has been successfully tested so far with the following DLNA media servers: DiXim, Twonky, UMS (Universal Media Server), Jellyfin, Emby, Kodi, Plex, Serviio, Subsonic, MinimServer, QNAP-DLNA and Windows Media Player.

Integrating this library into your ESP32 Arduino projects is easy. Here e.g. the basics for searching and printing media servers in your local network. For detailed info have a look at the many examples included.

...
#include "SoapESP32.h"

WiFiClient client;
WiFiUDP    udp;

SoapESP32    soap(&client, &udp);
soapServer_t srv;
uint8_t      srvNum = 0;

setup() {
  // setting up Wifi, serial output, etc.
  ...
  // searching local network for media servers
  soap.seekServer();
  // printing details of all discovered servers
  while (soap.getServerInfo(srvNum++, &srv)) {
    Serial.print("Server name: ");
    Serial.println(srv.friendlyName);
    ...
  }
}
...

โšก Application notes

To install SoapESP32 into your Arduino IDE you can use the Library Manager. Open the IDE and click to the Sketch menu and then Include Library > Manage Libraries. Search for SoapESP32, select the newest release and click on install.

In VSCode/PlatformIO click the platformio sidebar icon, open the libraries view and search for SoapESP32. Once found, select the newest release and click on Add to Project.

Always make sure you have one of the latest versions of Arduino core for ESP32 installed in your IDE. Older versions might produce build errors with some examples.

As of Version 1.1.0 the struct soapObject_t has seen two modifications:
Firstly, the type of member variable size has changed from size_t to uint64_t. If used in your projects, you might have to adjust some code. Secondly, a new member variable sizeMissing (boolean) has been added.

Most DLNA media servers I tested the library with showed some oddities. All compatibility issues I ran across have been fixed. Please note the following:

  • Streams/podcasts: Some media servers (e.g. Fritzbox, Serviio) do not provide a size for items (media content) located in their Web/Online/InternetRadio folders. Thanks to Github user KiloOscarRomeo for drawing my attention to this fact. In contrast, UMS (Universal Media Server) always provides a fixed size=9223372034707292159 for items in directory Web (incl. subdirectories Radio, Podcasts, etc.).

  • Empty files: Some media servers (MS MediaPlayer/Kodi/Jellyfin) show empty files, others don't. This library by default ignores files with reported size zero. They will not show up in browse results. You can change this behaviour with build option SHOW_EMPTY_FILES.

  • Empty directories: They always show up in browse results.

  • Missing attribute size: Media servers often show items without telling their size. That applies to all item types: streams, video files, audio files, image files, etc. In this case the library will return them in browse results with size=0 and sizeMissing=true.

  • Missing attributes child count & searchable: Some servers report container (directories) with child count 0 or missing attribute child count when in fact they are not empty. Same applies to attribute searchable. This is very annoying for it forces you to dig into each (sub)directory not to overlook anything.

  • Parent-ID Mismatch: The id of a directory and the parent id of it's content should match. Sometimes it does not (e.g. Subsonic). As of V1.1.1 this mismatch is ignored by default. You can go back to strict behaviour with build option PARENT_ID_MUST_MATCH

  • Downloading big files/reading streams: Files with reported size bigger than 4.2GB (SIZE_MAX) will be shown in browse results but an attempt to download them with readStart()/read()/readEnd() will fail. If you want to download them or read endless streams you will have to do it outside this library in your own code.

If you run into trouble with your particular DLNA media server or NAS, increase CORE_DEBUG_LEVEL and it gives you an indication where the problem is. Tracing the communication with Wireshark can help as well.

โ— Using W5x00 Ethernet shield/boards instead of builtin WiFi (optional)

Using a Wiznet W5x00 board and the standard Arduino Ethernet lib for communication produced some sporadic issues. Especially client.read() calls returned corrupted data every now and then, esp. with other threads using the SPI bus simultaneously. This problem is mentioned a few times in forums on the internet, so it seems to be a known ESP32 Arduino SPI library issue.

The only remedy I found was to wrap all function calls that use SPI with a global/project wide mutex lock (realized within this library with the aid of claimSPI()/releaseSPI()). This completely wiped all those problems. See example UsingMutexLocks_Ethernet.ino for more details.

Of course, the ESP32 Arduino SPI library already uses locks (SPI_MUTEX_LOCK/SPI_MUTEX_UNLOCK) but doesn't seem to be 100% thread proof though. Please correct me if I'm wrong or you do find a better solution.

Ethernet SSDP multicast issue:

SSDP M-SEARCH multicast packets carry the destination ip 239.255.255.250 and port 1900. However, some NAS devices do not reply to such packets when the source port is 1900 as well. Unfortunately when using the standard Arduino Ethernet library, all SSDP multicast packets carry identical destination & source ports, in our case 1900. There are two solutions to this problem:

a) use addServer() to manually add a server to the server list, which I recommend or

b) modify "socket.cpp" in Arduino Ethernet library to use a source port between 49152 & 65535. Which is not only a dirty solution, it puts you under risk to forget about it and then lose those changes with a later Ethernet lib update.

uint8_t EthernetClass::socketBeginMulticast(uint8_t protocol, IPAddress ip, uint16_t port)
{
  ...
  if (port > 0 && (protocol != (SnMR::UDP | SnMR::MULTI))) {	 // <------ modification 
    W5100.writeSnPORT(s, port);
  } else {
    // if don't set the source port, set local_port number.
    if (++local_port < 49152) local_port = 49152;
    W5100.writeSnPORT(s, local_port);
  }
  ...

๐Ÿ› ๏ธ Setting compiler/build options:

All examples were build & tested with ArduinoIDE V1.8.9 and VSCode/PlatformIO.

If possible, always set project wide preprocessor option __GNU_VISIBLE which enables usage of strcasestr() provided in string.h. However, if __GNU_VISIBLE is not defined, a quick and dirty version of strcasestr() defined in SoapESP32.cpp will be used instead.

If you use an Ethernet module/shield instead of builtin WiFi you must set the preprocessor option USE_ETHERNET. Otherwise the build will fail.

Arduino IDE:

Unfortunately we can't set project wide build options in *.ino sketches. So the easiest way is to uncomment the line //#define USE_ETHERNET in SoapESP32.h. Alternatively you could add any needed build options to line compiler.cpreprocessor.flags in your Arduino IDE file platform.txt. On my PC for example I find this file in directory:

  • C:\Users\tj\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4

Be reminded, those options will stay permanent until you delete them!

VSCode/PlatformIO:

Simply put build options to your platformio.ini project file, e.g.: build_flags = -D__GNU_VISIBLE, -DUSE_ETHERNET

๐Ÿ” How to find correct server parameters needed in some examples

Four examples, BrowseRecursively_Ethernet.ino, BrowseRecursively_WiFi.ino, DownloadFileExample1_Ethernet.ino and DownloadFileExample1_WiFi.ino require some parameters (that apply to your specific DLNA media server) be defined manually. The three snapshots Using_VLC_to_find.....parameter.JPG in folder Doc show you how to use the open source VLC media player to find the right values.

๐Ÿ“ Documentation

Folder Doc contains a big collection of files to help you implement this library into your projects:

  • The platformio.ini file I used when testing examples with VSCode/PlatformIO
  • Build log
  • Log files (serial monitor output) of all examples, mostly with different core debug levels
  • Schematic diagram (wiring) plus picture of the test set used
  • VLC snapshots to help you find server & file download parameters needed for above mentioned examples

๐ŸŽ‰ Example of an implementation: ESP32-Radio using SoapESP32

After merging this library with my ESP32-Radio project I don't have to fiddle around with SD cards anymore. Using the rotary switch encoder is all it needs to browse through the content of a DLNA media server in the local network and select an audio file. After selecting the file, the radio simply reads the data from the server and writes it into the queue which feeds the audio codec VS1053B.

The following picture sequence shows how the library has been implemented:

github

Alternatively have a look at the short clip ESP32-Radio-DLNA.mp4 in folder Doc to see the final implementation in action. To watch now, click Here

soapesp32's People

Contributors

yellobyte avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.