道路運輸車輛衛星定位系統JT/T808服務實現和壓測

smark發表於2017-05-24

        在工作上的需要接觸道路運輸車輛衛星定位系統相關應用,由於自己對網路服務的編寫比較感興趣,所以利用空閒時間實現了JT/T808的一些協議和相關服務(不得不說這種協議的設計在解釋的確導致效能上的損耗,特別針地託管語言的C#來說就更加容易導致效能問題,不過對於現有硬體資源來說一臺簡配的PC支撐上幾萬個終端那還是沒什麼壓力的).主要基於興趣來寫所以JT/T808只實現了幾個常用的協議:0x0002,0x0200,0x0100等.

        為了更好地進行模擬測試還實現了一個簡單的JT/T808模擬器方便進行一些簡單的測試  

       

訊息封裝

         一個好的訊息封裝會給訊息擴充套件帶來極大的方便和效率(不過不得不面對資源損耗的加大).Beetle.JT808採用物件結合特性的方式來描述一個JT808訊息,特別對於一個多位組合的屬性也通過物件化來表現,這樣可以上使用者使用起來更方便和簡單.

    /// <summary>
    /// 終端註冊
    /// </summary>
    [MessageType(ID = 0x0100)]
    public class Register 
    {
        /// <summary>
        /// 標示終端安裝車輛所在的省域,0保留,由平臺取預設值。省域ID採用GB/T 2260中規定的行政區劃程式碼六位中前兩位
        /// </summary>
        [UInt16Handler]
        public ushort Province { get; set; }
        /// <summary>
        /// 標示終端安裝車輛所在的市域和縣域,0保留, 由平臺取預設值。市縣域ID採用GB/T 2260中規定的行政區劃程式碼六位後四位
        /// </summary>
        [UInt16Handler]
        public ushort City { get; set; }
        /// <summary>
        /// 五個位元組,終端製造商編碼。
        /// </summary>
        [ASCIIHandler(5)]
        public string Provider { get; set; }
        /// <summary>
        /// 八個位元組,此終端型號由製造商自行定義,位數不是八位的,補空格。
        /// </summary>
        [ASCIIHandler(8)]
        public string DeviceNumber { get; set; }
        /// <summary>
        /// 七個位元組,由大寫字母和數字組成,此終端ID由製造商自行定義
        /// </summary>
        [ASCIIHandler(7)]
        public string DeviceID { get; set; }
        /// <summary>
        /// 車牌顏色,按照JT/T 415-2006的5.4.12
        /// </summary>
        [ByteHandler]
        public byte Color { get; set; }
        /// <summary>
        /// 公安交通管理部門頒發的機動車號牌
        /// </summary>
        [GBKHandler]
        public string PlateNumber { get; set; }
    }
}

伺服器封裝

        有服務端封裝上也是採購訊息事件來驅動訊息邏輯的處理,這樣在擴充套件訊息處理上也非常方便

        protected virtual void OnPostion(Message msg, Messages.Postion e, Beetle.Express.IChannel channel)
        {
            channel.Name = msg.SIM;
            channel["GPS_INFO"] = e;
            if (Loger.Enabled(LogType.DEBUG))
                Loger.Process(LogType.DEBUG, "{0} postion lng:{1}/lat:{2} time:{3}", msg.SIM, e.Longitude, e.Latitude, e.Time);
            ReturnCenterResponse(msg, channel);
        }

        protected virtual void OnRegister(Message msg, Messages.Register e, Beetle.Express.IChannel channel)
        {
            if (Loger.Enabled(LogType.DEBUG))
                Loger.Process(LogType.DEBUG, "{0} registed platenumber:{1}", msg.SIM, e.PlateNumber);
            Message result = MessageFactory.CreateMessage<RegisterResponse>(msg.SIM);
            RegisterResponse response = result.GetBody<RegisterResponse>();
            response.BusinessNO = msg.BussinessNO;
            response.Result = RegisterStatus.Success;
            response.Signature = Guid.NewGuid().ToString("N");
            result.Send(channel);
        }

        protected virtual void OnSignature(Message msg, Messages.ClientSignature e, Beetle.Express.IChannel channel)
        {
            if (Loger.Enabled(LogType.DEBUG))
                Loger.Process(LogType.DEBUG, "{0} signature {1}", msg.SIM, e.Signature);
            ReturnCenterResponse(msg, channel);
        }

        protected virtual void OnNotImplement(Message msg, Messages.MessageNotImplement e, Beetle.Express.IChannel channel)
        {
            if (Loger.Enabled(LogType.DEBUG))
                Loger.Process(LogType.DEBUG, "{0} message:{1} not implement!", msg.SIM, e.MessageID);
            ReturnCenterResponse(msg, channel);
        }

壓測結果

        雖然對服務功能進行了大量的抽象封裝,在效率上會有很大的開銷損耗.但在現有的硬體資源下並不會存在多大問題.以下是模擬10000個終端裝置每5秒提交一條車輛行駛資訊的測試情況:

        服務端是一臺虛擬化的4核,16G記憶體的電腦.

        行車資訊:

                Messages.Postion postion = new Messages.Postion();
                postion.Direction = (ushort)ran.Next(ushort.MinValue, ushort.MaxValue);
                postion.Height = (ushort)ran.Next(ushort.MinValue, ushort.MaxValue);
                postion.Latitude = (uint)ran.Next(0, 2000000);
                postion.Longitude = (uint)ran.Next(0, 2000000);
                postion.Speed = (ushort)ran.Next(ushort.MinValue, ushort.MaxValue);
                postion.Time = DateTime.Now;
                postion.FuelGauge.Value = (ushort)ran.Next(ushort.MinValue, ushort.MaxValue);
                postion.Milometer.Value = (uint)ran.Next(0, 2000000);
                postion.Speedometer.Value = (ushort)ran.Next(10, 200);
                Client.Postion(postion);

        伺服器壓力17小時後的結果:

         

         測試終端情況:

         

 

相關文章