123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- using AwInitilizer.Model;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- namespace AwInitilizer.Assist
- {
- public class SerialPortocol : INotifyPropertyChanged
- {
- private static int TimeoutDuration = 1 * 1000;
- public event EventHandler<EvseSerialResponseModel> OnMsgReceived;
- public event PropertyChangedEventHandler PropertyChanged;
- public string LatestErrorMessage { get; private set; }
- private Interface.ISerialPort _serialPort;
- private SemaphoreQueue receivedBufferLock = new SemaphoreQueue(1, 1);
- private byte[] receivedBuffer = new byte[0];
- private bool IsSerialPortAvaliable
- {
- get
- {
- if (_serialPort == null || _serialPort.ConnectStatus != Interface.ConnectStatus.Connected)
- return false;
- return true;
- }
- }
- public void Open() => _serialPort?.Open();
- public void Close() => _serialPort?.Close();
- public Interface.ConnectStatus ConnectStatus => _serialPort == null ? Interface.ConnectStatus.Cleared : _serialPort.ConnectStatus;
- public SerialPortocol(Interface.ISerialPort serialPort)
- {
- _serialPort = serialPort;
- _serialPort.OnDataReceived += _serialPort_OnDataReceived;
- _serialPort.PropertyChanged += _serialPort_PropertyChanged;
- }
- public async Task<string> GetModelName()
- {
- return await SendAndWait(0x24, SimpleStringParser);
- }
- public async Task<bool> SetModelName(string modelName)
- {
- var param = Encoding.ASCII.GetBytes(modelName);
- return await SendAndWait(0x83, SimpleResultParser, parameter: param);
- }
- public async Task<string> GetSerialNumber()
- {
- return await SendAndWait(0x23, SerialNumberParser);
- string SerialNumberParser(byte[] parameter)
- {
- if (parameter == null || parameter.Length < 19)
- return null;
- var snBytes = parameter.Skip(8).ToArray();
- return SimpleStringParser(snBytes);
- }
- }
- public async Task<bool> SetSerialNumber(string serialNumber)
- {
- DateTime nowTime = DateTime.Now.ToUniversalTime();
- var DataString = nowTime.ToString("yyyyMMdd");
- var dateTimeParam = Encoding.ASCII.GetBytes(DataString);
- var snParam = Encoding.ASCII.GetBytes(serialNumber);
- var param = new byte[dateTimeParam.Length + snParam.Length];
- Array.Copy(dateTimeParam, 0, param, 0, dateTimeParam.Length);
- Array.Copy(snParam, 0, param, dateTimeParam.Length, snParam.Length);
- return await SendAndWait(0x82, SimpleResultParser, parameter: param);
- }
- public async Task<DateTime?> GetUTCTime()
- {
- return await SendAndWait(0x26, TimeParser);
- DateTime? TimeParser(byte[] parameter)
- {
- if (parameter == null || parameter.Length < 14)
- return null;
- string rawDateString = Encoding.ASCII.GetString(parameter);
- var year = int.Parse(rawDateString.Substring(0,4));
- var month = int.Parse(rawDateString.Substring(4, 2));
- var day = int.Parse(rawDateString.Substring(6, 2));
- var hour = int.Parse(rawDateString.Substring(8, 2));
- var minut = int.Parse(rawDateString.Substring(10, 2));
- var sec = int.Parse(rawDateString.Substring(12, 2));
- try
- {
- DateTime dateTime = new DateTime(year, month, day, hour, minut, sec);
- return dateTime;
- }
- catch
- {
- return null;
- }
- }
- }
- public async Task<bool> SetUTCTime(DateTime dateTime)
- {
- var DataString = dateTime.ToString("yyyyMMddHHmmss");
- var param = Encoding.ASCII.GetBytes(DataString);
- return await SendAndWait(0x87, SimpleResultParser, parameter: param);
- }
- public async Task<string> GetFourGenModuleVersion()
- {
- return await SendAndWait(0x31, SimpleStringParser, WaitSec: 5);
- }
- public async Task<SimStatus> GetSimStatus()
- {
- return await SendAndWait(0x34, SimStatusParser);
- SimStatus SimStatusParser(byte[] param)
- {
- if(param==null || param.Length != 39)
- {
- return null;
- }
- SimStatus toReturn = new SimStatus();
- toReturn.IsInstalled = param[0] == 0x01;
- toReturn.ICCID = param.Skip(1).Take(22).ToArray();
- toReturn.IMSI = param.Skip(22).Take(16).ToArray();
- return toReturn;
- }
- }
- public async Task<bool> SettingChangeConfirm()
- {
- return await SendAndWait(0x91, SimpleResultParser, WaitSec: 10);
- }
- private void _serialPort_PropertyChanged(object sender, PropertyChangedEventArgs e)
- {
- if (e.PropertyName == nameof(Interface.ISerialPort.ConnectStatus))
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SerialPortocol.ConnectStatus)));
- }
- }
- private async Task<T> SendAndWait<T>(byte command, Func<byte[], T> ParserFunction, byte[] parameter = null, T defauit = default(T), int WaitSec = -1)
- {
- if (!IsSerialPortAvaliable)
- return defauit;
- T result = defauit;
- SemaphoreSlim signal = new SemaphoreSlim(0, 1);
- OnMsgReceived += EvseSerialProtocal_OnMsgReceived;
- if (SendMessage(command, parameter))
- {
- if (WaitSec < 0)
- await signal.WaitAsync(TimeoutDuration);
- else
- await signal.WaitAsync(WaitSec * 1000);
- }
- OnMsgReceived -= EvseSerialProtocal_OnMsgReceived;
- if (signal.CurrentCount == 0)
- {
- //timeout
- LatestErrorMessage = "Serial portocol timeout";
- }
- return result;
- void EvseSerialProtocal_OnMsgReceived(object sender, EvseSerialResponseModel e)
- {
- if (e.Command == command)
- {
- result = ParserFunction(e.Parameter);
- signal.Release();
- }
- }
- }
- private bool SendMessage(byte command, byte[] parameter = null)
- {
- if (!IsSerialPortAvaliable)
- return false;
- int parameterLength = parameter == null ? 0 : parameter.Length;
- int messagLength = parameterLength + 7;
- byte[] message = new byte[parameterLength + 7];
- message[0] = 0xAA;
- message[1] = 0x10; //Master
- message[2] = 0xFF; //broadcast
- message[3] = command;
- message[4] = (byte)(parameterLength % 256);
- message[5] = (byte)(parameterLength / 256);
- if (parameter != null && parameter.Length > 0)
- Array.Copy(parameter, 0, message, 6, parameter.Length);
- byte chksum = 0x00;
- for (int idx = 0; idx < parameterLength; idx++)
- chksum ^= message[6 + idx];
- message[6 + parameterLength] = chksum;
- _serialPort?.WriteData(message);
- //_serialPort?.WriteData(message);
- return true;
- }
- private void _serialPort_OnDataReceived(object sender, byte[] e)
- {
- receivedBufferLock.Wait();
- {
- var tmp = new byte[e.Length + receivedBuffer.Length];
- Array.Copy(receivedBuffer, 0, tmp, 0, receivedBuffer.Length);
- Array.Copy(e, 0, tmp, receivedBuffer.Length, e.Length);
- //receivedBuffer = tmp;
- receivedBuffer = ParseReceive(tmp, out List<EvseSerialResponseModel> reponseModels);
- foreach (EvseSerialResponseModel responseModel in reponseModels)
- {
- OnMsgReceived?.Invoke(this, responseModel);
- }
- }
- receivedBufferLock.Release();
- }
- private bool SimpleResultParser(byte[] parameter)
- {
- if (parameter == null || parameter.Length != 1)
- return false;
- var resultByte = parameter[0];
- return resultByte == 0x01;
- }
- private string SimpleHexStringParser(byte[] parameter)
- {
- if (parameter == null)
- {
- return default;
- }
- return BitConverter.ToString(parameter).Replace("-", " ");
- }
- private string SimpleStringParser(byte[] parameter)
- {
- if(parameter == null)
- {
- LatestErrorMessage = "parameter null exception";
- return string.Empty;
- }
- if (parameter.Length <= 1)
- {
- LatestErrorMessage = $"parameter legnth {parameter.Length} error";
- return string.Empty;
- }
- if(parameter.ToList().Contains(0x00))
- {
- int endIndex = Array.FindIndex(parameter, (x) => { return x == 0x00; });
- //int endIndex = parameter.FindIndex((x) => { return x == 0x00; });
- if (endIndex != default)
- {
- parameter = parameter.Take(endIndex).ToArray();
- }
- }
- while (parameter.Length != 0 && parameter[parameter.Length - 1] < 32)
- {
- parameter = parameter.Take(parameter.Length - 1).ToArray();
- }
- try
- {
- var result = Encoding.ASCII.GetString(parameter);
- return result;
- }
- catch(Exception e)
- {
- LatestErrorMessage = $"string parse exception : {e.Message}";
- return string.Empty;
- }
- }
- private byte[] ParseReceive(byte[] parseData, out List<EvseSerialResponseModel> reponseModels)
- {
- reponseModels = new List<EvseSerialResponseModel>();
- while (true)
- {
- int stIndex = -1;
- //find first 0xff 0xff
- for (int index = 0; index < parseData.Length - 1; index++)
- {
- if (parseData[index] == 0xAA)
- {
- stIndex = index;
- break;
- }
- }
- //int index = Array.IndexOf(receivedBuffer, startChar);
- if (stIndex < 0)
- break;
- //discard data before 0xaa
- parseData = parseData.Skip(stIndex).ToArray();
- //response msg is at leat 6 bytes
- if (parseData.Length < 6)
- break;
- var msgLength = parseData[5] * 256 + parseData[4];
- if (parseData.Length < msgLength + 6)
- break;
- //Add handle data
- reponseModels.Add(new EvseSerialResponseModel() {
- Source = parseData[1],
- Destination = parseData[2],
- Command = parseData[3],
- Parameter = parseData.Skip(6).Take(msgLength).ToArray()
- });
- parseData = parseData.Skip(msgLength + 6).ToArray();
- }
- return parseData;
- }
- }
- }
|