Skip to content

Commit

Permalink
reading messages
Browse files Browse the repository at this point in the history
  • Loading branch information
atmdevnet committed May 19, 2016
1 parent 643bc7e commit 07371fe
Show file tree
Hide file tree
Showing 6 changed files with 311 additions and 10 deletions.
29 changes: 28 additions & 1 deletion SmsTools/Commands/ATCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,33 @@ public enum ATCommand
/// AT+CMGS=
/// </summary>
[ATCommand(Command = "AT+CMGS=", HasParameters = true, HasSteps = true)]
MessageSend
MessageSend,

/// <summary>
/// AT+CPMS?
/// </summary>
[ATCommand(Command = "AT+CPMS?")]
MessageStorageInfo,
/// <summary>
/// AT+CPMS=
/// </summary>
[ATCommand(Command = "AT+CPMS=", HasParameters = true)]
MessageStorage,

/// <summary>
/// AT+CMGL=
/// </summary>
[ATCommand(Command = "AT+CMGL=", HasParameters = true)]
MessageList,
/// <summary>
/// AT+CMGR=
/// </summary>
[ATCommand(Command = "AT+CMGR=", HasParameters = true)]
MessageRead,
/// <summary>
/// AT+CMGD=
/// </summary>
[ATCommand(Command = "AT+CMGD=", HasParameters = true)]
MessageDelete
}
}
23 changes: 23 additions & 0 deletions SmsTools/Constants.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
Expand Down Expand Up @@ -37,5 +38,27 @@ public enum MessageFormat
{
Pdu, Text
}

public enum MessageStorage
{
Unspecified,
[Description("\"MT\"")]
MobileAssociated,
[Description("\"ME\"")]
MobileEquipment,
[Description("\"SM\"")]
Sim,
[Description("\"SR\"")]
StateReport
}

public enum MessageStatus
{
Unread,
Read,
Unsent,
Sent,
Any
}
}
}
13 changes: 13 additions & 0 deletions SmsTools/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using SmsTools.Commands;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
Expand Down Expand Up @@ -34,5 +35,17 @@ public static string ToValueString(this Enum value)
return Convert.ToInt32(value).ToString();
}

public static string Description(this Enum value)
{
return value.GetEnumAttributeValue<DescriptionAttribute, string>(a => a.Description);
}

