mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-18 00:59:18 +02:00
The snapshot sent right after SUBSCRIBE was taken from the previous frame, which on the first frame of a session meant every value came back as UNAVAILABLE. The link now publishes the state of the current frame before the received frames are processed.
158 lines
5.4 KiB
C++
158 lines
5.4 KiB
C++
/*
|
|
This Source Code Form is subject to the
|
|
terms of the Mozilla Public License, v.
|
|
2.0. If a copy of the MPL was not
|
|
distributed with this file, You can
|
|
obtain one at
|
|
http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <deque>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
#include "hardware/diagnostics/hardware_diagnostics.h"
|
|
#include "hardware/hardware_config.h"
|
|
#include "hardware/protocol/protocol_codec.h"
|
|
#include "hardware/registry/state_registry.h"
|
|
#include "hardware/subscriptions/subscription_manager.h"
|
|
#include "input/command.h"
|
|
|
|
// logical protocol layer of one connection
|
|
// runs on the simulation thread; the transport worker only hands over decoded frames, so nothing
|
|
// here ever blocks on hardware, and nothing outside here touches simulation state
|
|
|
|
namespace hardware
|
|
{
|
|
|
|
// sink for packets produced by the session
|
|
class session_output
|
|
{
|
|
|
|
public:
|
|
// methods
|
|
virtual ~session_output() = default;
|
|
virtual void send_packet( packet_header const &Header, std::vector<std::uint8_t> const &Payload ) = 0;
|
|
};
|
|
|
|
class protocol_session
|
|
{
|
|
|
|
public:
|
|
// methods
|
|
protocol_session( session_output &Output, config const &Config );
|
|
|
|
// drops the session, called when the transport connection is lost
|
|
void reset();
|
|
// consumes one decoded frame
|
|
void handle_packet( decoded_packet const &Packet );
|
|
// publishes the state of the current simulation frame, before the received frames are processed
|
|
void set_snapshot( state_snapshot const &Snapshot ) { m_snapshot = Snapshot; }
|
|
// periodic work: heartbeats, subscription updates, timeouts
|
|
void update( double const Deltatime, state_snapshot const &Snapshot );
|
|
// copies the current condition into the debug report
|
|
void fill_report( link_report &Report ) const;
|
|
|
|
session_state state() const { return m_state; }
|
|
link_state link_condition() const;
|
|
protocol_diagnostics const &diagnostics() const { return m_diagnostics; }
|
|
// adds the frame level error counts gathered by the transport worker since the last call
|
|
void add_frame_errors( frame_decoder::counters const &Delta );
|
|
|
|
private:
|
|
// types
|
|
struct transaction_result
|
|
{
|
|
bool accepted = false;
|
|
error_code error = error_code::none;
|
|
};
|
|
|
|
// methods
|
|
void send( message_type const Type, std::uint8_t const Flags, payload_writer const &Payload );
|
|
void send_ack( std::uint32_t const Transaction, message_type const Type );
|
|
void send_nack( std::uint32_t const Transaction, message_type const Type, error_code const Error );
|
|
|
|
void handle_hello( decoded_packet const &Packet );
|
|
void handle_resolve_symbols( decoded_packet const &Packet );
|
|
void handle_query_symbol( decoded_packet const &Packet );
|
|
void handle_subscribe( decoded_packet const &Packet );
|
|
void handle_unsubscribe( decoded_packet const &Packet );
|
|
void handle_command_event( decoded_packet const &Packet );
|
|
void handle_control_set( decoded_packet const &Packet );
|
|
void handle_device_diagnostics( decoded_packet const &Packet );
|
|
void handle_heartbeat( decoded_packet const &Packet );
|
|
|
|
void send_state_update( std::vector<state_item> const &Items, bool const Snapshot );
|
|
void send_symbol_context_changed( std::uint32_t const Context );
|
|
|
|
// returns the registry index for a session handle, or symbol_registry::npos
|
|
std::size_t symbol_of_handle( std::uint16_t const Handle ) const;
|
|
std::uint16_t handle_of_symbol( std::size_t const SymbolIndex );
|
|
|
|
bool consume_frame_budget( std::size_t const PayloadSize );
|
|
bool consume_command_budget();
|
|
bool remember_transaction( std::uint32_t const Transaction, transaction_result const &Result );
|
|
transaction_result const *recall_transaction( std::uint32_t const Transaction ) const;
|
|
|
|
// executes a command, returns the error which should be reported to the device
|
|
error_code execute_command( std::size_t const SymbolIndex, command_action const Action, double const Parameter1, double const Parameter2, std::uint16_t const Recipient );
|
|
|
|
// members
|
|
session_output &m_output;
|
|
config m_config;
|
|
command_relay m_relay;
|
|
|
|
session_state m_state = session_state::waiting_for_hello;
|
|
std::uint32_t m_sessionid = 0;
|
|
std::uint32_t m_sequence = 0;
|
|
std::uint32_t m_lastreceivedsequence = 0;
|
|
bool m_sequenceseen = false;
|
|
std::size_t m_framesize = protocol_frame_size_default;
|
|
std::uint32_t m_capabilities = 0;
|
|
std::uint8_t m_peermajor = 0;
|
|
std::uint8_t m_peerminor = 0;
|
|
|
|
std::string m_devicename;
|
|
std::string m_devicerole;
|
|
std::string m_deviceid;
|
|
std::string m_firmwareversion;
|
|
std::string m_hardwareversion;
|
|
|
|
std::vector<std::size_t> m_handles;
|
|
std::unordered_map<std::size_t, std::uint16_t> m_handlelookup;
|
|
subscription_manager m_subscriptions;
|
|
// per control sequence counters, used to drop stale continuous updates
|
|
std::unordered_map<std::uint16_t, std::uint32_t> m_controlsequence;
|
|
|
|
std::unordered_map<std::uint32_t, transaction_result> m_transactions;
|
|
std::deque<std::uint32_t> m_transactionorder;
|
|
|
|
double m_uptime = 0.0;
|
|
double m_lastreceived = 0.0;
|
|
double m_heartbeattimer = 0.0;
|
|
double m_pingtimer = 0.0;
|
|
std::uint32_t m_pingtoken = 0;
|
|
double m_pingsent = 0.0;
|
|
bool m_pingpending = false;
|
|
|
|
double m_ratewindow = 0.0;
|
|
int m_framebudget = 0;
|
|
int m_payloadbudget = 0;
|
|
int m_commandbudget = 0;
|
|
|
|
std::uint32_t m_context = 0;
|
|
bool m_contextvalid = false;
|
|
// most recent simulator state, kept so that a subscription can be answered right away
|
|
state_snapshot m_snapshot;
|
|
|
|
protocol_diagnostics m_diagnostics;
|
|
device_diagnostics m_devicediagnostics;
|
|
rate_counter m_rxrate;
|
|
rate_counter m_txrate;
|
|
};
|
|
|
|
} // namespace hardware
|