Exemple #1
0
 def onmessage(self, peer, sender, bus, topic, headers, message):
     d = {'topic': topic, 'headers': headers, 'message': message}
     # Forward message to FNCS
     if not fncs.is_initialized():
         raise RuntimeError("FNCS connection was terminated. Killing Bridge.")
     fncsmessage = str(message)
     topic = topic.replace('fncs/input/','')
     fncs.publish(topic, fncsmessage)
     _log.debug('Volttron->FNCS:\nTopic:%s\nMessage:%s\n'%(topic, message))
Exemple #2
0
 def start(self, sender, **kwargs):
     self.vip.pubsub.subscribe(peer = 'pubsub',
                               prefix = 'fncs/input/',
                               #prefix = '',
                               callback = self.onmessage).get(timeout=5)
     #Register with FNCS
     cfg = "name = {0[name]}\ntime_delta = {0[time_delta]}\nbroker = {0[broker]}\n".format(self.fncs_zpl)
     if 'values' in self.fncs_zpl.keys():
         cfg += "values"
         for x in self.fncs_zpl['values'].keys():
             cfg += "\n    {0}\n        topic = {1[topic]}\n        defualt = {1[default]}\n        type = {1[type]}\n        list = {1[list]}".format(x,self.fncs_zpl['values'][x])
     fncs.initialize(cfg)
     if not fncs.is_initialized():
         raise RuntimeError("FNCS connection failed!")
     self.publish_heartbeat()
     print(self.heartbeat_period)
     self.core.periodic(self.heartbeat_period, self.publish_heartbeat)
    def publish_to_fncs(self, goss_message):
        """publish a message received from the GOSS bus to the FNCS bus.

        Function arguments:
            simulation_id -- Type: string. Description: The simulation id.
                It must not be an empty string. Default: None.
            goss_message -- Type: string. Description: The message from the GOSS bus
                as a json string. It must not be an empty string. Default: None.
        Function returns:
            None.
        Function exceptions:
            RuntimeError()
            ValueError()
        """
        message_str = 'publish to fncs bus {} {}'.format(self.simulation_id, goss_message)
        self._gridappsd.send_simulation_status('RUNNING', message_str, DEBUG)

        if not self.simulation_id or type(self.simulation_id) != str:
            raise ValueError(
                'simulation_id must be a nonempty string.\n'
                + 'simulation_id = {0}'.format(self.simulation_id))
        if not goss_message or type(goss_message) != str:
            raise ValueError(
                'goss_message must be a nonempty string.\n'
                + 'goss_message = {0}'.format(goss_message))
        if not fncs.is_initialized():
            raise RuntimeError(
                'Cannot publish message as there is no connection'
                + ' to the FNCS message bus.')
        try:
            test_goss_message_format = yaml.safe_load(goss_message)
            if type(test_goss_message_format) != dict:
                raise ValueError(
                    'goss_message is not a json formatted string.'
                    + '\ngoss_message = {0}'.format(goss_message))
        except ValueError as ve:
            raise ValueError(ve)
        except:
            raise RuntimeError(
                'Unexpected error occured while executing yaml.safe_load(goss_message'
                + '{0}'.format(sys.exc_info()[0]))
        fncs_input_topic = '{0}/fncs_input'.format(self.simulation_id)
        message_str = 'fncs input topic ' + fncs_input_topic
        self._gridappsd.send_simulation_status('RUNNING', message_str, DEBUG)
        fncs.publish_anon(fncs_input_topic, goss_message)
