Hi @SnokxStefan - What do you want to do with the Smappee Charger? As in what are you trying to control from HA and what will drive the automation?
I control my Smappee charger via an appdaemon “app” (to put only solar surplus in to the car and a few other modes of operation). I use OCPP to control sessions and just needed this for adjusting current as Smappee have not implemented current control in OCPP.
I have stripped it back a lot here for you to see just the smappee token and charger operation. However, this is defintely getting in to python programming to make it do something useful.
I tried to make the token generation and the use of token work via REST commands but in the end they were just too problematic (getting and saving and then using the bearer token) so I went the appdaemon path.
apps.yaml
smappee_charger_control:
module: smappee_charger_control
class: ChargerControl
#Secrets......
username: "UUUUUUUU"
password: "PPPPPPPP"
client_id: "IIIIIIII"
client_secret: "SSSSSSS"
smappee_charger_control.py
import appdaemon.plugins.hass.hassapi as hass
import requests
import datetime as dt
from functools import wraps
#
# Smappee Smart Charging
# An AppDaemon App for controlling a smappee charger (via API)
#
# This was very customised to my house and emissions goals....
# Stripped back here
class ChargerControl(hass.Hass):
def initialize(self):
self.log("ChargerControl initialisation begins")
self.access_token = None
self.refresh_token = None
self.token_expiration_time = None
self.run_in( self.fetch_token, 0 ) #Get straight away and ever day (implement refresh one day.....)
self.run_every(self.fetch_token, self.datetime(), 23*60*60)
self.run_in(self.adjust_charger, 2)
self.run_every(self.adjust_charger, self.datetime(), 60) #Update current every minute
self.log("ChargerControl initialisation completes")
def fetch_token(self, kwargs):
login_url = "https://farm1pub.smappee.net/dev/v3/oauth2/token"
data = {
"grant_type": "password",
"client_id": self.args["client_id"],
"client_secret": self.args["client_secret"],
"username": self.args["username"],
"password": self.args["password"]
}
r = requests.post(login_url, data=data)
r.raise_for_status()
j = r.json()
self.access_token = j['access_token']
self.refresh_token = j['refresh_token']
self._set_token_expiration_time(expires_in=j['expires_in'])
self.log("sensor.smappee_token: {}".format( self.access_token ))
self.log("sensor.smappee_refresh_token: {}".format( self.refresh_token ))
return r
def adjust_charger(self, kwargs):
self.log("adjust_charger begin")
headers = {
'Authorization': "Bearer {}".format( self.access_token),
'Content-Type': 'application/json'
}
current_amps = 6 #minimum
#I have a lot more logic to control what the current should be based on solar, battery and load
json_dict = {
'mode':"NORMAL",
'limit':{"unit": "AMPERE","value": current_amps},
}
r = requests.put('https://app1pub.smappee.net/dev/v3/chargingstations/MY_CHARGER_ID/connectors/1/mode', json = json_dict, headers = headers)
if r.status_code != 200:
self.log("Not OK status code: {}".format(r.status_code))
self.log("Charger current set to {} amps".format(current_amps) )
return r
def _set_token_expiration_time(self, expires_in):
"""
Saves the token expiration time by adding the 'expires in' parameter
to the current datetime (in utc).
"""
self.token_expiration_time = dt.datetime.utcnow() + \
dt.timedelta(0, expires_in) # timedelta(days, seconds)
Let me know your thoughts/plans. I am happy to give some guidance and to tidy up my appdaemon app if it is useful.
Cheers,
Brody