1212import time
1313import logging
1414
15+ from scrutiny .server .device .submodules .base_device_handler_submodule import BaseDeviceHandlerSubmodule
1516from scrutiny .server .protocol import *
1617import scrutiny .server .protocol .typing as protocol_typing
1718from scrutiny .server .device .request_dispatcher import RequestDispatcher
1819from scrutiny import tools
1920from scrutiny .tools .typing import *
2021
2122
22- class HeartbeatGenerator :
23+ class HeartbeatGenerator ( BaseDeviceHandlerSubmodule ) :
2324 """
2425 Poll the device with periodic heartbeat message to know if it is still there and alive.
2526 """
@@ -32,15 +33,15 @@ class HeartbeatGenerator:
3233 """Our dispatcher priority"""
3334 session_id : Optional [int ]
3435 """The session ID to include in the heartbeat request"""
35- last_heartbeat_request : Optional [float ]
36+ last_heartbeat_request_timestamp : Optional [float ]
3637 """Time at which that last heartbeat request has been sent."""
3738 last_heartbeat_timestamp : Optional [float ]
3839 """Time at which the last successful heartbeat response has been received"""
3940 challenge : int
40- """The computation challenge included in the pending request."""
41+ """The computation challenge included in the request_pending request."""
4142 interval : float
4243 """Heartbeat interval in seconds"""
43- pending : bool
44+ request_pending : bool
4445 """True when a request is sent and we are waiting for a response"""
4546 started : bool
4647 """True when started. Sends heartbeat only when started, otherwise keep silent"""
@@ -50,7 +51,7 @@ def __init__(self, protocol: Protocol, dispatcher: RequestDispatcher, priority:
5051 self .dispatcher = dispatcher
5152 self .protocol = protocol
5253 self .session_id = None
53- self .last_heartbeat_request = None
54+ self .last_heartbeat_request_timestamp = None
5455 self .last_heartbeat_timestamp = time .monotonic ()
5556 self .challenge = 0
5657 self .interval = 3
@@ -76,24 +77,36 @@ def stop(self) -> None:
7677 self .started = False
7778
7879 def fully_stopped (self ) -> bool :
79- """Indicates that this submodule is stopped and has no pending state"""
80+ """Indicates that this submodule is stopped and has no request_pending state"""
8081 return self .started == False
8182
8283 def reset (self ) -> None :
8384 """Put the heartbeat generator in its startup state"""
84- self .pending = False
85+ self .request_pending = False
8586 self .started = False
8687 self .session_id = None
8788
89+ def _heartbeat_timedout (self ) -> bool :
90+ return self .last_heartbeat_request_timestamp is None or (time .monotonic () - self .last_heartbeat_request_timestamp > self .interval )
91+
92+ def would_send_data (self ) -> bool :
93+ if not self .started :
94+ return False
95+
96+ if self .request_pending or self .session_id is None :
97+ return False
98+
99+ return self ._heartbeat_timedout ()
100+
88101 def process (self ) -> None :
89102 """To be called periodically"""
90103 if not self .started :
91104 self .reset ()
92105 return
93106
94107 # If no request is being waited and we have a session ID assigned
95- if self .pending == False and self .session_id is not None :
96- if self .last_heartbeat_request is None or ( time . monotonic () - self . last_heartbeat_request > self . interval ):
108+ if self .request_pending == False and self .session_id is not None :
109+ if self ._heartbeat_timedout ( ):
97110 if self .logger .isEnabledFor (logging .DEBUG ): # pragma: no cover
98111 self .logger .debug ('Registering a Heartbeat request' )
99112 self .dispatcher .register_request (
@@ -102,8 +115,8 @@ def process(self) -> None:
102115 failure_callback = self ._failure_callback ,
103116 priority = self .priority
104117 )
105- self .pending = True
106- self .last_heartbeat_request = time .monotonic ()
118+ self .request_pending = True
119+ self .last_heartbeat_request_timestamp = time .monotonic ()
107120
108121 def _success_callback (self , request : Request , response : Response , params : Any = None ) -> None :
109122 """ Called by the dispatcher when a request is completed and succeeded"""
@@ -140,4 +153,4 @@ def _failure_callback(self, request: Request, params: Any = None) -> None:
140153 def _completed (self ) -> None :
141154 """ Common code between success and failure"""
142155 self .challenge = (self .challenge + 1 ) & 0xFFFF # Next challenge
143- self .pending = False
156+ self .request_pending = False
0 commit comments