How to make a remote acquisition system
Added by Marco Trapanese about 13 years ago
Hello, I'm new to wt and I read through the documentation and the examples.
Anyway I need a suggestion how to manage the whole system.
I have an embedded board (arm-based) which collects data from a serial line, storing information on the sd card.
The goal is to create a webserver (in wt) that allow to control the acquisition (start/stop), display real-time data, manage files and so on.
Few questions:
1) is it a good idea to do all in wt? A single application that do everything (like a standard desktop app).
1b) if "yes" I need to maintain alive a section of the software in order to acquire data even when the user is not surfing the webserver. Is there an example on this topic?
2) if "no" what do you recommend to exchange information (commands, status, data to display, etc) between the applications? I know zmq that provides a inter-process communication. But I'd prefer to develop only one application.
Thanks in advance
Replies (11)
RE: How to make a remote acquisition system - Added by Garrett Mc about 13 years ago
Marco,
This documentation page may help:
http://www.webtoolkit.eu/wt/doc/reference/html/classWt_1_1WServer.html#details
-Garrett
RE: How to make a remote acquisition system - Added by Koen Deforche about 13 years ago
Hey,
1) Yes I believe it makes sense for an embedded system. The down-side is the perpetual down-case for integrating things in a single executable: you are more sensitive to bugs. We try our best to harden Wt itself, but nothing beats splitting the risk in two processes.
Integration is ofcourse a lot more pleasant, especially if you want real-time features, with a single process. You might want to start with that and split things later? With that in mind you can already create an interface that would later be the separation point if it is needed.
You can indeed consider a WServer as an object which you can control from another place, as Garrett suggests.
2) I can't make a recommendation from personal experience, but I've heard good words on zmq.
Regards,
koen
RE: How to make a remote acquisition system - Added by Marco Trapanese about 13 years ago
Thank you both for the hints.
I'm going to develop a single exe at first, but keeping in mind that I will split it in the future.
RE: How to make a remote acquisition system - Added by Marco Trapanese almost 13 years ago
Garrett Mc wrote:
This documentation page may help:
http://www.webtoolkit.eu/wt/doc/reference/html/classWt_1_1WServer.html#details
If I understand correctly I may instantiate my own "background" class in the new implementation of WRun.
I added the "myWRun" function like the example of your link and the server still works fine.
Then I create a simple classes (Worker) based upon WObject that does nothing else then update a counter with a WTimer.
At the beginning of myWRun I create a new instance of Worker. The program crashes due to a seg fault when I try to connect the timeout() signal of the WTimer in Worker.
Some code:
int myWRun(int argc, char **argv, ApplicationCreator createApplication) {
Worker *worker = new Worker(0);
try {
WServer server(argv[0]);
server.setServerConfiguration(argc, argv, WTHTTP_CONFIGURATION);
server.addEntryPoint(Wt::Application, createApplication);
if (server.start()) {
int sig = WServer::waitForShutdown(argv[0]);
std::cerr << "Shutdown (signal = " << sig << ")" << std::endl;
server.stop();
if (sig == SIGHUP) WServer::restart(argc, argv, environ);
}
} catch (WServer::Exception &e) {
std::cerr << e.what() << "\n";
return 1;
} catch (std::exception &e) {
std::cerr << "exception: " << e.what() << "\n";
return 1;
}
return 0;
}
int main(int argc, char **argv) {
return myWRun(argc, argv, &createApplication);
}
and here my simple Worker class:
#ifndef WORKER_H
#define WORKER_H
#include <Wt/WObject>
#include <Wt/WTimer>
using namespace Wt;
class Worker: public Wt::WObject {
public:
Worker(Wt::WObject *parent);
private:
void timerISR();
WTimer *timerUpdate;
int64_t m_samples;
};
#endif // WORKER_H
---
#include "worker.h"
Worker::Worker(Wt::WObject *parent) : Wt::WObject(parent) {
timerUpdate = new WTimer(this);
timerUpdate->setInterval(1000);
timerUpdate->timeout().connect(this, &Worker::timerISR); // here I get the seg fault
timerUpdate->start();
m_samples = 0;
}
void Worker::timerISR() {
std::cout << m_samples++ << std::endl;
}
RE: How to make a remote acquisition system - Added by Vyacheslav Blinov almost 13 years ago
This is due to fact that timeout is an EventSignal and can be used only in WApplication`s main loop.
See http://www.webtoolkit.eu/wt/doc/reference/html/classWt_1_1EventSignal.html#details
RE: How to make a remote acquisition system - Added by Marco Trapanese almost 13 years ago
Ok, but of course I need eventsignals in my background worker in order to perform activities such as logging, data reading, etc when the user is not visiting the webserver (i.e. the main WApplication is not running).
What do you do usually?
I'm thinking about a dummy WApplication to provide a main loop. Will I be able to exchange data and call functions between the two WApplications?
RE: How to make a remote acquisition system - Added by Vyacheslav Blinov almost 13 years ago
I don`t clearly see that for you need EventSignals in background worker, I think simple Signals is enouth. Note that EventSignals is depends of JavaScript which runs on clientside in WApplication.
In my vision your problem can be solved like this:
Worker starts it`s dirty work in another thread in background. If you need to check for some kind of timer in your worker thread I think you will need your own event loop or state machine inside it.
Meanwhile WServer listens for WApplications and then needed will create WApplication with control/statistics interface. Thenever needed WApplication will access YourServer::instance()worker>doSomething (which should be aware of the fact multiple applications can access single Worker simulatiously and that Worker has it`s own background thread waiting for data).
RE: How to make a remote acquisition system - Added by Vyacheslav Blinov almost 13 years ago
listens for WApplications
listens for socket of course :)
RE: How to make a remote acquisition system - Added by Marco Trapanese almost 13 years ago
Thank you for your answer.
Using different threads doesn't make things similar to use different processes? As Koen suggested it would be easier to have a single "entity" which does both jobs, allowing to exchange data with no difficult.
It seems Wt doesn't provide a WThread class (like Qt) so I assume I need to use boost::thread.
I cannot imagine an acquisition system that doesn't work with timers! One for polling the serial, another for the timeout, another to log data, ...
Instead to reinvent the wheel (er.. the main loop) is it possible to enable a reliable main loop (Wt or Qt) inside the worker thread?
RE: How to make a remote acquisition system - Added by Marco Trapanese almost 13 years ago
I managed to create a working example, but I it's very ugly.
I created a class that embed a boost::thread. This class is declared as global in an header file included in all others.
In the main() I start the worker thread.
In the WApplication I can "see" the worker class and through functions I can read and write the variables I need.
I know it's a very bad solution because it uses global variables, it isn't thread safe and currently the worker class has an infinite loop without any exit condition... anyway it works and does what I want.
RE: How to make a remote acquisition system - Added by Wim Dumon almost 13 years ago
In new Wt versions (I believe since 3.2.0), you can use WIOService for server-side timers. Basically, you schedule your function, and a thread of Wt's thread pool will execute it after the time has elapsed. See this:
http://www.webtoolkit.eu/wt/doc/reference/html/classWt_1_1WIOService.html#af21d302bdae0011e84f921b155d9a40d
Regards,
Wim.