diff --git a/CHANGELOG.md b/CHANGELOG.md index 0eede6e..0ec1d47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- add timeout monitoring for received packets - parse Modbus values and store them in the database - add cron task to request the output power every minute - GEN3PLUS: add MQTT topics to send AT commands to the inverter diff --git a/README.md b/README.md index 1a26179..342a643 100644 --- a/README.md +++ b/README.md @@ -39,12 +39,15 @@ If you use a Pi-hole, you can also store the host entry in the Pi-hole. ## Features -- supports TSUN GEN3 PLUS inverters: TSOL-MS2000, MS1800 and MS1600 -- supports TSUN GEN3 inverters: TSOL-MS800, MS700, MS600, MS400, MS350 and MS300 +- Supports TSUN GEN3 PLUS inverters: TSOL-MS2000, MS1800 and MS1600 +- Supports TSUN GEN3 inverters: TSOL-MS800, MS700, MS600, MS400, MS350 and MS300 - `MQTT` support - `Home-Assistant` auto-discovery support +- `MODBUS` support via MQTT topics +- `AT Command` support via MQTT topics (GEN3PLUS only) +- Faster DataUp interval sends measurement data to the MQTT broker every minute - Self-sufficient island operation without internet -- runs in a non-root Docker Container +- Runs in a non-root Docker Container ## Home Assistant Screenshots diff --git a/app/proxy.svg b/app/proxy.svg index dfbdd46..cef1e69 100644 --- a/app/proxy.svg +++ b/app/proxy.svg @@ -4,352 +4,372 @@ - - + + G - + A0 - - - -You can stick notes -on diagrams too! + + + +You can stick notes +on diagrams too! A1 - -Singleton + +Singleton A2 - -Mqtt - -<static>ha_restarts -<static>__client -<static>__cb_MqttIsUp - -<async>publish() -<async>close() + +Mqtt + +<static>ha_restarts +<static>__client +<static>__cb_MqttIsUp + +<async>publish() +<async>close() A1->A2 - - - - - -A3 - -Modbus - - - -A1->A3 - - + + A11 - -Inverter - -cls.db_stat -cls.entity_prfx -cls.discovery_prfx -cls.proxy_node_id -cls.proxy_unique_id -cls.mqtt:Mqtt - + +Inverter + +cls.db_stat +cls.entity_prfx +cls.discovery_prfx +cls.proxy_node_id +cls.proxy_unique_id +cls.mqtt:Mqtt + - + A2->A11 - + + + + +A3 + +Modbus + + +build_msg() +recv_req() +recv_resp() +check_crc() A4 - -IterRegistry - - -__iter__ + +IterRegistry + + +__iter__ A5 - -Message - -server_side:bool -header_valid:bool -header_len:unsigned -data_len:unsigned -unique_id -node_id -sug_area -_recv_buffer:bytearray -_send_buffer:bytearray -_forward_buffer:bytearray -db:Infos -new_data:list - -_read():void<abstract> -close():void -inc_counter():void -dec_counter():void + +Message + +server_side:bool +header_valid:bool +header_len:unsigned +data_len:unsigned +unique_id +node_id +sug_area +_recv_buffer:bytearray +_send_buffer:bytearray +_forward_buffer:bytearray +db:Infos +new_data:list + +_read():void<abstract> +close():void +inc_counter():void +dec_counter():void - + A4->A5 - - + + A6 - -Talent - -await_conn_resp_cnt -id_str -contact_name -contact_mail -switch - -msg_contact_info() -msg_ota_update() -msg_get_time() -msg_collector_data() -msg_inverter_data() -msg_unknown() -close() + +Talent + +await_conn_resp_cnt +id_str +contact_name +contact_mail +db:InfosG3 +mb:Modbus +switch + +msg_contact_info() +msg_ota_update() +msg_get_time() +msg_collector_data() +msg_inverter_data() +msg_unknown() +close() - + A5->A6 - - + + A7 - -SolarmanV5 - -control -serial -snr -switch - -msg_unknown() -close() + +SolarmanV5 + +control +serial +snr +db:InfosG3P +mb:Modbus +switch + +msg_unknown() +close() - + A5->A7 - - + + + + + +A6->A3 + + +1 +has A8 - -ConnectionG3 - -remoteStream:ConnectionG3 - -close() + +ConnectionG3 + +remoteStream:ConnectionG3 + +close() - + A6->A8 - - + + + + + +A7->A3 + + +1 +has A9 - -ConnectionG3P - -remoteStream:ConnectionG3P - -close() + +ConnectionG3P + +remoteStream:ConnectionG3P + +close() A7->A9 - - + + - + A8->A8 - - -0..1 -has + + +0..1 +has A12 - -InverterG3 - -__ha_restarts - -async_create_remote() -close() + +InverterG3 + +__ha_restarts + +async_create_remote() +close() - + A8->A12 - - + + - + A9->A9 - - -0..1 -has + + +0..1 +has A13 - -InverterG3P - -__ha_restarts - -async_create_remote() -close() + +InverterG3P + +__ha_restarts + +async_create_remote() +close() - + A9->A13 - - + + A10 - -AsyncStream - -reader -writer -addr -r_addr -l_addr - -<async>server_loop() -<async>client_loop() -<async>loop -disc() -close() -__async_read() -async_write() -__async_forward() + +AsyncStream + +reader +writer +addr +r_addr +l_addr + +<async>server_loop() +<async>client_loop() +<async>loop +disc() +close() +__async_read() +async_write() +__async_forward() - + A10->A8 - - + + - + A10->A9 - - + + - + A11->A12 - - + + - + A11->A13 - - + + A14 - -Infos - -stat -new_stat_data -info_dev - -static_init() -dev_value() -inc_counter() -dec_counter() -ha_proxy_conf -ha_conf -update_db -set_db_def_value -get_db_value -ignore_this_device + +Infos + +stat +new_stat_data +info_dev + +static_init() +dev_value() +inc_counter() +dec_counter() +ha_proxy_conf +ha_conf +update_db +set_db_def_value +get_db_value +ignore_this_device A15 - -InfosG3 - - -ha_confs() -parse() + +InfosG3 + + +ha_confs() +parse() - + A14->A15 - - + + A16 - -InfosG3P - - -ha_confs() -parse() + +InfosG3P + + +ha_confs() +parse() - + A14->A16 - - + + - + A15->A6 - - + + - + A16->A7 - - + + diff --git a/app/proxy.yuml b/app/proxy.yuml index daf5d3c..7514a93 100644 --- a/app/proxy.yuml +++ b/app/proxy.yuml @@ -4,12 +4,14 @@ [note: You can stick notes on diagrams too!{bg:cornsilk}] [Singleton]^[Mqtt|ha_restarts;__client;__cb_MqttIsUp|publish();close()] -[Singleton]^[Modbus] +[Modbus||build_msg();recv_req();recv_resp();check_crc()] [IterRegistry||__iter__]^[Message|server_side:bool;header_valid:bool;header_len:unsigned;data_len:unsigned;unique_id;node_id;sug_area;_recv_buffer:bytearray;_send_buffer:bytearray;_forward_buffer:bytearray;db:Infos;new_data:list|_read():void;close():void;inc_counter():void;dec_counter():void] -[Message]^[Talent|await_conn_resp_cnt;id_str;contact_name;contact_mail;switch|msg_contact_info();msg_ota_update();msg_get_time();msg_collector_data();msg_inverter_data();msg_unknown();;close()] -[Message]^[SolarmanV5|control;serial;snr;switch|msg_unknown();;close()] +[Message]^[Talent|await_conn_resp_cnt;id_str;contact_name;contact_mail;db:InfosG3;mb:Modbus;switch|msg_contact_info();msg_ota_update();msg_get_time();msg_collector_data();msg_inverter_data();msg_unknown();;close()] +[Message]^[SolarmanV5|control;serial;snr;db:InfosG3P;mb:Modbus;switch|msg_unknown();;close()] [Talent]^[ConnectionG3|remoteStream:ConnectionG3|close()] +[Talent]has-1>[Modbus] [SolarmanV5]^[ConnectionG3P|remoteStream:ConnectionG3P|close()] +[SolarmanV5]has-1>[Modbus] [AsyncStream|reader;writer;addr;r_addr;l_addr|server_loop();client_loop();loop;disc();close();;__async_read();async_write();__async_forward()]^[ConnectionG3] [AsyncStream]^[ConnectionG3P] [Inverter|cls.db_stat;cls.entity_prfx;cls.discovery_prfx;cls.proxy_node_id;cls.proxy_unique_id;cls.mqtt:Mqtt|]^[InverterG3|__ha_restarts|async_create_remote();;close()]