-
Notifications
You must be signed in to change notification settings - Fork 2
Logaddress issue testing code #332
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -27,6 +27,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||
| from ..constants import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| DAY_IN_HOURS, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| DEFAULT_CONS_INTERVAL, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| LOGADDR_MAX, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| MAX_TIME_DRIFT, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| MINIMAL_POWER_UPDATE, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| NO_PRODUCTION_INTERVAL, | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1030,26 +1031,11 @@ async def node_info_update( | |||||||||||||||||||||||||||||||||||||||||||||||||
| node_info = await node_request.send() | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| if node_info is None: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| _LOGGER.debug("No response for node_info_update() for %s", self.mac) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| await self._available_update_state(False) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return None | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| await super().node_info_update(node_info) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| await self._relay_update_state( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| node_info.relay_state, timestamp=node_info.timestamp | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._current_log_address is not None and ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._current_log_address > node_info.current_logaddress_pointer | ||||||||||||||||||||||||||||||||||||||||||||||||||
| or self._current_log_address == 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ): | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # Rollover of log address | ||||||||||||||||||||||||||||||||||||||||||||||||||
| _LOGGER.debug( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| "Rollover log address from %s into %s for node %s", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._current_log_address, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| node_info.current_logaddress_pointer, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._mac_in_str, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._current_log_address != node_info.current_logaddress_pointer: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._current_log_address = node_info.current_logaddress_pointer | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| return self._node_info | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1059,14 +1045,29 @@ async def update_node_details( | |||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> bool: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """Process new node info and return true if all fields are updated.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if node_info.relay_state is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._relay_state = replace( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._relay_state, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| state=node_info.relay_state, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| timestamp=node_info.timestamp, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| await self._relay_update_state( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| node_info.relay_state, timestamp=node_info.timestamp | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| if ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| node_info.current_logaddress_pointer is not None | ||||||||||||||||||||||||||||||||||||||||||||||||||
| and self._current_log_address is not None | ||||||||||||||||||||||||||||||||||||||||||||||||||
| and ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._current_log_address < node_info.current_logaddress_pointer | ||||||||||||||||||||||||||||||||||||||||||||||||||
| or self._current_log_address == 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ): | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # Rollover of log address | ||||||||||||||||||||||||||||||||||||||||||||||||||
| _LOGGER.debug( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| "Rollover log address from %s into %s for node %s", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._current_log_address, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| node_info.current_logaddress_pointer, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._mac_in_str, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| if node_info.current_logaddress_pointer is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._current_log_address = node_info.current_logaddress_pointer | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._energy_counters.set_current_logaddres(self._current_log_address) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| return await super().update_node_details(node_info) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1363,3 +1364,71 @@ async def energy_reset_request(self) -> None: | |||||||||||||||||||||||||||||||||||||||||||||||||
| "Node info update after energy-reset successful for %s", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._mac_in_str, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| async def energy_logaddr_setrequest(self, logaddr: int) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """Set the logaddress to a specific value.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._node_protocols is None: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| raise NodeError("Unable to energy-reset when protocol version is unknown") | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| if logaddr < 1 or logaddr >= LOGADDR_MAX: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError("Set logaddress out of range for {self._mac_in_str}") | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1370
to
+1374
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix exception text and formatting (missing f-string, wrong action).
- if self._node_protocols is None:
- raise NodeError("Unable to energy-reset when protocol version is unknown")
+ if self._node_protocols is None:
+ raise NodeError("Unable to set logaddress when protocol version is unknown")
@@
- if logaddr < 1 or logaddr >= LOGADDR_MAX:
- raise ValueError("Set logaddress out of range for {self._mac_in_str}")
+ if logaddr < 1 or logaddr >= LOGADDR_MAX:
+ raise ValueError(
+ f"Set logaddress out of range for {self._mac_in_str} "
+ f"(got {logaddr}, allowed 1..{LOGADDR_MAX-1})"
+ )📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||
| request = CircleClockSetRequest( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._send, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._mac_in_bytes, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| datetime.now(tz=UTC), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._node_protocols.max, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| logaddr, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if (response := await request.send()) is None: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| raise NodeError(f"Logaddress set for {self._mac_in_str} failed") | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| if response.ack_id != NodeResponseType.CLOCK_ACCEPTED: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| raise MessageError( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| f"Unexpected NodeResponseType {response.ack_id!r} received as response to CircleClockSetRequest" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| _LOGGER.warning("Logaddress set for Node %s successful", self._mac_in_str) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| # Follow up by an energy-intervals (re)set | ||||||||||||||||||||||||||||||||||||||||||||||||||
| interval_request = CircleMeasureIntervalRequest( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._send, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._mac_in_bytes, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| DEFAULT_CONS_INTERVAL, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| NO_PRODUCTION_INTERVAL, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if (interval_response := await interval_request.send()) is None: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| raise NodeError("No response for CircleMeasureIntervalRequest") | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| if ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| interval_response.response_type | ||||||||||||||||||||||||||||||||||||||||||||||||||
| != NodeResponseType.POWER_LOG_INTERVAL_ACCEPTED | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ): | ||||||||||||||||||||||||||||||||||||||||||||||||||
| raise MessageError( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| f"Unknown NodeResponseType '{interval_response.response_type.name}' received" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| _LOGGER.warning("Resetting energy intervals to default (= consumption only)") | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| # Clear the cached energy_collection | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._cache_enabled: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._set_cache(CACHE_ENERGY_COLLECTION, "") | ||||||||||||||||||||||||||||||||||||||||||||||||||
| _LOGGER.warning( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| "Energy-collection cache cleared successfully, updating cache for %s", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._mac_in_str, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| await self.save_cache() | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| # Clear PulseCollection._logs | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._energy_counters.reset_pulse_collection() | ||||||||||||||||||||||||||||||||||||||||||||||||||
| _LOGGER.warning("Resetting pulse-collection") | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| # Request a NodeInfo update | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if await self.node_info_update() is None: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| _LOGGER.warning( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| "Node info update failed after energy-reset for %s", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._mac_in_str, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| _LOGGER.warning( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| "Node info update after energy-reset successful for %s", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| self._mac_in_str, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1425
to
+1434
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Bypass 30s NodeInfo skip; fix log messages.
- # Request a NodeInfo update
- if await self.node_info_update() is None:
- _LOGGER.warning(
- "Node info update failed after energy-reset for %s",
- self._mac_in_str,
- )
- else:
- _LOGGER.warning(
- "Node info update after energy-reset successful for %s",
- self._mac_in_str,
- )
+ # Request a fresh NodeInfo update (bypass 30s skip window)
+ node_request = NodeInfoRequest(self._send, self._mac_in_bytes)
+ node_info = await node_request.send()
+ if node_info is None:
+ _LOGGER.warning(
+ "Node info update failed after logaddress set for %s",
+ self._mac_in_str,
+ )
+ else:
+ await super().node_info_update(node_info)
+ _LOGGER.info(
+ "Node info update after logaddress set successful for %s",
+ self._mac_in_str,
+ )📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Bug: bool is a subclass of int — default reset=False currently resets logs
isinstance(reset, int) matches True/False. With the current order, reset=True becomes LogAddr(1, …) and reset=False becomes LogAddr(0, …), unintentionally resetting by default. Reorder the checks and validate input.
Apply:
Check call sites and add a focused test for the int path:
🏁 Script executed:
Length of output: 1464
We need to inspect the
CircleClockSetRequestconstructor to verify default values and signature before concluding. Please run:🏁 Script executed:
Length of output: 887
🏁 Script executed:
Length of output: 2471
Fix reset logic in CircleClockSetRequest to distinguish bool from int
Invert the
isinstance(reset, …)checks so thatboolis handled first—defaultreset=Falsenow produces the no‐reset sentinel, and onlyTrueor a non‐negativeinttriggers a log reset. RaiseMessageErroron negative or invalid types.📝 Committable suggestion
🤖 Prompt for AI Agents