docstr: Start our heart beating
docstr_tok: ["Start","our","heart","beating"]
code: def start_heartbeat(self, hb_ping, hb_pong, hb_period, identity):
      """Start our heart beating"""
  
      hb_monitor = None
      if self.max_heartbeat_misses > 0:
          # Add a monitor socket which will record the last time a ping was seen
          mon = self.context.socket(zmq.SUB)
          if self.curve_serverkey:
              mon.setsockopt(zmq.CURVE_SERVER, 1)
              mon.setsockopt(zmq.CURVE_SECRETKEY, self.curve_secretkey)
          mport = mon.bind_to_random_port("tcp://%s" % localhost())
          mon.setsockopt(zmq.SUBSCRIBE, b"")
          self._hb_listener = zmqstream.ZMQStream(mon, self.loop)
          self._hb_listener.on_recv(self._report_ping)
  
          hb_monitor = "tcp://%s:%i" % (localhost(), mport)
  
      heart = Heart(
          hb_ping,
          hb_pong,
          hb_monitor,
          heart_id=identity,
          curve_serverkey=self.curve_serverkey,
          curve_secretkey=self.curve_secretkey,
          curve_publickey=self.curve_publickey,
      )
      heart.start()
  
      # periodically check the heartbeat pings of the controller
      # Should be started here and not in "start()" so that the right period can be taken
      # from the hubs HeartBeatMonitor.period
      if self.max_heartbeat_misses > 0:
          # Use a slightly bigger check period than the hub signal period to not warn unnecessary
          self.hb_check_period = hb_period + 500
          self.log.info(
              "Starting to monitor the heartbeat signal from the hub every %i ms.",
              self.hb_check_period,
          )
          self._hb_reporter = ioloop.PeriodicCallback(
              self._hb_monitor, self.hb_check_period
          )
          self._hb_reporter.start()
      else:
          self.log.info(
              "Monitoring of the heartbeat signal from the hub is not enabled."
          )
  
imports: import json
  import os
  import signal
  import sys
  import time
  from getpass import getpass
  from io import FileIO, TextIOWrapper
  from logging import StreamHandler
  import zmq
  from ipykernel.kernelapp import IPKernelApp
  from ipykernel.zmqshell import ZMQInteractiveShell
  from IPython.core.profiledir import ProfileDir
  from jupyter_client.localinterfaces import localhost
  from jupyter_client.session import Session, session_aliases, session_flags
  from tornado import ioloop
  from traitlets import Bool, Bytes, Dict, Float, Instance, Integer, List, Type, Unicode, default, observe, validate
  from traitlets.config import Config
  from zmq.eventloop import zmqstream
  from ipyparallel.apps.baseapp import BaseParallelApplication, base_aliases, base_flags, catch_config_error
  from ipyparallel.controller.heartmonitor import Heart
  from ipyparallel.util import disambiguate_ip_address, disambiguate_url
  from .kernel import IPythonParallelKernel
  from .log import EnginePUBHandler
  from .nanny import start_nanny
label_desc: Use image node_id 23 for calling the IPEngine obj's underlying member method code with example usage: obj.start_heartbeat(hb_ping, hb_pong, hb_period, identity) without return types