Skip to content

Commit

Permalink
Added a GUI logger component
Browse files Browse the repository at this point in the history
Added a component to show AgIsoStack logs.
  • Loading branch information
ad3154 committed Nov 16, 2023
1 parent 369fc9d commit 45de7b4
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 5 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ Supported features:
- Picture graphics (with and without run-length encoding)
- Output Strings (partial - font clipping is not compliant)
- Input lists (partial - drawing the selector needs work)
- Some CAN messages (Object pool upload state machine and handshake messages, maintenance messages, change active mask response, change child location response, change numeric value and response, key/button activation and release messages, change numeric value, select input object)
- Most relevant VT server CAN messages
- Logging

Unimplemented features (for now)

Expand All @@ -46,7 +47,6 @@ Unimplemented features (for now)
- Animations
- Output Lists
- Output arched bar graph
- Logging
- Graphics contexts
- Pointing events
- TAN
Expand Down
41 changes: 41 additions & 0 deletions include/LoggerComponent.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//================================================================================================
/// @file LoggerComponent.hpp
///
/// @brief Defines a GUI component to draw log output.
/// @author Adrian Del Grosso
///
/// @copyright 2023 Adrian Del Grosso
//================================================================================================
#ifndef LOGGER_COMPONENT_HPP
#define LOGGER_COMPONENT_HPP

#include "isobus/isobus/can_stack_logger.hpp"
#include "isobus/isobus/isobus_virtual_terminal_objects.hpp"
#include "isobus/isobus/isobus_virtual_terminal_server_managed_working_set.hpp"

#include "JuceHeader.h"

/// @brief Defines a GUI component that will draw log info sunk from the stack
class LoggerComponent : public Component
, public isobus::CANStackLogger
{
public:
LoggerComponent();

void paint(Graphics &g) override;

void sink_CAN_stack_log(LoggingLevel level, const std::string &logText) override;

private:
struct LogData
{
String logText;
isobus::CANStackLogger::LoggingLevel logLevel;
};
static constexpr std::size_t MAX_NUMBER_MESSAGES = 3000;
std::deque<LogData> loggedMessages;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LoggerComponent);
};

#endif // LOGGER_COMPONENT_HPP
3 changes: 3 additions & 0 deletions include/ServerMainComponent.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "DataMaskRenderAreaComponent.hpp"
#include "LoggerComponent.hpp"
#include "SoftKeyMaskRenderAreaComponent.hpp"
#include "WorkingSetSelectorComponent.hpp"
#include "isobus/isobus/isobus_virtual_terminal_server.hpp"
Expand Down Expand Up @@ -75,6 +76,8 @@ class ServerMainComponent : public juce::Component
WorkingSetSelectorComponent workingSetSelector;
DataMaskRenderAreaComponent dataMaskRenderer;
SoftKeyMaskRenderAreaComponent softKeyMaskRenderer;
LoggerComponent logger;
Viewport loggerViewport;
SoundPlayer mSoundPlayer;
AudioDeviceManager mAudioDeviceManager;
std::uint8_t numberOfPoolsToRender = 0;
Expand Down
84 changes: 84 additions & 0 deletions src/LoggerComponent.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//================================================================================================
/// @file LoggerComponent.cpp
///
/// @brief Implements a GUI component to draw log output.
/// @author Adrian Del Grosso
///
/// @copyright 2023 Adrian Del Grosso
//================================================================================================
#include "LoggerComponent.hpp"

LoggerComponent::LoggerComponent()
{
auto bounds = getLocalBounds();
setBounds(10, 10, bounds.getWidth() - 10, bounds.getHeight() - 10);
}