public static Constants.MessageStorage ToMessageStorage(this string value)
{
if (string.IsNullOrWhiteSpace(value))
return Constants.MessageStorage.Unspecified;

return Enum.GetValues(typeof(Constants.MessageStorage)).Cast<Constants.MessageStorage>().FirstOrDefault(e => e.Description().Equals(value));
}
}
}
242 changes: 242 additions & 0 deletions SmsTools/MessageStorage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
using SmsTools.Commands;
using SmsTools.Operations;
using SmsTools.PduProfile;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace SmsTools
{
public class MessageStorage
{
private PduProfileManager _manager = new PduProfileManager();
private ICommandParameter _empty = null;
private IATCommand _storageQuery = null;
private IATCommand _listQuery = null;
private IATCommand _mfCmd = null;


public MessageStorage()
{
init();
}

private void init()
{
_empty = CommandParameter.CreateEmpty(Constants.BasicSuccessfulResponse);
_storageQuery = new SimpleATCommand(ATCommand.MessageStorageInfo.Command(), _empty);

var listParam = new CommandParameter(Constants.MessageStatus.Any.ToValueString(), Constants.BasicSuccessfulResponse);
_listQuery = new ParamATCommand(ATCommand.MessageList.Command(), listParam);

var mfParam = new CommandParameter(Constants.MessageFormat.Pdu.ToValueString(), Constants.BasicSuccessfulResponse);
_mfCmd = new ParamATCommand(ATCommand.MessageFormat.Command(), mfParam);
}

public async Task<bool> SelectStorage(IPortPlug port, Constants.MessageStorage readStore = Constants.MessageStorage.MobileEquipment, Constants.MessageStorage writeStore = Constants.MessageStorage.Unspecified, Constants.MessageStorage receivedStore = Constants.MessageStorage.Unspecified)
{
if (readStore == Constants.MessageStorage.Unspecified)
return false;

var storageParam = new CommandParameter(getStorageParam(readStore, writeStore, receivedStore), Constants.BasicSuccessfulResponse);
var storageCmd = new ParamATCommand(ATCommand.MessageStorage.Command(), storageParam);

await storageCmd.ExecuteAsync(port);

return storageCmd.Succeeded();
}

public async Task<IEnumerable<MessageStorageState>> StorageState(IPortPlug port)
{
var result = Enumerable.Empty<MessageStorageState>();

await _storageQuery.ExecuteAsync(port);
if (_storageQuery.Succeeded())
{
result = getStorageState(_storageQuery.Response);
}

return result;
}

public async Task<IEnumerable<MessageStorageItem>> List(IPortPlug port)
{
var result = Enumerable.Empty<MessageStorageItem>();

if (await setFormat(port))
{
await _listQuery.ExecuteAsync(port);
if (_listQuery.Succeeded())
{
result = getStorageItems(_listQuery.Response);
}
}

return result;
}

public async Task<MessageInfo> Read(IPortPlug port, MessageStorageItem item)
{
MessageInfo result = new MessageInfo();

if (item == null || !item.IsValid || !_manager.ContainsProfile("default-receive"))
return result;

if (await setFormat(port))
{
var readParam = new CommandParameter(item.Index.ToString(), Constants.BasicSuccessfulResponse);
var readCmd = new ParamATCommand(ATCommand.MessageRead.Command(), readParam);

await readCmd.ExecuteAsync(port);
if (readCmd.Succeeded())
{
result = getMessage(readCmd.Response);
}
}

return result;
}


private MessageInfo getMessage(string response)
{
MessageInfo result = new MessageInfo();

try
{
var lengthMatch = Regex.Match(response, @"^\S*(?:cmgr:.+,(\d+)\s*)$", RegexOptions.IgnoreCase | RegexOptions.Multiline);
var pduMatch = Regex.Match(response, @"^(?:\s*([a-fA-F0-9]+)\s*)$", RegexOptions.IgnoreCase | RegexOptions.Multiline);

if (lengthMatch.Success && lengthMatch.Groups.Count > 1 && pduMatch.Success && pduMatch.Groups.Count > 1)
{
int length = int.Parse(lengthMatch.Groups[1].Value.Trim());
string pdu = pduMatch.Groups[1].Value.Trim();

var profile = _manager["default-receive"];

result = profile.GetMessage(pdu, length);
}
}
catch { }

return result;
}

private IEnumerable<MessageStorageItem> getStorageItems(string response)
{
var result = Enumerable.Empty<MessageStorageItem>();

try
{
var matches = Regex.Matches(response, @"^\S*(?:cmgl:(.+))$", RegexOptions.IgnoreCase | RegexOptions.Multiline);
if (matches.Count > 0)
{
var items = new List<MessageStorageItem>();

for (int m = 0; m < matches.Count; ++m)
{
var match = matches[m];
if (!match.Success || match.Groups.Count < 2)
throw new Exception();

var itemValue = match.Groups[1].Value.Trim();
var itemValues = itemValue.Split(',');
int value = 0;
if (itemValues.Length < 3 || itemValues.Any(v => !int.TryParse(v, out value)))
throw new Exception();

var item = itemValues.Select(v => int.Parse(v)).ToArray();

items.Add(new MessageStorageItem() { Index = item[0], Status = (Constants.MessageStatus)item[1], Length = item.Last() });
}

result = items;
}
}
catch { }

return result;
}

private IEnumerable<MessageStorageState> getStorageState(string response)
{
var result = Enumerable.Empty<MessageStorageState>();

try
{
var state = Regex.Match(response, $@"(?:cpms:(.+){Constants.BasicSuccessfulResponse})", RegexOptions.IgnoreCase);
if (state.Success && state.Groups.Count > 1)
{
var stateValue = state.Groups[1].Value.Trim();
var stateValues = stateValue.Split(',');
if (stateValues.Length % 3 == 0 && stateValues.All(s => !string.IsNullOrWhiteSpace(s)))
{
var storages = new List<MessageStorageState>();

for (int i = 0; i < stateValues.Length; i += 3)
{
var storageValue = stateValues[i];
var countValue = stateValues[i + 1];
var limitValue = stateValues[i + 2];

int count = 0, limit = 0;
if (!int.TryParse(countValue, out count) || !int.TryParse(limitValue, out limit))
throw new Exception();

storages.Add(new MessageStorageState() { Storage = storageValue.ToMessageStorage(), Count = count, Limit = limit });
}

result = storages;
}
}
}
catch { }

return result;
}

private string getStorageParam(Constants.MessageStorage readStore, Constants.MessageStorage writeStore, Constants.MessageStorage receivedStore)
{
var param = new StringBuilder(readStore.Description());

if (writeStore != Constants.MessageStorage.Unspecified)
{
param.Append(",").Append(writeStore.Description());
}

if (receivedStore != Constants.MessageStorage.Unspecified)
{
param.Append(",").Append(receivedStore.Description());
}

return param.ToString();
}

private async Task<bool> setFormat(IPortPlug port)
{
await _mfCmd.ExecuteAsync(port);
return _mfCmd.Succeeded();
}
}


public class MessageStorageState
{
public Constants.MessageStorage Storage { get; set; }
public int Count { get; set; }
public int Limit { get; set; }
public bool IsFull { get { return Count == Limit; } }
public bool IsEmpty { get { return Count == 0; } }
}

public class MessageStorageItem
{
public int Index { get; set; }
public Constants.MessageStatus Status { get; set; }
public int Length { get; set; }
public bool IsValid { get { return Index >= 0 && Length >= 0; } }
}
}
13 changes: 4 additions & 9 deletions SmsTools/Operations/SerialPortPlug.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,13 @@ private void _port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
_buffer.Append((sender as SerialPort).ReadExisting());

if (e.EventType == SerialData.Eof)
if (e.EventType == SerialData.Eof
|| (e.EventType == SerialData.Chars
&& (Regex.IsMatch(_buffer.ToString(), @"\s*(ok|>)\s*$", RegexOptions.IgnoreCase)
|| Regex.IsMatch(_buffer.ToString(), @"error", RegexOptions.IgnoreCase))))
{
_wait.Set();
}
else if (e.EventType == SerialData.Chars)
{
if (Regex.IsMatch(_buffer.ToString(), @"\s*(ok|>)\s*$", RegexOptions.IgnoreCase)
|| Regex.IsMatch(_buffer.ToString(), @"error", RegexOptions.IgnoreCase))
{
_wait.Set();
}
}
}

private void _port_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
Expand Down
1 change: 1 addition & 0 deletions SmsTools/SmsTools.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
<Compile Include="Commands\ICommandParameter.cs" />
<Compile Include="Commands\ParamATCommand.cs" />
<Compile Include="Commands\SimpleATCommand.cs" />
<Compile Include="MessageStorage.cs" />
<Compile Include="Operations\IPortPlug.cs" />
<Compile Include="Operations\SerialPortPlug.cs" />
<Compile Include="Operations\SerialPortConfig.cs" />
Expand Down

0 comments on commit 07371fe

Please sign in to comment.