update gas providers

This commit is contained in:
2026-03-02 14:41:27 +01:00
parent bac25fa944
commit ba6683ceea
5 changed files with 58390 additions and 43 deletions

58019
alfen_ocpp_2025-12-17.log Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,93 @@
import mysql.connector
import sys
from mysql.connector import Error
def copy_tomorrow_data():
source_conn = None
dest_conn = None
# ---- Gegevens voor de BRON (alfen) ----
source_db_config = {
'host': '127.0.0.1',
'database': 'alfen',
'user': 'alfen_user',
'password': '5uVgr%f%s2P5GR@3q!',
'port': 3307
}
# ---- Gegevens voor de BESTEMMING (energy_prices) ----
dest_db_config = {
'host': '127.0.0.1',
'database': 'energy_prices',
'user': 'energy_prices_user',
'password': 'kS9R*xp17ZwCD@CV&E^N',
'port': 3307
}
try:
source_conn = mysql.connector.connect(**source_db_config)
dest_conn = mysql.connector.connect(**dest_db_config)
if source_conn.is_connected() and dest_conn.is_connected():
source_cursor = source_conn.cursor(dictionary=True)
dest_cursor = dest_conn.cursor()
# 1. Maak de doeltabel aan als deze niet bestaat
# Let op: UNIQUE KEY op datetime is nodig voor ON DUPLICATE KEY UPDATE
create_table_query = """
CREATE TABLE IF NOT EXISTS dynamic_price_data_tommorow (
id INT AUTO_INCREMENT PRIMARY KEY,
datetime DATETIME NOT NULL,
price DECIMAL(10, 4) NOT NULL,
UNIQUE KEY unique_datetime (datetime)
) ENGINE=InnoDB;
"""
dest_cursor.execute(create_table_query)
# 2. Data ophalen uit de bron (alfen)
print("Data selecteren uit bron...")
select_query = """
SELECT datetime, price
FROM dynamic_price_data_tommorow
WHERE DATE(datetime) = CURDATE() + INTERVAL 1 DAY
"""
source_cursor.execute(select_query)
rows_to_copy = source_cursor.fetchall()
if not rows_to_copy:
print("Geen data voor morgen gevonden in de bron.")
return
# --- NIEUW: Eerst de doeltabel leegmaken ---
print("Oude data verwijderen uit bestemming...")
dest_cursor.execute("DELETE FROM dynamic_price_data_tommorow")
# ------------------------------------------
# 3. Data invoeren in de bestemming
insert_query = """
INSERT INTO dynamic_price_data_tommorow (datetime, price)
VALUES (%s, %s)
"""
# We hebben ON DUPLICATE KEY UPDATE niet meer strikt nodig als we net DELETE hebben gedaan,
# maar het kan geen kwaad om het simpel te houden.
rows_data = [(row['datetime'], row['price']) for row in rows_to_copy]
dest_cursor.executemany(insert_query, rows_data)
dest_conn.commit()
print(f"Succes! {len(rows_data)} rijen vers gekopieerd.")
except Error as e:
print(f"Fout tijdens proces: {e}", file=sys.stderr)
sys.exit(1)
finally:
if source_conn and source_conn.is_connected():
source_cursor.close()
source_conn.close()
if dest_conn and dest_conn.is_connected():
dest_cursor.close()
dest_conn.close()
if __name__ == "__main__":
copy_tomorrow_data()

5
gas.py
View File

@@ -47,8 +47,13 @@ def insert_gas_price_data():
'GSL': 'prijsGSL',
'MDE': 'prijsMDE',
'NE': 'prijsNE',
'PE': 'prijsPE',
'QU': 'prijsQU',
'SS': 'prijsSS',
'TI': 'prijsTI',
'VDB': 'prijsVDB',
'VON': 'prijsVON',
'VF': 'prijsVF',
'WE': 'prijsWE',
'ZP': 'prijsZP'
}

235
ocpp_logger.py Normal file
View File

