Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[VT]: Add state tracker and updater for active masks #406

Merged
merged 3 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions examples/task_controller_client/section_control_implement_sim.cpp

Large diffs are not rendered by default.

31 changes: 18 additions & 13 deletions examples/virtual_terminal/esp32_platformio_object_pool/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "isobus/isobus/can_partnered_control_function.hpp"
#include "isobus/isobus/can_stack_logger.hpp"
#include "isobus/isobus/isobus_virtual_terminal_client.hpp"
#include "isobus/isobus/isobus_virtual_terminal_client_update_helper.hpp"
#include "isobus/utility/iop_file_interface.hpp"

#include "console_logger.cpp"
Expand All @@ -17,40 +18,40 @@
#include <memory>

//! It is discouraged to use global variables, but it is done here for simplicity.
static std::shared_ptr<isobus::VirtualTerminalClient> TestVirtualTerminalClient = nullptr;
static std::shared_ptr<isobus::VirtualTerminalClient> virtualTerminalClient = nullptr;
static std::shared_ptr<isobus::VirtualTerminalClientUpdateHelper> virtualTerminalUpdateHelper = nullptr;

// This callback will provide us with event driven notifications of button presses from the stack
void handleVTKeyEvents(const isobus::VirtualTerminalClient::VTKeyEvent &event)
{
static std::uint32_t exampleNumberOutput = 214748364; // In the object pool the output number has an offset of -214748364 so we use this to represent 0.

switch (event.keyEvent)
{
case isobus::VirtualTerminalClient::KeyActivationCode::ButtonUnlatchedOrReleased:
case isobus::VirtualTerminalClient::KeyActivationCode::ButtonStillHeld:
{
switch (event.objectID)
{
case Plus_Button:
{
TestVirtualTerminalClient->send_change_numeric_value(ButtonExampleNumber_VarNum, ++exampleNumberOutput);
virtualTerminalUpdateHelper->increase_numeric_value(ButtonExampleNumber_VarNum);
}
break;

case Minus_Button:
{
TestVirtualTerminalClient->send_change_numeric_value(ButtonExampleNumber_VarNum, --exampleNumberOutput);
virtualTerminalUpdateHelper->decrease_numeric_value(ButtonExampleNumber_VarNum);
}
break;

case alarm_SoftKey:
{
TestVirtualTerminalClient->send_change_active_mask(example_WorkingSet, example_AlarmMask);
virtualTerminalUpdateHelper->set_active_data_or_alarm_mask(example_WorkingSet, example_AlarmMask);
}
break;

case acknowledgeAlarm_SoftKey:
{
TestVirtualTerminalClient->send_change_active_mask(example_WorkingSet, mainRunscreen_DataMask);
virtualTerminalUpdateHelper->set_active_data_or_alarm_mask(example_WorkingSet, mainRunscreen_DataMask);
}
break;

Expand Down Expand Up @@ -107,18 +108,22 @@ extern "C" void app_main()
auto TestInternalECU = isobus::InternalControlFunction::create(TestDeviceNAME, 0x1C, 0);
auto TestPartnerVT = isobus::PartneredControlFunction::create(0, vtNameFilters);

TestVirtualTerminalClient = std::make_shared<isobus::VirtualTerminalClient>(TestPartnerVT, TestInternalECU);
TestVirtualTerminalClient->set_object_pool(0, testPool, (object_pool_end - object_pool_start) - 1, "ais1");
auto softKeyListener = TestVirtualTerminalClient->add_vt_soft_key_event_listener(handleVTKeyEvents);
auto buttonListener = TestVirtualTerminalClient->add_vt_button_event_listener(handleVTKeyEvents);
TestVirtualTerminalClient->initialize(true);
virtualTerminalClient = std::make_shared<isobus::VirtualTerminalClient>(TestPartnerVT, TestInternalECU);
virtualTerminalClient->set_object_pool(0, testPool, (object_pool_end - object_pool_start) - 1, "ais1");
auto softKeyListener = virtualTerminalClient->add_vt_soft_key_event_listener(handleVTKeyEvents);
auto buttonListener = virtualTerminalClient->add_vt_button_event_listener(handleVTKeyEvents);
virtualTerminalClient->initialize(true);

virtualTerminalUpdateHelper = std::make_shared<isobus::VirtualTerminalClientUpdateHelper>(virtualTerminalClient);
virtualTerminalUpdateHelper->add_tracked_numeric_value(ButtonExampleNumber_VarNum, 214748364); // In the object pool the output number has an offset of -214748364 so we use this to represent 0.
virtualTerminalUpdateHelper->initialize();

while (true)
{
// CAN stack runs in other threads. Do nothing forever.
vTaskDelay(10);
}

TestVirtualTerminalClient->terminate();
virtualTerminalClient->terminate();
isobus::CANHardwareInterface::stop();
}
4 changes: 2 additions & 2 deletions examples/virtual_terminal/version3_object_pool/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ void handleVTKeyEvents(const isobus::VirtualTerminalClient::VTKeyEvent &event)

case alarm_SoftKey:
{
virtualTerminalClient->send_change_active_mask(example_WorkingSet, example_AlarmMask);
virtualTerminalUpdateHelper->set_active_data_or_alarm_mask(example_WorkingSet, example_AlarmMask);
}
break;

case acknowledgeAlarm_SoftKey:
{
virtualTerminalClient->send_change_active_mask(example_WorkingSet, mainRunscreen_DataMask);
virtualTerminalUpdateHelper->set_active_data_or_alarm_mask(example_WorkingSet, mainRunscreen_DataMask);
}
break;

Expand Down
1 change: 1 addition & 0 deletions isobus/include/isobus/isobus/can_constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace isobus
constexpr std::uint8_t BROADCAST_CAN_ADDRESS = 0xFF; ///< The global/broadcast CAN address
constexpr std::uint8_t CAN_DATA_LENGTH = 8; ///< The length of a classical CAN frame
constexpr std::uint32_t CAN_PORT_MAXIMUM = 4; ///< An arbitrary limit for memory consumption
constexpr std::uint16_t NULL_OBJECT_ID = 65535; ///< Special ID used to indicate no object

}

Expand Down
5 changes: 5 additions & 0 deletions isobus/include/isobus/isobus/can_message.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ namespace isobus
/// @returns True if the message is destined for the control function, false otherwise
bool is_destination(std::shared_ptr<ControlFunction> controlFunction) const;

/// @brief Returns whether the message is originated from the control function.
/// @param[in] controlFunction The control function to check
/// @returns True if the message is originated from the control function, false otherwise
bool is_source(std::shared_ptr<ControlFunction> controlFunction) const;

/// @brief Returns the identifier of the message
/// @returns The identifier of the message
CANIdentifier get_identifier() const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,6 @@ namespace isobus
/// @brief The max allowable "valid" object ID
static constexpr std::uint16_t MAX_OBJECT_ID = 65534;

/// @brief Special ID used to indicate no object
static constexpr std::uint16_t NULL_OBJECT_ID = 65535;

/// @brief Defines the max length of a designator (in bytes)
static constexpr std::size_t MAX_DESIGNATOR_LENGTH = 128;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,6 @@ namespace isobus
AuxiliaryTypeTwoFunctionType functionType; ///< The type of function
};

static constexpr std::uint16_t NULL_OBJECT_ID = 0xFFFF; ///< The NULL Object ID, usually drawn as blank space

/// @brief The constructor for a VirtualTerminalClient
/// @param[in] partner The VT server control function
/// @param[in] clientSource The internal control function to communicate from
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
#ifndef ISOBUS_VIRTUAL_TERMINAL_CLIENT_STATE_TRACKER_HPP
#define ISOBUS_VIRTUAL_TERMINAL_CLIENT_STATE_TRACKER_HPP

#include "isobus/isobus/can_constants.hpp"
#include "isobus/isobus/can_control_function.hpp"
#include "isobus/isobus/can_message.hpp"

#include <deque>
#include <map>
#include <vector>

Expand Down Expand Up @@ -53,8 +55,47 @@ namespace isobus
/// @return The current numeric value of the tracked object.
std::uint32_t get_numeric_value(std::uint16_t objectId) const;

/// @brief Get the data/alarm mask currently active on the server for this client. It may not be displayed if the working set is not active.
/// @return The data/alarm mask currently active on the server for this client.
std::uint16_t get_active_mask() const;

/// @brief Get the history of data/alarm masks that were active on the server for this client.
/// @return The history of data/alarm masks that were active on the server for this client.
const std::deque<std::uint16_t> &get_mask_history() const;

/// @brief Get the maximum size of the data/alarm mask history.
/// @return The maximum size of the data/alarm mask history.
std::size_t get_max_mask_history_size() const;

/// @brief Sets the maximum size of the data/alarm mask history (default: 100)
/// @param[in] size The maximum size of the data/alarm mask history.
void set_max_mask_history_size(std::size_t size);

/// @brief Adds a data/alarm mask to track the soft key mask for.
/// @param[in] dataOrAlarmMaskId The data/alarm mask to track the soft key mask for.
/// @param[in] initialSoftKeyMaskId The initial soft key mask to associate with the data/alarm mask.
void add_tracked_soft_key_mask(std::uint16_t dataOrAlarmMaskId, std::uint16_t initialSoftKeyMaskId);

/// @brief Removes a data/alarm mask from tracking the soft key mask for.
/// @param[in] dataOrAlarmMaskId The data/alarm mask to remove the soft key mask from tracking for.
void remove_tracked_soft_key_mask(std::uint16_t dataOrAlarmMaskId);

/// @brief Get the soft key mask currently active on thse server for this client. It may not be displayed if the working set is not active.
/// @return The soft key mask currently active on the server for this client.
std::uint16_t get_active_soft_key_mask() const;

/// @brief Get the soft key mask currently associated with a data/alarm mask.
/// @param[in] dataOrAlarmMaskId The data/alarm mask to get the currently associated soft key mask for.
/// @return The soft key mask currently associated with the supplied mask.
std::uint16_t get_soft_key_mask(std::uint16_t dataOrAlarmMaskId) const;

/// @brief Get whether the working set of the client is active on the server.
/// @return True if the working set is active, false otherwise.
bool is_working_set_active() const;

protected:
std::shared_ptr<ControlFunction> client; ///< The control function of the virtual terminal client to track.
std::shared_ptr<ControlFunction> server; ///< The control function of the server the client is connected to.

//! TODO: std::map<std::uint16_t, bool> shownStates; ///< Holds the 'hide/show' state of tracked objects.
//! TODO: std::map<std::uint16_t, bool> enabledStates; ///< Holds the 'enable/disable' state of tracked objects.
Expand All @@ -70,9 +111,11 @@ namespace isobus
//! TODO: add font attribute state
//! TODO: add line attribute state
//! TODO: add fill attribute state
std::uint16_t currentActiveMask; ///< Holds the currently active mask.
//! TODO: std::uint16_t currentWorkingSet; ///< Holds the working set of the current active mask.
//! TODO: std::map<std::uint16_t, std::uint16_t> softKeyMasks; ///< Holds the data/alarms masks with their associated soft keys masks for tracked objects.
std::uint16_t activeDataOrAlarmMask = NULL_OBJECT_ID; ///< Holds the data/alarm mask currently visible on the server for this client.
std::deque<std::uint16_t> dataAndAlarmMaskHistory; ///< Holds the history of data/alarm masks that were active on the server for this client.
std::size_t maxDataAndAlarmMaskHistorySize = 100; ///< Holds the maximum size of the data/alarm mask history.
std::uint8_t activeWorkingSetAddress = NULL_CAN_ADDRESS; ///< Holds the address of the control function that currently has
std::map<std::uint16_t, std::uint16_t> softKeyMasks; ///< Holds the data/alarms masks with their associated soft keys masks for tracked objects.
//! TODO: std::map<std::uint16_t, std::pair<std::uint8_t, std::uint32_t>> attributeStates; ///< Holds the 'attribute' state of tracked objects.
//! TODO: std::map<std::uint16_t, std::uint8_t> alarmMaskPrioritiesStates; ///< Holds the 'alarm mask priority' state of tracked objects.
//! TODO: std::map<std::uint16_t, std::pair<std::uint8_t, std::uint16_t>> listItemStates; ///< Holds the 'list item' state of tracked objects.
Expand All @@ -84,14 +127,26 @@ namespace isobus
//! TODO: std::uint16_t currentColourMap; ///< Holds the current colour map/palette object.

private:
/// @brief Processes a received message.
/// @param[in] message The received message.
/// @brief Cache a mask as the active mask on the server.
/// @param[in] maskId The mask to cache as the active mask on the server.
void cache_active_mask(std::uint16_t maskId);

/// @brief Processes a received or transmitted message.
/// @param[in] message The message to process.
/// @param[in] parentPointer The pointer to the parent object, which should be the VirtualTerminalClientStateTracker.
static void process_rx_message(const CANMessage &message, void *parentPointer);
static void process_rx_or_tx_message(const CANMessage &message, void *parentPointer);

/// @brief Processes a status message from a VT server.
/// @param[in] message The message to process.
void process_status_message(const CANMessage &message);

/// @brief Processes a VT->ECU message received by any client, sent from the connected server.
/// @param[in] message The message to process.
void process_message_from_connected_server(const CANMessage &message);

/// @brief Processes a received message.
/// @param[in] message The received message.
void process_rx_message(const CANMessage &message);
/// @brief Processes a ECU->VT message received by the connected server, sent from any control function.
/// @param[in] message The message to process.
void process_message_to_connected_server(const CANMessage &message);
};
} // namespace isobus

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ namespace isobus
/// @param[in] callback The callback function to register, or nullptr to unregister.
void set_callback_validate_numeric_value(const std::function<bool(std::uint16_t, std::uint32_t)> &callback);

