Esempio n. 1
0
    /// <summary>
    /// Reads settings from the DB or config files.
    /// The files are used as a backup in case DB is not available.
    /// They are: log4net.config, plc.config and App.config, located in /config
    /// </summary>
    public static void readAllSettings()
    {
        Console.WriteLine("Starting AMR Connect");

        // Begins logging to the console and file
        try
        {
            var logRepository = LogManager.GetRepository(System.Reflection.Assembly.GetEntryAssembly());
            XmlConfigurator.Configure(logRepository, new FileInfo(@"config\log4net.config"));
        }
        catch (Exception exception)
        {
            Console.WriteLine("Failed To Read Logger Configuration.");
            Console.WriteLine(exception);
        }

        try
        {
            connectToDB();

            readSettingsFromDB();
        }
        catch (ConfigurationErrorsException exception)
        {
            logger(AREA, DEBUG, "Couldn't Read App Settings. Error: ", exception);
            gracefulTermination("Failed to read application settings, on start-up. App will terminate");
        }

        //=========================================================|
        //  Initialize Siemens PLC                                 |
        //=========================================================|
        SiemensPLC.initialize();

        //=========================================================|
        //  Initialize SMS communication for alerts                |
        //=========================================================|
        TwilioClient.Init(accountSid, authToken);

        //=========================================================|
        //  Initialize PLC comms and REST Header                   |
        //=========================================================|
        setUpDefaultComms();

        //=========================================================|
        //  Initialize Fleet Container                             |
        //=========================================================|
        if (fleetManagerIP != null && fleetManagerAuthToken != null)
        {
            logger(AREA, INFO, "Fleet Connection Details Assigned");
            mirFleet = new Fleet(sizeOfFleet, fleetManagerIP, fleetManagerAuthToken);
        }
        else
        {
            logger(AREA, WARNING, "Fleet Data Missing Or Fleet Not Used");
            mirFleet = new Fleet(sizeOfFleet);
        }

        logger(AREA, DEBUG, "Settings Obtained");
    }
Esempio n. 2
0
    /// <summary>
    ///
    /// </summary>
    private static int unknownMission(int robotID)
    {
        logger(AREA, ERROR, "==== Unknown Mission ====");

        SiemensPLC.updateTaskStatus(robotID, Globals.TaskStatus.CouldntProcessRequest);

        return(Globals.TaskStatus.CouldntProcessRequest);

        // Issue an alert
    }
Esempio n. 3
0
    /// <summary>
    ///
    /// </summary>
    /// <returns></returns>
    private static void getRobotGroups()
    {
        logger(AREA, DEBUG, "Saving Robot Groups In Fleet PLC Block");

        // Comment out for now - we're relying on keeping track of the groups ourselves
        //int restStatus = mirFleet.issueGetRequest("robots?whitelist=robot_group_id", SiemensPLC.fleetID);

        fleetMemoryToPLC();
        SiemensPLC.writeFleetBlock(SiemensPLC.fleetBlock.getTaskStatus());
    }
Esempio n. 4
0
    /// <summary>
    ///
    /// </summary>
    private static int clearScheduler()
    {
        logger(AREA, INFO, "==== Clear Mission Schedule ====");

        int restStatus = mirFleet.fleetManager.sendRESTdata(mirFleet.fleetManager.Missions[0].deleteRequest());

        SiemensPLC.updateTaskStatus(fleetID, restStatus);

        logger(AREA, DEBUG, "==== Cleared Mission Scheduler ====");

        return(restStatus);
    }
Esempio n. 5
0
    /// <summary>
    /// Disposes default communication: HTTP Client as well as Siemens Libnodave connection.
    /// </summary>
    public static void closeComms()
    {
        logger(AREA, DEBUG, "==== Closing Connections ====");

        try
        {
            comms.Dispose();
            SiemensPLC.disconnect();

            logger(AREA, INFO, "Closed Communications");
        }
        catch (NullReferenceException exception)
        {
            logger(AREA, ERROR, "Couldn't close comms as they've not been instantiated: ", exception);
        }
        catch (Exception exception)
        {
            logger(AREA, ERROR, "Couldn't close comms because of the following exception: ", exception);
        }

        logger(AREA, DEBUG, "==== Finished Closing Connections ====");
    }
Esempio n. 6
0
    public static void readPLCSequenceBreak()
    {
        try
        {
            string sql = "SELECT * FROM plc_sequence_reset WHERE RESET = 1;";
            using var cmd             = new MySqlCommand(sql, db);
            using MySqlDataReader rdr = cmd.ExecuteReader();
            int id = 999;

            while (rdr.Read())
            {
                id = rdr.GetInt32(0);
                SiemensPLC.updateResetBits(id);
            }

            cmd.Dispose();
            rdr.Close();

            if (id < 999)
            {
                using var cmd1 = new MySqlCommand("UPDATE plc_sequence_reset SET RESET = 0 WHERE ID = " + id + ";", db);
                issueQuery(cmd1);

                cmd1.Dispose();
                rdr.Close();

                using var cmd2 = new MySqlCommand("UPDATE plc_reset SET RESET_REQUIRED = 0", db);
                issueQuery(cmd2);
            }
        }
        catch (Exception e)
        {
            logger(AREA, ERROR, "Failed Resetting Sequence Bits");
            logger(AREA, ERROR, "Exception: ", e);
        }
    }
