|
2 | 2 | #include "Drives.hpp"
|
3 | 3 | #include "wifi_ap.hpp"
|
4 | 4 | #include "library_extension.hpp"
|
| 5 | +#include "EnvironmentRecord.hpp" |
| 6 | +#include "WebserverHandle.hpp" |
5 | 7 | #include <assert.h>
|
6 | 8 | #include <ESP8266WebServer.h>
|
7 |
| -#include <atomic> |
8 | 9 | #include <algorithm>
|
| 10 | +#include <functional> |
9 | 11 |
|
| 12 | +static EnvironmentRecord environmentRecord; |
10 | 13 | static ESP8266WebServer server(80);
|
11 |
| - |
12 |
| -static struct |
13 |
| -{ |
14 |
| - bool isTargetNew = false; |
15 |
| - drives::Counter newDrive = 0; |
16 |
| - bool forward = true; |
17 |
| - drives::Counter newRotate = 0; |
18 |
| - bool clockwise = true; |
19 |
| -} newTarget; |
20 |
| - |
21 |
| -static constexpr std::size_t numberOfPositions = 50; |
22 |
| -static Position positions[numberOfPositions] = { {0,0} }; |
23 |
| -static std::size_t positionIndex = 0; |
24 |
| - |
25 |
| -static constexpr char htmlSourceTemplate[] = |
26 |
| - "<!DOCTYPE html>\n" |
27 |
| - "<html lang=\"en\">\n" |
28 |
| - " <head>\n" |
29 |
| - " <title>Robot Control</title>\n" |
30 |
| - " <meta charset=\"utf-8\" />\n" |
31 |
| - " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.6\">\n" |
32 |
| - " <meta http-equiv=\"refresh\" content=\"5\">\n" |
33 |
| - " </head>\n" |
34 |
| - " <body>\n" |
35 |
| - " <main>\n" |
36 |
| - " <form method=\"post\" action=\"/\">\n" |
37 |
| - " <table>\n" |
38 |
| - " <tbody align=center valign=middle>\n" |
39 |
| - " <tr><td></td><td><button type=\"submit\" name=\"forwards\" value=\"10\" title=\"+37,70mm\">↑</button></td><td></td></tr>\n" |
40 |
| - " <tr><td><button type=\"submit\" name=\"left\" value=\"5\" title=\"-86,4°\">↺</button></td><td>🤖</td><td><button type=\"submit\" name=\"right\" value=\"5\" title=\"+86,4°\">↻</button></td></tr>\n" |
41 |
| - " <tr><td></td><td><button type=\"submit\" name=\"backwards\" value=\"10\" title=\"-37,70mm\">↓</button></td><td></td></tr>\n" |
42 |
| - " </tbody>\n" |
43 |
| - " </table>\n" |
44 |
| - " </form>\n" |
45 |
| - " <img style=\"max-width:90vw; max-height:100vh;\" src=\"https://david.hebbeker.info/robot-control.php?positions=%s\" />\n" |
46 |
| - " </main>\n" |
47 |
| - " </body>\n" |
48 |
| - "</html>"; |
49 |
| - |
50 |
| - |
51 |
| -constexpr std::size_t maxCharPerPosition = (5+1)*2; //!< when serializing the position, the number of characters maximum used per position |
52 |
| -constexpr std::size_t positionsStringMaxLength = maxCharPerPosition*numberOfPositions+1; |
53 |
| - |
54 |
| -static char htmlSourceBackBufferA[size(htmlSourceTemplate) + positionsStringMaxLength] = {0}; |
55 |
| -static char htmlSourceBackBufferB[size(htmlSourceTemplate) + positionsStringMaxLength] = {0}; |
56 |
| -static std::atomic<const char *> htmlSourceFrontBuffer(htmlSourceTemplate); |
57 |
| - |
58 |
| -void updateHtmlSource() |
59 |
| -{ |
60 |
| - char * const backBuffer = (htmlSourceFrontBuffer.load() == htmlSourceBackBufferA) ? htmlSourceBackBufferB : htmlSourceBackBufferA; |
61 |
| - char positionStringBuffer[positionsStringMaxLength] = { 0 }; |
62 |
| - std::size_t charPos = 0; |
63 |
| - for(std::size_t i=0; i<=positionIndex; i++) |
64 |
| - { |
65 |
| - const int writtenCharacters = snprintf(&(positionStringBuffer[charPos]), maxCharPerPosition+1, "%i;%i;", positions[i].x, positions[i].y); |
66 |
| - assert(writtenCharacters>0); |
67 |
| - charPos += writtenCharacters; |
68 |
| - } |
69 |
| - const int writtenCharacters = snprintf(backBuffer, size(htmlSourceBackBufferA), htmlSourceTemplate, positionStringBuffer); |
70 |
| - assert(writtenCharacters>0); |
71 |
| - htmlSourceFrontBuffer = backBuffer; |
72 |
| -} |
73 |
| - |
74 |
| -static void handleRoot() |
75 |
| -{ |
76 |
| - digitalWrite(board::debugLed, LOW); |
77 |
| - if(server.hasArg("forwards")) |
78 |
| - { |
79 |
| - newTarget.newDrive = server.arg("forwards").toInt(); |
80 |
| - newTarget.forward = true; |
81 |
| - newTarget.isTargetNew = true; |
82 |
| - Serial.printf("Got forwards by %u!\n", newTarget.newDrive); |
83 |
| - } |
84 |
| - if(server.hasArg("backwards")) |
85 |
| - { |
86 |
| - newTarget.newDrive = server.arg("backwards").toInt(); |
87 |
| - newTarget.forward = false; |
88 |
| - newTarget.isTargetNew = true; |
89 |
| - Serial.printf("Got backwards by %u!\n", newTarget.newDrive); |
90 |
| - } |
91 |
| - if(server.hasArg("left")) |
92 |
| - { |
93 |
| - newTarget.newRotate = server.arg("left").toInt(); |
94 |
| - newTarget.clockwise = false; |
95 |
| - newTarget.isTargetNew = true; |
96 |
| - Serial.printf("Got left by %u!\n", newTarget.newRotate); |
97 |
| - } |
98 |
| - if(server.hasArg("right")) |
99 |
| - { |
100 |
| - newTarget.newRotate = server.arg("right").toInt(); |
101 |
| - newTarget.clockwise = true; |
102 |
| - newTarget.isTargetNew = true; |
103 |
| - Serial.printf("Got right by %u!\n", newTarget.newRotate); |
104 |
| - } |
105 |
| - server.send(200, "text/html", htmlSourceFrontBuffer.load()); |
106 |
| - digitalWrite(board::debugLed, HIGH); |
107 |
| -} |
| 14 | +static WebserverHandle webserverHandle(server, environmentRecord); |
108 | 15 |
|
109 | 16 | void setup()
|
110 | 17 | {
|
@@ -164,8 +71,8 @@ void setup()
|
164 | 71 |
|
165 | 72 | server.begin();
|
166 | 73 | Serial.printf("webserver has IP %s\n", WiFi.localIP().toString().c_str());
|
167 |
| - server.on("/", handleRoot); |
168 |
| - updateHtmlSource(); |
| 74 | + server.on("/", std::bind(&WebserverHandle::handleRoot, &webserverHandle)); |
| 75 | + webserverHandle.setup(); |
169 | 76 | }
|
170 | 77 |
|
171 | 78 | static void printSensorStatus(VL53L1GpioInterface* const sensor)
|
@@ -215,24 +122,23 @@ void loop()
|
215 | 122 | if(drives::LeftDrive::isIdle && drives::RightDrive::isIdle)
|
216 | 123 | {
|
217 | 124 | const Position newPositionCandidate = drives::flushCurrentPosition();
|
218 |
| - if(positions[positionIndex] != newPositionCandidate) |
| 125 | + if(environmentRecord.positions[environmentRecord.positionIndex] != newPositionCandidate) |
219 | 126 | {
|
220 |
| - positions[++positionIndex] = newPositionCandidate; |
221 |
| - positionIndex %= numberOfPositions; |
222 |
| - updateHtmlSource(); |
| 127 | + environmentRecord.positions[++environmentRecord.positionIndex] = newPositionCandidate; |
| 128 | + environmentRecord.positionIndex %= environmentRecord.numberOfPositions; |
| 129 | + webserverHandle.loop(); |
223 | 130 | }
|
| 131 | + const auto newTarget = webserverHandle.flushTargetRequest(); |
224 | 132 | if(newTarget.isTargetNew)
|
225 | 133 | {
|
226 | 134 | const bool bumperIsPressed = digitalRead(board::leftBumper) == LOW || digitalRead(board::rightBumper) == LOW;
|
227 | 135 | if(newTarget.newDrive!=0 && (!newTarget.forward || !bumperIsPressed))
|
228 | 136 | {
|
229 | 137 | drives::driveCounter(newTarget.newDrive, drives::cruiseSpeed, !newTarget.forward);
|
230 |
| - newTarget = { }; |
231 | 138 | }
|
232 | 139 | else if(newTarget.newRotate!=0 && !bumperIsPressed)
|
233 | 140 | {
|
234 | 141 | drives::rotateCounter(newTarget.newRotate, drives::cruiseSpeed, newTarget.clockwise);
|
235 |
| - newTarget = { }; |
236 | 142 | }
|
237 | 143 | }
|
238 | 144 | }
|
|
0 commit comments