1313class LMDirect :
1414 def __init__ (self , key ):
1515 """Init LMDirect"""
16- self .run = True
17- self .cipher = AESCipher (key )
18- self .response_task = None
19- self .status_task = None
20- self .current_status = {}
16+ self ._run = True
17+ self ._cipher = AESCipher (key )
18+ self ._read_response_task = None
19+ self ._poll_status_task = None
20+ self ._current_status = {}
21+ self ._callback = None
22+
23+ def register_callback (self , callback ):
24+ """Register callback for updates"""
25+ if callable (callback ):
26+ self ._callback = callback
2127
2228 async def connect (self , addr ):
2329 """Conmnect to espresso machine"""
@@ -29,34 +35,40 @@ async def connect(self, addr):
2935 loop = asyncio .get_event_loop ()
3036
3137 """Start listening for responses & sending status requests"""
32- self .response_task = loop .create_task (self .response ())
33-
34- """Start sending status requests"""
35- self .status_task = loop .create_task (self .status ())
38+ self ._read_response_task = loop .create_task (
39+ self .read_response_task (), name = "Response Task"
40+ )
3641
3742 async def close (self ):
3843 """Stop listening for responses and close the socket"""
39- self .run = False
44+ self ._run = False
45+ tasks = [self ._read_response_task ]
46+
47+ if self ._poll_status_task :
48+ tasks .append (self ._poll_status_task )
4049
41- await asyncio .gather (* [ self . response_task , self . status_task ] )
50+ await asyncio .gather (* tasks )
4251
4352 """Close the connection"""
4453 self .writer .close ()
4554
46- async def response (self ):
55+ async def read_response_task (self ):
4756 """Start thread to receive responses"""
4857 BUFFER_SIZE = 1000
4958
50- while self .run :
59+ while self ._run :
5160 encoded_data = await self .reader .read (BUFFER_SIZE )
5261
5362 _LOGGER .debug (encoded_data )
5463 if encoded_data is not None :
55- loop = asyncio .get_running_loop ()
56- fn = partial (self .cipher .decrypt , encoded_data [1 :- 1 ])
64+ loop = asyncio .get_event_loop ()
65+ fn = partial (self ._cipher .decrypt , encoded_data [1 :- 1 ])
5766 plaintext = await loop .run_in_executor (None , fn )
5867 await self .process_data (plaintext )
5968
69+ if self ._callback is not None :
70+ self ._callback (self ._current_status )
71+
6072 async def process_data (self , plaintext ):
6173 """Process incoming packet"""
6274
@@ -77,36 +89,50 @@ async def process_data(self, plaintext):
7789
7890 if any (preamble in x for x in CMD .PREAMBLES ):
7991 await self .populate_items (data , CMD .RESP_MAP [preamble ])
80- _LOGGER .debug (self .current_status )
92+ _LOGGER .debug (self ._current_status )
8193
8294 async def populate_items (self , data , map ):
8395 for elem in map :
8496 index = elem .index * 2
8597 size = elem .size * 2
8698
87- value = int (data [index : index + size ], 16 )
88- if any (x in map [elem ] for x in ["TEMP" , "PREBREWING_K" ]):
99+ value = int (data [index : index + size ], 16 )
100+ if any (x in map [elem ] for x in ["TSET" , " TEMP" , "PREBREWING_K" ]):
89101 value = value / 10
90102 elif "AUTO_BITFIELD" in map [elem ]:
91103 for i in range (0 , 7 ):
92104 setting = ENABLED if value & 0x01 else DISABLED
93- self .current_status [CMD .AUTO_BITFIELD_MAP [i ]] = setting
105+ self ._current_status [CMD .AUTO_BITFIELD_MAP [i ]] = setting
94106 value = value >> 1
95107 continue
96- self .current_status [map [elem ]] = value
108+ self ._current_status [map [elem ]] = value
109+
110+ @property
111+ def current_status (self ):
112+ """Return a dict of all the properties that have been received"""
113+ return self ._current_status
97114
98- async def status (self ):
115+ async def create_polling_task (self ):
116+ """Start a polling task"""
117+ self ._poll_status_task = asyncio .get_event_loop ().create_task (
118+ self .poll_status_task (), name = "Request Status Task"
119+ )
120+
121+ async def poll_status_task (self ):
99122 """Send periodic status requests"""
100- while self .run :
101- await self .send_cmd (CMD .STATUS )
102- await self .send_cmd (CMD .CONFIG )
103- await self .send_cmd (CMD .AUTO_SCHED )
123+ while self ._run :
124+ await self .request_status ()
104125 await asyncio .sleep (5 )
105126
127+ async def request_status (self ):
128+ await self .send_cmd (CMD .STATUS )
129+ await self .send_cmd (CMD .CONFIG )
130+ await self .send_cmd (CMD .AUTO_SCHED )
131+
106132 async def send_cmd (self , cmd ):
107133 """Send command to espresso machine"""
108- loop = asyncio .get_running_loop ()
109- fn = partial (self .cipher .encrypt , cmd )
134+ loop = asyncio .get_event_loop ()
135+ fn = partial (self ._cipher .encrypt , cmd )
110136 ciphertext = "@" + (await loop .run_in_executor (None , fn )).decode ("utf-8" ) + "%"
111137 _LOGGER .debug (ciphertext )
112138
0 commit comments