修正命名错误
xiyunfei authored at 2023-04-09 21:10:58
8.10 KiB
NewLife.JT808
using System.Globalization;
using NewLife.JT808.Protocols;
using NewLife.JT808.Protocols;
using NewLife.Serialization;

namespace NewLife.JT808.Models
{
    /// <summary>插拔状态</summary>
    public enum CardStatus : Byte
    {
        /// <summary>从业资格证IC卡插入_驾驶员上班</summary>
        插入 = 0x01,

        /// <summary>从业资格证IC卡拔出_驾驶员下班</summary>
        拔出 = 0x02
    }

    /// <summary>IC 卡读取结果</summary>
    public enum CardResult : Byte
    {
        /// <summary>IC卡读卡成功</summary>
        读卡成功 = 0x00,

        /// <summary>读卡失败_原因为卡片密钥认证未通过</summary>
        卡片密钥认证未通过 = 0x01,

        /// <summary>读卡失败_原因为卡片已被锁定</summary>
        卡片已被锁定 = 0x02,

        /// <summary>读卡失败_原因为卡片被拔出</summary>
        卡片被拔出 = 0x03,

        /// <summary>读卡失败_原因为数据校验错误</summary>
        数据校验错误 = 0x04,
    }

    /// <summary>驾驶员身份信息采集上报</summary>
    [MessageKind(MessageKinds.驾驶员上报)]
    public class T0702 : IAccessor
    {
        /// <summary>
        /// 状态
        /// 0x01:从业资格证 IC 卡插入(驾驶员上班);
        /// 0x02:从业资格证 IC 卡拔出(驾驶员下班)。
        /// </summary>
        public CardStatus Status { get; set; }

        /// <summary>
        /// 插卡/拔卡时间,YY-MM-DD-hh-mm-ss;
        /// 以下字段在状态为 0x01 时才有效并做填充。
        /// BCD[6]
        /// </summary>
        public DateTime Time { get; set; }

        /// <summary>
        /// IC 卡读取结果
        /// 0x00:IC 卡读卡成功;
        /// 0x01:读卡失败,原因为卡片密钥认证未通过;
        /// 0x02:读卡失败,原因为卡片已被锁定;
        /// 0x03:读卡失败,原因为卡片被拔出;
        /// 0x04:读卡失败,原因为数据校验错误。
        /// 以下字段在 IC 卡读取结果等于 0x00 时才有效。
        /// </summary>
        public CardResult Result { get; set; }

        /// <summary>驾驶员姓名</summary>
        public String UserName { get; set; }

        /// <summary>
        /// 从业资格证编码 
        /// 2011 长度40 位 ,不足补 '\0';
        /// 2013 长度 20 位,不足补 '\0'。
        /// </summary>
        public String QualificationCode { get; set; }

        /// <summary>发证机构名称</summary>
        public String LicenseIssuing { get; set; }

        /// <summary>证件有效期 BCD[4]</summary>
        public String CertificateExpire { get; set; }

        /// <summary>
        /// 驾驶员身份证号 长度20 不足补 '\0'
        /// 2011版本
        /// 2019版本
        /// </summary>
        public String IdentityCard { get; set; }

        /// <summary>
        /// 人脸匹配度
        /// 身份证或从业资格证照片与人脸匹配度比例:0~100
        /// 2019版本
        /// </summary>
        public Byte? FaceMatch { get; set; }

        /// <summary>
        /// 身份证 UID
        /// 长度 20 位,不足补0x00
        /// 2019版本
        /// </summary>
        public String UID { get; set; }

        /// <summary>解析消息</summary>
        /// <param name="stream"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public Boolean Read(Stream stream, Object? context)
        {
            var reader = Helper.CreateReader(stream);
            var header = context as JTMessage;

            // 因2011第一个字节代表姓名长度 所以该值长度只能为  2,3,4,整个数据长度 62+m+n
            var firstByte = reader.ReadByte();
            if (firstByte == 0x01)
            {
                Status = (CardStatus)firstByte;

                // 过滤非标BCD数据
                var str = reader.ReadBCD(6);
                if (DateTime.TryParseExact(str, "yyMMddHHmmss", null, DateTimeStyles.None, out var dt))
                    Time = dt;
                else if (DateTime.TryParseExact(str[2..], "MMddHHmmss", null, DateTimeStyles.None, out dt))
                    Time = dt;

                if (Status == CardStatus.插入)
                {
                    Result = (CardResult)reader.ReadByte();
                    if (Result == CardResult.读卡成功)
                    {
                        UserName = reader.ReadString();
                        QualificationCode = reader.ReadString(20);
                        LicenseIssuing = reader.ReadString();
                        //UserName = reader.Read<String>();
                        //QualificationCode = reader.ReadFixedString(20);
                        //LicenseIssuing = reader.Read<String>();
                        CertificateExpire = reader.ReadBCD(4);

                        if (header.Version >= 1)
                        {
                            IdentityCard = reader.ReadString(20);
                            //IdentityCard = reader.ReadFixedString(20);

                            // 兼容808-2019 补充
                            if (stream.Position < stream.Length)
                            {
                                FaceMatch = reader.ReadByte();
                                UID = reader.ReadFixedString(20);
                            }
                        }
                    }
                }
            }
            else
            {
                if (firstByte == 0x02 && stream.Position + 6 == stream.Length)
                {
                    // 如果字节是0x02且长度只有7,那么该协议就是2013或者2019
                    Status = (CardStatus)firstByte;
                    var str = reader.ReadBCD(6);
                    if (DateTime.TryParseExact(str, "yyMMddHHmmss", null, DateTimeStyles.None, out var dt))
                        Time = dt;
                    //Time = reader.ReadDateTime();
                }
                else
                {
                    var len = firstByte;
                    UserName = reader.ReadFixedString(len);
                    IdentityCard = reader.ReadFixedString(20);
                    QualificationCode = reader.ReadFixedString(40);
                    LicenseIssuing = reader.ReadString();
                    //LicenseIssuing = reader.Read<String>();
                }
            }

            return true;
        }

        /// <summary>写入消息</summary>
        /// <param name="stream"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public Boolean Write(Stream stream, Object? context)
        {
            var writer = Helper.CreateWriter(stream);
            var header = context as JTMessage;

            if (header.Version == 0)
            {
                writer.Write(UserName);
                writer.WriteFixedString(IdentityCard, 20);
                writer.WriteFixedString(QualificationCode, 40);
                writer.Write(LicenseIssuing);
            }
            else
            {
                writer.WriteByte((Byte)Status);
                //writer.WriteDateTime(Time);
                writer.WriteBCD(Time.ToString("yyMMddHHmmss"), 6);
                if (Status == CardStatus.插入)
                {
                    writer.WriteByte((Byte)Result);
                    if (Result == CardResult.读卡成功)
                    {
                        writer.Write(UserName);
                        writer.WriteFixedString(QualificationCode, 20);
                        writer.Write(LicenseIssuing);
                        writer.WriteBCD(CertificateExpire, 4);

                        if (header.Version == 1)
                        {
                            writer.WriteFixedString(IdentityCard, 20);

                            //兼容808-2019 补充
                            if (FaceMatch.HasValue) writer.WriteByte(FaceMatch.Value);
                            if (!String.IsNullOrEmpty(UID)) writer.WriteFixedString(UID, 20);
                        }
                    }
                }
            }

            return true;
        }
    }
}