TeslaSolarCharger is a service to set one or multiple Teslas' charging current using the datalogger TeslaMate.
You can either install the software in a Docker container or download the binaries and deploy it on any server.
The easiest way to use TeslaSolarCharger is with Docker. Depending on your system, you have to install Docker, including Docker-Compose, first.
To set up TeslaSolarCharger, you must create a docker-compose.yml (name is important!) file in a new directory. Note: During the setup, some additional data folders to persist data will be created in that folder, so it is recommended to use a new directory for your docker-compose.yml.
The needed content of your docker-compose.yml depends on your inverter. By default, TeslaSolarCharger can consume JSON/XML REST APIs. To get the software running on SMA or SolarEdge, you can use specific plugins which create the needed JSON API. You can use the software with any ModbusTCP-capable inverter also.
Below you can see the content for your docker-compose.yml if you are not using any plugin. Note: I recommend changing as few things as possible on this file as this will increase the effort to set everything up but feel free to change the database password, encryption key, and Timezone. Important: If you change the password or the encryption key, you need to use the same password and encryption key at all points in your docker-compose.yml
version: '3.3'
services:
teslamate:
image: teslamate/teslamate:latest
restart: always
environment:
- DATABASE_USER=teslamate
- DATABASE_PASS=secret ##You can change your password here
- DATABASE_NAME=teslamate
- DATABASE_HOST=database
- MQTT_HOST=mosquitto
- ENCRYPTION_KEY=supersecret ##You can change your encryption key here
- TZ=Europe/Berlin ##You can change your Timezone here
ports:
- 4000:4000
volumes:
- ./import:/opt/app/import
cap_drop:
- all
database:
image: postgres:13
restart: always
environment:
- POSTGRES_USER=teslamate
- POSTGRES_PASSWORD=secret ##You can change your password here
- POSTGRES_DB=teslamate
volumes:
- teslamate-db:/var/lib/postgresql/data
grafana:
image: teslamate/grafana:latest
restart: always
environment:
- DATABASE_USER=teslamate
- DATABASE_PASS=secret ##You can change your password here
- DATABASE_NAME=teslamate
- DATABASE_HOST=database
ports:
- 3100:3000
volumes:
- teslamate-grafana-data:/var/lib/grafana
mosquitto:
image: eclipse-mosquitto:2
restart: always
command: mosquitto -c /mosquitto-no-auth.conf
#ports:
# - 1883:1883
volumes:
- mosquitto-conf:/mosquitto/config
- mosquitto-data:/mosquitto/data
teslamateapi:
image: tobiasehlert/teslamateapi:latest
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
restart: always
depends_on:
- database
environment:
- DATABASE_USER=teslamate
- DATABASE_PASS=secret ##You can change your password here
- DATABASE_NAME=teslamate
- DATABASE_HOST=database
- MQTT_HOST=mosquitto
- TZ=Europe/Berlin ##You can change your Timezone here
- ENABLE_COMMANDS=true
- COMMANDS_ALL=true
- API_TOKEN_DISABLE=true
- ENCRYPTION_KEY=supersecret ##You can change your encryption key here
#ports:
# - 8080:8080
teslasolarcharger:
image: pkuehnel/teslasolarcharger:latest
container_name: teslasolarcharger
logging:
driver: "json-file"
options:
max-file: "10"
max-size: "100m"
restart: always
depends_on:
- teslamateapi
environment:
# - Serilog__MinimumLevel__Default=Verbose #uncomment this line and recreate container with docker-compose up -d for more detailed logs
- TZ=Europe/Berlin ##You can change your Timezone here
ports:
- 7190:80
volumes:
- teslasolarcharger-configs:/app/configs
volumes:
teslamate-db:
teslamate-grafana-data:
mosquitto-conf:
mosquitto-data:
teslasolarcharger-configs:
The SMA plugin is used to access your EnergyMeter (or Sunny Home Manager 2.0) values.
To use the plugin, add these lines to the bottom of your docker-compose.yml.
smaplugin:
image: pkuehnel/teslasolarchargersmaplugin:latest
container_name: teslasolarcharger_smaplugin
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
restart: always
network_mode: host
environment:
- ASPNETCORE_URLS=http://+:7192
You can also copy the complete content from here:
Complete file using SMA plugin
version: '3.3'
services:
teslamate:
image: teslamate/teslamate:latest
restart: always
environment:
- DATABASE_USER=teslamate
- DATABASE_PASS=secret ##You can change your password here
- DATABASE_NAME=teslamate
- DATABASE_HOST=database
- MQTT_HOST=mosquitto
- ENCRYPTION_KEY=supersecret ##You can change your encryption key here
- TZ=Europe/Berlin ##You can change your Timezone here
ports:
- 4000:4000
volumes:
- ./import:/opt/app/import
cap_drop:
- all
database:
image: postgres:13
restart: always
environment:
- POSTGRES_USER=teslamate
- POSTGRES_PASSWORD=secret ##You can change your password here
- POSTGRES_DB=teslamate
volumes:
- teslamate-db:/var/lib/postgresql/data
grafana:
image: teslamate/grafana:latest
restart: always
environment:
- DATABASE_USER=teslamate
- DATABASE_PASS=secret ##You can change your password here
- DATABASE_NAME=teslamate
- DATABASE_HOST=database
ports:
- 3100:3000
volumes:
- teslamate-grafana-data:/var/lib/grafana
mosquitto:
image: eclipse-mosquitto:2
restart: always
command: mosquitto -c /mosquitto-no-auth.conf
#ports:
# - 1883:1883
volumes:
- mosquitto-conf:/mosquitto/config
- mosquitto-data:/mosquitto/data
teslamateapi:
image: tobiasehlert/teslamateapi:latest
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
restart: always
depends_on:
- database
environment:
- DATABASE_USER=teslamate
- DATABASE_PASS=secret ##You can change your password here
- DATABASE_NAME=teslamate
- DATABASE_HOST=database
- MQTT_HOST=mosquitto
- TZ=Europe/Berlin ##You can change your Timezone here
- ENABLE_COMMANDS=true
- COMMANDS_ALL=true
- API_TOKEN_DISABLE=true
- ENCRYPTION_KEY=supersecret ##You can change your encryption key here
#ports:
# - 8080:8080
teslasolarcharger:
image: pkuehnel/teslasolarcharger:latest
container_name: teslasolarcharger
logging:
driver: "json-file"
options:
max-file: "10"
max-size: "100m"
restart: always
depends_on:
- teslamateapi
environment:
# - Serilog__MinimumLevel__Default=Verbose #uncomment this line and recreate container with docker-compose up -d for more detailed logs
- TZ=Europe/Berlin ##You can change your Timezone here
ports:
- 7190:80
volumes:
- teslasolarcharger-configs:/app/configs
smaplugin:
image: pkuehnel/teslasolarchargersmaplugin:latest
container_name: teslasolarcharger_smaplugin
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
restart: always
network_mode: host
environment:
- ASPNETCORE_URLS=http://+:7192
volumes:
teslamate-db:
teslamate-grafana-data:
mosquitto-conf:
mosquitto-data:
teslasolarcharger-configs:
The SolarEdge Plugin uses the cloud API, which is limited to 300 calls per day. To stay within this limit, there is an environment variable that limits the refresh interval to 360 seconds. This results in a very low update frequency of your power values. That is why it is recommended to use the ModbusPlugin below.
To use the plugin, just add these lines to the bottom of your docker-compose.yml. Note: You have to change your site ID and your API key in the CloudUrl environment variable
solaredgeplugin:
image: pkuehnel/teslasolarchargersolaredgeplugin:latest
container_name: teslasolarcharger_solaredgeplugin
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
restart: always
environment:
- CloudUrl=https://monitoringapi.solaredge.com/site/1561056/currentPowerFlow.json?api_key=asdfasdfasdfasdfasdfasdf& ##Change your site ID and API Key here
- RefreshIntervalSeconds=360
ports:
- 7193:80
You can also copy the complete content from here:
Complete file using SolarEdge plugin
version: '3.3'
services:
teslamate:
image: teslamate/teslamate:latest
restart: always
environment:
- DATABASE_USER=teslamate
- DATABASE_PASS=secret ##You can change your password here
- DATABASE_NAME=teslamate
- DATABASE_HOST=database
- MQTT_HOST=mosquitto
- ENCRYPTION_KEY=supersecret ##You can change your encryption key here
- TZ=Europe/Berlin ##You can change your Timezone here
ports:
- 4000:4000
volumes:
- ./import:/opt/app/import
cap_drop:
- all
database:
image: postgres:13
restart: always
environment:
- POSTGRES_USER=teslamate
- POSTGRES_PASSWORD=secret ##You can change your password here
- POSTGRES_DB=teslamate
volumes:
- teslamate-db:/var/lib/postgresql/data
grafana:
image: teslamate/grafana:latest
restart: always
environment:
- DATABASE_USER=teslamate
- DATABASE_PASS=secret ##You can change your password here
- DATABASE_NAME=teslamate
- DATABASE_HOST=database
ports:
- 3100:3000
volumes:
- teslamate-grafana-data:/var/lib/grafana
mosquitto:
image: eclipse-mosquitto:2
restart: always
command: mosquitto -c /mosquitto-no-auth.conf
#ports:
# - 1883:1883
volumes:
- mosquitto-conf:/mosquitto/config
- mosquitto-data:/mosquitto/data
teslamateapi:
image: tobiasehlert/teslamateapi:latest
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
restart: always
depends_on:
- database
environment:
- DATABASE_USER=teslamate
- DATABASE_PASS=secret ##You can change your password here
- DATABASE_NAME=teslamate
- DATABASE_HOST=database
- MQTT_HOST=mosquitto
- TZ=Europe/Berlin ##You can change your Timezone here
- ENABLE_COMMANDS=true
- COMMANDS_ALL=true
- API_TOKEN_DISABLE=true
- ENCRYPTION_KEY=supersecret ##You can change your encryption key here
#ports:
# - 8080:8080
teslasolarcharger:
image: pkuehnel/teslasolarcharger:latest
container_name: teslasolarcharger
logging:
driver: "json-file"
options:
max-file: "10"
max-size: "100m"
restart: always
depends_on:
- teslamateapi
environment:
# - Serilog__MinimumLevel__Default=Verbose #uncomment this line and recreate container with docker-compose up -d for more detailed logs
- TZ=Europe/Berlin ##You can change your Timezone here
ports:
- 7190:80
volumes:
- teslasolarcharger-configs:/app/configs
solaredgeplugin:
image: pkuehnel/teslasolarchargersolaredgeplugin:latest
container_name: teslasolarcharger_solaredgeplugin
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
restart: always
environment:
- CloudUrl=https://monitoringapi.solaredge.com/site/1561056/currentPowerFlow.json?api_key=asdfasdfasdfasdfasdfasdf& ##Change your site ID and API Key here
- RefreshIntervalSeconds=360
ports:
- 7193:80
volumes:
teslamate-db:
teslamate-grafana-data:
mosquitto-conf:
mosquitto-data:
teslasolarcharger-configs:
You can also use the Modbus plugin. This is a general plugin, so don't be surprised if it does not work as expected right after starting up. Feel free to share your configurations here so I can add templates for future users.
To use the plugin, just add these lines to the bottom of your docker-compose.yml. Note: As some inverters struggle with too many requests within a specific time, you can change the RequestBlockMilliseconds environment variable.
modbusplugin:
image: pkuehnel/teslasolarchargermodbusplugin:latest
container_name: teslasolarcharger_modbusplugin
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
restart: always
environment:
- RequestBlockMilliseconds=0
ports:
- 7191:80
You can also copy the complete content from here:
Complete file using Modbus plugin
version: '3.3'
services:
teslamate:
image: teslamate/teslamate:latest
restart: always
environment:
- DATABASE_USER=teslamate
- DATABASE_PASS=secret ##You can change your password here
- DATABASE_NAME=teslamate
- DATABASE_HOST=database
- MQTT_HOST=mosquitto
- ENCRYPTION_KEY=supersecret ##You can change your encryption key here
- TZ=Europe/Berlin ##You can change your Timezone here
ports:
- 4000:4000
volumes:
- ./import:/opt/app/import
cap_drop:
- all
database:
image: postgres:13
restart: always
environment:
- POSTGRES_USER=teslamate
- POSTGRES_PASSWORD=secret ##You can change your password here
- POSTGRES_DB=teslamate
volumes:
- teslamate-db:/var/lib/postgresql/data
grafana:
image: teslamate/grafana:latest
restart: always
environment:
- DATABASE_USER=teslamate
- DATABASE_PASS=secret ##You can change your password here
- DATABASE_NAME=teslamate
- DATABASE_HOST=database
ports:
- 3100:3000
volumes:
- teslamate-grafana-data:/var/lib/grafana
mosquitto:
image: eclipse-mosquitto:2
restart: always
command: mosquitto -c /mosquitto-no-auth.conf
#ports:
# - 1883:1883
volumes:
- mosquitto-conf:/mosquitto/config
- mosquitto-data:/mosquitto/data
teslamateapi:
image: tobiasehlert/teslamateapi:latest
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
restart: always
depends_on:
- database
environment:
- DATABASE_USER=teslamate
- DATABASE_PASS=secret ##You can change your password here
- DATABASE_NAME=teslamate
- DATABASE_HOST=database
- MQTT_HOST=mosquitto
- TZ=Europe/Berlin ##You can change your Timezone here
- ENABLE_COMMANDS=true
- COMMANDS_ALL=true
- API_TOKEN_DISABLE=true
- ENCRYPTION_KEY=supersecret ##You can change your encryption key here
#ports:
# - 8080:8080
teslasolarcharger:
image: pkuehnel/teslasolarcharger:latest
container_name: teslasolarcharger
logging:
driver: "json-file"
options:
max-file: "10"
max-size: "100m"
restart: always
depends_on:
- teslamateapi
environment:
# - Serilog__MinimumLevel__Default=Verbose #uncomment this line and recreate container with docker-compose up -d for more detailed logs
- TZ=Europe/Berlin ##You can change your Timezone here
ports:
- 7190:80
volumes:
- teslasolarcharger-configs:/app/configs
modbusplugin:
image: pkuehnel/teslasolarchargermodbusplugin:latest
container_name: teslasolarcharger_modbusplugin
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
restart: always
environment:
- RequestBlockMilliseconds=0
ports:
- 7191:80
volumes:
teslamate-db:
teslamate-grafana-data:
mosquitto-conf:
mosquitto-data:
teslasolarcharger-configs:- Move to your above created directory with your
docker-compose.yml. - Start all containers using the command
docker-compose up -d. - Use a third-party app to create a new Tesla Token [Android] [iOS]
- Open your browser, go to
http://your-ip-address:4000and paste your token and refresh token into the form. - Go to
Geo-Fencesand add a Geo-Fence calledHomeat the location you want TeslaSolarCharger to be active. - Open
http://your-ip-address:7190 - Go to
Base Configuration(if you are on a mobile device, it is behind the menu button).
To let the TeslaSolarCharger know how much power there is to charge the car, you need to add a value in Grid Power Url.
Note: These values will be filled in automatically in a future release. Maybe it is already working, and I just forgot to remove this section ;-)
Depending on your used plugins, you have to paste one of the following URLs to the Grid Power Url field:
- SMA Plugin:
http://<IP of your Docker host>:7192/api/CurrentPower/GetPower - SolarEdge Plugin:
- Grid Power:
http://solaredgeplugin/api/CurrentValues/GetPowerToGrid - Inverter Power:
http://solaredgeplugin/api/CurrentValues/GetInverterPower - Home Battery SoC:
http://solaredgeplugin/api/CurrentValues/GetHomeBatterySoc - Home Battery Power:
http://solaredgeplugin/api/CurrentValues/GetHomeBatteryPower
- Grid Power:
Warning: As this plugin keeps an open connection to your inverter, it is highly recommended not to kill this container but always shut it down gracefully. To use the Modbus plugin, you must create the URL string yourself. The URL looks like this:
http://modbusplugin/api/Modbus/GetInt32Value?unitIdentifier=3&startingAddress=<modbusregisterAddress>&quantity=<NumberOFModbusRegistersToRead>&ipAddress=<IPAdressOfModbusDevice>&port=502&factor=<conversionFactor>&connectDelaySeconds=1&timeoutSeconds=10
An example URL with all values filled could look like this:
http://modbusplugin/api/Modbus/GetInt32Value?unitIdentifier=3&startingAddress=30775&quantity=2&ipAddress=192.168.1.28&port=502&factor=1&connectDelaySeconds=1&timeoutSeconds=10
You can test the result of the URL by pasting it into your browser and replacing modbusplugin with ipOfYourDockerHost:7091, e.g.:
http://192.168.1.50:7091/api/Modbus/GetInt32Value?unitIdentifier=3&startingAddress=30775&quantity=2&ipAddress=192.168.1.28&port=502&factor=1&connectDelaySeconds=1&timeoutSeconds=10
What the values mean:
unitIdentifier: Internal ID of your inverter (in most cases, 3)startingAddress: Register address of the value you want to extract. You will find this value in the documentation of your inverter.quantity: Number of registers to read from (for integer values should be 2)ipAddress: IP Address of your inverterport: Modbus TCP Port of your inverter (default: 502)factor: Factor to multiply the resulting value with. The result should be Watt, so if your inverter returns Watt, you can leave 1. If your inverter returns 0.1W, you have to use 10.connectDelaySeconds: Delay before communication the first time (you should use 1)timeoutSeconds: Timeout until returning an error if the inverter is not responding (you should use 10)
For more convenience, you can go to http://your-ip-address:7091/swagger. There you can try your values with a user interface.
If you have your own API or your energymeter directly has a REST API, you can also use these to get the grid power. Just insert the Grid Power Url Url; if there is a plain integer value, it should work. If your API returns JSON or XML results, you must add the exact path to that specific value.
If you have the following JSON result:
{
"request": {
"method": "get",
"key": "asdf"
},
"code": 0,
"type": "call",
"data": {
"value": 14
}
}You can use $.data.value as Grid Power Json Pattern.
If your energy monitoring device or inverter has no JSON, but an XML API, use the following instructions: Given an API endpoint http://192.168.xxx.xxx/measurements.xml which returns the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<Device Name="PIKO 4.6-2 MP plus" Type="Inverter" Platform="Net16" HmiPlatform="HMI17" NominalPower="4600" UserPowerLimit="nan" CountryPowerLimit="nan" Serial="XXXXXXXXXXXXXXXXXXXX" OEMSerial="XXXXXXXX" BusAddress="1" NetBiosName="XXXXXXXXXXXXXXX" WebPortal="PIKO Solar Portal" ManufacturerURL="kostal-solar-electric.com" IpAddress="192.168.XXX.XXX" DateTime="2022-06-08T19:33:25" MilliSeconds="806">
<Measurements>
<Measurement Value="231.3" Unit="V" Type="AC_Voltage"/>
<Measurement Value="1.132" Unit="A" Type="AC_Current"/>
<Measurement Value="256.1" Unit="W" Type="AC_Power"/>
<Measurement Value="264.3" Unit="W" Type="AC_Power_fast"/>
<Measurement Value="49.992" Unit="Hz" Type="AC_Frequency"/>
<Measurement Value="474.2" Unit="V" Type="DC_Voltage"/>
<Measurement Value="0.594" Unit="A" Type="DC_Current"/>
<Measurement Value="473.5" Unit="V" Type="LINK_Voltage"/>
<Measurement Value="18.7" Unit="W" Type="GridPower"/>
<Measurement Value="0.0" Unit="W" Type="GridConsumedPower"/>
<Measurement Value="18.7" Unit="W" Type="GridInjectedPower"/>
<Measurement Value="237.3" Unit="W" Type="OwnConsumedPower"/>
<Measurement Value="100.0" Unit="%" Type="Derating"/>
</Measurements>
</Device>Grid Power:
Assuming the Measurement node with Type GridPower is the power your house feeds to the grid, you need the following values in your Base configuration:
- CurrentPowerToGridUrl=http://192.168.xxx.xxx/measurements.xml
- CurrentPowerToGridXmlPattern=Device/Measurements/Measurement
- CurrentPowerToGridXmlAttributeHeaderName=Type
- CurrentPowerToGridXmlAttributeHeaderValue=GridPower
- CurrentPowerToGridXmlAttributeValueName=ValueInverter Power:
Assuming the Measurement node with Type AC_Power is the power your inverter is currently feeding, you can use the following values in your Base configuration:
- CurrentInverterPowerUrl=http://192.168.xxx.xxx/measurements.xml
- CurrentInverterPowerXmlPattern=Device/Measurements/Measurement
- CurrentInverterPowerAttributeHeaderName=Type
- CurrentInverterPowerAttributeHeaderValue=AC_Power
- CurrentInverterPowerAttributeValueName=ValueNote: These values are not needed. They are just used to show additional information.
When you are at this point, your car connected to any charging cable in your set home area should start charging based on solar power. But there are a few additional settings that are maybe helpful for your environment:
If you have more than one car (or your car does not have ID 1), you can change this setting in the Car Ids form field separated by |. Note: The order of the IDs is the order of power distribution.
If you set PowerBuffer to a value different from 0, the system uses the value as an offset. E.g., If you set 1000, the car's current is reduced as long as less than 1000 Watt power goes to the grid.
To configure your home battery, you need to add the following settings:
- URL for getting the state of charge
- URL for getting current charging/discharging power
- Home Battery Minimum SoC
- Home Battery Charging Power
After setting everything up, your overview page should look like this:
Note: If your battery is discharging, the power should be displayed in red. If the battery is charging, the power should be displayed in green. If this is the other way around, you must update the Correction Factor below your HomeBatteryPower Url setting and invert it to a negative number, e.g. -1.0.
If you use this feature in combination with the SolarEdge plugin, the URLs are:
http://solaredgeplugin/api/CurrentValues/GetHomeBatterySochttp://solaredgeplugin/api/CurrentValues/GetHomeBatteryPower
After setting everything up, you can use the software via http://your-ip-address:7190.
Currently, there are three different charge modes available:
- PV only: Only solar energy is used to charge. You can set a SOC level which should be reached at a specific date and time. If solar power is not enough to reach the set soc level in time, the car starts charging at full speed. Note: To let this work, you must specify
usable kWhin the car settings section. - Maximum Power: The car charges with the maximum available power
- Min SoC + PV: If plugged in, the car starts charging with maximum power until the set Min SoC is reached. After that, only PV Power is used to charge the car.
To generate logfiles, you must write each container's logs to a separate logfile.
Note: To create a more detailed logfile, you must add - Serilog__MinimumLevel__Default=Verbose as environment variable.
The commands if you used the docker-compose.yml files from above:
For the main TeslaSolarCharger container:
docker logs teslasolarcharger > teslasolarcharger.logFor the SmaPlugin:
docker logs teslasolarcharger_smaplugin > teslasolarcharger_smaplugin.logFor the SolaredgePlugin:
docker logs teslasolarcharger_solaredgeplugin > teslasolarcharger_solaredgeplugin.logFor the ModbusPlugin:
docker logs teslasolarcharger_modbusplugin > teslasolarcharger_modbusplugin.logIf you get an error like Error: No such container: you can look up the containernames with
docker ps