summaryrefslogtreecommitdiffstats
path: root/utils/bigclown/bigclown-gateway/0002-fix-support-for-decimals.patch
blob: 1736cc99575d62b168848a44a91af5bee469748e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
From df50e792cbc0c6e03fde2397e9802c81bca1c89b Mon Sep 17 00:00:00 2001
From: Martin Pecka <peci1@seznam.cz>
Date: Wed, 22 Oct 2025 02:15:04 +0200
Subject: [PATCH] Fix support for Decimals

---
 bcg/gateway.py | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

--- a/bcg/gateway.py
+++ b/bcg/gateway.py
@@ -11,11 +11,26 @@ import yaml
 import serial
 import paho.mqtt.client
 import appdirs
+from collections.abc import Mapping, Iterable
 
 if platform.system() == 'Linux':
     import fcntl
 
 
+# https://stackoverflow.com/a/60243503/1076564
+class DecimalJSONEncoder(json.JSONEncoder):
+    """Add support for encoding Decimal"""
+    def encode(self, obj):
+        if isinstance(obj, Mapping):
+            return '{' + ', '.join(f'{self.encode(k)}: {self.encode(v)}' for (k, v) in obj.items()) + '}'
+        if isinstance(obj, Iterable) and (not isinstance(obj, str)):
+            return '[' + ', '.join(map(self.encode, obj)) + ']'
+        if isinstance(obj, decimal.Decimal):
+            # using normalize() gets rid of trailing 0s, using ':f' prevents scientific notation
+            return f'{obj.normalize():f}'
+        return super().encode(obj)
+
+
 class Gateway:
 
     def __init__(self, config):
@@ -218,7 +233,7 @@ class Gateway:
             node_id = self._node_rename_name.get(node_name, None)
             if node_id:
                 topic = node_id + topic[i:]
-        line = json.dumps([topic, payload], use_decimal=True) + '\n'
+        line = json.dumps([topic, payload], cls=DecimalJSONEncoder) + '\n'
         line = line.encode('utf-8')
         logging.debug("write %s", line)
         self.ser.write(line)
@@ -226,7 +241,7 @@ class Gateway:
     def publish(self, topic, payload):
         if isinstance(topic, list):
             topic = '/'.join(topic)
-        self.mqttc.publish(self._config['base_topic_prefix'] + topic, json.dumps(payload, use_decimal=True), qos=1)
+        self.mqttc.publish(self._config['base_topic_prefix'] + topic, json.dumps(payload, cls=DecimalJSONEncoder), qos=1)
 
     def log_message(self, line):
         logging.debug('log_message %s', line)
@@ -324,7 +339,7 @@ class Gateway:
             if node_name:
                 subtopic = node_name + '/' + topic
 
-            self.mqttc.publish(self._config['base_topic_prefix'] + "node/" + subtopic, json.dumps(payload, use_decimal=True), qos=self._msg_qos, retain=self._msg_retain)
+            self.mqttc.publish(self._config['base_topic_prefix'] + "node/" + subtopic, json.dumps(payload, cls=DecimalJSONEncoder), qos=self._msg_qos, retain=self._msg_retain)
 
         except Exception:
             raise