Skip to content

Commit

Permalink
canbus_stats: Periodically report canbus interface statistics
Browse files Browse the repository at this point in the history
Add support or a new get_canbus_status command to canserial.c .

Add new canbus_stats.py module that will periodically query canbus
mcus for connection status information.

Signed-off-by: Kevin O'Connor <[email protected]>
  • Loading branch information
KevinOConnor committed Jan 15, 2025
1 parent 03c3054 commit ee9814f
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 1 deletion.
15 changes: 15 additions & 0 deletions docs/Status_Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,21 @@ the following strings: "adjust", "fine".
- `current_screw`: The index for the current screw being adjusted.
- `accepted_screws`: The number of accepted screws.

## canbus_stats

The following information is available in the `canbus_stats
some_mcu_name` object (this object is automatically available if an
mcu is configured to use canbus):
- `rx_error`: The number of receive errors detected by the
micro-controller canbus hardware.
- `tx_error`: The number of transmit errors detected by the
micro-controller canbus hardware.
- `bus_state`: The status of the interface (typically "active" for a
bus in normal operation, "warn" for a bus with recent errors,
"passive" for a bus that will no longer transmit canbus error
frames, or "off" for a bus that will no longer transmit or receive
messages).

## configfile

The following information is available in the `configfile` object
Expand Down
48 changes: 48 additions & 0 deletions klippy/extras/canbus_stats.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Report canbus connection status
#
# Copyright (C) 2025 Kevin O'Connor <[email protected]>
#
# This file may be distributed under the terms of the GNU GPLv3 license.

class PrinterCANBusStats:
def __init__(self, config):
self.printer = config.get_printer()
self.name = config.get_name().split()[-1]
self.mcu = None
self.get_canbus_status_cmd = None
self.status = {'rx_error': None, 'tx_error': None, 'bus_state': None}
self.printer.register_event_handler("klippy:connect", self._connect)
def _connect(self):
# Lookup mcu
mcu_name = self.name
if mcu_name != 'mcu':
mcu_name = 'mcu ' + mcu_name
self.mcu = self.printer.lookup_object(mcu_name)
# Lookup status query command
if self.mcu.try_lookup_command("get_canbus_status") is None:
return
self.get_canbus_status_cmd = self.mcu.lookup_query_command(
"get_canbus_status",
"canbus_status rx_error=%u tx_error=%u canbus_bus_state=%u")
# Register periodic query timer
reactor = self.printer.get_reactor()
reactor.register_timer(self.query_event, reactor.NOW)
def query_event(self, eventtime):
params = self.get_canbus_status_cmd.send()
rx = params['rx_error']
tx = params['tx_error']
state = params['canbus_bus_state']
self.status = {'rx_error': rx, 'tx_error': tx, 'bus_state': state}
return eventtime + 1.
def stats(self, eventtime):
status = self.status
if status['rx_error'] is None:
return (False, '')
return (False, 'canstat_%s: rx_error=%d tx_error=%d bus_state=%s'
% (self.name, status['rx_error'], status['tx_error'],
status['bus_state']))
def get_status(self, eventtime):
return self.status

def load_config_prefix(config):
return PrinterCANBusStats(config)
1 change: 1 addition & 0 deletions klippy/mcu.py
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,7 @@ def __init__(self, config, clocksync):
self._canbus_iface = config.get('canbus_interface', 'can0')
cbid = self._printer.load_object(config, 'canbus_ids')
cbid.add_uuid(config, canbus_uuid, self._canbus_iface)
self._printer.load_object(config, 'canbus_stats %s' % (self._name,))
else:
self._serialport = config.get('serial')
if not (self._serialport.startswith("/dev/rpmsg_")
Expand Down
18 changes: 17 additions & 1 deletion src/generic/canserial.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// Copyright (C) 2019 Eug Krashtan <[email protected]>
// Copyright (C) 2020 Pontus Borg <[email protected]>
// Copyright (C) 2021 Kevin O'Connor <[email protected]>
// Copyright (C) 2021-2025 Kevin O'Connor <[email protected]>
//
// This file may be distributed under the terms of the GNU GPLv3 license.

Expand Down Expand Up @@ -318,6 +318,22 @@ DECL_TASK(canserial_rx_task);
* Setup and shutdown
****************************************************************/

DECL_ENUMERATION("canbus_bus_state", "active", CANBUS_STATE_ACTIVE);
DECL_ENUMERATION("canbus_bus_state", "warn", CANBUS_STATE_WARN);
DECL_ENUMERATION("canbus_bus_state", "passive", CANBUS_STATE_PASSIVE);
DECL_ENUMERATION("canbus_bus_state", "off", CANBUS_STATE_OFF);

void
command_get_canbus_status(uint32_t *args)
{
struct canbus_status status;
canhw_get_status(&status);
sendf("canbus_status rx_error=%u tx_error=%u canbus_bus_state=%u"
, status.rx_error, status.tx_error, status.bus_state);
}
DECL_COMMAND_FLAGS(command_get_canbus_status, HF_IN_SHUTDOWN
, "get_canbus_status");

void
command_get_canbus_id(uint32_t *args)
{
Expand Down

0 comments on commit ee9814f

Please sign in to comment.