From 4e3cbc8a25db59129f1c18f4441ca88b7da0fcfe Mon Sep 17 00:00:00 2001 From: jgyates Date: Sat, 28 Oct 2023 20:10:50 -0400 Subject: [PATCH] V1.18.18 --- data/controller/Evolution_Liquid_Cooled.json | 14 ++- genmonlib/custom_controller.py | 103 ++++++++++++++----- 2 files changed, 90 insertions(+), 27 deletions(-) diff --git a/data/controller/Evolution_Liquid_Cooled.json b/data/controller/Evolution_Liquid_Cooled.json index 1da02221..3f615d96 100644 --- a/data/controller/Evolution_Liquid_Cooled.json +++ b/data/controller/Evolution_Liquid_Cooled.json @@ -58,9 +58,17 @@ "01f4": {"length": 10, "text": "Serial Number"} }, "log_registers": { - "03e8": {"length": 10, "text": "Alarm Log", "iteration": 50, "step": 5}, - "04e2": {"length": 8, "text": "Service Log", "iteration": 50, "step": 4}, - "012c": {"length": 8, "text": "Run Log", "iteration": 50, "step": 4} + "03e8": { + "comment": "The registers in this instance is 03e8. By default, this is read from holding registers.", + "comment2:": " To read from input registers add the field 'reg_type': 'input'", + "reg_type": "holding", + "length": 10, + "text": "Alarm Log", + "iteration": 50, + "step": 5 + }, + "04e2": {"reg_type": "holding", "length": 8, "text": "Service Log", "iteration": 50, "step": 4}, + "012c": {"reg_type": "holding", "length": 8, "text": "Run Log", "iteration": 50, "step": 4} }, "switch_state": [ { diff --git a/genmonlib/custom_controller.py b/genmonlib/custom_controller.py index 33c931fc..7a7c70e1 100644 --- a/genmonlib/custom_controller.py +++ b/genmonlib/custom_controller.py @@ -517,6 +517,7 @@ def WaitAndPergeforTimeout(self): ): # return self.ModBus.Flush() + # -------------CustomController:RegisterIsLog-------------------------------- def RegisterIsLog(self, Register): try: @@ -549,6 +550,10 @@ def UpdateLogRegistersAsMaster(self): self.LogDebug("Invalid register data in log register description") return try: + IsInput = False + if "reg_type" in RegisterData.keys(): + if RegisterData["reg_type"] == "input": + IsInput = True Length = RegisterData["length"] Step = RegisterData["step"] Iteration = RegisterData["iteration"] @@ -559,7 +564,7 @@ def UpdateLogRegistersAsMaster(self): return localTimeoutCount = self.ModBus.ComTimoutError localSyncError = self.ModBus.ComSyncError - self.ModBus.ProcessTransaction(Register, Length / 2) + self.ModBus.ProcessTransaction(Register, Length / 2, IsInput = IsInput) if ( localSyncError != self.ModBus.ComSyncError or localTimeoutCount != self.ModBus.ComTimoutError @@ -761,17 +766,23 @@ def UpdateRegisterList(self, Register, Value, IsString=False, IsFile=False, IsCo elif IsInput: if self.ValidateRegister("input_registers", Register, Value): self.Inputs[Register] = Value + else: + ReturnStatus, LogRegLength, Name = self.RegisterIsLog(Register) + if ReturnStatus: + self.Inputs[Register] = Value + else: + self.LogError("Failure validating log input register: " + Register) + return False else: # base register (holding register) # validate data length if self.ValidateRegister("holding_registers", Register, Value): self.Registers[Register] = Value else: - # TODO Validate log registers ReturnStatus, LogRegLength, Name = self.RegisterIsLog(Register) if ReturnStatus: self.Registers[Register] = Value else: - self.LogError("Failure validating log register: " + Register) + self.LogError("Failure validating log holding register: " + Register) return False return True @@ -801,7 +812,8 @@ def ValidateRegister(self, type, Register, Value): return False return True else: - self.LogError("Error in ValidateRegister: register " + str(Register) + " not in " + str(type)) + #self.LogDebug("Error in ValidateRegister: register " + str(Register) + " not in " + str(type)) + return False except Exception as e1: self.LogErrorLine("Error in ValidateRegister: " + str(e1)) return False @@ -837,10 +849,6 @@ def GetRegisterLabels(self): RegData = self.controllerimport["coil_registers"][Register] if isinstance(RegData, dict): ReturnDict[Register] = RegData["text"] - else: - Success, Length, Name = self.RegisterIsLog(Register) - if Success: - ReturnDict[Register] = Name return json.dumps(ReturnDict) except Exception as e1: self.LogErrorLine("Error in GetRegisterLabels: " + str(e1)) @@ -1290,35 +1298,82 @@ def SetButton(self): self.LogErrorLine("Error in SetButton: " + str(e1)) return {} # -------------CustomController:GetButtons----------------------------------- - def GetButtons(self, singlebuttonname = None): + def GetButtons(self): try: button_list = self.controllerimport.get("buttons", None) - if not singlebuttonname == None: - for button in button_list: - if button["onewordcommand"] == singlebuttonname: - return button - return None - if button_list == None: return {} if not isinstance(button_list, list): - self.LogDebug("Error in GetButtons: invalid input or data: "+ str(type(button_list))) + self.LogError("Error in GetButtons: invalid input or data: "+ str(type(button_list))) return {} - if True: + # Validate buttons before sending to the web app + return_buttons = {} + for button in button_list: + + if not "onewordcommand" in button.keys(): + self.LogError("Error in GetButtons: button must have onewordcommand element: "+ str(button)) + continue + elif not isinstance(button["onewordcommand"], str): + self.LogError("Error in GetButtons: invalid button defined validateing onewordcommand (non string): "+ str(button)) + continue + if not "title" in button.keys(): + self.LogError("Error in GetButtons: button must have title element: "+ str(button)) + continue + elif not isinstance(button["title"], str): + self.LogError("Error in GetButtons: invalid button defined validateing title (not string): "+ str(button)) + continue + if not "command_sequence" in button.keys(): + self.LogError("Error in GetButtons: button must have command_sequence element: "+ str(button)) + continue + elif not isinstance(button["command_sequence"], list): + self.LogError("Error in GetButtons: invalid button defined validateing command_sequence:(not list) "+ str(button)) + continue + + # valiate command sequeuence + CommandError = False + for command in button["command_sequence"]: + if not "reg" in command.keys() and not isinstance(command["reg"], str): + self.LogError("Error in GetButtons: invalid command string defined validateing reg: "+ str(button)) + CommandError = True + break + if not "value" in command.keys(): + # this command requires input from the web app, let's validate the params + # "input_title", "type" is required. "length" is default 2 but must be a multiple of 2 + if not "input_title" in command.keys() or not "type" in command.keys(): + self.LogError("Error in GetButtons: Error validateing input_title and type: "+ str(button)) + CommandError = True + break + if "length" in command.keys(): + if(int(command["length"]) % 2 != 0): + self.LogError("Error in GetButtons: length of command_sequence input must be a multiple of 2: " + str(button)) + CommandError = True + break + if "bounds_regex" in command.keys(): + if not self.RegExIsValid(command["bounds_regex"]): + self.LogError("Error in GetButtons: invalid regular expression for bounds_regex in command_sequence: " + str(button)) + CommandError = True + break + if CommandError: + continue + # TODO fix this - return_buttons = {} - for button in button_list: - return_buttons[button["onewordcommand"]] = button["title"] - return return_buttons - else: - return button_list + #return_buttons.append(button) + return_buttons[button["onewordcommand"]] = button["title"] + return return_buttons except Exception as e1: self.LogErrorLine("Error in GetButtons: " + str(e1)) return {} + # ---------- CustomController::RegExIsValid--------------------------------- + def RegExIsValid(self, input_str): + try: + re.compile(input_str) + return True + except Exception as e1: + return False # ---------- CustomController::SetGeneratorRemoteCommand-------------------- # CmdString will be in the format: "setremote=start" # valid commands are defined in the JSON file @@ -1351,7 +1406,7 @@ def SetGeneratorRemoteCommand(self, CmdString): button_list = self.controllerimport.get("buttons", None) if button_list == None: - return "No buttons defined" + return "No commands defined." if not isinstance(button_list, list): self.LogDebug("Error in SetGeneratorRemoteCommand: invalid input or data: "+ str(type(button_list))) return "Malformed button in JSON file."