Skip to content

Commit 70b83b2

Browse files
authored
Merge pull request #34 from wilbersl/fix-alarm-and-event-mapping
fix: alarm and event mapping
2 parents b7de64a + 8a1592b commit 70b83b2

File tree

2 files changed

+131
-40
lines changed

2 files changed

+131
-40
lines changed

tedge_modbus/reader/mapper.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
topics = {
1111
"measurement": "te/device/CHILD_ID///m/",
12-
"event": "te/device/CHILD_ID///e/",
13-
"alarm": "te/device/CHILD_ID///a/",
12+
"event": "te/device/CHILD_ID///e/TYPE",
13+
"alarm": "te/device/CHILD_ID///a/TYPE",
1414
}
1515

1616

@@ -215,13 +215,16 @@ def check_alarm(self, value, alarm_mapping, register_type, register_key):
215215
# raise alarm if bit is 1
216216
if (old_data is None or old_data == 0) and value > 0:
217217
severity = alarm_mapping["severity"].lower()
218-
alarm_type = alarm_mapping["type"]
218+
alarm_type = alarm_mapping.get("type", "")
219219
text = alarm_mapping["text"]
220220
topic = topics["alarm"]
221221
topic = topic.replace("CHILD_ID", self.device.get("name"))
222-
topic = topic.replace("SEVERITY", severity)
223222
topic = topic.replace("TYPE", alarm_type)
224-
data = {"text": text, "time": datetime.now(timezone.utc).isoformat()}
223+
data = {
224+
"text": text,
225+
"severity": severity,
226+
"time": datetime.now(timezone.utc).isoformat(),
227+
}
225228
messages.append(MappedMessage(json.dumps(data), topic))
226229
return messages
227230

@@ -231,7 +234,7 @@ def check_event(self, value, event_mapping, register_type, register_key):
231234
old_data = self.data.get(register_type).get(register_key)
232235
# raise event if value changed
233236
if old_data is None or old_data != value:
234-
eventtype = event_mapping["type"]
237+
eventtype = event_mapping.get("type", "")
235238
text = event_mapping["text"]
236239
topic = topics["event"]
237240
topic = topic.replace("CHILD_ID", self.device.get("name"))

tests/unit/test_mapper.py

Lines changed: 122 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,19 @@ def test_on_change_true_and_value_changes(self):
3333
}
3434

