using Edge.Core.Processor; using Edge.Core.IndustryStandardInterface.Pump; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using MQTTnet; using MQTTnet.Client; using MQTTnet.Diagnostics; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Printing; using System.Linq; using System.Text; using System.Threading.Tasks; namespace XinHua_XPrinter_WindowsPrinter_App { public class App : IAppProcessor { private ILogger logger = new LoggerFactory().CreateLogger("no exists"); private IMqttClient mqttClient; private string mqttServerUrl; private int mqttServerPort; private string mqttClientId; private string mqttClientUsername; private string mqttClientPassword; private string topic_PrintingRequest; private string topic_PrintRequestReply; private string printerName; private string printingContent; private bool shouldReconnect = true; public string MetaConfigName { get; set; } public App(string mqttServerUrl, int mqttServerPort, string mqttClientId, string mqttClientUsername, string mqttClientPassword, string topic_PrintingRequest, string topic_PrintRequestReply, string printerName, IServiceProvider services) { if (services != null) { var loggerFactory = services.GetRequiredService(); this.logger = loggerFactory.CreateLogger("Application"); } this.mqttServerUrl = mqttServerUrl; this.mqttServerPort = mqttServerPort; this.mqttClientId = mqttClientId; this.mqttClientUsername = mqttClientUsername; this.mqttClientPassword = mqttClientPassword; this.topic_PrintingRequest = topic_PrintingRequest; this.topic_PrintRequestReply = topic_PrintRequestReply; this.printerName = printerName; } public async void Init(IEnumerable processors) { //https://docs.microsoft.com/en-us/dotnet/api/system.drawing.graphics.drawstring?view=netcore-3.0 PrintDocument printDocument = new PrintDocument(); var installedPrinters = PrinterSettings.InstalledPrinters.Cast(); this.logger.LogInformation("System installed printers are: " + installedPrinters.Aggregate((acc, n) => acc + ", " + n) + Environment.NewLine + "now the printer with name: " + printDocument.PrinterSettings.PrinterName + " is defaultly chosen."); if (!string.IsNullOrEmpty(this.printerName)) { this.logger.LogInformation(" will switch to printer with name: " + this.printerName); printDocument.PrinterSettings.PrinterName = this.printerName; } printDocument.PrintPage += Pd_PrintPage; //MqttNetGlobalLogger.LogMessagePublished += (s, e) => //{ // //var trace = $">> [{e.TraceMessage.ThreadId}] [{e.TraceMessage.Source}] [{e.TraceMessage.Level}]: {e.TraceMessage.Message}"; // if (this.logger.IsEnabled(LogLevel.Trace)) // { // var trace = $"MQTTnet - {e.TraceMessage.Message}"; // if (e.TraceMessage.Exception != null) // trace += Environment.NewLine + e.TraceMessage.Exception.ToString(); // this.logger.LogTrace(trace); // } //}; // Create a new MQTT client. var factory = new MqttFactory(); this.mqttClient = factory.CreateMqttClient(); this.mqttClient.ApplicationMessageReceivedAsync += e => { if (this.logger.IsEnabled(LogLevel.Trace)) { this.logger.LogTrace("### Received Messages from Topic ###"); this.logger.LogTrace($" Topic = {e.ApplicationMessage.Topic}"); this.logger.LogTrace($" Payload = {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}"); this.logger.LogTrace($" QoS = {e.ApplicationMessage.QualityOfServiceLevel}"); this.logger.LogTrace($" Retain = {e.ApplicationMessage.Retain}"); } if (e.ApplicationMessage.Topic == this.topic_PrintingRequest) { this.printingContent = this.ParseToPrinterStringData(e.ApplicationMessage.Payload); printDocument.Print(); if (!string.IsNullOrEmpty(this.topic_PrintRequestReply)) this.mqttClient.PublishAsync(new MqttApplicationMessage() { Topic = this.topic_PrintRequestReply, Payload = new byte[] { } }); } return Task.CompletedTask; }; this.mqttClient.DisconnectedAsync += arg => { this.shouldReconnect = true; this.logger.LogInformation(" Mqtt connection disconnected, " + "AuthenticateResult: " + (arg.ReasonString ?? "") + ", ClientWasConnected: " + arg.ClientWasConnected + ", exception: " + arg.Exception); return Task.CompletedTask; }; // Create TCP based options using the builder. var options = new MqttClientOptionsBuilder() .WithClientId(this.mqttClientId) .WithTcpServer(this.mqttServerUrl, this.mqttServerPort) .WithCredentials(this.mqttClientUsername, this.mqttClientPassword) .WithKeepAlivePeriod(new TimeSpan(0, 0, 30)) .WithCleanSession(true) .Build(); await Task.Run(async () => { while (true) { if (!this.shouldReconnect) { await Task.Delay(30000); continue; } this.logger.LogDebug("Connecting to mqtt server..."); try { try { // always try to close previous conn. await mqttClient.DisconnectAsync(); } catch { } var result = await mqttClient.ConnectAsync(options); if (result.ResultCode == MqttClientConnectResultCode.Success) { this.logger.LogInformation(" Successfully connected to mqtt server."); var subResult = await this.mqttClient.SubscribeAsync(this.topic_PrintingRequest, MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce); if (subResult.Items.Any()) { if ((int)(subResult.Items.First().ResultCode) <= 2) { this.logger.LogInformation(" Successfully subscribed on topic."); this.shouldReconnect = false; } else { this.logger.LogInformation(" Failed on subscribe on topic with Sub resultCode: " + subResult.Items.First().ResultCode); } } else this.logger.LogInformation(" Failed on subscribe on topic by generic error."); } else { this.logger.LogInformation(" Failed connecting to mqtt server with returned ResultCode: " + result.ResultCode + ", ReasonString:" + (result.ReasonString ?? "")); } } catch (Exception exx) { this.logger.LogError(" Connecting to mqtt server exceptioned: " + exx); } } }); } private void Pd_PrintPage(object sender, PrintPageEventArgs e) { //string drawString = "hello world this is my test line0" // + Environment.NewLine + "line1" // + Environment.NewLine + "line2"; // Create font and brush. Font drawFont = new Font("Arial", 10);//, FontStyle.Bold); SolidBrush drawBrush = new SolidBrush(Color.Black); // Create point for upper-left corner of drawing. float x = 0.00F; float y = 0.00F; // Set format of string. StringFormat drawFormat = new StringFormat(); //drawFormat.FormatFlags = StringFormatFlags.DirectionVertical; //drawFormat.FormatFlags = StringFormatFlags.DisplayFormatControl; e.Graphics.DrawString(this.printingContent, drawFont, drawBrush, x, y, drawFormat); //e.Graphics.DrawString("\x1b\x69", drawFont, drawBrush, x, y + 40, drawFormat); //string GS = Convert.ToString((char)29); //string ESC = Convert.ToString((char)27); //string COMMAND = ""; //COMMAND = ESC + "@"; //COMMAND += GS + "V" + (char)1; //e.Graphics.DrawString(COMMAND, drawFont, drawBrush, x, y + 60, drawFormat); //e.Graphics.DrawString("\x1B@\x1DV1", drawFont, drawBrush, x, y + 80, drawFormat); } public async Task Start() { return true; } public async Task Stop() { return true; } /// /// parse the bytes from remote which most likely with format control chars included. /// /// /// a string that the device can read and operate private string ParseToPrinterStringData(byte[] rawContent) { return Encoding.UTF8.GetString(rawContent); } } }