def _publishToFncsBus(simulationId, gossMessage):
    '''publish a message received from the GOSS bus to the FNCS bus.
    
    Function arguments:
        simulationId -- Type: string. Description: The simulation id. 
            It must not be an empty string. Default: None.
        gossMessage -- Type: string. Description: The message from the GOSS bus
            as a json string. It must not be an empty string. Default: None.
    Function returns:
        None.
    Function exceptions:
        RuntimeError()
        ValueError()
    '''
    logger.debug('publish to fncs bus ' + simulationId + ' ' +
                 str(gossMessage))

    if simulationId == None or simulationId == '' or type(simulationId) != str:
        raise ValueError('simulationId must be a nonempty string.\n' +
                         'simulationId = {0}'.format(simulationId))
    if gossMessage == None or gossMessage == '' or type(gossMessage) != str:
        raise ValueError('gossMessage must be a nonempty string.\n' +
                         'gossMessage = {0}'.format(gossMessage))
    if not fncs.is_initialized():
        raise RuntimeError('Cannot publish message as there is no connection' +
                           ' to the FNCS message bus.')
    try:
        testGossMessageFormat = yaml.safe_load(gossMessage)
        if type(testGossMessageFormat) != dict:
            raise ValueError('gossMessage is not a json formatted string.' +
                             '\ngossMessage = {0}'.format(gossMessage))
    except ValueError as ve:
        raise ValueError(ve)
    except:
        raise RuntimeError(
            'Unexpected error occured while executing yaml.safe_load(gossMessage'
            + '{0}'.format(sys.exc_info()[0]))
    fncsInputTopic = '{0}/fncs_input'.format(simulationId)
    logger.debug('fncs input topic ' + fncsInputTopic)
    fncs.publish_anon(fncsInputTopic, gossMessage)
 def on_disconnected(self):
     if fncs.is_initialized():
         fncs.die()
 def on_error(self, headers, message):
     message_str = 'Error in {} {}'.format('GridAPPSDListener', message)
     self._gridappsd.send_simulation_status('STOPPED', message_str)
     if fncs.is_initialized():
         fncs.die()
    def on_message(self, headers, msg):
        message = {}
        try:
            message_str = 'received message ' + str(msg)
            if fncs.is_initialized():
                self._gridappsd.send_simulation_status('RUNNING', message_str, DEBUG)
            else:
                self._gridappsd.send_simulation_status('STARTED', message_str, DEBUG)

            json_msg = yaml.safe_load(str(msg))
            if json_msg['command'] == 'isInitialized':
                message_str = 'isInitialized check: ' + str(is_initialized)
                if fncs.is_initialized():
                    self._gridappsd.send_simulation_status('RUNNING', message_str, DEBUG)
                else:
                    self._gridappsd.send_simulation_status('STARTED', message_str, DEBUG)
                message['command'] = 'isInitialized'
                message['response'] = str(is_initialized)
                if self.simulation_id is not None:
                    message['output'] = self._bridge.get_messages_from_fncs()
                message_str = 'Added isInitialized output, sending message {}'.format(message)

                if fncs.is_initialized():
                    self._gridappsd.send_simulation_status('RUNNING', message_str, DEBUG)
                else:
                    self._gridappsd.send_simulation_status('RUNNING', message_str, DEBUG)
                self._gridappsd.send(topic=self._bridge.simulation_output_topic,
                                     message=json.dumps(message))
            elif json_msg['command'] == 'update':
                message['command'] = 'update'
                # does not return
                self._bridge.publish_to_fncs(json.dumps(json_msg['message']))
            elif json_msg['command'] == 'nextTimeStep':
                message_str = 'is next timestep'
                self._gridappsd.send_simulation_status('RUNNING', message_str, DEBUG)
                message['command'] = 'nextTimeStep'
                current_time = json_msg['currentTime']
                message_str = 'incrementing to ' + str(current_time)
                self._gridappsd.send_simulation_status('RUNNING', message_str, DEBUG)
                # current_time is incrementing integer 0 ,1, 2.... representing seconds
                self._bridge.timestep_complete(current_time)
                message_str = 'done with timestep ' + str(current_time)
                self._gridappsd.send_simulation_status('RUNNING', message_str, DEBUG)
                message_str = 'simulation id ' + str(self._bridge.simulation_id)
                self._gridappsd.send_simulation_status('RUNNING', message_str, DEBUG)
                message['output'] = self._bridge.get_messages_from_fncs()
                response_msg = json.dumps(message)
                message_str = 'sending fncs output message ' + str(response_msg)
                self._gridappsd.send_simulation_status('RUNNING', message_str, DEBUG)
                self._gridappsd.send(topic=self._bridge.simulation_output_topic,
                                     message=json.dumps(message))
            elif json_msg['command'] == 'stop':
                message_str = 'Stopping the simulation'
                self._gridappsd.send_simulation_status('STOPPED', message_str)
                fncs.die()
                sys.exit()

        except Exception as e:
            message_str = 'Error in command ' + str(e)
            self._gridappsd.send_simulation_status('ERROR', message_str, ERROR)
            if fncs.is_initialized():
                fncs.die()
    def start_bridge(self):
        """Register with the fncs_broker and return.

            Function arguments:
                broker_location -- Type: string. Description: The ip location and port
                    for the fncs_broker. It must not be an empty string.
                    Default: 'tcp://localhost:5570'.
            Function returns:
                None.
            Function exceptions:
                RuntimeError()
                ValueError()
            """
        global is_initialized

        # First connect with goos via the GridAPPSD interface
        self._gridappsd = GridAPPSD(self.simulation_id, id=2,
                                    base_simulation_status_topic=BASE_SIMULATION_STATUS_TOPIC)
        self._gridappsd_listener = GridAPPSDListener(self, self._gridappsd)

        self._gridappsd.subscribe(self.simulation_input_topic,
                                  callback=self._gridappsd_listener)
        self._gridappsd.send_simulation_status("STARTING",
                                               "Starting Bridge for simulation id: {}".format(self.simulation_id))

        configuration_zpl = ''
        try:

            message_str = 'Registering with FNCS broker ' + str(self.simulation_id) + ' and broker ' + self.fncs_broker_location
            self._gridappsd.send_simulation_status("STARTED", message_str)

            message_str = 'connected to goss {}'.format(self._gridappsd.connected)
            self._gridappsd.send_simulation_status("STARTED", message_str)
            if not self.simulation_id or type(self.simulation_id) != str:
                raise ValueError(
                    'simulation_id must be a nonempty string.\n'
                    + 'simulation_id = {0}'.format(self.simulation_id))

            if not self.fncs_broker_location or type(self.fncs_broker_location) != str:
                raise ValueError(
                    'broker_location must be a nonempty string.\n'
                    + 'broker_location = {0}'.format(self.fncs_broker_location))
            fncs_configuration = {
                'name': 'FNCS_GOSS_Bridge_' + self.simulation_id,
                'time_delta': '1s',
                'broker': self.fncs_broker_location,
                'values': {
                    self.simulation_id: {
                        'topic': self.simulation_id + '/fncs_output',
                        'default': '{}',
                        'type': 'JSON',
                        'list': 'false'
                    }
                }
            }

            configuration_zpl = ('name = {0}\n'.format(fncs_configuration['name'])
                                 + 'time_delta = {0}\n'.format(fncs_configuration['time_delta'])
                                 + 'broker = {0}\nvalues'.format(fncs_configuration['broker']))
            for x in fncs_configuration['values'].keys():
                configuration_zpl += '\n    {0}'.format(x)
                configuration_zpl += '\n        topic = {0}'.format(
                    fncs_configuration['values'][x]['topic'])
                configuration_zpl += '\n        default = {0}'.format(
                    fncs_configuration['values'][x]['default'])
                configuration_zpl += '\n        type = {0}'.format(
                    fncs_configuration['values'][x]['type'])
                configuration_zpl += '\n        list = {0}'.format(
                    fncs_configuration['values'][x]['list'])
            fncs.initialize(configuration_zpl)

            is_initialized = fncs.is_initialized()
            if is_initialized:
                message_str = 'Registered with fncs ' + str(is_initialized)
                self._gridappsd.send_simulation_status("RUNNING", message_str)

        except Exception as e:
            message_str = 'Error while registering with fncs broker ' + str(e)
            self._gridappsd.send_simulation_status('ERROR', message_str, 'ERROR')
            if fncs.is_initialized():
                fncs.die()

        if not fncs.is_initialized():
            message_str = 'fncs.initialize(configuration_zpl) failed!\n' + 'configuration_zpl = {0}'.format(
                configuration_zpl)
            self._gridappsd.send_simulation_status('ERROR', message_str, 'ERROR')
            if fncs.is_initialized():
                fncs.die()
            raise RuntimeError(
                'fncs.initialize(configuration_zpl) failed!\n'
                + 'configuration_zpl = {0}'.format(configuration_zpl))
