示例#1
0
        public async Task ExecuteAsync(Parameter parameter)
        {
            if (!IsInitSuccess)
            {
                return;
            }

            if (parameter.Parameters.Length > MaxParameterCount)
            {
                ShellOut.Error("Too many arguments.");
                return;
            }

            if (parameter.Parameters == null || parameter.Parameters.Length <= 0)
            {
                return;
            }

            await Sync.WaitAsync().ConfigureAwait(false);

            try {
                if (OnExecuteFunc != null)
                {
                    if (OnExecuteFunc.Invoke(parameter))
                    {
                        return;
                    }
                }

                switch (parameter.ParameterCount)
                {
                case 1 when !string.IsNullOrEmpty(parameter.Parameters[0].Trim()):
                    string bashScriptPath = parameter.Parameters[0].Trim();

                    if (!File.Exists(bashScriptPath))
                    {
                        ShellOut.Error($"{bashScriptPath} doesn't exist.");
                        return;
                    }

                    ShellOut.Info($"Executing {bashScriptPath} ...");
                    ShellOut.Info(bashScriptPath.ExecuteBash(false));
                    return;

                default:
                    ShellOut.Error("Command seems to be in incorrect syntax.");
                    return;
                }
            }
            catch (Exception e) {
                ShellOut.Exception(e);
                return;
            }
            finally {
                Sync.Release();
            }
        }
示例#2
0
        /// <summary>
        /// Executes the received command by first parsing it then executing with the parsed values.
        /// </summary>
        /// <param name="command">The command<see cref="string"/></param>
        /// <returns>The <see cref="bool"/></returns>
        private static async Task <bool> ExecuteCommandAsync(string?command)
        {
            if (!InitCompleted)
            {
                Logger.Warning("Shell isn't initiated properly.");
                ShellOut.Error("Shell is offline!");
                return(false);
            }

            if (string.IsNullOrEmpty(command))
            {
                Logger.Trace("Command is null.");
                ShellOut.Error("Command empty or invalid.");
                return(false);
            }

            CurrentCommand = command;
            return(await ParseCommandAsync(command).ConfigureAwait(false));
        }
示例#3
0
        private void PrintAll()
        {
            if (Interpreter.CommandsCount <= 0)
            {
                ShellOut.Error("No commands exist.");
                return;
            }

            ShellOut.Info("--------------------------------------- Shell Commands ---------------------------------------");
            foreach (KeyValuePair <string, IShellCommand> cmd in Interpreter.Commands)
            {
                if (string.IsNullOrEmpty(cmd.Key) || cmd.Value == null)
                {
                    continue;
                }

                cmd.Value.OnHelpExec(false);
            }
            ShellOut.Info("----------------------------------------------------------------------------------------------");
        }
        public async Task ExecuteAsync(Parameter parameter)
        {
            if (!IsInitSuccess)
            {
                return;
            }

            if (!Core.CoreInitiationCompleted)
            {
                ShellOut.Error("Cannot execute as the core hasn't been successfully started yet.");
                return;
            }

            if (parameter.Parameters.Length > MaxParameterCount)
            {
                ShellOut.Error("Too many arguments.");
                return;
            }

            await Sync.WaitAsync().ConfigureAwait(false);

            try {
                switch (parameter.ParameterCount)
                {
                case 0:
                default:
                    ShellOut.Info("After this process, you wont be able to execute shell commands in assistant...");
                    Interpreter.ShutdownShell = true;
                    ShellOut.Info("Shutdown process started!");
                    return;
                }
            }
            catch (Exception e) {
                ShellOut.Exception(e);
                return;
            }
            finally {
                Sync.Release();
            }
        }
