Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions ct/myelectricaldata.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#!/usr/bin/env bash
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/DevScripts/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func")
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Marlboro62
# License: MIT | https://github.com/community-scripts/DevScripts/raw/main/LICENSE
# Source: https://github.com/MyElectricalData/myelectricaldata_new

APP="MyElectricalData"
var_tags="${var_tags:-energy;smart-home}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
#var_arm64="${var_arm64:-no}" # unset = ask the user; set yes/no only when verified

export var_med_client_id="${var_med_client_id:-}"
export var_med_client_secret="${var_med_client_secret:-}"

header_info "$APP"
variables
color
catch_errors

function update_script() {
header_info
check_container_storage
check_container_resources

if [[ ! -d /opt/myelectricaldata ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi

if check_for_gh_release "myelectricaldata" "MyElectricalData/myelectricaldata_new"; then
msg_info "Stopping MyElectricalData"
systemctl stop myelectricaldata
msg_ok "Stopped MyElectricalData"

create_backup /opt/myelectricaldata/.env

CLEAN_INSTALL=1 fetch_and_deploy_gh_release "myelectricaldata" "MyElectricalData/myelectricaldata_new" "tarball"

restore_backup

msg_info "Updating MyElectricalData Backend"
cd /opt/myelectricaldata/apps/api
$STD uv sync --locked --no-dev --no-install-project
msg_ok "Updated MyElectricalData Backend"

msg_info "Building MyElectricalData Frontend"
cd /opt/myelectricaldata/apps/web
$STD npm ci
$STD npm run build
msg_ok "Built MyElectricalData Frontend"

msg_info "Starting MyElectricalData"
systemctl start myelectricaldata
systemctl reload nginx
msg_ok "Started MyElectricalData"
msg_ok "Updated successfully!"
fi
exit
}

# The gateway credentials are asked on the host, before the container is built:
# a missing value then costs seconds instead of a full build.
if command -v pveversion >/dev/null 2>&1; then
if [[ -z "${var_med_client_id}" ]]; then
read -rp "${TAB3}MyElectricalData Client ID (cli_...): " var_med_client_id
fi
if [[ -z "${var_med_client_secret}" ]]; then
read -rsp "${TAB3}MyElectricalData Client Secret: " var_med_client_secret
echo
fi
if [[ -z "${var_med_client_id}" || -z "${var_med_client_secret}" ]]; then
msg_error "var_med_client_id and var_med_client_secret are required (MyElectricalData account > API)."
exit 1
fi
fi

start
build_container
description

msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW}Access it using the following URL:${CL}"
echo -e "${GATEWAY}${BGN}http://${IP}:8100${CL}"
118 changes: 118 additions & 0 deletions install/myelectricaldata-install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/usr/bin/env bash

# Copyright (c) 2021-2026 community-scripts ORG
# Author: Marlboro62
# License: MIT | https://github.com/community-scripts/DevScripts/raw/main/LICENSE
# Source: https://github.com/MyElectricalData/myelectricaldata_new

source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os

msg_info "Installing Dependencies"
$STD apt install -y nginx
msg_ok "Installed Dependencies"

PG_VERSION="16" setup_postgresql
PG_DB_NAME="myelectricaldata_client" PG_DB_USER="myelectricaldata" setup_postgresql_db
PYTHON_VERSION="3.11" setup_uv
NODE_VERSION="24" setup_nodejs

fetch_and_deploy_gh_release "myelectricaldata" "MyElectricalData/myelectricaldata_new" "tarball"

msg_info "Configuring MyElectricalData Backend"
cat <<EOF >/opt/myelectricaldata/.env
MED_CLIENT_ID=${var_med_client_id}
MED_CLIENT_SECRET=${var_med_client_secret}
MED_API_URL=https://www.v2.myelectricaldata.fr/api
DATABASE_URL=postgresql+asyncpg://${PG_DB_USER}:${PG_DB_PASS}@127.0.0.1:5432/${PG_DB_NAME}
VICTORIAMETRICS_URL=
SECRET_KEY=$(random_password 43)
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=43200
ALLOWED_HOSTS=
TZ=Europe/Paris
DEBUG=false
API_HOST=127.0.0.1
API_PORT=8000
PYTHONUNBUFFERED=1
EOF
chmod 600 /opt/myelectricaldata/.env
cd /opt/myelectricaldata/apps/api
$STD uv sync --locked --no-dev --no-install-project
msg_ok "Configured MyElectricalData Backend"

msg_info "Building MyElectricalData Frontend"
cd /opt/myelectricaldata/apps/web
$STD npm ci
$STD npm run build
msg_ok "Built MyElectricalData Frontend"

msg_info "Configuring Nginx"
cat <<'EOF' >/etc/nginx/sites-available/myelectricaldata
server {
listen 8100;
server_name _;

root /opt/myelectricaldata/apps/web/dist;
index index.html;

location /api/ {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_read_timeout 300s;
}

location = /index.html {
add_header Cache-Control "no-cache";
}
location = /env.js {
add_header Cache-Control "no-cache";
}

location /assets/ {
add_header Cache-Control "public, max-age=31536000, immutable";
}

location / {
try_files $uri $uri/ /index.html;
}
}
EOF
nginx_enable_site "myelectricaldata"
msg_ok "Configured Nginx"

msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/myelectricaldata.service
[Unit]
Description=MyElectricalData Backend
After=network-online.target postgresql.service
Wants=network-online.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/myelectricaldata/apps/api
EnvironmentFile=/opt/myelectricaldata/.env
ExecStartPre=/opt/myelectricaldata/apps/api/.venv/bin/alembic upgrade head
ExecStart=/opt/myelectricaldata/apps/api/.venv/bin/uvicorn src.main:app --host 127.0.0.1 --port 8000
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now myelectricaldata
msg_ok "Created Service"

motd_ssh
customize
cleanup_lxc
63 changes: 63 additions & 0 deletions json/myelectricaldata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"name": "MyElectricalData",
"slug": "myelectricaldata",
"categories": [
16
],
"date_created": "2026-10-28",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8100,
"documentation": "https://github.com/MyElectricalData/myelectricaldata_new/tree/main/docs/local-client",
"website": "https://www.v2.myelectricaldata.fr/",
"repository": "https://github.com/MyElectricalData/myelectricaldata_new",
"platforms": [
"pve"
],
"logo": "https://cdn.jsdelivr.net/gh/MyElectricalData/myelectricaldata_new@main/apps/web/public/logo.svg",
"description": "MyElectricalData is the local client of the MyElectricalData gateway for French Linky smart meters. It keeps the consumption and production history from Enedis in its own database, shows it in a web interface with costs per tariff, Tempo and EcoWatt, and exports it to Home Assistant or VictoriaMetrics.",
"install_methods": [
{
"type": "default",
"script": "ct/myelectricaldata.sh",
"config_path": "/opt/myelectricaldata/.env",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 8,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Requires a free account on www.v2.myelectricaldata.fr with the Enedis consent: its Client ID and Client Secret are asked during the install.",
"type": "info"
},
{
"text": "The gateway allows 50 uncached requests per day per account: do not run several instances with the same credentials.",
"type": "warning"
}
],
"app_vars": [
{
"name": "var_med_client_id",
"label": "MyElectricalData Client ID",
"type": "text",
"required": true
},
{
"name": "var_med_client_secret",
"label": "MyElectricalData Client Secret",
"type": "password",
"secret": true,
"required": true
}
]
}
Loading