/// <summary> /// Read a G-code channel /// </summary> /// <param name="from">Origin</param> /// <param name="channel">Channel that has acquired the lock</param> /// <returns>Number of bytes read</returns> public static int ReadCodeChannel(ReadOnlySpan <byte> from, out CodeChannel channel) { CodeChannelHeader header = MemoryMarshal.Cast <byte, CodeChannelHeader>(from)[0]; channel = header.Channel; return(Marshal.SizeOf(header)); }
/// <summary> /// Read a G-code channel /// </summary> /// <param name="from">Origin</param> /// <param name="channel">Channel that has acquired the lock</param> /// <returns>Number of bytes read</returns> public static int ReadCodeChannel(ReadOnlySpan <byte> from, out CodeChannel channel) { CodeChannelHeader header = MemoryMarshal.Read <CodeChannelHeader>(from); channel = header.Channel; return(Marshal.SizeOf <CodeChannelHeader>()); }
/// <summary> /// Wait for all pending codes of the given channel to finish /// </summary> /// <param name="channel">Code channel to wait for</param> /// <param name="cancellationToken">Optional cancellation token</param> /// <returns>Asynchronous task</returns> public Task Flush(CodeChannel channel = CodeChannel.SPI, CancellationToken cancellationToken = default) { return(PerformCommand(new Flush() { Channel = channel }, cancellationToken)); }
/// <summary> /// Read a lock confirmation /// </summary> /// <param name="from">Origin</param> /// <param name="channel">Channel that has acquired the lock</param> /// <returns>Number of bytes read</returns> public static int ReadResourceLocked(ReadOnlySpan <byte> from, out CodeChannel channel) { LockUnlock header = MemoryMarshal.Cast <byte, LockUnlock>(from)[0]; channel = header.Channel; return(Marshal.SizeOf(header)); }
/// <summary> /// Lock the move module and wait for standstill /// </summary> /// <param name="channel">Code channel acquiring the lock</param> /// <returns>Whether the resource could be locked</returns> public static Task <bool> LockMovementAndWaitForStandstill(CodeChannel channel) { using (_channels[channel].Lock()) { return(_channels[channel].LockMovementAndWaitForStandstill()); } }
/// <summary> /// Unlock all resources occupied by the given channel /// </summary> /// <param name="channel">Channel holding the resources</param> /// <returns>Asynchronous task</returns> public static Task UnlockAll(CodeChannel channel) { using (_channels[channel].Lock()) { return(_channels[channel].UnlockAll()); } }
/// <summary> /// Wait for all pending codes to finish /// </summary> /// <param name="channel">Code channel to wait for</param> /// <returns>Whether the codes have been flushed successfully</returns> public static Task <bool> Flush(CodeChannel channel) { using (_channels[channel].Lock()) { return(_channels[channel].Flush()); } }
/// <summary> /// Get list of user's chats /// </summary> /// <param name="token"></param> /// <param name="jObject"></param> /// <returns></returns> public object GetChats(string token, JObject jObject) { string userName = _validator.GetUserName(token); if (_validator.CheckUser(userName)) { ChannelsList list = new ChannelsList(); foreach (var chat in _repository.GetChatsList(userName)) { Channel channel = new Channel(); channel.ChatId = chat.Id; channel.Name = chat.Name; foreach (var codeChat in _repository.GetCodeChatsList(channel.ChatId)) { CodeChannel codeChannel = new CodeChannel(); codeChannel.CodeChatId = codeChat.Id; codeChannel.MainChatName = chat.Name; codeChannel.Name = codeChat.Name; channel.CodeChats.Add(codeChannel); } list.Channels.Add(channel); } _response.Status = 20000; _response.Result = list; } else { _response.Status = 40002; _response.Result = "Validation failed!!!"; } return(_response); }
/// <summary> /// Index operator for simple access via the <see cref="CodeChannel"/> enum /// </summary> /// <param name="key">Channel to access</param> /// <returns>Channel instance</returns> public Channel this[CodeChannel key] { get { switch (key) { case CodeChannel.HTTP: return(HTTP); case CodeChannel.Telnet: return(Telnet); case CodeChannel.File: return(File); case CodeChannel.USB: return(USB); case CodeChannel.AUX: return(AUX); case CodeChannel.Daemon: return(Daemon); case CodeChannel.CodeQueue: return(CodeQueue); case CodeChannel.LCD: return(LCD); case CodeChannel.AutoPause: return(AutoPause); default: return(SPI); } } }
/// <summary> /// Constructor of this class /// </summary> /// <param name="channel">Where to evaluate the expression</param> /// <param name="createVariable">Whether the variable is supposed to be created</param> /// <param name="varName">Name of the variable</param> /// <param name="expression">Expression to evaluate</param> public VariableRequest(CodeChannel channel, bool createVariable, string varName, string expression) { Channel = channel; CreateVariable = createVariable; VariableName = varName; Expression = expression; }
/// <summary> /// Constructor of a code channel processor /// </summary> /// <param name="channel">Code channel of this instance</param> public Processor(CodeChannel channel) { _logger = NLog.LogManager.GetLogger(channel.ToString()); Channel = channel; CurrentState = new State(); Stack.Push(CurrentState); }
/// <summary> /// Read information about an abort file request /// </summary> /// <param name="from">Origin</param> /// <param name="channel">Code channel running the file</param> /// <param name="abortAll">Whether all files are supposed to be aborted</param> /// <returns>Number of bytes read</returns> public static int ReadAbortFile(ReadOnlySpan <byte> from, out CodeChannel channel, out bool abortAll) { AbortFileHeader header = MemoryMarshal.Read <AbortFileHeader>(from); channel = (CodeChannel)header.Channel; abortAll = header.AbortAll != 0; return(Marshal.SizeOf <AbortFileHeader>()); }
/// <summary> /// Read information about an abort file request /// </summary> /// <param name="from">Origin</param> /// <param name="channel">Code channel running the file</param> /// <param name="abortAll">Whether all files are supposed to be aborted</param> /// <returns>Number of bytes read</returns> public static int ReadAbortFile(ReadOnlySpan <byte> from, out CodeChannel channel, out bool abortAll) { AbortFileRequest header = MemoryMarshal.Cast <byte, AbortFileRequest>(from)[0]; channel = (CodeChannel)header.Channel; abortAll = header.AbortAll != 0; return(Marshal.SizeOf(header)); }
/// <summary> /// Establish a connection to the given UNIX socket file /// </summary> /// <param name="socketPath">Path to the UNIX socket file</param> /// <param name="bufferSize">Maximum number of codes to execute simultaneously</param> /// <param name="channel">Destination channel for incoming codes</param> /// <param name="cancellationToken">Optional cancellation token</param> /// <returns>Asynchronous task</returns> /// <exception cref="IncompatibleVersionException">API level is incompatible</exception> /// <exception cref="IOException">Connection mode is unavailable</exception> /// <exception cref="OperationCanceledException">Operation has been cancelled</exception> /// <exception cref="SocketException">Init message could not be processed</exception> public Task Connect(int bufferSize = Defaults.CodeBufferSize, CodeChannel channel = Defaults.InputChannel, string socketPath = Defaults.FullSocketPath, CancellationToken cancellationToken = default) { BufferSize = bufferSize; Channel = channel; CodeStreamInitMessage initMessage = new() { BufferSize = bufferSize, Channel = channel }; return(Connect(initMessage, socketPath, cancellationToken)); }
/// <summary> /// Unlock all resources occupied by the given channel /// </summary> /// <param name="channel">Channel holding the resources</param> /// <returns>Asynchronous task</returns> public static async Task UnlockAll(CodeChannel channel) { QueuedLockRequest request = new QueuedLockRequest(false); using (await Channels[channel].LockAsync()) { Channels[channel].PendingLockRequests.Enqueue(request); } await request.Task; }
/// <summary> /// Wait for all pending codes to finish /// </summary> /// <param name="channel">Code channel to wait for</param> /// <returns>Whether the codes have been flushed successfully</returns> public static Task <bool> Flush(CodeChannel channel) { TaskCompletionSource <bool> tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously); using (_channels[channel].Lock()) { _channels[channel].PendingFlushRequests.Enqueue(tcs); } return(tcs.Task); }
/// <summary> /// Write a G-code channel /// </summary> /// <param name="to">Destination</param> /// <param name="channel">Channel for the lock request</param> /// <returns>Number of bytes written</returns> public static int WriteCodeChannel(Span <byte> to, CodeChannel channel) { CodeChannelHeader header = new CodeChannelHeader { Channel = channel }; MemoryMarshal.Write(to, ref header); return(Marshal.SizeOf(header)); }
/// <summary> /// Read a stack event /// </summary> /// <param name="from">Origin</param> /// <param name="channel">Code channel where the stack event occurred</param> /// <param name="stackDepth">New stack depth</param> /// <param name="flags">Flags of the stack</param> /// <param name="feedrate">Feedrate in mm/s</param> /// <returns>Number of bytes read</returns> /// <seealso cref="Request.StackEvent"/> public static int ReadStackEvent(ReadOnlySpan <byte> from, out CodeChannel channel, out byte stackDepth, out StackFlags flags, out float feedrate) { StackEvent header = MemoryMarshal.Cast <byte, StackEvent>(from)[0]; channel = (CodeChannel)header.Channel; stackDepth = header.StackDepth; flags = (StackFlags)header.Flags; feedrate = header.Feedrate; return(Marshal.SizeOf(header)); }
/// <summary> /// Unlock all resources occupied by the given channel /// </summary> /// <param name="channel">Channel holding the resources</param> /// <returns>Asynchronous task</returns> public static Task UnlockAll(CodeChannel channel) { QueuedLockRequest request = new QueuedLockRequest(false); using (_channels[channel].Lock()) { _channels[channel].PendingLockRequests.Enqueue(request); } return(request.Task); }
/// <summary> /// Wait for all pending codes to finish /// </summary> /// <param name="channel">Code channel to wait for</param> /// <returns>Asynchronous task</returns> public static Task Flush(CodeChannel channel) { TaskCompletionSource <object> source = new TaskCompletionSource <object>(); using (Channels[channel].Lock()) { Channels[channel].PendingFlushRequests.Enqueue(source); } return(source.Task); }
/// <summary> /// Request a resource to be locked or unlocked /// </summary> /// <param name="to">Destination</param> /// <param name="channel">Channel for the lock request</param> /// <returns>Number of bytes written</returns> public static int WriteLockUnlock(Span <byte> to, CodeChannel channel) { LockUnlock header = new LockUnlock { Channel = channel }; MemoryMarshal.Write(to, ref header); return(Marshal.SizeOf(header)); }
/// <summary> /// Lock the move module and wait for standstill /// </summary> /// <param name="channel">Code channel acquiring the lock</param> /// <returns>Whether the resource could be locked</returns> public static Task <bool> LockMovementAndWaitForStandstill(CodeChannel channel) { QueuedLockRequest request = new QueuedLockRequest(true); using (_channels[channel].Lock()) { _channels[channel].PendingLockRequests.Enqueue(request); } return(request.Task); }
/// <summary> /// Write notification about a completed macro file /// </summary> /// <param name="to">Destination</param> /// <param name="channel">Channel where the macro file has finished</param> /// <param name="error">Whether an error occurred when trying to open/process the macro file</param> /// <returns>Number of bytes written</returns> public static int WriteMacroCompleted(Span <byte> to, CodeChannel channel, bool error) { MacroCompleted header = new MacroCompleted { Channel = channel, Error = (byte)(error ? 1 : 0) }; MemoryMarshal.Write(to, ref header); return(Marshal.SizeOf(header)); }
/// <summary> /// Create a new macro instance /// </summary> /// <param name="fileName">Filename of the macro</param> /// <param name="channel">Channel to send the codes to</param> /// <param name="startCode">Which code is starting this macro file</param> public MacroFile(string fileName, CodeChannel channel, QueuedCode startCode) : base(fileName, channel) { if (startCode == null) { string name = Path.GetFileName(fileName); IsConfig = (name == FilePath.ConfigFile || name == FilePath.ConfigFileFallback); IsConfigOverride = (name == FilePath.ConfigOverrideFile); } StartCode = startCode; Console.WriteLine($"[info] Executing {((startCode == null) ? "system" : "nested")} macro file '{fileName}' on channel {channel}"); }
/// <summary> /// Constructor of the code stream interpreter /// </summary> /// <param name="conn">Connection instance</param> /// <param name="initMessage">Initialization message from the client</param> public CodeStream(Connection conn, ClientInitMessage initMessage) : base(conn) { CodeStreamInitMessage codeStreamInitMessage = (CodeStreamInitMessage)initMessage; _bufferSize = codeStreamInitMessage.BufferSize; if (_bufferSize < 1 || _bufferSize > DuetAPI.Connection.Defaults.MaxCodeBufferSize) { throw new ArgumentException("BufferSize is out of range"); } _channel = codeStreamInitMessage.Channel; conn.Logger.Debug("CodeStream processor added"); }
/// <summary> /// Cancel pending codes of the given channel /// </summary> /// <param name="channel">Channel to cancel codes from</param> public static void CancelPending(CodeChannel channel) { lock (_cancellationTokenSources) { // Cancel and dispose the existing CTS CancellationTokenSource oldCTS = _cancellationTokenSources[(int)channel]; oldCTS.Cancel(); oldCTS.Dispose(); // Create a new one _cancellationTokenSources[(int)channel] = new CancellationTokenSource(); } }
/// <summary> /// Begin a file print /// </summary> /// <param name="fileName">File to print</param> /// <param name="source">Channel that requested the file to be printed</param> /// <returns>Code result</returns> public static async Task <CodeResult> Start(string fileName, CodeChannel source) { // Initialize the file using (await _lock.LockAsync()) { if (_file != null) { return(new CodeResult(MessageType.Error, "A file is already being printed")); } _file = new BaseFile(fileName, CodeChannel.File); IsPaused = IsAborted = false; } // Wait for all pending firmware codes on the source channel to finish first await SPI.Interface.Flush(source); // Reset the resume event if (_resumeEvent.IsSet) { await _resumeEvent.WaitAsync(); } // Analyze it and update the object model ParsedFileInfo info = await FileInfoParser.Parse(fileName); using (await Model.Provider.AccessReadWriteAsync()) { Model.Provider.Get.Channels[CodeChannel.File].VolumetricExtrusion = false; Model.Provider.Get.Job.File.Assign(info); } // Notify RepRapFirmware and start processing the file in the background Console.WriteLine($"[info] Printing file '{fileName}'"); SPI.Interface.SetPrintStarted(); _ = Task.Run(RunPrint); // Return a result using (await Model.Provider.AccessReadOnlyAsync()) { if (Model.Provider.Get.Channels[source].Compatibility == Compatibility.Marlin) { return(new CodeResult(MessageType.Success, "File opened\nFile selected")); } else { return(new CodeResult()); } } }
/// <summary> /// Abort all running macro files on a given code channel /// </summary> /// <param name="channel">Code channel</param> /// <returns>Asynchronous task</returns> private static async Task AbortAll(CodeChannel channel) { int numChannel = (int)channel; using (await _openFilesLock.LockAsync(Program.CancellationToken)) { foreach (CodeFile file in _openFiles[numChannel]) { using (await file.LockAsync()) { file.Close(); } } } }
/// <summary> /// Read a <see cref="Request.DoCode"/> request /// </summary> /// <param name="from">Origin</param> /// <param name="channel">Code channel</param> /// <param name="code">Code to execute</param> /// <returns>Number of bytes read</returns> public static int ReadDoCode(ReadOnlySpan <byte> from, out CodeChannel channel, out string code) { DoCodeHeader header = MemoryMarshal.Cast <byte, DoCodeHeader>(from)[0]; int bytesRead = Marshal.SizeOf(header); // Read header channel = header.Channel; // Read code ReadOnlySpan <byte> unicodeCode = from.Slice(bytesRead, header.Length); code = Encoding.UTF8.GetString(unicodeCode); bytesRead += header.Length; return(AddPadding(bytesRead)); }
/// <summary> /// Abort the last file on the given channel /// </summary> /// <param name="channel">Channel of the running macro file</param> /// <returns>If an abortion could be requested</returns> public static bool AbortLastFile(CodeChannel channel) { lock (_macroFiles) { foreach (MacroFile file in _macroFiles) { if (file.Channel == channel) { file.Abort(); _macroFiles.Remove(file); return(true); } } } return(false); }