Skip to content

Commit ff95e96

Browse files
committed
add ESPNowStats class and more
1 parent a1644f1 commit ff95e96

File tree

8 files changed

+220
-84
lines changed

8 files changed

+220
-84
lines changed

ports/espressif/bindings/espnow/ESPNow.c

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,8 @@
2727
* THE SOFTWARE.
2828
*/
2929

30-
#include "py/runtime.h"
31-
#include "py/objarray.h"
3230
#include "py/objproperty.h"
31+
#include "py/runtime.h"
3332
#include "py/stream.h"
3433

3534
#include "bindings/espnow/ESPNow.h"
@@ -74,19 +73,15 @@ STATIC mp_obj_t espnow_make_new(const mp_obj_type_t *type, size_t n_args, size_t
7473
mp_raise_RuntimeError(translate("Already running"));
7574
}
7675

76+
// Allocate a new object
7777
self = m_new_obj(espnow_obj_t);
7878
self->base.type = &espnow_type;
7979

80-
common_hal_espnow_set_buffer_size(self, args[ARG_buffer_size].u_int);
81-
common_hal_espnow_set_phy_rate(self, args[ARG_phy_rate].u_int);
82-
83-
self->peers = espnow_peers_new();
80+
// Construct the object
81+
common_hal_espnow_construct(self, args[ARG_buffer_size].u_int, args[ARG_phy_rate].u_int);
8482

8583
// Set the global singleton pointer for the espnow protocol.
8684
MP_STATE_PORT(espnow_singleton) = self;
87-
88-
common_hal_espnow_init(self);
89-
9085
return self;
9186
}
9287

@@ -167,23 +162,29 @@ MP_PROPERTY_GETSET(espnow_phy_rate_obj,
167162
(mp_obj_t)&espnow_get_phy_rate_obj,
168163
(mp_obj_t)&espnow_set_phy_rate_obj);
169164

170-
//| stats: Tuple[int, int, int, int, int]
171-
//| """Provide some useful stats in a `tuple` of
172-
//| (tx_packets, tx_responses, tx_failures, rx_packets, rx_failures). (read-only)"""
165+
//| tx_stats: ESPNowStats
166+
//| """The ``TX`` packet statistics."""
167+
//|
168+
STATIC mp_obj_t espnow_get_tx_stats(mp_obj_t self_in) {
169+
espnow_obj_t *self = MP_OBJ_TO_PTR(self_in);
170+
return MP_OBJ_FROM_PTR(self->tx_stats);
171+
}
172+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(espnow_get_tx_stats_obj, espnow_get_tx_stats);
173+
174+
MP_PROPERTY_GETTER(espnow_tx_stats_obj,
175+
(mp_obj_t)&espnow_get_tx_stats_obj);
176+
177+
//| rx_stats: ESPNowStats
178+
//| """The ``RX`` packet statistics."""
173179
//|
174-
STATIC mp_obj_t espnow_get_stats(mp_obj_t self_in) {
180+
STATIC mp_obj_t espnow_get_rx_stats(mp_obj_t self_in) {
175181
espnow_obj_t *self = MP_OBJ_TO_PTR(self_in);
176-
return MP_OBJ_NEW_TUPLE(
177-
mp_obj_new_int(self->tx_packets),
178-
mp_obj_new_int(self->tx_responses),
179-
mp_obj_new_int(self->tx_failures),
180-
mp_obj_new_int(self->rx_packets),
181-
mp_obj_new_int(self->rx_failures));
182+
return MP_OBJ_FROM_PTR(self->rx_stats);
182183
}
183-
STATIC MP_DEFINE_CONST_FUN_OBJ_1(espnow_get_stats_obj, espnow_get_stats);
184+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(espnow_get_rx_stats_obj, espnow_get_rx_stats);
184185

185-
MP_PROPERTY_GETTER(espnow_stats_obj,
186-
(mp_obj_t)&espnow_get_stats_obj);
186+
MP_PROPERTY_GETTER(espnow_rx_stats_obj,
187+
(mp_obj_t)&espnow_get_rx_stats_obj);
187188

188189
// --- Send and Receive ESP-NOW data ---
189190

@@ -195,9 +196,8 @@ MP_PROPERTY_GETTER(espnow_stats_obj,
195196
//| """Send a message to the peer's mac address.
196197
//|
197198
//| :param ReadableBuffer message: The message to send (length <= 250 bytes).
198-
//| :param ReadableBuffer mac: The peer's address (length = 6 bytes). If `None` or any non-true value, send to all registered peers.
199-
//|
200-
//| :raises EAGAIN: if the internal espnow buffers are full."""
199+
//| :param ReadableBuffer mac: The peer's address (length = 6 bytes).
200+
//| If `None` or any non-true value, send to all registered peers."""
201201
//| ...
202202
STATIC mp_obj_t espnow_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
203203
enum { ARG_message, ARG_mac, ARG_sync };
@@ -255,14 +255,17 @@ STATIC const mp_rom_map_elem_t espnow_locals_dict_table[] = {
255255
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
256256
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&espnow___exit___obj) },
257257

258+
// Deinit the object
258259
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&espnow_deinit_obj) },
259260

