using DbusSmsForward.Helper; using DbusSmsForward.SettingModel; using DbusSmsForward.SMSModel; using ModemManager1.DBus; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Text.Json; using Tmds.DBus.Protocol; namespace DbusSmsForward.ModemHelper { public class ModemManagerHelper { private readonly Lock _modemObjectPathListLockObject = new(); public Dictionary>> _modemObjectPathList = new Dictionary>>(); public string _modemObjectPathNowUse = ""; public string qmiPathNowUse = ""; public string _modemManagerObjectPath = "/org/freedesktop/ModemManager1"; public string? systemBusAddress = Address.System; public string baseService = "org.freedesktop.ModemManager1"; public List> smsSendMethodList = new List>(); public string deviceUidNowUse = ""; private readonly Lock _subscribeSmsPathListLockObject = new(); public Dictionary SubscribeSmsPathList=new Dictionary(); public ModemManagerHelper() { if (!string.IsNullOrEmpty(systemBusAddress)) { InitLoadModemObjectPathList(); WatchModems(); } } public void InitLoadModemObjectPathList() { lock (_modemObjectPathListLockObject) { _modemObjectPathList = GetModemsPathList().Result; } if (_modemObjectPathList.Count == 1) { SetNowUsedModemPath(_modemObjectPathList.First().Key); } if (_modemObjectPathList.Count == 0) { SetNowUsedModemPath(null); } foreach (var item in _modemObjectPathList) { SubscribeSms(item.Key); } } public void SetSendMethodList(List> SendMethodList) { smsSendMethodList = SendMethodList; } public void SetNowUsedModemPath(string modemObjectPathNowUse) { _modemObjectPathNowUse = modemObjectPathNowUse; if (string.IsNullOrEmpty(_modemObjectPathNowUse)) { qmiPathNowUse = ""; deviceUidNowUse = ""; } else { qmiPathNowUse = GetQMIDevice().Result; deviceUidNowUse = GetDevice().Result; } } public void WatchModems() { Task.Run(async () => { try { using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var objectManager = service.CreateObjectManager(_modemManagerObjectPath); //Console.WriteLine($"Subscribing for modem RemovedChanges"); await objectManager.WatchInterfacesRemovedAsync( async (Exception? ex, (ObjectPath ObjectPath, string[] Interfaces) change) => { if (ex is null) { //Console.WriteLine("modem has been removed,modem path:" + change.ObjectPath.ToString()); InitLoadModemObjectPathList(); if (!string.IsNullOrEmpty(_modemObjectPathNowUse)) { DisableAndEnableModem().Wait(); } } }); var tcs = new TaskCompletionSource(); var task = tcs.Task; await task; } } catch (Exception ex) { Console.WriteLine(ex); } }); Task.Run(async () => { try { using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var objectManager = service.CreateObjectManager(_modemManagerObjectPath); //Console.WriteLine($"Subscribing for modem AddedChanges"); await objectManager.WatchInterfacesAddedAsync( async (Exception? ex, (ObjectPath ObjectPath, Dictionary> InterfacesAndProperties) change) => { if (ex is null) { //Console.WriteLine("new modem added,modem path:" + change.ObjectPath.ToString()); InitLoadModemObjectPathList(); if (!string.IsNullOrEmpty(_modemObjectPathNowUse)) { DisableAndEnableModem().Wait(); } } }); var tcs = new TaskCompletionSource(); var task = tcs.Task; await task; } } catch (Exception ex) { Console.WriteLine(ex); } }); } public void SubscribeSms(string path) { Task.Run(async () => { try { if ((!SubscribeSmsPathList.ContainsKey(path) || (SubscribeSmsPathList.ContainsKey(path) && !SubscribeSmsPathList[path]))&& _modemObjectPathList.ContainsKey(path)) { if (SubscribeSmsPathList.ContainsKey(path)) { lock (_subscribeSmsPathListLockObject) { SubscribeSmsPathList[path] = true; } } else { lock (_subscribeSmsPathListLockObject) { SubscribeSmsPathList.Add(path, true); } } //SetMsgDefaultStorageToME(path); using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var messaging = service.CreateMessaging(path); //Console.WriteLine($"add subscribe sms for modem path:" + path); await messaging.WatchAddedAsync( async (Exception? ex, (ObjectPath Path, bool Received) change) => { if (ex is null) { if (change.Received) { try { var smsPath = change.Path; var service = new ModemManager1Service(connection, baseService); var sms = service.CreateSms(smsPath); var smsState = await sms.GetStateAsync(); if (smsState == 2 || smsState == 3) { uint Storage = await sms.GetStorageAsync(); if (!ConfigHelper.JudgeIsForwardIgnore(Storage)) { string telNum = await sms.GetNumberAsync(); //string smsDate = (await sms.GetTimestampAsync()).Replace("T", " ").Replace("+08:00", " "); string smsdateOrg = await sms.GetTimestampAsync(); string smsDate = string.Empty; try { DateTimeOffset dto = DateTimeOffset.Parse(smsdateOrg, null, DateTimeStyles.RoundtripKind); // 转换为本地时间 DateTime localTime = dto.LocalDateTime; smsDate = localTime.ToString("yyyy-MM-dd HH:mm:ss"); } catch (Exception ex1) { Console.WriteLine("smsdate转换失败:\n" + ex1.Message); smsDate = smsdateOrg; } int tryCount = 0; do { smsState = await sms.GetStateAsync(); Thread.Sleep(100); } while (smsState == 2 && tryCount < 300); if (smsState == 3) { appsettingsModel result = new appsettingsModel(); ConfigHelper.GetSettings(ref result); string DeviceName = result.appSettings.DeviceName; result = null; if (string.IsNullOrEmpty(DeviceName) || DeviceName== "*Host*Name*") { DeviceName= ConfigHelper.GetDeviceHostName(); } string smsContent = await sms.GetTextAsync(); SmsContentModel smsmodel = new SmsContentModel(); smsmodel.TelNumber = telNum; smsmodel.SmsDate = smsDate; smsmodel.SmsContent = smsContent; string body = "发信电话:" + telNum + "\n" + "时间:" + smsDate + "\n" + "转发设备:" + DeviceName + "\n" + "短信内容:" + smsContent; Console.WriteLine("smspath " + smsPath); if (smsSendMethodList.Count() > 0) { //Console.WriteLine("转发方法数量"+smsSendMethodList.Count()); foreach (var action in smsSendMethodList) { action.Invoke(smsmodel, body, DeviceName); } } } else { Console.WriteLine("smspath:" + change.Path + " 接收超时,转发取消"); } } } } catch (Exception ex2) { Console.WriteLine("GetSmsError" + ex2.Message); } } } else { Console.WriteLine(ex); } }); Task task = Task.Run(() => { var modem = service.CreateModem(path); do { try { var Manufacturer = modem.GetManufacturerAsync().Result; Manufacturer = null; Thread.Sleep(1000); } catch (Exception ex) { break; } } while (SubscribeSmsPathList.ContainsKey(path) && SubscribeSmsPathList[path] && _modemObjectPathList.ContainsKey(path)); if (SubscribeSmsPathList.ContainsKey(path)) { lock (_subscribeSmsPathListLockObject) { SubscribeSmsPathList[path] = false; } } }); await task; //Console.WriteLine($"remove subscribe sms for modem path:" + path); } } } catch (Exception ex) { Console.WriteLine(ex); Console.WriteLine($"remove subscribe sms for modem path:" + path); } }); } public async Task SendSms(string telNum, string smsContent) { try { using (var connection = new Connection(Address.System)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var messaging = service.CreateMessaging(_modemObjectPathNowUse); var sendsmsPath = await messaging.CreateAsync(new Dictionary { { "text", smsContent }, { "number", telNum } }); var sms = service.CreateSms(sendsmsPath); await sms.SendAsync(); return true; } } catch (Exception ex) { Console.WriteLine(ex); return false; } } public async Task>>> GetModemsPathList() { try { await ScanDevices(); using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var objectManager = service.CreateObjectManager(_modemManagerObjectPath); return await objectManager.GetManagedObjectsAsync(); } } catch (Exception ex) { Console.WriteLine(ex); } return new Dictionary>>(); } public async Task ScanDevices() { try { using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var modemManager = service.CreateModemManager1(_modemManagerObjectPath); await modemManager.ScanDevicesAsync(); modemManager = null; service = null; } } catch (Exception ex) { if (!(ex.Message.IndexOf("unsupported") >-1)) { Console.WriteLine("ScanDevices失败" + ex.Message); } } } public async Task GetManufacturer(string? path = null) { try { string actUsePath = path == null ? _modemObjectPathNowUse : path; using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var modem = service.CreateModem(actUsePath); var Manufacturer = await modem.GetManufacturerAsync(); modem = null; service = null; return Manufacturer; } } catch (Exception ex) { Console.WriteLine(ex); return string.Empty; } } public async Task JudgeCanGetStatus(string? path = null) { try { string actUsePath = path == null ? _modemObjectPathNowUse : path; using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var modem = service.CreateSimple(actUsePath); var status = await modem.GetStatusAsync(); modem = null; service = null; return true; } } catch (Exception ex) { //Console.WriteLine(ex); return false; } } public async Task DisableAndEnableModem(string? path = null) { try { string actUsePath = path == null ? _modemObjectPathNowUse : path; if (!string.IsNullOrEmpty(actUsePath)) { using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var modem = service.CreateModem(actUsePath); try { await modem.EnableAsync(false); Thread.Sleep(200); await modem.EnableAsync(true); } catch (Exception e) { Console.WriteLine(e); } } } else { Console.WriteLine("DisableAndEnableModem:actUsePath为空"); } } catch (Exception ex) { Console.WriteLine(ex); } } public async Task InhibitModemDevice(string uid, bool inhibit) { try { Console.WriteLine("device:" + uid); using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var modemManager = service.CreateModemManager1(_modemManagerObjectPath); await modemManager.InhibitDeviceAsync(uid, inhibit); modemManager = null; service = null; } } catch (Exception ex) { Console.WriteLine("InhibitModemDevice失败" + ex); } } public async Task GetDevice(string? path = null) { try { string actUsePath = path == null ? _modemObjectPathNowUse : path; using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var modem = service.CreateModem(actUsePath); var device = await modem.GetDeviceAsync(); modem = null; service = null; return device; } } catch (Exception ex) { Console.WriteLine(ex); return string.Empty; } } public async Task GetQMIDevice(string? path = null) { try { string actUsePath = path == null ? _modemObjectPathNowUse : path; using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var modem = service.CreateModem(actUsePath); var Ports = await modem.GetPortsAsync(); foreach (var port in Ports) { if (port.Item2 == 6) { return "/dev/" + port.Item1; } } return ""; } } catch (Exception ex) { Console.WriteLine(ex); return string.Empty; } } public async Task GetModel(string? path = null) { try { string actUsePath = path == null ? _modemObjectPathNowUse : path; using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var modem = service.CreateModem(actUsePath); var Model = await modem.GetModelAsync(); modem = null; service = null; return Model; } } catch (Exception ex) { Console.WriteLine(ex); return string.Empty; } } public async Task GetRevision(string? path = null) { try { string actUsePath = path == null ? _modemObjectPathNowUse : path; using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var modem = service.CreateModem(actUsePath); var Revision = await modem.GetRevisionAsync(); modem = null; service = null; return Revision; } } catch (Exception ex) { Console.WriteLine(ex); return string.Empty; } } public async Task GetSignalQuality(string? path = null) { try { string actUsePath = path == null ? _modemObjectPathNowUse : path; using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var modem = service.CreateModem(actUsePath); var SignalQuality = await modem.GetSignalQualityAsync(); modem = null; service = null; return SignalQuality.Item1.ToString(); } } catch (Exception ex) { Console.WriteLine(ex); return string.Empty; } } public async Task GetOwnNumbers(string? path = null) { try { string actUsePath = path == null ? _modemObjectPathNowUse : path; using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var modem = service.CreateModem(actUsePath); var OwnNumbers = await modem.GetOwnNumbersAsync(); modem = null; service = null; return OwnNumbers; } } catch (Exception ex) { Console.WriteLine(ex); return []; } } public async Task GetPrimarySimSlot(string? path = null) { try { string actUsePath = path == null ? _modemObjectPathNowUse : path; using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var modem = service.CreateModem(actUsePath); var PrimarySimSlot = await modem.GetPrimarySimSlotAsync(); return PrimarySimSlot; } } catch (Exception ex) { Console.WriteLine(ex); return null; } } public async Task GetICCID(string? path = null) { try { string actUsePath = path == null ? _modemObjectPathNowUse : path; using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var modem = service.CreateModem(actUsePath); var simpath = await modem.GetSimAsync(); var sim = service.CreateSim(simpath); var iccid = await sim.GetSimIdentifierAsync(); modem = null; service = null; return iccid; } } catch (Exception ex) { Console.WriteLine(ex); return string.Empty; } } public async Task GetImei(string? path = null) { try { string actUsePath = path == null ? _modemObjectPathNowUse : path; using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var modem3gpp = service.CreateModem3gpp(actUsePath); var Imei = await modem3gpp.GetImeiAsync(); modem3gpp = null; service = null; return Imei; } } catch (Exception ex) { Console.WriteLine(ex); return string.Empty; } } public async Task GetOperatorCode(string? path = null) { try { string actUsePath = path == null ? _modemObjectPathNowUse : path; using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var modem3gpp = service.CreateModem3gpp(actUsePath); var OperatorCode = await modem3gpp.GetOperatorCodeAsync(); modem3gpp = null; service = null; return OperatorCode; } } catch (Exception ex) { Console.WriteLine(ex); return string.Empty; } } public async Task GetOperatorName(string? path = null) { try { string actUsePath = path == null ? _modemObjectPathNowUse : path; using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var modem3gpp = service.CreateModem3gpp(actUsePath); var OperatorName = await modem3gpp.GetOperatorNameAsync(); modem3gpp = null; service = null; return OperatorName; } } catch (Exception ex) { Console.WriteLine(ex); return string.Empty; } } public async Task SetMsgDefaultStorageToME(string path) { try { using (var connection = new Connection(systemBusAddress)) { await connection.ConnectAsync(); var service = new ModemManager1Service(connection, baseService); var messaging = service.CreateMessaging(path); await messaging.SetDefaultStorageAsync(2); } } catch (Exception ex) { Console.WriteLine(ex); } } public bool RestartModem() { string qmiPath = GetQMIDevice().Result; uint? simslot = GetPrimarySimSlot().Result; string usedDevice = deviceUidNowUse; if (simslot.HasValue) { if (simslot.Value == 0) { simslot += 1; } ProcessStartInfo startInfo = new ProcessStartInfo { FileName = "qmicli", Arguments = @$"-d {qmiPath} -p --uim-sim-power-off={simslot}", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false }; using (Process process = Process.Start(startInfo)) { if (process != null) { string output = process.StandardOutput.ReadToEnd(); string error = process.StandardError.ReadToEnd(); process.WaitForExit(); if (process.ExitCode != 0) { Console.WriteLine(error); return false; } } else { Console.WriteLine("Failed to exec qmicli"); return false; } } ProcessStartInfo startInfo2 = new ProcessStartInfo { FileName = "qmicli", Arguments = @$"-d {qmiPath} -p --uim-sim-power-on={simslot}", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false }; using (Process process = Process.Start(startInfo2)) { if (process != null) { string output = process.StandardOutput.ReadToEnd(); string error = process.StandardError.ReadToEnd(); process.WaitForExit(); if (process.ExitCode != 0) { Console.WriteLine(error); return false; } } else { Console.WriteLine("Failed to exec qmicli"); return false; } } if (JudgeCanGetStatus().Result) { DisableAndEnableModem().Wait(); } Thread.Sleep(200); if (JudgeCanGetStatus().Result) { InhibitModemDevice(usedDevice, true).Wait(); Thread.Sleep(200); InhibitModemDevice(usedDevice, false).Wait(); } return true; } else { return false; } } } }