I accidentally clicked verified answer while trying to edit the page.
This is the patch file:
diff --git a/nrf5_SDK_for_Mesh_v5.0.0_src/scripts/interactive_pyaci/aci/aci_cmd.py b/nrf5_SDK_for_Mesh_v5.0.0_src/scripts/interactive_pyaci/aci/aci_cmd.py
index f7f92f3b..8fa50048 100644
--- a/nrf5_SDK_for_Mesh_v5.0.0_src/scripts/interactive_pyaci/aci/aci_cmd.py
+++ b/nrf5_SDK_for_Mesh_v5.0.0_src/scripts/interactive_pyaci/aci/aci_cmd.py
@@ -968,6 +968,70 @@ class NetStateGet(CommandPacket):
__data = bytearray()
super(NetStateGet, self).__init__(0xAF, __data)
+class HBPublicationGet(CommandPacket):
+ """Gets the Heartbeat Publication state"""
+ def __init__(self):
+ __data = bytearray()
+ super(HBPublicationGet, self).__init__(0xB0, __data)
+
+class HBPublicationSet(CommandPacket):
+ """Sets the Heartbeat Publication state
+
+ Parameters
+ ----------
+ dst : uint16_t
+ The destination to send heartbeat messages.
+ count : uint32_t
+ How many messages to send.
+ period : uint32_t
+ What interval to send messages.
+ ttl : uint8_t
+ Initial TTL.
+ features : uint16_t
+ The features that trigger sending messages when changed.
+ netkey_index : uint16_t
+ The global NetKey Index of the Netkey used to send.
+
+ Return
+ ------
+ NRF_ERROR_INVALID_DATA :
+ Invalid netkey_index.
+ Check that A netkey is added corresponding the netkey_index in device
+ """
+ def __init__(self, dst, count, period, ttl, features, netkey_index):
+ __data = bytearray()
+ __data += struct.pack("<H", dst)
+ __data += struct.pack("<I", count)
+ __data += struct.pack("<I", period)
+ __data += struct.pack("<B", ttl)
+ __data += struct.pack("<H", features)
+ __data += struct.pack("<H", netkey_index)
+ super(HBPublicationSet, self).__init__(0xB1, __data)
+
+class HBSubscriptionGet(CommandPacket):
+ """Gets the Heartbeat Subscription state"""
+ def __init__(self):
+ __data = bytearray()
+ super(HBSubscriptionGet, self).__init__(0xB2, __data)
+
+class HBSubscriptionSet(CommandPacket):
+ """Sets the Heartbeat Subscription state
+
+ Parameters
+ ----------
+ src : uint16_t
+ The unicast source address for messages a node shall process.
+ dst : uint16_t
+ The destination to send heartbeat messages.
+ period : uint32_t
+ The number of seconds left for processing messages.
+ """
+ def __init__(self, src, dst, period):
+ __data = bytearray()
+ __data += struct.pack("<H", src)
+ __data += struct.pack("<H", dst)
+ __data += struct.pack("<I", period)
+ super(HBSubscriptionSet, self).__init__(0xB3, __data)
class JumpToBootloader(CommandPacket):
"""Immediately jump to bootloader mode."""
@@ -1740,6 +1804,29 @@ class NetStateGetRsp(ResponsePacket):
__data["next_seqnum_block"], = struct.unpack("<I", raw_data[7:11])
super(NetStateGetRsp, self).__init__("NetStateGet", 0xAF, __data)
+class HBPublicationGetRsp(ResponsePacket):
+ """Response to a(n) HBPublicationGet command."""
+ def __init__(self, raw_data):
+ __data = {}
+ __data["dst"], = struct.unpack("<H", raw_data[0:2])
+ __data["count_log"], = struct.unpack("<B", raw_data[2:3])
+ __data["period_log"], = struct.unpack("<B", raw_data[3:4])
+ __data["ttl"], = struct.unpack("<B", raw_data[4:5])
+ __data["features"], = struct.unpack("<H", raw_data[5:7])
+ __data["netkey_index"], = struct.unpack("<H", raw_data[7:9])
+ super(HBPublicationGetRsp, self).__init__("HBPublicationGet", 0xB0, __data)
+
+class HBSubscriptionGetRsp(ResponsePacket):
+ """Response to a(n) HBSubscriptionGet command."""
+ def __init__(self, raw_data):
+ __data = {}
+ __data["src"], = struct.unpack("<H", raw_data[0:2])
+ __data["dst"], = struct.unpack("<H", raw_data[2:4])
+ __data["period_log"], = struct.unpack("<B", raw_data[4:5])
+ __data["count_log"], = struct.unpack("<B", raw_data[5:6])
+ __data["min_hops"], = struct.unpack("<B", raw_data[6:7])
+ __data["max_hops"], = struct.unpack("<B", raw_data[7:8])
+ super(HBSubscriptionGetRsp, self).__init__("HBSubscriptionGet", 0xB2, __data)
class BankInfoGetRsp(ResponsePacket):
"""Response to a(n) BankInfoGet command."""
@@ -1930,6 +2017,8 @@ RESPONSE_LUT = {
0xA6: {"object": AddrPublicationRemoveRsp, "name": "AddrPublicationRemove"},
0xAB: {"object": PacketSendRsp, "name": "PacketSend"},
0xAF: {"object": NetStateGetRsp, "name": "NetStateGet"},
+ 0xB0: {"object": HBPublicationGetRsp, "name": "HBPublicationGet"},
+ 0xB2: {"object": HBSubscriptionGetRsp, "name": "HBSubscriptionGet"},
0xD4: {"object": BankInfoGetRsp, "name": "BankInfoGet"},
0xD6: {"object": StateGetRsp, "name": "StateGet"},
0xE1: {"object": ModelPubAddrGetRsp, "name": "ModelPubAddrGet"},
diff --git a/nrf5_SDK_for_Mesh_v5.0.0_src/mesh/serial/include/serial_cmd.h b/nrf5_SDK_for_Mesh_v5.0.0_src/mesh/serial/include/serial_cmd.h
index 11c94a6f..1118e6fc 100644
--- a/nrf5_SDK_for_Mesh_v5.0.0_src/mesh/serial/include/serial_cmd.h
+++ b/nrf5_SDK_for_Mesh_v5.0.0_src/mesh/serial/include/serial_cmd.h
@@ -155,6 +155,10 @@
#define SERIAL_OPCODE_CMD_MESH_CONFIG_SERVER_BIND (0xAD) /**< Params: @ref serial_cmd_mesh_config_server_devkey_bind_t */
#define SERIAL_OPCODE_CMD_MESH_NET_STATE_SET (0xAE) /**< Params: @ref serial_cmd_mesh_net_state_set_t */
#define SERIAL_OPCODE_CMD_MESH_NET_STATE_GET (0xAF) /**< Params: None. */
+#define SERIAL_OPCODE_CMD_MESH_HB_PUBLICATION_GET (0xB0) /**< Params: None. */
+#define SERIAL_OPCODE_CMD_MESH_HB_PUBLICATION_SET (0xB1) /**< Params: @ref serial_cmd_mesh_hb_publication_set_t */
+#define SERIAL_OPCODE_CMD_MESH_HB_SUBSCRIPTION_GET (0xB2) /**< Params: None. */
+#define SERIAL_OPCODE_CMD_MESH_HB_SUBSCRIPTION_SET (0xB3) /**< Params: @ref serial_cmd_mesh_hb_subscription_set_t */
#define SERIAL_OPCODE_CMD_RANGE_MESH_END (0xBF) /**< MESH range end. */
#define SERIAL_OPCODE_CMD_RANGE_DFU_START (0xD0) /**< DFU range start. */
@@ -518,6 +522,25 @@ typedef struct __attribute((packed))
uint32_t next_seqnum_block; /**< The first sequence number block which is not yet allocated. */
} serial_cmd_mesh_net_state_set_t;
+/** Heartbeat publication set command parameters */
+typedef struct __attribute((packed))
+{
+ uint16_t dst; /**< The destination to send heartbeat messages.*/
+ uint32_t count; /**< How many messages to send.*/
+ uint32_t period; /**< What interval to send messages.*/
+ uint8_t ttl; /**< Initial TTL.*/
+ uint16_t features; /**< The features that trigger sending messages when changed.*/
+ uint16_t netkey_index; /**< The global NetKey Index of the Netkey used to send.*/
+} serial_cmd_mesh_hb_publication_set_t;
+
+/** Heartbeat subscription set command parameters */
+typedef struct __attribute((packed))
+{
+ uint16_t src; /**< The unicast source address for messages a node shall process.*/
+ uint16_t dst; /**< The destination to receive heartbeat messages.*/
+ uint32_t period; /**< The number of seconds left for processing messages.*/
+} serial_cmd_mesh_hb_subscription_set_t;
+
/** Mesh command parameters. */
typedef union __attribute((packed))
{
@@ -549,6 +572,8 @@ typedef union __attribute((packed))
serial_cmd_mesh_packet_send_t packet_send; /**< Packet send parameters. */
serial_cmd_mesh_config_server_devkey_bind_t config_server_devkey_bind; /**< Configuration Server: device key bind parameters. */
serial_cmd_mesh_net_state_set_t net_state_set; /**< Net state set parameters */
+ serial_cmd_mesh_hb_publication_set_t hb_publication_set; /**< Heartbeat Publication set parameters */
+ serial_cmd_mesh_hb_subscription_set_t hb_subscription_set; /**< Heartbeat Subscription set parameters */
} serial_cmd_mesh_t;
/* **** PB-MESH Client **** */
diff --git a/nrf5_SDK_for_Mesh_v5.0.0_src/mesh/serial/include/serial_cmd_rsp.h b/nrf5_SDK_for_Mesh_v5.0.0_src/mesh/serial/include/serial_cmd_rsp.h
index 00f4d45b..f1733aa7 100644
--- a/nrf5_SDK_for_Mesh_v5.0.0_src/mesh/serial/include/serial_cmd_rsp.h
+++ b/nrf5_SDK_for_Mesh_v5.0.0_src/mesh/serial/include/serial_cmd_rsp.h
@@ -309,6 +309,28 @@ typedef struct __attribute((packed))
uint32_t next_seqnum_block; /**< The start of the next unused sequence number block. */
} serial_evt_cmd_rsp_data_net_state_get_t;
+/** Command response to @ref SERIAL_OPCODE_CMD_MESH_HB_PUBLICATION_GET with the current heartbeat publication state */
+typedef struct __attribute((packed))
+{
+ uint16_t dst; /**< The destination to send heartbeat messages.*/
+ uint8_t count_log; /**< How many messages to send.*/
+ uint8_t period_log; /**< What interval to send messages.*/
+ uint8_t ttl; /**< Initial TTL.*/
+ uint16_t features; /**< The features that trigger sending messages when changed.*/
+ uint16_t netkey_index; /**< The global NetKey Index of the Netkey used to send.*/
+} serial_evt_cmd_rsp_data_hb_publication_get_t;
+
+/** Command response to @ref SERIAL_OPCODE_CMD_MESH_HB_SUBSCRIPTION_GET with the current heartbeat subscription state */
+typedef struct __attribute((packed))
+{
+ uint16_t src; /**< The unicast source address for messages a node shall process.*/
+ uint16_t dst; /**< The destination to receive heartbeat messages.*/
+ uint8_t period_log; /**< The number of seconds left for processing messages.*/
+ uint8_t count_log; /**< The number of periodical messages received.*/
+ uint16_t min_hops; /**< The minimum hops value registered when receiving messages.*/
+ uint16_t max_hops; /**< The maximum hops value registered when receiving messages.*/
+} serial_evt_cmd_rsp_data_hb_subscription_get_t;
+
/** Command response packet. */
typedef struct __attribute((packed))
{
@@ -348,7 +370,8 @@ typedef struct __attribute((packed))
serial_evt_cmd_rsp_data_model_init_t model_init; /**< Reserved handle for the initialized model instance. */
serial_evt_cmd_rsp_data_packet_send_t packet_send; /**< Information about the sent packet. */
serial_evt_cmd_rsp_data_net_state_get_t net_state_get; /**< Net state. */
-
+ serial_evt_cmd_rsp_data_hb_publication_get_t hb_publication_get; /**< Heartbeat Publication States. */
+ serial_evt_cmd_rsp_data_hb_subscription_get_t hb_subscription_get; /**< Heartbeat Subscription States. */
} data; /**< Optional command response data. */
} serial_evt_cmd_rsp_t;
diff --git a/nrf5_SDK_for_Mesh_v5.0.0_src/mesh/serial/src/serial_handler_mesh.c b/nrf5_SDK_for_Mesh_v5.0.0_src/mesh/serial/src/serial_handler_mesh.c
index 655cdcd3..25fd52ff 100644
--- a/nrf5_SDK_for_Mesh_v5.0.0_src/mesh/serial/src/serial_handler_mesh.c
+++ b/nrf5_SDK_for_Mesh_v5.0.0_src/mesh/serial/src/serial_handler_mesh.c
@@ -54,6 +54,7 @@
#include "mesh_opt_net_state.h"
#include "mesh_config_entry.h"
#include "mesh_config_listener.h"
+#include "heartbeat.h"
/* Ensure that we're mapping the size of the serial parameter to the
* dsm_handle_t. If this triggers, someone changed the size of the
@@ -488,6 +489,143 @@ static void handle_net_state_get(const serial_packet_t * p_cmd)
serial_handler_common_cmd_rsp_nodata_on_error(p_cmd->opcode, status, (uint8_t *)&rsp, sizeof(rsp));
}
+static inline uint8_t heartbeat_pubsub_period_encode(uint32_t period)
+{
+ if (period == 0)
+ {
+ return 0x00;
+ }
+ else if (period <= HEARTBEAT_MAX_PERIOD)
+ {
+ return (log2_get(period) + 1);
+ }
+ else
+ {
+ NRF_MESH_ASSERT(false);
+ return HEARTBEAT_MAX_PERIOD_LOG;
+ }
+}
+
+static inline uint8_t heartbeat_publication_count_encode(uint32_t count)
+{
+ if (count <= 1)
+ {
+ return count;
+ }
+ else if (count <= HEARTBEAT_MAX_COUNT)
+ {
+ /* Finding smallest n where 2^(n-1) is greater than or equal to the count value */
+ return (log2_get(count - 1) + 1 + 1);
+ }
+ else if (count == HEARTBEAT_INF_COUNT)
+ {
+ return HEARTBEAT_INF_COUNT_LOG;
+ }
+ else
+ {
+ NRF_MESH_ASSERT(false);
+ return HEARTBEAT_MAX_COUNT_LOG;
+ }
+}
+
+static inline uint8_t heartbeat_subscription_count_encode(uint32_t count)
+{
+ if (count == 0)
+ {
+ return 0x00;
+ }
+ else if (count <= HEARTBEAT_MAX_COUNT)
+ {
+ /* Finding largest n where 2^(n-1) is less than or equal to the count value */
+ return (log2_get(count) + 1);
+ }
+ else if (count == HEARTBEAT_INF_COUNT)
+ {
+ return HEARTBEAT_INF_COUNT_LOG;
+ }
+ else
+ {
+ NRF_MESH_ASSERT(false);
+ return HEARTBEAT_MAX_COUNT_LOG;
+ }
+}
+
+static void handle_heartbeat_publication_get(const serial_packet_t * p_cmd)
+{
+ const heartbeat_publication_state_t * p_hb_pub = heartbeat_publication_get();
+ serial_evt_cmd_rsp_data_hb_publication_get_t rsp = {
+ .dst = p_hb_pub->dst,
+ .count_log = heartbeat_publication_count_encode(p_hb_pub->count),
+ .period_log = heartbeat_pubsub_period_encode(p_hb_pub->period),
+ .ttl = p_hb_pub->ttl,
+ .features = p_hb_pub->features,
+ .netkey_index = p_hb_pub->netkey_index
+ };
+ serial_cmd_rsp_send(p_cmd->opcode, SERIAL_STATUS_SUCCESS, (uint8_t *)&rsp, sizeof(rsp));
+}
+
+static void handle_heartbeat_publication_set(const serial_packet_t * p_cmd)
+{
+ uint32_t status;
+ const heartbeat_publication_state_t hb_pub = {
+ .dst = p_cmd->payload.cmd.mesh.hb_publication_set.dst,
+ .count = p_cmd->payload.cmd.mesh.hb_publication_set.count,
+ .period = p_cmd->payload.cmd.mesh.hb_publication_set.period,
+ .ttl = p_cmd->payload.cmd.mesh.hb_publication_set.ttl,
+ .features = p_cmd->payload.cmd.mesh.hb_publication_set.features,
+ .netkey_index = p_cmd->payload.cmd.mesh.hb_publication_set.netkey_index
+ };
+
+ /* This is specifically required for INVALID_NETKEY status code */
+ if (dsm_net_key_index_to_subnet_handle(p_cmd->payload.cmd.mesh.hb_publication_set.netkey_index)
+ == DSM_HANDLE_INVALID)
+ {
+ status = NRF_ERROR_INVALID_DATA;
+ }
+ else
+ {
+ status = heartbeat_publication_set(&hb_pub);
+ }
+ serial_handler_common_cmd_rsp_nodata_on_error(p_cmd->opcode, status, NULL, 0);
+}
+static void handle_heartbeat_subscription_get(const serial_packet_t * p_cmd)
+{
+ const heartbeat_subscription_state_t * p_hb_sub = heartbeat_subscription_get();
+ serial_evt_cmd_rsp_data_hb_subscription_get_t rsp;
+
+ /* When the Heartbeat Subscription Source or Destination state is set to the unassigned address,
+ the value of - the Source and Destination fields of the Status message shall be set to the
+ unassigned address and the values of the CountLog, PeriodLog, MinHops, and MaxHops fields shall
+ be set to 0x00. Refer to @tagMeshSp section 4.4.1.2.16 */
+ if (p_hb_sub->src == NRF_MESH_ADDR_UNASSIGNED ||
+ p_hb_sub->dst == NRF_MESH_ADDR_UNASSIGNED)
+ {
+ memset(&rsp, 0, sizeof(serial_evt_cmd_rsp_data_hb_subscription_get_t));
+ }
+ else
+ {
+ rsp.src = p_hb_sub->src;
+ rsp.dst = p_hb_sub->dst;
+ rsp.count_log = heartbeat_subscription_count_encode(p_hb_sub->count);
+ rsp.period_log = heartbeat_pubsub_period_encode(p_hb_sub->period);
+ rsp.min_hops = p_hb_sub->min_hops;
+ rsp.max_hops = p_hb_sub->max_hops;
+ }
+ serial_cmd_rsp_send(p_cmd->opcode, SERIAL_STATUS_SUCCESS, (uint8_t *)&rsp, sizeof(rsp));
+}
+static void handle_heartbeat_subscription_set(const serial_packet_t * p_cmd)
+{
+ uint32_t status;
+ const heartbeat_subscription_state_t hb_sub = {
+ .src = p_cmd->payload.cmd.mesh.hb_subscription_set.src,
+ .dst = p_cmd->payload.cmd.mesh.hb_subscription_set.dst,
+ .period = p_cmd->payload.cmd.mesh.hb_subscription_set.period,
+ /* other state values shall remain unchanged, see @tagMeshSp section 4.4.1.2.16 */
+ };
+ status = heartbeat_subscription_set(&hb_sub);
+ serial_handler_common_cmd_rsp_nodata_on_error(p_cmd->opcode, status, NULL, 0);
+}
+
/*****************************************************************************
* Static functions
*****************************************************************************/
@@ -527,7 +665,11 @@ static const mesh_serial_cmd_handler_t m_handlers[] =
{SERIAL_OPCODE_CMD_MESH_STATE_CLEAR, 0, 0, handle_cmd_clear},
{SERIAL_OPCODE_CMD_MESH_CONFIG_SERVER_BIND, sizeof(serial_cmd_mesh_config_server_devkey_bind_t), 0, handle_config_devkey_bind},
{SERIAL_OPCODE_CMD_MESH_NET_STATE_SET, sizeof(serial_cmd_mesh_net_state_set_t), 0, handle_net_state_set},
- {SERIAL_OPCODE_CMD_MESH_NET_STATE_GET, 0, 0, handle_net_state_get}
+ {SERIAL_OPCODE_CMD_MESH_NET_STATE_GET, 0, 0, handle_net_state_get},
+ {SERIAL_OPCODE_CMD_MESH_HB_PUBLICATION_GET, 0, 0, handle_heartbeat_publication_get},
+ {SERIAL_OPCODE_CMD_MESH_HB_PUBLICATION_SET, sizeof(serial_cmd_mesh_hb_publication_set_t), 0, handle_heartbeat_publication_set},
+ {SERIAL_OPCODE_CMD_MESH_HB_SUBSCRIPTION_GET, 0, 0, handle_heartbeat_subscription_get},
+ {SERIAL_OPCODE_CMD_MESH_HB_SUBSCRIPTION_SET, sizeof(serial_cmd_mesh_hb_subscription_set_t), 0, handle_heartbeat_subscription_set}
};
static void mesh_config_listener_cb(mesh_config_change_reason_t reason, mesh_config_entry_id_t id, const void * p_entry)
This is a procedure:
$sudo python3 interactive_pyaci.py -d /dev/ttyACM0
To control your device, use d[x], where x is the device index.
Devices are indexed based on the order of the COM ports specified by the -d option.
The first device, d[0], can also be accessed using device.
Type d[x]. and hit tab to see the available methods.
Python 3.8.10 (default, Nov 26 2021, 20:14:08)
Type 'copyright', 'credits' or 'license' for more information
IPython 8.2.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: db = MeshDB("database/test_database.json")
In [2]: p = Provisioner(device, db)
In [3]: 2022-04-20 16:32:31,318 - INFO - ttyACM0: Success
2022-04-20 16:32:31,321 - INFO - ttyACM0: Success
2022-04-20 16:32:31,326 - INFO - ttyACM0: SubnetAdd: {'subnet_handle': 0}
2022-04-20 16:32:31,331 - INFO - ttyACM0: AppkeyAdd: {'appkey_handle': 0}
2022-04-20 16:32:31,336 - INFO - ttyACM0: AppkeyAdd: {'appkey_handle': 1}
In [3]:
In [3]: p.provision(uuid="0b01a6561a474762bfbaafa3f6ecb494", name="dimmer3")
In [4]: 2022-04-20 16:32:43,383 - INFO - ttyACM0: Provision: {'context': 0}
2022-04-20 16:32:43,549 - INFO - ttyACM0: Link established
2022-04-20 16:32:47,619 - INFO - ttyACM0: Received capabilities
2022-04-20 16:32:47,619 - INFO - ttyACM0: Number of elements: 3
2022-04-20 16:32:47,622 - INFO - ttyACM0: OobUse: {'context': 0}
2022-04-20 16:32:49,882 - INFO - ttyACM0: ECDH request received
2022-04-20 16:32:49,889 - INFO - ttyACM0: EcdhSecret: {'context': 0}
2022-04-20 16:32:54,346 - INFO - ttyACM0: Provisioning complete
2022-04-20 16:32:54,346 - INFO - ttyACM0: Address(es): 0x10-0x12
2022-04-20 16:32:54,346 - INFO - ttyACM0: Device key: 44f39b33df8a2599fdb2e942100588e7
2022-04-20 16:32:54,346 - INFO - ttyACM0: Network key: 18eed9c2a56add85049ffc3c59ad0e12
2022-04-20 16:32:54,346 - INFO - ttyACM0: Adding device key to subnet 0
2022-04-20 16:32:54,346 - INFO - ttyACM0: Adding publication address of root element
2022-04-20 16:32:54,355 - INFO - ttyACM0: DevkeyAdd: {'devkey_handle': 8}
2022-04-20 16:32:54,356 - INFO - ttyACM0: AddrPublicationAdd: {'address_handle': 0}
2022-04-20 16:32:54,522 - INFO - ttyACM0: Provisioning link closed
In [4]:
In [4]: cc = ConfigurationClient(db)
In [5]: device.model_add(cc)
In [6]: cc.publish_set(8, 0)
In [7]: device.send(cmd.HBSubscriptionSet(16, 0xFFFF, 0xFF))
In [8]: 2022-04-20 16:33:57,661 - INFO - ttyACM0: Success
In [8]:
In [8]: device.send(cmd.HBSubscriptionGet())
In [9]: 2022-04-20 16:34:28,137 - INFO - ttyACM0: HBSubscriptionGet: {'src': 16, 'dst': 65535, 'period_log': 8, 'count_log': 0, 'min_hops': 127, 'max_hops': 0}
In [9]:
In [9]: cc.heartbeat_publication_set(0xFFFF, 0xF, 2, feature_bitfield=2, ttl=11)
In [10]: 2022-04-20 16:34:40,192 - INFO - ttyACM0: PacketSend: {'token': 1}
In [10]: 2022-04-20 16:34:40,215 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 1}}
In [10]: cc.heartbeat_publication_set(0xFFFF, 0xF, 2, feature_bitfield=2, ttl=11)
In [11]: 2022-04-20 16:34:43,852 - INFO - ttyACM0: PacketSend: {'token': 2}
2022-04-20 16:34:43,871 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 2}}
2022-04-20 16:34:43,917 - INFO - ttyACM0.ConfigurationClient: Heartbeat publication status: AccessStatus.SUCCESS
2022-04-20 16:34:43,917 - INFO - ttyACM0.ConfigurationClient: Heartbeat publication state: dst: ffff, count: 8, period: 2s, features: {'relay': False, 'proxy': True, 'friend': False, 'lowPower': False}, subnet: 0
2022-04-20 16:34:43,925 - INFO - ttyACM0: {event: MeshHeartbeatReceived, data: {'init_ttl': 11, 'hops': 1, 'features': 0, 'src': 16}}
In [11]:
In [11]: 2022-04-20 16:34:45,899 - INFO - ttyACM0: {event: MeshHeartbeatReceived, data: {'init_ttl': 11, 'hops': 1, 'features': 0, 'src': 16}}
2022-04-20 16:34:47,895 - INFO - ttyACM0: {event: MeshHeartbeatReceived, data: {'init_ttl': 11, 'hops': 1, 'features': 0, 'src': 16}}
2022-04-20 16:34:49,902 - INFO - ttyACM0: {event: MeshHeartbeatReceived, data: {'init_ttl': 11, 'hops': 1, 'features': 0, 'src': 16}}
2022-04-20 16:34:51,896 - INFO - ttyACM0: {event: MeshHeartbeatReceived, data: {'init_ttl': 11, 'hops': 1, 'features': 0, 'src': 16}}
2022-04-20 16:34:53,917 - INFO - ttyACM0: {event: MeshHeartbeatReceived, data: {'init_ttl': 11, 'hops': 1, 'features': 0, 'src': 16}}
2022-04-20 16:34:55,930 - INFO - ttyACM0: {event: MeshHeartbeatReceived, data: {'init_ttl': 11, 'hops': 1, 'features': 0, 'src': 16}}
2022-04-20 16:34:57,903 - INFO - ttyACM0: {event: MeshHeartbeatReceived, data: {'init_ttl': 11, 'hops': 1, 'features': 0, 'src': 16}}
In [11]:
In [11]: device.send(cmd.HBSubscriptionGet())
In [12]: 2022-04-20 16:35:06,889 - INFO - ttyACM0: HBSubscriptionGet: {'src': 16, 'dst': 65535, 'period_log': 8, 'count_log': 4, 'min_hops': 1, 'max_hops': 0}
In [12]:
In [12]: cc.heartbeat_subscription_set(1, 0xffff, 0xFF)
In [13]: 2022-04-20 16:35:36,163 - INFO - ttyACM0: PacketSend: {'token': 3}
In [13]: 2022-04-20 16:35:36,216 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 3}}
2022-04-20 16:35:36,219 - INFO - ttyACM0.ConfigurationClient: Heartbeat subscription status: AccessStatus.SUCCESS
2022-04-20 16:35:36,219 - INFO - ttyACM0.ConfigurationClient: Heartbeat subscription state: src: 0001, dst: ffff, period: 128s, count: 0, min/max: 127/0
In [13]:
In [13]: device.send(cmd.HBPublicationSet(0xFFFF, 0xF, 2, features=2, ttl=11, netkey_index=0))
In [14]: 2022-04-20 16:35:55,190 - INFO - ttyACM0: Success
2022-04-20 16:35:55,192 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:35:55,213 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:35:57,192 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:35:57,239 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:35:59,192 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:35:59,241 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:01,192 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:01,236 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:03,199 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:03,214 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:05,192 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:05,235 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:07,205 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:07,213 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:09,192 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:09,248 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:11,193 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:11,222 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:13,213 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:13,213 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:15,192 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:15,237 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:17,195 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:17,212 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:19,209 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:19,217 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:21,216 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:21,222 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:23,192 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
2022-04-20 16:36:23,239 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4294967293}}
In [14]:
In [14]: cc.heartbeat_subscription_get()
In [15]: 2022-04-20 16:36:37,077 - INFO - ttyACM0: PacketSend: {'token': 4}
In [15]: 2022-04-20 16:36:37,104 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 4}}
In [15]: cc.heartbeat_subscription_get()
In [16]: 2022-04-20 16:36:38,664 - INFO - ttyACM0: PacketSend: {'token': 5}
2022-04-20 16:36:38,665 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 5}}
In [16]:
In [16]: cc.heartbeat_subscription_get()
In [17]: 2022-04-20 16:36:42,163 - INFO - ttyACM0: PacketSend: {'token': 6}
2022-04-20 16:36:42,189 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 6}}
2022-04-20 16:36:42,226 - INFO - ttyACM0.ConfigurationClient: Heartbeat subscription status: AccessStatus.SUCCESS
2022-04-20 16:36:42,226 - INFO - ttyACM0.ConfigurationClient: Heartbeat subscription state: src: 0001, dst: ffff, period: 32s, count: 4, min/max: 1/1
In [17]:
And, I wonder there are other ways for heartbeat models in serial interface and also health model officially.