Exemple #9
0
    def on_message(self, headers, msg):
        message = {}
        try:
            message_str = 'received message ' + str(msg)
            if fncs.is_initialized():
                _send_simulation_status('RUNNING', message_str, 'DEBUG')
            else:
                _send_simulation_status('STARTED', message_str, 'DEBUG')
            json_msg = yaml.safe_load(str(msg))
            if json_msg['command'] == 'isInitialized':
                message_str = 'isInitialized check: ' + str(is_initialized)
                if fncs.is_initialized():
                    _send_simulation_status('RUNNING', message_str, 'DEBUG')
                else:
                    _send_simulation_status('STARTED', message_str, 'DEBUG')
                message['command'] = 'isInitialized'
                message['response'] = str(is_initialized)
                if (simulation_id != None):
                    message['output'] = _get_fncs_bus_messages(simulation_id)
                message_str = 'Added isInitialized output, sending message ' + str(
                    message) + ' connection ' + str(goss_connection)
                if fncs.is_initialized():
                    _send_simulation_status('RUNNING', message_str, 'DEBUG')
                else:
                    _send_simulation_status('STARTED', message_str, 'DEBUG')
                goss_connection.send(output_to_goss_topic, json.dumps(message))
                goss_connection.send(output_to_goss_queue, json.dumps(message))
            elif json_msg['command'] == 'update':
                message['command'] = 'update'
                _publish_to_fncs_bus(
                    simulation_id,
                    json.dumps(json_msg['message']))  #does not return
            elif json_msg['command'] == 'nextTimeStep':
                message_str = 'is next timestep'
                _send_simulation_status('RUNNING', message_str, 'DEBUG')
                message['command'] = 'nextTimeStep'
                current_time = json_msg['currentTime']
                message_str = 'incrementing to ' + str(current_time)
                _send_simulation_status('RUNNING', message_str, 'DEBUG')
                _done_with_time_step(
                    current_time
                )  #current_time is incrementing integer 0 ,1, 2.... representing seconds
                message_str = 'done with timestep ' + str(current_time)
                _send_simulation_status('RUNNING', message_str, 'DEBUG')
                message_str = 'simulation id ' + str(simulation_id)
                _send_simulation_status('RUNNING', message_str, 'DEBUG')
                message['output'] = _get_fncs_bus_messages(simulation_id)
                response_msg = json.dumps(message)
                message_str = 'sending fncs output message ' + str(
                    response_msg)
                _send_simulation_status('RUNNING', message_str, 'DEBUG')
                goss_connection.send(output_to_goss_topic, response_msg)
                goss_connection.send(output_to_goss_queue, response_msg)
            elif json_msg['command'] == 'stop':
                message_str = 'Stopping the simulation'
                _send_simulation_status('stopped', message_str, 'INFO')
                fncs.die()
                sys.exit()

        except Exception as e:
            message_str = 'Error in command ' + str(e)
            _send_simulation_status('ERROR', message_str, 'ERROR')
            if fncs.is_initialized():
                fncs.die()
