【问题标题】:How to use RPC with Volttron如何将 RPC 与 Volttron 一起使用
【发布时间】:2019-10-27 18:47:44
【问题描述】:

我想在我的 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()

其中“sender”是“server”代理的 VIP 身份(结果是“rpcserver.agent_1”,对应于从 rpcserver.agent 接收 pubsub 消息时的“sender”参数的值。我已在 IDENTITY 文件中将身份定义为 rpcserver.agent_{n}。

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

我在 Ubuntu 虚拟机中运行 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): No route to host: rpcclient.agent_1”

编辑 我最终发现问题在于 volttron 中的特工身份以“\n”字符结尾。这是由于 gedit 自动附加它,显然字符串没有被 volttron 剥离。

【问题讨论】:

    标签: python rpc volttron


    【解决方案1】:

    关于如何创建一个 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 中找到。

    【讨论】:

    • 感谢您的回答!我最终发现了问题 - 请参阅上面的编辑。 Rpc 现在工作正常。
    猜你喜欢
    • 1970-01-01
    • 2020-02-27
    • 1970-01-01
    • 2015-05-06
    • 1970-01-01
    • 1970-01-01
    • 2015-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多