Skip to content

Commit

Permalink
add a basic http server to host the client app, add README and launch…
Browse files Browse the repository at this point in the history
….json for vscode debugging
  • Loading branch information
catink123 committed Jan 6, 2024
1 parent 8d65dbf commit d2c0930
Show file tree
Hide file tree
Showing 10 changed files with 570 additions and 1 deletion.
24 changes: 24 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "(msvc) Launch",
"type": "cppvsdbg",
"request": "launch",
// Resolved by CMake Tools:
"program": "${command:cmake.launchTargetPath}",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
// add the directory where our target was built to the PATHs
// it gets resolved by CMake Tools:
"name": "PATH",
"value": "${env:PATH}:${command:cmake.getLaunchTargetDirectory}"
}
],
"console": "integratedTerminal"
}
]
}
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ set(GATE_CONTROL_PROJECT_NAME GateControl)
set(GATE_CONTROL_SOURCE_DIR src)

set(GATE_CONTROL_SOURCE
${GATE_CONTROL_SOURCE_DIR}/common.hpp
${GATE_CONTROL_SOURCE_DIR}/main.cpp
${GATE_CONTROL_SOURCE_DIR}/http_listener.hpp
${GATE_CONTROL_SOURCE_DIR}/http_listener.cpp
${GATE_CONTROL_SOURCE_DIR}/http_session.hpp
${GATE_CONTROL_SOURCE_DIR}/http_session.cpp
)

include("cmake/modules/CPM.cmake")
Expand Down
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Gate Control

Gate Control is a client-server application that allows control of an Arduino microcontroller over the local network.

## Building

There are two ways of getting built server binaries: manual build and release build.

### Manual build

First, clone the repo to your local machine:

```sh
$ git clone https://github.com/catink123/gate-control
$ cd gate-control
```

Then, run CMake (version >= 3.14) in the repo's root directory with one of the provided presets:

```sh
$ cmake --build --preset <build-preset>
```

Substitute `<build-preset>` with the chosen preset. Available presets can be obtained using the following command:

```sh
$ cmake --list-presets
```

After CMake successfully builds the server, the binaries should be located in the `out/<build-preset>` directory.

### Release build

You can obtain prebuilt binaries from the [Releases tab](https://github.com/catink123/gate-control/releases).

## Architecture

The server acts as a bridge between a user on the network and the USB-connected Arduino microcontroller.

The server hosts a client application, available at it's address. A user can enter the server's address in the web browser and access the remote control panel for the microcontroller.

Arduino microcontroller acts as a gate control, or in other words it holds information about the physical state of the gate and allows to change that state (raise or lower the gate).
11 changes: 11 additions & 0 deletions src/client/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gate Control</title>
</head>
<body>
<h1>Test Client Page</h1>
</body>
</html>
16 changes: 16 additions & 0 deletions src/common.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef COMMON_HPP
#define COMMON_HPP

#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/asio/dispatch.hpp>
#include <boost/asio/strand.hpp>
#include <boost/config.hpp>
#include <iostream>

namespace beast = boost::beast;
namespace http = beast::http;
namespace net = boost::beast::net;
using tcp = net::ip::tcp;

#endif
66 changes: 66 additions & 0 deletions src/http_listener.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include "http_listener.hpp"

http_listener::http_listener(
net::io_context& ioc,
tcp::endpoint endpoint,
const std::shared_ptr<const std::string>& doc_root
) : ioc(ioc),
acceptor(net::make_strand(ioc)),
doc_root(doc_root)
{
beast::error_code ec;

acceptor.open(endpoint.protocol(), ec);
if (ec) {
std::cerr << "Couldn't open acceptor: " << ec.message() << std::endl;
return;
}

acceptor.set_option(net::socket_base::reuse_address(true), ec);
if (ec) {
std::cerr << "Couldn't set reuse_address: " << ec.message() << std::endl;
return;
}

acceptor.bind(endpoint, ec);
if (ec) {
std::cerr << "Couldn't bind to endpoint: " << ec.message() << std::endl;
return;
}

acceptor.listen(
net::socket_base::max_listen_connections, ec
);
if (ec) {
std::cerr << "Couldn't start listening: " << ec.message() << std::endl;
return;
}
}

void http_listener::run() {
do_accept();
}

void http_listener::do_accept() {
acceptor.async_accept(
net::make_strand(ioc),
beast::bind_front_handler(
&http_listener::on_accept,
shared_from_this()
)
);
}

void http_listener::on_accept(beast::error_code ec, tcp::socket socket) {
if (ec) {
std::cerr << "Couldn't accept incoming connection: " << ec.message() << std::endl;
return;
}

std::make_shared<http_session>(
std::move(socket),
doc_root
)->run();

do_accept();
}
29 changes: 29 additions & 0 deletions src/http_listener.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef HTTP_LISTENER_HPP
#define HTTP_LISTENER_HPP

#include <nlohmann/json.hpp>
#include <memory>
#include <string>
#include "common.hpp"
#include "http_session.hpp"

class http_listener : public std::enable_shared_from_this<http_listener> {
net::io_context& ioc;
tcp::acceptor acceptor;
std::shared_ptr<const std::string> doc_root;

public:
http_listener(
net::io_context& ioc,
tcp::endpoint endpoint,
const std::shared_ptr<const std::string>& doc_root
);

void run();

private:
void do_accept();
void on_accept(beast::error_code ec, tcp::socket socket);
};

#endif

0 comments on commit d2c0930

Please sign in to comment.