add support for dtu/inverter version

This commit is contained in:
suaveolent 2024-02-06 16:35:33 +01:00
parent 22c1ef183f
commit e2b6d6709f
6 changed files with 88 additions and 14 deletions

View File

@ -1,6 +1,13 @@
import argparse
from hoymiles_wifi.inverter import Inverter
from hoymiles_wifi.utils import (
generate_version_string,
generate_sw_version_string,
generate_dtu_version_string
)
# Inverter commands
def get_real_data_new(inverter):
return inverter.get_real_data_new()
@ -111,6 +118,17 @@ def turn_on(inverter):
return inverter.turn_on()
def get_information_data(inverter):
return inverter.get_information_data()
def get_version_info(inverter):
response = app_information_data(inverter)
return {
"dtu_hw_version": "H" + generate_dtu_version_string(response.dtu_info.dtu_hw_version),
"dtu_sw_version": "V" + generate_dtu_version_string(response.dtu_info.dtu_sw_version),
"inverter_hw_version" : "H" + generate_version_string(response.pv_info[0].pv_hw_version),
"inverter_sw_version": "V" + generate_sw_version_string(response.pv_info[0].pv_sw_version),
}
def print_invalid_command(command):
@ -137,7 +155,10 @@ def main():
"firmware-update",
"restart",
"turn-on",
"turn-off"
"turn-off",
"get-dtu-serial-number",
"get-information-data",
"get-version-info"
],
help="Command to execute",
)
@ -159,7 +180,9 @@ def main():
'firmware-update': firmware_update,
'restart': restart,
'turn-on': turn_on,
'turn-off': turn_off
'turn-off': turn_off,
'get-information-data': get_information_data,
'get-version-info': get_version_info,
}
command_func = switch.get(args.command, print_invalid_command)

View File