@@ -0,0 +1,235 @@
import asyncio
import websockets
import json
from ocpp.routing import on
from ocpp.v16 import ChargePoint as cp
from ocpp.v16 import call_result
from datetime import datetime
import os
def get_log_filename():
"""Genereer log bestandsnaam met datum"""
date_str = datetime.now().strftime("%Y-%m-%d")
return f"alfen_ocpp_{date_str}.log"
def log_message(message, level="INFO"):
"""Log naar bestand en console"""
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_entry = f"[{timestamp}] [{level}] {message}"
# Print naar console
print(log_entry)
# Append naar dagelijks log bestand
log_file = get_log_filename()
with open(log_file, 'a', encoding='utf-8') as f:
f.write(log_entry + "\n")
def log_json(title, data):
"""Log JSON data mooi geformatteerd"""
log_message(f"\n{title}:")
formatted = json.dumps(data, indent=2, ensure_ascii=False)
for line in formatted.split('\n'):
log_message(f" {line}")
class ChargePoint(cp):
@on('BootNotification')
def on_boot_notification(self, charge_point_model, charge_point_vendor, **kwargs):
log_message("=" * 60, "SUCCESS")
log_message("LAADPAAL VERBONDEN!", "SUCCESS")
log_message("=" * 60, "SUCCESS")
log_json("Boot Notification data", {
"model": charge_point_model,
"vendor": charge_point_vendor,
**kwargs
})
return call_result.BootNotification(
current_time=datetime.utcnow().isoformat(),
interval=300,
status='Accepted'
)
@on('Heartbeat')
def on_heartbeat(self, **kwargs):
log_message("💓 Heartbeat ontvangen", "HEARTBEAT")
if kwargs:
log_json("Heartbeat data", kwargs)
return call_result.Heartbeat(
current_time=datetime.utcnow().isoformat()
)
@on('StatusNotification')
def on_status_notification(self, connector_id, error_code, status, **kwargs):
log_message(f"📊 Status Update - Connector {connector_id}", "STATUS")
log_json("Status details", {
"connector_id": connector_id,
"status": status,
"error_code": error_code,
**kwargs
})
return call_result.StatusNotification()
@on('StartTransaction')
def on_start_transaction(self, connector_id, id_tag, meter_start, timestamp, **kwargs):
log_message("=" * 60, "TRANSACTION")
log_message("🔌 LAADSESSIE GESTART!", "TRANSACTION")
log_message("=" * 60, "TRANSACTION")
log_json("Start Transaction data", {
"connector_id": connector_id,
"id_tag": id_tag,
"meter_start": meter_start,
"timestamp": timestamp,
**kwargs
})
return call_result.StartTransaction(
transaction_id=int(datetime.now().timestamp()),
id_tag_info={'status': 'Accepted'}
)
@on('StopTransaction')
def on_stop_transaction(self, meter_stop, timestamp, transaction_id, **kwargs):
log_message("=" * 60, "TRANSACTION")
log_message("🔋 LAADSESSIE GESTOPT!", "TRANSACTION")
log_message("=" * 60, "TRANSACTION")
# Bereken verbruik als meter_start beschikbaar is
transaction_data = {
"transaction_id": transaction_id,
"meter_stop": meter_stop,
"timestamp": timestamp,
**kwargs
}
# Check of reason aanwezig is in kwargs
if 'reason' in kwargs:
transaction_data['reason'] = kwargs['reason']
# Check of transaction_data aanwezig is in kwargs
if 'transaction_data' in kwargs:
# Parse meter values uit transaction_data
for data_item in kwargs['transaction_data']:
if 'sampled_value' in data_item:
for value in data_item['sampled_value']:
if value.get('measurand') == 'Energy.Active.Import.Register':
meter_start_value = int(value.get('value', 0))
verbruik_wh = meter_stop - meter_start_value
transaction_data['meter_start'] = meter_start_value
transaction_data['verbruik_wh'] = verbruik_wh
transaction_data['verbruik_kwh'] = round(verbruik_wh / 1000, 3)
log_json("Stop Transaction data", transaction_data)
return call_result.StopTransaction(
id_tag_info={'status': 'Accepted'}
)
@on('MeterValues')
def on_meter_values(self, connector_id, meter_value, **kwargs):
log_message(f"⚡ Meter waarden - Connector {connector_id}", "METER")
log_json("Meter Values", {
"connector_id": connector_id,
"meter_value": meter_value,
**kwargs
})
return call_result.MeterValues()
@on('Authorize')
def on_authorize(self, id_tag, **kwargs):
log_message(f"🔐 Autorisatie aanvraag - Tag: {id_tag}", "AUTH")
if kwargs:
log_json("Authorize data", kwargs)
return call_result.Authorize(
id_tag_info={'status': 'Accepted'}
)
@on('DataTransfer')
def on_data_transfer(self, vendor_id, **kwargs):
log_message(f"📦 Data Transfer - Vendor: {vendor_id}", "DATA")
log_json("Data Transfer", {
"vendor_id": vendor_id,
**kwargs
})
return call_result.DataTransfer(status='Accepted')
@on('DiagnosticsStatusNotification')
def on_diagnostics_status(self, status, **kwargs):
log_message(f"🔧 Diagnostics Status: {status}", "DIAG")
if kwargs:
log_json("Diagnostics data", kwargs)
return call_result.DiagnosticsStatusNotification()
@on('FirmwareStatusNotification')
def on_firmware_status(self, status, **kwargs):
log_message(f"🔄 Firmware Status: {status}", "FIRMWARE")
if kwargs:
log_json("Firmware data", kwargs)
return call_result.FirmwareStatusNotification()
async def on_connect(websocket, path):
charge_point_id = path.strip('/')
log_message("\n" + "=" * 60, "CONNECTION")
log_message(f"Nieuwe verbinding!", "CONNECTION")
log_message(f" Charge Point ID: {charge_point_id}", "CONNECTION")
log_message(f" IP adres: {websocket.remote_address[0]}", "CONNECTION")
log_message(f" Poort: {websocket.remote_address[1]}", "CONNECTION")
log_message("=" * 60, "CONNECTION")
cp = ChargePoint(charge_point_id, websocket)
try:
await cp.start()
except websockets.exceptions.ConnectionClosed:
log_message("Verbinding verbroken", "WARNING")
except Exception as e:
log_message(f"Fout opgetreden: {e}", "ERROR")
import traceback
log_message(traceback.format_exc(), "ERROR")
async def main():
log_file = get_log_filename()
# Check of log bestand voor vandaag al bestaat
if not os.path.exists(log_file):
# Nieuw dagelijks log bestand
with open(log_file, 'w', encoding='utf-8') as f:
f.write(f"OCPP Log gestart op {datetime.now()}\n")
f.write("=" * 60 + "\n\n")
else:
# Bestand bestaat al, voeg scheidingslijn toe
with open(log_file, 'a', encoding='utf-8') as f:
f.write("\n" + "=" * 60 + "\n")
f.write(f"Server herstart op {datetime.now()}\n")
f.write("=" * 60 + "\n\n")
log_message("🚀 OCPP Test Server gestart", "INFO")
log_message("=" * 60, "INFO")
log_message("Poort: 9000", "INFO")
log_message(f"Log bestand: {os.path.abspath(log_file)}", "INFO")
log_message("Ondersteunde OCPP versie: 1.6", "INFO")
log_message("=" * 60, "INFO")
log_message("\nWacht op verbinding van laadpaal...\n", "INFO")
server = await websockets.serve(
on_connect,
'0.0.0.0',
9000,
subprotocols=['ocpp1.6'],
ping_interval=None # Disable websocket pings, OCPP heeft eigen heartbeat
)
await server.wait_closed()
if __name__ == '__main__':
try:
asyncio.run(main())
except KeyboardInterrupt:
log_message("\n\n👋 Server gestopt door gebruiker", "INFO")
except Exception as e:
log_message(f"Fatale fout: {e}", "ERROR")
import traceback
log_message(traceback.format_exc(), "ERROR")