示例#5
0
        /// <summary>
        /// The REPL Loop. <br>Loops until an external shutdown of the shell as been triggered by the assistant core program.</br>
        /// </summary>
        /// <returns></returns>
        private static async Task ReplAsync()
        {
            if (!InitCompleted)
            {
                return;
            }

            await LoopSync.WaitAsync().ConfigureAwait(false);

            try {
                Console.WriteLine("Assistant Shell waiting for your commands!");
                do
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.Write($"#~/{Core.AssistantName.Trim()}/$ |> ");
                    Console.ResetColor();
                    string command = Console.ReadLine();

                    if (string.IsNullOrEmpty(command) || string.IsNullOrWhiteSpace(command))
                    {
                        ShellOut.Error("Please input a valid command.");
                        continue;
                    }

                    await ExecuteCommandAsync(command).ConfigureAwait(false);
                } while (!ShutdownShell);
            }
            catch (Exception e) {
                Logger.Exception(e);
                return;
            }
            finally {
                LoopSync.Release();
                Logger.Info("Shell has been shutdown.");
            }
        }
        public async Task ExecuteAsync(Parameter parameter)
        {
            if (!IsInitSuccess)
            {
                return;
            }

            if (parameter.Parameters.Length > MaxParameterCount)
            {
                ShellOut.Error("Too many arguments.");
                return;
            }

            await Sync.WaitAsync().ConfigureAwait(false);

            try {
                if (OnExecuteFunc != null)
                {
                    if (OnExecuteFunc.Invoke(parameter))
                    {
                        return;
                    }
                }

                string?apiKey;
                if (string.IsNullOrEmpty(Core.Config.OpenWeatherApiKey))
                {
                    ShellOut.Error("Weather API key isn't set.");

                    apiKey = ShellOut.GetString("Open Weather Api Key");

                    if (string.IsNullOrEmpty(apiKey))
                    {
                        ShellOut.Error("Api key is invalid or not set properly.");
                        return;
                    }
                }

                apiKey = Core.Config.OpenWeatherApiKey;
                int pinCode;
                Weather.WeatherResponse?weather;

                switch (parameter.ParameterCount)
                {
                case 0:
                    ShellOut.Error("Pin code is invalid or not set.");
                    return;

                case 1 when !string.IsNullOrEmpty(parameter.Parameters[0]):
                    if (!int.TryParse(parameter.Parameters[0], out pinCode))
                    {
                        ShellOut.Error("Failed to parse pin code. Entered pin code is invalid.");
                        return;
                    }

                    weather = await Core.WeatherClient.GetWeather(apiKey, pinCode, "in").ConfigureAwait(false);

                    if (weather == null || weather.Location == null || weather.Wind == null || weather.Data == null)
                    {
                        ShellOut.Error("Weather request failed.");
                        return;
                    }

                    ShellOut.Info($"---------- Weather Data | {weather.LocationName} | {weather.Location.Latitude}:{weather.Location.Longitude} ----------");
                    ShellOut.Info($"Wind Speed: {weather.Wind.Speed}");
                    ShellOut.Info($"Humidity: {weather.Data.Humidity}");
                    ShellOut.Info($"Pressure: {weather.Data.Pressure}");
                    ShellOut.Info($"Sea Level: {weather.Data.SeaLevel}");
                    ShellOut.Info($"Temperature: {KelvinToCelsius(weather.Data.Temperature)} C");
                    return;

                case 2 when !string.IsNullOrEmpty(parameter.Parameters[0]) && !string.IsNullOrEmpty(parameter.Parameters[1]):
                    if (!int.TryParse(parameter.Parameters[0], out pinCode))
                    {
                        ShellOut.Error("Pin code is invalid.");
                        return;
                    }

                    if (parameter.Parameters[1].Length > 3)
                    {
                        ShellOut.Error("Country code is invalid.");
                        return;
                    }

                    weather = await Core.WeatherClient.GetWeather(apiKey, pinCode, parameter.Parameters[1]).ConfigureAwait(false);

                    if (weather == null || weather.Location == null || weather.Wind == null || weather.Data == null)
                    {
                        ShellOut.Error("Weather request failed.");
                        return;
                    }

                    ShellOut.Info($"---------- Weather Data | {weather.LocationName} | {weather.Location.Latitude}:{weather.Location.Longitude} ----------");
                    ShellOut.Info($"Wind Speed: {weather.Wind.Speed}");
                    ShellOut.Info($"Humidity: {weather.Data.Humidity}");
                    ShellOut.Info($"Pressure: {weather.Data.Pressure}");
                    ShellOut.Info($"Sea Level: {weather.Data.SeaLevel}");
                    ShellOut.Info($"Temperature: {KelvinToCelsius(weather.Data.Temperature)} C");
                    return;

                case 3 when !string.IsNullOrEmpty(parameter.Parameters[0]) && !string.IsNullOrEmpty(parameter.Parameters[1]) && !string.IsNullOrEmpty(parameter.Parameters[2]):
                    if (!int.TryParse(parameter.Parameters[0], out pinCode))
                    {
                        ShellOut.Error("Pin code is invalid.");
                        return;
                    }

                    if (parameter.Parameters[1].Length > 3)
                    {
                        ShellOut.Error("Country code is invalid.");
                        return;
                    }

                    if (!parameter.Parameters[2].AsBool(out bool?tts))
                    {
                        ShellOut.Error("'TTS' argument is invalid.");
                        return;
                    }

                    weather = await Core.WeatherClient.GetWeather(apiKey, pinCode, parameter.Parameters[1]).ConfigureAwait(false);

                    if (weather == null || weather.Location == null || weather.Wind == null || weather.Data == null)
                    {
                        ShellOut.Error("Weather request failed.");
                        return;
                    }

                    if (tts != null && tts.HasValue && tts.Value)
                    {
                        Helpers.InBackground(async() => await TTS.SpeakText($"Weather Data for {weather.LocationName}. " +
                                                                            $"Wind Speed is {weather.Wind.Speed}. " +
                                                                            $"Humidity level is {weather.Data.Humidity}. Pressure level {weather.Data.Pressure}. " +
                                                                            $"Sea Level is {weather.Data.SeaLevel}. Temperature is {weather.Data.Temperature}.", true));
                    }

                    ShellOut.Info($"---------- Weather Data | {weather.LocationName} | {weather.Location.Latitude}:{weather.Location.Longitude} ----------");
                    ShellOut.Info($"Wind Speed: {weather.Wind.Speed}");
                    ShellOut.Info($"Humidity: {weather.Data.Humidity}");
                    ShellOut.Info($"Pressure: {weather.Data.Pressure}");
                    ShellOut.Info($"Sea Level: {weather.Data.SeaLevel}");
                    ShellOut.Info($"Temperature: {KelvinToCelsius(weather.Data.Temperature)} C");
                    return;

                default:
                    ShellOut.Error("Command seems to be in incorrect syntax.");
                    return;
                }
            }
            catch (Exception e) {
                ShellOut.Exception(e);
                return;
            }
            finally {
                Sync.Release();
            }
        }
