The following documentation steps through the process of creating a simple agent that listens to the entire message bus and writes it to the log file. This agent uses pipenv for its base, however you could use poetry or another package manager if you choose (support for installing from a directory is limited to poetry, pipenv, and pip installations only).
The second part of the tutorial is for seasoned VOLTTRON veterans with agents that need to be ported to the new modular code base, but also want to have them available for the 8.x environment.
With every tutorial there are requirements in order to make them work. This one is no different, the following requirements should be installed system-wide, so they are available to be used throughout the tutorial.
System level requirements:
# Python 3.8 is required for the installation of VOLTTRON
sudo apt-get update
sudo apt-get install -y build-essential libffi-dev python3.8-dev python3.8-venv openssl libssl-dev libevent-dev pipenv
The VOLTTRON team uses virtual environments for Python development and Pipenv for the dependency management of those environments. For this quickstart guide we will walk you through building a new listener agent.
-
Open terminal and create a folder to hold the code for the agent.
$> mkdir volttron-listener $> cd volttron-listener
-
Initialize volttron-server to a new environment
$> pipenv install volttron-server
This will create an environment and install volttron-server in it. At this point there should be a Pipfile and Pipfile.lock file in the current working directory.
-
Create a setup.py file and copy the following to it
from os import path from setuptools import setup, find_packages MAIN_MODULE = 'agent' # Find the agent package that contains the main module packages = find_packages('.') agent_package = '' for package in find_packages(): # Because there could be other packages such as tests if path.isfile(package + '/' + MAIN_MODULE + '.py') is True: agent_package = package if not agent_package: raise RuntimeError('None of the packages under {dir} contain the file ' '{main_module}'.format(main_module=MAIN_MODULE + '.py', dir=path.abspath('.'))) # Find the version number from the main module agent_module = agent_package + '.' + MAIN_MODULE # Setup setup( name=agent_package + 'agent', version="0.1", install_requires=['volttron-client'], packages=packages, entry_points={ 'setuptools.installation': [ 'eggsecutable = ' + agent_module + ':main', ] } )
-
Create a directory for your agent code to go into and cd into that directory
$> mkdir mylistener $> cd mylistener
-
Create an agent.py module within the mylistener directory with the following code.
import logging from volttron import utils from volttron.utils import vip_main from volttron.client.vip.agent import Agent, Core, PubSub utils.setup_logging() _log = logging.getLogger(__name__) class MyListener(Agent): def __init__(self, config_path, **kwargs): super().__init__(**kwargs) self.config = utils.load_config(config_path) @Core.receiver('onstart') def onstart(self, sender, **kwargs): _log.info("MyListener has started") @PubSub.subscribe('pubsub', '', all_platforms=True) def on_match(self, peer, sender, bus, topic, headers, message): _log.debug(f"Peer: {peer}, Sender: {sender}:, Bus: {bus}, " f"Topic: {topic}, Headers: {headers}, Message: {message}") def main(): try: vip_main(MyListener, version="0.1") except Exception as e: _log.exception('unhandled exception') if __name__ == '__main__': # Entry point for script sys.exit(main())
-
Create an empty init.py file inside the mylistener
$> touch __init__.py
-
Cd to the parent directory(volttron-listener) and create Wheel and source distribution
$> cd .. $> pipenv run python setup.py bdist_wheel sdist
-
Start VOLTTRON
$> pipenv run volttron -vv
-
Open a new terminal to the same volttron-listener directory
$> pipenv run vctl install dist/mylisteneragent-0.1-py3-none-any.whl --start $> pipenv run vctl status
Congratulations you now have a working volttron environment. There is a lot more to VOLTTRON than this simple agent, however this agent shows the patterns for larger agents. In the following section we will port an agent from the VOLTTRON 8.x platform to the modular code base. The process will actually allow the agent to be installed on both the 8.x platform and the modular code base.
This tutorial unlike the one above will not use pipenv as a package manager. Instead there will be a plain virtual environment in which we can install volttron-server and the upgraded existing agent. This tutorial is made in two parts, the first we upgrade the agent and install it on the 8.x platform and second we create a virtual environment and install the modular code and the agent.
-
Create a directory for a new example agent 'mynewlistener' outside of the volttron-listener agent created above.
$> mkdir mynewlistener $> cd mynewlistener
-
Copy the current <volttron_8.x source dir>/examples/ListenerAgent to your directory. Modify the source path in the below command before executing
$> cp <volttron_8.x_source dir>/examples/ListenerAgent . -R
-
Modify the top of the file ./ListenerAgent/listener/agent.py file. Replace the imports statements that import VOLTTRON specific packages with the following code:
try: # Attempt to import from 8.x version of VOLTTRON if not successful to import then # attempt to import from modular version of VOLTTRON. from volttron.platform.agent import utils from volttron.platform.messaging.health import STATUS_GOOD from volttron.platform.vip.agent import Agent, Core, PubSub from volttron.platform.vip.agent.subsystems.query import Query except ImportError: from volttron import utils from volttron.client.messaging.health import STATUS_GOOD from volttron.client.vip.agent import Agent, Core, PubSub from volttron.client.vip.agent.subsystems.query import Query
-
Edit the ./ListenerAgent/setup.py file and remove the install_requires line
# Setup setup( name=agent_package + 'agent', version=__version__, ############## REMOVE THIS LINE ### install_requires=['volttron'], ################ packages=packages, entry_points={ 'setuptools.installation': [ 'eggsecutable = ' + agent_module + ':main', ] } )
-
Activate the VOLTTRON 8.x environment and install the agent
$> cd <yourvolttron 8.x sourcedirectory> $> source env/bin/activate $(volttron)> cd <your mynewlistener directory> $(volttron)> volttron -vv -l volttron.log & $(volttron)> vctl install ListenerAgent --start $(volttron)> tail -f volttron.log # ctrl-d to exit tail.
-
Once verified that the listener is running as expected stop volttron
$(volttron)> vctl shutdown --platform
-
Remove VOLTTRON home(update path below if you are using custom $VOLTTRON_HOME) and deactivate
$(volttron)> rm -rf ~/.volttron $(volttron)> deactivate $>
-
Move to a different directory (modularcode) and create a virtual environment
$> cd .. && mkdir modularcode && cd modularcode $> python3 -m venv venv
-
Activate the new envrironment
$> source venv/bin/activate
-
Install volttron-server the environment.
$(venv)> pip install volttron-server
-
Start volttron. Below command will start moduler VOLTTRON server
$(venv)> volttron -vv -l volttron.log &
-
Install and start the Listener agent you modified - i.e. the agent under mynewlistener directory. Update source path in the below command
$(venv)> vctl install <parent directory>/mynewlistener/ListenerAgent --start
-
Verify successful start through the log or status
$(venv) vctl status # or $(venv) tail -f volttron.log
That's it for this agent. There are a lot of agents where this will be enough to do the transition. For other items there may be some more things to modify, however VOLTTRON team will have a full disclosure of those in the upcoming white paper and will update this repository accordingly.