diff --git a/.github/workflows/expo-preview.yml b/.github/workflows/expo-preview.yml index 9bbd322..27f3aa7 100644 --- a/.github/workflows/expo-preview.yml +++ b/.github/workflows/expo-preview.yml @@ -9,6 +9,13 @@ jobs: name: EAS Update runs-on: ubuntu-latest steps: + - name: Check for CDN_DOMAIN_NAME_DEV + run: | + if [ -z "${{ secrets.CDN_DOMAIN_NAME_DEV }}" ]; then + echo "You must provide an CDN_DOMAIN_NAME_DEV secret linked to this project's Expo account in this repo's secrets. Learn more: https://docs.expo.dev/eas-update/github-actions" + exit 1 + fi + - name: Check for EXPO_TOKEN run: | if [ -z "${{ secrets.EXPO_TOKEN }}" ]; then @@ -36,3 +43,5 @@ jobs: - name: Publish update run: eas update --auto --channel preview + env: + EXPO_PUBLIC_CDN_DOMAIN_NAME: ${{ secrets.CDN_DOMAIN_NAME_DEV }} \ No newline at end of file diff --git a/.github/workflows/expo-prod.yml b/.github/workflows/expo-prod.yml index 647ad11..3c58989 100644 --- a/.github/workflows/expo-prod.yml +++ b/.github/workflows/expo-prod.yml @@ -10,6 +10,14 @@ jobs: name: EAS Update runs-on: ubuntu-latest steps: + + - name: Check for CDN_DOMAIN_NAME + run: | + if [ -z "${{ secrets.CDN_DOMAIN_NAME }}" ]; then + echo "You must provide an CDN_DOMAIN_NAME secret linked to this project's Expo account in this repo's secrets. Learn more: https://docs.expo.dev/eas-update/github-actions" + exit 1 + fi + - name: Check for EXPO_TOKEN run: | if [ -z "${{ secrets.EXPO_TOKEN }}" ]; then @@ -36,4 +44,6 @@ jobs: run: yarn install - name: Publish update - run: eas update --auto --channel production # Here we specify the production channel for the update. + run: eas update --auto --channel production + env: + EXPO_PUBLIC_CDN_DOMAIN_NAME: ${{ secrets.CDN_DOMAIN_NAME }} diff --git a/backend/lambda/gb_snapshot/gb_snapshot.py b/backend/lambda/gb_snapshot/gb_snapshot.py index 5ff3226..739e6b0 100644 --- a/backend/lambda/gb_snapshot/gb_snapshot.py +++ b/backend/lambda/gb_snapshot/gb_snapshot.py @@ -1,9 +1,12 @@ import logging from typing import List +from .ng_dist.ng_dist import NationalGridDistributionNetworks from .s3 import write_summary_output from .ptypes import ( BalancingTotals, EmbeddedSnapshot, + ForeignMarketSnapshot, + NationalGridGspSnapshot, SummaryOutput, TotalsSnapshot, ) @@ -14,12 +17,22 @@ from .bm import Bm -def combine_totals(gen_totals: List[TotalsSnapshot], fm_totals: TotalsSnapshot): +def combine_totals(gen_totals: List[TotalsSnapshot], fm_totals: ForeignMarketSnapshot): totals = gen_totals + [fm_totals] totals.sort(key=lambda x: x.ac, reverse=True) return totals +def combine_gen_unit_groups( + bm_unit_groups: List[EmbeddedSnapshot], ngdnos: List[NationalGridGspSnapshot] +): + ngdnos = [n for n in ngdnos if n.ac > 0] + combined = bm_unit_groups + ngdnos + # resort by ac, then cp + combined.sort(key=lambda x: x.ac, reverse=True) + return combined + + def gb_snapshot(): request_params = get_request_params() print(f"preparing for {request_params.dt}...") @@ -37,7 +50,16 @@ def gb_snapshot(): fms, fm_totals = ForeignMarketTotals(bm=bm.copy()).run() logging.info(f"combining totals for generators and foreign markets") totals = combine_totals(gen_totals, fm_totals) + logging.info(f"if possible, adding national grid embeddded to totals") + ngdnos = NationalGridDistributionNetworks().run() + if ngdnos is not None: + gen_unit_groups = combine_gen_unit_groups(gen_unit_groups, ngdnos) + else: + logging.info( + f"no national grid distribution networks response returned, skipping..." + ) logging.info(f"writing summary output") + write_summary_output( SummaryOutput( dt=request_params.dt, diff --git a/backend/lambda/gb_snapshot/ng_dist/Readme.md b/backend/lambda/gb_snapshot/ng_dist/Readme.md new file mode 100644 index 0000000..cfd3305 --- /dev/null +++ b/backend/lambda/gb_snapshot/ng_dist/Readme.md @@ -0,0 +1,7 @@ +# National Grid DNO Areas + +Gets latest data from National Grid DNO Areas + +From time to time, the capacity needs to be updated by running the capacity.py module + +If for any reason, the Gb Snapshot is unable to call any of the National Grid Distribution Networks for data, all of them will be excluded from the live data. \ No newline at end of file diff --git a/backend/lambda/gb_snapshot/ng_dist/__init__.py b/backend/lambda/gb_snapshot/ng_dist/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/lambda/gb_snapshot/ng_dist/capacity.py b/backend/lambda/gb_snapshot/ng_dist/capacity.py new file mode 100644 index 0000000..6f6b3a2 --- /dev/null +++ b/backend/lambda/gb_snapshot/ng_dist/capacity.py @@ -0,0 +1,66 @@ +# gets the latest capacity totals for the national grid distribution networks for wind and solar + +import pandas as pd, requests, os + +# write to current module directory +CAPACITY_TOTALS_CSV_FP = os.path.join(os.path.dirname(__file__), "capacity_totals.csv") +BASE_API = "https://connecteddata.nationalgrid.co.uk" +INITIAL_URL = f"{BASE_API}/api/3/action/datastore_search?resource_id=0baf38d3-8f7a-41e5-ad17-8d5785877f8c" + + +CAPACITY_COLUMN = "Connected Maximum Export Capacity (MW)" +TECHNOLOGY_COLUMN = "Energy Source 1" +DNO_REGION_COLUMN = "Licence Area" + +COLUMNS_TO_KEEP = [ + DNO_REGION_COLUMN, + TECHNOLOGY_COLUMN, + CAPACITY_COLUMN, +] + +SIMPLER_COLUMN_NAMES = { + "Connected Maximum Export Capacity (MW)": "cp", + "Energy Source 1": "technology", + "Licence Area": "region", +} + +SOLAR_TECHNOLOGY_NAME = "Solar" +WIND_TECHNOLOGY_NAME = "Wind" + +TECHNOLOGIES_TO_KEEP = [SOLAR_TECHNOLOGY_NAME, WIND_TECHNOLOGY_NAME] + + +def get_capacity_register(): + url = INITIAL_URL + data = [] + complete = False + while not complete: + response = requests.get(url) + response.raise_for_status() + as_dict = response.json() + new_records = as_dict["result"]["records"] + data.extend(new_records) + if len(new_records) > 0: + next_url = as_dict["result"]["_links"]["next"] + url = f"{BASE_API}{next_url}" + print(url) + else: + complete = True + + df = pd.DataFrame(data)[COLUMNS_TO_KEEP] + df = df[df[TECHNOLOGY_COLUMN].isin(TECHNOLOGIES_TO_KEEP)] + df = df.rename(columns=SIMPLER_COLUMN_NAMES) + df["technology"] = df["technology"].str.lower() + + df = df.groupby( + [ + "region", + "technology", + ] + ).sum() + + df.to_csv(CAPACITY_TOTALS_CSV_FP) + + +if __name__ == "__main__": + resp = get_capacity_register() diff --git a/backend/lambda/gb_snapshot/ng_dist/capacity_totals.csv b/backend/lambda/gb_snapshot/ng_dist/capacity_totals.csv new file mode 100644 index 0000000..bae6399 --- /dev/null +++ b/backend/lambda/gb_snapshot/ng_dist/capacity_totals.csv @@ -0,0 +1,9 @@ +region,technology,cp +Western Power Distribution (East Midlands) Plc,solar,1235.0 +Western Power Distribution (East Midlands) Plc,wind,459.0 +Western Power Distribution (South Wales) Plc,solar,607.0 +Western Power Distribution (South Wales) Plc,wind,503.0 +Western Power Distribution (South West) Plc,solar,1139.0 +Western Power Distribution (South West) Plc,wind,242.0 +Western Power Distribution (West Midlands) Plc,solar,491.0 +Western Power Distribution (West Midlands) Plc,wind,38.0 diff --git a/backend/lambda/gb_snapshot/ng_dist/ng_dist.py b/backend/lambda/gb_snapshot/ng_dist/ng_dist.py new file mode 100644 index 0000000..a7a2089 --- /dev/null +++ b/backend/lambda/gb_snapshot/ng_dist/ng_dist.py @@ -0,0 +1,203 @@ +from typing import List, Union +from pydantic import BaseModel, Field +import pandas as pd, requests +from ..ptypes import NationalGridGspSnapshot +from .capacity import CAPACITY_TOTALS_CSV_FP +import logging + + +NATIONAL_GRID_DISTRIBUTION_NETWORKS = [ + { + "id": 11, + "name": "East Midlands", + "coords": { + "solar": { + # leicester + "lat": 52.6369, + "lng": -1.1398, + }, + "wind": { + # skegness + "lat": 53.144, + "lng": 0.336, + }, + }, + "url": "https://connecteddata.nationalgrid.co.uk/dataset/7235194a-884d-47ff-bd03-a0ad38eedcb3/resource/92d3431c-15d7-4aa6-ad34-2335596a026c/download/eastmidlands.csv", + "embedded_capacity_register_name": "Western Power Distribution (East Midlands) Plc", + }, + { + "id": 14, + "name": "West Midlands", + "coords": { + # telford + "solar": { + # telford + "lat": 52.6784, + "lng": -2.4453, + }, + "wind": { + # birmingham + "lat": 52.4862, + "lng": -1.8904, + }, + }, + "url": "https://connecteddata.nationalgrid.co.uk/dataset/7235194a-884d-47ff-bd03-a0ad38eedcb3/resource/1c3447df-37d7-4fb4-9f99-0e2a0d691dbe/download/westmidlands.csv", + "embedded_capacity_register_name": "Western Power Distribution (West Midlands) Plc", + }, + { + "id": 21, + "name": "South Wales", + "coords": { + "solar": { + # cardiff + "lat": 51.4816, + "lng": -3.1791, + }, + "wind": { + # llandovery + "lat": 51.995, + "lng": -3.802, + }, + }, + "url": "https://connecteddata.nationalgrid.co.uk/dataset/7235194a-884d-47ff-bd03-a0ad38eedcb3/resource/38b81427-a2df-42f2-befa-4d6fe9b54c98/download/southwales.csv", + "embedded_capacity_register_name": "Western Power Distribution (South Wales) Plc", + }, + { + "id": 22, + "name": "South West", + "coords": { + "wind": { + # truro + "lat": 50.2632, + "lng": -5.051, + }, + "solar": { + # yeovil + "lat": 50.9421, + "lng": -2.6336, + }, + }, + "url": "https://connecteddata.nationalgrid.co.uk/dataset/7235194a-884d-47ff-bd03-a0ad38eedcb3/resource/85aaa199-15df-40ec-845f-6c61cbedc20f/download/southwest.csv", + "embedded_capacity_register_name": "Western Power Distribution (South West) Plc", + }, +] + + +class InterpolatedValue(BaseModel): + ac: float + dl: float + + +class NationalGridDistributionNetworkResponse(BaseModel): + solar: InterpolatedValue + wind: InterpolatedValue + + +class NationalGridDistributionNetwork(BaseModel): + id: int + name: str + coords: dict + url: str + + def run(self): + logging.debug(f"running NationalGridDistributionNetwork for {self.name}...") + + resp = requests.get(self.url, headers={}) + lines = resp.text.split("\r\n") + columns = lines[0].split(",") + rows = [line.split(",") for line in lines[1:-1]] + data = [] + for row in rows: + data.append(dict(zip(columns, row))) + df = pd.DataFrame(data) + # set Timestamp as index + df.set_index("Timestamp", inplace=True) + # set all columns as floats + df = df.astype(float) + # set Timestamp as UTC + df.index = pd.to_datetime(df.index, utc=True) + # sort index + df.sort_index(inplace=True) + # get latest + most_recent = df.iloc[-1] + # assert latest is less than 10 minutes old + assert (pd.Timestamp.now(tz="UTC") - most_recent.name) < pd.Timedelta( + "10 minutes" + ) + + previous = df.iloc[-2] + + time_diff_minutes = (most_recent.name - previous.name).seconds / 60 + + return NationalGridDistributionNetworkResponse( + solar=InterpolatedValue( + ac=most_recent["Solar"], + dl=(most_recent["Solar"] - previous["Solar"]) / time_diff_minutes, + ), + wind=InterpolatedValue( + ac=most_recent["Wind"], + dl=(most_recent["Wind"] - previous["Wind"]) / time_diff_minutes, + ), + ) + + +class NationalGridDistributionNetworks: + def run(self) -> Union[None, List[NationalGridGspSnapshot]]: + logging.info("running NationalGridDistributionNetworks...") + capacities = self._read_capacity_totals() + try: + results = [] + for network in NATIONAL_GRID_DISTRIBUTION_NETWORKS: + + ngdn = NationalGridDistributionNetwork(**network) + response = ngdn.run() + # add solar and wind + kwargs = { + "bids": 0, + "offers": 0, + } + + results.append( + NationalGridGspSnapshot( + name=network["name"], + code=f'NGDNO-{network["id"]}-solar', + fuel_type="solar", + coords=network["coords"]["solar"], + ac=response.solar.ac, + dl=response.solar.dl, + cp=capacities.loc[ + (network["embedded_capacity_register_name"], "solar") + ]["cp"], + **kwargs, + ) + ) + results.append( + NationalGridGspSnapshot( + name=network["name"], + code=f'NGDNO-{network["id"]}-wind', + fuel_type="wind", + ac=response.wind.ac, + dl=response.wind.dl, + cp=capacities.loc[ + (network["embedded_capacity_register_name"], "wind") + ]["cp"], + coords=network["coords"]["wind"], + **kwargs, + ) + ) + logging.info("NationalGridDistributionNetworks completed.") + return results + + except Exception as e: + print(e) + return None + + def _read_capacity_totals(self): + df = pd.read_csv(CAPACITY_TOTALS_CSV_FP) + df.set_index(["region", "technology"], inplace=True) + return df + + +if __name__ == "__main__": + results = NationalGridDistributionNetworks().run() + print(results) diff --git a/backend/lambda/gb_snapshot/ptypes.py b/backend/lambda/gb_snapshot/ptypes.py index 53c52b1..1ee390e 100644 --- a/backend/lambda/gb_snapshot/ptypes.py +++ b/backend/lambda/gb_snapshot/ptypes.py @@ -84,6 +84,14 @@ class UnitGroupSnapshot(Snapshot): coords: Coords +class SheffieldGspSnapshot(UnitGroupSnapshot): + pass + + +class NationalGridGspSnapshot(UnitGroupSnapshot): + pass + + class TotalsSnapshot(Snapshot): name: str code: FuelType diff --git a/backend/lambda/gb_snapshot/sheffield/__init__.py b/backend/lambda/gb_snapshot/sheffield/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/lambda/gb_snapshot/sheffield/gsp.py b/backend/lambda/gb_snapshot/sheffield/gsp.py new file mode 100644 index 0000000..1d35bad --- /dev/null +++ b/backend/lambda/gb_snapshot/sheffield/gsp.py @@ -0,0 +1,93 @@ +# use the sheffield solar API to get current solar power generation +from time import sleep +import requests, pandas as pd, logging, json, os +from pydantic import BaseModel +from datetime import datetime +from typing import List +from ..ptypes import SheffieldGspSnapshot +from multiprocessing import Pool, cpu_count + + +GSP_CSV_FP = os.path.join(os.path.dirname(__file__), "gsp_points.csv") + + +# class RawGspResponse(BaseModel): +# data: List[List[any]] +# meta: List[str] + + +class SheffieldGspResponse(BaseModel): + settlementPeriod: int + startTime: datetime + mw: float + + +def get_and_retry_with_backoff(url, retries=15): + for i in range(retries): + resp = requests.get(url) + if resp.status_code == 200: + return resp + print(f"Failed to get data from Sheffield Solar API: {resp.text}") + sleep(2**i) + raise Exception(f"Failed to get data from Sheffield Solar API: {resp.text}") + + +class SheffieldGsp(BaseModel): + + gsp_id: int + + def run(self): + url = f"https://api.solar.sheffield.ac.uk/pvlive/api/v4/pes/{self.gsp_id}" + resp = get_and_retry_with_backoff(url) + raw_data = resp.json()["data"] + + if len(raw_data) == 0: + return None + + data = [ + SheffieldGspResponse( + settlementPeriod=settlementPeriod, startTime=startTime, mw=mw + ) + for settlementPeriod, startTime, mw in raw_data + ] + + # print(self.gsp_id, data[0].mw, data[0].startTime, data[0].settlementPeriod) + + return float(data[0].mw) + + +def get_gsp_data(gsp: SheffieldGsp): + """Get the current solar power generation from Sheffield Solar API""" + print(f"Getting data for GSP {gsp.gsp_id}") + return gsp.run() + + +class SheffieldGsps(BaseModel): + """Sheffield GSP data model""" + + dt: datetime + + def run(self) -> List[SheffieldGspSnapshot]: + """Get the current solar power generation from Sheffield Solar API""" + df = self._import_csv_data() + # filter to remove those with null gsp_id + df = df[df["gsp_id"].notnull()] + gsps = [SheffieldGsp(gsp_id=int(gsp_id), dt=self.dt) for gsp_id in df["gsp_id"]] + mw = [get_gsp_data(gsp) for gsp in gsps] + # with Pool(cpu_count()) as p: + # mw = p.map(get_gsp_data, gsps) + df["mw"] = mw + import pdb + + pdb.set_trace() + + def _import_csv_data(self) -> pd.DataFrame: + """Import the Sheffield Solar data from the CSV file""" + return pd.read_csv(GSP_CSV_FP) + + +if __name__ == "__main__": + now = datetime.now().replace(minute=0, second=0, microsecond=0) + dt = now.replace(minute=now.minute + 1) + sg = SheffieldGsps(dt=dt) + sg.run() diff --git a/backend/lambda/gb_snapshot/sheffield/gsp_points.csv b/backend/lambda/gb_snapshot/sheffield/gsp_points.csv new file mode 100644 index 0000000..a8c3b22 --- /dev/null +++ b/backend/lambda/gb_snapshot/sheffield/gsp_points.csv @@ -0,0 +1,381 @@ +ng_id,ggd_id,gnode_id,gnode_name,gnode_lat,gnode_lon,gsp_id,gsp_name,gsp_lat,gsp_lon,dc_id,dc_name,dc_lat,dc_lon,region_id,region_name,has_pv,pes_id,pes_name +1,1,1,COWL,51.71105,-1.18901,1,COWL_1,51.71105,-1.18901,,,,,1,Cowley,1,20,_H +2,2,2,ECLA,51.92579,-0.90565,2,ECLA_1,51.92579,-0.90565,,,,,19,East Claydon,1,11,_B +3,3,3,ENDEDW,52.59726,-1.21548,3,ENDE_1,52.59726,-1.21548,,,,,20,Enderby,1,11,_B +4,4,4,GRENDW,52.24269,-0.72736,4,GREN_1,52.24269,-0.72736,,,,,21,Grendon,1,11,_B +5,5,5,RATS,52.86342,-1.25444,5,RATS_1,52.86342,-1.25444,,,,,22,Ratcliffe,1,11,_B +6,6,6,STAYDW,53.07717,-0.86738,6,STAY_1,53.07717,-0.86738,,,,,23,Staythorpe,1,11,_B +7,7,7,STOB,52.95976,-1.05062,7,SBAR,52.95976,-1.05062,,,,,24,Stoke Bardolph,1,11,_B +8,8,8,WBUR,53.35891,-0.80781,8,WBUR_1,53.35891,-0.80781,,,,,25,West Burton,1,11,_B +9,9,9,BRWA,51.1168,-2.9677,9,BRWA1,51.1168,-2.9677,,,,,58,Bridgewater,1,22,_L +10,10,10,MITY,51.60728,-2.00116,10,MITY_1,51.60728,-2.00116,,,,,2,Minety,1,20,_H +11,11,11,TAUN,51.01643,-3.15387,11,TAUN1,51.01643,-3.15387,,,,,59,Taunton,1,22,_L +12,12,12,CAML,53.729427,-1.000941,12,CAMB_01,53.729427,-1.000941,,,,,161,Camblesforth,1,23,_M +13,13,13,DRAX,53.73598,-0.9908,13,DRAX_1,53.73598,-0.9908,,,,,162,Drax,1,23,_M +14,14,14,GRIW,53.56499,-0.15065,14,GRIW_1,53.56499,-0.15065,,,,,163,Grimsby West,1,23,_M +15,15,15,KEADDW,53.5978,-0.75457,15,KEAD_1,53.5978,-0.75457,,,,,164,Keadby,1,23,_M +16,16,16,OSBA,53.95657,-1.02091,16,OSBA_1,53.95657,-1.02091,,,,,115,Osbaldwick,1,15,_F +17,17,17,BRK1,51.52017,0.113296,17,BARKC1,51.52017,0.113296,,,,,88,Barking,1,12,_C +18,18,18,BRK3,51.52017,0.113296,18,BARKW3,51.52017,0.113296,,,,,88,Barking,1,12,_C +19,19,19,SYD1,51.433113,-0.053455,19,BEDDT1,51.433113,-0.053455,,,,,89,Beddington (_C),1,12,_C +20,20,20,BED1,51.37408,-0.12618,20,BEDD_1,51.37408,-0.12618,,,,,149,Beddington (_J),1,19,_J +21,21,21,BRIMDM,51.66398,-0.0217,21,BRIM_1,51.66398,-0.0217,,,,,68,Brimsdown,1,10,_A +22,22,22,CITR,51.52967,-0.09412,22,CITR_1,51.52967,-0.09412,,,,,90,City Road,1,12,_C +23,23,23,EALI,51.50134,-0.29454,23,EALI_6,51.50134,-0.29454,,,,,3,Ealing,1,20,_H +24,24,24,HCK1,51.55898,-0.04172,24,HACK_1,51.55898,-0.04172,,,,,91,Hackney,1,12,_C +25,25,25,HACK,51.55898,-0.04172,25,HACK_6,51.55898,-0.04172,,,,,91,Hackney,1,12,_C +26,26,26,HURS,51.43215,0.15625,26,HURS_1,51.43215,0.15625,,,,,92,Hurst,1,12,_C +27,27,27,NFLE,51.427952,0.329733,27,NFLE,51.427952,0.329733,,,,,150,Northfleet East,1,19,_J +28,28,28,REBR,51.58803,0.04463,28,REBR_3,51.58803,0.04463,,,,,93,Redbridge,1,12,_C +29,29,29,SJOW,51.527,-0.16795,29,SJOW_1,51.527,-0.16795,,,,,94,St Johns Wood,1,12,_C +30,30,30,TOTT,51.60402,-0.04604,30,TOTT_1,51.60402,-0.04604,,,,,69,Tottenham,1,10,_A +31,31,31,WHAM,51.51908,0.00238,31,WHAM_1,51.51908,0.00238,,,,,95,West Ham,1,12,_C +32,32,32,WISDDM,51.53373,-0.25632,32,WISD_1,51.53373,-0.25632,,,,,96,Willesden 132kV,1,12,_C +33,33,33,WIM1,51.43048,-0.18643,33,WIMBS1,51.43048,-0.18643,,,,,97,Wimbledon,1,12,_C +34,34,34,WIM2,51.43048,-0.18643,34,WIMBN1,51.43048,-0.18643,,,,,97,Wimbledon,1,12,_C +35,35,35,BIRKDW,53.36549,-3.06139,35,BIRK_1,53.36549,-3.06139,,,,,102,Birkenhead,1,13,_D +36,36,36,FIDF,53.37103,-2.68771,36,FIDF_1,53.37103,-2.68771,,,,,103,Fiddlers Ferry,1,13,_D +37,37,37,KIBY,53.46896,-2.84636,37,KIBY_1,53.46896,-2.84636,,,,,104,Kirkby (_D),1,13,_D +38,38,38,KIR1,53.46896,-2.84636,38,KIBY_G,53.46896,-2.84636,,,,,133,Kirkby (_G),1,16,_G +39,39,39,LISDDW,53.41838,-2.9228,39,LISD_1,53.41838,-2.9228,,,,,105,Lister Drive,1,13,_D +40,40,40,PENW,53.74634,-2.75658,40,PENW_1,53.74634,-2.75658,,,,,134,Penwortham,1,16,_G +41,41,41,PENE,53.74634,-2.75658,41,PENE_1,53.74634,-2.75658,,,,,134,Penwortham,1,16,_G +42,42,42,RAIN,53.42095,-2.73746,42,RAIN_1,53.42095,-2.73746,,,,,106,Rainhill,1,13,_D +43,43,43,WASF,53.56236,-2.81818,43,WASF_1,53.56236,-2.81818,,,,,135,Washway Farm,1,16,_G +44,44,44,CHIC,50.62406,-2.48521,44,CHIC_1,50.62406,-2.48521,,,,,4,Chickerell,1,20,_H +45,45,45,FOUR,55.01175,-2.16266,45,FOUR_1,55.01175,-2.16266,,,,,116,Fourstones,1,15,_F +46,46,46,FROD,53.30934,-2.71542,46,FROD_1,53.30934,-2.71542,,,,,107,Frodsham,1,13,_D +47,47,47,IMPP,51.54744,-3.02962,47,IMPK_1,51.54744,-3.02962,,,,,108,Imperial Park,1,13,_D +48,48,48,MAGA,51.56246,-3.75272,48,MAGA_6,51.56246,-3.75272,,,,,49,Margam,1,21,_K +49,49,49,PYLEDW,51.53544,-3.68659,49,PYLE_1,51.53544,-3.68659,,,,,50,Pyle,1,21,_K +50,50,50,SALH,54.60537,-1.23616,50,SALH_1,54.60537,-1.23616,,,,,117,Saltholme,1,15,_F +51,51,51,TEMP,53.41178,-1.38428,51,TEMP_3,53.41178,-1.38428,,,,,165,Templeborough,1,23,_M +52,52,52,TRAW,52.9271,-3.94628,52,TRAW_1,52.9271,-3.94628,,,,,109,Trawsfynydd,1,13,_D +53,53,53,TYN5,55.0236,-1.49902,53,TYNE_2,55.0236,-1.49902,,,,,118,Tynemouth,1,15,_F +54,54,54,BICF,52.93046,-0.21951,54,BICF_1,52.93046,-0.21951,,,,,26,Bicker Fen,1,11,_B +55,55,55,BRAI,51.86442,0.57806,55,BRAI_1,51.86442,0.57806,,,,,70,Braintree,1,10,_A +56,56,56,BURWDW,52.28034,0.3151,56,BURM_1,52.28034,0.3151,,,,,71,Burwell Main,1,10,_A +57,57,57,EASO,52.21422,-0.30001,57,EASO_1,52.21422,-0.30001,,,,,72,Eaton Socon,1,10,_A +58,58,58,IVR1,51.54361,-0.49728,58,IVER_1,51.54361,-0.49728,,,,,5,Iver 132kV,1,20,_H +59,59,59,IVR6,51.54361,-0.49728,59,IVER_6,51.54361,-0.49728,,,,,6,Iver 66kV,1,20,_H +60,60,60,KINO,51.41803,0.60007,60,KINO_1,51.41803,0.60007,,,,,151,Kingsnorth,1,19,_J +61,61,61,LALE,51.42324,-0.46904,61,LALE1SG003,51.42324,-0.46904,,,,,7,Laleham,1,20,_H +62,62,62,LODR,51.528355,-0.170383,62,LODR_6,51.528355,-0.170383,,,,,98,Lodge Road,1,12,_C +63,63,63,MILH,51.61738,-0.20697,63,MILH_1,51.61738,-0.20697,,,,,73,Mill Hill,1,10,_A +64,64,64,NHYDDW,51.49941,-0.40981,64,NHYD_6,51.49941,-0.40981,,,,,8,North Hyde,1,20,_H +65,65,65,PELH,51.93467,0.12036,65,PELH_1,51.93467,0.12036,,,,,74,Pelham,1,10,_A +66,66,66,RAYLDW,51.59355,0.56816,66,RAYL_1,51.59355,0.56816,,,,,75,Rayleigh,1,10,_A +67,67,67,RYEH,51.75854,0.01019,67,RYEH_1,51.75854,0.01019,,,,,76,Rye House,1,10,_A +68,68,68,SUND,51.93586,-0.50142,68,SUND_1,51.93586,-0.50142,,,,,77,Sundon,1,10,_A +69,69,69,WARL,51.55232,0.30304,69,WARL_1,51.55232,0.30304,,,,,78,Warley,1,10,_A +70,70,70,WATS,51.64253,-0.40252,70,WATFS_1,51.64253,-0.40252,,,,,79,Watford South,1,10,_A +71,71,71,WTHU,51.47041,0.28966,71,WTHU31,51.47041,0.28966,,,,,80,West Thurrock,1,10,_A +72,72,72,WWEY,51.35286,-0.47801,72,WWEY_1,51.35286,-0.47801,,,,,152,West Weybridge,1,19,_J +73,73,73,WYMODW,51.92672,-0.24865,73,WYMOM_1,51.92672,-0.24865,,,,,81,Wymondley,1,10,_A +74,74,74,BRED,53.41428,-2.12746,74,BRED_1,53.41428,-2.12746,,,,,136,Bredbury,1,16,_G +75,75,75,KER1,53.53738,-2.35604,75,KEAR_1,53.53738,-2.35604,,,,,137,Kearsley,1,16,_G +76,76,76,KER3,53.53738,-2.35604,76,KEAR_3,53.53738,-2.35604,,,,,137,Kearsley,1,16,_G +77,77,77,MACC,53.26843,-2.12,77,MACC_3,53.26843,-2.12,,,,,138,Macclesfield,1,16,_G +78,78,78,SMAN,53.42002,-2.27484,78,SMAN_1,53.42002,-2.27484,,,,,139,South Manchester,1,16,_G +79,79,79,STAL,53.4934,-2.03978,79,STAL_1,53.4934,-2.03978,,,,,140,Stalybridge,1,16,_G +80,80,80,WHGA,53.52853,-2.16577,80,WHGA_1,53.52853,-2.16577,,,,,141,Whitegate,1,16,_G +81,81,81,BLY6,55.14106,-1.53101,81,BLYTB1,55.14106,-1.53101,,,,,129,Blyth 66kV,1,15,_F +82,82,82,HARM,54.70038,-1.29041,82,HARM_6,54.70038,-1.29041,,,,,119,Hart Moor,1,15,_F +83,83,83,HAWPDW,54.80525,-1.40147,83,HAWP_6,54.80525,-1.40147,,,,,120,Hawthorn Pit,1,15,_F +84,84,84,LACK,54.56683,-1.1301,84,LACK_6,54.56683,-1.1301,,,,,121,Lackenby,1,15,_F +85,85,85,NORTDW,54.5927,-1.36566,85,NORT_1,54.5927,-1.36566,,,,,122,Norton,1,15,_F +86,86,86,OFFE,54.88069,-1.45638,86,OFFE_3,54.88069,-1.45638,,,,,123,Offerton,1,15,_F +87,87,87,SSHIDW,54.9733,-1.44787,87,SSHI_3,54.9733,-1.44787,,,,,124,South Shields,1,15,_F +88,88,88,SPENDW,54.70514,-1.55123,88,SPEN_1,54.70514,-1.55123,,,,,125,Spennymoor,1,15,_F +89,89,89,TYN1,55.0236,-1.49902,89,TYNE_1,55.0236,-1.49902,,,,,118,Tynemouth,1,15,_F +90,90,90,WBOL,54.94002,-1.46879,90,WBOL_6,54.94002,-1.46879,,,,,126,West Boldon,1,15,_F +91,91,91,HUTTDM,54.29736,-2.66949,91,HUTT_1,54.29736,-2.66949,,,,,142,Hutton,1,16,_G +92,92,92,PADIDW,53.79514,-2.31962,92,PADIB1,53.79514,-2.31962,,,,,143,Padiham,1,16,_G +93,93,93,ROCH,53.6217,-2.21535,93,ROCH_1,53.6217,-2.21535,,,,,144,Rochdale,1,16,_G +94,94,94,CELL,53.04058,-2.08115,94,CELL_1,53.04058,-2.08115,,,,,33,Cellarhead,1,14,_E +95,95,95,LEGADW,53.02823,-3.05246,95,LEGA_1,53.02823,-3.05246,,,,,110,Legacy,1,13,_D +96,96,96,PENT,53.1873,-4.15676,96,PENT_1,53.1873,-4.15676,,,,,111,Pentir,1,13,_D +97,97,97,BOLNDM,50.97466,-0.2335,97,BOLN_1,50.97466,-0.2335,,,,,153,Bolney,1,19,_J +98,98,98,BOTW,50.88393,-1.23059,98,BOTW_1,50.88393,-1.23059,,,,,9,Botley Wood,1,20,_H +99,99,99,FAWLDM,50.82116,-1.32711,99,FAWL_1,50.82116,-1.32711,,,,,10,Fawley,1,20,_H +100,100,100,FLEEDW,51.25075,-0.88184,100,FLEE_1,51.25075,-0.88184,,,,,11,Fleet,1,20,_H +101,101,101,LOVE,50.91681,-1.03854,101,LOVE_1,50.91681,-1.03854,,,,,12,Lovedean,1,20,_H +102,102,102,NINFDW,50.88089,0.44941,102,NINF_1,50.88089,0.44941,,,,,154,Ninfield,1,19,_J +103,103,103,NURS,50.94195,-1.48521,103,NURS_1,50.94195,-1.48521,,,,,13,Nursling,1,20,_H +104,104,104,ABTHDM,51.38785,-3.40198,104,ABTH_1,51.38785,-3.40198,,,,,51,Aberthaw,1,21,_K +105,105,105,CARE,51.49432,-3.14415,105,CARE_1,51.49432,-3.14415,,,,,52,Cardiff East,1,21,_K +106,106,106,IROADW,51.56933,-2.47937,106,IROA1,51.56933,-2.47937,,,,,60,Iron Acton,1,22,_L +107,107,107,PEMB,51.68165,-4.98939,107,PEMB_1,51.68165,-4.98939,,,,,53,Pembroke,1,21,_K +108,108,108,RASSDW,51.80789,-3.2254,108,RASS_1,51.80789,-3.2254,,,,,54,Rassau,1,21,_K +109,109,109,SEAB,51.53663,-2.66869,109,SEAB1,51.53663,-2.66869,,,,,61,Seabank,1,22,_L +110,110,110,SWANDW,51.68897,-3.95558,110,SWAN_1,51.68897,-3.95558,,,,,55,Swansea North,1,21,_K +111,111,111,UPP1,51.57359,-3.29916,111,UPPB_1,51.57359,-3.29916,,,,,56,Upper Boat,1,21,_K +112,112,112,UPP3,51.57359,-3.29916,112,UPPB_3,51.57359,-3.29916,,,,,56,Upper Boat,1,21,_K +113,113,113,USKMDW,51.54663,-2.97729,113,USKM_1,51.54663,-2.97729,,,,,57,Uskmouth,1,21,_K +114,114,114,USK3,51.54663,-2.97729,114,ALST_3,51.54663,-2.97729,,,,,57,Uskmouth,1,21,_K +115,115,115,WALH,51.87874,-2.25251,115,WALH_1,51.87874,-2.25251,,,,,34,Walham,1,14,_E +116,116,116,ABHA,50.47108,-3.72977,116,ABHA1,50.47108,-3.72977,,,,,62,Abham,1,22,_L +117,117,117,ALVE,51.00538,-4.13534,117,ALVE1,51.00538,-4.13534,,,,,63,Alverdiscott,1,22,_L +118,118,118,AXMI,50.78594,-2.92337,118,AXMI1,50.78594,-2.92337,,,,,64,Axminster,1,22,_L +119,119,119,EXET,50.76702,-3.40398,119,EXET1,50.76702,-3.40398,,,,,65,Exeter,1,22,_L +120,120,120,INDQ,50.39439,-4.89788,120,INDQ1,50.39439,-4.89788,,,,,66,Indian Queens,1,22,_L +121,121,121,LAND,50.44447,-4.24153,121,LAND1,50.44447,-4.24153,,,,,67,Landulph,1,22,_L +122,122,122,MANN,50.84632,-1.89465,122,MANN_1,50.84632,-1.89465,,,,,14,Mannington,1,20,_H +123,123,123,CHTE,53.22425,-1.38736,123,CHTE_1,53.22425,-1.38736,,,,,27,Chesterfield,1,11,_B +124,124,124,JORD,53.32921,-1.4565,124,JORD_3,53.32921,-1.4565,,,,,166,Jordanthorpe,1,23,_M +125,125,125,NEEP,53.40642,-1.48696,125,NEEP_3,53.40642,-1.48696,,,,,167,Neepsend,1,23,_M +126,126,126,NORL,53.34823,-1.46998,126,NORL_3,53.34823,-1.46998,,,,,168,Norton Lees,1,23,_M +127,127,127,SHEC,53.37445,-1.47708,127,SHEC_3,53.37445,-1.47708,,,,,169,Sheffield City,1,23,_M +128,128,128,THOM,53.57845,-1.08549,128,THOM_6,53.57845,-1.08549,,,,,170,Thorpe Marsh,1,23,_M +129,129,129,THURDW,53.40464,-1.26697,129,THUR_6,53.40464,-1.26697,,,,,171,Thurcroft,1,23,_M +130,130,130,WMEL,53.50118,-1.37543,130,WMEL_1,53.50118,-1.37543,,,,,172,West Melton,1,23,_M +131,131,131,WIBA,53.41559,-1.41236,131,WIBA_3,53.41559,-1.41236,,,,,173,Wincobank,1,23,_M +132,132,132,BESW,52.38546,-1.61401,132,BESW_1,52.38546,-1.61401,,,,,28,Berkswell,1,11,_B +133,133,133,BISW,52.31172,-2.24028,133,BISW_1,52.31172,-2.24028,,,,,35,Bishops Wood,1,14,_E +134,134,134,BUSH,52.63662,-2.11432,134,BUSH_1,52.63662,-2.11432,,,,,36,Bushbury,1,14,_E +135,135,135,BUST,52.5529,-1.95942,135,BUST_1,52.5529,-1.95942,,,,,37,Bustleholme,1,14,_E +136,136,136,COVE,52.45608,-1.46225,136,COVE_1,52.45608,-1.46225,,,,,29,Coventry,1,11,_B +137,137,137,DRAK,52.77345,-1.65155,137,DRAK_1,52.77345,-1.65155,,,,,30,Drakelow,1,11,_B +138,138,138,FECKDM,52.2519,-1.97238,138,FECK_6,52.2519,-1.97238,,,,,38,Feckenham,1,14,_E +139,139,139,IRON,52.63163,-2.5129,139,IRONB1,52.63163,-2.5129,,,,,39,Ironbridge,1,14,_E +140,140,140,KITW,52.4304,-2.01243,140,KITW_1,52.4304,-2.01243,,,,,40,Kitwell,1,14,_E +141,141,141,LEMR,52.528656,-1.708746,141,HAMHC1,52.528656,-1.708746,,,,,41,Hams Hall,1,14,_E +142,142,142,OCKH,52.54155,-2.02821,142,OCKH_1,52.54155,-2.02821,,,,,42,Ocker Hill,1,14,_E +143,143,143,OLDB,52.49906,-2.0216,143,OLDB_1,52.49906,-2.0216,,,,,43,Oldbury,1,14,_E +144,144,144,PENN,52.55656,-2.20838,144,PENN_1,52.55656,-2.20838,,,,,44,Penn,1,14,_E +145,145,145,RUGE,52.75633,-1.91351,145,RUGEB1,52.75633,-1.91351,,,,,45,Rugeley,1,14,_E +146,146,146,SHREDW,52.70869,-2.69141,146,SHRW_1,52.70869,-2.69141,,,,,46,Shrewsbury,1,14,_E +147,147,147,WIEN,52.57746,-2.04808,147,WIEN_1,52.57746,-2.04808,,,,,47,Willenhall,1,14,_E +148,148,148,WILLDM,52.85506,-1.54523,148,WILL_1,52.85506,-1.54523,,,,,31,Willington,1,11,_B +149,149,149,BRAWDW,53.81028,-1.86383,149,BRAW_1,53.81028,-1.86383,,,,,174,Bradford West,1,23,_M +150,150,150,ELLA,53.69365,-1.82222,150,ELLA_1,53.69365,-1.82222,,,,,175,Elland,1,23,_M +151,151,151,FERB,53.71912,-1.2702,151,FERRB1,53.71912,-1.2702,,,,,127,Ferrybridge (_F),1,15,_F +152,152,152,FERA,53.71912,-1.2702,152,FERRA2,53.71912,-1.2702,,,,,176,Ferrybridge (_M),1,23,_M +153,153,153,KIRKDW,53.80602,-1.59652,153,KIRKB1,53.80602,-1.59652,,,,,177,Kirkstall,1,23,_M +154,154,154,POPP,53.97485,-1.13005,154,POPP_3,53.97485,-1.13005,,,,,128,Poppleton,1,15,_F +155,155,155,SKLG,53.77667,-1.49531,155,SKLGB1,53.77667,-1.49531,,,,,178,Skelton Grange,1,23,_M +156,156,156,COUADW,56.53827,-3.27319,156,COUA_P,56.53827,-3.27319,,,,,262,Coupar Angus,1,17,_P +157,157,157,MACDDW,57.664,-2.49946,157,MACD_P,57.664,-2.49946,,,,,263,Macduff,1,17,_P +158,158,158,MYBSDW,58.44655,-3.42537,158,MYBS_P,58.44655,-3.42537,,,,,264,Mybster,1,17,_P +159,159,159,STIRDW,56.11777,-3.91906,159,STIR,56.11777,-3.91906,,,,,183,Stirling,1,18,_N +160,160,160,THSODW,58.57492,-3.51141,160,THSO_P,58.57492,-3.51141,,,,,265,Thurso,1,17,_P +161,161,161,ABNEDW,56.33949,-3.29406,161,ABNE_P,56.33949,-3.29406,,,,,266,Abernethy,1,17,_P +162,162,162,ALNEDM,57.70741,-4.2757,162,ALNE_P,57.70741,-4.2757,,,,,267,Alness,1,17,_P +163,163,163,ARBRDW,56.56393,-2.61666,163,ARBR_P,56.56393,-2.61666,,,,,268,Arbroath,1,17,_P +164,164,164,ARMODW,57.554486,-6.645033,164,ARMO_P,57.554486,-6.645033,,,,,269,Ardmore,1,17,_P +165,165,165,AYRR,55.45746,-4.58795,165,AYRR,55.45746,-4.58795,,,,,182,Ayr,1,18,_N +166,166,166,BAIN,56.01379,-3.76841,166,BAIN,56.01379,-3.76841,,,,,184,Bainsford,1,18,_N +167,167,167,BAGA,55.89992,-3.67308,167,BAGA,55.89992,-3.67308,,,,,185,Bathgate,1,18,_N +168,168,168,BEAUDM,57.46882,-4.49099,168,BEAU_P,57.46882,-4.49099,,,,,270,Beauly,1,17,_P +169,169,169,BERW,55.77749,-2.07909,169,BERW,55.77749,-2.07909,,,,,186,Berwick,1,18,_N +170,170,170,BOAG,57.25332,-3.73205,170,BOAG_P,57.25332,-3.73205,,,,,271,Boat of Garten,1,17,_P +171,171,171,BONNDW,56.00791,-3.86196,171,BONN,56.00791,-3.86196,,,,,187,Bonnybridge,1,18,_N +172,172,172,BRACDM,56.2763,-3.87822,172,BRAC_P,56.2763,-3.87822,,,,,272,Braco West,1,17,_P +173,173,173,BRAP,55.8807,-4.38052,173,BRAP,55.8807,-4.38052,,,,,188,Braehead Park,1,18,_N +174,174,174,BRIDDM,56.72143,-2.55715,174,BRID_P,56.72143,-2.55715,,,,,273,Bridge of Dun,1,17,_P +175,175,175,BROA,57.24859,-5.93372,175,BROA_P,57.24859,-5.93372,,,,,274,Broadford,1,17,_P +176,176,176,BROR,58.02032,-3.87564,176,BROR_P,58.02032,-3.87564,,,,,275,Brora,1,17,_P +177,177,177,BROX,55.91953,-3.45348,177,BROX,55.91953,-3.45348,,,,,189,Broxburn,1,18,_N +178,178,178,BUMUDW,56.39663,-3.48718,178,BUMU_P,56.39663,-3.48718,,,,,276,Burghmuir,1,17,_P +179,179,179,CATY,55.85784,-4.19723,179,CATY,55.85784,-4.19723,,,,,190,Carntyne,1,18,_N +180,180,180,CAADDW,55.59091,-5.50244,180,CAAD_P,55.59091,-5.50244,,,,,277,Carradale,1,17,_P +181,181,181,WISHDW,55.76492,-3.92982,181,WISH,55.76492,-3.92982,,,,,191,Wishaw,1,18,_N +182,182,182,CASSDM,58.18731,-4.72825,182,CASS_P,58.18731,-4.72825,,,,,278,Cassley,1,17,_P +183,183,183,CEAN,57.154185,-4.937112,183,CEAN_P,57.154185,-4.937112,,,,,279,Ceannacroc,1,17,_P +184,184,184,CHAPDW,55.01653,-3.22937,184,CHAP,55.01653,-3.22937,,,,,192,Chapelcross,1,18,_N +185,185,185,CHARDW,56.47393,-3.04376,185,CHAR_P,56.47393,-3.04376,,,,,280,Charleston,1,17,_P +186,186,186,CHAS,55.85519,-4.23988,186,CHAS,55.85519,-4.23988,,,,,193,Charlotte Street,1,18,_N +187,187,187,CLAY,57.14036,-2.09912,187,CLAY_P,57.14036,-2.09912,,,,,281,Clayhills,1,17,_P +188,188,188,CLYM,55.82502,-4.15302,188,CLYM,55.82502,-4.15302,,,,,194,Clyde’s Mill,1,18,_N +189,189,189,COCK,55.96733,-2.9674,189,COCK,55.96733,-2.9674,,,,,195,Cockenzie,1,18,_N +190,190,190,COYLDW,55.44719,-4.43078,190,COYL,55.44719,-4.43078,,,,,196,Coylton,1,18,_N +191,191,191,CRAI,57.13132,-2.15361,191,CRAI_P,57.13132,-2.15361,,,,,282,Craigiebuckler,1,17,_P +192,192,192,CUMBDW,55.94687,-3.96418,192,CUMB,55.94687,-3.96418,,,,,197,Cumbernauld,1,18,_N +193,193,193,CUPA,56.31469,-3.03492,193,CUPA,56.31469,-3.03492,,,,,198,Cupar,1,18,_N +194,194,194,CURR,55.90112,-3.30901,194,CURR,55.90112,-3.30901,,,,,199,Currie,1,18,_N +195,195,195,DEVM,55.91631,-4.71011,195,DEVM,55.91631,-4.71011,,,,,200,Devol Moor,1,18,_N +196,196,196,DEVODW,56.13696,-3.78,196,DEVO,56.13696,-3.78,,,,,201,Devonside,1,18,_N +197,197,197,DEWP,55.94704,-3.2101,197,DEWP,55.94704,-3.2101,,,,,202,Dewar Place,1,18,_N +198,198,198,DOUNDM,58.57592179,-3.753501664,198,DOUN_P,58.57592179,-3.753501664,,,,,283,Dounreay,1,17,_P +199,199,199,DRUM,55.91525,-4.34927,199,DRUM,55.91525,-4.34927,,,,,203,Drumchapel,1,18,_N +200,200,200,DRCR,55.90659,-3.58727,200,DRCR,55.90659,-3.58727,,,,,204,Drumcross,1,18,_N +201,201,201,DUDH,56.46279,-2.97692,201,DUDH_P,56.46279,-2.97692,,,,,284,Dudhope,1,17,_P +202,202,202,DUNBDM,55.97735,-2.5738,202,DUNB,55.97735,-2.5738,,,,,205,Dunbar,1,18,_N +203,203,203,DUBEDM,58.2659,-3.43515,203,DUBE_P,58.2659,-3.43515,,,,,285,Dunbeath,0,17,_P +204,204,204,DUNF,56.08958,-3.44925,204,DUNF,56.08958,-3.44925,,,,,206,Dunfermline,1,18,_N +205,205,205,DUNODM,55.97589,-4.94718,205,DUNO_P,55.97589,-4.94718,,,,,286,Dunoon,1,17,_P +206,206,206,DUGRDM,57.432716,-6.539629,206,DUGR_P,57.432716,-6.539629,,,,,287,Dunvegan,1,17,_P +207,207,207,DYCEDW,57.21571,-2.19039,207,DYCE_P,57.21571,-2.19039,,,,,288,Dyce,1,17,_P +208,208,208,EKILDW,55.78534,-4.1933,208,EKIL,55.78534,-4.1933,,,,,207,East Kilbride,1,18,_N +209,209,209,EKISDW,55.74056,-4.16324,209,EKIS,55.74056,-4.16324,,,,,208,East Kilbride South,1,18,_N +210,210,210,EERH,55.87962,-4.07549,210,EERH,55.87962,-4.07549,,,,,209,Easterhouse,1,18,_N +211,211,211,ECCLDW,55.66835,-2.32746,211,ECCL,55.66835,-2.32746,,,,,210,Eccles,1,18,_N +212,212,212,ELDE,55.84061,-4.4649,212,ELDE,55.84061,-4.4649,,,,,211,Elderslie,1,18,_N +213,213,213,ELGIDW,57.66528,-3.32082,213,ELGI_P,57.66528,-3.32082,,,,,289,Elgin,1,17,_P +214,214,214,ERSKDW,55.90378,-4.46038,214,ERSK,55.90378,-4.46038,,,,,212,Erskine,1,18,_N +215,215,215,FASN,57.32867,-4.78887,215,FASN_P,57.32867,-4.78887,,,,,290,Fasnakyle,1,17,_P +216,216,216,FIDDDW,56.92444,-2.30061,216,FIDD_P,56.92444,-2.30061,,,,,291,Fiddes,1,17,_P +217,217,217,FRAS,57.68654,-2.02347,217,FRAS_P,57.68654,-2.02347,,,,,292,Fraserburgh,1,17,_P +218,218,218,FAUG,57.13696,-4.71988,218,FAUG_P,57.13696,-4.71988,,,,,293,Fort Augustus,1,17,_P +219,219,219,FWIL,56.82035,-5.07878,219,FWIL_P,56.82035,-5.07878,,,,,294,Fort William,1,17,_P +220,220,220,GALADW,55.61037,-2.77145,220,GALA,55.61037,-2.77145,,,,,213,Galashiels,1,18,_N +221,221,221,GIFFDW,55.79869,-4.29982,221,GIFF,55.79869,-4.29982,,,,,214,Giffnock,1,18,_N +222,222,222,GLAG,56.481073,-3.017255,222,GLAG_P,56.481073,-3.017255,,,,,295,Glenagnes,0,17,_P +223,223,223,GLNIDW,56.11106,-3.27111,223,GLNI,56.11106,-3.27111,,,,,215,Glenniston,1,18,_N +224,224,224,GLLUDW,54.88189,-4.80802,224,GLLU,54.88189,-4.80802,,,,,216,Glenluce,1,18,_N +225,225,225,GLRO,56.20701,-3.20078,225,GLRO,56.20701,-3.20078,,,,,217,Glenrothes,1,18,_N +226,226,226,GORG,55.93637,-3.23676,226,GORG,55.93637,-3.23676,,,,,218,Gorgie,1,18,_N +227,227,227,GOVA,55.8551,-4.31621,227,GOVA,55.8551,-4.31621,,,,,219,Govan,1,18,_N +228,228,228,GRUBDM,57.6198,-4.83126,228,GRUB_P,57.6198,-4.83126,,,,,296,Grudie Bridge,1,17,_P +229,229,229,HAGR,55.82997,-4.29678,229,HAGR,55.82997,-4.29678,,,,,220,Haggs Road,1,18,_N +230,230,230,HAWI,55.43296,-2.80204,230,HAWI,55.43296,-2.80204,,,,,221,Hawick,1,18,_N +231,231,231,HELE,56.02378,-4.70904,231,HELE,56.02378,-4.70904,,,,,222,Helensburgh,1,18,_N +232,232,232,HUNF,55.72213,-4.88846,232,HUER,55.72213,-4.88846,,,,,223,Hunterston Farm,1,18,_N +233,233,233,INKE,56.04232,-3.39001,233,INKE,56.04232,-3.39001,,,,,224,Inverkeithing,1,18,_N +234,234,234,INNEDM,57.45202908,-4.241401893,234,INNE_P,57.45202908,-4.241401893,,,,,297,Inverness,1,17,_P +235,235,235,JOHN,55.845,-4.50591,235,JOHN,55.845,-4.50591,,,,,225,Johnstone,1,18,_N +236,236,236,KAIMDW,55.89156,-3.16337,236,KAIM,55.89156,-3.16337,,,,,226,Kaimes,1,18,_N +237,237,237,KEITDW,57.54023,-2.93876,237,KEIT_P,57.54023,-2.93876,,,,,298,Keith,1,17,_P +238,238,238,KIINDM,56.47715,-4.32819,238,KIIN_P,56.47715,-4.32819,,,,,299,Killin,1,17,_P +239,239,239,KIER,55.9035,-4.30908,239,KIER,55.9035,-4.30908,,,,,227,Killermont,1,18,_N +240,240,240,KILS,55.575958,-4.436878,240,KILS,55.575958,-4.436878,,,,,228,Kilmarnock South,1,18,_N +241,241,241,KILT,55.59783,-4.49547,241,KILT,55.59783,-4.49547,,,,,229,Kilmarnock Town,1,18,_N +242,242,242,KILWDM,55.66523,-4.68013,242,KILW,55.66523,-4.68013,,,,,230,Kilwinning,1,18,_N +243,243,243,KILODM,56.71451,-4.95423,243,KINL_P,56.71451,-4.95423,,,,,300,Kinlochleven,1,17,_P +244,244,244,KINTDW,57.21887,-2.38083,244,KINT_P,57.21887,-2.38083,,,,,301,Kintore,1,17,_P +245,245,245,LAIRDW,58.02921,-4.41468,245,LAIR_P,58.02921,-4.41468,,,,,302,Lairg,1,17,_P +246,246,246,LEVEDW,56.19874,-3.03869,246,LEVE,56.19874,-3.03869,,,,,231,Leven,1,18,_N +247,247,247,LINMDW,55.67157,-3.82656,247,LINM,55.67157,-3.82656,,,,,232,Linnmill,1,18,_N +248,248,248,LINGDW,55.88266,-3.49274,248,LING,55.88266,-3.49274,,,,,233,Livingston East,1,18,_N +249,249,249,LUNA,56.65499,-2.86444,249,LUNA_P,56.65499,-2.86444,,,,,303,Lunanhead,1,17,_P +250,250,250,LYND,56.48132,-3.01961,250,LYND_P,56.48132,-3.01961,,,,,304,Lyndhurst,1,17,_P +251,251,251,MAYBDM,55.33702251,-4.677001696,251,MAYB,55.33702251,-4.677001696,,,,,234,Maybole,1,18,_N +252,252,252,MILCDW,56.47486,-2.9269,252,MILC_P,56.47486,-2.9269,,,,,305,Milton of Craigie,1,17,_P +253,253,253,NAIR,57.57694,-3.84607,253,NAIR_P,57.57694,-3.84607,,,,,306,Nairn,1,17,_P +254,254,254,NEAR,55.8248,-3.94613,254,NEAR,55.8248,-3.94613,,,,,235,Newarthill,1,18,_N +255,255,255,NETSDM,54.9484212,-4.491001462,255,NETS,54.9484212,-4.491001462,,,,,236,Newton Stewart,1,18,_N +256,256,256,PAIS,55.84013,-4.41366,256,PAIS,55.84013,-4.41366,,,,,237,Paisley,1,18,_N +257,257,257,PART,55.87028,-4.31639,257,PART,55.87028,-4.31639,,,,,238,Partick,1,18,_N +258,258,258,PEHS,57.473556,-1.799532,258,PEHS_P,57.473556,-1.799532,,,,,307,Peterhead Shell,1,17,_P +259,259,259,PERS,57.17446,-2.13725,259,PERS_P,57.17446,-2.13725,,,,,308,Persley,1,17,_P +260,260,260,PEHGDW,57.50944,-1.80472,260,PEHG_P,57.50944,-1.80472,,,,,309,Peterhead Grange,1,17,_P +261,261,261,PORADW,56.02837,-5.35575,261,PORA_P,56.02837,-5.35575,,,,,310,Port Ann,1,17,_P +262,262,262,PORD,55.87342,-4.2542,262,PORD,55.87342,-4.2542,,,,,239,Port Dundas,1,18,_N +263,263,263,POOBDW,55.95296,-3.12399,263,POOB,55.95296,-3.12399,,,,,240,Portobello,1,18,_N +264,264,264,RANNDM,56.69217,-4.41004,264,RANN_P,56.69217,-4.41004,,,,,311,Rannoch,1,17,_P +265,265,265,RAVE,56.145533,-3.145308,265,RAVE,56.145533,-3.145308,,,,,241,Ravenscraig,1,18,_N +266,266,266,REDHDW,56.14562,-3.14501,266,REDH,56.14562,-3.14501,,,,,242,Redhouse,1,18,_N +267,267,267,REDM,57.10803,-2.09243,267,REDM_P,57.10803,-2.09243,,,,,312,Redmoss,1,17,_P +268,268,268,SHINDW,57.94389,-4.41232,268,SHIN_P,57.94389,-4.41232,,,,,313,Shin,1,17,_P +269,269,269,SHRU,55.96433,-3.18531,269,SHRU,55.96433,-3.18531,,,,,243,Shrubhill,1,18,_N +270,270,270,SIGH,55.92867,-3.3046,270,SIGH,55.92867,-3.3046,,,,,244,Sighthill,1,18,_N +271,271,271,SLOY,56.24514,-4.73054,271,SLOY_P,56.24514,-4.73054,,,,,314,Sloy,1,17,_P +272,272,272,SPAV,55.93664,-4.81425,272,SPAV,55.93664,-4.81425,,,,,245,Spango Valley,1,18,_N +273,273,273,SFEG,57.57418,-1.84951,273,SFEG_P,57.57418,-1.84951,,,,,315,St Fergus Gas Terminal,1,17,_P +274,274,274,SFILDM,56.3946,-4.1206,274,SFIL_P,56.3946,-4.1206,,,,,316,St Fillans,1,17,_P +275,275,275,SANX,55.84403,-4.26053,275,SANX,55.84403,-4.26053,,,,,246,St Andrews Cross,1,18,_N +276,276,276,STHA,55.75309,-4.08078,276,STHA,55.75309,-4.08078,,,,,247,Strathaven,1,18,_N +277,277,277,STLE,55.96095,-4.56202,277,STLE,55.96095,-4.56202,,,,,248,Strathleven,1,18,_N +278,278,278,STRIDW,57.58682,-2.07023,278,STRI_P,57.58682,-2.07023,,,,,317,Strichen,1,17,_P +279,279,279,TARL,57.1514,-2.78839,279,TARL_P,57.1514,-2.78839,,,,,318,Tarland,1,17,_P +280,280,280,TAYNDW,56.43039,-5.21426,280,TAYN_P,56.43039,-5.21426,,,,,319,Taynuilt,1,17,_P +281,281,281,TELR,55.96161,-3.24337,281,TELR,55.96161,-3.24337,,,,,249,Telford Road,1,18,_N +282,282,282,TONGDM,54.85974,-4.03475,282,TONG,54.85974,-4.03475,,,,,250,Tongland,1,18,_N +283,283,283,TUMBDM,56.70624,-4.02375,283,TUMB_P,56.70624,-4.02375,,,,,320,Tummel Bridge,1,17,_P +284,284,284,WGEO,55.863,-4.2651,284,WGEO,55.863,-4.2651,,,,,251,West George Street,1,18,_N +285,285,285,WFIEDM,56.16384,-3.29876,285,WFIE,56.16384,-3.29876,,,,,252,Westfield,1,18,_N +286,286,286,WHHO,55.93129,-3.20176,286,WHHO,55.93129,-3.20176,,,,,253,Whitehouse,1,18,_N +287,287,287,WIOW,57.15384,-2.09751,287,WIOW_P,57.15384,-2.09751,,,,,321,Willowdale,1,17,_P +288,288,288,WOHI,57.15379,-2.14709,288,WOHI_P,57.15379,-2.14709,,,,,322,Woodhill,1,17,_P +289,289,289,DEESDM,53.23034,-3.07617,,,,,,,,,,,0,, +290,290,290,CASK,53.3421,2.7297,,,,,1,T_CASKD-1,53.3421,2.7297,,,0,, +291,291,291,CORR,54.606477,-1.116691,,,,,2,T_TODSD-1,54.606477,-1.116691,,,0,, +292,292,292,CULJ,51.6607,-1.22683,,,,,3,T__HYELT002,51.6607,-1.22683,,,0,, +293,293,293,GRTO,54.581721,-1.149598,,,,,4,M_GRTO,54.581721,-1.149598,,,0,, +294,294,294,TREM,51.48146,-3.12898,,,,,5,T__KYELT003,51.48146,-3.12898,,,0,, +295,295,295,WHSO,51.56488,-2.90742,,,,,6,T_LLWSD-1,51.56488,-2.90742,,,0,, +296,296,296,WILT,54.575826,-1.131708,,,,,7,T_WILCT-1,54.575826,-1.131708,,,0,, +297,297,297,MEAD,55.58377,-4.63817,,,,,8,T_MEADD-1,55.58377,-4.63817,,,0,, +298,298,298,MOSW,56.1055997,-3.293114,,,,,9,T_EXMOSSD-1,56.1055997,-3.293114,,,0,, +299,299,299,SFEM,57.57418,-1.84951,,,,,10,T_STFERGD-1,57.57418,-1.84951,,,0,, +300,300,300,WHTL,56.08972,-4.84166,,,,,11,T_WHISTLD-1,56.08972,-4.84166,,,0,, +301,301,301,BRL3,51.33557,-1.07584,289,BRLE_1,51.33557,-1.07584,,,,,15,Bramley,1,20,_H +302,302,302,BRL1,51.33557,-1.07584,289,BRLE_1,51.33557,-1.07584,,,,,15,Bramley,1,20,_H +303,303,303,BRL2,51.33557,-1.07584,289,BRLE_1,51.33557,-1.07584,,,,,15,Bramley,1,20,_H +304,304,304,NEW1,51.48412,-0.05792,290,NEWX_6,51.48412,-0.05792,,,,,99,New Cross,1,12,_C +305,305,305,NEWX,51.48412,-0.05792,290,NEWX_6,51.48412,-0.05792,,,,,99,New Cross,1,12,_C +306,306,306,CAPE,53.2685,-2.94786,291,CAPEA1,53.2685,-2.94786,,,,,112,Capenhurst,1,13,_D +307,307,307,INCE,53.277739,-2.811139,291,CAPEA1,53.2685,-2.94786,,,,,112,Capenhurst,1,13,_D +308,308,308,BLY1DM,55.14106,-1.53101,292,BLYTH132,55.14106,-1.53101,,,,,325,Blyth 132kV,1,15,_F +309,309,309,LINT,55.228725,-1.604966,292,BLYTH132,55.14106,-1.53101,,,,,325,Blyth 132kV,0,15,_F +310,310,310,PIT1,53.40046,-1.44215,293,PITS_3,53.40046,-1.44215,,,,,179,Pitsmoor,1,23,_M +311,311,311,PIT2,53.40046,-1.44215,293,PITS_3,53.40046,-1.44215,,,,,179,Pitsmoor,1,23,_M +312,312,312,SEL1,51.10592,0.97783,294,SELL_1,51.10592,0.97783,,,,,155,Sellindge,1,19,_J +313,313,313,SEL2,51.10592,0.97783,294,SELL_1,51.10592,0.97783,,,,,155,Sellindge,1,19,_J +314,314,314,CHS2,51.34358,-0.32112,295,CHSI_1,51.34358,-0.32112,,,,,156,Chessington,1,19,_J +315,315,315,CHS3,51.34358,-0.32112,295,CHSI_1,51.34358,-0.32112,,,,,156,Chessington,1,19,_J +316,316,316,ELS2,51.661,-0.34377,296,ELST_1,51.661,-0.34377,,,,,82,Elstree,1,10,_A +317,317,317,ELSA,51.661,-0.34377,296,ELST_1,51.661,-0.34377,,,,,82,Elstree,1,10,_A +318,318,318,STMO,51.660005,-0.342297997,296,ELST_1,51.661,-0.34377,,,,,82,Elstree,1,10,_A +319,319,319,KEM1,51.36774,0.74318,297,KEMS_1,51.36774,0.74318,,,,,157,Kemsley,1,19,_J +320,320,320,SHEE,51.436756,0.749608,297,KEMS_1,51.36774,0.74318,,,,,157,Kemsley,1,19,_J +321,321,321,TIL1,51.45976,0.3954,298,TILBB_1,51.45976,0.3954,,,,,83,Tilbury,1,10,_A +322,322,322,TIL2,51.45976,0.3954,298,TILBB_1,51.45976,0.3954,,,,,83,Tilbury,1,10,_A +323,323,323,CAR2,53.43601,-2.40573,299,CARR_1,53.43601,-2.40573,,,,,145,Carrington,1,16,_G +324,324,324,CAR1DM,53.43601,-2.40573,299,CARR_1,53.43601,-2.40573,,,,,145,Carrington,1,16,_G +325,325,325,CON1DM,53.22755,-3.07263,300,CONQA1,53.22755,-3.07263,,,,,113,Connahs Quay,1,13,_D +326,326,326,CON1DV,53.22755,-3.07263,300,CONQA1,53.22755,-3.07263,,,,,113,Connahs Quay,1,13,_D +327,327,327,NEC2,52.50647,-1.85091,301,NECE_1,52.50647,-1.85091,,,,,48,Nechells,1,14,_E +328,328,328,NEC1DM,52.50647,-1.85091,301,NECE_1,52.50647,-1.85091,,,,,48,Nechells,1,14,_E +329,329,329,COAX,55.8516,-4.01407,302,COAT,55.8516,-4.01407,,,,,254,Coatbridge,1,18,_N +330,330,330,COATDW,55.8516,-4.01407,302,COAT,55.8516,-4.01407,,,,,254,Coatbridge,1,18,_N +331,331,331,CROO,55.82121,-4.36533,303,CROO,55.82121,-4.36533,,,,,255,Crookston,1,18,_N +332,332,332,CROX,55.82121,-4.36533,303,CROO,55.82121,-4.36533,,,,,255,Crookston,1,18,_N +333,333,333,DUMX,55.06763,-3.5913,304,DUMF,55.06763,-3.5913,,,,,256,Dumfries,1,18,_N +334,334,334,DUMY,55.06763,-3.5913,304,DUMF,55.06763,-3.5913,,,,,256,Dumfries,1,18,_N +335,335,335,DUMFDW,55.06763,-3.5913,304,DUMF,55.06763,-3.5913,,,,,256,Dumfries,1,18,_N +336,336,336,GRMO,56.00463,-3.69399,305,GRMO,56.00463,-3.69399,,,,,257,Grangemouth,1,18,_N +337,337,337,GRMX,56.00463,-3.69399,305,GRMO,56.00463,-3.69399,,,,,257,Grangemouth,1,18,_N +338,338,338,KILB,55.9189,-4.41049,306,KILB,55.9189,-4.41049,,,,,258,Kilbowie,1,18,_N +339,339,339,KILX,55.930273,-4.376904,306,KILB,55.9189,-4.41049,,,,,258,Kilbowie,1,18,_N +340,340,340,SACX,55.6469,-4.79668,307,SACO,55.6469,-4.79668,,,,,259,Saltcoats,1,18,_N +341,341,341,SACODW,55.6469,-4.79668,307,SACO,55.6469,-4.79668,,,,,259,Saltcoats,1,18,_N +342,342,342,ALD1,53.44523,-1.31903,,,,,12,T__MYELT001,53.44523,-1.31903,,,0,, +343,343,343,ALD2,53.44523,-1.31903,,,,,12,T__MYELT001,53.44523,-1.31903,,,0,, +344,344,344,TIN1,53.40087,-1.39307,,,,,13,T_TINSD-1,53.40087,-1.39307,,,0,, +345,345,345,TIN2,53.40087,-1.39307,,,,,13,T_TINSD-1,53.40087,-1.39307,,,0,, +346,346,346,CRSE,53.8009731,-0.4144914,308,CREB_1,53.8009731,-0.4144914,,,,,180,Creyke Beck,1,23,_M +347,347,346,CRSE,53.8009731,-0.4144914,309,SALT_1,53.74276734,-0.238077699,,,,,181,Saltend North,1,23,_M +348,348,347,LITT,51.460622,0.244391,310,LITT_C,51.460622,0.244391,,,,,100,Littlebrook (_C),1,12,_C +349,349,347,LITT,51.460622,0.244391,311,LITT_J,51.460621,0.244394,,,,,158,Littlebrook (_J),1,19,_J +350,350,348,STAH,53.87966201,-2.989774208,312,STAH_1,53.87966201,-2.989774208,,,,,146,Stanah,1,16,_G +351,351,349,WSD6,51.53495051,-0.257050264,313,WISD_6,51.53495051,-0.257050264,,,,,101,Willesden 66kV (_C),1,12,_C +352,352,349,WSD6,51.53495051,-0.257050264,314,ACTL_C,51.53495051,-0.257050264,,,,,101,Willesden 66kV (_C),1,12,_C +353,353,349,WSD6,51.53495051,-0.257050264,315,ACTL_2,51.53495051,-0.257050264,,,,,16,Willesden 66kV (_H),1,20,_H +354,354,349,WSD6,51.53495051,-0.257050264,316,CBNK_H,51.53495051,-0.257050264,,,,,16,Willesden 66kV (_H),1,20,_H +355,355,349,WSD6,51.53495051,-0.257050264,317,GREE_H,51.53495051,-0.257050264,,,,,16,Willesden 66kV (_H),1,20,_H +356,356,349,WSD6,51.53495051,-0.257050264,318,PERI_H,51.53495051,-0.257050264,,,,,16,Willesden 66kV (_H),1,20,_H +357,357,350,AMEM,51.66424942,-0.655116209,319,AMEM_1,51.66424942,-0.655116209,,,,,84,Amersham Main,1,10,_A +358,358,350,AMEM,51.66424942,-0.655116209,320,LOUD_H,51.66424942,-0.655116209,,,,,17,Loudwater,1,20,_H +359,359,351,BRFODW,52.07018187,1.062822573,321,BRFO_1,52.07018187,1.062822573,,,,,85,Bramford,1,10,_A +360,360,352,CANT,51.29233519,1.094176117,322,CANTN1,51.29233519,1.094176117,,,,,159,Canterbury,1,19,_J +361,361,352,CANT,51.29233519,1.094176117,323,RICH1,51.30873,1.3459,,,,,160,Richborough,1,19,_J +362,362,353,NORMDW,52.57327,1.27176,324,NORM_1,52.57327,1.27176,,,,,86,Norwich Main,1,10,_A +363,363,354,WALPDM,52.72774811,0.1989261763,325,WALP_1,52.72774811,0.1989261763,,,,,87,Walpole (_A),1,10,_A +364,364,354,WALPDM,52.72774811,0.1989261763,326,WALP_B,52.72774811,0.1989261763,,,,,32,Walpole (_B),1,11,_B +365,365,355,STEL,54.97805729,-1.724488264,327,STEN_1,54.97805729,-1.724488264,,,,,130,Stella North,1,15,_F +366,366,355,STEL,54.97805729,-1.724488264,328,STES_1,54.97435217,-1.732510197,,,,,131,Stella South,1,15,_F +367,367,356,HAR1DM,54.94152557,-2.964416544,329,HARK_1,54.94152557,-2.964416544,,,,,147,Harker,1,16,_G +368,368,357,HEYSDM,54.03269168,-2.888958664,330,HEYS_1,54.03269168,-2.888958664,,,,,148,Heysham,1,16,_G +369,369,357,HEYSDM,54.03269168,-2.888958664,331,HEYS1,54.03269168,-2.888958664,,,,,148,Heysham,1,16,_G +370,370,358,CLACDM,56.27712554,-4.922002162,332,CLAC_P,56.27712554,-4.922002162,,,,,323,Clachan,1,17,_P +371,371,358,CLACDM,56.27712554,-4.922002162,333,ARDK_P,56.287166,-4.955504,,,,,324,Ardkinglas,0,17,_P +387,372,359,MELK,51.39181465,-2.150383477,334,MELK_1,51.39181465,-2.150383477,,,,,18,Melksham,1,20,_H +373,373,359,MELK,51.39181465,-2.150383477,,,,,14,T_THNJD-1,51.4341,2.1464,,,0,, +374,374,359,MELK,51.39181465,-2.150383477,,,,,15,T_THNJD-2,51.4341,2.1464,,,0,, +375,375,360,BPGR,56.01141,-3.72183,,,,,16,T_BPGRD-1,56.01141,-3.72183,,,0,, +376,376,360,BPGR,56.01141,-3.72183,,,,,17,T_BPGRD-2,56.01141,-3.72183,,,0,, +377,377,,,,,335,KNAR,54.03121063,-1.487843766,,,,,132,Knaresborough,1,15,_F +378,378,,,,,336,WYLF_1,53.413644,-4.482279,,,,,114,Wylfa,1,13,_D +379,379,,,,,337,DALM3,55.83856729,-4.208346491,,,,,260,Dalmarnock,1,18,_N +380,380,,,,,338,FINN,55.863398,-4.286086,,,,,261,Finnieston,1,18,_N diff --git a/backend/lambda/gb_snapshot/sheffield/pes.py b/backend/lambda/gb_snapshot/sheffield/pes.py new file mode 100644 index 0000000..0d0d0e0 --- /dev/null +++ b/backend/lambda/gb_snapshot/sheffield/pes.py @@ -0,0 +1,224 @@ +# use the sheffield solar API to get current solar power generation +from time import sleep +import requests, pandas as pd, logging, json, os +from pydantic import BaseModel +from datetime import datetime +from typing import List +from ..ptypes import SheffieldGspSnapshot +from multiprocessing import Pool, cpu_count + +PES = [ + { + "id": 10, + "name": "E. Anglia (total)", + "coords": { + # norwich + "lat": 52.6309, + "lng": 1.2974, + }, + }, + { + "id": 11, + "name": "E. Midlands (total)", + "coords": { + # leicester + "lat": 52.6369, + "lng": -1.1398, + }, + }, + { + "id": 12, + "name": "London (total)", + "coords": { + # westminster + "lat": 51.5074, + "lng": -0.1278, + }, + }, + { + "id": 13, + "name": "Merseyside + N. Wales (total)", + "coords": { + # liverpool + "lat": 53.4084, + "lng": -2.9916, + }, + }, + { + "id": 14, + "name": "W. Midlands (total)", + "coords": { + # telford + "lat": 52.6784, + "lng": -2.4453, + }, + }, + { + "id": 15, + "name": "N. East (total)", + "coords": { + # belsay + "lat": 55.0833, + "lng": -1.8667, + }, + }, + { + "id": 16, + "name": "N. West (total)", + "coords": { + # grasmere + "lat": 54.4667, + "lng": -3.0167, + }, + }, + { + "id": 17, + "name": "N. Scotland (total)", + "coords": { + # gairloch + "lat": 57.7167, + "lng": -5.6667, + }, + }, + { + "id": 18, + "name": "S. Scotland (total)", + "coords": { + # glasgow + "lat": 55.8642, + "lng": -4.2518, + }, + }, + { + "id": 19, + "name": "S. East (total)", + "coords": { + # crawley + "lat": 51.1167, + "lng": -0.1833, + }, + }, + { + "id": 20, + "name": "South (total)", + "coords": { + # andover + "lat": 51.2117, + "lng": -1.4927, + }, + }, + { + "id": 21, + "name": "S. Wales (total)", + "coords": { + # llandovery + "lat": 51.992, + "lng": -3.802, + }, + }, + { + "id": 22, + "name": "S. West (total)", + "coords": { + # okehampton + "lat": 50.732, + "lng": -3.982, + }, + }, + { + "id": 23, + "name": "Yorkshire (total)", + "coords": { + # ripon + "lat": 54.1333, + "lng": -1.5167, + }, + }, +] + + +class Coords(BaseModel): + lat: float + lng: float + + +class SheffieldPesResponse(BaseModel): + settlementPeriod: int + startTime: datetime + ac: float + cp: float + + +def get_and_retry_with_backoff(url, retries=15): + for i in range(retries): + resp = requests.get(url) + if resp.status_code == 200: + return resp + print(f"Failed to get data from Sheffield Solar API: {resp.text}") + sleep(2**i) + raise Exception(f"Failed to get data from Sheffield Solar API: {resp.text}") + + +class SheffieldPes(BaseModel): + dt: datetime + id: int + name: str + coords: Coords + + def run(self) -> SheffieldPesResponse: + url = f"https://api.solar.sheffield.ac.uk/pvlive/api/v4/pes/{self.id}?extra_fields=capacity_mwp" + resp = get_and_retry_with_backoff(url) + raw_data = resp.json()["data"] + + if len(raw_data) == 0: + return None + + data = [ + SheffieldPesResponse( + settlementPeriod=settlementPeriod, startTime=startTime, ac=ac, cp=cp + ) + for settlementPeriod, startTime, ac, cp in raw_data + ] + return data[0] + + +def get_pes_data(pes: SheffieldPes): + return pes.run() + + +class SheffieldPess(BaseModel): + """Sheffield GSP data model""" + + dt: datetime + + def run(self) -> List[SheffieldGspSnapshot]: + """Get the current solar power generation from Sheffield Solar API""" + pess = [SheffieldPes(**x, dt=self.dt) for x in PES] + # mw = [get_pes_data(gsp) for gsp in pess] + with Pool(cpu_count()) as p: + mws = p.map(get_pes_data, pess) + + return [ + SheffieldGspSnapshot( + bids=0, + offers=0, + fuel_type="solar", + name=x["name"], + code=f"solar_pes_{x['id']}", + # need to update + cp=r.cp, + # need to update + dl=0, + ac=r.ac, + coords=x["coords"], + dt=self.dt, + ) + for x, r in zip(PES, mws) + ] + + +if __name__ == "__main__": + now = datetime.now().replace(minute=0, second=0, microsecond=0) + dt = now.replace(minute=now.minute + 1) + sg = SheffieldPess(dt=dt) + sg.run() diff --git a/backend/lib/kilowatts-grid-stack.ts b/backend/lib/kilowatts-grid-stack.ts index 9ded1a8..b7a8cb2 100644 --- a/backend/lib/kilowatts-grid-stack.ts +++ b/backend/lib/kilowatts-grid-stack.ts @@ -88,7 +88,7 @@ export class KilowattsGridStack extends cdk.Stack { functionName: "gb-snapshot", code: lambda.Code.fromAsset("lambda"), handler: "gb_snapshot.handler.handler", - timeout: cdk.Duration.seconds(45), + timeout: cdk.Duration.seconds(60), memorySize: 512, environment: { BUCKET_NAME: bucket.bucketName,