示例#7
0
        /// <summary>
        /// Executes the command.
        /// Searches the command with its command key on the internal command collection.
        /// Cross checks the result command by verifying its argument count.
        /// Then executes the command.
        /// </summary>
        /// <param name="commandKey">The command key</param>
        /// <param name="parameters">The parameters</param>
        /// <returns>Boolean indicating status of the execution</returns>
        private static async Task <bool> Execute(string commandKey, string[] parameters)
        {
            IShellCommand command = await Init.GetCommandWithKeyAsync <IShellCommand>(commandKey).ConfigureAwait(false);

            if (command == null)
            {
                ShellOut.Error("Command doesn't exist. use 'help' to check all available commands!");
                return(false);
            }

            try {
                if (!command.IsInitSuccess)
                {
                    await command.InitAsync().ConfigureAwait(false);
                }

                if (!command.IsCurrentCommandContext(command.CommandKey, parameters.Length))
                {
                    ShellOut.Error("Command doesn't match the syntax. Please retype.");
                    return(false);
                }

                if (!command.HasParameters && parameters.Length > 0)
                {
                    ShellOut.Info($"'{command.CommandName}' doesn't require any arguments.");

                    string args = string.Empty;
                    for (int i = 0; i < parameters.Length; i++)
                    {
                        if (!string.IsNullOrEmpty(parameters[i]))
                        {
                            args += parameters[i] + ",";
                        }
                    }

                    ShellOut.Info($"Entered arguments '{args}' will be trimmed out.");
                    parameters = new string[0];
                }

                if (parameters.Length > command.MaxParameterCount)
                {
                    ShellOut.Info($"'{command.CommandName}' only supports a maximum of '{command.MaxParameterCount}' arguments. You have entered '{parameters.Length}'");

                    string args = string.Empty;
                    for (int i = (parameters.Length - command.MaxParameterCount) - 1; i > parameters.Length - command.MaxParameterCount; i--)
                    {
                        parameters[i] = null;
                    }

                    ShellOut.Info($"'{parameters.Length - command.MaxParameterCount}' arguments will be trimmed out.");
                    return(false);
                }

                Sound.PlayNotification(Sound.ENOTIFICATION_CONTEXT.ALERT);
                await command.ExecuteAsync(new Parameter(commandKey, parameters)).ConfigureAwait(false);

                return(true);
            }
            finally {
                command.Dispose();
            }
        }
