Repository: electricitymaps/electricitymaps-contrib

Issue:
Data for Wrangell, Petersburg and Ketchikan (Alaska, USA)
The Southeast Alaska Power Agency services Ketchikan, Wrangell and Petersburg in Alaska.

They have a page with SCADA data available: https://seapahydro.org/scada

The abbreviations seem pretty intuitive: TYL =TYEE LAKE hydropower plant, SWL = SWAN LAKE  hydropower plant; WRG = WRANGELL, PTG = PETERSBURG, KTN = KETCHIKAN

The page has hydro and diesel generation. As the latter is currently 0 MW, I think it's only used as a backup.

![SEAPA SCADA](https://github.com/electricitymaps/electricitymaps-contrib/assets/2470175/1554331b-83b2-4ecf-a66a-b53ef5e2ef4d)




Discussion:
Looks like we can split off part of Alaska and add it as a zone with this data!
As far as I can tell there is no historical data but the realtime data seems to be of high quality and updated every few seconds.

What we need to do now is:

1. Create a new zone config for The Southeast Alaska Power Agency
2. Create a parser to fetch the new data.
3. Update the geographies to split Alaska.
4. Update the US zone config with the new zone in both the aggregated array and the excluded array (for now).
Can I take this one? The task I'm currently working through with Lord Howe Island seems pretty similar so I'm hoping that I can apply what I learned from there to this task 😄 
Feel free to do so, I wasn't planning on working on this anytime soon.

Resolving patch:
diff --git a/parsers/SEAPA.py b/parsers/SEAPA.py
new file mode 100644
--- /dev/null
+++ b/parsers/SEAPA.py
@@ -0,0 +1,64 @@
+from datetime import datetime, timezone
+from logging import Logger, getLogger
+from typing import Any
+
+from requests import Session
+
+from electricitymap.contrib.lib.models.event_lists import ProductionBreakdownList
+from electricitymap.contrib.lib.models.events import ProductionMix
+from electricitymap.contrib.lib.types import ZoneKey
+from parsers.lib.exceptions import ParserException
+
+PARSER_NAME = "SEAPA.py"
+
+SOURCE = "seapahydro.org"
+DATA_URL = "https://seapahydro.org/api/scada/index"
+
+
+def get_value(data: dict, key: str) -> float:
+    return float(data[key]["text"])
+
+
+def fetch_production(
+    zone_key: ZoneKey,
+    session: Session | None = None,
+    target_datetime: datetime | None = None,
+    logger: Logger = getLogger(__name__),
+) -> list[dict[str, Any]]:
+    session = session or Session()
+
+    if target_datetime is not None:
+        raise ParserException(
+            PARSER_NAME, "This parser is not yet able to parse past dates", zone_key
+        )
+
+    res = session.get(DATA_URL)
+    data = res.json()
+
+    data = {
+        "seapa_total": get_value(data, "ss_mw"),  # 2 hydro plants owned by SEAPA
+        "ktn_hydro": get_value(
+            data, "ktn_hydro_mw"
+        ),  # hydro from pre-existing Ketchikan plants
+        "ktn_diesel": get_value(data, "ktn_diesel_mw"),  # backup Ketchikan diesel
+    }
+
+    production_mix = ProductionMix(oil=data["ktn_diesel"])
+    production_mix.add_value("hydro", data["seapa_total"], True)
+    production_mix.add_value("hydro", data["ktn_hydro"], True)
+
+    production_list = ProductionBreakdownList(logger=logger)
+    production_list.append(
+        zoneKey=zone_key,
+        datetime=datetime.now(timezone.utc),
+        production=production_mix,
+        source=SOURCE,
+    )
+
+    return production_list.to_list()
+
+
+if __name__ == "__main__":
+    """Main method, never used by the Electricity Maps backend, but handy for testing."""
+
+    print(fetch_production(ZoneKey("US-AK-SEAPA")))


Test patch: