I would like to integrate my Kostal Plenticore Plus solar inverter with HA.
Basically I would just like to read consumption stats.
I found this openHab binding:
Have you seen something similar for HA?
Bo
I would like to integrate my Kostal Plenticore Plus solar inverter with HA.
Basically I would just like to read consumption stats.
I found this openHab binding:
Have you seen something similar for HA?
Bo
Hi Bo,
Im trying to program a component at the moment. But im struggling with the authentication.
The API is very strange (and not documented)
You can access the API like this:
http : / /-IP-/api/v1/
200 lines of code just for the authentication, jesus
Could be the complicatest Auth for a web API i’ve seen so far… Maybe polling the values via Modbus is easier.
I think the way to go is really just getting the data via Modbus. Problem here: I’m struggling with reading the first value at all…
modbus:
- type: tcp
host: 192.168.1.11
port: 502
name: energy_meter
- type: tcp
host: 192.168.1.22
port: 1502
name: inverter
sensor:
- platform: modbus
scan_interval: 1
registers:
- name: Aktueller_Verbrauch
hub: energy_meter
unit_of_measurement: W
slave: 1
register: 0
count: 2
scale: 0.1
- platform: modbus
scan_interval: 1
registers:
- name: Total_DC_power
hub: inverter
unit_of_measurement: W
slave: 71
register: 100
count: 2
#reverse_order: true
#scale: 0.1
data_type: float
The Energy Meter works. The inverter doesn’t. It shows some value but that is garbage. I tried to reverse or only read one, doesn’t help.
I found a python script in some PV forum which works very good in reading the values via Modbus though:
Documentation from Kostal regarding the registers:
I found another working implementation - ioBroker this time. I use that one now to publish to MQTT and read it from Home Assistant. If anyone is able to develop are Plugin for HA, here is the sourcecode:
This time “only” 100 lines for authentication:
function login() {
let nonce = KOSTAL.getNonce();
let payload = {
username: 'user',
nonce: nonce
};
apiCall('POST', 'auth/start', payload, function(body, code, headers) {
if(code !== 200) {
adapter.log.warn('Login failed with code ' + code + ': ' + body);
return;
}
var json = JSON.parse(body);
if(!json.nonce) {
adapter.log.warn('No nonce in json reply to start: ' + body);
return;
}
var mainTransactionId = json.transactionId;
var serverNonce = json.nonce;
var salt = json.salt;
var hashRounds = parseInt(json.rounds);
var r = KOSTAL.pbkdf2(devicePassword, KOSTAL.base64.toBits(salt), hashRounds);
var sKey = new KOSTAL.hash.hmac(r, KOSTAL.hash.sha256).mac('Client Key');
var cKey = new KOSTAL.hash.hmac(r, KOSTAL.hash.sha256).mac('Server Key');
var sHash = KOSTAL.hash.sha256.hash(sKey);
var hashString = 'n=user,r=' + nonce + ',r=' + serverNonce + ',s=' + salt + ',i=' + hashRounds + ',c=biws,r=' + serverNonce;
var sHmac = new KOSTAL.hash.hmac(sHash, KOSTAL.hash.sha256).mac(hashString);
var cHmac = new KOSTAL.hash.hmac(cKey, KOSTAL.hash.sha256).mac(hashString);
var proof = sKey.map(function(l, n) {
return l ^ sHmac[n];
});
var payload = {
transactionId: mainTransactionId,
proof: KOSTAL.base64.fromBits(proof)
};
apiCall('POST', 'auth/finish', payload, function(body, code, headers) {
if(code !== 200) {
adapter.log.warn('auth/finish failed with code ' + code + ': ' + body);
return;
}
var json = JSON.parse(body);
if(!json.token) {
adapter.log.warn('No nonce in json reply to finish: ' + body);
return;
}
var bitSignature = KOSTAL.base64.toBits(json.signature);
if(!KOSTAL.bitArray.equal(bitSignature, cHmac)) {
adapter.log.warn('Signature verification failed!');
return;
}
var hashHmac = new KOSTAL.hash.hmac(sHash, KOSTAL.hash.sha256);
hashHmac.update('Session Key');
hashHmac.update(hashString);
hashHmac.update(sKey);
var digest = hashHmac.digest();
json.protocol_key = digest;
json.transactionId = mainTransactionId;
var pkey = json.protocol_key,
tok = json.token,
transId = json.transactionId,
encToken = KOSTAL.encrypt(pkey, tok);
var iv = encToken.iv,
tag = encToken.tag,
ciph = encToken.ciphertext,
payload = {
transactionId: transId,
iv: KOSTAL.base64.fromBits(iv),
tag: KOSTAL.base64.fromBits(tag),
payload: KOSTAL.base64.fromBits(ciph)
};
apiCall('POST', 'auth/create_session', payload, function(body, code, headers) {
if(code !== 200) {
adapter.log.warn('auth/create_session failed with code ' + code + ': ' + body);
return;
}
var json = JSON.parse(body);
if(!json.sessionId) {
adapter.log.warn('No session id in json reply to create session: ' + body);
return;
}
loginSessionId = json.sessionId;
adapter.log.debug('Session id is ' + loginSessionId);
loginSuccess();
});
});
});
}
Hello Lukas,
I saw that you started a git repo. I am interested as well. If you need some support in testing or others things that do not require the full dev environment please let me know. My Kostal plenticore should be installed end of March.
Great work here at hassio!
Greetings,
Sebastian
Hi Sebastian,
yes I created a simple component. But its not finished at all.
I can upload it to my github this evening
Greetings,
Lukas
Hi Lukas,
great. I will have a look at it. Are there beginners/Routine parts I could support in?
Greetings,
Sebastian
The following things are missing in my opinion:
Optional:
I would be happy if someone would help me with it.
Is there something we can reuse from the Fronius or SMA implementation?
I am still a bloody beginner in hassio. What I recognized is that both go with async. I am currently getting myself aquainted with the classes and methods hoping that I can contribute.
yes, those are good examples. As far as I know is not necessary to do it with async (I have no experience with it). I have read some part of the dev docs now and I think the easiest way to get it as dynamic and functional as possible is to just add a for loop to the setup_platform function and loop through the parameters witch we can read from the configuration.yml.
Wow that looks good - well done
Great job. You should add a “send me a beer” Button in GitHub
Any further steps to make it a git loadable package? I will definitely try when the kostal system is installed.
I want to add it to home assistant as an official component. I even created a pull request and noticed afterwards it does not work as perfect as is thought An closed it again
Things I noticed:
Maybe we can add it to HACs until its fixed
https://github.com/ITTV-tools/homeassistant-kostalplenticore -> Integration
It is now possible to add it to HACs
I added two more sensor in the new Version:
The values are negative if the energy is going out of the inverter and positive if it goes inside.