예제 #1
0
    def stopkill(self):
        """Called to stop all scheduled RepeatedFunctions"""
        try:
            self.stop_event.set()  #no more scheduling new events

            while len(self.running_rep_functions[:]) != 0:

                for repfunc_thread in self.running_rep_functions[:]:
                    repfunc_thread.stop_event.set(
                    )  #stop this RepeatedFunction

                for repfunc_thread in self.running_rep_functions[:]:
                    if not repfunc_thread.is_alive():
                        self.running_rep_functions.remove(repfunc_thread)
                        logger.debug("removed {}".format(repfunc_thread))

            # now self.running_rep_functions is empty
            self.stop_event.clear()

        except Exception as e:
            logger.error("Unexpected Error, sending to cloud {}".format(e))
            formatted_publish_message(
                topic=TOPIC_STATE,
                payload=
                "Error scheduling old timing events, consider restarting device: {} "
                .format(e),
                c_queue=pub_queue)
def read_setup(pub_queue, sleeptime=True, send_answer_to_cloud=False):

    port_config = dict()
    slave_config = dict()
    checkresult = False
    time.sleep(random.randint(5, 15) / 10)
    read_complete = 0

    logger.debug("check the setup_modbus.json")

    while not read_complete >= 5:

        try:
            checkresult, response, data_json = modbus_json_check(
                file=su.setup_modbus_filepath)

            if send_answer_to_cloud:
                logger.debug("setup_modbus.json response:" + str(response))

            port_config = data_json["port_config"]
            slave_config = data_json["slaveconfig"]
            read_complete = 5

            if send_answer_to_cloud:
                gmc.formatted_publish_message(
                    topic=gmc.TOPIC_STATE,
                    payload=
                    "Start up with modbus config: {}       JSON CHECKUP {}".
                    format(data_json, response),
                    c_queue=pub_queue)

        except Exception as e:
            try:
                if read_complete > 1:
                    gmc.formatted_publish_message(
                        topic=gmc.TOPIC_STATE,
                        payload="ERROR reading setup_modbus:" + str(e),
                        c_queue=pub_queue)
            finally:
                time.sleep(
                    3 + random.randint(0, 10)
                )  #randomized access if multiple read at the same time
                read_complete = read_complete + 1
    if not checkresult:  #unsuccessful, default
        port_config = {
            "port": "COM6",
            "baudrate": 9600,
            "databits": 8,
            "parity": "N",
            "stopbits": 1,
            "timeout_connection": 10
        }

        slave_config = {}
    return port_config, slave_config
예제 #3
0
    def read_modbus_event(self):
        """read operations of the timing_queue with the Modbus RTU Master and Execute them with """

        logger.debug("calling read_modbus_event")

        while self.serial_connected and self.alive and self.master_status < self.max_master_attemps - 1:

            request = self.timing_queue.get(
            )  #blocking call until new request is received
            if self.alive == False:  #discontinue if function is wished to be stopped
                self.timing_queue.task_done()
                break

            slave_id = request["slave_id"]
            startadress = request["startadress"]
            function_code = request["function_code"]
            display_name = request["display_name"]

            result = (99999, "modbus_request_not_possible")  #default
            try:
                if "quantity_of_x" in request:
                    result = self.master.execute(
                        slave=slave_id,
                        function_code=function_code,
                        starting_address=startadress,
                        quantity_of_x=request["quantity_of_x"])  #read
                elif "output_value" in request:
                    result = self.master.execute(
                        slave=slave_id,
                        function_code=function_code,
                        starting_address=startadress,
                        output_value=request["output_value"])  #write

                logger.debug(
                    "slave no {}, starting_adress {} with name {} and {} ".
                    format(slave_id, startadress, display_name, str(result)))

                self.master_status = 0  #successfull read, reset to 0

            except ModbusError as exc:
                self.master_status = self.master_status + 1  #unsuccessfull, increase the status
                logger.warning(
                    "ModbusError in read_modbus_event {}".format(ex))

            except Exception as ex:  #other error, like serial port etc.
                logger.warning(
                    "Unexpected error in read_modbus_event {}".format(ex))
                self.master_status = self.master_status + 5  #unsuccessfull, increase the status
                self.serial_connected = False

            payload = {
                "na": display_name,
                "res": result,
                "sl": slave_id,
                "time": time.time()
            }
            formatted_publish_message(topic=TOPIC_EVENT,
                                      payload=payload,
                                      c_queue=self.publishing_queue)

            self.timing_queue.task_done()

        logger.warning("Disconnected the Modbus, restarting")
        try:
            if self.serial_port != "undefined":  #if not just initialisized
                self.serial_port.close()
        except Exception as ex:
            logger.error("error closing serial port: {}".format(ex))