260261
// Config parameters
261262
{ MP_ROM_QSTR(MP_QSTR_set_pmk), MP_ROM_PTR(&espnow_set_pmk_obj) },
262263
{ MP_ROM_QSTR(MP_QSTR_buffer_size), MP_ROM_PTR(&espnow_buffer_size_obj) },
263264
{ MP_ROM_QSTR(MP_QSTR_phy_rate), MP_ROM_PTR(&espnow_phy_rate_obj) },
264265

265-
{ MP_ROM_QSTR(MP_QSTR_stats), MP_ROM_PTR(&espnow_stats_obj) },
266+
// Packet statistics
267+
{ MP_ROM_QSTR(MP_QSTR_tx_stats), MP_ROM_PTR(&espnow_tx_stats_obj) },
268+
{ MP_ROM_QSTR(MP_QSTR_rx_stats), MP_ROM_PTR(&espnow_rx_stats_obj) },
266269

267270
// Send and receive messages
268271
{ MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&espnow_send_obj) },
@@ -278,21 +281,25 @@ STATIC MP_DEFINE_CONST_DICT(espnow_locals_dict, espnow_locals_dict_table);
278281

279282
// Support ioctl(MP_STREAM_POLL, ) for asyncio
280283
STATIC mp_uint_t espnow_stream_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
281-
if (request != MP_STREAM_POLL) {
282-
*errcode = MP_EINVAL;
283-
return MP_STREAM_ERROR;
284-
}
285-
286284
espnow_obj_t *self = MP_OBJ_TO_PTR(self_in);
287-
return (common_hal_espnow_deinited(self)) ? 0 : // If not initialized
288-
arg ^ (
289-
// If no data in the buffer, unset the Read ready flag
290-
((!ringbuf_num_filled(self->recv_buffer)) ? MP_STREAM_POLL_RD : 0) |
291-
// If still waiting for responses, unset the Write ready flag
292-
((self->tx_responses < self->tx_packets) ? MP_STREAM_POLL_WR : 0));
285+
check_for_deinit(self);
286+
switch (request) {
287+
case MP_STREAM_POLL: {
288+
mp_uint_t flags = arg;
289+
mp_uint_t ret = 0;
290+
if ((flags & MP_STREAM_POLL_RD) && ringbuf_num_filled(self->recv_buffer) > 0) {
291+
ret |= MP_STREAM_POLL_RD;
292+
}
293+
return ret;
294+
}
295+
default:
296+
*errcode = MP_EINVAL;
297+
return MP_STREAM_ERROR;
298+
}
293299
}
294300

295301
STATIC const mp_stream_p_t espnow_stream_p = {
302+
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream)
296303
.ioctl = espnow_stream_ioctl,
297304
};
298305

ports/espressif/bindings/espnow/ESPNowPacket.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
#include "bindings/espnow/ESPNowPacket.h"
2828

2929
//| class ESPNowPacket:
30-
//| """A packet retreived from ESP-NOW communication protocol"""
30+
//| """A packet retrieved from ESP-NOW communication protocol"""
3131
//|
3232
//| mac: ReadableBuffer
3333
//| """The sender's mac address (length = 6 bytes)"""
@@ -39,7 +39,7 @@
3939
//| """The received signal strength indication (in dBm from -127 to 0)"""
4040
//|
4141
//| time: int
42-
//| """The is the time in milliseconds since device last booted"""
42+
//| """The time in milliseconds since the device last booted when the packet was received"""
4343
//|
4444

