Skip to content

Commit 2b1b509

Browse files
rlubosdanieldegrasse
authored andcommitted
tests: net: lwm2m: interop: Add custom tests for observe atributes
Add custom interoperability tests verifying that numerical observe attributes work as expected. Signed-off-by: Robert Lubos <[email protected]>
1 parent 8aa842c commit 2b1b509

File tree

1 file changed

+157
-0
lines changed

1 file changed

+157
-0
lines changed
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
"""
2+
Tests for Observe attributes in LwM2M
3+
#####################################
4+
5+
Copyright (c) 2025 Nordic Semiconductor ASA
6+
7+
SPDX-License-Identifier: Apache-2.0
8+
"""
9+
10+
import time
11+
12+
import pytest
13+
from leshan import Leshan
14+
from twister_harness import Shell
15+
16+
TEST_PMAX: float = 4
17+
TEST_TIME_ACC: float = 0.5
18+
19+
20+
def test_attribute_gt_lt_st_wrong_res_type(leshan: Leshan, endpoint: str):
21+
"""
22+
Verify that gt/lt/st attributes only be assigned to numerical resources.
23+
"""
24+
# Manufacturer - should fail as that's a string type
25+
assert leshan.write_attributes(endpoint, '3/0/0', {'gt': 4200})['status'] != 'CHANGED(204)'
26+
assert leshan.write_attributes(endpoint, '3/0/0', {'lt': 3000})['status'] != 'CHANGED(204)'
27+
assert leshan.write_attributes(endpoint, '3/0/0', {'st': 200})['status'] != 'CHANGED(204)'
28+
# Battery level - should be fine
29+
assert leshan.write_attributes(endpoint, '3/0/7', {'gt': 4200})['status'] == 'CHANGED(204)'
30+
assert leshan.write_attributes(endpoint, '3/0/7', {'lt': 3000})['status'] == 'CHANGED(204)'
31+
assert leshan.write_attributes(endpoint, '3/0/7', {'st': 200})['status'] == 'CHANGED(204)'
32+
leshan.remove_attributes(endpoint, '3/0/7', ['gt'])
33+
leshan.remove_attributes(endpoint, '3/0/7', ['lt'])
34+
leshan.remove_attributes(endpoint, '3/0/7', ['st'])
35+
36+
37+
@pytest.mark.slow
38+
def test_attribute_step(shell: Shell, leshan: Leshan, endpoint: str):
39+
"""
40+
Verify that Step attribute is respected when sending notifications
41+
"""
42+
assert leshan.write_attributes(endpoint, '3/0/7', {'st': 200})['status'] == 'CHANGED(204)'
43+
assert (
44+
leshan.write_attributes(endpoint, '3/0/7', {'pmax': TEST_PMAX})['status'] == 'CHANGED(204)'
45+
)
46+
leshan.observe(endpoint, '3/0/7')
47+
with leshan.get_event_stream(endpoint, timeout=30) as events:
48+
shell.exec_command('lwm2m write /3/0/7/0 -u32 3000')
49+
data = events.next_event('NOTIFICATION')
50+
assert data is not None
51+
assert data[3][0][7][0] == 3000
52+
# Ensure that we don't get new notification before pmax expires
53+
start = time.time()
54+
shell.exec_command('lwm2m write /3/0/7/0 -u32 3100')
55+
data = events.next_event('NOTIFICATION')
56+
assert data[3][0][7][0] == 3100
57+
assert (start + TEST_PMAX) < time.time() + TEST_TIME_ACC
58+
assert (start + TEST_PMAX) > time.time() - TEST_TIME_ACC
59+
# Step attribute condition should be satisfied
60+
start = time.time()
61+
shell.exec_command('lwm2m write /3/0/7/0 -u32 3500')
62+
data = events.next_event('NOTIFICATION')
63+
assert data[3][0][7][0] == 3500
64+
assert start <= time.time() + TEST_TIME_ACC
65+
leshan.cancel_observe(endpoint, '3/0/7')
66+
leshan.remove_attributes(endpoint, '3/0/7', ['st'])
67+
leshan.remove_attributes(endpoint, '3/0/7', ['pmax'])
68+
69+
70+
@pytest.mark.slow
71+
def test_attribute_greater_than(shell: Shell, leshan: Leshan, endpoint: str):
72+
"""
73+
Verify that Greater Than attribute is respected when sending notifications
74+
"""
75+
assert leshan.write_attributes(endpoint, '3/0/7', {'gt': 4200})['status'] == 'CHANGED(204)'
76+
assert (
77+
leshan.write_attributes(endpoint, '3/0/7', {'pmax': TEST_PMAX})['status'] == 'CHANGED(204)'
78+
)
79+
leshan.observe(endpoint, '3/0/7')
80+
with leshan.get_event_stream(endpoint, timeout=30) as events:
81+
shell.exec_command('lwm2m write /3/0/7/0 -u32 3000')
82+
data = events.next_event('NOTIFICATION')
83+
assert data is not None
84+
assert data[3][0][7][0] == 3000
85+
# Ensure that we don't get new notification before pmax expires
86+
start = time.time()
87+
shell.exec_command('lwm2m write /3/0/7/0 -u32 4100')
88+
data = events.next_event('NOTIFICATION')
89+
assert data[3][0][7][0] == 4100
90+
assert (start + TEST_PMAX) < time.time() + TEST_TIME_ACC
91+
assert (start + TEST_PMAX) > time.time() - TEST_TIME_ACC
92+
# Greater than attribute condition should be satisfied
93+
start = time.time()
94+
shell.exec_command('lwm2m write /3/0/7/0 -u32 4400')
95+
data = events.next_event('NOTIFICATION')
96+
assert data[3][0][7][0] == 4400
97+
assert start <= time.time() + TEST_TIME_ACC
98+
# Still above threshold - no new notification expected before pmax
99+
start = time.time()
100+
shell.exec_command('lwm2m write /3/0/7/0 -u32 4300')
101+
data = events.next_event('NOTIFICATION')
102+
assert data[3][0][7][0] == 4300
103+
assert (start + TEST_PMAX) < time.time() + TEST_TIME_ACC
104+
assert (start + TEST_PMAX) > time.time() - TEST_TIME_ACC
105+
# Greater than attribute condition should be satisfied again
106+
start = time.time()
107+
shell.exec_command('lwm2m write /3/0/7/0 -u32 4100')
108+
data = events.next_event('NOTIFICATION')
109+
assert data[3][0][7][0] == 4100
110+
leshan.cancel_observe(endpoint, '3/0/7')
111+
leshan.remove_attributes(endpoint, '3/0/7', ['gt'])
112+
leshan.remove_attributes(endpoint, '3/0/7', ['pmax'])
113+
114+
115+
@pytest.mark.slow
116+
def test_attribute_less_than(shell: Shell, leshan: Leshan, endpoint: str):
117+
"""
118+
Verify that Less Than attribute is respected when sending notifications
119+
"""
120+
assert leshan.write_attributes(endpoint, '3/0/7', {'gt': 3000})['status'] == 'CHANGED(204)'
121+
assert (
122+
leshan.write_attributes(endpoint, '3/0/7', {'pmax': TEST_PMAX})['status'] == 'CHANGED(204)'
123+
)
124+
leshan.observe(endpoint, '3/0/7')
125+
with leshan.get_event_stream(endpoint, timeout=30) as events:
126+
shell.exec_command('lwm2m write /3/0/7/0 -u32 3200')
127+
data = events.next_event('NOTIFICATION')
128+
assert data is not None
129+
assert data[3][0][7][0] == 3200
130+
# Ensure that we don't get new notification before pmax expires
131+
start = time.time()
132+
shell.exec_command('lwm2m write /3/0/7/0 -u32 3100')
133+
data = events.next_event('NOTIFICATION')
134+
assert data[3][0][7][0] == 3100
135+
assert (start + TEST_PMAX) < time.time() + TEST_TIME_ACC
136+
assert (start + TEST_PMAX) > time.time() - TEST_TIME_ACC
137+
# Less than attribute condition should be satisfied
138+
start = time.time()
139+
shell.exec_command('lwm2m write /3/0/7/0 -u32 2800')
140+
data = events.next_event('NOTIFICATION')
141+
assert data[3][0][7][0] == 2800
142+
assert start <= time.time() + TEST_TIME_ACC
143+
# Still below threshold - no new notification expected before pmax
144+
start = time.time()
145+
shell.exec_command('lwm2m write /3/0/7/0 -u32 2900')
146+
data = events.next_event('NOTIFICATION')
147+
assert data[3][0][7][0] == 2900
148+
assert (start + TEST_PMAX) < time.time() + TEST_TIME_ACC
149+
assert (start + TEST_PMAX) > time.time() - TEST_TIME_ACC
150+
# Less than attribute condition should be satisfied again
151+
start = time.time()
152+
shell.exec_command('lwm2m write /3/0/7/0 -u32 3100')
153+
data = events.next_event('NOTIFICATION')
154+
assert data[3][0][7][0] == 3100
155+
leshan.cancel_observe(endpoint, '3/0/7')
156+
leshan.remove_attributes(endpoint, '3/0/7', ['gt'])
157+
leshan.remove_attributes(endpoint, '3/0/7', ['pmax'])

0 commit comments

Comments
 (0)