prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  King Island: battery never seems to discharge 
  I've been keeping an eye on AUS-TAS-KI since it was added to the map. Charging works fine, discharging doesn't show up.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `parsers/AUS_TAS_KI.py`
  Content:
  ```
  1 # Initial PR https://github.com/tmrowco/electricitymap-contrib/pull/2456
  2 # Discussion thread https://github.com/tmrowco/electricitymap-contrib/issues/636
  3 # A promotion webpage for King's Island energy production is here : https://www.hydro.com.au/clean-energy/hybrid-energy-solutions/success-stories/king-island
  4 # As of 09/2020, it embeds with <iframe> the URI https://data.ajenti.com.au/KIREIP/index.html
  5 # About the data, the feed we get seems to be counters with a 2 seconds interval.
  6 # That means that if we fetch these counters every 15 minutes, we only are reading "instantaneous" metters that could differ from the total quantity of energies at play. To get the very exact data, we would need to have a parser running constanty to collect those 2-sec interval counters.
  7 
  8 import asyncio
  9 import json
  10 import logging
  11 import arrow
  12 from signalr import Connection
  13 from requests import Session
  14 
  15 class SignalR:
  16     def __init__(self, url):
  17         self.url = url
  18     
  19     def update_res(self, msg):
  20         if (msg != {}):
  21             self.res = msg
  22 
  23     def get_value(self, hub, method):
  24         self.res = {}
  25         with Session() as session:
  26             #create a connection
  27             connection = Connection(self.url, session)
  28             chat = connection.register_hub(hub)
  29             chat.client.on(method, self.update_res)
  30             connection.start()
  31             connection.wait(3)
  32             connection.close()
  33             return self.res
  34         
  35 def parse_payload(logger, payload):
  36     technologies_parsed = {}
  37     if not 'technologies' in payload:
  38       raise KeyError(
  39         f"No 'technologies' in payload\n"
  40         f"serie : {json.dumps(payload)}"
  41       )
  42     else:
  43       logger.debug(f"serie : {json.dumps(payload)}")
  44     for technology in payload['technologies']:
  45         assert technology['unit'] == 'kW'
  46         # The upstream API gives us kW, we need MW
  47         technologies_parsed[technology['id']] = int(technology['value'])/1000
  48     logger.debug(f"production : {json.dumps(technologies_parsed)}")
  49 
  50     biodiesel_percent = payload['biodiesel']['percent']
  51 
  52     return technologies_parsed, biodiesel_percent
  53 
  54 # Both keys battery and flywheel are negative when storing energy, and positive when feeding energy to the grid
  55 def format_storage_techs(technologies_parsed):
  56     storage_techs = technologies_parsed['battery']+technologies_parsed['flywheel']
  57     battery_production = storage_techs if storage_techs > 0 else 0
  58     battery_storage = storage_techs if storage_techs < 0 else 0
  59 
  60     return battery_production, battery_storage
  61 
  62 def fetch_production(zone_key='AUS-TAS-KI', session=None, target_datetime=None, logger: logging.Logger = logging.getLogger(__name__)):
  63 
  64     if target_datetime is not None:
  65         raise NotImplementedError('The datasource currently implemented is only real time')
  66       
  67     payload = SignalR("https://data.ajenti.com.au/live/signalr").get_value("TagHub", "Dashboard")
  68     technologies_parsed, biodiesel_percent = parse_payload(logger, payload)
  69     battery_production, battery_storage = format_storage_techs(technologies_parsed)
  70     return {
  71       'zoneKey': zone_key,
  72       'datetime': arrow.now(tz='Australia/Currie').datetime,
  73       'production': {
  74           'battery discharge': battery_production,
  75           'biomass': technologies_parsed['diesel']*biodiesel_percent/100,
  76           'coal': 0,
  77           'gas': 0,
  78           'hydro': 0,
  79           'nuclear': 0,
  80           'oil': technologies_parsed['diesel']*(100-biodiesel_percent)/100,
  81           'solar': technologies_parsed['solar'],
  82           'wind': 0 if technologies_parsed['wind'] < 0 and technologies_parsed['wind'] > -0.1 else technologies_parsed['wind'], #If wind between 0 and -0.1 set to 0 to ignore self-consumption
  83           'geothermal': 0,
  84           'unknown': 0
  85       },
  86       'storage': {
  87           'battery': battery_storage*-1
  88       },
  89       'source': 'https://data.ajenti.com.au/KIREIP/index.html'
  90     }
  91 
  92 if __name__ == '__main__':
  93     print(fetch_production())
  94
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/parsers/AUS_TAS_KI.py b/parsers/AUS_TAS_KI.py
  --- a/parsers/AUS_TAS_KI.py
  +++ b/parsers/AUS_TAS_KI.py
  @@ -52,12 +52,10 @@
       return technologies_parsed, biodiesel_percent
   
   # Both keys battery and flywheel are negative when storing energy, and positive when feeding energy to the grid
  -def format_storage_techs(technologies_parsed):
  +def sum_storage_techs(technologies_parsed):
       storage_techs = technologies_parsed['battery']+technologies_parsed['flywheel']
  -    battery_production = storage_techs if storage_techs > 0 else 0
  -    battery_storage = storage_techs if storage_techs < 0 else 0
   
  -    return battery_production, battery_storage
  +    return storage_techs
   
   def fetch_production(zone_key='AUS-TAS-KI', session=None, target_datetime=None, logger: logging.Logger = logging.getLogger(__name__)):
   
  @@ -66,12 +64,11 @@
         
       payload = SignalR("https://data.ajenti.com.au/live/signalr").get_value("TagHub", "Dashboard")
       technologies_parsed, biodiesel_percent = parse_payload(logger, payload)
  -    battery_production, battery_storage = format_storage_techs(technologies_parsed)
  +    storage_techs = sum_storage_techs(technologies_parsed)
       return {
         'zoneKey': zone_key,
         'datetime': arrow.now(tz='Australia/Currie').datetime,
         'production': {
  -          'battery discharge': battery_production,
             'biomass': technologies_parsed['diesel']*biodiesel_percent/100,
             'coal': 0,
             'gas': 0,
  @@ -84,9 +81,9 @@
             'unknown': 0
         },
         'storage': {
  -          'battery': battery_storage*-1
  +          'battery': storage_techs*-1 #Somewhat counterintuitively,to ElectricityMap positive means charging and negative means discharging
         },
  -      'source': 'https://data.ajenti.com.au/KIREIP/index.html'
  +      'source': 'https://www.hydro.com.au/clean-energy/hybrid-energy-solutions/success-stories/king-island' #Iframe: https://data.ajenti.com.au/KIREIP/index.html
       }
   
   if __name__ == '__main__':
  
verification_info: {"golden_diff": "diff --git a/parsers/AUS_TAS_KI.py b/parsers/AUS_TAS_KI.py\n--- a/parsers/AUS_TAS_KI.py\n+++ b/parsers/AUS_TAS_KI.py\n@@ -52,12 +52,10 @@\n     return technologies_parsed, biodiesel_percent\n \n # Both keys battery and flywheel are negative when storing energy, and positive when feeding energy to the grid\n-def format_storage_techs(technologies_parsed):\n+def sum_storage_techs(technologies_parsed):\n     storage_techs = technologies_parsed['battery']+technologies_parsed['flywheel']\n-    battery_production = storage_techs if storage_techs > 0 else 0\n-    battery_storage = storage_techs if storage_techs < 0 else 0\n \n-    return battery_production, battery_storage\n+    return storage_techs\n \n def fetch_production(zone_key='AUS-TAS-KI', session=None, target_datetime=None, logger: logging.Logger = logging.getLogger(__name__)):\n \n@@ -66,12 +64,11 @@\n       \n     payload = SignalR(\"https://data.ajenti.com.au/live/signalr\").get_value(\"TagHub\", \"Dashboard\")\n     technologies_parsed, biodiesel_percent = parse_payload(logger, payload)\n-    battery_production, battery_storage = format_storage_techs(technologies_parsed)\n+    storage_techs = sum_storage_techs(technologies_parsed)\n     return {\n       'zoneKey': zone_key,\n       'datetime': arrow.now(tz='Australia/Currie').datetime,\n       'production': {\n-          'battery discharge': battery_production,\n           'biomass': technologies_parsed['diesel']*biodiesel_percent/100,\n           'coal': 0,\n           'gas': 0,\n@@ -84,9 +81,9 @@\n           'unknown': 0\n       },\n       'storage': {\n-          'battery': battery_storage*-1\n+          'battery': storage_techs*-1 #Somewhat counterintuitively,to ElectricityMap positive means charging and negative means discharging\n       },\n-      'source': 'https://data.ajenti.com.au/KIREIP/index.html'\n+      'source': 'https://www.hydro.com.au/clean-energy/hybrid-energy-solutions/success-stories/king-island' #Iframe: https://data.ajenti.com.au/KIREIP/index.html\n     }\n \n if __name__ == '__main__':\n", "issue": "King Island: battery never seems to discharge \nI've been keeping an eye on AUS-TAS-KI since it was added to the map. Charging works fine, discharging doesn't show up.\n", "before_files": [{"content": "# Initial PR https://github.com/tmrowco/electricitymap-contrib/pull/2456\n# Discussion thread https://github.com/tmrowco/electricitymap-contrib/issues/636\n# A promotion webpage for King's Island energy production is here : https://www.hydro.com.au/clean-energy/hybrid-energy-solutions/success-stories/king-island\n# As of 09/2020, it embeds with <iframe> the URI https://data.ajenti.com.au/KIREIP/index.html\n# About the data, the feed we get seems to be counters with a 2 seconds interval.\n# That means that if we fetch these counters every 15 minutes, we only are reading \"instantaneous\" metters that could differ from the total quantity of energies at play. To get the very exact data, we would need to have a parser running constanty to collect those 2-sec interval counters.\n\nimport asyncio\nimport json\nimport logging\nimport arrow\nfrom signalr import Connection\nfrom requests import Session\n\nclass SignalR:\n    def __init__(self, url):\n        self.url = url\n    \n    def update_res(self, msg):\n        if (msg != {}):\n            self.res = msg\n\n    def get_value(self, hub, method):\n        self.res = {}\n        with Session() as session:\n            #create a connection\n            connection = Connection(self.url, session)\n            chat = connection.register_hub(hub)\n            chat.client.on(method, self.update_res)\n            connection.start()\n            connection.wait(3)\n            connection.close()\n            return self.res\n        \ndef parse_payload(logger, payload):\n    technologies_parsed = {}\n    if not 'technologies' in payload:\n      raise KeyError(\n        f\"No 'technologies' in payload\\n\"\n        f\"serie : {json.dumps(payload)}\"\n      )\n    else:\n      logger.debug(f\"serie : {json.dumps(payload)}\")\n    for technology in payload['technologies']:\n        assert technology['unit'] == 'kW'\n        # The upstream API gives us kW, we need MW\n        technologies_parsed[technology['id']] = int(technology['value'])/1000\n    logger.debug(f\"production : {json.dumps(technologies_parsed)}\")\n\n    biodiesel_percent = payload['biodiesel']['percent']\n\n    return technologies_parsed, biodiesel_percent\n\n# Both keys battery and flywheel are negative when storing energy, and positive when feeding energy to the grid\ndef format_storage_techs(technologies_parsed):\n    storage_techs = technologies_parsed['battery']+technologies_parsed['flywheel']\n    battery_production = storage_techs if storage_techs > 0 else 0\n    battery_storage = storage_techs if storage_techs < 0 else 0\n\n    return battery_production, battery_storage\n\ndef fetch_production(zone_key='AUS-TAS-KI', session=None, target_datetime=None, logger: logging.Logger = logging.getLogger(__name__)):\n\n    if target_datetime is not None:\n        raise NotImplementedError('The datasource currently implemented is only real time')\n      \n    payload = SignalR(\"https://data.ajenti.com.au/live/signalr\").get_value(\"TagHub\", \"Dashboard\")\n    technologies_parsed, biodiesel_percent = parse_payload(logger, payload)\n    battery_production, battery_storage = format_storage_techs(technologies_parsed)\n    return {\n      'zoneKey': zone_key,\n      'datetime': arrow.now(tz='Australia/Currie').datetime,\n      'production': {\n          'battery discharge': battery_production,\n          'biomass': technologies_parsed['diesel']*biodiesel_percent/100,\n          'coal': 0,\n          'gas': 0,\n          'hydro': 0,\n          'nuclear': 0,\n          'oil': technologies_parsed['diesel']*(100-biodiesel_percent)/100,\n          'solar': technologies_parsed['solar'],\n          'wind': 0 if technologies_parsed['wind'] < 0 and technologies_parsed['wind'] > -0.1 else technologies_parsed['wind'], #If wind between 0 and -0.1 set to 0 to ignore self-consumption\n          'geothermal': 0,\n          'unknown': 0\n      },\n      'storage': {\n          'battery': battery_storage*-1\n      },\n      'source': 'https://data.ajenti.com.au/KIREIP/index.html'\n    }\n\nif __name__ == '__main__':\n    print(fetch_production())\n", "path": "parsers/AUS_TAS_KI.py"}], "after_files": [{"content": "# Initial PR https://github.com/tmrowco/electricitymap-contrib/pull/2456\n# Discussion thread https://github.com/tmrowco/electricitymap-contrib/issues/636\n# A promotion webpage for King's Island energy production is here : https://www.hydro.com.au/clean-energy/hybrid-energy-solutions/success-stories/king-island\n# As of 09/2020, it embeds with <iframe> the URI https://data.ajenti.com.au/KIREIP/index.html\n# About the data, the feed we get seems to be counters with a 2 seconds interval.\n# That means that if we fetch these counters every 15 minutes, we only are reading \"instantaneous\" metters that could differ from the total quantity of energies at play. To get the very exact data, we would need to have a parser running constanty to collect those 2-sec interval counters.\n\nimport asyncio\nimport json\nimport logging\nimport arrow\nfrom signalr import Connection\nfrom requests import Session\n\nclass SignalR:\n    def __init__(self, url):\n        self.url = url\n    \n    def update_res(self, msg):\n        if (msg != {}):\n            self.res = msg\n\n    def get_value(self, hub, method):\n        self.res = {}\n        with Session() as session:\n            #create a connection\n            connection = Connection(self.url, session)\n            chat = connection.register_hub(hub)\n            chat.client.on(method, self.update_res)\n            connection.start()\n            connection.wait(3)\n            connection.close()\n            return self.res\n        \ndef parse_payload(logger, payload):\n    technologies_parsed = {}\n    if not 'technologies' in payload:\n      raise KeyError(\n        f\"No 'technologies' in payload\\n\"\n        f\"serie : {json.dumps(payload)}\"\n      )\n    else:\n      logger.debug(f\"serie : {json.dumps(payload)}\")\n    for technology in payload['technologies']:\n        assert technology['unit'] == 'kW'\n        # The upstream API gives us kW, we need MW\n        technologies_parsed[technology['id']] = int(technology['value'])/1000\n    logger.debug(f\"production : {json.dumps(technologies_parsed)}\")\n\n    biodiesel_percent = payload['biodiesel']['percent']\n\n    return technologies_parsed, biodiesel_percent\n\n# Both keys battery and flywheel are negative when storing energy, and positive when feeding energy to the grid\ndef sum_storage_techs(technologies_parsed):\n    storage_techs = technologies_parsed['battery']+technologies_parsed['flywheel']\n\n    return storage_techs\n\ndef fetch_production(zone_key='AUS-TAS-KI', session=None, target_datetime=None, logger: logging.Logger = logging.getLogger(__name__)):\n\n    if target_datetime is not None:\n        raise NotImplementedError('The datasource currently implemented is only real time')\n      \n    payload = SignalR(\"https://data.ajenti.com.au/live/signalr\").get_value(\"TagHub\", \"Dashboard\")\n    technologies_parsed, biodiesel_percent = parse_payload(logger, payload)\n    storage_techs = sum_storage_techs(technologies_parsed)\n    return {\n      'zoneKey': zone_key,\n      'datetime': arrow.now(tz='Australia/Currie').datetime,\n      'production': {\n          'biomass': technologies_parsed['diesel']*biodiesel_percent/100,\n          'coal': 0,\n          'gas': 0,\n          'hydro': 0,\n          'nuclear': 0,\n          'oil': technologies_parsed['diesel']*(100-biodiesel_percent)/100,\n          'solar': technologies_parsed['solar'],\n          'wind': 0 if technologies_parsed['wind'] < 0 and technologies_parsed['wind'] > -0.1 else technologies_parsed['wind'], #If wind between 0 and -0.1 set to 0 to ignore self-consumption\n          'geothermal': 0,\n          'unknown': 0\n      },\n      'storage': {\n          'battery': storage_techs*-1 #Somewhat counterintuitively,to ElectricityMap positive means charging and negative means discharging\n      },\n      'source': 'https://www.hydro.com.au/clean-energy/hybrid-energy-solutions/success-stories/king-island' #Iframe: https://data.ajenti.com.au/KIREIP/index.html\n    }\n\nif __name__ == '__main__':\n    print(fetch_production())\n", "path": "parsers/AUS_TAS_KI.py"}]}