4545
const mp_obj_namedtuple_type_t espnow_packet_type_obj = {
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* This file is part of the CircuitPython project, https://github.com/adafruit/circuitpython
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2023 MicroDev
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "bindings/espnow/ESPNowStats.h"
28+
#include "py/objproperty.h"
29+
30+
//| class ESPNowStats:
31+
//| """Provide some useful packet tx/rx statistics."""
32+
//|
33+
34+
//| success: int
35+
//| """The number of successes. (read-only)
36+
//|
37+
//| * In case of transmit ``TX``:
38+
//| The number of tx packets received by the peer(s) ``ESP_NOW_SEND_SUCCESS``.
39+
//|
40+
//| * In case of receive ``RX``:
41+
//| The number of rx packets captured in the buffer."""
42+
//|
43+
STATIC mp_obj_t espnow_stats_get_success(const mp_obj_t self_in) {
44+
espnow_stats_obj_t *self = MP_OBJ_TO_PTR(self_in);
45+
return mp_obj_new_int_from_uint(self->success);
46+
}
47+
MP_DEFINE_CONST_FUN_OBJ_1(espnow_stats_get_success_obj, espnow_stats_get_success);
48+
49+
MP_PROPERTY_GETTER(espnow_stats_success_obj,
50+
(mp_obj_t)&espnow_stats_get_success_obj);
51+
52+
//| failure: int
53+
//| """The number of failures. (read-only)
54+
//|
55+
//| * In case of transmit ``TX``:
56+
//| The number of failed tx packets ``ESP_NOW_SEND_FAIL``.
57+
//|
58+
//| * In case of receive ``RX``:
59+
//| The number of dropped rx packets due to buffer overflow."""
60+
//|
61+
STATIC mp_obj_t espnow_stats_get_failure(const mp_obj_t self_in) {
62+
espnow_stats_obj_t *self = MP_OBJ_TO_PTR(self_in);
63+
return mp_obj_new_int_from_uint(self->failure);
64+
}
65+
MP_DEFINE_CONST_FUN_OBJ_1(espnow_stats_get_failure_obj, espnow_stats_get_failure);
66+
67+
MP_PROPERTY_GETTER(espnow_stats_failure_obj,
68+
(mp_obj_t)&espnow_stats_get_failure_obj);
69+
70+
STATIC const mp_rom_map_elem_t espnow_stats_locals_dict_table[] = {
71+
// Peer parameters
72+
{ MP_ROM_QSTR(MP_QSTR_success), MP_ROM_PTR(&espnow_stats_success_obj) },
73+
{ MP_ROM_QSTR(MP_QSTR_failure), MP_ROM_PTR(&espnow_stats_failure_obj) },
74+
};
75+
STATIC MP_DEFINE_CONST_DICT(espnow_stats_locals_dict, espnow_stats_locals_dict_table);
76+
77+
espnow_stats_obj_t *espnow_stats_new(void) {
78+
espnow_stats_obj_t *self = m_new_obj(espnow_stats_obj_t);
79+
self->base.type = &espnow_stats_type;
80+
return self;
81+
}
82+
83+
const mp_obj_type_t espnow_stats_type = {
84+
{ &mp_type_type },
85+
.name = MP_QSTR_ESPNowStats,
86+
.locals_dict = (mp_obj_t)&espnow_stats_locals_dict,
87+
};
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2023 MicroDev
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#pragma once
28+
29+
#include "py/obj.h"
30+
31+
typedef struct {
32+
mp_obj_base_t base;
33+
volatile size_t success;
34+
volatile size_t failure;
35+
} espnow_stats_obj_t;
36+
37+
const mp_obj_type_t espnow_stats_type;
38+
extern espnow_stats_obj_t *espnow_stats_new(void);

ports/espressif/bindings/espnow/Peers.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535

3636
#include "esp_now.h"
3737

38+
// TODO: Check for deinit
39+
3840
//| class Peers:
3941
//| """A class that provides peer managment functions. Sequence[Peer]."""
4042
//|

ports/espressif/bindings/espnow/__init__.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "bindings/espnow/__init__.h"
3030
#include "bindings/espnow/ESPNow.h"
3131
#include "bindings/espnow/ESPNowPacket.h"
32+
#include "bindings/espnow/ESPNowStats.h"
3233
#include "bindings/espnow/Peer.h"
3334
#include "bindings/espnow/Peers.h"
3435

@@ -51,7 +52,7 @@
5152
//|
5253
//| e.send("Starting...")
5354
//| for i in range(100):
54-
//| e.send(peer, str(i)*20, True)
55+
//| e.send(str(i)*20)
5556
//| e.send(b'end')
5657
//|
5758
//| **Receiver**
@@ -84,6 +85,7 @@ STATIC const mp_rom_map_elem_t espnow_module_globals_table[] = {
8485
// module classes
8586
{ MP_ROM_QSTR(MP_QSTR_ESPNow), MP_ROM_PTR(&espnow_type) },
8687
{ MP_ROM_QSTR(MP_QSTR_ESPNowPacket),MP_ROM_PTR(&espnow_packet_type_obj) },
88+
{ MP_ROM_QSTR(MP_QSTR_ESPNowStats), MP_ROM_PTR(&espnow_stats_type) },
8789
{ MP_ROM_QSTR(MP_QSTR_Peer), MP_ROM_PTR(&espnow_peer_type) },
8890
{ MP_ROM_QSTR(MP_QSTR_Peers), MP_ROM_PTR(&espnow_peers_type) },
8991
};

0 commit comments

Comments
 (0)