如何在Volttron中使用RPC

时间:2019-06-13 08:05:45

标签: python rpc volttron

我想在我的volttron应用程序中使用RPC调用,但无法进行任何调用。所有呼叫均失败,并显示“无法路由到主机”错误

<stderr> ERROR: Unreachable: VIP error (113): No route to host: rpcserver.agent_1

基本上,有两个代理,一个是“服务器”代理,它导出RPC过程,另一个是“客户端”代理,它调用该过程。

在“服务器”代理中,我已导出了代理类的方法,如下所示:

@RPC.export('setConfig')
def setConfig(self, config):
    self.config = config                       
    self.initialize_device()

“客户端”代理按如下所示调用导出的方法:

self.vip.rpc.call(sender, 'setConfig', self.config[sender]).get()

其中“发送者”是“服务器”代理的VIP身份(原来是“ rpcserver.agent_1”,与从rpcserver.agent接收到pubsub消息时的“发送者”参数值相对应。)已在IDENTITY文件中将身份定义为rpcserver.agent_ {n}。

我的问题是: 1.我是否在做一些明显错误的事情或缺少正确设置RPC子系统的步骤? 2. self.vip.rpc.call(peer, method, ...)中的“ peer”参数是否应为代理的身份?在文档中不清楚(我尝试了其他选项,例如代理名称或uuid,但没有用)

我在Ubuntu VM中运行volttron 5.1.0。

任何对此的帮助将不胜感激。 最好的问候

详细信息:

这是用于互连多个设备的控制应用程序。根据网络中的可用设备动态加载代理。我想尝试RPC,而不是仅使用pubsub。到目前为止,我已经非常彻底地搜索了Volttron代码和文档以获取有关RPC API的详细信息。

最小的“服务器”类别:

class rpcServerAgent(Agent):    
    def __init__(self, config, **kwargs):        
        super(rpcServerAgent, self).__init__(**kwargs)
        self.config = config

    @Core.receiver('onstart')
    def onstart(self, sender, **kwargs):                     
        self.vip.rpc.export(self.setConfig, name='setConfig')           # Also tried online exporting 

        # Ask the client to call the exported procedure
        myutils.publish(self, topic='rpc/test', message={})             # myutils.publish publishes the message on pubsub 


    @RPC.export('setConfig')
    def setConfig(self, config):
        self.config = config        
        self.initialize_device()
        myutils.publish(self, topic='rpc/clientready')

    def initialize_device(self):
        pass

最小的“客户”类别:

class rpcClientAgent(Agent):    
    def __init__(self, config, **kwargs):
        super(rpcClientAgent, self).__init__(**kwargs)        
        self.config = {'rpcclient.agent_1': {'a': 0, 'b': 1}}                   # dummy config for rpcclient.agent

    @Core.receiver('onstart')
    def onstart(self, sender, **kwargs):
        self.vip.pubsub.subscribe(peer='pubsub',
                                prefix='rpc',
                                callback=self.__handle_request__).get(timeout=5)      

    def call_RPC(self, sender):        
        sender = sender.strip()         # volttron adds a newline at the end        
        self.vip.rpc.call(sender, 'setConfig', self.config[sender]).get()       # assume that self.config[sender] is well-defined    

    @PubSub.subscribe('pubsub', 'rpc')
    def __handle_request__(self, peer, sender, bus, topic, headers, message):
        try:
            msg = json.loads(message)
        except:
            raise ValueError("failed to decode message")

        topics = topic.split('/')
        if len(topics) > 1:
            if topics[0] == 'rpc':                
                if topics[1] == 'test':                                                            
                    self.call_RPC(sender)

预期的行为:调用导出的函数,并发布主题为“ rpc / clientready”的pubsub消息。

实际行为:RPc调用失败,并显示错误“无法访问:VIP错误(113):主机没有路由:rpcclient.agent_1”

编辑 最终,我发现问题在于伏特龙内代理商的身份以“ \ n”字符结尾。这是由于gedit自动附加了它,并且显然该字符串并未被电压源剥离。

1 个答案:

答案 0 :(得分:0)

关于如何创建RPC方法,我想说您做得很好(尽管:

@RPC.export('setConfig')

可能是:

@RPC.export

因为您没有更改方法名称)。

就进行RPC调用而言,第一个参数确实意味着代理身份或地址。

如果您想查看更多示例,请在services / core / MasterDriverAgent / master_driver / interfaces中查看Modbus或Bacnet驱动程序。

其他一些注意事项:

  • 配置存储可用于设置代理配置。可以在volttron / platform / agent / base_weather.py(以及许多其他代理)中找到此类示例

  • 尽管我不是很熟悉,但是看来您可以通过利用主驱动程序的功能来完成您想做的事情。我相信Market Service代理可能会与您要完成的工作共享一些设计功能,可以在services / core / MarketServiceAgent中找到它。