Skip to content

Commit a6d24ee

Browse files
committed
- adds validation of schedule items against retrieved stock
- adds some memoization to stock access - removes conflicting cancel gesture for weighing states in tap_cancel_green_task_slot
1 parent 81e4413 commit a6d24ee

9 files changed

Lines changed: 102 additions & 52 deletions

File tree

src/artisanlib/acaia.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,8 @@ def on_connect(self) -> None:
311311
else:
312312
self.max_weight = 1000
313313
self.readability = 0.1
314+
self.fast_notifications()
315+
self.fast_notifications_sent = False
314316

315317
else: #connected_service_UUID == ACAIA_SERVICE_UUID:
316318
_log.debug('connected to Acaia Scale (%s)', connected_device_name)
@@ -401,9 +403,9 @@ def decode_weight(self, payload:bytes) -> Tuple[Optional[float], bool]:
401403
return None, False
402404

403405
def update_weight(self, value:Optional[float], stable:Optional[bool] = False) -> None:
404-
# _log.debug('PRINT update_weight(%s,%s)', value, stable)
406+
_log.debug('PRINT update_weight(%s,%s)', value, stable)
405407
if value is not None and (not self.stable_only or stable):
406-
# convert the weight in g delivered with one decimals to an int
408+
# convert the weight in g delivered with one decimal to an int
407409
value_rounded:float = float2float(value, self.decimals)
408410
if stable and value_rounded != self.stable_weight:
409411
# if value is fresh and reading is stable (if self.stable_only is set)
@@ -674,13 +676,15 @@ def parse_data(self, msg_type:int, data:bytes) -> None:
674676
try:
675677
if msg_type == CMD.INFO_A:
676678
self.parse_info(data)
677-
self.send_ID() # send also after very INFO_A as handshake confirmation
679+
self.send_ID() # send after very INFO_A as handshake confirmation
678680
elif msg_type == CMD.STATUS_A:
679681
self.parse_status(data)
680682
elif msg_type == CMD.EVENT_SA:
681683
self.parse_scale_events(data)
682684
#
683-
if self.id_sent and not self.fast_notifications_sent:
685+
if self.id_sent and (not self.fast_notifications_sent or not self.slow_notifications_sent):
686+
# NOTE: in some cases previously send fast_notifications are ignore so we have to repeat sending them until we received some initial weight data
687+
# (until self.slow_notifications_sent is set)
684688
# we configure the scale to receive the initial
685689
# weight notification as fast as possible
686690
# Note: this event is needed to have the connected scale start to send weight messages even on relay scales which ignore the settings

src/artisanlib/async_comm.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def start_background_loop(loop:asyncio.AbstractEventLoop) -> None:
6161
def __del__(self) -> None:
6262
self.__loop.call_soon_threadsafe(self.__loop.stop) # pyrefly: ignore[bad-argument-type]
6363
# self.__thread.join()
64-
# WARNING: we don't join and expect the clients running on this thread to stop themself
64+
# WARNING: we don't join and expect the clients running on this thread to stop them
6565
# (using self._running) to finally get rid of this thread to prevent hangs
6666

