124 lines
2.4 KiB
C++
124 lines
2.4 KiB
C++
#include <boost/asio.hpp>
|
|
|
|
#include <sys/socket.h>
|
|
#include <netdb.h>
|
|
#include <cstdint>
|
|
#include <thread>
|
|
#include <atomic>
|
|
#include <queue>
|
|
#include <mutex>
|
|
#include <chrono>
|
|
#include <condition_variable>
|
|
|
|
#include "engine.hpp"
|
|
|
|
using namespace std;
|
|
using boost::asio::ip::tcp;
|
|
using boost::asio::io_service;
|
|
|
|
template <typename T>
|
|
class prodcon
|
|
{
|
|
private:
|
|
mutex mut;
|
|
condition_variable condition;
|
|
queue<T> q;
|
|
public:
|
|
void push(T data)
|
|
{
|
|
unique_lock<mutex> lock(mut);
|
|
q.push(data);
|
|
condition.notify_one();
|
|
}
|
|
template<typename _Rep, typename _Period>
|
|
bool pop(T &result, const chrono::duration<_Rep, _Period> __rtime)
|
|
{
|
|
unique_lock<mutex> lock(mut);
|
|
bool success = condition.wait_for(lock, __rtime, [this] {return !this->q.empty();});
|
|
if (!success)
|
|
return false;
|
|
result = q.front();
|
|
q.pop();
|
|
return true;
|
|
}
|
|
};
|
|
|
|
class remote_server
|
|
{
|
|
private:
|
|
tcp::acceptor acceptor;
|
|
io_service &io;
|
|
thread engine_thread;
|
|
atomic<bool> stop_thread;
|
|
prodcon<pair<int8_t, int8_t>> commands;
|
|
public:
|
|
remote_server(io_service &io_service);
|
|
void run();
|
|
void engine_loop();
|
|
};
|
|
|
|
int main()
|
|
{
|
|
io_service io;
|
|
remote_server server(io);
|
|
server.run();
|
|
return 0;
|
|
}
|
|
|
|
remote_server::remote_server(io_service &io_service)
|
|
: acceptor(io_service),
|
|
io(io_service),
|
|
stop_thread(false)
|
|
{
|
|
// Nothing to do
|
|
}
|
|
|
|
void remote_server::run()
|
|
{
|
|
tcp::endpoint endpoint(tcp::v4(), 1337);
|
|
acceptor.open(endpoint.protocol());
|
|
acceptor.set_option(tcp::acceptor::reuse_address(true));
|
|
acceptor.bind(endpoint);
|
|
acceptor.listen(1);
|
|
while (true)
|
|
{
|
|
tcp::socket socket(io);
|
|
acceptor.accept(socket);
|
|
stop_thread = false;
|
|
engine_thread = thread(&remote_server::engine_loop, this);
|
|
while (true)
|
|
{
|
|
int8_t speed_left, speed_right;
|
|
socket.read_some(boost::asio::buffer(&speed_left, 1));
|
|
socket.read_some(boost::asio::buffer(&speed_right, 1));
|
|
commands.push(pair<int8_t, int8_t>(speed_left, speed_right));
|
|
}
|
|
}
|
|
}
|
|
|
|
void remote_server::engine_loop()
|
|
{
|
|
engine left(
|
|
gpio(13, gpio::pin_direction::OUTPUT, gpio::pin_type::LOW_ON),
|
|
gpio(20, gpio::pin_direction::OUTPUT, gpio::pin_type::LOW_ON)
|
|
);
|
|
engine right(
|
|
gpio(19, gpio::pin_direction::OUTPUT, gpio::pin_type::LOW_ON),
|
|
gpio(26, gpio::pin_direction::OUTPUT, gpio::pin_type::LOW_ON)
|
|
);
|
|
while (!stop_thread)
|
|
{
|
|
pair<int8_t, int8_t> command;
|
|
if (commands.pop(command, 1s))
|
|
{
|
|
left.set_speed(command.first);
|
|
right.set_speed(command.second);
|
|
}
|
|
else
|
|
{
|
|
left.set_speed(0);
|
|
right.set_speed(0);
|
|
}
|
|
}
|
|
}
|