Solax X3 Hybrid G1/G2 support #21802
-
After facing some initial challenges - apparently the X3 Hybrid G1/G2 inverter only accepts ONE modbus connection at a time - evcc is able to connect and talk to my inverter. Unfortunately without much success.
My assumption is that this is not working because G3/G4 models speak a different protocol? At a quick glance the registers defined in https://github.com/evcc-io/evcc/blob/master/templates/definition/meter/solax.yaml pretty much match what I am reading out using my own tooling for influxdb. So I am wondering where the incompatibility comes from? Does anyone know? What would I presumably need to do to add G1/G2 support? Are there any other solutions G1/G2 users typically consider? |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 2 replies
-
This is apparently not modbus. Somebody will have to find out what it actually is. |
Beta Was this translation helpful? Give feedback.
-
I think it is modbus. Probably it's the lsb/msb magic I am applying after reading out the registers? using inverter.data.common;
using inverter.data.common.exceptions;
using inverter.data.common.models;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NModbus;
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace inverter.data.solaxpower
{
public class SolaxX3HybridInverter : IInverter, IDisposable
{
private readonly ILogger<SolaxX3HybridInverter> _logger;
private readonly SolaxX3HybridInverterOptions _options;
private readonly TcpClient _tcpClient;
private readonly IModbusMaster _modbusMaster;
private bool disposedValue;
public SolaxX3HybridInverter(ILogger<SolaxX3HybridInverter> logger, IOptions<SolaxX3HybridInverterOptions> options)
{
_logger = logger;
_options = options.Value;
if (options?.Value == null) throw new ConfigurationException("SolaxX3HybridInverter configuration is missing.");
_tcpClient = new TcpClient(_options.Host, _options.Port);
_tcpClient.ReceiveTimeout = 5000;
_tcpClient.SendTimeout = 5000;
ModbusFactory factory = new ModbusFactory();
_modbusMaster = factory.CreateMaster(_tcpClient);
}
#region -- dispose pattern --
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
_modbusMaster?.Dispose();
_tcpClient?.Close();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
#endregion
// public async Task<BatteryInfo> GetBatteryInfoAsync() { ... }
// public async Task<DateTime> GetDateTimeAsync() { ... }
// public async Task<GridInfo> GetGridInfoAsync() { ... }
// public async Task<SolarInfo> GetSolarInfoAsync() { ... }
public async Task<FeedInInfo> GetFeedInInfoAsync()
{
ushort[] powerToTheGrid = await _modbusMaster.ReadInputRegistersAsync(0, 0x0046, 6);
FeedInInfo feedInInfo = new()
{
PowerToTheGrid = UShortArrayToInt32(powerToTheGrid[0], powerToTheGrid[1]),
EnergyToTheGrid = UShortArrayToUInt32(powerToTheGrid[2], powerToTheGrid[3]) / 100,
EnergyFromTheGrid = UShortArrayToUInt32(powerToTheGrid[4], powerToTheGrid[5]) / 100,
};
return feedInInfo;
}
private static int UShortArrayToInt32(ushort lsb, ushort msb)
{
ushort[] received = new ushort[] { lsb, msb };
byte[] asByte = new byte[4];
Buffer.BlockCopy(received, 0, asByte, 0, 4);
return BitConverter.ToInt32(asByte, 0);
}
private static uint UShortArrayToUInt32(ushort lsb, ushort msb)
{
ushort[] received = new ushort[] { lsb, msb };
byte[] asByte = new byte[4];
Buffer.BlockCopy(received, 0, asByte, 0, 4);
return BitConverter.ToUInt32(asByte, 0);
}
}
} |
Beta Was this translation helpful? Give feedback.
-
Did you get TCP/RTU wrong?
The error has nothing to do with that. |
Beta Was this translation helpful? Give feedback.
-
Hmmm I went with |
Beta Was this translation helpful? Give feedback.
-
Ok. This wasn't obvious to me.
Turns out Ethernet-RS485 Adapter is the wrong choice even though it's Modbus over Ethernet.
No errors...! Good! |
Beta Was this translation helpful? Give feedback.
Ok. This wasn't obvious to me.
These are the options the configure script provides:
Turns out Ethernet-RS485 Adapter is the wrong choice even though it's Modbus over Ethernet.
Anyway... choose TCP/IP. It still assumes modbus over TCP and asks for modbus ID and so on.