update gas providers
This commit is contained in:
58019
alfen_ocpp_2025-12-17.log
Normal file
58019
alfen_ocpp_2025-12-17.log
Normal file
File diff suppressed because it is too large
Load Diff
93
copy_energy_prices_tommorow.py
Normal file
93
copy_energy_prices_tommorow.py
Normal 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
5
gas.py
@@ -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
235
ocpp_logger.py
Normal 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")
|
||||
81
tommorow.py
81
tommorow.py
@@ -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()
|
||||
Reference in New Issue
Block a user