Exemple #10
0
def _register_with_fncs_broker(broker_location='tcp://localhost:5570'):
    """Register with the fncs_broker and return.
    
    Function arguments:
        broker_location -- Type: string. Description: The ip location and port
            for the fncs_broker. It must not be an empty string.
            Default: 'tcp://localhost:5570'.
    Function returns:
        None.
    Function exceptions:
        RuntimeError()
        ValueError()
    """
    global is_initialized
    configuration_zpl = ''
    try:
        message_str = 'Registering with FNCS broker ' + str(
            simulation_id) + ' and broker ' + broker_location
        _send_simulation_status('STARTED', message_str, 'INFO')

        message_str = 'still connected to goss 1 ' + str(
            goss_connection.is_connected())
        _send_simulation_status('STARTED', message_str, 'INFO')
        if simulation_id == None or simulation_id == '' or type(
                simulation_id) != str:
            raise ValueError('simulation_id must be a nonempty string.\n' +
                             'simulation_id = {0}'.format(simulation_id))

        if (broker_location == None or broker_location == ''
                or type(broker_location) != str):
            raise ValueError('broker_location must be a nonempty string.\n' +
                             'broker_location = {0}'.format(broker_location))
        fncs_configuration = {
            'name': 'FNCS_GOSS_Bridge_' + simulation_id,
            'time_delta': '1s',
            'broker': broker_location,
            'values': {
                simulation_id: {
                    'topic': simulation_id + '/fncs_output',
                    'default': '{}',
                    'type': 'JSON',
                    'list': 'false'
                }
            }
        }

        configuration_zpl = (
            'name = {0}\n'.format(fncs_configuration['name']) +
            'time_delta = {0}\n'.format(fncs_configuration['time_delta']) +
            'broker = {0}\nvalues'.format(fncs_configuration['broker']))
        for x in fncs_configuration['values'].keys():
            configuration_zpl += '\n    {0}'.format(x)
            configuration_zpl += '\n        topic = {0}'.format(
                fncs_configuration['values'][x]['topic'])
            configuration_zpl += '\n        default = {0}'.format(
                fncs_configuration['values'][x]['default'])
            configuration_zpl += '\n        type = {0}'.format(
                fncs_configuration['values'][x]['type'])
            configuration_zpl += '\n        list = {0}'.format(
                fncs_configuration['values'][x]['list'])
        fncs.initialize(configuration_zpl)

        is_initialized = fncs.is_initialized()
        if is_initialized:
            message_str = 'Registered with fncs ' + str(is_initialized)
            _send_simulation_status('RUNNING', message_str, 'INFO')

    except Exception as e:
        message_str = 'Error while registering with fncs broker ' + str(e)
        _send_simulation_status('ERROR', message_str, 'ERROR')
        if fncs.is_initialized():
            fncs.die()

    if not fncs.is_initialized():
        message_str = 'fncs.initialize(configuration_zpl) failed!\n' + 'configuration_zpl = {0}'.format(
            configuration_zpl)
        _send_simulation_status('ERROR', message_str, 'ERROR')
        if fncs.is_initialized():
            fncs.die()
        raise RuntimeError('fncs.initialize(configuration_zpl) failed!\n' +
                           'configuration_zpl = {0}'.format(configuration_zpl))