@ -14,6 +14,7 @@ from hoymiles_wifi.protobuf import (
APPInfomationData_pb2,
AppGetHistPower_pb2,
CommandPB_pb2,
InfomationData_pb2,
GetConfig_pb2,
RealData_pb2,
RealDataNew_pb2,
@ -203,6 +204,17 @@ class Inverter:
command = CMD_CLOUD_COMMAND_RES_DTO
return self.send_request(command, request, CommandPB_pb2.CommandReqDTO)
def get_information_data(self):
request = InfomationData_pb2.InfoDataResDTO()
request.time_ymd_hms = datetime.now().strftime("%Y-%m-%d %H:%M:%S").encode("utf-8")
request.offset = 28800
request.time = int(time.time())
command = CMD_APP_INFO_DATA_RES_DTO
return self.send_request(command, request, InfomationData_pb2.InfoDataReqDTO)
def send_request(self, command: bytes, request: Any, response_type: Any, inverter_port: int = INVERTER_PORT):
self.sequence = (self.sequence + 1) & 0xFFFF

View File

@ -51,8 +51,8 @@ message APPPvInfoMO {
int32 pv_sw_version = 4; // PV software version
int32 pv_hw_part_number = 5; // PV hardware part number
int32 pv_hw_version = 6; // PV hardware version
int32 pv_gpf_code = 7; // PV GPF code
int32 pv_gpf = 8; // PV GPF
int32 pv_grid_profile_code = 7; // PV grid profile code
int32 pv_grid_profile = 8; // PV grid profile
int32 pv_rf_hw_version = 9; // PV RF hardware version
int32 pv_rf_sw_version = 10; // PV RF software version
int32 mi_rule_id = 11; // MI rule ID

View File

@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17\x41PPInfomationData.proto\"\xa6\x04\n\x0c\x41PPDtuInfoMO\x12\x13\n\x0b\x64\x65vice_kind\x18\x01 \x01(\x05\x12\x16\n\x0e\x64tu_sw_version\x18\x02 \x01(\x05\x12\x16\n\x0e\x64tu_hw_version\x18\x03 \x01(\x05\x12\x15\n\rdtu_step_time\x18\x04 \x01(\x05\x12\x19\n\x11\x64tu_rf_hw_version\x18\x05 \x01(\x05\x12\x19\n\x11\x64tu_rf_sw_version\x18\x06 \x01(\x05\x12\x14\n\x0c\x61\x63\x63\x65ss_model\x18\x07 \x01(\x05\x12\x1a\n\x12\x63ommunication_time\x18\x08 \x01(\x05\x12\x17\n\x0fsignal_strength\x18\t \x01(\x05\x12\x14\n\x0cgprs_version\x18\n \x01(\t\x12\x14\n\x0cwifi_version\x18\x0b \x01(\t\x12\x11\n\tka_number\x18\x0c \x01(\t\x12\x13\n\x0b\x64tu_rule_id\x18\r \x01(\x05\x12\x16\n\x0e\x64tu_error_code\x18\x0e \x01(\x05\x12\x13\n\x0b\x64tu485_mode\x18\x0f \x01(\x05\x12\x16\n\x0e\x64tu485_address\x18\x10 \x01(\x05\x12\x1c\n\x14sub1g_frequency_band\x18\x11 \x01(\x05\x12\"\n\x1asub1g_channel_total_number\x18\x12 \x01(\x05\x12\x1c\n\x14sub1g_channel_number\x18\x13 \x01(\x05\x12\x10\n\x08sub1g_rp\x18\x14 \x01(\x05\x12\x1b\n\x13sub1g_channel_total\x18\x15 \x01(\x05\x12\x11\n\tgprs_imei\x18\x16 \x01(\t\"\xc2\x01\n\x0e\x41PPMeterInfoMO\x12\x13\n\x0b\x64\x65vice_kind\x18\x01 \x01(\x05\x12\x1b\n\x13meter_serial_number\x18\x02 \x01(\x03\x12\x13\n\x0bmeter_model\x18\x03 \x01(\x05\x12\x10\n\x08meter_ct\x18\x04 \x01(\x05\x12\x19\n\x11\x63ommunication_way\x18\x05 \x01(\x05\x12\x13\n\x0b\x61\x63\x63\x65ss_mode\x18\x06 \x01(\x05\x12\x12\n\nsw_version\x18\x07 \x01(\x05\x12\x13\n\x0bmeter_value\x18\x08 \x01(\t\"~\n\x0b\x41PPRpInfoMO\x12\x13\n\x0b\x64\x65vice_kind\x18\x01 \x01(\x05\x12\x18\n\x10rp_serial_number\x18\x02 \x01(\x03\x12\x15\n\rrp_sw_version\x18\x03 \x01(\x05\x12\x15\n\rrp_hw_version\x18\x04 \x01(\x05\x12\x12\n\nrp_rule_id\x18\x05 \x01(\x05\"\x83\x02\n\x0b\x41PPPvInfoMO\x12\x13\n\x0b\x64\x65vice_kind\x18\x01 \x01(\x05\x12\x18\n\x10pv_serial_number\x18\x02 \x01(\x03\x12\x0f\n\x07pv_usfw\x18\x03 \x01(\x05\x12\x15\n\rpv_sw_version\x18\x04 \x01(\x05\x12\x19\n\x11pv_hw_part_number\x18\x05 \x01(\x05\x12\x15\n\rpv_hw_version\x18\x06 \x01(\x05\x12\x13\n\x0bpv_gpf_code\x18\x07 \x01(\x05\x12\x0e\n\x06pv_gpf\x18\x08 \x01(\x05\x12\x18\n\x10pv_rf_hw_version\x18\t \x01(\x05\x12\x18\n\x10pv_rf_sw_version\x18\n \x01(\x05\x12\x12\n\nmi_rule_id\x18\x0b \x01(\x05\"*\n\x0c\x41PPFeatureMO\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\t\"\xed\x02\n\x11\x41PPInfoDataReqDTO\x12\x19\n\x11\x64tu_serial_number\x18\x01 \x01(\t\x12\x11\n\ttimestamp\x18\x02 \x01(\r\x12\x15\n\rdevice_number\x18\x03 \x01(\x05\x12\x11\n\tpv_number\x18\x04 \x01(\x05\x12\x16\n\x0epackage_number\x18\x05 \x01(\x05\x12\x17\n\x0f\x63urrent_package\x18\x06 \x01(\x05\x12\x0f\n\x07\x63hannel\x18\x07 \x01(\x05\x12\x1f\n\x08\x64tu_info\x18\x08 \x01(\x0b\x32\r.APPDtuInfoMO\x12#\n\nmeter_info\x18\t \x03(\x0b\x32\x0f.APPMeterInfoMO\x12\x1d\n\x07rp_info\x18\n \x03(\x0b\x32\x0c.APPRpInfoMO\x12\x1d\n\x07pv_info\x18\x0b \x03(\x0b\x32\x0c.APPPvInfoMO\x12\x15\n\runknown_field\x18\x0c \x01(\r\x12#\n\x0c\x61pp_features\x18\r \x03(\x0b\x32\r.APPFeatureMO\"t\n\x11\x41PPInfoDataResDTO\x12\x14\n\x0ctime_ymd_hms\x18\x01 \x01(\t\x12\x0e\n\x06offset\x18\x02 \x01(\x05\x12\x17\n\x0f\x63urrent_package\x18\x03 \x01(\x05\x12\x12\n\nerror_code\x18\x04 \x01(\x05\x12\x0c\n\x04time\x18\x05 \x01(\rb\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17\x41PPInfomationData.proto\"\xa6\x04\n\x0c\x41PPDtuInfoMO\x12\x13\n\x0b\x64\x65vice_kind\x18\x01 \x01(\x05\x12\x16\n\x0e\x64tu_sw_version\x18\x02 \x01(\x05\x12\x16\n\x0e\x64tu_hw_version\x18\x03 \x01(\x05\x12\x15\n\rdtu_step_time\x18\x04 \x01(\x05\x12\x19\n\x11\x64tu_rf_hw_version\x18\x05 \x01(\x05\x12\x19\n\x11\x64tu_rf_sw_version\x18\x06 \x01(\x05\x12\x14\n\x0c\x61\x63\x63\x65ss_model\x18\x07 \x01(\x05\x12\x1a\n\x12\x63ommunication_time\x18\x08 \x01(\x05\x12\x17\n\x0fsignal_strength\x18\t \x01(\x05\x12\x14\n\x0cgprs_version\x18\n \x01(\t\x12\x14\n\x0cwifi_version\x18\x0b \x01(\t\x12\x11\n\tka_number\x18\x0c \x01(\t\x12\x13\n\x0b\x64tu_rule_id\x18\r \x01(\x05\x12\x16\n\x0e\x64tu_error_code\x18\x0e \x01(\x05\x12\x13\n\x0b\x64tu485_mode\x18\x0f \x01(\x05\x12\x16\n\x0e\x64tu485_address\x18\x10 \x01(\x05\x12\x1c\n\x14sub1g_frequency_band\x18\x11 \x01(\x05\x12\"\n\x1asub1g_channel_total_number\x18\x12 \x01(\x05\x12\x1c\n\x14sub1g_channel_number\x18\x13 \x01(\x05\x12\x10\n\x08sub1g_rp\x18\x14 \x01(\x05\x12\x1b\n\x13sub1g_channel_total\x18\x15 \x01(\x05\x12\x11\n\tgprs_imei\x18\x16 \x01(\t\"\xc2\x01\n\x0e\x41PPMeterInfoMO\x12\x13\n\x0b\x64\x65vice_kind\x18\x01 \x01(\x05\x12\x1b\n\x13meter_serial_number\x18\x02 \x01(\x03\x12\x13\n\x0bmeter_model\x18\x03 \x01(\x05\x12\x10\n\x08meter_ct\x18\x04 \x01(\x05\x12\x19\n\x11\x63ommunication_way\x18\x05 \x01(\x05\x12\x13\n\x0b\x61\x63\x63\x65ss_mode\x18\x06 \x01(\x05\x12\x12\n\nsw_version\x18\x07 \x01(\x05\x12\x13\n\x0bmeter_value\x18\x08 \x01(\t\"~\n\x0b\x41PPRpInfoMO\x12\x13\n\x0b\x64\x65vice_kind\x18\x01 \x01(\x05\x12\x18\n\x10rp_serial_number\x18\x02 \x01(\x03\x12\x15\n\rrp_sw_version\x18\x03 \x01(\x05\x12\x15\n\rrp_hw_version\x18\x04 \x01(\x05\x12\x12\n\nrp_rule_id\x18\x05 \x01(\x05\"\x95\x02\n\x0b\x41PPPvInfoMO\x12\x13\n\x0b\x64\x65vice_kind\x18\x01 \x01(\x05\x12\x18\n\x10pv_serial_number\x18\x02 \x01(\x03\x12\x0f\n\x07pv_usfw\x18\x03 \x01(\x05\x12\x15\n\rpv_sw_version\x18\x04 \x01(\x05\x12\x19\n\x11pv_hw_part_number\x18\x05 \x01(\x05\x12\x15\n\rpv_hw_version\x18\x06 \x01(\x05\x12\x1c\n\x14pv_grid_profile_code\x18\x07 \x01(\x05\x12\x17\n\x0fpv_grid_profile\x18\x08 \x01(\x05\x12\x18\n\x10pv_rf_hw_version\x18\t \x01(\x05\x12\x18\n\x10pv_rf_sw_version\x18\n \x01(\x05\x12\x12\n\nmi_rule_id\x18\x0b \x01(\x05\"*\n\x0c\x41PPFeatureMO\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\t\"\xed\x02\n\x11\x41PPInfoDataReqDTO\x12\x19\n\x11\x64tu_serial_number\x18\x01 \x01(\t\x12\x11\n\ttimestamp\x18\x02 \x01(\r\x12\x15\n\rdevice_number\x18\x03 \x01(\x05\x12\x11\n\tpv_number\x18\x04 \x01(\x05\x12\x16\n\x0epackage_number\x18\x05 \x01(\x05\x12\x17\n\x0f\x63urrent_package\x18\x06 \x01(\x05\x12\x0f\n\x07\x63hannel\x18\x07 \x01(\x05\x12\x1f\n\x08\x64tu_info\x18\x08 \x01(\x0b\x32\r.APPDtuInfoMO\x12#\n\nmeter_info\x18\t \x03(\x0b\x32\x0f.APPMeterInfoMO\x12\x1d\n\x07rp_info\x18\n \x03(\x0b\x32\x0c.APPRpInfoMO\x12\x1d\n\x07pv_info\x18\x0b \x03(\x0b\x32\x0c.APPPvInfoMO\x12\x15\n\runknown_field\x18\x0c \x01(\r\x12#\n\x0c\x61pp_features\x18\r \x03(\x0b\x32\r.APPFeatureMO\"t\n\x11\x41PPInfoDataResDTO\x12\x14\n\x0ctime_ymd_hms\x18\x01 \x01(\t\x12\x0e\n\x06offset\x18\x02 \x01(\x05\x12\x17\n\x0f\x63urrent_package\x18\x03 \x01(\x05\x12\x12\n\nerror_code\x18\x04 \x01(\x05\x12\x0c\n\x04time\x18\x05 \x01(\rb\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@ -28,11 +28,11 @@ if _descriptor._USE_C_DESCRIPTORS == False:
_globals['_APPRPINFOMO']._serialized_start=777
_globals['_APPRPINFOMO']._serialized_end=903
_globals['_APPPVINFOMO']._serialized_start=906
_globals['_APPPVINFOMO']._serialized_end=1165
_globals['_APPFEATUREMO']._serialized_start=1167
_globals['_APPFEATUREMO']._serialized_end=1209
_globals['_APPINFODATAREQDTO']._serialized_start=1212
_globals['_APPINFODATAREQDTO']._serialized_end=1577
_globals['_APPINFODATARESDTO']._serialized_start=1579
_globals['_APPINFODATARESDTO']._serialized_end=1695
_globals['_APPPVINFOMO']._serialized_end=1183
_globals['_APPFEATUREMO']._serialized_start=1185
_globals['_APPFEATUREMO']._serialized_end=1227
_globals['_APPINFODATAREQDTO']._serialized_start=1230
_globals['_APPINFODATAREQDTO']._serialized_end=1595
_globals['_APPINFODATARESDTO']._serialized_start=1597
_globals['_APPINFODATARESDTO']._serialized_end=1713
# @@protoc_insertion_point(module_scope)

View File

@ -1,8 +1,45 @@
""""Utils for interacting with Hoymiles WiFi API."""
from hoymiles_wifi.protobuf import (
GetConfig_pb2,
SetConfig_pb2,
)
def format_number(num):
return "{:02d}".format(num)
def generate_version_string(i):
value_of = i
version_string = format_number(value_of // 2048) + "." + format_number((value_of // 64) % 32) + "." + format_number(value_of % 64)
return version_string
def generate_sw_version_string(i):
value_of = i
value_of2 = value_of // 10000
value_of3 = (value_of - (value_of2 * 10000)) // 100
value_of4 = (value_of - (value_of2 * 10000)) - (value_of3 * 100)
version_string = format_number(value_of2) + "." + format_number(value_of3) + "." + format_number(value_of4)
return version_string
def generate_dtu_version_string(i):
def format_number(num):
return "{:02d}".format(num)
string_buffer = ""
i2 = i % 256
i3 = (i // 256) % 16
if "SRF" == str:
string_buffer += f"{format_number(i // 1048576)}.{format_number((i % 65536) // 4096)}.{format_number(i3)}.{format_number(i2)}"
elif "HRF" == str:
string_buffer += f"{format_number(i // 65536)}.{format_number((i % 65536) // 4096)}.{format_number(i3)}.{format_number(i2)}"
else:
string_buffer += f"{format_number(i // 4096)}.{format_number(i3)}.{format_number(i2)}"
return string_buffer
def initialize_set_config(get_config_req: GetConfig_pb2.GetConfigReqDTO):
set_config_res = SetConfig_pb2.SetConfigResDTO()
set_config_res.lock_password = get_config_req.lock_password
@ -53,4 +90,6 @@ def initialize_set_config(get_config_req: GetConfig_pb2.GetConfigReqDTO):
set_config_res.dtu_ap_ssid = get_config_req.dtu_ap_ssid
set_config_res.dtu_ap_pass = get_config_req.dtu_ap_pass
return set_config_res
return set_config_res

View File

@ -3,7 +3,7 @@ from setuptools import setup
setup(
name='hoymiles-wifi',
packages=['hoymiles_wifi', 'hoymiles_wifi.protobuf'],
version='0.0.10',
version='0.0.11',
description='A python library for interfacing with Hoymiles HMS-XXXXW-T2 series of micro-inverters.',
author='suaveolent',
include_package_data=True,