@@ -118,6 +118,12 @@ class CoreModbusHub:
118118 SLEEPMODE_LASTAWAKE ,
119119 CONF_TIME_OUT ,
120120 DEFAULT_TIME_OUT ,
121+ BUTTONREPEAT_FIRST ,
122+ BUTTONREPEAT_LOOP ,
123+ BUTTONREPEAT_POST ,
124+ WRITE_MULTI_MODBUS ,
125+ WRITE_SINGLE_MODBUS ,
126+ WRITE_MULTISINGLE_MODBUS ,
121127)
122128
123129PLATFORMS = [Platform .BUTTON , Platform .NUMBER , Platform .SELECT , Platform .SENSOR , Platform .SWITCH ]
@@ -392,7 +398,9 @@ def loadLocalData(self):
392398 else :
393399 if loaded .get ("_version" ) == self .DATAFORMAT_VERSION :
394400 for desc in self .writeLocals :
395- self .data [desc ] = loaded .get (desc )
401+ val = loaded .get (desc )
402+ if val != None : self .data [desc ] = val
403+ else : self .data [desc ] = self .writeLocals [desc ].initvalue # first time initialisation
396404 else :
397405 _LOGGER .warning (f"local persistent data lost - please reinitialize { self .writeLocals .keys ()} " )
398406 fp .close ()
@@ -719,13 +727,13 @@ async def async_read_modbus_data(self, group):
719727 try :
720728 res = await self .async_read_modbus_registers_all (group )
721729 except ConnectionException as ex :
722- _LOGGER .error ("Reading data failed! Inverter is offline." )
730+ _LOGGER .error (f "Reading data failed! Inverter is offline. { ex } " )
723731 res = False
724732 except ModbusIOException as ex :
725733 _LOGGER .error (f"ModbusIOError: { ex } " )
726734 res = False
727735 except Exception as ex :
728- _LOGGER .exception ("Something went wrong reading from modbus" )
736+ _LOGGER .exception (f "Something went wrong reading from modbus: { ex } " )
729737 res = False
730738 return res
731739
@@ -910,7 +918,8 @@ async def async_read_modbus_registers_all(self, group):
910918 else :
911919 _LOGGER .debug (f"device group inverter" )
912920
913- data = {"_repeatUntil" : self .data ["_repeatUntil" ]}
921+ data = {"_repeatUntil" : self .data ["_repeatUntil" ]} # remove for issue #1440 but then does not recognize comm errors
922+ #data = self.data # add for issue #1440 - is an alias, not a copy - but then does not recognize communication errors anymore
914923 res = True
915924 for block in group .holdingBlocks :
916925 res = res and await self .async_read_modbus_block (data , block , "holding" )
@@ -931,8 +940,8 @@ async def async_read_modbus_registers_all(self, group):
931940 _LOGGER .warning (f"device group check not success" )
932941 return True
933942
934- for key , value in data .items ():
935- self .data [key ] = value
943+ for key , value in data .items (): # remove for issue #1440, but then does not recognize communication errors anymore
944+ self .data [key ] = value # remove for issue #1440, but then comm errors are not detected
936945
937946 if res and self .writequeue and self .plugin .isAwake (self .data ): # self.awakeplugin(self.data):
938947 # process outstanding write requests
@@ -941,20 +950,43 @@ async def async_read_modbus_registers_all(self, group):
941950 val = self .writequeue .get (addr )
942951 await self .async_write_register (self ._modbus_addr , addr , val )
943952 self .writequeue = {} # make sure we do not write multiple times
953+
954+ # execute autorepeat buttons
944955 self .last_ts = time ()
945956 for (
946957 k ,
947958 v ,
948- ) in self .data ["_repeatUntil" ].items ():
959+ ) in list (self .data ["_repeatUntil" ].items ()): # use a list copy because dict may change during iteration
960+ buttondescr = self .computedButtons [k ]
949961 if self .last_ts < v :
950- buttondescr = self .computedButtons [k ]
951- payload = buttondescr .value_function (0 , buttondescr , self .data )
952- _LOGGER .debug (f"ready to repeat button { k } data: { payload } " )
953- await self .async_write_registers_multi (
954- unit = self ._modbus_addr ,
955- address = buttondescr .register ,
956- payload = payload ,
957- )
962+ payload = buttondescr .value_function (BUTTONREPEAT_LOOP , buttondescr , self .data ) # initval = 1 means autorepeat run
963+ if payload :
964+ reg = payload .get ("register" , buttondescr .register )
965+ action = payload .get ("action" )
966+ if not action : __LOGGER .error (f"autorepeat value function for { k } must return dict containing action" )
967+ else :
968+ if action == WRITE_MULTI_MODBUS :
969+ _LOGGER .debug (f"**debug** ready to repeat button { k } data: { payload } " )
970+ await self .async_write_registers_multi (
971+ unit = self ._modbus_addr ,
972+ address = reg ,
973+ payload = payload .get ('data' ),
974+ )
975+ else : # expired autorepeats
976+ if self .data ["_repeatUntil" ][k ] > 0 : # expired recently
977+ self .data ["_repeatUntil" ][k ] = 0 # mark as finally expired, no further buttonrepeat post after this one
978+ _LOGGER .info (f"calling final value function POST for { k } with initval { BUTTONREPEAT_POST } " )
979+ payload = buttondescr .value_function (BUTTONREPEAT_POST , buttondescr , self .data ) # None means no final call after expiration
980+ if payload :
981+ reg = payload .get ("register" , buttondescr .register )
982+ action = payload .get ("action" )
983+ if action == WRITE_MULTI_MODBUS :
984+ _LOGGER .info (f"terminating loop { k } - ready to send final payload data: { payload } " )
985+ await self .async_write_registers_multi (
986+ unit = self ._modbus_addr ,
987+ address = reg ,
988+ payload = payload .get ('data' ),
989+ )
958990 return res
959991
960992
0 commit comments