Exemple #11
0
 def on_error(self, headers, message):
     message_str = 'Error in goss listener ' + str(message)
     _send_simulation_status('ERROR', message_str, 'ERROR')
     if fncs.is_initialized():
         fncs.die()
def _registerWithFncsBroker(simId, brokerLocation='tcp://localhost:5570'):
    '''Register with the fncs_broker and return.
    
    Function arguments:
        simulationId -- Type: string. Description: The simulation id. 
            It must not be an empty string. Default: None.
        brokerLocation -- Type: string. Description: The ip location and port
            for the fncs_broker. It must not be an empty string.
            Default: 'tcp://localhost:5570'.
    Function returns:
        None.
    Function exceptions:
        RuntimeError()
        ValueError()
    '''
    global simulationId
    global isInitialized
    simulationId = simId
    try:
        logger.info('Registering with FNCS broker ' + str(simulationId) +
                    ' and broker ' + brokerLocation)

        logger.debug('still connected to goss 1 ' +
                     str(gossConnection.is_connected()))
        if simulationId == None or simulationId == '' or type(
                simulationId) != str:
            raise ValueError('simulationId must be a nonempty string.\n' +
                             'simulationId = {0}'.format(simulationId))

        if (brokerLocation == None or brokerLocation == ''
                or type(brokerLocation) != str):
            raise ValueError('brokerLocation must be a nonempty string.\n' +
                             'brokerLocation = {0}'.format(brokerLocation))
        fncsConfiguration = {
            'name': 'FNCS_GOSS_Bridge_' + simulationId,
            'time_delta': '1s',
            'broker': brokerLocation,
            'values': {
                simulationId: {
                    'topic': simulationId + '/fncs_output',
                    'default': '{}',
                    'type': 'JSON',
                    'list': 'false'
                }
            }
        }

        configurationZpl = (
            'name = {0}\n'.format(fncsConfiguration['name']) +
            'time_delta = {0}\n'.format(fncsConfiguration['time_delta']) +
            'broker = {0}\nvalues'.format(fncsConfiguration['broker']))
        for x in fncsConfiguration['values'].keys():
            configurationZpl += '\n    {0}'.format(x)
            configurationZpl += '\n        topic = {0}'.format(
                fncsConfiguration['values'][x]['topic'])
            configurationZpl += '\n        default = {0}'.format(
                fncsConfiguration['values'][x]['default'])
            configurationZpl += '\n        type = {0}'.format(
                fncsConfiguration['values'][x]['type'])
            configurationZpl += '\n        list = {0}'.format(
                fncsConfiguration['values'][x]['list'])
        fncs.initialize(configurationZpl)

        isInitialized = fncs.is_initialized()
        logger.info('Registered with fncs ' + str(isInitialized))

    except Exception as e:
        logger.error('Error while registering with fncs broker ' + str(e))

    if not fncs.is_initialized():
        raise RuntimeError('fncs.initialize(configurationZpl) failed!\n' +
                           'configurationZpl = {0}'.format(configurationZpl))
