GENWiki

Premier IT Outsourcing and Support Services within the UK

User Tools

Site Tools


opensource:pulling_the_uk_threat_level_from_mi5

Pulling the Current UK Threat Level from MI5

The MI5 provide 'the current' UK threat level in an RSS (Atom) feed, which can be parsed to use within Home Assistant. Unfortunately, feedreader is poorly documented and doesn't really do what we need so for this you have two options; AppDeemon, PyScript, both of which are Add-ons from HACS.

I'm going to document the PyScript Method here, and this tutorial assumed you already have PyScript installed and working.

PyScript

Firstly, create an input_text helper called threatlevel. This is where we'll store the threat level.

Next, we create our PyScript code (which you place in config/pyscript by default) in a file named mi5.py:

  1. import feedparser
  2. import requests
  3. import json
  4. import pprint
  5. import datetime
  6. @pyscript_compile
  7. def getmi5(url):
  8. try:
  9. headers = {'User-Agent': 'curl/7.68.0'}
  10. response = requests.get(url, headers=headers)
  11. data = response.content # bytes cus its UTF-8
  12. return data, None
  13. except Exception as exc:
  14. return None, exc
  15.  
  16. @service
  17. def mi5(action=None, id=None):
  18. """MI5 API (RSS) fetcher and parser"""
  19. log.info(f"MI5 got action {action} id {id}")
  20. contents, exception = task.executor(getmi5, "https://www.mi5.gov.uk/UKThreatLevel/UKThreatLevel.xml")
  21. if exception:
  22. raise exception
  23.  
  24. feed = feedparser.parse(contents)
  25. if feed.entries:
  26. levelstr = feed.entries[0]['title']
  27. levelarr = levelstr.split(': ')
  28. level = levelarr[1]
  29. else:
  30. level = "Unknown"
  31. threat = input_text.threatlevel
  32. log.info(f"Current Value: {threat} new value {level}")
  33. if threat != level:
  34. input_text.threatlevel = level

What we are doing here is fetching the XML from the MI5 website, then parsing this with feedparser, checking we've got entries, and then extracting the threat level from the feed entry. We then check to see if its the same, and if not, we update input_text.threatlevel.

The reason we need to use task.executor, is because MI5 can't afford a proper web host and it takes too long to retrieve the feed otherwise.

To actually make this code run, you need to setup an automation to call it. Something like:

  1. alias: "Schedule: MI5 Threat Level"
  2. description: ""
  3. trigger:
  4.   - platform: time_pattern
  5.   minutes: "0"
  6. condition:
  7.   - condition: time
  8.   after: "07:00:00"
  9.   before: "22:00:00"
  10. action:
  11.   - service: pyscript.mi5
  12.   data: {}
  13. mode: single

Notice we're getting the update every hour between 0700 and 2200. Its important not to be silly with this and don't spam MI5's server or it will likely block you (I would), so once an hour seems a fair rate.

Finally, you can create an automation that's triggered on a state change of input_text.threatlevel to, for example, send you a message, play a message, broadcast an announcement and anything else you want.

AppDaemon

For anyone wanting to use AppDaemon instead this would be the code:

  1. import hassapi as hass
  2. import feedparser
  3. import requests
  4. import json
  5. import pprint
  6. import datetime
  7.  
  8. class MI5(hass.Hass):
  9.  
  10. def initialize(self):
  11. self.run_hourly(self.run_schedule, datetime.time(hour=0))
  12.  
  13. def run_schedule(self, cb_args):
  14. url = "https://www.mi5.gov.uk/UKThreatLevel/UKThreatLevel.xml"
  15. headers = {'User-Agent': 'curl/7.68.0'}
  16. response = requests.get(url, headers=headers)
  17.  
  18. data = response.content # bytes cus its UTF-8
  19. feed = feedparser.parse(data)
  20. if feed.entries:
  21. levelstr = feed.entries[0]['title']
  22. levelarr = levelstr.split(': ')
  23. level = levelarr[1]
  24. else:
  25. level = "Unknown"
  26.  
  27. clevel = self.get_entity("input_text.threatlevel")
  28.  
  29. if clevel.state != level:
  30. log = "Setting threat level to "+level
  31. self.log(log)
  32. self.set_textvalue("input_text.threatlevel",level)
  33. self.set_state("input_text.threatlevel",level)
  34. else:
  35. self.log("No Change Required")

Don't forget to add the app in apps.yaml.

/home/gen.uk/domains/wiki.gen.uk/public_html/data/pages/opensource/pulling_the_uk_threat_level_from_mi5.txt · Last modified: 2024/02/20 18:57 by genadmin

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki