11import copy
2- from .sd_protocol_data import protocols
2+ import json
3+ from pathlib import Path
4+ from typing import Any , Dict
35from .helpers import ProtocolHelpersMixin
46from .manchester import ManchesterMixin
57from .postdemodulation import PostdemodulationMixin
@@ -17,10 +19,23 @@ class SDProtocols(ProtocolHelpersMixin, ManchesterMixin, PostdemodulationMixin,
1719 """
1820
1921 def __init__ (self ):
20- self ._protocols = copy . deepcopy ( protocols )
22+ self ._protocols = self . _load_protocols ( )
2123 self ._log_callback = None
2224 self .set_defaults ()
2325
26+ def _load_protocols (self ) -> Dict [str , Any ]:
27+ """Loads protocols from protocols.json."""
28+ json_path = Path (__file__ ).resolve ().parent / "protocols.json"
29+ try :
30+ with open (json_path , "r" , encoding = "utf-8" ) as f :
31+ data = json .load (f )
32+ return data .get ("protocols" , {})
33+ except Exception as e :
34+ # Fallback or error logging if needed, though for now we raise
35+ # or return empty dict if file missing (should not happen in prod)
36+ print (f"Error loading protocols.json: { e } " )
37+ return {}
38+
2439 def protocol_exists (self , pid : str ) -> bool :
2540 return pid in self ._protocols
2641
@@ -38,6 +53,50 @@ def check_property(self, pid: str, value_name: str, default=None):
3853 def get_property (self , pid : str , value_name : str ):
3954 return self ._protocols .get (pid , {}).get (value_name )
4055
56+ def demodulate_mn (self , msg_data : Dict [str , Any ], msg_type : str ) -> list :
57+ """Attempts to demodulate an MN message using registered protocols."""
58+ if "protocol_id" not in msg_data :
59+ self ._logging (f"MN Demodulation failed: Missing protocol_id in msg_data: { msg_data } " , 3 )
60+ return []
61+
62+ protocol_id = msg_data ["protocol_id" ]
63+
64+ if not self .protocol_exists (protocol_id ):
65+ self ._logging (f"MN Demodulation: Protocol ID { protocol_id } not found." , 3 )
66+ return []
67+
68+ method_name_full = self .get_property (protocol_id , 'method' )
69+
70+ if not method_name_full :
71+ self ._logging (f"MN Demodulation: No method defined for protocol { protocol_id } . Data: { msg_data .get ('data' , '' )} " , 3 )
72+ return []
73+
74+ # MN messages usually pass the raw data directly (no bit conversion)
75+ # We assume the method handles raw hex/data string or needs it as hex.
76+ # The method name is expected to be 'method_name' or 'module.method_name'
77+ method_name = method_name_full .split ('.' )[- 1 ]
78+
79+ if hasattr (self , method_name ) and callable (getattr (self , method_name )):
80+ method_func = getattr (self , method_name )
81+
82+ # MN methods might be called differently than MC methods, let's check existing ones
83+ # For now, we will assume they take msg_data and return a list of decoded messages/dicts
84+ try :
85+ # Generic call signature for new methods, using msg_data and msg_type for context
86+ demodulated_list = method_func (msg_data , msg_type )
87+ except TypeError :
88+ self ._logging (f"MN Demodulation: Method { method_name } failed due to wrong signature/arguments." , 3 )
89+ return []
90+ else :
91+ self ._logging (f"MN Demodulation: Unknown method { method_name } referenced by '{ method_name_full } '." , 3 )
92+ return []
93+
94+ if not isinstance (demodulated_list , list ):
95+ self ._logging (f"MN Demodulation: Method { method_name } returned non-list: { type (demodulated_list )} ." , 3 )
96+ return []
97+
98+ return demodulated_list
99+
41100 def set_defaults (self ):
42101 for pid , proto in self ._protocols .items ():
43102 proto .setdefault ("active" , True )
@@ -52,4 +111,3 @@ def _logging(self, message: str, level: int = 3):
52111 """Log a message if a callback is registered."""
53112 if self ._log_callback :
54113 self ._log_callback (message , level )
55-
0 commit comments