/// @brief Sets the active data/alarm mask.
/// @param[in] workingSetId The working set to set the active data/alarm mask for.
/// @param[in] dataOrAlarmMaskId The data/alarm mask to set active.
/// @return True if the data/alarm mask was set active successfully, false otherwise.
bool set_active_data_or_alarm_mask(std::uint16_t workingSetId, std::uint16_t dataOrAlarmMaskId);

/// @brief Sets the active soft key mask.
/// @param[in] maskType The type of mask to set the active soft key mask for.
/// @param[in] maskId The mask to set the active soft key mask for.
/// @param[in] softKeyMaskId The soft key mask to set active.
/// @return True if the soft key mask was set active successfully, false otherwise.
bool set_active_soft_key_mask(VirtualTerminalClient::MaskType maskType, std::uint16_t maskId, std::uint16_t softKeyMaskId);

private:
/// @brief Processes a numeric value change event
/// @param[in] event The numeric value change event to process.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,6 @@ namespace isobus
std::array<VTColourVector, VT_COLOUR_TABLE_SIZE> colourTable; ///< Colour table data. Associates VT colour index with RGB value.
};

static constexpr std::uint16_t NULL_OBJECT_ID = 0xFFFF; ///< The NULL Object ID, usually drawn as blank space

/// @brief Generic VT object base class
class VTObject
{
Expand Down
5 changes: 5 additions & 0 deletions isobus/src/can_message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ namespace isobus
return has_valid_destination_control_function() && destination == controlFunction;
}

