arkhipenko / TaskScheduler

Cooperative multitasking for Arduino, ESPx, STM32, nRF and other microcontrollers
http://playground.arduino.cc/Code/TaskScheduler
BSD 3-Clause "New" or "Revised" License
1.22k stars 224 forks source link

Multiple declarations issue after following the OO example #93

Closed curieos closed 4 years ago

curieos commented 4 years ago

I'm having issues with multiple declarations in Platform.io on the ESP32. My code seems to be identical to the example, but it fails to link. I would try the example code to sanity check, but PIO doesn't make that the easiest thing.

It's saying all the Task and Scheduler methods are being redefined. These are my header files that are relevant.

restserver.h

#ifndef RESTSERVER_H
#define RESTSERVER_H

#define _TASK_TIMEOUT
#define _TASK_OO_CALLBACKS

#include <ESPAsyncWebServer.h>
#include <TaskScheduler.h>

#include "config.h"
#include "moduleservice.h"
#include "plantservice.h"

class RestServer {
public:
    ModuleService* GetModuleService() { return module_service; }
    PlantService* GetPlantService() { return plant_service; }

    RestServer(AsyncWebServer *server);
    ~RestServer();
private:
    Scheduler *scheduler;
    ModuleService *module_service;
    PlantService *plant_service;
};

#endif

plantservice.h:

#ifndef PLANTSERVICE_H
#define PLANTSERVICE_H

#define _TASK_TIMEOUT 
#define _TASK_OO_CALLBACKS

#include <Adafruit_Sensor.h>
#include <Adafruit_AM2320.h>
#include <TaskSchedulerDeclarations.h>

#include "config.h"

class PlantService : public Task {
public:
    bool Callback();

    void CheckSensors();
    void GetPlantInfo(char* info);

    PlantService(Scheduler* scheduler);
    ~PlantService() {};
private:
    Adafruit_AM2320* am2320;
    float temperature;
    float humidity;
};

#endif
arkhipenko commented 4 years ago

The only place where you include<TaskScheduler.h> is in the main .INO file. Every other header file should be using <TaskSchedulerDeclarations.h> Your restserver.h includes the former.

Hope this helps.

curieos commented 4 years ago

I'm not using the scheduler in my main file, just in restserver and its objects. I'd prefer to make the scheduler inside the rest server, mainly because it's only needed there.

arkhipenko commented 4 years ago

Well, you are including TaskScheduler twice somewhere or Platform.io does it for you. I do not use Platform.io - found it to be difficult to set up for I need to do. Try to see if that is the case -OR- send me your code (all of it) to arkhipenko@hotmail.com - I won;t be able to help you based on just 2 header files.

curieos commented 4 years ago

Code can be found in this repo. Ignore the outdated Readme.

arkhipenko commented 4 years ago

Can you try including once in the main.cpp and everywhere else? See if this resolves the compile problem.

On a separate note - your code does not really use task scheduler, definitely not the way it is intended to be used, so most probably won't work even if compiles.

The philosophy of TaskScheduler is that it is the scheduler. All your actions are tasks and therefore classes derived from the Task. You define the conditions by which the tasks are invoked and let the scheduler do the coordination. I do not recommend using TS with other scheduling tools (with one exception - FreeRTOS on ESP32, but even that is still experimental).

arkhipenko commented 4 years ago

Have a look at this: https://github.com/arkhipenko/IoT_apis2.git Not an OO approach - but similar hardware and tasks - running a web server while reading sensors. All on TS. Please note that as mentioned above, TS is the only scheduler.

curieos commented 4 years ago

I know I'm not calling execute, I was first setting things up and making sure it compiled. I'm pretty sure I'm using delay at points where it doesn't matter for multi-tasking, like before a restart to be sure an HTTP response sends, at the beginning of execution to give me a chance to connect with the serial console before debug output flies by, etc. Besides this, I know the code is a little rough, mostly trying to get a proof of concept running.

I think have a solution to my own problem, but I was trying to avoid creating the scheduler in the main file since it's not really needed anywhere other than the rest server.

curieos commented 4 years ago

I made the change, but I'm getting a new error

.pio/build/huzzah/src/plantservice.cpp.o:(.literal._ZN12PlantServiceC2EP9Scheduler+0x8): undefined reference to `Task::Task(unsigned long, long, Scheduler*, bool)'
.pio/build/huzzah/src/plantservice.cpp.o: In function `PlantService::PlantService(Scheduler*)':
/private path/Grow.local/grow-local-esp/grow.local/src/plantservice.cpp:30: undefined reference to `Task::Task(unsigned long, long, Scheduler*, bool)'
.pio/build/huzzah/src/plantservice.cpp.o:(.rodata._ZTV12PlantService[vtable for PlantService]+0x14): undefined reference to `Task::OnEnable()'
.pio/build/huzzah/src/plantservice.cpp.o:(.rodata._ZTV12PlantService[vtable for PlantService]+0x18): undefined reference to `Task::OnDisable()'

Code for plantservice.cpp hasn't changed

curieos commented 4 years ago

Oops, I forgot to include the defines for the configuration in the main file. It compiles now.

arkhipenko commented 4 years ago

Great. I am closing this issue then. Good luck!