示例#8
0
        /// <summary>
        /// Parses the raw command string value. <br>Then executes it by calling the Execute() method with the parsed values.</br>
        /// </summary>
        /// <param name="cmd">The command <see cref="string"/></param>
        /// <returns>The <see cref="bool"/></returns>
        private static async Task <bool> ParseCommandAsync(string cmd)
        {
            if (Commands.Count <= 0)
            {
                ShellOut.Info("No commands have been loaded into the shell.");
                return(false);
            }

            if (string.IsNullOrEmpty(cmd))
            {
                ShellOut.Error("Invalid command.");
                return(false);
            }

            await Sync.WaitAsync().ConfigureAwait(false);

            bool anyExec = false;

            try {
                // If there is multiple commands separated by the Multi command delimiter
                if (cmd.Contains(ShellConstants.MULTI_COMMAND))
                {
                    //commands - returns {help -argument}
                    string[] cmdSplit = cmd.Split(ShellConstants.MULTI_COMMAND, StringSplitOptions.RemoveEmptyEntries);

                    if (cmdSplit == null || cmdSplit.Length <= 0)
                    {
                        ShellOut.Error("Failed to parse the command. Please retype in correct syntax!");
                        return(false);
                    }

                    // for each -> {help -arg1 -arg2}
                    for (int i = 0; i < cmdSplit.Length; i++)
                    {
                        if (string.IsNullOrEmpty(cmdSplit[i]))
                        {
                            continue;
                        }

                        bool     doesContainArgs = cmdSplit[i].Contains(ShellConstants.ARGUMENT_SPLITTER);
                        string[] parameters      = new string[0];
                        string?  commandKey      = null;

                        // If contains arguments
                        if (doesContainArgs)
                        {
                            string[] cmdArgumentSplit = cmdSplit[i].Split(ShellConstants.ARGUMENT_SPLITTER, StringSplitOptions.RemoveEmptyEntries);
                            if (cmdArgumentSplit == null || cmdArgumentSplit.Length <= 0)
                            {
                                continue;
                            }

                            parameters = new string[cmdArgumentSplit.Length - 1];

                            for (int k = 0; k < cmdArgumentSplit.Length; k++)
                            {
                                if (string.IsNullOrEmpty(cmdArgumentSplit[k]))
                                {
                                    continue;
                                }

                                cmdArgumentSplit[k] = Replace(cmdArgumentSplit[k].Trim());

                                if (string.IsNullOrEmpty(commandKey))
                                {
                                    commandKey = cmdArgumentSplit[k];
                                }

                                if (cmdArgumentSplit[k].Equals(commandKey, StringComparison.OrdinalIgnoreCase))
                                {
                                    continue;
                                }

                                parameters[k - 1] = cmdArgumentSplit[k];
                            }
                        }
                        else
                        {
                            // If no arguments
                            commandKey = Replace(cmdSplit[i].Trim());
                        }

                        if (string.IsNullOrEmpty(commandKey))
                        {
                            continue;
                        }

                        if (await Execute(commandKey, parameters))
                        {
                            anyExec = true;
                        }
                        continue;
                    }
                }
                else
                {
                    //If there is only single command
                    bool     doesContainArgs = cmd.Contains(ShellConstants.ARGUMENT_SPLITTER);
                    string[] parameters      = new string[0];
                    string?  commandKey      = null;

                    if (doesContainArgs)
                    {
                        string[] cmdArgumentSplit = cmd.Split(ShellConstants.ARGUMENT_SPLITTER, StringSplitOptions.RemoveEmptyEntries);

                        if (cmdArgumentSplit == null || cmdArgumentSplit.Length <= 0)
                        {
                            return(false);
                        }

                        parameters = new string[cmdArgumentSplit.Length - 1];

                        for (int k = 0; k < cmdArgumentSplit.Length; k++)
                        {
                            if (string.IsNullOrEmpty(cmdArgumentSplit[k]))
                            {
                                continue;
                            }

                            cmdArgumentSplit[k] = Replace(cmdArgumentSplit[k].Trim());

                            if (string.IsNullOrEmpty(commandKey))
                            {
                                commandKey = cmdArgumentSplit[k];
                            }

                            if (cmdArgumentSplit[k].Equals(commandKey, StringComparison.OrdinalIgnoreCase))
                            {
                                continue;
                            }

                            parameters[k - 1] = cmdArgumentSplit[k];
                        }
                    }
                    else
                    {
                        commandKey = Replace(cmd.Trim());
                    }

                    if (string.IsNullOrEmpty(commandKey))
                    {
                        return(false);
                    }

                    if (await Execute(commandKey, parameters))
                    {
                        anyExec = true;
                    }
                }

                if (!anyExec)
                {
                    return(false);
                }

                return(true);
            }
            catch (Exception e) {
                Logger.Log(e);
                ShellOut.Error("Internal exception occurred. Execution failed unexpectedly.");
                ShellOut.Exception(e);
                return(false);
            }
            finally {
                Sync.Release();
            }
        }
        public async Task ExecuteAsync(Parameter parameter)
        {
            if (!IsInitSuccess)
            {
                return;
            }

            if (parameter.Parameters.Length > MaxParameterCount)
            {
                ShellOut.Error("Too many arguments.");
                return;
            }

            await Sync.WaitAsync().ConfigureAwait(false);

            MorseCore morseCore = GpioMorseTranslator.GetCore();
            string    morse     = string.Empty;

            try {
                if (OnExecuteFunc != null)
                {
                    if (OnExecuteFunc.Invoke(parameter))
                    {
                        return;
                    }
                }

                switch (parameter.ParameterCount)
                {
                case 1 when !string.IsNullOrEmpty(parameter.Parameters[0]):
                    morse = morseCore.ConvertToMorseCode(parameter.Parameters[0]);

                    if (string.IsNullOrEmpty(morse) || !morseCore.IsValidMorse(morse))
                    {
                        ShellOut.Error("Failed to verify generated morse code.");
                        return;
                    }

                    ShellOut.Info(">>> " + morse);
                    return;

                case 2 when !string.IsNullOrEmpty(parameter.Parameters[0]) && !string.IsNullOrEmpty(parameter.Parameters[1]):
                    morse = morseCore.ConvertToMorseCode(parameter.Parameters[0]);

                    if (string.IsNullOrEmpty(morse) || !morseCore.IsValidMorse(morse))
                    {
                        ShellOut.Error("Failed to verify generated morse code.");
                        return;
                    }

                    ShellOut.Info(">>> " + morse);
                    GpioMorseTranslator?translator = PiGpioController.GetMorseTranslator();

                    if (translator == null || !translator.IsTranslatorOnline)
                    {
                        ShellOut.Error("Morse translator might be offline.");
                        return;
                    }

                    if (!int.TryParse(parameter.Parameters[1], out int relayNumber))
                    {
                        ShellOut.Error("Relay number argument is invalid.");
                        return;
                    }

                    if (!PinController.IsValidPin(PiGpioController.AvailablePins.OutputPins[relayNumber]))
                    {
                        ShellOut.Error("The specified pin is invalid.");
                        return;
                    }

                    await translator.RelayMorseCycle(morse, PiGpioController.AvailablePins.OutputPins[relayNumber]);

                    ShellOut.Info("Completed!");
                    return;

                default:
                    ShellOut.Error("Command seems to be in incorrect syntax.");
                    return;
                }
            }
            catch (Exception e) {
                ShellOut.Exception(e);
                return;
            }
            finally {
                Sync.Release();
            }
        }
