Forum
Pánové (a dámy), nemáte prosím někdo hotovou integraci EV chargeru od Solaxu s Loxone? Chystám se na přechod na SPOT a chci mít možnost říct chargeru, kdy má začít/skončit s dobíjením.
Solax EV charger už nenabízí MODBUS TCP/IP. Ale HomeAssitent to umí ovládat přes local HTTP API, což považuji za rovnocenné (pozor, nikoliv cloud HTTP API, ale local HTTP API).
Dříve než se ponořím do střev toho HomeAssitantu, neudělal to prosím už někdo přede mnou? Asi nejsem první, kdo chce podle SPOTu řídit dobíjení auta s Loxonem a má na to EV Charger od Solaxu.
Děkuju za rady!
Pracoval jsem pouze s local API střídačů. Mrkni zde: https://github.com/nazar-pc/solax-local-api-docs
EV charger je tam zmíněný také.
Pánové (a dámy), nemáte prosím někdo hotovou integraci EV chargeru od Solaxu s Loxone? Chystám se na přechod na SPOT a chci mít možnost říct chargeru, kdy má začít/skončit s dobíjením.
Solax EV charger už nenabízí MODBUS TCP/IP. Ale HomeAssitent to umí ovládat přes local HTTP API, což považuji za rovnocenné (pozor, nikoliv cloud HTTP API, ale local HTTP API).Dříve než se ponořím do střev toho HomeAssitantu, neudělal to prosím už někdo přede mnou? Asi nejsem první, kdo chce podle SPOTu řídit dobíjení auta s Loxonem a má na to EV Charger od Solaxu.
Děkuju za rady!
neni to tohle?
https://github.com/nazar-pc/solax-local-api-docs
Částečně jo. Přes POST ReadRealTimeData si lze vyčíst data a dekódovat podle tabulky. Ale jednak se mi (zatím) nepodařil udělat z Loxone ani ten POST (resp. podařil, přes HTTP výstup, ale nevím, kde mám tu odpověď serveru) a jednak bych potřeboval poslat příkaz - říct tomu teď si nastav mód dobíjení FAST a začni dobíjet atp.
To se (asi) dělá přes POST optType=ReadSetData, ale (zatím) nevím, jaké data tam mám poslat.
Zrovna jsem do toho ponořený...
@rpav Ano, aby ses dostal k odpovědi na HTTP dotaz, musíš v nastavení vistuálního výstupu zaškrtnout "Uložit HTTP odpověď". Problém je, že potom se každá odpověď ukládá na SD kartu. Proto jsem to řešil pomocí jednoduchého PicoC prográmku.
@radeg
A podělil by ses pls o ten PicoC prográmek a návod, jak s tím pracovat? Počítám, že to bude zajímavé i pro ostatní tady na fóru. Předem díky, 👍
Odpovím sám sobě 😉
Ale může se to hodit pro ostatní, kteří se budou potýkat s integrací Solax EV Chargeru tak, jako já.
Blbá zpráva je, že od jakési verze neumí Solax EVC TCP/IP modbus. Nevím, proč to čímani vypnuli, ale vypnuli to 🙁
Dobrá zpráva je, že na tom EV Chargeru je lokální HTTP API a dle toho, co je implementované v HomeAssistentu se s tím dají nastavovat registry stejně, jako s TCP/IP modbusem.
Základní info z EV Chargeru se dá získat takto:
curl -d "?optType=ReadRealTimeData&pwd=HESLO" -X POST http://IP_ADRESA_CHARGERU
Ten post vrátí něco jako:
{"SN":"XXXXXXXXXX","ver":"3.007.04","type":1,"Data":[3,0,23805,23049,23593,0,0,0,0,0,0,0,0,0,5554,0,65479,61,65471,11,65515,65530,0,0,20,0,1,13,0,0,0,0,0,5004,5002,5000,6956,7185,6155,4,0,0,0,0,0,0,0,0,1,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3338,7185,6155,0,1,2,1,0,0,120,889,100,120,50],"Information":[22.000,1,"C32203K3368150",1,1.12,1.01,0.00,0.00,0.00,1],"OCPPServer":"","OCPPChargerId":"","QRContent":""}
No a když to přepársujeme (doufám, že s PicoC prográmkem od @radeg to dáme), tak zjistíme stav Chargeru.
Jednotlivé registry se nastavují takto:
curl -d 'optType=setReg&pwd=HESLO&data={"num":1,"Data":[{"reg":60D,"val":"6"}]}' -X POST http://IP_ADRESA_CHARGERU
Přišlo mi už jednoduché opsat čísla registrů a možné hodnoty z HomeAssitenta, tady:
https://github.com/wills106/homeassistant-solax-modbus/blob/main/custom_components/solax_modbus/plugin_solax_ev_charger.py
Jenže ouha! Když chci například nastavit registr 0x60D na hodnotu 3 (neboli přepnout charger use mode na "green"), tak ten curl nedopadne dobře:
curl -d 'optType=setReg&pwd=HESLO&data={"num":1,"Data":[{"reg":60D,"val":"3"}]}' -X POST http://IP_ADRESA_CHARGERU
vrátí to:
0:code,message:"failed"}
A nevím proč 🙁
Podotýkám, že HomeAssistenta nemám, jen jsem koukal do toho jejich kódu na GitHubu a tak buď se blbě dívám nebo jsem někde udělal chybně úvahu anebo s mojí verzí firmware to možná nejede.
@rpav Následující kód běží se Solax X3 Mic. Pro jiné střídače (a obvzlášt EV Charger) bude potřeba upravit.
// write program here in PicoC
char buffer[1024];
char *bufPtr;
int read_bytes;
unsigned int low, high;
float GridAPower, GridBPower, GridCPower, PowerDc1, PowerDc2, PowerDc3, RunMode, Yield_Total, Yield_Today, feedInPower, FeedInEnergy, ConsumeEnergy;
float convertSigned16 (unsigned int low16)
{
float retVal;
low16 &= 0xFFFF;
if (low16 < 0x8000)
{
retVal = (float) low16;
}
else
{
retVal = (float) (low16 - 0xFFFF);
}
return retVal;
}
float convertUnsigned32 (unsigned int low16, unsigned int high16)
{
unsigned int tmp;
low16 &= 0xFFFF;
high16 &= 0xFFFF;
tmp = (high16 << 16) + low16;
return (float) tmp;
}
float convertSigned32 (unsigned int low16, unsigned int high16)
{
float retVal;
unsigned int tmp;
low16 &= 0xFFFF;
high16 &= 0xFFFF;
tmp = (high16 << 16) + low16;
if (tmp < 0x80000000)
{
retVal = (float) tmp;
}
else
{
retVal = (float) (tmp - 0xFFFFFFFF);
}
return retVal;
}
STREAM* pTcpStream;
char* pTcpCmd = "POST / HTTP/1.1\r\nHost: 192.168.1.XX\r\nUser-Agent: [en]\r\nContent-Length: 39\r\nContent-Type: text/plain; charset=utf-8\r\nConnection: close\r\n\r\noptType=ReadRealTimeData&pwd=SRxxxxxxxx";
while (TRUE)
{
GridAPower = 0;
GridBPower = 0;
GridCPower = 0;
PowerDc1 = 0;
PowerDc2 = 0;
PowerDc3 = 0;
RunMode = 0;
Yield_Total = 0;
Yield_Today = 0;
feedInPower = 0;
FeedInEnergy = 0;
ConsumeEnergy = 0;
read_bytes = 0;
buffer[0] = 0;
pTcpStream = stream_create("/dev/tcp/192.168.1.XX/80",0,0);
if (pTcpStream != NULL)
{
stream_write(pTcpStream, pTcpCmd, strlen(pTcpCmd));
stream_flush(pTcpStream);
sleep (1000);
read_bytes = stream_read(pTcpStream, buffer, 1024, 200);
stream_close (pTcpStream);
}
if (read_bytes != 0)
{
bufPtr = strstrskip(buffer, "\"Data\":[");
for (int numberIndex = 0; numberIndex < 79; numberIndex++)
{
if (bufPtr == NULL)
{
break;
}
switch (numberIndex)
{
case 6: //GridAPower
low = (unsigned int) atoi (bufPtr);
GridAPower = convertSigned16 (low);
GridAPower /= 1000;
break;
case 7: //GridBPower
low = (unsigned int) atoi (bufPtr);
GridBPower = convertSigned16 (low);
GridBPower /= 1000;
break;
case 8: //GridCPower
low = (unsigned int) atoi (bufPtr);
GridCPower = convertSigned16 (low);
GridCPower /= 1000;
break;
case 15: //PowerDc1
PowerDc1 = (float)((unsigned int) atoi(bufPtr));
PowerDc1 /= 1000;
break;
case 16: //PowerDc2
PowerDc2 = (float)((unsigned int) atoi(bufPtr));
PowerDc2 /= 1000;
break;
case 17: //PowerDc3
PowerDc3 = (float)((unsigned int) atoi(bufPtr));
PowerDc3 /= 1000;
break;
case 21: // RunMode
RunMode = (float)((unsigned int) atoi(bufPtr));
break;
case 22: // Yield_Total
low = (unsigned int) atoi(bufPtr);
break;
case 23: // Yield_Total
high = (unsigned int) atoi(bufPtr);
Yield_Total = convertUnsigned32 (low, high);
Yield_Total /= 10;
break;
case 24: // Yield_Today
Yield_Today = (float)((unsigned int) atoi(bufPtr));
Yield_Today /= 10;
break;
case 72: // feedInPower
low = (unsigned int) atoi(bufPtr);
break;
case 73: // feedInPower
high = (unsigned int) atoi(bufPtr);
feedInPower = convertSigned32 (low, high);
feedInPower /= -1000;
break;
case 74: // FeedInEnergy
low = (unsigned int) atoi(bufPtr);
break;
case 75: // FeedInEnergy
high = (unsigned int) atoi(bufPtr);
FeedInEnergy = convertUnsigned32 (low, high);
FeedInEnergy /= 100;
break;
case 76: // ConsumeEnergy
low = (unsigned int) atoi(bufPtr);
break;
case 77: // ConsumeEnergy
high = (unsigned int) atoi(bufPtr);
ConsumeEnergy = convertUnsigned32 (low, high);
ConsumeEnergy /= 100;
break;
default:
low = 0;
high = 0;
break;
}
bufPtr = index(bufPtr, ',');
if (bufPtr == NULL)
{
break;
}
bufPtr ++;
}
}
setoutput(0, GridAPower);
setoutput(1, GridBPower);
setoutput(2, GridCPower);
setoutput(3, PowerDc1);
setoutput(4, PowerDc2);
setoutput(5, PowerDc3);
setoutput(6, RunMode);
setoutput(7, Yield_Total);
setoutput(8, Yield_Today);
setoutput(9, feedInPower);
setoutput(10, FeedInEnergy);
setoutput(11, ConsumeEnergy);
setoutput(13, read_bytes);
setoutputtext(0, buffer);
sleeps(5);
}
@radeg
Díky moc! Moc hezký 👍
Mám ještě dva dotazy:
Fakt je možné z bloku Program mít jen 13 výstupů? Ten charger vrací v datech 29 údajů a nevím, zda se mi to podaří seškrtat na 13 nejzajímavějších. Jestli jsem to pochopil správně, tak budu muset, protože to víc jak 13 výstupů neumí 🙁
Jak moc je ten interpret PicoC robustní? Všude v dokumentaci se píše, jak je o chatrný, ladící prostředky jsou mizerný (vlastně nejsou skoro žádný), tak jestli si mám nejprve udělat zálohu SDkarty nebo se mohu spolehnout, že se z nějaké té chyby probere ??
Program se spustí první změnou stavu na I1? Nebo po restartu Miniserveru?
Díky ta rady!
Podařilo se tady někomu implementovat Solax Wallbox do Loxone?
Mám Wallbox X3-22 a asi nefunguje modbus tcp. Miniserver nedokáže načíst.
Jak máte řešeno ovládaní, zda vůbec máte? Jaký protokol?
@radeg Podařilo se mi pochopit strukturu pro Solax
EV Charger. Upravil jsem si odpovídajícím způsobem program v PicoC pro první hodnoty.
Co se mi však stalo je, že program proběhl jednou a dále se výstupy v loopu while(TRUE) neaktualizují.
Máte prosím nějakou zkušenost s chováním PicoC v 16.1.11.6 ?
Jen bacha, nový firmware LAN+WIFi dongelu již nemá todle local HTTP API. Firmwary k dalším zařízením budou následovat.