6767
@property
@@ -149,8 +149,8 @@ def __init__(self, host:str = '127.0.0.1', port:int = 8080, serial:Optional['Ser
149149
disconnected_handler:Optional[Callable[[], None]] = None) -> None:
150150
# internals
151151
self._asyncLoopThread: Optional[AsyncLoopThread] = None # the asyncio AsyncLoopThread object
152-
self._write_queue: 'Optional[asyncio.Queue[bytes]]' = None # noqa: UP037 # quotes for Python3.8 # the write queue
153-
self._running:bool = False # while True we keep running the thread
152+
self._write_queue: 'Optional[asyncio.Queue[bytes]]' = None # noqa: UP037 # quotes for Python3.8 # the write_queue
153+
self._running:bool = False # while true we keep running the thread
154154

155155
# connection
156156
self._host:str = host
@@ -256,7 +256,7 @@ async def handle_writes(self, writer: asyncio.StreamWriter, queue: 'asyncio.Queu
256256
with suppress(asyncio.CancelledError, ConnectionResetError):
257257
await writer.drain()
258258

259-
# if serial settings are given, host/port are ignore and communication is handled by the given serial port
259+
# if serial settings are given, the host/port settings are ignored and communication is handled by the given serial port
260260
async def connect(self, connect_timeout:float=5) -> None:
261261
writer:Optional[asyncio.StreamWriter] = None
262262
while self._running:

src/artisanlib/ble_port.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ async def _connect(self, case_sensitive:bool=True, scan_timeout:float=6, connect
326326
_log.error(e)
327327
if self._connected_service_uuid is None:
328328
# the client does not offer our service thus we put its
329-
# address on the blacklist to be ignore on next discover
329+
# address on the blacklist to be ignored on next discover
330330
# and disconnect
331331
##blacklist.add(self._ble_client.address) # we don't blacklist as the searched for service might just not yet be discovered
332332
self._disconnect()

src/artisanlib/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5390,7 +5390,7 @@ def setRecentRoast(self, rr:'RecentRoast') -> None:
53905390
if self.qmc.plus_blend_spec is not None and 'hr_id' in self.qmc.plus_blend_spec and self.qmc.plus_store is not None:
53915391
try:
53925392
weight_unit_idx = weight_units.index(rr['weightUnit'])
5393-
blends = plus.stock.getBlends(weight_unit_idx,self.qmc.plus_store)
5393+
blends = plus.stock.getStandardBlends(weight_unit_idx,self.qmc.plus_store)
53945394
blend = next(b for b in blends if \
53955395
plus.stock.getBlendId(b) == self.qmc.plus_blend_spec['hr_id'] and
53965396
plus.stock.getBlendStockDict(b)['location_hr_id'] == self.qmc.plus_store)

src/artisanlib/roast_properties.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4394,6 +4394,7 @@ def roastpropertiesChanged(self, _:int = 0) -> None:
43944394
@pyqtSlot(int)
43954395
def labelOriginFlagChanged(self, _:int = 0) -> None:
43964396
plus.stock.coffee_label_normal_order = self.label_origin_flag.isChecked()
4397+
plus.stock.clearStockCaches() # we need to clear the stock caches to receive the updated coffee labels
43974398
self.populatePlusCoffeeBlendCombos() # update the plus stock popups to display the correct bean label format
43984399

43994400
@pyqtSlot(int)

src/artisanlib/scale.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,11 @@ def tare_scale(self) -> None:
108108
def is_connected(self) -> bool: # pylint: disable=no-self-use
109109
return False
110110

111+
# weight in g
111112
def max_weight(self) -> float: # pylint: disable=no-self-use
112113
return 0
113114

115+
# readability in g
114116
def readability(self) -> float: # pylint: disable=no-self-use
115117
return 0
116118

@@ -302,6 +304,7 @@ def scale1_disconnected_slot(self) -> None:
302304
self.scale1_disconnected_signal.emit()
303305

304306
## try to catch a last non weight change and send as stable state
307+
# weight in g
305308
@pyqtSlot(float, bool)
306309
def scale1_weight_changed_slot(self, weight:float, stable:bool) -> None:
307310
weight = int(round(weight))
@@ -410,6 +413,7 @@ def scale2_disconnected_slot(self) -> None:
410413
self.scale2_disconnected_signal.emit()
411414

412415
## try to catch a last non weight change and send as stable state
416+
# weight in g
413417
@pyqtSlot(float, bool)
414418
def scale2_weight_changed_slot(self, weight:float, stable:bool) -> None:
415419
weight = int(round(weight))

src/plus/schedule.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,7 @@ def set_visible(plus_account_id:Optional[str], item:ScheduledItem) -> None:
831831
# returns blend name or None and list of components (just one if item is about a coffee
832832
def scheduleditem_beans_descriptions(weight_unit_idx:int, item:ScheduledItem) -> Tuple[Optional[str], List[Tuple[float,str]]]:
833833
if item.blend is not None:
834-
blends = plus.stock.getBlends(weight_unit_idx, item.store)
834+
blends = plus.stock.getStandardBlends(weight_unit_idx, item.store)
835835
blend = next((b for b in blends if plus.stock.getBlendId(b) == item.blend and plus.stock.getBlendStockDict(b)['location_hr_id'] == item.store), None)
836836
if blend is not None:
837837
return plus.stock.blend2ratio_beans(blend, item.weight, html_escape=False)
@@ -840,6 +840,7 @@ def scheduleditem_beans_descriptions(weight_unit_idx:int, item:ScheduledItem) ->
840840
coffee = plus.stock.getCoffee(item_coffee)
841841
if coffee is not None:
842842
return None, [(1,plus.stock.coffeeLabel(coffee))]
843+
_log.error('scheduleditem_beans_descriptions(%s,%s) could not be resolved', weight_unit_idx, item)
843844
return None, []
844845

845846
def scheduleditem_beans_description(weight_unit_idx:int, item:ScheduledItem) -> str:
@@ -853,7 +854,7 @@ def scheduleditem_beans_description(weight_unit_idx:int, item:ScheduledItem) ->
853854
store_label = f'<br>[{html.escape(store_label)}]'
854855
beans_description = f'<b>{html.escape(plus.stock.coffeeLabel(coffee))}</b>{store_label}'
855856
else:
856-
blends = plus.stock.getBlends(weight_unit_idx, item.store)
857+
blends = plus.stock.getStandardBlends(weight_unit_idx, item.store)
857858
blend = next((b for b in blends if plus.stock.getBlendId(b) == item.blend and plus.stock.getBlendStockDict(b)['location_hr_id'] == item.store), None)
858859
if blend is not None:
859860
blend_lines = ''.join([f'<tr><td>{html.escape(bl[0])}</td><td>{html.escape(bl[1])}</td></tr>'
@@ -2787,7 +2788,7 @@ def set_roast_properties(self, item:ScheduledItem, overwrite_nondefault_title:bo
27872788
except Exception as e: # pylint: disable=broad-except
27882789
_log.error(e)
27892790
elif item.blend is not None:
2790-
blends:List[plus.stock.BlendStructure] = plus.stock.getBlends(weight_unit_idx, item.store)
2791+
blends:List[plus.stock.BlendStructure] = plus.stock.getStandardBlends(weight_unit_idx, item.store)
27912792
# NOTE: a blend might not have an hr_id as is the case for all custom blends
27922793
blend_structure:Optional[plus.stock.BlendStructure] = next((bs for bs in blends if plus.stock.getBlendId(bs) == item.blend), None)
27932794
if blend_structure is not None:
@@ -3908,9 +3909,9 @@ def show_item(self, item:'WeightItem', state:PROCESS_STATE = PROCESS_STATE.DISCO
39083909

39093910
self.rendered_task['timer'] = 0 # clear timer start trigger immediately
39103911

3911-
39123912
# current_weight indicates total measured weight over both containers in g (not including the bucket weights)
39133913
def show_progress(self, state:PROCESS_STATE, component:int, bucket:int, current_weight:int) -> None:
3914+
# _log.debug("PRINT show_progress(%s,%s,%s,%s)",state,component,bucket,current_weight)
39143915
if (self.last_item is not None and (self.last_process_state != state or self.last_component != component or self.last_bucket != bucket or
39153916
self.last_current_weight != current_weight)):
39163917
self.last_process_state = state
@@ -3927,6 +3928,7 @@ def show_progress(self, state:PROCESS_STATE, component:int, bucket:int, current_
39273928
self.rendered_task['blend_percent'] = ''
39283929
self.rendered_task['subtitle'] = ''
39293930
self.rendered_task['bucket'] = bucket
3931+
39303932
if state == PROCESS_STATE.WEIGHING and len(self.last_item.descriptions)>component and len(self.last_item.descriptions[component])>0:
39313933
target = self.last_item.weight * 1000 # target in g
39323934
self.rendered_task['total_percent'] = 100 * current_weight / target

0 commit comments

Comments
 (0)