示例#10
0
        public async Task ExecuteAsync(Parameter parameter)
        {
            if (!IsInitSuccess)
            {
                return;
            }

            if (parameter.Parameters.Length > MaxParameterCount)
            {
                ShellOut.Error("Too many arguments.");
                return;
            }

            await Sync.WaitAsync().ConfigureAwait(false);

            try {
                if (OnExecuteFunc != null)
                {
                    if (OnExecuteFunc.Invoke(parameter))
                    {
                        return;
                    }
                }

                int exitCode = 0;
                switch (parameter.ParameterCount)
                {
                case 0:
                    ShellOut.Info("Exiting assistant in 5 seconds...");
                    Helpers.ScheduleTask(async() => await Core.Exit(0).ConfigureAwait(false), TimeSpan.FromSeconds(5));
                    return;

                case 1 when !string.IsNullOrEmpty(parameter.Parameters[0]):
                    if (!int.TryParse(parameter.Parameters[0], out exitCode))
                    {
                        ShellOut.Error("Couldn't parse exit code argument.");
                        return;
                    }

                    ShellOut.Info($"Exiting assistant with '{exitCode}' exit code in 5 seconds...");
                    Helpers.ScheduleTask(async() => await Core.Exit(exitCode).ConfigureAwait(false), TimeSpan.FromSeconds(5));
                    return;

                case 2 when !string.IsNullOrEmpty(parameter.Parameters[0]) && !string.IsNullOrEmpty(parameter.Parameters[1]):
                    if (!int.TryParse(parameter.Parameters[0], out exitCode))
                    {
                        ShellOut.Error("Couldn't parse exit code argument.");
                        return;
                    }

                    if (!int.TryParse(parameter.Parameters[1], out int delay))
                    {
                        ShellOut.Error("Couldn't parse delay argument.");
                        return;
                    }

                    ShellOut.Info($"Exiting assistant with '{exitCode}' exit code in '{delay}' seconds...");
                    Helpers.ScheduleTask(async() => await Core.Exit(exitCode).ConfigureAwait(false), TimeSpan.FromSeconds(delay));
                    return;

                default:
                    ShellOut.Error("Command seems to be in incorrect syntax.");
                    return;
                }
            }
            catch (Exception e) {
                ShellOut.Exception(e);
                return;
            }
            finally {
                Sync.Release();
            }
        }