3535
# First poll: Should always publish
36-
messages1 = self.mapper.map_register(
36+
messages1, _ = self.mapper.map_register(
3737
read_register=[123], register_def=register_def
3838
)
3939
self.assertEqual(len(messages1), 1, "Should publish on first poll")
4040
data1 = json.loads(messages1[0].data)
4141
self.assertAlmostEqual(data1["temp"], 123.0)
4242

4343
# Second poll with a different value: Should publish
44-
messages2 = self.mapper.map_register(
44+
messages, _ = self.mapper.map_register(
4545
read_register=[456], register_def=register_def
4646
)
47-
self.assertEqual(len(messages2), 1, "Should publish when value changes")
48-
data2 = json.loads(messages2[0].data)
47+
self.assertEqual(len(messages), 1, "Should publish when value changes")
48+
data2 = json.loads(messages[0].data)
4949
self.assertAlmostEqual(data2["temp"], 456.0)
5050

5151
def test_on_change_true_and_value_is_same(self):
@@ -59,18 +59,16 @@ def test_on_change_true_and_value_is_same(self):
5959
}
6060

6161
# First poll: should publish
62-
messages1 = self.mapper.map_register(
62+
messages1, _ = self.mapper.map_register(
6363
read_register=[123], register_def=register_def
6464
)
6565
self.assertEqual(len(messages1), 1, "Should publish on first poll")
6666

6767
# Second poll with the same value: should NOT publish
68-
messages2 = self.mapper.map_register(
68+
messages, _ = self.mapper.map_register(
6969
read_register=[123], register_def=register_def
7070
)
71-
self.assertEqual(
72-
len(messages2), 0, "Should not publish when value is unchanged"
73-
)
71+
self.assertEqual(len(messages), 0, "Should not publish when value is unchanged")
7472

7573
def test_on_change_false_and_value_is_same(self):
7674
register_def = {
@@ -82,16 +80,16 @@ def test_on_change_false_and_value_is_same(self):
8280
"measurementmapping": {"templatestring": '{"temp": %%}'},
8381
}
8482

85-
messages1 = self.mapper.map_register(
83+
messages1, _ = self.mapper.map_register(
8684
read_register=[123], register_def=register_def
8785
)
8886
self.assertEqual(len(messages1), 1)
8987

90-
messages2 = self.mapper.map_register(
88+
messages, _ = self.mapper.map_register(
9189
read_register=[123], register_def=register_def
9290
)
9391
self.assertEqual(
94-
len(messages2), 1, "Should always publish when on_change is false"
92+
len(messages), 1, "Should always publish when on_change is false"
9593
)
9694

9795
def test_on_change_not_present_and_value_is_same(self):
@@ -103,16 +101,16 @@ def test_on_change_not_present_and_value_is_same(self):
103101
"measurementmapping": {"templatestring": '{"temp": %%}'},
104102
}
105103

106-
messages1 = self.mapper.map_register(
104+
messages1, _ = self.mapper.map_register(
107105
read_register=[123], register_def=register_def
108106
)
109107
self.assertEqual(len(messages1), 1)
110108

111-
messages2 = self.mapper.map_register(
109+
messages, _ = self.mapper.map_register(
112110
read_register=[123], register_def=register_def
113111
)
114112
self.assertEqual(
115-
len(messages2), 1, "Should default to on_change=false and always publish"
113+
len(messages), 1, "Should default to on_change=false and always publish"
116114
)
117115

118116
def test_on_change_with_float_values(self):
@@ -131,7 +129,7 @@ def float_to_regs(f_val):
131129
}
132130

133131
# First poll with 123.45
134-
messages1 = self.mapper.map_register(
132+
messages1, _ = self.mapper.map_register(
135133
read_register=list(float_to_regs(123.45)), register_def=register_def
136134
)
137135
self.assertEqual(
@@ -141,24 +139,24 @@ def float_to_regs(f_val):
141139
self.assertAlmostEqual(data1["voltage"], 123.45, places=5)
142140

143141
# Second poll, same value
144-
messages2 = self.mapper.map_register(
142+
messages, _ = self.mapper.map_register(
145143
read_register=list(float_to_regs(123.45)), register_def=register_def
146144
)
147145
self.assertEqual(
148-
len(messages2), 0, "Should not publish when float value is the same"
146+
len(messages), 0, "Should not publish when float value is the same"
149147
)
150148

151149
# Third poll, very close value (should be considered the same by math.isclose)
152150
close_value = 123.45 + 1e-8
153-
messages3 = self.mapper.map_register(
151+
messages3, _ = self.mapper.map_register(
154152
read_register=list(float_to_regs(close_value)), register_def=register_def
155153
)
156154
self.assertEqual(
157155
len(messages3), 0, "Should not publish for very close float values"
158156
)
159157

160158
# Fourth poll, different value
161-
messages4 = self.mapper.map_register(
159+
messages4, _ = self.mapper.map_register(
162160
read_register=list(float_to_regs(125.0)), register_def=register_def
163161
)
164162
self.assertEqual(
@@ -187,27 +185,29 @@ def test_separate_measurements(self):
187185
}
188186

189187
# First poll: Check if all Messagetypes get send out
190-
messages1 = self.mapper.map_register(
188+
messages1, _ = self.mapper.map_register(
191189
read_register=[1], register_def=register_def
192190
)
193191
topics1 = [message.topic for message in messages1]
194192
self.assertTrue("te/device/test_device///m/" in topics1)
195-
self.assertTrue("te/device/test_device///e/" in topics1)
196-
self.assertTrue("te/device/test_device///a/" in topics1)
193+
self.assertTrue("te/device/test_device///e/TestEvent" in topics1)
194+
self.assertTrue("te/device/test_device///a/TestAlarm" in topics1)
197195

198196
self.mapper.map_register(read_register=[0], register_def=register_def)
199197
# Second poll: Check if Measurements get separated
200-
messages2, measurement3 = self.mapper.map_register(
201-
read_register=[1], register_def=register_def, separate_measurement=True
198+
messages, measurement3 = self.mapper.map_register(
199+
read_register=[1],
200+
register_def=register_def,
201+
device_combine_measurements=True,
202202
)
203-
topics2 = [message.topic for message in messages2]
204-
self.assertTrue("te/device/test_device///m/" not in topics2)
205-
self.assertTrue("te/device/test_device///e/" in topics2)
206-
self.assertTrue("te/device/test_device///a/" in topics2)
203+
topics = [message.topic for message in messages]
204+
self.assertTrue("te/device/test_device///m/" not in topics)
205+
self.assertTrue("te/device/test_device///e/TestEvent" in topics)
206+
self.assertTrue("te/device/test_device///a/TestAlarm" in topics)
207207

208208
self.assertTrue("te/device/test_device///m/" in measurement3.topic)
209-
self.assertTrue("te/device/test_device///e/" not in measurement3.topic)
210-
self.assertTrue("te/device/test_device///a/" not in measurement3.topic)
209+
self.assertTrue("te/device/test_device///e/TestEvent" not in measurement3.topic)
210+
self.assertTrue("te/device/test_device///a/TestAlarm" not in measurement3.topic)
211211

212212
def test_combine_messages(self):
213213
register_def1 = {
@@ -236,13 +236,19 @@ def test_combine_messages(self):
236236
}
237237

238238
_, measurement1 = self.mapper.map_register(
239-
read_register=[25], register_def=register_def1, separate_measurement=True
239+
read_register=[25],
240+
register_def=register_def1,
241+
device_combine_measurements=True,
240242
)
241243
_, measurement2 = self.mapper.map_register(
242-
read_register=[43], register_def=register_def2, separate_measurement=True
244+
read_register=[43],
245+
register_def=register_def2,
246+
device_combine_measurements=True,
243247
)
244248
_, measurement3 = self.mapper.map_register(
245-
read_register=[21], register_def=register_def3, separate_measurement=True
249+
read_register=[21],
250+
register_def=register_def3,
251+
device_combine_measurements=True,
246252
)
247253

248254
measurement1.extend_data(measurement2)
@@ -252,3 +258,85 @@ def test_combine_messages(self):
252258
self.assertAlmostEqual(data["sensor1"]["temp"], 25.0)
253259
self.assertAlmostEqual(data["sensor1"]["RH"], 43.0)
254260
self.assertAlmostEqual(data["sensor2"]["temp"], 21.0)
261+
262+
def test_alarm_mapping(self):
263+
register_def = {
264+
"number": 100,
265+
"startbit": 0,
266+
"nobits": 16,
267+
"signed": False,
268+
"alarmmapping": {
269+
"severity": "MAJOR",
270+
"text": "This alarm tests the alarm mapping",
271+
"type": "TestAlarm",
272+
},
273+
}
274+
register_def2 = {
275+
"number": 101,
276+
"startbit": 0,
277+
"nobits": 16,
278+
"signed": False,
279+
"alarmmapping": {
280+
"severity": "MAJOR",
281+
"text": "This alarm tests the alarm mapping",
282+
},
283+
}
284+
285+
messages, _ = self.mapper.map_register(
286+
read_register=[1], register_def=register_def
287+
)
288+
topics = [message.topic for message in messages]
289+
self.assertTrue("te/device/test_device///a/TestAlarm" in topics)
290+
self.assertEqual(len(messages), 1)
291+
alarm_data = json.loads(messages[0].data)
292+
self.assertEqual(alarm_data["severity"], "major")
293+
self.assertEqual(alarm_data["text"], "This alarm tests the alarm mapping")
294+
295+
messages2, _ = self.mapper.map_register(
296+
read_register=[1], register_def=register_def2
297+
)
298+
topics2 = [message.topic for message in messages2]
299+
self.assertTrue("te/device/test_device///a/" in topics2)
300+
self.assertEqual(len(messages2), 1)
301+
alarm_data2 = json.loads(messages2[0].data)
302+
self.assertEqual(alarm_data2["severity"], "major")
303+
self.assertEqual(alarm_data2["text"], "This alarm tests the alarm mapping")
304+
305+
def test_event_mapping(self):
306+
register_def = {
307+
"number": 100,
308+
"startbit": 0,
309+
"nobits": 16,
310+
"signed": False,
311+
"eventmapping": {
312+
"text": "This event tests the event mapping",
313+
"type": "TestEvent",
314+
},
315+
}
316+
register_def2 = {
317+
"number": 101,
318+
"startbit": 0,
319+
"nobits": 16,
320+
"signed": False,
321+
"eventmapping": {
322+
"text": "This event tests the event mapping",
323+
},
324+
}
325+
326+
messages, _ = self.mapper.map_register(
327+
read_register=[1], register_def=register_def
328+
)
329+
topics = [message.topic for message in messages]
330+
self.assertTrue("te/device/test_device///e/TestEvent" in topics)
331+
self.assertEqual(len(messages), 1)
332+
event_data = json.loads(messages[0].data)
333+
self.assertEqual(event_data["text"], "This event tests the event mapping")
334+
335+
messages2, _ = self.mapper.map_register(
336+
read_register=[1], register_def=register_def2
337+
)
338+
topics2 = [message.topic for message in messages2]
339+
self.assertTrue("te/device/test_device///e/" in topics2)
340+
self.assertEqual(len(messages2), 1)
341+
event_data2 = json.loads(messages2[0].data)
342+
self.assertEqual(event_data2["text"], "This event tests the event mapping")

0 commit comments

Comments
 (0)