void LoggerComponent::paint(Graphics &g)
{
g.fillAll(Colours::black);
g.setFont(14.0f);

int numberOfLinesFitted = getHeight() / 14;

for (std::size_t i = 0; i < loggedMessages.size() && i < numberOfLinesFitted; i++)
{
const auto &message = loggedMessages.at(i);

switch (message.logLevel)
{
case LoggingLevel::Info:
{
g.setColour(Colours::white);
}
break;

case LoggingLevel::Warning:
{
g.setColour(Colours::yellow);
}
break;

case LoggingLevel::Error:
case LoggingLevel::Critical:
{
g.setColour(Colours::red);
}
break;

case LoggingLevel::Debug:
{
g.setColour(Colours::blueviolet);
}
break;

default:
{
g.setColour(Colours::white);
}
break;
}
g.drawFittedText(message.logText, 0, i * 14, getWidth(), 14, Justification::centredLeft, 1);
}
}

void LoggerComponent::sink_CAN_stack_log(LoggingLevel level, const std::string &logText)
{
const auto mmLock = MessageManagerLock();

loggedMessages.push_front({ logText, level });

if (loggedMessages.size() > MAX_NUMBER_MESSAGES)
{
loggedMessages.pop_back();
}

int newSize = loggedMessages.size() * 14;

if (newSize < 200)
{
newSize = 200;
}
setSize(getWidth(), newSize);
repaint();
}
2 changes: 1 addition & 1 deletion src/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ class AgISOUniversalTerminalApplication : public juce::JUCEApplication
jassert(nullptr != canDriver); // You need some kind of CAN interface to run this program!
isobus::CANHardwareInterface::set_number_of_can_channels(1);
isobus::CANHardwareInterface::assign_can_channel_frame_handler(0, canDriver);
isobus::CANHardwareInterface::start();

isobus::NAME serverNAME(0);
serverNAME.set_arbitrary_address_capable(true);
Expand All @@ -98,6 +97,7 @@ class AgISOUniversalTerminalApplication : public juce::JUCEApplication
serverInternalControlFunction = isobus::InternalControlFunction::create(serverNAME, 0x26, 0);
setUsingNativeTitleBar(true);
setContentOwned(new ServerMainComponent(serverInternalControlFunction), true);
isobus::CANHardwareInterface::start();

#if JUCE_IOS || JUCE_ANDROID
setFullScreen(true);
Expand Down
15 changes: 13 additions & 2 deletions src/ServerMainComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,18 @@ ServerMainComponent::ServerMainComponent(std::shared_ptr<isobus::InternalControl
addAndMakeVisible(workingSetSelector);
addAndMakeVisible(dataMaskRenderer);
addAndMakeVisible(softKeyMaskRenderer);
addAndMakeVisible(loggerViewport);
// Make sure you set the size of the component after
// you add any child components.
setSize(800, 800);

logger.setTopLeftPosition(0, 600);
logger.setSize(800, 200);
loggerViewport.setViewedComponent(&logger, false);
logger.setVisible(true);

isobus::CANStackLogger::set_can_stack_logger_sink(&logger);
isobus::CANStackLogger::set_log_level(isobus::CANStackLogger::LoggingLevel::Debug);
// setFramesPerSecond(60); // This sets the frequency of the update calls.
startTimer(50);
}
Expand Down Expand Up @@ -264,6 +273,8 @@ void ServerMainComponent::resized()
// This is called when the MainContentComponent is resized.
// If you add any child components, this is where you should
// update their positions.
loggerViewport.setSize(getWidth(), getHeight() - 600);
loggerViewport.setTopLeftPosition(0, 600);
}

std::shared_ptr<isobus::ControlFunction> ServerMainComponent::get_client_control_function_for_working_set(std::shared_ptr<isobus::VirtualTerminalServerManagedWorkingSet> workingSet) const
Expand Down Expand Up @@ -307,11 +318,11 @@ void ServerMainComponent::on_change_active_mask_callback(std::shared_ptr<isobus:
softKeyMaskRenderer.on_change_active_mask(activeWorkingSet);

auto activeMask = affectedWorkingSet->get_object_by_id(newMask);

if (activeWorkingSetDataMaskObjectID != newMask)
{
activeWorkingSetDataMaskObjectID = newMask;

if (send_status_message())
{
statusMessageTimestamp_ms = isobus::SystemTiming::get_timestamp_ms();
Expand Down

0 comments on commit 45de7b4

Please sign in to comment.