View File

@@ -1,26 +1,29 @@
import requests
import mysql.connector
from mysql.connector import Error
from datetime import datetime, timedelta
def insert_dynamic_price_data_tomorrow():
connection = None # Connection buiten de try initialiseren
connection = None
try:
# URL van de API
# 1. Bepaal de datum van morgen (bijv. '2026-01-25')
tomorrow_date = (datetime.now() + timedelta(days=1)).strftime('%Y-%m-%d')
print(f"Filteren op data voor: {tomorrow_date}")
# 2. Data ophalen
url = "https://enever.nl/api/stroomprijs_morgen.php?token=5a7d9b371fe147cfc8100bcf6d9ebd55"
response = requests.get(url)
if response.status_code != 200:
raise Exception('Fout bij het ophalen van de data.')
data = response.json()
if not data or 'data' not in data:
raise Exception('Geen data gevonden in API respons.')
if data is None or 'data' not in data:
raise Exception('Fout bij het decoderen van de JSON-data.')
# Verbinden met de MySQL-database
# 3. Verbinden met MySQL
connection = mysql.connector.connect(
host='127.0.0.1', # Gebruik 127.0.0.1 ipv localhost
host='127.0.0.1',
database='alfen',
user='alfen_user',
password='5uVgr%f%s2P5GR@3q!',
@@ -30,17 +33,6 @@ def insert_dynamic_price_data_tomorrow():
if connection.is_connected():
cursor = connection.cursor()
# Verwijder bestaande records uit de tabel
cursor.execute("DELETE FROM dynamic_price_data_tommorow")
connection.commit()
# Voorbereiding van de query
query = """
INSERT INTO dynamic_price_data_tommorow (datetime, price)
VALUES (%s, %s)
"""
# Sleutelwoorden voor prijsvelden
price_fields = [
'prijsAA', 'prijsAIP', 'prijsANWB', 'prijsBE', 'prijsEE',
'prijsEN', 'prijsEVO', 'prijsEZ', 'prijsFR', 'prijsGSL',
@@ -48,37 +40,40 @@ def insert_dynamic_price_data_tomorrow():
'prijsWE', 'prijsZG', 'prijsZP'
]
# Data invoegen
rows_to_insert = []
# 4. Loop door de data en filter op morgen
for entry in data['data']:
datetime = entry['datum']
# Controleer of de datum in de API begint met de datum van morgen
if entry['datum'].startswith(tomorrow_date):
prices = [float(entry[f]) for f in price_fields if f in entry and entry[f] != '']
if prices:
avg_price = sum(prices) / len(prices)
rows_to_insert.append((entry['datum'], avg_price))
# Gemiddelde prijs berekenen (exclusief het veld 'prijs')
prices = [
float(entry[field]) for field in price_fields if field in entry and entry[field] != ''
]
if prices:
avg_price = sum(prices) / len(prices)
else:
avg_price = None # Geen prijzen beschikbaar
# Data invoegen in de tabel
if avg_price is not None:
try:
cursor.execute(query, (datetime, avg_price))
connection.commit()
except Error as e:
print(f"Fout bij invoeren van data voor datetime {datetime}: {e}")
continue
# 5. Database bijwerken
if rows_to_insert:
# Wis de tabel
cursor.execute("DELETE FROM dynamic_price_data_tommorow")
# Voeg alleen de gefilterde rijen toe
query = "INSERT INTO dynamic_price_data_tommorow (datetime, price) VALUES (%s, %s)"
cursor.executemany(query, rows_to_insert)
connection.commit()
print(f"Succes! {len(rows_to_insert)} rijen toegevoegd voor {tomorrow_date}.")
else:
print(f"Geen data gevonden voor {tomorrow_date} in de API-respons.")
except Error as e:
print(f"Fout bij databaseverbinding: {e}")
print(f"Database fout: {e}")
except Exception as e:
print(f"Algemene fout: {e}")
print(f"Fout: {e}")
finally:
# Sluit de verbinding
if connection is not None and connection.is_connected():
if connection and connection.is_connected():
cursor.close()
connection.close()
if __name__ == "__main__":
insert_dynamic_price_data_tomorrow()
insert_dynamic_price_data_tomorrow()