Repository: electricitymaps/electricitymaps-contrib

Issue:
Bornholm
From the nitpicking file ;)

Currently we draw Bornholm as part of Denmark.

From what I've read, Bornholm is connected to Swedish mainland grid ([Bornholm Cable](https://en.wikipedia.org/wiki/Bornholm_Cable)).

Questions/issues:
- [ ] Is Bornholm generation included in Swedish or Danish totals, or neither?
- [ ] Is it possible to break out its generation, including any imports/exports?



Discussion:
In sorta the same area, Shetland is not connected to the main UK Grid, but is drawn as being part of it.

@bjarkigd right, good point! I pasted that into the ticket for Scotland, #596
Hi @jarek,
Happy to see you added this issue. I'm in discussion with DTU Elektro and Bornholm to try to get us access to the data. It's taking time though, but I know they have it!
Will send them a follow up email
Olivier
I'm at a Danish conference and was able to dig out some info:
- Live viz is here: http://bornholm.powerlab.dk/
- Live data is here (JSON): http://bornholm.powerlab.dk/visualizer/latestdata, including interconnector to SE
- Apparently the data we get for DK currently includes Bornholm production (same with interconnectors)

Let's do it!
I've added the geometry. Only the parser is left to do.
What sort of generation is factory?
Biomass

On Fri 26 Jan 2018 at 11:46, Chris <notifications@github.com> wrote:

> What sort of generation is factory?
>
> —
> You are receiving this because you commented.
>
>
> Reply to this email directly, view it on GitHub
> <https://github.com/tmrowco/electricitymap/issues/882#issuecomment-360747769>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/ABlEKOULVDWXKRITLCN0pBQdj-gJ-2j5ks5tOazugaJpZM4QxG8u>
> .
>

@systemcatch from looking at the dashboard, I'd say Biomass
" The important CHP plant in Rønne has just been converted from coal to sustainable biomass, so most of the electricity consumption of approx. 230 GWh will be covered with green electricity. "
@systemcatch are you working on this? If yes, can you assign yourself? Then we can see who is working on what!

Not at the moment but I can do it if you want to get this up and running
soon? Maybe someone else would like a crack at it though, looks like a good
first issue.

On 26 Jan 2018 16:05, "Olivier Corradi" <notifications@github.com> wrote:

@systemcatch <https://github.com/systemcatch> are you working on this? If
yes, can you assign yourself? Then we can see who is working on what!

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<https://github.com/tmrowco/electricitymap/issues/882#issuecomment-360826316>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AczDHoTSr-dXxmQQ6bzw4_GUdXx8E806ks5tOfe4gaJpZM4QxG8u>
.


Resolving patch:
diff --git a/mockserver/update_state.py b/mockserver/update_state.py
--- a/mockserver/update_state.py
+++ b/mockserver/update_state.py
@@ -37,24 +37,25 @@
     raise Exception('Missing argument <zone_name>')
 
 if sys.argv[1] == 'all':
-    zone_name = list(zones_config.keys())
+    zone_names = list(zones_config.keys())
     zone_config = zones_config
 else:
-    zone_name = [sys.argv[1]]
+    zone_names = [sys.argv[1]]
     zone_config = zones_config
 
-exchange_parser_keys = []
+exchange_parser_keys = set()
 for k in exchanges_config.keys():
     if sys.argv[1] == 'all':
         exchange_parser_keys = list(exchanges_config.keys())
         break
     zones = k.split('->')
-    if zone_name in zones:
-        exchange_parser_keys.append(k)
+    for zone_name in zone_names:
+        if zone_name in zones:
+            exchange_parser_keys.add(k)
 
 # Import / run production parser
 production_datapoints = []
-for k in zone_name:
+for k in zone_names:
     try:
         production_parser = zone_config[k]['parsers']['production']
     except KeyError as e:
@@ -85,6 +86,7 @@
         exchange_parser = exchanges_config[k]['parsers']['exchange']
     except KeyError as e:
         # There is no exchange implemented yet.
+        print('No exchange parser found for {}'.format(k))
         continue
 
     mod_name, fun_name = exchange_parser.split('.')
diff --git a/parsers/DK_BHM.py b/parsers/DK_BHM.py
new file mode 100644
--- /dev/null
+++ b/parsers/DK_BHM.py
@@ -0,0 +1,112 @@
+#!/usr/bin/env python3
+# The arrow library is used to handle datetimes
+import arrow
+# The request library is used to fetch content through HTTP
+import requests
+
+PRODUCTION_MAPPING = {
+    'wind': 'wind_turbines',
+    'biomass': 'factory',
+    'solar': 'solar_cells',
+}
+
+
+def _fetch_data(session=None):
+    r = session or requests.session()
+    url = 'http://bornholm.powerlab.dk/visualizer/latestdata'
+    response = r.get(url)
+    obj = response.json()
+    return obj
+
+
+def fetch_production(country_code='DK-BHM', session=None):
+    """Requests the last known production mix (in MW) of a given country
+
+    Arguments:
+    country_code (optional) -- used in case a parser is able to fetch multiple countries
+    session (optional)      -- request session passed in order to re-use an existing session
+
+    Return:
+    A dictionary in the form:
+    {
+      'countryCode': 'FR',
+      'datetime': '2017-01-01T00:00:00Z',
+      'production': {
+          'biomass': 0.0,
+          'coal': 0.0,
+          'gas': 0.0,
+          'hydro': 0.0,
+          'nuclear': null,
+          'oil': 0.0,
+          'solar': 0.0,
+          'wind': 0.0,
+          'geothermal': 0.0,
+          'unknown': 0.0
+      },
+      'storage': {
+          'hydro': -10.0,
+      },
+      'source': 'mysource.com'
+    }
+    """
+    obj = _fetch_data(session)
+
+    data = {
+        'countryCode': country_code,
+        'production': {},
+        'storage': {},
+        'source': 'bornholm.powerlab.dk',
+        'datetime': arrow.get(obj['latest']).datetime
+    }
+    for productionKey, objKey in PRODUCTION_MAPPING.items():
+        data['production'][productionKey] = obj['sub'][objKey]
+
+    return data
+
+
+def fetch_exchange(country_code1='DK-BHM', country_code2='SE', session=None):
+    """Requests the last known power exchange (in MW) between two countries
+
+    Arguments:
+    country_code (optional) -- used in case a parser is able to fetch multiple countries
+    session (optional)      -- request session passed in order to re-use an existing session
+
+    Return:
+    A dictionary in the form:
+    {
+      'sortedCountryCodes': 'DK->NO',
+      'datetime': '2017-01-01T00:00:00Z',
+      'netFlow': 0.0,
+      'source': 'mysource.com'
+    }
+    """
+
+    obj = _fetch_data(session)
+
+    data = {
+        'sortedCountryCodes': '->'.join(sorted([country_code1, country_code2])),
+        'source': 'bornholm.powerlab.dk',
+        'datetime': arrow.get(obj['latest']).datetime
+    }
+
+    # Country codes are sorted in order to enable easier indexing in the database
+    sorted_country_codes = sorted([country_code1, country_code2])
+    # Here we assume that the net flow returned by the api is the flow from
+    # country1 to country2. A positive flow indicates an export from country1
+    # to country2. A negative flow indicates an import.
+    netFlow = obj['sub']['seacable'] # Export is positive
+    # The net flow to be reported should be from the first country to the second
+    # (sorted alphabetically). This is NOT necessarily the same direction as the flow
+    # from country1 to country2
+    data['netFlow'] = netFlow if country_code1 == sorted_country_codes[0] else -1 * netFlow
+
+    return data
+
+
+if __name__ == '__main__':
+    """Main method, never used by the Electricity Map backend, but handy for testing."""
+
+    print('fetch_production() ->')
+    print(fetch_production())
+    print('fetch_exchange(DK-BHM, SE) ->')
+    print(fetch_exchange('DK-BHM', 'SE'))


Test patch: