{"action":"created","comment":{"url":"https://api.github.com/repos/VOLTTRON/volttron/pulls/comments/91848013","pull_request_review_id":12359930,"id":91848013,"diff_hunk":"@@ -58,95 +58,137 @@\n import logging\n from datetime import datetime\n \n+import gevent\n+\n from volttron.platform.vip.agent import Agent, Core, RPC\n+from volttron.platform.vip.agent.utils import build_agent\n from volttron.platform.agent import utils\n from volttron.platform.messaging.health import Status, STATUS_BAD\n from volttron.platform.agent.known_identities import PLATFORM_ALERTER\n \n utils.setup_logging()\n _log = logging.getLogger(__name__)\n \n-__version__ = '0.3'\n+__version__ = '0.4'\n \n \n class AlertAgent(Agent):\n     def __init__(self, config_path, **kwargs):\n         super(AlertAgent, self).__init__(**kwargs)\n         self.config = utils.load_config(config_path)\n-        self.wait_time = {}\n-        self.topic_ttl = {}\n-        self.point_ttl = {}\n+        self.group_agent = {}\n \n     @Core.receiver('onstart')\n     def onstart(self, sender, **kwargs):\n-        config = self.config\n-        for topic in config.iterkeys():\n-\n-            # Optional config option with a list of points that\n-            # might not be published.\n-            if type(config[topic]) is dict:\n-                point_config = config[topic]\n-                self.watch_device(topic,\n-                                  point_config[\"seconds\"],\n-                                  point_config[\"points\"])\n+        for group_name, config in self.config.items():\n+            event = gevent.event.Event()\n+            group = AlertGroup(group_name, config,\n+                               address=self.core.address,\n+                               enable_store=False)\n+            gevent.spawn(group.core.run, event)\n+            event.wait()\n \n-            # Default config option\n-            else:\n-                timeout = config[topic]\n-                self.watch_topic(topic, timeout)\n+            self.group_agent[group_name] = group\n \n     @RPC.export\n-    def watch_topic(self, topic, timeout):\n+    def watch_topic(self, group, topic, timeout):\n         \"\"\"RPC method\n \n         Listen for a topic to be published within a given\n         number of seconds or send alerts.\n \n+        :pararm group: Group that should watch the topic.\n+        :type group: str\n         :param topic: Topic expected to be published.\n         :type topic: str\n         :param timeout: Seconds before an alert is sent.\n         :type timeout: int\n         \"\"\"\n-        self.wait_time[topic] = timeout\n-        self.topic_ttl[topic] = timeout\n-        self.vip.pubsub.subscribe(peer='pubsub',\n-                                  prefix=topic,\n-                                  callback=self.reset_time)\n-        _log.info(\"Expecting {} every {} seconds\"\n-                   .format(topic, timeout))\n+        group = self.group_agent[group]\n+        group.watch_topic(topic, timeout)\n \n     @RPC.export\n-    def watch_device(self, topic, timeout, points):\n+    def watch_device(self, group, topic, timeout, points):\n         \"\"\"RPC method\n-        \n+\n         Watch a device's ALL topic and expect points. This\n         method calls the watch topic method so both methods\n         don't need to be called.\n \n+        :pararm group: Group that should watch the device.\n+        :type group: str\n         :param topic: Topic expected to be published.\n         :type topic: str\n         :param timeout: Seconds before an alert is sent.\n         :type timeout: int\n         :param points: Points to expect in the publish message.\n         :type points: [str]\n         \"\"\"\n-        self.point_ttl[topic] = {}\n-\n-        for p in points:\n-            self.point_ttl[topic][p] = timeout\n-\n-        self.watch_topic(topic, timeout)\n+        group = self.group_agent[group]\n+        group.watch_device(topic, timeout, points)\n \n     @RPC.export\n-    def ignore_topic(self, topic):\n+    def ignore_topic(self, group, topic):\n         \"\"\"RPC method\n \n         Remove a topic from agent's watch list. Alerts will no\n         longer be sent if a topic stops being published.\n \n+        :param group: Group that should ignore the topic.\n+        :type group: str\n         :param topic: Topic to remove from the watch list.\n         :type topic: str\n         \"\"\"\n+        group = self.group_agent[group]\n+        group.ignore_topic(topic)\n+\n+\n+class AlertGroup(Agent):\n+    def __init__(self, group_name, config, **kwargs):\n+        super(AlertGroup, self).__init__(**kwargs)\n+        self.group_name = group_name\n+        self.config = config\n+        self.wait_time = {}\n+        self.topic_ttl = {}\n+        self.point_ttl = {}\n+\n+    @Core.receiver('onstart')\n+    def onstart(self, sender, **kwargs):\n+        _log.info(\"Listening for alert group {}\".format(self.group_name))\n+        config = self.config\n+        for topic in config.iterkeys():\n+\n+            # Optional config option with a list of points that\n+            # might not be published.\n+            if type(config[topic]) is dict:\n+                point_config = config[topic]\n+                self.watch_device(topic,\n+                                  point_config[\"seconds\"],\n+                                  point_config[\"points\"])\n+\n+            # Default config option\n+            else:\n+                timeout = config[topic]\n+                self.watch_topic(topic, timeout)\n+\n+    def watch_topic(self, topic, timeout):\n+        self.wait_time[topic] = timeout","path":"services/core/AlertAgent/alerter/agent.py","position":153,"original_position":153,"commit_id":"aa3d25709e675c8f4d4cb9a5f9ca50a11acba4a7","original_commit_id":"aa3d25709e675c8f4d4cb9a5f9ca50a11acba4a7","user":{"login":"craig8","id":3979063,"avatar_url":"https://avatars.githubusercontent.com/u/3979063?v=3","gravatar_id":"","url":"https://api.github.com/users/craig8","html_url":"https://github.com/craig8","followers_url":"https://api.github.com/users/craig8/followers","following_url":"https://api.github.com/users/craig8/following{/other_user}","gists_url":"https://api.github.com/users/craig8/gists{/gist_id}","starred_url":"https://api.github.com/users/craig8/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/craig8/subscriptions","organizations_url":"https://api.github.com/users/craig8/orgs","repos_url":"https://api.github.com/users/craig8/repos","events_url":"https://api.github.com/users/craig8/events{/privacy}","received_events_url":"https://api.github.com/users/craig8/received_events","type":"User","site_admin":false},"body":"Add documentation to these methods.","created_at":"2016-12-11T05:22:17Z","updated_at":"2016-12-11T05:22:17Z","html_url":"https://github.com/VOLTTRON/volttron/pull/1083#discussion_r91848013","pull_request_url":"https://api.github.com/repos/VOLTTRON/volttron/pulls/1083","_links":{"self":{"href":"https://api.github.com/repos/VOLTTRON/volttron/pulls/comments/91848013"},"html":{"href":"https://github.com/VOLTTRON/volttron/pull/1083#discussion_r91848013"},"pull_request":{"href":"https://api.github.com/repos/VOLTTRON/volttron/pulls/1083"}}},"pull_request":{"url":"https://api.github.com/repos/VOLTTRON/volttron/pulls/1083","id":96591517,"html_url":"https://github.com/VOLTTRON/volttron/pull/1083","diff_url":"https://github.com/VOLTTRON/volttron/pull/1083.diff","patch_url":"https://github.com/VOLTTRON/volttron/pull/1083.patch","issue_url":"https://api.github.com/repos/VOLTTRON/volttron/issues/1083","number":1083,"state":"open","locked":false,"title":"Add grouping to alert agent","user":{"login":"mikeroup","id":4081515,"avatar_url":"https://avatars.githubusercontent.com/u/4081515?v=3","gravatar_id":"","url":"https://api.github.com/users/mikeroup","html_url":"https://github.com/mikeroup","followers_url":"https://api.github.com/users/mikeroup/followers","following_url":"https://api.github.com/users/mikeroup/following{/other_user}","gists_url":"https://api.github.com/users/mikeroup/gists{/gist_id}","starred_url":"https://api.github.com/users/mikeroup/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mikeroup/subscriptions","organizations_url":"https://api.github.com/users/mikeroup/orgs","repos_url":"https://api.github.com/users/mikeroup/repos","events_url":"https://api.github.com/users/mikeroup/events{/privacy}","received_events_url":"https://api.github.com/users/mikeroup/received_events","type":"User","site_admin":false},"body":"\n\n<!-- Reviewable:start -->\nThis change is [<img src=\"https://reviewable.io/review_button.svg\" height=\"34\" align=\"absmiddle\" alt=\"Reviewable\"/>](https://reviewable.io/reviews/volttron/volttron/1083)\n<!-- Reviewable:end -->\n","created_at":"2016-12-05T19:19:33Z","updated_at":"2016-12-11T05:22:55Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c46c4b9a9ad28f67b1229206b540d87035ae3b2e","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/VOLTTRON/volttron/pulls/1083/commits","review_comments_url":"https://api.github.com/repos/VOLTTRON/volttron/pulls/1083/comments","review_comment_url":"https://api.github.com/repos/VOLTTRON/volttron/pulls/comments{/number}","comments_url":"https://api.github.com/repos/VOLTTRON/volttron/issues/1083/comments","statuses_url":"https://api.github.com/repos/VOLTTRON/volttron/statuses/aa3d25709e675c8f4d4cb9a5f9ca50a11acba4a7","head":{"label":"mikeroup:alerter-groups","ref":"alerter-groups","sha":"aa3d25709e675c8f4d4cb9a5f9ca50a11acba4a7","user":{"login":"mikeroup","id":4081515,"avatar_url":"https://avatars.githubusercontent.com/u/4081515?v=3","gravatar_id":"","url":"https://api.github.com/users/mikeroup","html_url":"https://github.com/mikeroup","followers_url":"https://api.github.com/users/mikeroup/followers","following_url":"https://api.github.com/users/mikeroup/following{/other_user}","gists_url":"https://api.github.com/users/mikeroup/gists{/gist_id}","starred_url":"https://api.github.com/users/mikeroup/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mikeroup/subscriptions","organizations_url":"https://api.github.com/users/mikeroup/orgs","repos_url":"https://api.github.com/users/mikeroup/repos","events_url":"https://api.github.com/users/mikeroup/events{/privacy}","received_events_url":"https://api.github.com/users/mikeroup/received_events","type":"User","site_admin":false},"repo":{"id":62091684,"name":"volttron","full_name":"mikeroup/volttron","owner":{"login":"mikeroup","id":4081515,"avatar_url":"https://avatars.githubusercontent.com/u/4081515?v=3","gravatar_id":"","url":"https://api.github.com/users/mikeroup","html_url":"https://github.com/mikeroup","followers_url":"https://api.github.com/users/mikeroup/followers","following_url":"https://api.github.com/users/mikeroup/following{/other_user}","gists_url":"https://api.github.com/users/mikeroup/gists{/gist_id}","starred_url":"https://api.github.com/users/mikeroup/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mikeroup/subscriptions","organizations_url":"https://api.github.com/users/mikeroup/orgs","repos_url":"https://api.github.com/users/mikeroup/repos","events_url":"https://api.github.com/users/mikeroup/events{/privacy}","received_events_url":"https://api.github.com/users/mikeroup/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mikeroup/volttron","description":"VOLTTRON Distributed Control System Platform","fork":true,"url":"https://api.github.com/repos/mikeroup/volttron","forks_url":"https://api.github.com/repos/mikeroup/volttron/forks","keys_url":"https://api.github.com/repos/mikeroup/volttron/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mikeroup/volttron/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mikeroup/volttron/teams","hooks_url":"https://api.github.com/repos/mikeroup/volttron/hooks","issue_events_url":"https://api.github.com/repos/mikeroup/volttron/issues/events{/number}","events_url":"https://api.github.com/repos/mikeroup/volttron/events","assignees_url":"https://api.github.com/repos/mikeroup/volttron/assignees{/user}","branches_url":"https://api.github.com/repos/mikeroup/volttron/branches{/branch}","tags_url":"https://api.github.com/repos/mikeroup/volttron/tags","blobs_url":"https://api.github.com/repos/mikeroup/volttron/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mikeroup/volttron/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mikeroup/volttron/git/refs{/sha}","trees_url":"https://api.github.com/repos/mikeroup/volttron/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mikeroup/volttron/statuses/{sha}","languages_url":"https://api.github.com/repos/mikeroup/volttron/languages","stargazers_url":"https://api.github.com/repos/mikeroup/volttron/stargazers","contributors_url":"https://api.github.com/repos/mikeroup/volttron/contributors","subscribers_url":"https://api.github.com/repos/mikeroup/volttron/subscribers","subscription_url":"https://api.github.com/repos/mikeroup/volttron/subscription","commits_url":"https://api.github.com/repos/mikeroup/volttron/commits{/sha}","git_commits_url":"https://api.github.com/repos/mikeroup/volttron/git/commits{/sha}","comments_url":"https://api.github.com/repos/mikeroup/volttron/comments{/number}","issue_comment_url":"https://api.github.com/repos/mikeroup/volttron/issues/comments{/number}","contents_url":"https://api.github.com/repos/mikeroup/volttron/contents/{+path}","compare_url":"https://api.github.com/repos/mikeroup/volttron/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mikeroup/volttron/merges","archive_url":"https://api.github.com/repos/mikeroup/volttron/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mikeroup/volttron/downloads","issues_url":"https://api.github.com/repos/mikeroup/volttron/issues{/number}","pulls_url":"https://api.github.com/repos/mikeroup/volttron/pulls{/number}","milestones_url":"https://api.github.com/repos/mikeroup/volttron/milestones{/number}","notifications_url":"https://api.github.com/repos/mikeroup/volttron/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mikeroup/volttron/labels{/name}","releases_url":"https://api.github.com/repos/mikeroup/volttron/releases{/id}","deployments_url":"https://api.github.com/repos/mikeroup/volttron/deployments","created_at":"2016-06-27T22:08:25Z","updated_at":"2016-06-27T22:08:28Z","pushed_at":"2016-12-09T22:05:52Z","git_url":"git://github.com/mikeroup/volttron.git","ssh_url":"git@github.com:mikeroup/volttron.git","clone_url":"https://github.com/mikeroup/volttron.git","svn_url":"https://github.com/mikeroup/volttron","homepage":null,"size":43990,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"VOLTTRON:develop","ref":"develop","sha":"b2fe867912aa33bd172916b5cfff51e1eae0cfeb","user":{"login":"VOLTTRON","id":5875448,"avatar_url":"https://avatars.githubusercontent.com/u/5875448?v=3","gravatar_id":"","url":"https://api.github.com/users/VOLTTRON","html_url":"https://github.com/VOLTTRON","followers_url":"https://api.github.com/users/VOLTTRON/followers","following_url":"https://api.github.com/users/VOLTTRON/following{/other_user}","gists_url":"https://api.github.com/users/VOLTTRON/gists{/gist_id}","starred_url":"https://api.github.com/users/VOLTTRON/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VOLTTRON/subscriptions","organizations_url":"https://api.github.com/users/VOLTTRON/orgs","repos_url":"https://api.github.com/users/VOLTTRON/repos","events_url":"https://api.github.com/users/VOLTTRON/events{/privacy}","received_events_url":"https://api.github.com/users/VOLTTRON/received_events","type":"Organization","site_admin":false},"repo":{"id":14191740,"name":"volttron","full_name":"VOLTTRON/volttron","owner":{"login":"VOLTTRON","id":5875448,"avatar_url":"https://avatars.githubusercontent.com/u/5875448?v=3","gravatar_id":"","url":"https://api.github.com/users/VOLTTRON","html_url":"https://github.com/VOLTTRON","followers_url":"https://api.github.com/users/VOLTTRON/followers","following_url":"https://api.github.com/users/VOLTTRON/following{/other_user}","gists_url":"https://api.github.com/users/VOLTTRON/gists{/gist_id}","starred_url":"https://api.github.com/users/VOLTTRON/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VOLTTRON/subscriptions","organizations_url":"https://api.github.com/users/VOLTTRON/orgs","repos_url":"https://api.github.com/users/VOLTTRON/repos","events_url":"https://api.github.com/users/VOLTTRON/events{/privacy}","received_events_url":"https://api.github.com/users/VOLTTRON/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/VOLTTRON/volttron","description":"VOLTTRON Distributed Control System Platform","fork":false,"url":"https://api.github.com/repos/VOLTTRON/volttron","forks_url":"https://api.github.com/repos/VOLTTRON/volttron/forks","keys_url":"https://api.github.com/repos/VOLTTRON/volttron/keys{/key_id}","collaborators_url":"https://api.github.com/repos/VOLTTRON/volttron/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/VOLTTRON/volttron/teams","hooks_url":"https://api.github.com/repos/VOLTTRON/volttron/hooks","issue_events_url":"https://api.github.com/repos/VOLTTRON/volttron/issues/events{/number}","events_url":"https://api.github.com/repos/VOLTTRON/volttron/events","assignees_url":"https://api.github.com/repos/VOLTTRON/volttron/assignees{/user}","branches_url":"https://api.github.com/repos/VOLTTRON/volttron/branches{/branch}","tags_url":"https://api.github.com/repos/VOLTTRON/volttron/tags","blobs_url":"https://api.github.com/repos/VOLTTRON/volttron/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/VOLTTRON/volttron/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/VOLTTRON/volttron/git/refs{/sha}","trees_url":"https://api.github.com/repos/VOLTTRON/volttron/git/trees{/sha}","statuses_url":"https://api.github.com/repos/VOLTTRON/volttron/statuses/{sha}","languages_url":"https://api.github.com/repos/VOLTTRON/volttron/languages","stargazers_url":"https://api.github.com/repos/VOLTTRON/volttron/stargazers","contributors_url":"https://api.github.com/repos/VOLTTRON/volttron/contributors","subscribers_url":"https://api.github.com/repos/VOLTTRON/volttron/subscribers","subscription_url":"https://api.github.com/repos/VOLTTRON/volttron/subscription","commits_url":"https://api.github.com/repos/VOLTTRON/volttron/commits{/sha}","git_commits_url":"https://api.github.com/repos/VOLTTRON/volttron/git/commits{/sha}","comments_url":"https://api.github.com/repos/VOLTTRON/volttron/comments{/number}","issue_comment_url":"https://api.github.com/repos/VOLTTRON/volttron/issues/comments{/number}","contents_url":"https://api.github.com/repos/VOLTTRON/volttron/contents/{+path}","compare_url":"https://api.github.com/repos/VOLTTRON/volttron/compare/{base}...{head}","merges_url":"https://api.github.com/repos/VOLTTRON/volttron/merges","archive_url":"https://api.github.com/repos/VOLTTRON/volttron/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/VOLTTRON/volttron/downloads","issues_url":"https://api.github.com/repos/VOLTTRON/volttron/issues{/number}","pulls_url":"https://api.github.com/repos/VOLTTRON/volttron/pulls{/number}","milestones_url":"https://api.github.com/repos/VOLTTRON/volttron/milestones{/number}","notifications_url":"https://api.github.com/repos/VOLTTRON/volttron/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/VOLTTRON/volttron/labels{/name}","releases_url":"https://api.github.com/repos/VOLTTRON/volttron/releases{/id}","deployments_url":"https://api.github.com/repos/VOLTTRON/volttron/deployments","created_at":"2013-11-07T02:07:46Z","updated_at":"2016-12-06T18:07:36Z","pushed_at":"2016-12-11T05:20:04Z","git_url":"git://github.com/VOLTTRON/volttron.git","ssh_url":"git@github.com:VOLTTRON/volttron.git","clone_url":"https://github.com/VOLTTRON/volttron.git","svn_url":"https://github.com/VOLTTRON/volttron","homepage":null,"size":98531,"stargazers_count":106,"watchers_count":106,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":56,"mirror_url":null,"open_issues_count":252,"forks":56,"open_issues":252,"watchers":106,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/VOLTTRON/volttron/pulls/1083"},"html":{"href":"https://github.com/VOLTTRON/volttron/pull/1083"},"issue":{"href":"https://api.github.com/repos/VOLTTRON/volttron/issues/1083"},"comments":{"href":"https://api.github.com/repos/VOLTTRON/volttron/issues/1083/comments"},"review_comments":{"href":"https://api.github.com/repos/VOLTTRON/volttron/pulls/1083/comments"},"review_comment":{"href":"https://api.github.com/repos/VOLTTRON/volttron/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/VOLTTRON/volttron/pulls/1083/commits"},"statuses":{"href":"https://api.github.com/repos/VOLTTRON/volttron/statuses/aa3d25709e675c8f4d4cb9a5f9ca50a11acba4a7"}}}}
{"actor":{"display_login":"craig8"}}