Why does OpenSprinkler Firmware (for ESP8266) compile in VisualMicro and Arduino but not in this?

Hello and thank you for reading!

I’ve managed to get it running after installing the four libraries (SSD1306, RCSwitch, pubsubclient and UIPEthernet) in VisualMicro with forward declarations and enabling “deep search for libraries + accurate prototype insertion” and “local files override library files” so that “includes via Gcc”

Now I tried the same with Platformio by trying all permutations of lib_ldf_mode = chain/deep&+.

Still… a lot of only this kind of errors:

C:\Users\me\Documents\Arduino\libraries\UIPEthernet/UIPServer.h:42:35: error: expected class-name before '{' token
   class UIPServer : public Server {
                                   ^
C:\Users\me\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.7.4\libraries\ESP8266WiFi\src/WiFiServer.h:97:16: error: type 'Print' is not a base type for type 'WiFiServer'     
   using Print::write;
                ^
C:\Users\me\Documents\Arduino\libraries\UIPEthernet/UIPServer.h:59:16: error: type 'Print' is not a base type for type 'UIPServer'
   using Print::write;

but Dependency Graph is

|-- <Wire> 1.0
|-- <INA219>
|   |-- <Wire> 1.0
|-- <rc-switch> 2.6.3
|-- <ESP8266SdFat> 1.1.0
|   |-- <SPI> 1.0
|-- <SPI> 1.0
|-- <Time> 1.6
|-- <UIPEthernet>
|   |-- <SPI> 1.0
|-- <ESP8266_SSD1306> 4.1.0
|   |-- <SPI> 1.0
|   |-- <Wire> 1.0
|-- <ESP8266WebServer> 1.0
|   |-- <ESP8266WiFi> 1.0
|-- <ESP8266WiFi> 1.0
|-- <PubSubClient> 2.8

like in Arduino:

Using library Wire at version 1.0 in folder: C:\Users\me\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.7.4\libraries\Wire 
Using library SPI at version 1.0 in folder: C:\Users\me\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.7.4\libraries\SPI 
Using library UIPEthernet at version 2.0.9 in folder: C:\Users\me\Documents\Arduino\libraries\UIPEthernet 
Using library rc-switch at version 2.6.3 in folder: C:\Users\me\Documents\Arduino\libraries\rc-switch 
Using library ESP8266_and_ESP32_OLED_driver_for_SSD1306_displays at version 4.1.0 in folder: C:\Users\me\Documents\Arduino\libraries\ESP8266_and_ESP32_OLED_driver_for_SSD1306_displays 
Using library ESP8266WiFi at version 1.0 in folder: C:\Users\me\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.7.4\libraries\ESP8266WiFi 
Using library ESP8266WebServer at version 1.0 in folder: C:\Users\me\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.7.4\libraries\ESP8266WebServer 
Using library ArduinoINA219 at version 1.0.4 in folder: C:\Users\me\Documents\Arduino\libraries\ArduinoINA219 
Using library PubSubClient at version 2.8 in folder: C:\Users\me\Documents\Arduino\libraries\PubSubClient 

What am I doing wrong and why is this so hard in this “best IDE for embedded”?

PS: platformio.ini:

[env:d1_mini_lite]
platform = espressif8266
board = d1_mini_lite
framework = arduino
lib_extra_dirs = 
    ~/Documents/Arduino/libraries
    C:/Users/me/AppData/Local/arduino15/packages/esp8266/hardware/esp8266/2.7.4/libraries
; evaluate C/C++ Preprocessor conditional syntax
lib_ldf_mode = deep

PPS: I’m trying to make the OpenSprinkler project more accessible to the community and would really apprechiate your support!

PlatformIO has a library registry where these libs can be sourced from without ever relying on Arduino or harcoded paths.

Regarding the problem: I think there’s just a header file conflict between Arduino/cores/esp8266/Server.h at master · esp8266/Arduino · GitHub and https://github.com/OpenSprinkler/OpenSprinkler-Firmware/blob/master/server.h.

Windows filesystem is from the stone age and case-insensitive – server.h = Server.h. Would probably build on Linux.

Currently using the platformio.ini

[env:d1_mini_lite]
platform = espressif8266
board = d1_mini_lite
framework = arduino
lib_ldf_mode = deep
lib_deps =
     uipethernet/UIPEthernet @ ^2.0.8
     sui77/rc-switch @ ^2.6.3
     squix78/ESP8266_SSD1306 @ ^4.1.0

and investigating the error above by a small refactor.

1 Like

Yeah the problem was as I said. After refactoring server.h to opensprinkler_server.h and adding the PubSub library, it compiles without problems. One just needs to respect the filesystem of the OS.

See GitHub - maxgerhardt/pio-opensprinkler-Firmware: PIO compilable version of https://github.com/OpenSprinkler/OpenSprinkler-Firmware/

Note: By using platformio.ini directives such as src_dir and friends, one can also surely just fork the original repo and add the platformio.ini to it plus the server refactor, while leaving every other file untouched.

In any case, the compile error is solved.

1 Like

Ho- ly sh*t! Thank you so much! I read something like that before but wasn’t thinking about it while banging my head against the keyboard :confused:

I’m looking forward to work with this supposedly great product :smiley: with an awesome community :tada:

1 Like

FYI I implemented the thing with src_dir and created the pull-request Make firmware PlatformIO compilable by maxgerhardt · Pull Request #158 · OpenSprinkler/OpenSprinkler-Firmware · GitHub.

Just adds one file and adds one minor refactor without changing anything else, and the firmware compiles for ESP8266 and PlatformIO :slight_smile:

PS: To circle back to the original question: There is also the possibility that it compiles on Windows without changing the conflicting file names, when the gcc include direction options -I are ordered in such a way that when the firmware gets built, the server.h in the firmware folder is found but when the Arduino-ESP8266 library is built, the Server.h in the library folder is found… Very tricky and hacky though. The small rename makes it bulletproof against these build-system differences.

2 Likes

Thank you!

Hopefully they will merge it and save the next person the hassle!

Why did you add this to opensprinkler_server.h?
os-server-git

#include <Arduino.h>
#include <utils.h>

Somehow it compiled without it, but I have not tested if it works in silico yet!

Yes it compiles without it but it’s cleaner to have it with it.

The header file uses types and functions which it does not include (pgm_read_byte(), file_read_block(), strlen()). So this only works because the .cpp file that includes the server header includes the headers it needs before it. This is not my understanding of good code. The header should include all needed types and be valid “standalone”, includable from everywhere without having a needed previous #include sequence. So that’s just cleanup.

2 Likes

How did you do the structure in your demo Git? Is it no coincidence it’s not a fork?

In mine you can’t see the structure + .ini — is this not easily possible from a fork?

PS: my .gitignore

.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch

The folder structure created here is the default PlatformIO folder structure when creating a new project (either by the VSCode GUI or directly pio init -b <board> on the commandline). See e.g. the basic Arduino-AVR Blink example. In-depth explanaion of the meaning of those folders is explained in the docs – well to make it short, the folders seperate include / header files (not-compiled files) in include/, the main source code in src/, library folders in lib/ and unit-testing code in test/, while the platformio.ini configuration is on top of all of it; not much more.

Yes you can still move folders around in a fork without problems, but I thought of that as too intrusive, which is why I applied the same compilation fixes and an adapted platformio.ini to a real fork of the project at GitHub - maxgerhardt/OpenSprinkler-Firmware: OpenSprinkler Unified Firmware for OpenSprinkler, OpenSprinkler Pi, and OpenSprinkler Beagle..

The directives are explained above for redirecting / redifining the usual “src” and “include” folders to be less intrusive.

Here I think it’s also mandatory because the project has Makefiles and those would break if the files were in different paths (without those makefiles being adapted)

1 Like

@maxgerhardt thank you for your thorough and motivated answer!

Damn, I asked the wrong question :sweat_smile:

As a quick fix, I copied pio.ini into the src dir and pushed it with your adaptions added. If I delete the original project-root pio.ini, unsurprisingly nothing works anymore.

So I guess my real question is, how to make sure others can use my git in PlatformIO without much hassle. I have not tried if this fixes it for others, but I have to manually update two pio.ini’s for the time beeing.

My project structure in pio has everything in the repo in src.

PS: To give you a bit of background what I’m trying to achieve: I want to make my bachelors thesis a reference for home made irrigation taylor-made to one’s needs and intend to refer to pio and my fork for the software.

It does not matter how the folder structure of the project is as long as the platformio.ini is adapted to build with it. A PlatformIO project is any folder which has a platformio.ini inside it. Both GitHub - maxgerhardt/OpenSprinkler-Firmware: OpenSprinkler Unified Firmware for OpenSprinkler, OpenSprinkler Pi, and OpenSprinkler Beagle. and GitHub - maxgerhardt/pio-opensprinkler-Firmware: PIO compilable version of https://github.com/OpenSprinkler/OpenSprinkler-Firmware/ are valid PlatformIO projects which can be used with the “Import Open Project” button in VSCode or with the PlatformIO commandline tools (pio run, pio run -t upload) at any time. It’s just that the folder structure in the latter repository is the “traditional” one with which the “standard” PlatformIO user is accustomed with, which is however not the one of the original project – just a style preference.

Or did I misunderstand the question?

Just as I did in my first-posted repository.

1 Like

Thank you @maxgerhardt, just cloned it again and it just works! I wish you all the best! Thank you so much again!

PS: “Open Project” not “Import Arduino Project” (skips name check for future reference)

1 Like