Esempio n. 7
0
    /// <summary>
    /// Establishes default communications with the PLC and standard headers for HTTP REST traffic.
    /// </summary>
    public static void setUpDefaultComms()
    {
        logger(AREA, DEBUG, "==== Setting Up Connection Details ====");

        try
        {
            comms = new HttpClient();
            comms.DefaultRequestVersion = HttpVersion.Version11;
            comms.DefaultRequestHeaders.Accept.Clear();
            comms.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            comms.DefaultRequestHeaders.Add("Accept-Language", "en_US");
            comms.Timeout = TimeSpan.FromMinutes(10);

            logger(AREA, INFO, "MiR HTTP Header Created");
        }
        catch (Exception exception)
        {
            logger(AREA, ERROR, "Failed to set up an HTTP Connection. Error: ", exception);
        }

        SiemensPLC.establishConnection();

        logger(AREA, DEBUG, "==== Connections Established ====");
    }
Esempio n. 8
0
    /// <summary>
    /// Used to check the mission status on both the Robot and the Fleet level
    /// </summary>
    private static void checkMissionAssignment(Stopwatch robotAssignment)
    {
        logger(AREA, DEBUG, "Checking Mission Assignment");

        if (mirFleet.fleetManager.schedule.working_response)
        {
            // We're waiting for the Fleet to assign a robot to a mission in queue

            int currentMissionRobot = 0;
            int restStatus          = 0;

            logger(AREA, INFO, "Current Scheduler Fleet Robot ID is: " + mirFleet.fleetManager.schedule.robot_id);
            logger(AREA, INFO, "Current Mission Schedule ID is: " + mirFleet.fleetManager.schedule.id);

            restStatus = mirFleet.issueGetRequest("mission_scheduler/" + mirFleet.fleetManager.schedule.id, fleetID);

            logger(AREA, DEBUG, "Mission Scheduler Robot ID After polling is: " + mirFleet.fleetManager.schedule.robot_id);

            if (restStatus == Globals.TaskStatus.CompletedNoErrors && mirFleet.fleetManager.schedule.robot_id != 0)
            {
                logger(AREA, INFO, "It Took Fleet " + robotAssignment.Elapsed.TotalSeconds + " Seconds To Find An Available Robot");
                robotAssignment.Stop();

                //currentMissionRobot = mirFleet.fleetManager.schedule.robot_id - 3; // TODO: This is as the robots are offset by one in fleet - change to be better

                currentMissionRobot = mirFleet.getInternalRobotID(mirFleet.fleetManager.schedule.robot_id);

                mirFleet.returnParameter = (short)(mirFleet.robots[currentMissionRobot].plcRobotID);

                logger(AREA, INFO, "Mission " + mirFleet.fleetManager.schedule.id + " Has A New Robot (Mirage: " + currentMissionRobot + ", Fleet: " + mirFleet.fleetManager.schedule.robot_id + ")");

                mirFleet.robots[currentMissionRobot].schedule.id = mirFleet.fleetManager.schedule.id;

                occupyRobot(currentMissionRobot);

                restStatus = Globals.TaskStatus.CompletedNoErrors;

                // Add a record to the robot's job ledger - this is a new mission added on top of the existing mission stack
                int mission_number = mirFleet.fleetManager.schedule.mission_number;
                mirFleet.robots[currentMissionRobot].currentJob.startJob(mission_number, mirFleet.fleetManager.Missions[mission_number].name);

                mirFleet.fleetManager.schedule.working_response = false;
            }
            else
            {
                restStatus = Globals.TaskStatus.StartedProcessing;
                mirFleet.fleetManager.schedule.working_response = true;
            }

            SiemensPLC.writeFleetBlock(restStatus);
        }

        // Check the mission status for each robot
        for (int r = 0; r < sizeOfFleet; r++)
        {
            int restStatus = 0;

            // Don't check if we're idling or if we aborted the job
            // Used to be: if (mirFleet.robots[r].schedule.id != Globals.TaskStatus.Idle)
            // Now we don't scan if the PLC Task Status is idle (since the mir isn't doing anything)
            // && SiemensPLC.robots[r].getPLCTaskStatus() != Globals.TaskStatus.Idle

            // Also changed:
            // if (mirFleet.robots[r].schedule.id != Globals.TaskStatus.Idle &&
            // To:
            // if (mirFleet.robots[r].schedule.id != 0 &&
            if (mirFleet.robots[r].schedule.id != 0 &&
                (robots[r].getPLCTaskStatus() != Globals.TaskStatus.Idle ||
                 fleetBlock.getPLCTaskStatus() != Globals.TaskStatus.Idle ||
                 mirFleet.robots[r].schedule.state_id != Globals.TaskStatus.Idle))
            {
                // Check the status of the mission assigned to robot r
                logger(AREA, INFO, "==== Robot ID: " + r + " And Mission Scheduler Robot ID is: " + mirFleet.robots[r].fleetRobotID + " ====");
                logger(AREA, INFO, "Mission Schedule ID is: " + mirFleet.robots[r].schedule.id);

                restStatus = mirFleet.checkMissionSchedule("mission_scheduler/" + mirFleet.robots[r].schedule.id + "?whilelist=state", fleetID, r);

                logger(AREA, INFO, "Mission Status For Robot: " + r + " is: " + mirFleet.robots[r].schedule.state);

                if (robots[r].getTaskParameter() == 351 || robots[r].getTaskParameter() == 352)
                {
                    logger(AREA, INFO, "Conveyor On/Off Register In MiR is: " + mirFleet.robots[r].Registers[1].value);
                    logger(AREA, INFO, "Mission Status is: " + mirFleet.robots[r].schedule.state_id);

                    if (mirFleet.robots[r].schedule.state == "Pending")
                    {
                        mirFleet.robots[r].schedule.state_id = Globals.TaskStatus.TaskReceivedFromPLC;
                    }
                    else if (mirFleet.robots[r].schedule.state == "Executing" && (int)(mirFleet.robots[r].Registers[1].value) == 1)
                    {
                        mirFleet.robots[r].schedule.state_id = Globals.TaskStatus.StartedProcessing;
                    }
                    else if (mirFleet.robots[r].schedule.state == "Outbound")
                    {
                        mirFleet.robots[r].schedule.state_id = Globals.TaskStatus.TaskReceivedFromPLC;
                    }
                    else if (mirFleet.robots[r].schedule.state == "Aborted")
                    {
                        mirFleet.robots[r].schedule.state_id = Globals.TaskStatus.CouldntProcessRequest;
                        mirFleet.robots[r].schedule.id       = 0;
                        updateTaskStatus(r, Globals.TaskStatus.CouldntProcessRequest);
                        //mirFleet.robots[r].currentJob.finishMission();
                        mirFleet.robots[r].currentJob.finishJob(r, true);
                    }
                    else if (mirFleet.robots[r].schedule.state == "Done")
                    {
                        mirFleet.robots[r].schedule.state_id = Globals.TaskStatus.CompletedNoErrors;
                        mirFleet.robots[r].schedule.id       = 0;
                        mirFleet.robots[r].currentJob.finishMission();
                    }
                }
                else
                {
                    if (mirFleet.robots[r].schedule.state == "Pending")
                    {
                        mirFleet.robots[r].schedule.state_id = Globals.TaskStatus.TaskReceivedFromPLC;
                    }
                    else if (mirFleet.robots[r].schedule.state == "Executing")
                    {
                        mirFleet.robots[r].schedule.state_id = Globals.TaskStatus.StartedProcessing;
                    }
                    else if (mirFleet.robots[r].schedule.state == "Outbound")
                    {
                        mirFleet.robots[r].schedule.state_id = Globals.TaskStatus.StartedProcessing;
                    }
                    else if (mirFleet.robots[r].schedule.state == "Aborted")
                    {
                        mirFleet.robots[r].schedule.state_id = Globals.TaskStatus.CouldntProcessRequest;
                        updateTaskStatus(r, Globals.TaskStatus.CouldntProcessRequest);
                        //mirFleet.robots[r].currentJob.finishMission();
                        mirFleet.robots[r].currentJob.finishJob(r, true);
                        mirFleet.robots[r].schedule.id = 0;
                    }
                    else if (mirFleet.robots[r].schedule.state == "Done")
                    {
                        // Used to be else if (mirFleet.robots[r].schedule.state == "Done")
                        // Potentially remove this condition as the dock prox checks are now done inside MiRs
                        if ((int)(mirFleet.robots[r].Registers[2].value) == 1)
                        {
                            mirFleet.robots[r].schedule.state_id = Globals.TaskStatus.CompletedNoErrors;
                            mirFleet.robots[r].schedule.id       = 0;
                            mirFleet.robots[r].currentJob.finishMission();
                        }
                        else if (robots[r].getTaskParameter() == 353)
                        {
                            mirFleet.robots[r].schedule.state_id = Globals.TaskStatus.CompletedNoErrors;
                            mirFleet.robots[r].schedule.id       = 0;
                            mirFleet.robots[r].currentJob.finishMission();
                        }
                        else
                        {
                            mirFleet.robots[r].schedule.state_id = Globals.TaskStatus.CouldntProcessRequest;
                            mirFleet.robots[r].schedule.id       = 0;
                            mirFleet.robots[r].currentJob.finishMission();
                        }
                    }
                    else
                    {
                        mirFleet.robots[r].schedule.state_id = Globals.TaskStatus.StartedProcessing;
                    }
                }

                logger(AREA, DEBUG, "Mission Status For Robot: " + r + " State ID is: " + mirFleet.robots[r].schedule.state_id);
            }
        }
    }