예제 #4
0
    def startup(self):
        """Start or Restart the Scheduling events"""

        #Step 1: Figure out what current setup_modbus.json is and its slaveconfig
        unused_port_config, slaveconfig = read_setup(
            self.publishing_queue)  #wait to get newest setup

        try:
            while not self.stop_event.is_set():

                #Step 2: For every operation in slaveconfig: find out details
                for slave_name in slaveconfig:  #looping through all exisiting slaves
                    operations = slaveconfig[slave_name]["operations"]
                    slave_id = slaveconfig[slave_name]["slave_id"]

                    for operation in operations:  #looping for all operations of a specific slave

                        #[Start get Information of Operation]
                        op = operations[operation]
                        interval = (op["sampling_interval"]
                                    )  #interval for Scheduling events

                        process_request = {
                            "slave_id": slave_id,
                            "startadress": op["startadress"],
                            "function_code": op["function_code"],
                            "display_name": op["display_name"],
                        }

                        if "quantity_of_x" in op:
                            process_request["quantity_of_x"] = op[
                                "quantity_of_x"]
                        elif "output_value" in op:
                            process_request["output_value"] = op[
                                "output_value"]
                        else:
                            logger.error(
                                "FATAL ERROR, no output value or quantity_of_x {}"
                                .format(process_request))
                        #[End get Information of Operation]

                        self.stop_event.wait(
                            self.timeout_between_functions
                        )  #timeout, so differet request will be executed at different times

                        if self.stop_event.is_set():
                            logger.warning(
                                "Error: unwanted break in scheduling new RepeatedFunctions"
                            )
                            return
                        #Step 3: For a specific operation schedule a specific RepeatedFunction every interval seconds
                        #[Start Schedule new RepeatedFunction]
                        rf = RepeatedFunction(interval, self.query_task,
                                              (self, process_request))
                        rf.setDaemon = True
                        rf.start()
                        self.running_rep_functions.append(rf)

                        logger.debug(
                            "scheduleded {} \t at interval {} ".format(
                                process_request,
                                (str(interval) +
                                 "s") if interval != 0 else "once occuring"))

                        #[End Schedule new RepeatedFunction]

                logger.debug("ending this scheduler thread {}".format(
                    self.running_rep_functions))
                return

        except Exception as e:  #should in no case occur
            logger.error(
                "Error scheduling new timing events, consider restarting device: {}"
                .format(e))
            formatted_publish_message(
                topic=TOPIC_STATE,
                payload=
                "Error scheduling new timing events, consider restarting device: {} "
                .format(e),
                c_queue=pub_queue)
def check_configuration_message(config_payload, scheduler_obj,
                                modbus_reader_obj, publising_queue):
    logger.info("check new message on content")
    """checks for the Configuration Messages and applies them when the new and deployment formally correct"""

    answer_config_update = " /Config Subscription Message received"

    novel_json_content = False  #
    absolute_success_update = False  #whether successfull update
    replacing_file_success = False  #
    content_correct = False  #
    received_json_checkresult = False  #

    current_checkresult, current_response, current_json = modbus_json_check(
        file=su.setup_modbus_filepath)
    #answer_config_update = answer_config_update + str(" \n CURRENT JSON running is ") + str(current_json) #current json

    content_correct = bool("content_start" in config_payload
                           and "content_end" in config_payload
                           and "configuration_update_modbus" in config_payload)

    if content_correct:  #elements of a correct config message exists
        try:

            received_json_string = config_payload.split(
                "content_start")[1].split("content_end")[0]
            received_json = json.loads(
                received_json_string
            )  #will not work, if a invalid json it throws an error

            received_json_checkresult, received_json_response, unused_json = modbus_json_check(
                dictio=received_json)

            if received_json_checkresult == True:

                answer_config_update = answer_config_update + str(
                    "\n Received JSON is valid")  #json is currently used
                if current_json != received_json:
                    novel_json_content = True
                    logger.debug(
                        "SUCCESS! Received a new, valid JSON. Will update an use:  {}"
                        .format(received_json))
                    result = "UPDATING"

                    # [Start UPDATE]
                    replacing_file_success, answer_update = execute_configuration_message(
                        received_json)  #use the new json
                    answer_config_update = answer_config_update + answer_update
                    # [End UPDATE]
                elif current_json == received_json:
                    answer_config_update = answer_config_update + str(
                        "\n CURRENT JSON is the SAME as received JSON, not changing setup "
                    )  #json is currently used
            elif received_json_checkresult == False:

                answer_config_update = answer_config_update + "\n received JSON is invalid: {} ".format(
                    received_json_response)
        except Exception as e:
            received_json_checkresult = False
            answer_config_update = answer_config_update + "\n ERROR content between content_start and content_end is not a JSON {} ".format(
                e)

    elif not content_correct:
        answer_config_update = answer_config_update + str(
            "\n  configuration_update_modbus, content_start, content_end is missing as header, not valid configuration"
        )

    if replacing_file_success:
        try:
            logger.debug("config about to be implemented ")

            scheduler_obj.stopkill()
            modbus_reader_obj.stopkill()
            logger.debug("stopped all, wait before starting up")
            time.sleep(3)
            logger.debug("starting modbus and scheduler back up")

            scheduler_obj.startup()
            modbus_reader_obj.startup()
            absolute_success_update = True
        except Exception as e:
            absolute_success_update = False
            result = result + "BUT FAILED"
        logger.debug("config implemented ")

    if not content_correct:
        result = " configuration_update_modbus, content_start, content_end is missing as header - NO Further Processing "
    elif not received_json_checkresult:
        result = "JSON between content_start and  content_end is invalid - NO Further Processing "
    elif not novel_json_content:
        result = "JSON sent already in use"
    else:
        # JSON was further Processed "

        if replacing_file_success:
            if absolute_success_update:
                result = "SUCCESS, using received_json {} ".format(
                    received_json)
            elif not absolute_success_update:
                result = "ERROR JSON was further processed and saved, but not implemented due to an error"
        if not replacing_file_success:
            result = "Fatal ERROR JSON was further processed, but writing failed"

    answer_config_update = answer_config_update + "\n  RESULT: {} \n".format(
        result)
    logger.info(answer_config_update)
    gmc.formatted_publish_message(topic=gmc.TOPIC_STATE,
                                  payload=answer_config_update,
                                  c_queue=publising_queue)

    return