Skip to content

Commit

Permalink
Move CGI handling to own class
Browse files Browse the repository at this point in the history
Also use global static variable for parameter-related functions in
opcuacolorchecker.cpp for more clarity.

Change-Id: Iecb6ba56328a753c03762b32ed3176a034748cac
Signed-off-by: Joakim Roubert <[email protected]>
  • Loading branch information
joakimr-axis committed Feb 19, 2025
1 parent ec8b8f9 commit e2372fd
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 136 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ RM ?= rm -f

PKGS = gio-2.0 gio-unix-2.0 vdostream open62541 axevent axhttp axparameter

CXXFLAGS += -Os -pipe -std=c++11 -Wall -Werror -Wextra
CXXFLAGS += -Os -pipe -std=c++2a -Wall -Werror -Wextra
CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --cflags-only-I $(PKGS))
LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs $(PKGS))

Expand Down
52 changes: 52 additions & 0 deletions include/CgiHandler.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Copyright (C) 2025, Axis Communications AB, Lund, Sweden
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* This header file handles the vdo part of the application.
*/

#pragma once

#include <axhttp.h>

class CgiHandler
{
public:
CgiHandler(
gboolean (*GetColorAreaValue)(),
gboolean (*GetParamDouble)(const gchar *, double &),
gboolean (*PickCurrentCallback)());
~CgiHandler();
static void RequestHandler(
const gchar *path,
const gchar *method,
const gchar *query,
GHashTable *params,
GOutputStream *output_stream,
gpointer user_data);

private:
static void
WriteErrorResponse(GDataOutputStream &dos, const guint32 statuscode, const gchar *statusname, const gchar *msg);
static void WriteBadRequest(GDataOutputStream &dos, const gchar *msg);
static void WriteInternalError(GDataOutputStream &dos, const gchar *msg);

gboolean (*GetColorAreaValue_)();
gboolean (*GetParamDouble_)(const gchar *, double &);
gboolean (*PickCurrentCallback_)();

AXHttpHandler *http_handler_;
};
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
},
"vendorUrl": "https://www.axis.com/",
"runMode": "respawn",
"version": "1.1.1"
"version": "1.1.2"
},
"configuration": {
"settingPage": "settings.html",
Expand Down
134 changes: 134 additions & 0 deletions src/CgiHandler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/**
* Copyright (C) 2025, Axis Communications AB, Lund, Sweden
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <assert.h>
#include <ostream>
#include <sstream>
#include <string>

#include "CgiHandler.hpp"
#include "common.hpp"

using namespace std;

CgiHandler::CgiHandler(
gboolean (*GetColorAreaValue)(),
gboolean (*GetParamDouble)(const gchar *, double &),
gboolean (*PickCurrentCallback)())
: GetColorAreaValue_(GetColorAreaValue), GetParamDouble_(GetParamDouble), PickCurrentCallback_(PickCurrentCallback),
http_handler_(ax_http_handler_new(this->RequestHandler, this))
{
assert(nullptr != GetColorAreaValue_);
assert(nullptr != GetParamDouble_);
assert(nullptr != PickCurrentCallback_);
assert(nullptr != http_handler_);
}

CgiHandler::~CgiHandler()
{
LOG_I("%s/%s: Free http handler ...", __FILE__, __FUNCTION__);
assert(nullptr != http_handler_);
ax_http_handler_free(http_handler_);
}

void CgiHandler::WriteErrorResponse(
GDataOutputStream &dos,
const guint32 statuscode,
const gchar *statusname,
const gchar *msg)
{
ostringstream ss;
ss << "Status: " << statuscode << " " << statusname << "\r\n"
<< "Content-Type: text/html\r\n"
<< "\r\n"
<< "<HTML><HEAD><TITLE>" << statuscode << " " << statusname << "</TITLE></HEAD>\n"
<< "<BODY><H1>" << statuscode << " " << statusname << "</H1>\n"
<< msg << "\n"
<< "</BODY></HTML>\n";

g_data_output_stream_put_string(&dos, ss.str().c_str(), nullptr, nullptr);
}

void CgiHandler::WriteBadRequest(GDataOutputStream &dos, const gchar *msg)
{
WriteErrorResponse(dos, 400, "Bad Request", msg);
}

void CgiHandler::WriteInternalError(GDataOutputStream &dos, const gchar *msg)
{
WriteErrorResponse(dos, 500, "Internal Server Error", msg);
}

void CgiHandler::RequestHandler(
const gchar *path,
const gchar *method,
const gchar *query,
GHashTable *params,
GOutputStream *output_stream,
gpointer user_data)
{
(void)method;
(void)query;
(void)params;

auto dos = g_data_output_stream_new(output_stream);
assert(nullptr != dos);
assert(nullptr != user_data);
auto cgi_handler = static_cast<CgiHandler *>(user_data);

const auto func = basename(const_cast<char *>(path));
if (0 == strcmp("getstatus.cgi", func))
{
assert(nullptr != cgi_handler->GetColorAreaValue_);
const auto status = cgi_handler->GetColorAreaValue_();
g_data_output_stream_put_string(dos, "Status: 200 OK\r\n", nullptr, nullptr);
g_data_output_stream_put_string(dos, "Content-Type: application/json\r\n\r\n", nullptr, nullptr);
ostringstream ss;
ss << "{\"status\": " << (status ? "true" : "false") << "}" << endl;
g_data_output_stream_put_string(dos, ss.str().c_str(), nullptr, nullptr);
}
else if (0 == strcmp("pickcurrent.cgi", func))
{
assert(nullptr != cgi_handler->PickCurrentCallback_);
if (!cgi_handler->PickCurrentCallback_())
{
WriteInternalError(*dos, "Failed to pick current color");
goto http_exit;
}

double blue;
double green;
double red;
assert(nullptr != cgi_handler->GetParamDouble_);
if (!cgi_handler->GetParamDouble_("ColorB", blue) || !cgi_handler->GetParamDouble_("ColorG", green) ||
!cgi_handler->GetParamDouble_("ColorR", red))
{
WriteInternalError(*dos, "Inner parameter retrieval error");
goto http_exit;
}
g_data_output_stream_put_string(dos, "Status: 200 OK\r\n", nullptr, nullptr);
g_data_output_stream_put_string(dos, "Content-Type: application/json\r\n\r\n", nullptr, nullptr);
ostringstream ss;
ss << "{\"R\":" << red << ", \"G\":" << green << ", \"B\":" << blue << "}" << endl;
g_data_output_stream_put_string(dos, ss.str().c_str(), nullptr, nullptr);
}
else
{
WriteBadRequest(*dos, "Unknown action");
}
http_exit:
g_object_unref(dos);
}
18 changes: 9 additions & 9 deletions src/ColorArea.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ Scalar ColorArea::GetAverageColor(const Mat &img) const
assert(img.size() == img_size_);

// Crop
auto crop_img = img(croprange_y_, croprange_x_);
const auto crop_img = img(croprange_y_, croprange_x_);
DBG_WRITE_IMG("avg_after_crop.jpg", crop_img);

return mean(crop_img, colorarea_mask_);
Expand All @@ -113,7 +113,7 @@ bool ColorArea::ColorAreaValueWithinTolerance(const Mat &img) const
// Make sure input image has the same size as the gague was set up for
assert(img_size_ == img.size());

auto currentavg = GetAverageColor(img);
const auto currentavg = GetAverageColor(img);
LOG_D(
"%s/%s: Target/Current average color in region: (%1.f, %.1f, %.1f)/(%.1f, %.1f, %.1f)",
__FILE__,
Expand All @@ -124,9 +124,9 @@ bool ColorArea::ColorAreaValueWithinTolerance(const Mat &img) const
currentavg.val[R],
currentavg.val[G],
currentavg.val[B]);
auto colordiff_r = abs(color_.val[R] - currentavg.val[R]);
auto colordiff_g = abs(color_.val[G] - currentavg.val[G]);
auto colordiff_b = abs(color_.val[B] - currentavg.val[B]);
const auto colordiff_r = abs(color_.val[R] - currentavg.val[R]);
const auto colordiff_g = abs(color_.val[G] - currentavg.val[G]);
const auto colordiff_b = abs(color_.val[B] - currentavg.val[B]);

return (tolerance_ > colordiff_r && tolerance_ > colordiff_g && tolerance_ > colordiff_b);
}
Expand All @@ -142,7 +142,7 @@ ColorAreaEllipse::ColorAreaEllipse(
{
#if defined(DEBUG_WRITE)
// Create a debug image tho show the marker
auto marker_img = img.clone();
const auto marker_img = img.clone();

// Draw the ellipse
Size axes(markerwidth / 2, markerheight / 2);
Expand Down Expand Up @@ -180,11 +180,11 @@ ColorAreaRectangle::ColorAreaRectangle(
{
#if defined(DEBUG_WRITE)
// Create a debug image tho show the marker
auto marker_img = img.clone();
const auto marker_img = img.clone();

// Draw the rectangle
auto pt1 = point_center - Point(markerwidth / 2, markerheight / 2);
auto pt2 = point_center + Point(markerwidth / 2, markerheight / 2);
const auto pt1 = point_center - Point(markerwidth / 2, markerheight / 2);
const auto pt2 = point_center + Point(markerwidth / 2, markerheight / 2);
rectangle(marker_img, pt1, pt2, Scalar(0, 0, 0), 3);
rectangle(marker_img, pt1, pt2, Scalar(255, 255, 255), 1);

Expand Down
Loading

0 comments on commit e2372fd

Please sign in to comment.