bool CANMessage::is_source(std::shared_ptr<ControlFunction> controlFunction) const
{
return has_valid_source_control_function() && source == controlFunction;
}

CANIdentifier CANMessage::get_identifier() const
{
return identifier;
Expand Down
9 changes: 5 additions & 4 deletions isobus/src/isobus_device_descriptor_object_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
//================================================================================================
#include "isobus/isobus/isobus_device_descriptor_object_pool.hpp"

#include "isobus/isobus/can_constants.hpp"
#include "isobus/isobus/can_stack_logger.hpp"
#include "isobus/utility/platform_endianness.hpp"
#include "isobus/utility/to_string.hpp"
Expand Down Expand Up @@ -1070,7 +1071,7 @@ namespace isobus
{
// Process parent object
auto currentDeviceElement = reinterpret_cast<task_controller_object::DeviceElementObject *>(currentObject.get());
if (task_controller_object::Object::NULL_OBJECT_ID != currentDeviceElement->get_parent_object())
if (NULL_OBJECT_ID != currentDeviceElement->get_parent_object())
{
auto parent = get_object_by_id(currentDeviceElement->get_parent_object());
if (nullptr != parent.get())
Expand Down Expand Up @@ -1143,7 +1144,7 @@ namespace isobus
{
auto currentProcessData = reinterpret_cast<task_controller_object::DeviceProcessDataObject *>(currentObject.get());

if (task_controller_object::Object::NULL_OBJECT_ID != currentProcessData->get_device_value_presentation_object_id())
if (NULL_OBJECT_ID != currentProcessData->get_device_value_presentation_object_id())
{
auto child = get_object_by_id(currentProcessData->get_device_value_presentation_object_id());
if (nullptr == child.get())
Expand Down Expand Up @@ -1171,7 +1172,7 @@ namespace isobus
{
auto currentProperty = reinterpret_cast<task_controller_object::DevicePropertyObject *>(currentObject.get());

if (task_controller_object::Object::NULL_OBJECT_ID != currentProperty->get_device_value_presentation_object_id())
if (NULL_OBJECT_ID != currentProperty->get_device_value_presentation_object_id())
{
auto child = get_object_by_id(currentProperty->get_device_value_presentation_object_id());
if (nullptr == child.get())
Expand Down Expand Up @@ -1214,7 +1215,7 @@ namespace isobus
{
bool retVal = true;

if ((0 != uniqueID) && (task_controller_object::Object::NULL_OBJECT_ID != uniqueID))
if ((0 != uniqueID) && (NULL_OBJECT_ID != uniqueID))
{
for (auto &currentObject : objectList)
{
Expand Down
1 change: 1 addition & 0 deletions isobus/src/isobus_task_controller_client_objects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
//================================================================================================
#include "isobus/isobus/isobus_task_controller_client_objects.hpp"

#include "isobus/isobus/can_constants.hpp"
#include "isobus/utility/platform_endianness.hpp"

#include <algorithm>
Expand Down
8 changes: 6 additions & 2 deletions isobus/src/isobus_virtual_terminal_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4464,7 +4464,7 @@ namespace isobus

if (!get_is_connected())
{
CANStackLogger::error("[VT]: Cannot send command, not connected");
CANStackLogger::warn("[VT]: Cannot send command, not connected");
return false;
}

Expand All @@ -4486,7 +4486,7 @@ namespace isobus
return false;
}

if (send_command(data))
if (get_is_connected() && send_command(data))
{
return true;
}
Expand Down Expand Up @@ -4528,6 +4528,10 @@ namespace isobus

void VirtualTerminalClient::process_command_queue()
{
if (!get_is_connected())
{
return;
}
#if !defined CAN_STACK_DISABLE_THREADS && !defined ARDUINO
std::lock_guard<std::mutex> lock(commandQueueMutex);
#endif
Expand Down
Loading
Loading