示例#11
0
        public async Task ExecuteAsync(Parameter parameter)
        {
            if (!IsInitSuccess)
            {
                return;
            }

            if (parameter.Parameters.Length > MaxParameterCount)
            {
                ShellOut.Error("Too many arguments.");
                return;
            }

            await Sync.WaitAsync().ConfigureAwait(false);

            try {
                if (OnExecuteFunc != null)
                {
                    if (OnExecuteFunc.Invoke(parameter))
                    {
                        return;
                    }
                }

                switch (parameter.ParameterCount)
                {
                case 0:
                    foreach (KeyValuePair <string, IShellCommand> cmd in Interpreter.Commands)
                    {
                        if (string.IsNullOrEmpty(cmd.Value.CommandKey) || string.IsNullOrEmpty(cmd.Value.CommandName))
                        {
                            continue;
                        }

                        cmd.Value.OnHelpExec(true);
                    }
                    return;

                case 1 when !string.IsNullOrEmpty(parameter.Parameters[0]) && parameter.Parameters[0].Equals("all", StringComparison.OrdinalIgnoreCase):
                    PrintAll();
                    return;

                case 1 when !string.IsNullOrEmpty(parameter.Parameters[0]):
                    IShellCommand shellCmd = await Interpreter.Init.GetCommandWithKeyAsync <IShellCommand>(parameter.Parameters[0]).ConfigureAwait(false);

                    if (shellCmd == null)
                    {
                        ShellOut.Error("Command doesn't exist. use ' help -all ' to check all available commands!");
                        return;
                    }

                    shellCmd.OnHelpExec(false);
                    return;

                default:
                    ShellOut.Error("Command seems to be in incorrect syntax.");
                    return;
                }
            }
            catch (Exception e) {
                ShellOut.Exception(e);
                return;
            }
            finally {
                Sync.Release();
            }
        }
