Skip to content

Commit

Permalink
added inverter_scan script
Browse files Browse the repository at this point in the history
  • Loading branch information
gustonator committed Feb 4, 2023
1 parent b82e76b commit a816fb4
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ tested on models:
GoodWe GW10K-ET
</br>

info:
It has been reported to work on GoodWe ET, EH, BT, BH, ES, EM, BP, DT, MS, D-NS, and XS families of inverters. It may work on other inverters as well, as long as they listen on UDP port 8899 and respond to one of supported communication protocols.
The inverters communicate via UDP protocol, by default running on port 8899. They use a native 'AA55' protocol and (some models) ModBus protocol. ET inverters support both protocols, some inverters may not support both of them.

(If you can't communicate with the inverter despite your model is listed above, it is possible you have old ARM firmware version. You should ask manufacturer support to upgrade your ARM firmware (not just inverter firmware) to be able to communicate with the inveter via UDP.)

more info about the python goodwe library: https://github.com/marcelblijleven/goodwe

</br>

## For standalone installation:

Expand Down
66 changes: 66 additions & 0 deletions inverter_scan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""Simple test script to scan inverter present on local network"""
import asyncio
import binascii
import logging
import sys

import goodwe
from goodwe.exceptions import InverterError
from goodwe.protocol import ProtocolCommand

logging.basicConfig(
format="%(asctime)-15s %(funcName)s(%(lineno)d) - %(levelname)s: %(message)s",
stream=sys.stderr,
level=getattr(logging, "DEBUG", None),
)


def try_command(command, ip):
print(f"Trying command: {command}")
try:
response = asyncio.run(ProtocolCommand(bytes.fromhex(command), lambda x: True).execute(result[0]))
print(f"Response to {command} command: {response.hex()}")
except InverterError as err:
print(f"No response to {command} command")


def omnik_command(logger_sn):
# frame = (headCode) + (dataFieldLength) + (contrlCode) + (sn) + (sn) + (command) + (checksum) + (endCode)
frame_hdr = binascii.unhexlify('680241b1') # from SolarMan / new Omnik app
command = binascii.unhexlify('0100')
defchk = binascii.unhexlify('87')
endCode = binascii.unhexlify('16')

# tar = bytearray.fromhex(hex(logger_sn)[8:10] + hex(logger_sn)[6:8] + hex(logger_sn)[4:6] + hex(logger_sn)[2:4])
# frame = bytearray(frame_hdr + tar + tar + command + defchk + endCode)
frame = bytearray(frame_hdr + binascii.unhexlify(logger_sn) + command + defchk + endCode)

checksum = 0
frame_bytes = bytearray(frame)
for i in range(1, len(frame_bytes) - 2, 1):
checksum += frame_bytes[i] & 255
frame_bytes[len(frame_bytes) - 2] = int((checksum & 255))
return frame_bytes.hex()


result = asyncio.run(goodwe.search_inverters()).decode("utf-8").split(",")
print(f"Located inverter at IP: {result[0]}, mac: {result[1]}, name: {result[2]}")

# EM/ES
try_command("AA55C07F0102000241", result[0])
# DT (SolarGo)
try_command("7F03753100280409", result[0])
# Omnik v5 ?
try_command("197d0001000dff045e50303036564657f6e60d", result[0])
# Omnik 4 ?
sn = bytes(result[2][10:], 'utf-8').hex()
try_command(omnik_command(sn), result[0])
# Omnik 4 reversed ?
sn = "".join(reversed([sn[i:i + 2] for i in range(0, len(sn), 2)]))
try_command(omnik_command(sn), result[0])

print(f"Identifying inverter at IP: {result[0]}")
inverter = asyncio.run(goodwe.discover(result[0]))
print(
f"Identified inverter model: {inverter.model_name}, serialNr: {inverter.serial_number}"
)

0 comments on commit a816fb4

Please sign in to comment.