Exemple #13
0
    def publish_heartbeat(self):
        '''Send heartbeat message every HEARTBEAT_PERIOD seconds.

        HEARTBEAT_PERIOD is set and can be adjusted in the settings module.
        '''
        now = datetime.utcnow().isoformat(' ') + 'Z'
        nowdate = datetime.utcnow()
        print "publish_heartbeat", now
        timeDiff = nowdate - self.simStart
        valMap = defaultdict(dict)
        metaMap = defaultdict(dict)
        headers = {headers_mod.TIMESTAMP: now, headers_mod.DATE: now}
        #Tell FNCS we are at our next timestep
        if not fncs.is_initialized():
            raise RuntimeError("FNCS connection was terminated. Killing Bridge.")
        elif self.simtime > self.simlength:
            fncs.finalize()
            self.core.stop()
        elif timeDiff.seconds >= 1:
            self.simtime+=self.heartbeat_period*self.heartbeat_multiplier
            print "fncs.time_request(",self.simtime,") request"
            self.simtime = fncs.time_request(self.simtime)
            print "fncs.time_request() response", self.simtime
            #Grab Subscriptions from FNCS to publish to Volttron message bus
            subKeys = fncs.get_events()
            if len(subKeys) > 0:
                for x in subKeys:
                    valStr = fncs.get_value(x)
                    #parse message to split value and unit
                    valList = valStr.split(' ')
                    if len(valList) == 1:
                        val = valList[0]
                        valUnit = '';
                        try:
                            val = float(val)
                        except:
                            pass
                    elif len(valList) == 2:
                        val = valList[0]
                        valUnit = valList[1]
                        if 'int' in self.fncs_zpl['values'][x]['type']:
                            val = int(val)
                        elif 'double' in self.fncs_zpl['values'][x]['type']:
                            val = float(val)
                        elif 'complex' in self.fncs_zpl['values'][x]['type']:
                            raise RuntimeError("complex data type is currently not supported in Volttron.")
                        #TODO: come up with a better way to handle all types that can come in from fncs
                    else:
                        warnings.warn("FNCS message could not be parsed into value and unit. The message will be farwarded to Volttron message bus as is.")
                        val = valStr
                        valUnit = ''
                    fncsmessage = [val, {'units' : '{0}'.format(valUnit), 'tz' : 'UTC', 'type': '{0[type]}'.format(self.fncs_zpl['values'][x])}]
                    fncsTopic = common.FNCS_OUTPUT_PATH(path = 'devices/{0[topic]}'.format(self.fncs_zpl['values'][x])) #fncs/output/devices/topic
                    self.vip.pubsub.publish('pubsub', fncsTopic, headers, fncsmessage).get(timeout=5)
                    _log.debug('FNCS->Volttron:\nTopic:%s\n:Message:%s\n'%(fncsTopic, str(fncsmessage)))
                    device, point = self.fncs_zpl['values'][x]['topic'].rsplit('/', 1)
                    deviceAllTopic = common.FNCS_OUTPUT_PATH(path = 'devices/' + device + '/all')
                    valMap[deviceAllTopic][point] = val
                    metaMap[deviceAllTopic][point] = fncsmessage[1]
                for k in valMap.keys():
                    allMessage = [valMap[k], metaMap[k]]
                    self.vip.pubsub.publish('pubsub', k, headers, allMessage).get(timeout=5)
                    _log.debug('FNCS->Volttron:\nTopic:%s\n:Message:%s\n'%(k, str(allMessage)))
                    
                
        #Publish heartbeat message to voltron bus        
        self.vip.pubsub.publish(
            'pubsub', '{0[name]}/heartbeat'.format(self.fncs_zpl), headers, now).get(timeout=5)
Exemple #14
0
        #Publish heartbeat message to voltron bus        
        self.vip.pubsub.publish(
            'pubsub', '{0[name]}/heartbeat'.format(self.fncs_zpl), headers, now).get(timeout=5)
    
def fncs_bridge(**kwargs): 
    config = utils.load_config('FNCS_VOLTTRON_Bridge.config')
    heartbeat_period = config.get('heartbeat_period', 1)
    heartbeat_multiplier = config.get('heartbeat_multiplier', 1)
    fncs_zpl = config["fncs_zpl"]
    params = config["remote_platform_params"]
    simulation_run_time = config.get("simulation_run_time", "1h")
    return FNCS_VOLTTRON_Bridge(simulation_run_time, 
                                heartbeat_period,
                                heartbeat_multiplier,
                                fncs_zpl,
                                address=remote_url(**params),
                                identity='FNCS_Volttron_Bridge')

def main():
    '''Main method to start the agent'''
    utils.vip_main(fncs_bridge)
    
if  __name__ == '__main__':
    # Entry point for script
    try:
        sys.exit(main())
    except KeyboardInterrupt:
        if fncs.is_initialized():
            fncs.die()
        pass