示例#12
0
        public async Task ExecuteAsync(Parameter parameter)
        {
            if (!IsInitSuccess)
            {
                return;
            }

            if (!Core.CoreInitiationCompleted)
            {
                ShellOut.Error("Cannot execute as the core hasn't been successfully started yet.");
                return;
            }

            if (parameter.Parameters.Length > MaxParameterCount)
            {
                ShellOut.Error("Too many arguments.");
                return;
            }

            if (!PiGpioController.IsAllowedToExecute)
            {
                ShellOut.Error("Gpio functions are not allowed to execute.");
                ShellOut.Info("Gpio pin controlling functions are only available on raspberry pi with an OS such as Raspbian.");
                return;
            }

            await Sync.WaitAsync().ConfigureAwait(false);

            try {
                if (OnExecuteFunc != null)
                {
                    if (OnExecuteFunc.Invoke(parameter))
                    {
                        return;
                    }
                }

                if (parameter.Parameters == null || parameter.Parameters.Length == 0)
                {
                    ShellOut.Error("Gpio pin, Pin state, pin mode values are not specified.");
                    return;
                }

                if (string.IsNullOrEmpty(parameter.Parameters[0]))
                {
                    ShellOut.Error("Gpio pin is invalid or not specified.");
                    return;
                }

                int          pin;
                GpioPinMode  pinMode;
                GpioPinState pinState;
                bool         isSet;

                IGpioControllerDriver?driver = PinController.GetDriver();
                if (driver == null || !driver.IsDriverProperlyInitialized)
                {
                    ShellOut.Error("Internal error occurred with the gpio driver. Please restart the assistant.");
                    return;
                }

                switch (parameter.ParameterCount)
                {
                case 1 when !string.IsNullOrEmpty(parameter.Parameters[0]):
                    ShellOut.Info("Note: as only 1 argument is specified, the default value will be set for the specified pin.");

                    if (!int.TryParse(parameter.Parameters[0], out pin))
                    {
                        ShellOut.Error("Failed to parse gpio pin value.");
                        return;
                    }

                    ShellOut.Info($"{pin} will be set to Output mode and configured in On state.");

                    if (!Constants.BcmGpioPins.Contains(pin) || !PinController.IsValidPin(pin) || !Core.Config.OutputModePins.Contains(pin))
                    {
                        ShellOut.Error("Specified gpio pin is an invalid.");
                        return;
                    }

                    isSet = driver.TogglePinState(pin);

                    if (!isSet)
                    {
                        ShellOut.Error($"Failed to configure {pin} gpio pin. Please validate the pin argument.");
                        return;
                    }

                    ShellOut.Info($"Successfully configured {pin} gpio pin.");
                    return;

                case 2 when !string.IsNullOrEmpty(parameter.Parameters[0]) &&
                    !string.IsNullOrEmpty(parameter.Parameters[1]) &&
                    parameter.Parameters[0].Equals("relay", StringComparison.OrdinalIgnoreCase):
                    if (!int.TryParse(parameter.Parameters[1], out int relayNum))
                    {
                        ShellOut.Error("Failed to parse relay number value.");
                        return;
                    }

                    if (!PinController.IsValidPin(PiGpioController.AvailablePins.OutputPins[relayNum]))
                    {
                        ShellOut.Error($"The pin ' {PiGpioController.AvailablePins.OutputPins[relayNum]} ' is invalid.");
                        return;
                    }

                    isSet = driver.TogglePinState(PiGpioController.AvailablePins.OutputPins[relayNum]);

                    if (!isSet)
                    {
                        ShellOut.Error($"Failed to configure {PiGpioController.AvailablePins.OutputPins[relayNum]} gpio pin. Please validate the pin argument.");
                        return;
                    }

                    ShellOut.Info($"Successfully configured {PiGpioController.AvailablePins.OutputPins[relayNum]} gpio pin.");
                    return;

                case 2 when !string.IsNullOrEmpty(parameter.Parameters[0]) &&
                    !string.IsNullOrEmpty(parameter.Parameters[1]):
                    if (!int.TryParse(parameter.Parameters[0], out pin))
                    {
                        ShellOut.Error("Failed to parse gpio pin value.");
                        return;
                    }

                    if (!int.TryParse(parameter.Parameters[1], out int modeVal))
                    {
                        ShellOut.Error("Failed to parse gpio pin mode value.");
                        return;
                    }

                    pinMode = (GpioPinMode)modeVal;

                    ShellOut.Info($"{pin} will be set to {pinMode.ToString()} mode and configured in On state.");

                    if (!Constants.BcmGpioPins.Contains(pin) || !PinController.IsValidPin(pin) || !Core.Config.OutputModePins.Contains(pin))
                    {
                        ShellOut.Error("Specified gpio pin is an invalid.");
                        return;
                    }

                    isSet = driver.SetGpioValue(pin, pinMode, GpioPinState.On);

                    if (!isSet)
                    {
                        ShellOut.Error($"Failed to configure {pin} gpio pin. Please validate the pin argument.");
                        return;
                    }

                    ShellOut.Info($"Successfully configured {pin} gpio pin.");
                    return;

                case 3 when !string.IsNullOrEmpty(parameter.Parameters[0]) &&
                    !string.IsNullOrEmpty(parameter.Parameters[1]) &&
                    !string.IsNullOrEmpty(parameter.Parameters[2]):
                    if (!int.TryParse(parameter.Parameters[0], out pin))
                    {
                        ShellOut.Error("Failed to parse gpio pin value.");
                        return;
                    }

                    if (!int.TryParse(parameter.Parameters[1], out int pinModeVal))
                    {
                        ShellOut.Error("Failed to parse gpio pin mode value.");
                        return;
                    }

                    if (!int.TryParse(parameter.Parameters[2], out int stateVal))
                    {
                        ShellOut.Error("Failed to parse gpio pin state value.");
                        return;
                    }

                    pinMode  = (GpioPinMode)pinModeVal;
                    pinState = (GpioPinState)stateVal;
                    ShellOut.Info($"{pin} will be set to {pinMode.ToString()} mode and configured in {pinState} state.");

                    if (!Constants.BcmGpioPins.Contains(pin) || !PinController.IsValidPin(pin) || !Core.Config.OutputModePins.Contains(pin))
                    {
                        ShellOut.Error("Specified gpio pin is an invalid.");
                        return;
                    }

                    isSet = driver.SetGpioValue(pin, pinMode, pinState);

                    if (!isSet)
                    {
                        ShellOut.Error($"Failed to configure {pin} gpio pin. Please validate the pin argument.");
                        return;
                    }

                    ShellOut.Info($"Successfully configured {pin} gpio pin.");
                    return;

                case 4 when !string.IsNullOrEmpty(parameter.Parameters[0]) &&
                    !string.IsNullOrEmpty(parameter.Parameters[1]) &&
                    !string.IsNullOrEmpty(parameter.Parameters[2]) &&
                    !string.IsNullOrEmpty(parameter.Parameters[3]):
                    if (!int.TryParse(parameter.Parameters[0], out pin))
                    {
                        ShellOut.Error("Failed to parse gpio pin value.");
                        return;
                    }

                    if (!int.TryParse(parameter.Parameters[1], out int modeValue))
                    {
                        ShellOut.Error("Failed to parse gpio pin mode value.");
                        return;
                    }

                    if (!int.TryParse(parameter.Parameters[2], out int stateValue))
                    {
                        ShellOut.Error("Failed to parse gpio pin state value.");
                        return;
                    }

                    if (!int.TryParse(parameter.Parameters[2], out int delayValue))
                    {
                        ShellOut.Error("Failed to parse gpio pin state value.");
                        return;
                    }

                    pinMode  = (GpioPinMode)modeValue;
                    pinState = (GpioPinState)stateValue;
                    ShellOut.Info($"{pin} will be set to {pinMode.ToString()} mode and configured in {pinState} state and set back by a delay of {delayValue} minutes.");
                    if (!Constants.BcmGpioPins.Contains(pin) || !PinController.IsValidPin(pin) || !Core.Config.OutputModePins.Contains(pin))
                    {
                        ShellOut.Error("Specified gpio pin is an invalid.");
                        return;
                    }

                    isSet = driver.SetGpioValue(pin, pinMode, pinState, TimeSpan.FromMinutes(delayValue));

                    if (!isSet)
                    {
                        ShellOut.Error($"Failed to configure {pin} gpio pin. Please validate the pin argument.");
                        return;
                    }

                    ShellOut.Info($"Successfully configured {pin} gpio pin.");
                    return;

                default:
                    ShellOut.Error("Command seems to be in incorrect syntax.");
                    return;
                }
            }
            catch (Exception e) {
                ShellOut.Exception(e);
                return;
            }
            finally {
                Sync.Release();
            }
        }