python-jebao 0.1.5__tar.gz → 0.1.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-jebao
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Summary: Python library for controlling Jebao aquarium pumps
5
5
  Home-page: https://github.com/jrigling/python-jebao
6
6
  Author: Justin Rigling
@@ -16,7 +16,7 @@ from .const import (
16
16
  MODEL_MD44,
17
17
  )
18
18
 
19
- __version__ = "0.1.5"
19
+ __version__ = "0.1.6"
20
20
 
21
21
  __all__ = [
22
22
  "JebaoDevice",
@@ -530,14 +530,19 @@ class JebaoProtocol:
530
530
  return bytes(buffer)
531
531
 
532
532
  async def _drain_garbage_bytes(self, timeout: float = 0.1) -> None:
533
- """Drain any garbage/padding bytes from the socket buffer.
533
+ """Drain leftover bytes and unsolicited messages from the socket buffer.
534
534
 
535
- The MDP-20000 pump appears to send extra padding bytes (0xee) after
536
- valid responses. This method drains those bytes to prevent them from
537
- corrupting subsequent reads.
535
+ The MDP-20000 pump emits two things we need to consume before a request:
536
+ - Padding bytes (0xee / 0x00) trailing some responses
537
+ - Unsolicited type 0x00 status broadcasts (header + body + 129-byte padding)
538
+
539
+ If an unsolicited type 0x00 frame is found and we only consume its body,
540
+ the trailing 129-byte padding remains in the buffer and corrupts the next
541
+ read (forcing a slow byte-by-byte resync that often races the pump's
542
+ connection close, surfacing as IncompleteReadError).
538
543
 
539
544
  Args:
540
- timeout: How long to wait for garbage bytes (default 0.1s)
545
+ timeout: How long to wait for bytes (default 0.1s)
541
546
  """
542
547
  if not self._reader:
543
548
  return
@@ -559,20 +564,21 @@ class JebaoProtocol:
559
564
  continue
560
565
  # Check if it's a valid header
561
566
  if header[0:4] == b"\x00\x00\x00\x03":
562
- # Valid header found - this is a real message!
563
- # Put it back somehow... actually, we can't put it back easily
564
- # This is a problem - we've consumed a valid message header
565
- _LOGGER.warning(
566
- "Found valid header while draining - this shouldn't happen! "
567
- "Pump may have sent unsolicited message."
568
- )
569
- # Read the rest of this message to consume it
567
+ # Pump sent an unsolicited message (e.g. periodic status broadcast).
568
+ # Consume the full frame so we don't desync the stream.
570
569
  length = header[4]
571
- remaining = await self._reader.read(length)
572
- _LOGGER.warning(
573
- "Consumed unsolicited message: type=0x%02x, %d bytes total",
574
- header[7] if len(header) > 7 else 0,
575
- len(header) + len(remaining),
570
+ body = await self._reader.readexactly(length)
571
+ msg_type = body[2] if len(body) > 2 else 0
572
+ total = len(header) + len(body)
573
+ # Type 0x00 messages carry an extra 129-byte padding frame
574
+ # (same as _read_raw). Skip it or stale bytes corrupt the next read.
575
+ if msg_type == MSG_EXTENDED_DATA:
576
+ padding = await self._reader.readexactly(129)
577
+ total += len(padding)
578
+ _LOGGER.debug(
579
+ "Drained unsolicited message: type=0x%02x, %d bytes total",
580
+ msg_type,
581
+ total,
576
582
  )
577
583
  else:
578
584
  # Garbage header - log and continue draining
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-jebao"
7
- version = "0.1.5"
7
+ version = "0.1.6"
8
8
  description = "Python library for controlling Jebao aquarium pumps"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-jebao
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Summary: Python library for controlling Jebao aquarium pumps
5
5
  Home-page: https://github.com/jrigling/python-jebao
6
6
  Author: Justin Rigling
File without changes
File without changes
File without changes
File without changes