@@ -15,6 +15,7 @@ const state = {
1515 sessionStartTime : null ,
1616 sessionTimerId : null ,
1717 heartbeatTimerId : null ,
18+ heartbeatIntervalSeconds : 60 , // Default 60 seconds
1819 messageSubscriptionId : null ,
1920 sensorData : {
2021 temperature : 20 ,
@@ -257,6 +258,9 @@ async function handleCreateGroup() {
257258
258259 // Join the created group automatically
259260 state . currentGroup = group ;
261+ if ( group . heartbeatIntervalSeconds ) {
262+ state . heartbeatIntervalSeconds = group . heartbeatIntervalSeconds ;
263+ }
260264
261265 // Initialize sensor data for this node
262266 // This immediately shares current sensor state with other group members
@@ -403,6 +407,10 @@ async function handleJoinGroup() {
403407 expiresAt : result . expiresAt
404408 } ;
405409
410+ if ( result . heartbeatIntervalSeconds ) {
411+ state . heartbeatIntervalSeconds = result . heartbeatIntervalSeconds ;
412+ }
413+
406414 // Initialize sensor data for this node
407415 // This immediately shares current sensor state with other group members
408416 const initialData = [
@@ -431,6 +439,7 @@ async function handleJoinGroup() {
431439
432440 // Stop heartbeat if it was running (e.g. from a previously created group)
433441 stopHeartbeat ( ) ;
442+ startHeartbeat ( ) ;
434443
435444 showSuccess ( 'groupSuccess' , `Joined group: ${ state . selectedGroup . name } ` ) ;
436445 updateCurrentGroupUI ( ) ;
@@ -861,15 +870,15 @@ function updateRateStatus() {
861870}
862871
863872/**
864- * Start heartbeat timer (host only)
865- * Renews the group heartbeat every 15 seconds
873+ * Start heartbeat timer
874+ * Renews the group heartbeat periodically using server-provided interval
866875 */
867876function startHeartbeat ( ) {
868877 if ( state . heartbeatTimerId ) {
869878 clearInterval ( state . heartbeatTimerId ) ;
870879 }
871880
872- console . log ( ' Starting heartbeat timer...' ) ;
881+ console . log ( ` Starting heartbeat timer ( ${ state . heartbeatIntervalSeconds } s)...` ) ;
873882 document . getElementById ( 'heartbeatStatus' ) . style . display = 'block' ;
874883
875884 state . heartbeatTimerId = setInterval ( async ( ) => {
@@ -879,31 +888,45 @@ function startHeartbeat() {
879888 }
880889
881890 const isHost = state . currentGroup . hostId === state . currentNodeId ;
882- if ( ! isHost ) {
883- stopHeartbeat ( ) ;
884- return ;
885- }
886891
887892 try {
888- const result = await state . client . renewHeartbeat (
889- state . currentGroup . id ,
890- state . currentNodeId ,
891- state . currentGroup . domain
892- ) ;
893- console . log ( 'Heartbeat renewed, expires at:' , result . expiresAt ) ;
893+ let result ;
894+ if ( isHost ) {
895+ result = await state . client . renewHeartbeat (
896+ state . currentGroup . id ,
897+ state . currentNodeId ,
898+ state . currentGroup . domain
899+ ) ;
900+ console . log ( 'Host heartbeat renewed, expires at:' , result . expiresAt ) ;
901+ } else {
902+ result = await state . client . sendMemberHeartbeat (
903+ state . currentGroup . id ,
904+ state . currentNodeId ,
905+ state . currentGroup . domain
906+ ) ;
907+ console . log ( 'Member heartbeat sent, expires at:' , result . expiresAt ) ;
908+ }
909+
894910 document . getElementById ( 'lastHeartbeatTime' ) . textContent = new Date ( ) . toLocaleTimeString ( ) ;
895911
896912 // Update session timer with new expiration if possible
897913 if ( result . expiresAt ) {
898914 state . currentGroup . expiresAt = result . expiresAt ;
899915 }
916+
917+ // Check if interval has changed
918+ if ( result . heartbeatIntervalSeconds && result . heartbeatIntervalSeconds !== state . heartbeatIntervalSeconds ) {
919+ console . log ( `Heartbeat interval changed: ${ state . heartbeatIntervalSeconds } s -> ${ result . heartbeatIntervalSeconds } s` ) ;
920+ state . heartbeatIntervalSeconds = result . heartbeatIntervalSeconds ;
921+ startHeartbeat ( ) ; // Restart with new interval
922+ }
900923 } catch ( error ) {
901- console . error ( 'Heartbeat renewal failed:' , error ) ;
924+ console . error ( 'Heartbeat failed:' , error ) ;
902925 if ( shouldDisconnectOnError ( error ) ) {
903926 handleGroupDissolved ( { message : 'Session expired or group lost' } ) ;
904927 }
905928 }
906- } , 15000 ) ; // Every 15 seconds
929+ } , state . heartbeatIntervalSeconds * 1000 ) ;
907930}
908931
909932/**
0 commit comments