From b290be9dde1492fa276649d4eb7acbb5c5f24e55 Mon Sep 17 00:00:00 2001
From: Administrator <Administrator@DESKTOP-1VKMM8S>
Date: 星期一, 15 三月 2021 15:03:03 +0800
Subject: [PATCH] 1.新增配置文件来修改镜头R边; 2.新增背板区分可视区和非可视区。

---
 P066.Data/P066.Data.csproj               |    7 
 Bro.Comn/Link/LinkBase.cs                |  106 +
 Bro.Comn/Link/TCPClient.cs               |  237 +++
 Bro.Comn/Properties/AssemblyInfo.cs      |   35 
 Bro.Comn/Util/ConfigHelper.cs            |  110 +
 P066XML/Jin_Mid.xml                      |   15 
 Bro.Comn/PubSub/ISubscriber.cs           |   19 
 P066XML/Jin_Mid - 副本.xml                 |   15 
 Bro.Comn/Link/SerialLink.cs              |  154 ++
 Bro.Comn/PubSub/SimplePubSubCenter.cs    |  391 +++++
 Bro.Comn/Except/ExceptionBase.cs         |   11 
 Bro.Comn/PubSub/IPublisher.cs            |   15 
 Bro.Comn/Procedure/UnitBase.cs           |  140 ++
 Bro.Comn/Util/LoginConfig.cs             |   39 
 P066.Data/P066RunParam.cs                |   29 
 Bro.Comn/Procedure/ProcedureIO.cs        |   11 
 Bro.Comn/Procedure/ProcedureBase.cs      |  475 ++++++
 Bro.Comn/AbstractFSM/State.cs            |   32 
 Bro.Comn/Procedure/IODataBase.cs         |  200 ++
 Bro.Comn/Link/TCPSvr.cs                  |  321 ++++
 P066.Data.sln                            |   20 
 Bro.Comn/AbstractFSM/Transition.cs       |  116 +
 Bro.Comn/PubSub/IPubSubCenter.cs         |   63 
 Bro.Comn/packages.config                 |    4 
 Bro.Comn/Properties/Resource.resx        |  124 +
 Bro.Comn/AbstractFSM/StatesManager.cs    |   63 
 Bro.Comn/Link/SerialPort.cs              |  449 ++++++
 Bro.Comn/PubSub/PubSubCenter.cs          |   28 
 P066.Data/Form1.cs                       |  143 +
 Bro.Comn/Properties/Resource.Designer.cs |   85 +
 Bro.Comn/Link/TCPLink.cs                 |  126 +
 Bro.Comn/OEE/OEEToolKit.cs               |  242 +++
 P066.Data/P066RunPaream.cs               |   23 
 Bro.Comn/FSM/SimpleFSM.cs                |   98 +
 Bro.Comn/Bro.Comn.csproj                 |  128 +
 Bro.Comn/PubSub/SimpleSubscriber.cs      |   19 
 36 files changed, 4,077 insertions(+), 16 deletions(-)

diff --git a/Bro.Comn/AbstractFSM/State.cs b/Bro.Comn/AbstractFSM/State.cs
new file mode 100644
index 0000000..d6a562d
--- /dev/null
+++ b/Bro.Comn/AbstractFSM/State.cs
@@ -0,0 +1,32 @@
+锘縰sing System;
+
+namespace Bro.Common.AbstractFSM
+{
+    public class StateEventArgs : EventArgs
+    {
+        public StateEventArgs(int id)
+        {
+            m_id = id;
+        }
+        private int m_id;
+        public int Id
+        {
+            get { return m_id; }
+        }
+    }
+
+    public class State
+    {
+        private String m_sState = null;
+        public State(string sState)
+        {
+            m_sState = sState; 
+        }
+        protected virtual void ChangeState(object sender, StateEventArgs eventArgs) {}
+
+        public override string ToString()
+        {
+            return m_sState;
+        }
+    }
+}
diff --git a/Bro.Comn/AbstractFSM/StatesManager.cs b/Bro.Comn/AbstractFSM/StatesManager.cs
new file mode 100644
index 0000000..b248aca
--- /dev/null
+++ b/Bro.Comn/AbstractFSM/StatesManager.cs
@@ -0,0 +1,63 @@
+锘縰sing System;
+
+namespace Bro.Common.AbstractFSM
+{
+    
+    public interface IStateManager : IDisposable 
+    {
+        void ChangeState(object sender, StateEventArgs eventArgs);
+        bool CheckState(object sender, StateEventArgs eventArgs);
+    }
+    public abstract class StatesManager : IStateManager
+    {
+        // Declare the delegate (if using non-generic pattern).
+        public delegate void StateChangedEventHandler(object sender, StateEventArgs eventArgs);
+        // Declare the event.
+        public event StateChangedEventHandler StateChanged;
+
+        public StatesManager()
+        {
+            //build transitions and set an initial state
+            m_activeState = BuildTransitionsTable(); 
+        }
+
+        public virtual void Dispose()
+        {
+            //virtual method
+        }
+        State m_activeState = null;
+        public State ActiveState
+        {
+            get { return m_activeState; }
+        }
+
+        Transitions m_transitions = new Transitions();
+        public Transitions Transitions
+        {
+            get { return m_transitions; }
+        }
+        //returns initial state
+        protected abstract State BuildTransitionsTable();
+        //
+        public virtual void ChangeState(object sender, StateEventArgs eventArgs)
+        {
+            Transition transition = m_transitions[m_activeState, eventArgs];
+            m_activeState = transition.finalState;
+            //raise 'StateChanged' event
+             if (StateChanged != null)
+                 StateChanged(this, eventArgs); 
+            if (transition.action != null)
+                transition.action(this, eventArgs);
+            //if the transitional is automatic - automatically go to the next state:
+            if (transition.AutoMode == true && transition.AutoTransition != null)
+            {
+                m_activeState = transition.AutoTransition.initialState;
+                ChangeState(sender, transition.AutoTransition.eventArgs);    
+            }
+        }
+        public virtual bool CheckState(object sender, StateEventArgs eventArgs)
+        {
+            return m_transitions.ContainsKey(Transition.GetHashCode(m_activeState, eventArgs));
+        } 
+    }
+}
diff --git a/Bro.Comn/AbstractFSM/Transition.cs b/Bro.Comn/AbstractFSM/Transition.cs
new file mode 100644
index 0000000..16231c8
--- /dev/null
+++ b/Bro.Comn/AbstractFSM/Transition.cs
@@ -0,0 +1,116 @@
+锘縰sing System;
+using System.Collections.Generic;
+
+namespace Bro.Common.AbstractFSM
+{
+    //actions that are performed when state changed
+    public delegate void StateAction(object sender, StateEventArgs eventArgs);
+
+    public class Transition
+    {
+        private State m_initialState;
+        public State initialState
+        {
+            get { return m_initialState; }
+        }
+        private StateEventArgs m_eventArgs;
+        public StateEventArgs eventArgs
+        {
+            get { return m_eventArgs; }
+        }
+        private State m_finalState;
+        public State finalState
+        {
+            get { return m_finalState; }
+        }
+        private StateAction m_state_action;
+        public StateAction action
+        {
+            get { return m_state_action; }
+        }
+        private bool m_autoMode = false;
+        public bool AutoMode
+        {
+            get { return m_autoMode; }
+        }
+
+        private Transition m_autoTransition = null;
+        public Transition AutoTransition
+        {
+            get { return m_autoTransition; }
+        }
+
+        public Transition(State initialState, StateEventArgs sevent, State finalState, StateAction action)
+        {
+            m_initialState = initialState;
+            m_eventArgs = sevent;
+            m_finalState = finalState;
+            m_state_action = action;
+        }
+        public Transition(State initialState, StateEventArgs sevent, State finalState, StateAction action, bool autoMode, Transition autoTransition) 
+                         : this(initialState, sevent, finalState, action)    
+        {
+            m_autoMode = autoMode;
+            m_autoTransition = autoTransition; 
+        }
+        public override int GetHashCode()
+        {
+            //create a unique transition key
+            return GetHashCode(m_initialState, m_eventArgs);
+        }
+
+        public static int GetHashCode(State state, StateEventArgs sevent)
+        {
+            return (state.GetHashCode() << 8) + sevent.Id;
+        }
+    }
+    /// <summary>
+    /// Represents a collection of transition objects.
+    /// </summary>
+    public class Transitions : System.Collections.Generic.Dictionary <int, Transition>   
+    {
+        /// <summary>Adds the specified transition to the collection.</summary> 
+        /// <param name="transition">Transition object</param>      
+        /// <see cref="System.Collections.Generic.Dictionary {int, Transition}"/>
+        /// <exception cref="System.ArgumentNullException">Key is null</exception>
+        /// <exception cref="System.ArgumentException">An transition with the same key already exists.</exception>
+        public void Add(Transition transition)
+        {
+            // The Add method throws an exception if the new key is already in the dictionary.
+            try
+            {
+                base.Add(transition.GetHashCode(), transition);
+            }
+            catch (ArgumentException)
+            {
+                throw new ArgumentException("A transition with the key (Initials state " + 
+                        transition.initialState + ", Event " + 
+                        transition.eventArgs + ") already exists.");
+            }  
+        }
+        //
+        public Transition this[State state, StateEventArgs sevent]
+        {
+            get
+            {
+                try
+                {
+                    return this[Transition.GetHashCode(state, sevent)];
+                }
+                catch(KeyNotFoundException)
+                {
+                    throw new KeyNotFoundException("The given transition was not found.");
+                }
+            }
+            set
+            {
+                this[Transition.GetHashCode(state, sevent)] = value;
+            }
+        }
+        //
+        public bool Remove(State state, StateEventArgs sevent)
+        {
+            return base.Remove(Transition.GetHashCode(state, sevent));   
+        }
+    }
+}
diff --git a/Bro.Comn/Bro.Comn.csproj b/Bro.Comn/Bro.Comn.csproj
new file mode 100644
index 0000000..1752f2e
--- /dev/null
+++ b/Bro.Comn/Bro.Comn.csproj
@@ -0,0 +1,128 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{42407C78-FB75-4310-8910-DF515652A012}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Broc.Comn</RootNamespace>
+    <AssemblyName>Broc.Comn</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x86\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+    <OutputPath>bin\x86\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
+      <HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Configuration" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Web" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AbstractFSM\State.cs" />
+    <Compile Include="AbstractFSM\StatesManager.cs" />
+    <Compile Include="AbstractFSM\Transition.cs" />
+    <Compile Include="Except\ExceptionBase.cs" />
+    <Compile Include="FSM\SimpleFSM.cs" />
+    <Compile Include="Link\LinkBase.cs" />
+    <Compile Include="Link\SerialLink.cs" />
+    <Compile Include="Link\SerialPort.cs" />
+    <Compile Include="Link\TCPClient.cs" />
+    <Compile Include="Link\TCPLink.cs" />
+    <Compile Include="Link\TCPSvr.cs" />
+    <Compile Include="Log\LogHelper.cs" />
+    <Compile Include="Log\LogTraceListener.cs" />
+    <Compile Include="OEE\OEEToolKit.cs" />
+    <Compile Include="Procedure\IODataBase.cs" />
+    <Compile Include="Procedure\ProcedureBase.cs" />
+    <Compile Include="Procedure\ProcedureIO.cs" />
+    <Compile Include="Procedure\UnitBase.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="PubSub\IPublisher.cs" />
+    <Compile Include="PubSub\ISubscriber.cs" />
+    <Compile Include="PubSub\IPubSubCenter.cs" />
+    <Compile Include="PubSub\PubSubCenter.cs" />
+    <Compile Include="PubSub\SimplePubSubCenter.cs" />
+    <Compile Include="PubSub\SimpleSubscriber.cs" />
+    <Compile Include="Properties\Resource.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resource.resx</DependentUpon>
+    </Compile>
+    <Compile Include="Util\ConfigHelper.cs" />
+    <Compile Include="Util\LoginConfig.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Properties\Resource.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resource.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Log\BroClog4net.xml">
+      <SubType>Designer</SubType>
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PostBuildEvent>
+    </PostBuildEvent>
+  </PropertyGroup>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Bro.Comn/Except/ExceptionBase.cs b/Bro.Comn/Except/ExceptionBase.cs
new file mode 100644
index 0000000..80077ff
--- /dev/null
+++ b/Bro.Comn/Except/ExceptionBase.cs
@@ -0,0 +1,11 @@
+锘縰sing System;
+
+namespace Bro.Common.AbstractFSM
+{
+    /// <summary>
+    /// 寮傚父鍩虹被
+    /// </summary>
+    public class ExceptionBase : Exception
+    {
+    }
+}
diff --git a/Bro.Comn/FSM/SimpleFSM.cs b/Bro.Comn/FSM/SimpleFSM.cs
new file mode 100644
index 0000000..a4f2c30
--- /dev/null
+++ b/Bro.Comn/FSM/SimpleFSM.cs
@@ -0,0 +1,98 @@
+锘縰sing System.Collections.Generic;
+
+namespace Bro.Common.FSM
+{
+    // 鐘舵�佸鐞嗕唬鐞嗗畾涔�
+    public delegate void StatHandler();
+
+
+    public class SimpleFSM
+    {
+        // 鐘舵�佹満鎻忚堪
+        public string   Desp { get;set; }
+
+        // 褰撳墠鐘舵��
+        private int     curStat { get;set;}
+
+        // 鐘舵�佸姩浣滆〃
+        private Dictionary<int, StatHandler> statTbl = new Dictionary<int,StatHandler>();
+
+        public SimpleFSM()
+        {
+        
+        }
+
+        /// <summary>
+        /// 娉ㄥ唽鐘舵�佸鐞�
+        /// </summary>
+        /// <param name="stat"></param>
+        /// <param name="handle"></param>
+        /// <returns></returns>
+        public bool Regist(int stat, StatHandler handle)
+        {
+            if ( null == handle || statTbl.ContainsKey(stat) )
+            {
+                return false;
+            }
+
+            statTbl.Add(stat, handle);
+
+            return true;
+        }
+
+        /// <summary>
+        /// 娉ㄥ唽鐘舵�佸鐞嗚〃
+        /// </summary>
+        /// <param name="statTbl"></param>
+        /// <returns></returns>
+        public bool Regist(Dictionary<int, StatHandler> statTbl)
+        {
+            this.statTbl = statTbl;
+
+            return true;
+        }
+
+        /// <summary>
+        /// 璁剧疆褰撳墠鐘舵��
+        /// </summary>
+        /// <param name="stat"></param>
+        public void SetStat(int stat)
+        {
+            this.curStat = stat;
+        }
+
+        /// <summary>
+        /// 鑾峰彇褰撳墠鐘舵��
+        /// </summary>
+        /// <returns></returns>
+        public int GetStat()
+        {
+            return curStat;
+        }
+
+        /// <summary>
+        /// 鐘舵�佸熀杩愯
+        /// </summary>
+        public void Run()
+        {
+            for (; ; )
+            {
+                foreach (var item in statTbl)
+                {
+                    StatHandler handle = item.Value;
+                    if (null == handle)
+                    {
+                        continue;
+                    }
+
+                    if (curStat == item.Key)
+                    {
+                        handle();
+                        break;
+                    }
+                }
+            }
+
+        }
+    }
+}
diff --git a/Bro.Comn/Link/LinkBase.cs b/Bro.Comn/Link/LinkBase.cs
new file mode 100644
index 0000000..9378604
--- /dev/null
+++ b/Bro.Comn/Link/LinkBase.cs
@@ -0,0 +1,106 @@
+锘縰sing System;
+using System.Diagnostics;
+
+namespace Bro.Common.Link
+{
+    /// <summary>
+    /// 璁惧鐨勮繛鎺ュ熀绫�
+    /// </summary>
+    public abstract class LinkBase
+    {
+        // 榛樿淇濆瓨鏁版嵁缂撳瓨闀垮害
+        public const int        DFT_BUFF_LEN    = 4096;
+
+        // 杩炴帴瀵硅薄鎺ユ敹缂撳瓨澶у皬
+        public const int        DFT_SEND_BUFF_LEN   = 4096;
+        // 杩炴帴瀵硅薄鍙戦�佺紦瀛樺ぇ灏�
+        public const int        DFT_RECV_BUFF_LEN   = 4096;
+
+        // 杩炴帴鎻忚堪
+        public string   Desp { get;set;}
+        // 鍒濆鍖栫姸鎬�
+        public bool     IsInit { get;set; }
+        // 杩炴帴鐘舵��
+        public bool     IsConn { get;set;}
+        // 鎺ユ敹缂撳瓨闀垮害
+        public int      BufferLen { get;set;}
+        // 鎺ユ敹缂撳瓨澶у皬
+        public int      SendBuffLen { get;set;}
+        // 鍙戦�佺紦瀛樺ぇ灏�
+        public int      RecvBuffLen { get;set;}
+
+        // 鎺ユ敹缂撳瓨
+        protected byte[] rcvBuf = null;
+
+        // 杩炴帴鐘舵��
+        public LinkBase()
+        {
+            Desp        = this.GetType().Name;
+            IsInit      = false;
+            IsConn      = false;
+            SendBuffLen = DFT_SEND_BUFF_LEN;
+            RecvBuffLen = DFT_RECV_BUFF_LEN;
+            BufferLen   = DFT_BUFF_LEN;
+
+        }
+
+        /// <summary>
+        /// 杩炴帴鍒濆鍖�
+        /// </summary>
+        /// <returns></returns>
+        public virtual bool Init()
+        {
+            if ( IsInit )
+            {
+                return true;
+            }
+
+            try
+            {
+                rcvBuf = new byte[BufferLen];
+
+                return true;
+            }
+            catch(Exception ex)
+            {
+                Trace.TraceError("Link:{0} Init fail, ex:{1}-{2}", this.Desp, ex.Message, ex.StackTrace);
+            }
+
+            return false;
+        }
+
+        /// <summary>
+        /// 鎵撳紑杩炴帴
+        /// </summary>
+        /// <returns></returns>
+        public abstract bool Open();
+
+        /// <summary>
+        /// 鍏抽棴杩炴帴
+        /// </summary>
+        public abstract void Close();
+
+        /// <summary>
+        /// 閿�姣�
+        /// </summary>
+        public abstract void Fnit();
+
+        /// <summary>
+        /// 鎺ユ敹鏁版嵁
+        /// </summary>
+        /// <param name="rcvBuf"></param>
+        /// <param name="offset"></param>
+        /// <returns></returns>
+        public abstract int Recv(byte[] rcvBuf, int offset);
+
+        /// <summary>
+        /// 鍙戦�佹暟鎹�
+        /// </summary>
+        /// <param name="sndBuf"></param>
+        /// <returns></returns>
+        public abstract bool Send(byte[] sndBuf, int offset, int len);
+
+    }
+
+
+}
diff --git a/Bro.Comn/Link/SerialLink.cs b/Bro.Comn/Link/SerialLink.cs
new file mode 100644
index 0000000..c123e86
--- /dev/null
+++ b/Bro.Comn/Link/SerialLink.cs
@@ -0,0 +1,154 @@
+锘縰sing System;
+using System.Diagnostics;
+using System.IO.Ports;
+
+namespace Bro.Common.Link
+{
+    /// <summary>
+    /// 涓插彛杩炴帴
+    /// </summary>
+    public class SerialLink : LinkBase
+    {
+        // 榛樿涓插彛鍙�
+        public const int        DFT_PORT        = 1;
+        // 榛樿娉㈢壒鐜�
+        public const int        DFT_BAUD_RATE   = 9600;
+
+        // 涓插彛鍙�
+        public int  Port { get;set;}
+        // 娉㈢壒鐜�
+        public int  BaudRate { get;set;}
+        // 涓插彛杩炴帴
+        private SerialPort  SerialPort = new SerialPort();
+
+        public SerialLink()
+        {
+            IsConn       = false;
+
+            Port        = DFT_PORT;
+            BaudRate    = DFT_BAUD_RATE;
+        }
+
+        /// <summary>
+        /// 鎵撳紑涓插彛杩炴帴
+        /// </summary>
+        /// <returns></returns>
+        public override bool Open()
+        {
+            if ( SerialPort.IsOpen )
+            {
+                return true;
+            }
+
+            try
+            {
+                SerialPort.PortName         = "COM" + this.Port;
+                SerialPort.BaudRate         = this.BaudRate;
+                SerialPort.WriteBufferSize  = this.SendBuffLen;
+                SerialPort.ReadBufferSize   = this.RecvBuffLen;
+
+                SerialPort.Open();
+
+                base.IsConn = true;
+
+                return true;
+            }
+            catch(Exception ex)
+            {
+                Trace.TraceError("SerialLink:{0} Open fail, ex:{1}-{2}", this.Desp, ex.Message, ex.StackTrace);
+            }
+        
+            return false;
+        }
+
+        /// <summary>
+        /// 鍏抽棴涓插彛杩炴帴
+        /// </summary>
+        public override void Close()
+        {
+            try
+            {
+                if ( !SerialPort.IsOpen )
+                {
+                    return;
+                }
+            
+                SerialPort.Close();
+            }
+            catch(Exception ex)
+            {
+                Trace.TraceError("SerialLink:{0} Close fail, ex:{1}-{2}", this.Desp, ex.Message, ex.StackTrace);
+            }
+        
+        }
+
+        /// <summary>
+        /// 閿�姣�
+        /// </summary>
+        public override void Fnit()
+        {
+            Close();
+        }
+
+        /// <summary>
+        /// 鎺ユ敹鏁版嵁
+        /// </summary>
+        /// <param name="rcvBuf"></param>
+        /// <param name="bufLen"></param>
+        /// <returns></returns>
+        public override int Recv(byte[] rcvBuf, int offset)
+        {
+            int rcvLen = -1;
+
+            if ( null == rcvBuf )
+            {
+                return -1;
+            }
+
+            try
+            {
+                var len = rcvBuf.Length - offset;
+                if ( len <= 0 )
+                {
+                    return -1;
+                }
+
+                rcvLen = SerialPort.Read(rcvBuf, offset, len);
+            }
+            catch(Exception ex)
+            {
+                Trace.TraceError("SerialLink:{0} Recv fail, ex:{1}-{2}", this.Desp, ex.Message, ex.StackTrace);
+            }
+
+            return rcvLen;
+        }
+
+        /// <summary>
+        /// 鍙戦�佹暟鎹�
+        /// </summary>
+        /// <param name="sndBuf"></param>
+        /// <param name="offset"></param>
+        /// <returns></returns>
+        public override bool Send(byte[] sndBuf, int offset, int len)
+        {
+            if ( null == sndBuf )
+            {
+                return false;
+            }
+
+            try
+            {
+                SerialPort.Write(sndBuf, offset, len);
+                
+                return true;
+            }
+            catch(Exception ex)
+            {
+                Trace.TraceError("SerialLink:{0} Send fail, ex:{1}-{2}", this.Desp, ex.Message, ex.StackTrace);
+            }
+            
+            return false;
+        }
+        
+    }
+}
diff --git a/Bro.Comn/Link/SerialPort.cs b/Bro.Comn/Link/SerialPort.cs
new file mode 100644
index 0000000..0af2609
--- /dev/null
+++ b/Bro.Comn/Link/SerialPort.cs
@@ -0,0 +1,449 @@
+锘縰sing System;
+using System.Text;
+//using System.Threading.Tasks;
+using System.IO.Ports;
+using System.Windows.Forms;
+using System.Diagnostics;
+
+namespace Bro.Common.Link
+{
+    public class SerialComPort //: LinkBase
+    {
+        /// 鎺ユ敹浜嬩欢鏄惁鏈夋晥 false琛ㄧず鏈夋晥
+        public bool ReceiveEventFlag = false;
+        /// 缁撴潫绗︽瘮鐗�
+        public byte EndByte = 0x23;//string End = "#";
+        /// 瀹屾暣鍗忚鐨勮褰曞鐞嗕簨浠�
+        public event DataReceivedEventHandler DataReceived;
+        public event SerialErrorReceivedEventHandler Error;
+        #region 鍙橀噺灞炴��
+        private string _portName = "COM1";//涓插彛鍙凤紝榛樿COM1
+        private SerialPortBaudRates _baudRate = SerialPortBaudRates.BaudRate_9600;//娉㈢壒鐜�
+        private Parity _parity = Parity.None;//鏍¢獙浣�
+        private StopBits _stopBits = StopBits.One;//鍋滄浣�
+        private SerialPortDatabits _dataBits = SerialPortDatabits.EightBits;//鏁版嵁浣�
+        public SerialPort comPort = new SerialPort();
+        /// 涓插彛鍙�
+        public string PortName
+        {
+            get { return _portName; }
+            set { _portName = value; comPort.PortName = _portName; }
+        }
+        /// 娉㈢壒鐜�
+        public SerialPortBaudRates BaudRate
+        {
+            get { return _baudRate; }
+            set { _baudRate = value; comPort.BaudRate = (int)_baudRate; }
+        }
+        /// 濂囧伓鏍¢獙浣�
+        public Parity Parity
+        {
+            get { return _parity; }
+            set { _parity = value; comPort.Parity = _parity; }
+        }
+        /// 鏁版嵁浣�
+        public SerialPortDatabits DataBits
+        {
+            get { return _dataBits; }
+            set { _dataBits = value; comPort.DataBits = (int)_dataBits; }
+        }
+        /// 鍋滄浣�
+        public StopBits StopBits
+ 
+        {
+            get { return _stopBits; }
+            set { _stopBits = value; comPort.StopBits = _stopBits; }
+        }
+        #endregion
+        #region 鏋勯�犲嚱鏁�
+        /// 鍙傛暟鏋勯�犲嚱鏁帮紙浣跨敤鏋氫妇鍙傛暟鏋勯�狅級
+        /// <param name="baud">娉㈢壒鐜�</param>
+        /// <param name="par">濂囧伓鏍¢獙浣�</param>
+        /// <param name="sBits">鍋滄浣�</param>
+ 
+        /// <param name="dBits">鏁版嵁浣�</param>
+        /// <param name="name">涓插彛鍙�</param>
+        public SerialComPort(string name, SerialPortBaudRates baud, Parity par, SerialPortDatabits dBits, StopBits sBits)
+        {
+            _portName = name;
+            _baudRate = baud;
+            _parity = par; 
+            _dataBits = dBits;
+            _stopBits = sBits;
+            comPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived);
+            comPort.ErrorReceived += new SerialErrorReceivedEventHandler(comPort_ErrorReceived);
+        }
+        /// 鍙傛暟鏋勯�犲嚱鏁帮紙浣跨敤瀛楃涓插弬鏁版瀯閫狅級
+        /// <param name="baud">娉㈢壒鐜�</param>
+        /// <param name="par">濂囧伓鏍¢獙浣�</param>
+        /// <param name="sBits">鍋滄浣�</param>
+        /// <param name="dBits">鏁版嵁浣�</param>
+        /// <param name="name">涓插彛鍙�</param>
+        public SerialComPort(string name, string baud, string par, string dBits, string sBits)
+        {
+            _portName = name;
+            _baudRate = (SerialPortBaudRates)Enum.Parse(typeof(SerialPortBaudRates), baud);
+            _parity = (Parity)Enum.Parse(typeof(Parity), par);
+            _dataBits = (SerialPortDatabits)Enum.Parse(typeof(SerialPortDatabits), dBits);
+            _stopBits = (StopBits)Enum.Parse(typeof(StopBits), sBits);
+            comPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived);
+            comPort.ErrorReceived += new SerialErrorReceivedEventHandler(comPort_ErrorReceived);
+        }
+        /// 榛樿鏋勯�犲嚱鏁�
+        public SerialComPort()
+        {
+            _portName = "COM1";
+            _baudRate = SerialPortBaudRates.BaudRate_9600;
+            _parity = Parity.None;
+            _dataBits = SerialPortDatabits.EightBits;
+            _stopBits = StopBits.One;
+            comPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived);
+            comPort.ErrorReceived += new SerialErrorReceivedEventHandler(comPort_ErrorReceived);
+        }
+        #endregion
+        /// 绔彛鏄惁宸茬粡鎵撳紑
+        public bool IsOpen
+        {
+            get
+            {
+                return comPort.IsOpen;
+            }
+        }
+        /// 鎵撳紑绔彛
+        public void OpenPort()
+        {
+            if (comPort.IsOpen) comPort.Close();
+            comPort.PortName = _portName;
+            comPort.BaudRate = (int)_baudRate;
+            comPort.Parity = _parity;
+            comPort.DataBits = (int)_dataBits;
+            comPort.StopBits = _stopBits;
+            try
+            {
+                comPort.Open();
+ 
+            }
+            catch (System.Exception ex)
+            {
+                MessageBox.Show(ex.Message, "鎻愮ず淇℃伅", MessageBoxButtons.OK, MessageBoxIcon.Error);
+            }
+        }
+        /// 鍏抽棴绔彛
+        public void ClosePort()
+        {
+            if (comPort.IsOpen) comPort.Close();
+        }
+        /// 涓㈠純鏉ヨ嚜涓茶椹卞姩绋嬪簭鐨勬帴鏀跺拰鍙戦�佺紦鍐插尯鐨勬暟鎹�
+        public void DiscardBuffer()
+        {
+            comPort.DiscardInBuffer();
+            comPort.DiscardOutBuffer();
+        }
+        /// <summary> 
+        /// 鏁版嵁鎺ユ敹澶勭悊
+        /// </summary>
+        void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
+        {
+            byte[] receviedBuf;
+            receviedBuf = new byte[comPort.BytesToRead];
+            int itemp = comPort.BytesToRead;
+            int rcvByteLen = 0;
+            try
+            {
+                for (int i = 0; i < itemp; i++)
+                {
+                    receviedBuf[i] = Convert.ToByte(comPort.ReadByte());
+                    rcvByteLen++;
+                }
+                if (receviedBuf != null)
+                {
+                    DataReceived(new DataReceivedEventArgs(Encoding.ASCII.GetString(receviedBuf)));  
+                }  
+            }  
+            catch (System.Exception ex)  
+            {
+                Trace.TraceError("SerialPort receive fail,ex:{0}", ex);
+            } 
+        }
+   
+        /// 閿欒澶勭悊鍑芥暟
+  
+        void comPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
+        {
+            if (Error != null)
+            {
+                Error(sender, e);
+            }
+        }
+
+        #region 鏁版嵁鍐欏叆鎿嶄綔
+
+        /// 鍐欏叆鏁版嵁
+        /// <param name="msg"></param>
+        public void WriteData(string msg)
+        {
+            //if (!(comPort.IsOpen)) comPort.Open();
+            try
+            {
+                comPort.Write(msg);
+            }
+            catch (System.Exception ex)
+            {
+                Trace.TraceError("SerialPort write data fail,ex:{0}", ex);
+            }
+        }
+        /// <summary>
+        /// 鍐欏叆鏁版嵁
+        /// </summary>
+        /// <param name="msg">鍐欏叆绔彛鐨勫瓧鑺傛暟缁�</param>
+        public void WriteData(byte[] msg)
+        {
+            //if (!(comPort.IsOpen)) comPort.Open(); 
+            try
+            {
+                comPort.Write(msg, 0, msg.Length);
+            }
+            catch (System.Exception ex)
+            {
+                Trace.TraceError("SerialPort write data fail,ex:{0}", ex);
+            }
+           
+        }
+        /// <summary>
+        /// 鍐欏叆鏁版嵁
+        /// </summary>
+        /// <param name="msg">鍖呭惈瑕佸啓鍏ョ鍙g殑瀛楄妭鏁扮粍</param>
+        /// <param name="offset">鍙傛暟浠�0瀛楄妭寮�濮嬬殑瀛楄妭鍋忕Щ閲�</param>
+        /// <param name="count">瑕佸啓鍏ョ殑瀛楄妭鏁�</param>
+        public void WriteData(byte[] msg, int offset, int count) 
+        {
+            //if (!(comPort.IsOpen)) comPort.Open();
+            try
+            {
+                comPort.Write(msg, offset, count);
+            }
+            catch (System.Exception ex)
+            {
+                Trace.TraceError("SerialPort write data fail,ex:{0}", ex);
+            }
+   
+        }
+  
+        /// <summary>  
+        /// 鍙戦�佷覆鍙e懡浠�  
+        /// </summary>  
+        /// <param name="SendData">鍙戦�佹暟鎹�</param>  
+        /// <param name="ReceiveData">鎺ユ敹鏁版嵁</param>  
+        /// <param name="Overtime">閲嶅娆℃暟</param> 
+        /// <returns></returns>  
+        public int SendCommand(byte[] SendData, ref  byte[] ReceiveData, int Overtime)
+        {
+            if (!(comPort.IsOpen)) comPort.Open();
+            ReceiveEventFlag = true;        //鍏抽棴鎺ユ敹浜嬩欢
+            comPort.DiscardInBuffer();      //娓呯┖鎺ユ敹缂撳啿鍖�                 
+            comPort.Write(SendData, 0, SendData.Length);           
+            int num = 0, ret = 0;
+            while (num++ < Overtime)
+            {
+                if (comPort.BytesToRead >= ReceiveData.Length) break;
+                System.Threading.Thread.Sleep(1);
+            }
+            if (comPort.BytesToRead >= ReceiveData.Length) 
+            { 
+                ret = comPort.Read(ReceiveData, 0, ReceiveData.Length); 
+            }
+            ReceiveEventFlag = false;       //鎵撳紑浜嬩欢
+ 
+            return ret;
+        }
+        #endregion
+  
+        #region 甯哥敤鐨勫垪琛ㄦ暟鎹幏鍙栧拰缁戝畾鎿嶄綔
+        /// <summary> 
+        /// 灏佽鑾峰彇涓插彛鍙峰垪琛� 
+        /// </summary>
+        /// <returns></returns>
+        public static string[] GetPortNames() 
+        {
+            return SerialPort.GetPortNames();
+        }
+  
+        /// <summary>  
+        /// 璁剧疆涓插彛鍙�
+        /// </summary>
+        /// <param name="obj"></param>
+        public static void SetPortNameValues(ComboBox obj)
+        {
+            obj.Items.Clear();
+            foreach (string str in SerialPort.GetPortNames())
+            {
+                obj.Items.Add(str);
+            } 
+        }
+        /// <summary>
+        /// 璁剧疆娉㈢壒鐜�
+        /// </summary>
+        public static void SetBauRateValues(ComboBox obj)
+        {
+            obj.Items.Clear(); 
+            foreach (SerialPortBaudRates rate in Enum.GetValues(typeof(SerialPortBaudRates)))
+            {
+                obj.Items.Add(((int)rate).ToString());
+            } 
+        }
+        /// <summary>
+        /// 璁剧疆鏁版嵁浣�
+        /// </summary>
+        public static void SetDataBitsValues(ComboBox obj)
+        {
+            obj.Items.Clear();
+            foreach (SerialPortDatabits databit in Enum.GetValues(typeof(SerialPortDatabits)))
+            {
+                obj.Items.Add(((int)databit).ToString());
+            }
+        } 
+        /// <summary>
+        /// 璁剧疆鏍¢獙浣嶅垪琛�
+        /// </summary>
+        public static  void SetParityValues(ComboBox obj)
+        {
+            obj.Items.Clear();
+            foreach (string str in Enum.GetNames(typeof(Parity))) 
+            {
+                obj.Items.Add(str);  
+            }
+        }
+  
+        /// <summary>
+        /// 璁剧疆鍋滄浣�
+        /// </summary>
+        public static void SetStopBitValues(ComboBox obj)
+        {
+  
+            obj.Items.Clear(); 
+            foreach (string str in Enum.GetNames(typeof(StopBits)))
+            {
+                obj.Items.Add(str);
+            }
+ 
+        }
+  
+        #endregion
+  
+        #region 鏍煎紡杞崲 
+        /// <summary> 
+        /// 杞崲鍗佸叚杩涘埗瀛楃涓插埌瀛楄妭鏁扮粍  
+        /// </summary>  
+        /// <param name="msg">寰呰浆鎹㈠瓧绗︿覆</param> 
+        /// <returns>瀛楄妭鏁扮粍</returns> 
+        public static byte[] HexToByte(string msg)
+        {
+            msg = msg.Replace(" ", "");//绉婚櫎绌烘牸
+ 
+            //create a byte array the length of the
+ 
+            //divided by 2 (Hex is 2 characters in length)
+ 
+            byte[] comBuffer = new byte[msg.Length / 2];
+            for (int i = 0; i < msg.Length; i += 2) 
+            {
+                comBuffer[i / 2] = (byte)Convert.ToByte(msg.Substring(i, 2), 16);
+            }
+            return comBuffer;
+        }
+ 
+        /// <summary>
+        /// 杞崲瀛楄妭鏁扮粍鍒板崄鍏繘鍒跺瓧绗︿覆
+        /// </summary>
+        /// <param name="comByte">寰呰浆鎹㈠瓧鑺傛暟缁�</param> 
+        /// <returns>鍗佸叚杩涘埗瀛楃涓�</returns>
+        public static string ByteToHex(byte[] comByte)  
+        {  
+            string returnStr = ""; 
+            if (comByte != null) 
+            {
+                for (int i = 0; i < comByte.Length; i++)
+                {
+                    returnStr += comByte[i].ToString("X2")+" ";
+                }
+            }
+            return returnStr;
+        }
+ 
+        #endregion
+  
+        /// <summary>
+        /// 妫�鏌ョ鍙e悕绉版槸鍚﹀瓨鍦�
+        /// </summary>
+        /// <param name="port_name"></param> 
+        /// <returns></returns>
+        public static bool Exists(string port_name) 
+        {
+            foreach (string port in SerialPort.GetPortNames()) if (port == port_name) return true;
+            return false;
+        }
+ 
+        /// <summary>
+        /// 鏍煎紡鍖栫鍙g浉鍏冲睘鎬�
+        /// </summary>
+        /// <param name="port"></param>
+        /// <returns></returns>
+        public static string Format(SerialPort port)
+        {
+            return String.Format("{0} ({1},{2},{3},{4},{5})",
+                port.PortName, port.BaudRate, port.DataBits, port.Parity, port.StopBits, port.Handshake);
+        }
+    }
+    public class DataReceivedEventArgs : EventArgs
+    {
+        public string DataReceived;
+        public byte[] DataRecv;
+        public DataReceivedEventArgs(string m_DataReceived)
+        {
+            this.DataReceived = m_DataReceived;
+        }
+        public DataReceivedEventArgs(byte[] m_DataRecv)
+        {
+            this.DataRecv = m_DataRecv;
+        }
+    }
+    public delegate void DataReceivedEventHandler(DataReceivedEventArgs e);
+
+    /// <summary>
+    /// 涓插彛鏁版嵁浣嶅垪琛紙5,6,7,8锛�
+    /// </summary>
+    public enum SerialPortDatabits : int
+    {
+        FiveBits = 5,
+        SixBits = 6,
+        SeventBits = 7,
+        EightBits = 8
+    }
+    /// <summary>
+    /// 涓插彛娉㈢壒鐜囧垪琛ㄣ��
+    /// 75,110,150,300,600,1 0,2400,4800,9600,14400,19200,28800,38400,56000,57600,
+    /// 115200,128000,230400,256000
+    /// </summary>
+    public enum SerialPortBaudRates : int
+    {
+        BaudRate_75 = 75,
+        BaudRate_110 = 110,
+        BaudRate_150 = 150,
+        BaudRate_300 = 300,
+        BaudRate_600 = 600,
+        BaudRate_1200 = 1200,
+        BaudRate_2400 = 2400,
+        BaudRate_4800 = 4800,
+        BaudRate_9600 = 9600,
+        BaudRate_14400 = 14400,
+        BaudRate_19200 = 19200,
+        BaudRate_28800 = 28800,
+        BaudRate_38400 = 38400,
+        BaudRate_56000 = 56000,
+        BaudRate_57600 = 57600,
+        BaudRate_115200 = 115200,
+        BaudRate_128000 = 128000,
+        BaudRate_230400 = 230400,
+        BaudRate_256000 = 256000
+    }
+}
diff --git a/Bro.Comn/Link/TCPClient.cs b/Bro.Comn/Link/TCPClient.cs
new file mode 100644
index 0000000..e8f633d
--- /dev/null
+++ b/Bro.Comn/Link/TCPClient.cs
@@ -0,0 +1,237 @@
+锘縰sing System;
+using System.Diagnostics;
+using System.Net.Sockets;
+using System.Threading;
+
+namespace Bro.Common.Link
+{
+    public delegate void OnMessageRecv(byte[] dataBuff);
+
+    /// <summary>
+    /// TCP瀹㈡埛绔繛鎺�
+    /// </summary>
+    public class TCPClient : LinkBase
+    {
+        private static object synObj = new object();
+        // 鏈嶅姟鍣ㄥ湴鍧�
+        public string ServerIP { get;set;}
+        // 鏈嶅姟鍣↖P
+        public int ServerPort { get;set;}
+        // 鍒濆鍖栨爣绀�
+        public bool IsInited { get;set; }
+
+        public OnMessageRecv MessageRecv;
+
+        // TCP瀹㈡埛绔�
+        public TcpClient Client = new TcpClient();
+        
+        private Thread pollTask;
+
+        // 鍋滄鏍囩ず
+        private bool bStop = false;
+
+        public TCPClient()
+        {
+            IsInited = false;
+        }
+
+        /// <summary>
+        /// 鍒濆鍖�
+        /// </summary>
+        /// <returns></returns>
+        public override bool Init()
+        {
+            Client = new TcpClient();
+
+            // 鎺ユ敹鍙戦�佺紦瀛樺ぇ灏�
+            Client.SendBufferSize    = 4096;
+            Client.ReceiveBufferSize = 4096;
+        
+            // 璇诲啓瓒呮椂
+            Client.SendTimeout       = 2000;
+            Client.ReceiveTimeout    = 100;
+
+            IsInited = true;
+
+            return true;
+        }
+
+        /// <summary>
+        /// 閿�姣�
+        /// </summary>
+        public override void Fnit()
+        {
+            IsInited = false;
+
+            if ( null == Client )
+            {
+                return;
+            }
+
+            Client.Close();
+        }
+
+        /// <summary>
+        /// 杩炴帴鏈嶅姟鍣�
+        /// </summary>
+        /// <returns></returns>
+        public override bool Open()
+        {
+            try
+            {
+                if ( Client.Connected )
+                {
+                    Trace.TraceInformation("TCPClient:{0} dunpliated open", this.Desp);
+                    return true;
+                }
+
+                Client.Connect(ServerIP, ServerPort);
+                
+                //pollTask = new Thread(new ThreadStart(PollThread));
+                //pollTask.Start();
+
+                return true;
+            }
+            catch(Exception ex)
+            {
+                Trace.TraceError("TCPClient:{0} Open fail, ex:{1}-{2}", this.Desp, ex.Message, ex.StackTrace);
+            }
+
+            return false;
+        }
+
+        /// <summary>
+        /// 鍏抽棴杩炴帴
+        /// </summary>
+        public override void Close()
+        {
+            try
+            {
+                if ( !Client.Connected )
+                {
+                    return;
+                }
+                bStop = true;
+                ClosePollTask();
+                Client.Close();
+               
+            }
+            catch(Exception ex)
+            {
+                Trace.TraceError("TCPClient:{0} Close fail, ex:{1}-{2}", this.Desp, ex.Message, ex.StackTrace);
+            }
+        }
+        
+        /// <summary>
+        /// 鍒ゆ柇瀵规柟鏄惁鍦ㄧ嚎锛屽己鍒堕噸鏂拌繛鎺�
+        /// </summary>
+        public void ReConnect()
+        {
+            if(!Client.IsOnline())
+            {
+                Close();
+                Init();
+                Open();
+            }
+        }
+
+        /// <summary>
+        /// 鎺ユ敹鏁版嵁
+        /// </summary>
+        /// <returns></returns>
+        public override int Recv(byte[] rcvBuf, int offset)
+        {
+            int rcvLen = -1;
+
+            if ( null == rcvBuf )
+            {
+                return -1;
+            }
+
+            try
+            {
+                var len = rcvBuf.Length - offset;
+                if ( len <= 0 )
+                {
+                    return -1;
+                }
+                rcvLen = Client.GetStream().Read(rcvBuf, offset, len);
+            }
+            catch(Exception ex)
+            {
+                Trace.TraceError("TCPClient:{0} Recv fail, ex:{1}-{2}", this.Desp, ex.Message, ex.StackTrace);
+                return -1;
+            }
+
+            return rcvLen;
+        }
+
+        /// <summary>
+        /// 鍙戦�佹暟鎹�
+        /// </summary>
+        /// <param name="sndBuf"></param>
+        /// <param name="bufLen"></param>
+        public override bool Send(byte[] sndBuf, int offset, int len)
+        {
+            if ( null == sndBuf )
+            {
+                return false;
+            }
+
+            try
+            {
+                Client.GetStream().Write(sndBuf, offset, len);
+                
+                return true;
+            }
+            catch(Exception ex)
+            {
+                Trace.TraceError("TCPClient:{0} Send fail, ex:{1}-{2}", this.Desp, ex.Message, ex.StackTrace);
+            }
+            
+            return false;
+        }
+
+        public void ClosePollTask()
+        {
+            pollTask?.Abort();
+        }
+
+        public void StartPollTask()
+        {
+            pollTask = new Thread(new ThreadStart(PollThread));
+            pollTask.Start();
+        }
+
+        /// <summary>
+        /// 鐩戝惉绾跨▼
+        /// </summary>
+        private void PollThread()
+        {
+            for (; ; )
+            {
+                lock (synObj)
+                {
+                    if (bStop)
+                        break;
+
+                    var data = new byte[2048];
+                    if (Recv(data, 0) > 0)
+                    {
+                        MessageRecv(data);
+                    }
+                }
+            }
+        }
+
+      
+    }
+
+    public static class TcpClientEx
+    {
+        public static bool IsOnline(this TcpClient c)
+        {
+            return !((c.Client.Poll(1000, SelectMode.SelectRead) && (c.Client.Available == 0)) || !c.Client.Connected);
+        }
+    }
+}
diff --git a/Bro.Comn/Link/TCPLink.cs b/Bro.Comn/Link/TCPLink.cs
new file mode 100644
index 0000000..e1ddad7
--- /dev/null
+++ b/Bro.Comn/Link/TCPLink.cs
@@ -0,0 +1,126 @@
+锘縰sing System;
+using System.Diagnostics;
+using System.Net.Sockets;
+
+namespace Bro.Common.Link
+{
+    /// <summary>
+    /// TCP杩炴帴
+    /// </summary>
+    public class TCPLink : LinkBase
+    {
+        // 缃戠粶杩炴帴鏁版嵁娴�
+        public NetworkStream netStream      = null;
+        // 杩滅淇℃伅
+        public string        remoteInfo {get;set;}
+        // 鏄惁杩滅鍏抽棴
+        public bool         IsRemoteDisconn {get;set;}
+
+        public TCPLink(NetworkStream stream)
+        {
+            this.netStream          = stream;
+            this.IsRemoteDisconn    = false;
+        }
+
+        public TCPLink()
+        {
+            this.IsRemoteDisconn    = false;
+        }
+
+        /// <summary>
+        /// 鍒濆鍖�
+        /// </summary>
+        /// <returns></returns>
+        public override bool Init()
+        {
+            // TODO:
+            return true;
+        }
+
+        /// <summary>
+        /// 鎵撳紑TCP杩炴帴
+        /// </summary>
+        /// <returns></returns>
+        public override bool Open()
+        {
+            // TODO:
+            return true;
+        }
+
+        /// <summary>
+        /// 鍏抽棴TCP杩炴帴
+        /// </summary>
+        public override void Close()
+        {
+            // TODO:
+            if ( null == this.netStream )
+            {
+                return;
+            }
+
+            try
+            {
+                this.netStream.Close();
+                this.netStream = null;
+
+                this.IsRemoteDisconn = true;
+            }
+            catch(Exception ex)
+            {
+                Trace.TraceError("TCPLink:{0} Close fail, ex:{1}-{2}", this.Desp, ex.Message, ex.StackTrace);
+            }
+        }
+
+        /// <summary>
+        /// 閿�姣�
+        /// </summary>
+        public override void Fnit()
+        {
+            this.Close();
+        }
+
+        /// <summary>
+        /// 鎺ユ敹鏁版嵁
+        /// </summary>
+        /// <returns></returns>
+        public override int Recv(byte[] rcvBuf, int bufLen)
+        {
+            int len = -1;
+            try
+            {
+                len = netStream.Read(rcvBuf, 0, bufLen);
+            }
+            catch(Exception ex)
+            {
+                this.IsRemoteDisconn = true;
+
+                Trace.TraceError("TCPLink:{0} Recv fail, ex:{1}-{2}", this.Desp, ex.Message, ex.StackTrace);
+            }
+
+            return len;
+        }
+
+        /// <summary>
+        /// 鍙戦�佹暟鎹�
+        /// </summary>
+        /// <param name="sndBuf"></param>
+        /// <param name="bufLen"></param>
+        public override bool Send(byte[] sndBuf, int offset, int len)
+        {
+            try
+            {
+                netStream.Write(sndBuf, offset, len);
+
+                return true;
+            }
+            catch(Exception ex)
+            {
+                this.IsRemoteDisconn = true;
+
+                Trace.TraceError("TCPLink:{0} Send fail, ex:{1}-{2}", this.Desp, ex.Message, ex.StackTrace);
+            }
+
+            return false;
+        }
+    }
+}
diff --git a/Bro.Comn/Link/TCPSvr.cs b/Bro.Comn/Link/TCPSvr.cs
new file mode 100644
index 0000000..136a857
--- /dev/null
+++ b/Bro.Comn/Link/TCPSvr.cs
@@ -0,0 +1,321 @@
+锘縰sing System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+
+namespace Bro.Common.Link
+{
+    // 瀹㈡埛绔姩浣滀唬鐞�
+    public delegate void OnClientOpen(TcpClient client);
+    public delegate void OnClientClose(TcpClient client);
+    public delegate void OnClientRecv(TcpClient client);
+
+    /// <summary>
+    /// TCP鏈嶅姟鍣�
+    /// </summary>
+    public class TCPSvr
+    {
+        private static object synObj = new object();
+        public OnClientOpen       ClientOpen;
+        public OnClientClose      ClientClose;
+        public OnClientRecv       ClientRecv;
+
+        // 鏈嶅姟鍣ㄦ弿杩�
+        public string   Desp {get;set;}
+        // 鏈嶅姟鍣↖P
+        public string   ServerIP { get;set; }
+        // 鏈嶅姟鍣ㄧ鍙�
+        public int      ServerPort { get; set; }
+        // 鏈嶅姟鍣ㄧ洃鍚�
+        private TcpListener tcpSvr  = null;
+        // 鍋滄鏍囩ず
+        private bool bStop = false;
+        // 鐩戝惉绾跨▼
+        private Thread listenThread;
+        private Thread pollThread;
+
+        private Dictionary<Socket,TcpClient> clientsMap = new Dictionary<Socket,TcpClient>();
+
+        public TCPSvr()
+        {
+        }
+
+        public TCPSvr(string ip, int port)
+        {
+            ServerIP    = ip;
+            ServerPort = port;
+        }
+
+        /// <summary>
+        /// 鍒濆鍖�
+        /// </summary>
+        /// <returns></returns>
+        public bool Init()
+        {
+            try
+            {
+                var ip = IPAddress.Parse(ServerIP);
+
+                tcpSvr = new TcpListener(ip, ServerPort);
+
+                bStop = false;
+            }
+            catch(Exception ex)
+            {
+                Trace.TraceError("TCP server init fail,ex:{0}", ex);
+                return false;
+            }
+
+            return true;
+        }
+
+        /// <summary>
+        /// 鍚姩鐩戝惉
+        /// </summary>
+        /// <returns></returns>
+        public bool Start()
+        {
+            try
+            {
+                clientsMap.Clear();
+
+                tcpSvr.Start();
+
+                listenThread = new Thread(new ThreadStart(DoAcceptCallBack));
+                listenThread.Start();
+                
+                pollThread = new Thread(new ThreadStart(PollThread));
+                pollThread.Start();
+
+                bStop = false;
+            }
+            catch(Exception ex)
+            {
+                Trace.TraceError("TCP server start listen fail,ex:{0}", ex);
+                return false;
+            }
+
+            return true;
+        }
+
+        /// <summary>
+        /// 鍋滄鐩戝惉
+        /// </summary>
+        public void Stop()
+        {
+            bStop = true;
+
+            try
+            {
+                tcpSvr.Stop();
+
+                listenThread.Join();
+                pollThread.Join();
+
+            }
+            catch(Exception ex)
+            {
+                Trace.TraceError("TCP server stop listen fail,ex:{0}", ex);
+            }
+
+            bStop = true;
+        }
+
+        /// <summary>
+        /// 鍏抽棴瀹㈡埛绔�
+        /// </summary>
+        /// <param name="client"></param>
+        public void Close(TcpClient client)
+        {
+            lock(synObj)
+            {
+                clientsMap.Remove(client.Client);
+
+                client.Close();
+            }
+        }
+
+        /// <summary>
+        /// 绉婚櫎瀹㈡埛绔洃鍚�
+        /// </summary>
+        /// <param name="client"></param>
+        public void Remove(TcpClient client)
+        {
+            lock (synObj)
+            {
+                clientsMap.Remove(client.Client);
+            }
+        }
+
+        /// <summary>
+        /// 鐩戝惉绾跨▼
+        /// </summary>
+        private void PollThread()
+        {
+            for(;;)
+            {
+                if (bStop)
+                {
+                    CloseAllClient();
+
+                    Trace.TraceInformation("{0} tcp server stop trigger", Desp);
+                    break;
+                }
+
+                lock(synObj)
+                {
+                    PollRecv();
+                }
+
+            }
+
+            Trace.TraceInformation("{0} tcp server stop finish", Desp);
+        }
+
+        /// <summary>
+        /// 鏂版帴鍏ュ鎴风杩炴帴
+        /// </summary>
+        /// <param name="ar"></param>
+        private void DoAcceptCallBack()
+        {
+            for (; ; )
+            {
+                TcpClient client = null;
+
+                try
+                {
+                    if (!tcpSvr.Pending())
+                    {
+                        Thread.Sleep(100);
+                        continue;
+                    }
+                        
+
+                    client = tcpSvr.AcceptTcpClient();
+
+                    // 鎺ユ敹鍙戦�佺紦瀛樺ぇ灏�
+                    client.ReceiveBufferSize = 2048;
+                    client.SendBufferSize = 2048;
+
+                    // 璇诲啓瓒呮椂
+                    client.SendTimeout = 2000;
+                    client.ReceiveTimeout = 200;
+
+                    lock (synObj)
+                    {
+                        clientsMap.Add(client.Client, client);
+
+                        // 閫氱煡瀹㈡埛绔繛鎺ヨ繘鍏�
+                        if (null != ClientOpen)
+                        {
+                            Trace.TraceInformation("DoAcceptCallBack {0} tcp server, accept client{1}", Desp, client.Client.RemoteEndPoint);
+
+                            ClientOpen(client);
+                        }
+                    }
+                }
+                catch (Exception ex)
+                {
+                    client?.Close();
+                    Trace.TraceInformation("DoAcceptCallBack fail, ex:{0},{1} tcp server, accept client{2}", ex.Message,
+                        Desp, client?.Client.RemoteEndPoint.ToString());
+                    return;
+                }
+            }
+        }
+
+        /// <summary>
+        /// 妫�鏌ユ暟鎹帴鏀�
+        /// </summary>
+        private void PollRecv()
+        {
+            var rList = new ArrayList();
+            var eList = new ArrayList();
+
+            foreach(var item in clientsMap)
+            {
+                var socket  = item.Key;
+
+                rList.Add(socket);
+                eList.Add(socket);
+            }
+
+            if (clientsMap.Count == 0)
+            {
+                Thread.Sleep(200);
+                return;
+            }
+
+            try
+            {
+                Thread.Sleep(200);
+                Socket.Select(rList, null, eList, 200);
+
+                // 瀹㈡埛绔紓甯稿垯鍏抽棴
+                foreach(var item in eList)
+                {
+                    Socket  socket = (Socket)item;
+                    TcpClient client;
+
+                    if ( clientsMap.TryGetValue(socket, out client) && null != ClientClose )
+                    {
+                        client.Close();
+
+                        ClientClose(client);
+                    }
+
+                    clientsMap.Remove(socket);
+                }
+
+                // 瀹㈡埛绔槸鍚︽湁鏁版嵁
+                foreach(var item in rList)
+                {
+                    Socket  socket = (Socket)item;
+                    TcpClient client;
+
+                    if ( clientsMap.TryGetValue(socket, out client) && null != ClientRecv )
+                    {
+                        ClientRecv(client);
+                        
+                    }
+                }
+            }
+            catch(Exception ex)
+            {
+                Trace.TraceInformation("CloseAllClient except{0}, {1} tcp server", ex.Message, Desp);
+            }
+        }
+
+        /// <summary>
+        /// 鍏抽棴鎵�鏈夊鎴风杩炴帴
+        /// </summary>
+        private void CloseAllClient()
+        {
+            Trace.TraceInformation("CloseAllClient {0} tcp server, client cnt{0}", Desp, clientsMap.Count);
+
+            foreach(var item in clientsMap)
+            {
+                var client  = item.Value;
+                try
+                {
+                    client.Close();
+
+                    if ( null != ClientClose )
+                    {
+                        ClientClose(client);
+                    }
+                }
+                catch(Exception ex)
+                {
+                    Trace.TraceInformation("CloseAllClient except{0}, {1} tcp server, accept client{2}", ex.Message, Desp, client.Client.RemoteEndPoint);
+                }
+                
+            }
+
+            clientsMap.Clear();
+        }
+    }
+}
diff --git a/Bro.Comn/OEE/OEEToolKit.cs b/Bro.Comn/OEE/OEEToolKit.cs
new file mode 100644
index 0000000..15aaaf3
--- /dev/null
+++ b/Bro.Comn/OEE/OEEToolKit.cs
@@ -0,0 +1,242 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace BroC.Comn.OEE
+{
+    public class OEEToolKit
+    {
+        private DateTime lastClearTime = DateTime.Now;
+
+        private int totalCount = 0;
+
+        private int okCount = 0;
+
+        private int ngCount = 0;
+
+        private double ct = 0;
+
+        private Dictionary<string, int> ngDic = new Dictionary<string, int>();
+
+        private List<DateTime> testEndTimeList = new List<DateTime>();
+
+        public int TotalCount
+        {
+            get => totalCount;
+        }
+
+        public int OKCount
+        {
+            get => okCount;
+        }
+
+        public int NGCount
+        {
+            get => ngCount;
+        }
+
+        public double CT
+        {
+            get => ct;
+            set => ct = value;
+        }
+
+        public double Rate
+        {
+            get
+            {
+                if (totalCount == 0)
+                    return 0;
+                else
+                    return okCount * 1.0 / totalCount;
+            }
+        }
+
+        public int UPHAverage
+        {
+            get
+            {
+                var timeOffset = DateTime.Now - lastClearTime;
+                var averageUPH = timeOffset.TotalSeconds == 0 ? totalCount : totalCount / (timeOffset.TotalSeconds / 3600.0);
+                return Convert.ToInt32(averageUPH);
+            }
+        }
+
+        public int UPHReal
+        {
+            get => testEndTimeList.Count;
+        }
+
+        public OEEToolKit()
+        {
+
+        }
+
+        public void AddNgType(string type)
+        {
+            ngDic.Add(type, 0);
+        }
+
+        public void Update(bool isok)
+        {
+            var time = DateTime.Now;
+
+            testEndTimeList.Add(time);
+
+            int removeCount = 0;
+
+            for (int i = 0; i < testEndTimeList.Count; i++)
+            {
+
+                if (testEndTimeList[i].CompareTo(time.AddHours(-1)) < 0)
+                {
+                    removeCount++;
+                }
+                else
+                {
+                    break;
+                }
+            }
+
+            testEndTimeList.RemoveRange(0, removeCount);
+
+            totalCount++;
+            if (isok)
+                okCount++;
+            else
+                ngCount++;
+
+        }
+
+        public void Update(string ngType)
+        {
+            if (ngType != "" && ngDic.ContainsKey(ngType))
+            {
+                ngDic[ngType]++;
+            }
+        }
+
+        public int GetNgTypeCount(string ngType)
+        {
+            if (!ngDic.Keys.Contains(ngType))
+                return -1;
+
+            return ngDic[ngType];
+        }
+
+        public void Clear()
+        {
+            lastClearTime = DateTime.Now;
+
+            totalCount = 0;
+
+            okCount = 0;
+
+            ngCount = 0;
+
+            var keys = ngDic.Keys.ToArray();
+
+            foreach (var item in keys)
+            {
+                ngDic[item] = 0;
+            }
+
+            testEndTimeList.Clear();
+        }
+
+        public void Record(string fileName,string tag="-", string ct = "-")
+        {
+            FileInfo fileInfo = new FileInfo(fileName);
+
+            if (!fileInfo.Directory.Exists)
+                fileInfo.Directory.Create();
+
+            if (!File.Exists(fileName))
+            {
+                var title = "寮�濮嬫椂闂�,璁板綍鏃堕棿,杩愯鏃堕棿,鏍囩,浜ч噺,鑹巼,OK,NG,";
+
+                foreach (var item in ngDic)
+                {
+                    title += $"{item.Key},";
+                }
+
+                title += "CT,UPH(瀹炴椂),UPH(骞冲潎),";
+
+                File.AppendAllText(fileName, title, Encoding.UTF8);
+                File.AppendAllText(fileName, "\r\n", Encoding.UTF8);
+            }
+
+            var recordTime = DateTime.Now;
+            var timeSpan = recordTime - lastClearTime;
+
+            var content = $"{lastClearTime:yyyy-MM-dd-HH-mm-ss}," +
+                $"{recordTime:yyyy-MM-dd-HH-mm-ss}," +
+                $"{timeSpan.Minutes / 60.0:f2}," +
+                $"{tag}," +
+                $"{TotalCount}," +
+                $"{Rate * 100:f2}," +
+                $"{OKCount}," +
+                $"{NGCount},";
+
+            foreach (var item in ngDic)
+            {
+                content += $"{item.Value},";
+            }
+
+            content += $"{ct},{UPHReal},{UPHAverage}";
+
+            File.AppendAllText(fileName, content, Encoding.UTF8);
+            File.AppendAllText(fileName, "\r\n", Encoding.UTF8);
+
+            Clear();
+        }
+
+        public void RecordNewLine(string fileName)
+        {
+            FileInfo fileInfo = new FileInfo(fileName);
+
+            if (!fileInfo.Directory.Exists)
+                fileInfo.Directory.Create();
+
+            if (!File.Exists(fileName))
+            {
+                var title = "寮�濮嬫椂闂�,璁板綍鏃堕棿,杩愯鏃堕棿,鏍囩,浜ч噺,鑹巼,OK,NG,";
+
+                foreach (var item in ngDic)
+                {
+                    title += $"{item.Key},";
+                }
+
+                title += "CT,UPH(瀹炴椂),UPH(骞冲潎),";
+
+                File.AppendAllText(fileName, title, Encoding.UTF8);
+                File.AppendAllText(fileName, "\r\n", Encoding.UTF8);
+            }
+
+            var content = $"-," +
+                $"-," +
+                $"-," +
+                $"-," +
+                $"-," +
+                $"-," +
+                $"-," +
+                $"-,";
+
+            File.AppendAllText(fileName, content, Encoding.UTF8);
+            File.AppendAllText(fileName, "\r\n", Encoding.UTF8);
+        }
+
+        public void StartAutoRecord()
+        {
+
+        }
+
+        private void AutoRecordThread()
+        {
+
+        }
+
+    }
+}
diff --git a/Bro.Comn/Procedure/IODataBase.cs b/Bro.Comn/Procedure/IODataBase.cs
new file mode 100644
index 0000000..717fb1e
--- /dev/null
+++ b/Bro.Comn/Procedure/IODataBase.cs
@@ -0,0 +1,200 @@
+锘縰sing System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Bro.Common.Procedure
+{
+    /// <summary>
+    /// IO鏁版嵁鐘舵��
+    /// </summary>
+    public enum IODStat
+    {
+        IODSUndo,
+        IODSDoing,
+        IODSDone,
+    }
+
+    /// <summary>
+    /// IO鏁版嵁鍩虹被
+    /// </summary>
+    public class IODataBase
+    {
+        #region 甯搁噺
+
+        // 榛樿鐨勮緭鍏ュ鐞嗗嚱鏁板悕绉�
+        public const string DFT_HANDLE_METHOD_NAME  = "HandleRequest";
+        
+        #endregion
+
+        #region 灞炴��
+
+        // 娑堟伅澶勭悊鑰�
+        public List<object>     Handlers {get;set;}
+
+        public IODStat          Stat { get { return curStat; }}
+
+        // 娑堟伅鎻忚堪
+        public string           Desp { get;set; }
+
+        // 鍒涘缓鏃堕棿
+        public DateTime         CreateTime { get;set; }
+
+        // 澶勭悊寮�濮嬫椂闂�
+        public DateTime         BeginTime { get;set; }
+
+        // 澶勭悊瀹屾垚鏃堕棿
+        public DateTime         EndTime { get;set; }
+
+        // 鐢ㄦ埛鏁版嵁
+        public object           Data { get;set; }
+
+        #endregion 
+
+        #region 鎴愬憳鍙橀噺
+
+        private IODStat       curStat = IODStat.IODSUndo;
+
+
+        #endregion
+
+        #region 缁撴瀯浣�
+
+        public IODataBase()
+        {
+            Handlers    = null;
+            curStat     = IODStat.IODSUndo;
+
+            CreateTime  = DateTime.Now;
+            BeginTime   = DateTime.MinValue;
+            EndTime     = DateTime.MinValue;
+
+            Desp        = this.GetType().ToString();
+            Data        = null;
+        }
+
+        public IODataBase(List<object> handlers, string desp, object userData)
+        {
+            Handlers        = handlers;
+            curStat         = IODStat.IODSUndo;
+
+            CreateTime      = DateTime.Now;
+            BeginTime       = DateTime.MinValue;
+            EndTime         = DateTime.MinValue;
+
+            this.Desp       = desp;
+            this.Data       = userData;
+        }
+
+        #endregion
+
+        #region 鏂规硶
+
+        /// <summary>
+        /// 娲鹃仯鍑芥暟锛屽埄鐢ㄥ弽灏勬満鍒惰嚜鍔ㄦ淳閬g粰杈撳叆澶勭悊鑰�
+        /// 
+        /// 澶勭悊鏂规硶
+        /// 1. 閬嶅巻鏁版嵁澶勭悊鑰�
+        /// 2. 妫�瀵熷鐞嗚�呬腑鏄惁鏈夋寚瀹氬悕绉板嚱鏁�
+        /// 3. 妫�瀵熸鍑芥暟鍙傛暟锛屼笌鏁拌繑鍥炲�兼嵁绫诲瀷涓�鑷�
+        /// 4. 鍒╃敤鍙嶅皠璋冪敤鍑芥暟
+        /// 5. 杩斿洖鍊间负true,鍒欏鐞嗙粨鏉�
+        /// </summary>
+        public void Dispatch()
+        {
+            var paramType = this.GetType();
+            var objParams = new object[1];
+
+            objParams[0] = this;
+
+            if ( null == Handlers )
+            {
+                return;
+            }
+
+            foreach(var handler in Handlers)
+            {
+                if ( null == handler )
+                {
+                    continue;
+                }
+
+                // 鑾峰彇鍙傛暟绫诲瀷
+                var instType     = handler.GetType();
+
+                do
+                {
+                    var instMthInfos = instType.GetMethods( BindingFlags.Instance       |
+                                                            BindingFlags.DeclaredOnly   |
+                                                            BindingFlags.Public         |
+                                                            BindingFlags.NonPublic
+                                                            );
+                    var findsMthInfos = FindMethods(instMthInfos, paramType.Name);
+
+                    foreach (var item in findsMthInfos)
+                    {
+                        var mth = (MethodInfo)item;
+
+                        // 璋冪敤瀵瑰簲瀹炰緥鏂规硶
+                        var ret = (bool)mth.Invoke(handler, objParams);
+                        if (ret)
+                        {
+                            return;
+                        }
+                    }
+
+                    instType = instType.BaseType;
+
+                } while (instType != null);
+
+            }
+
+        }
+
+        private Array FindMethods(MethodInfo[] mthInfos, string paramType)
+        {
+            var findMethods = new ArrayList();
+
+            foreach (var instMth in mthInfos)
+            {
+                var paramInfos = instMth.GetParameters();
+
+                // 闃叉璋冪敤鐖剁被鍑芥暟
+                //if ( instType != instMth.DeclaringType )
+                //{
+                //    continue;
+                //}
+
+                // 鍙傛暟涓暟妫�鏌�
+                if (paramInfos.Length != 1)
+                {
+                    continue;
+                }
+
+                // 鏂规硶蹇呴』鏄寚瀹氬悕绉�
+                if (DFT_HANDLE_METHOD_NAME.CompareTo(instMth.Name) != 0)
+                {
+                    continue;
+                }
+
+                // 鍙傛暟绫诲瀷妫�鏌�
+                if (paramInfos[0].ParameterType.Name.CompareTo(paramType) != 0)
+                {
+                    continue;
+                }
+
+                // 鏂规硶杩斿洖鍊兼瀵�
+                if (instMth.ReturnType.Name.CompareTo(typeof(bool).Name) != 0)
+                {
+                    continue;
+                }
+
+                findMethods.Add(instMth);
+            }
+
+            return findMethods.ToArray();
+        }
+
+        #endregion 
+    }
+}
diff --git a/Bro.Comn/Procedure/ProcedureBase.cs b/Bro.Comn/Procedure/ProcedureBase.cs
new file mode 100644
index 0000000..97de33a
--- /dev/null
+++ b/Bro.Comn/Procedure/ProcedureBase.cs
@@ -0,0 +1,475 @@
+锘縰sing System.Collections.Generic;
+using System.Threading;
+using Bro.Common.FSM;
+using System.Diagnostics;
+
+namespace Bro.Common.Procedure
+{
+    /// <summary>
+    /// 娴佺▼鐘舵��
+    /// </summary>
+    public enum ProcStat
+    {
+        PSInit = 0,         // 鍒濆鍖�
+        PSOpen,             // 鎵撳紑
+        PSRunning,          // 杩愯
+        PSReset,            // 閲嶇疆,
+        PSReseting,         // 閲嶇疆涓�
+        PSPause,            // 鏆傚仠
+        PSClose,            // 鍏抽棴
+        PSFnit              // 閿�姣�
+    }
+
+    /// <summary>
+    /// 澶勭悊娴佺▼鍩虹被
+    /// 
+    /// 璇存槑锛�
+    ///     宸ョ珯锛屽伐浣嶇被閮藉彲缁ф壙姝ょ被
+    /// 瀹氫箟濡備笅鍔ㄤ綔
+    /// 1. 鍒濆鍖�/閿�姣�
+    /// 2. 鎵撳紑/鍏抽棴
+    /// 3. 璇诲啓
+    /// 4. 璁剧疆閫夐」
+    /// 5. 浜嬩欢璁㈤槄/鍙栨秷
+    /// </summary>
+    public abstract class ProcedureBase
+    {
+        #region 浠g悊瀹氫箟
+        // 鐘舵�佸彉鍖栦簨浠�
+        public delegate void StatChange(ProcedureBase procedure, ProcStat srcStat, ProcStat dstStat);
+
+        #endregion
+
+        #region 甯搁噺
+
+        // 绾跨▼榛樿绛夊緟鏃堕棿锛堝崟浣嶏細姣锛�
+        protected const int         DFT_WAIT_INTERVAL = 200;
+
+        #endregion
+
+        #region 浜嬩欢浠g悊
+
+        // 娴佺▼鐘舵�佸彉鍖�
+        public StatChange StatChangeEvent;
+
+        #endregion
+
+        #region 灞炴��
+        // 娴佺▼鎻忚堪
+        public string               Desp { get; set; }
+        // 娴佺▼鐘舵��
+        public ProcStat             Stat{ get { return curStat; } }
+
+        #endregion
+
+        #region 鎴愬憳鍙橀噺
+
+        // 娴佺▼鐘舵�佹満
+        protected SimpleFSM         procFSM         = new SimpleFSM();
+        // 娴佺▼鐘舵��
+        protected ProcStat          curStat         = ProcStat.PSInit;
+        // 鐢熶骇宸ュ簭鍚屾浜嬩欢
+        protected AutoResetEvent    waitEvent       = new AutoResetEvent(false);
+        // 杈撳叆闃熷垪
+        private Queue<IODataBase>   requestQueue    = new Queue<IODataBase>();
+        // 杈撳叆澶勭悊鑰�
+        private List<object>        requestHandlers = new List<object>();
+
+        #endregion
+
+        #region 缁撴瀯浣�
+
+        public ProcedureBase()
+        {
+            this.Desp = this.GetType().Name;
+
+            // 璁剧疆榛樿鐨勭姸鎬佸鐞嗚��
+            AddRequestHandler(this);
+
+            RegistProcFSM();
+        }
+
+        public ProcedureBase(SimpleFSM fsm)
+        {
+            this.Desp    = this.GetType().Name;
+            this.procFSM = fsm;
+
+            // 璁剧疆榛樿鐨勭姸鎬佸鐞嗚��
+            AddRequestHandler(this);
+
+            RegistProcFSM();
+        }
+
+        #endregion
+
+        #region 澶栭儴鎺ュ彛
+
+        /// <summary>
+        /// 鏆傚仠娴佺▼
+        /// </summary>
+        public virtual void Pause()
+        {
+            Trace.TraceInformation("{0} Pause", Desp);
+
+            var req = new ProcStatChangeReq();
+            req.TargetStat = ProcStat.PSPause;
+
+            AddRequest(req);
+
+        }
+
+        /// <summary>
+        /// 閲嶇疆娴佺▼
+        /// </summary>
+        public virtual void Reset()
+        {
+            Trace.TraceInformation("{0} Reset", Desp);
+
+            var req = new ProcStatChangeReq();
+            req.TargetStat = ProcStat.PSReset;
+
+            AddRequest(req);
+        }
+
+        /// <summary>
+        /// 璇锋眰澶勭悊
+        /// </summary>
+        /// <param name="input"></param>
+        public void AddRequest(IODataBase req)
+        {
+            if (null == req)
+            {
+                return;
+            }
+
+            lock (requestQueue)
+            {
+                // 璁剧疆杈撳叆澶勭悊鑰�
+                req.Handlers = this.requestHandlers;
+
+                requestQueue.Enqueue(req);
+            }
+        }
+
+        #endregion
+
+        #region 鍩虹娴佺▼鐘舵�佹満
+
+        /// <summary>
+        /// 娉ㄥ唽鍩烘湰鐘舵�佸鐞�
+        /// </summary>
+        protected virtual bool RegistProcFSM()
+        {
+            int iRet = 0;
+
+            if ( null == procFSM )
+            {
+                return false;
+            }
+
+            iRet += procFSM.Regist((int)ProcStat.PSInit,            DoInit)     ? 0 : 1;
+            iRet += procFSM.Regist((int)ProcStat.PSOpen,            DoOpen)     ? 0 : 1;
+            iRet += procFSM.Regist((int)ProcStat.PSClose,           DoClose)    ? 0 : 1;
+            iRet += procFSM.Regist((int)ProcStat.PSRunning,         DoRunning)  ? 0 : 1;
+            iRet += procFSM.Regist((int)ProcStat.PSReset,           DoReset)    ? 0 : 1;
+            iRet += procFSM.Regist((int)ProcStat.PSReseting,        DoReseting) ? 0 : 1;
+            iRet += procFSM.Regist((int)ProcStat.PSPause,           DoPause)    ? 0 : 1;
+            iRet += procFSM.Regist((int)ProcStat.PSFnit,            DoFnit)     ? 0 : 1;
+            
+            // 璁剧疆鍒濆鐘舵��
+            SetState(ProcStat.PSInit);
+
+            return (iRet == 0);
+        }
+
+        /// <summary>
+        /// 鍒濆鍖�
+        /// </summary>
+       public virtual void DoInit()
+        {
+            Trace.TraceInformation("{0} DoInit", Desp);
+
+            ClearIOData();
+
+            SetState(ProcStat.PSOpen);
+        }
+
+        /// <summary>
+        /// 閿�姣�
+        /// </summary>
+        public virtual void DoFnit()
+        {
+            Trace.TraceInformation("{0} DoFnit", Desp);
+        }
+
+        /// <summary>
+        /// 寮�濮�
+        /// </summary>
+        public virtual void DoOpen()
+        {
+            Trace.TraceInformation("{0} DoOpen", Desp);
+
+            SetState(ProcStat.PSRunning);
+        }
+
+        /// <summary>
+        /// 鍋滄
+        /// </summary>
+        public virtual void DoClose()
+        {
+            Trace.TraceInformation("{0} DoClose", this.GetType().Name);
+
+            SetState(ProcStat.PSFnit);
+        }
+
+        /// <summary>
+        /// 閲嶇疆
+        /// </summary>
+        public virtual void DoReset()
+        {
+            Trace.TraceInformation("{0} DoReset", this.GetType().Name);
+
+            SetState(ProcStat.PSReseting);
+        }
+
+        /// <summary>
+        /// 閲嶇疆涓�
+        /// </summary>
+        public virtual void DoReseting()
+        {
+            Trace.TraceInformation("{0} DoReseting", this.GetType().Name);
+
+            SetState(ProcStat.PSRunning);
+        }
+
+        /// <summary>
+        /// 鏆傚仠
+        /// </summary>
+        public virtual void DoPause()
+        {
+            // 绛夊緟
+            waitEvent.WaitOne(DFT_WAIT_INTERVAL);
+        }
+
+        /// <summary>
+        /// 灏辩华
+        /// </summary>
+        public virtual void DoRunning()
+        {
+            // TODO:娴佺▼灏辩华锛屼富澶勭悊
+
+        }
+
+        #endregion
+
+        #region 璇锋眰澶勭悊
+
+        /// <summary>
+        /// 鐘舵�佽浆鍙樿姹�
+        /// </summary>
+        /// <param name="req"></param>
+        /// <returns></returns>
+        protected bool HandleRequest(ProcStatChangeReq req)
+        {
+            Trace.TraceInformation("{0} HandleRequest cur stat:{1} target:{2}", 
+                                    Desp, GetStatDesp(Stat), GetStatDesp(req.TargetStat));
+
+            if ( req.TargetStat == Stat )
+            {
+                Trace.TraceWarning("{0} HandleRequest fail, already in {1}", Desp, GetStatDesp(req.TargetStat));
+                return true;
+            }
+
+            if ( ProcStat.PSRunning != this.Stat )
+            {
+                Trace.TraceWarning("{0} not running, can't turn to {1}", Desp, GetStatDesp(req.TargetStat));
+                return true;
+            }
+
+            SetState(req.TargetStat);
+
+            return true;
+        }
+
+        #endregion
+
+        #region 鍏朵粬鏂规硶
+
+        /// <summary>
+        /// 杩愯
+        /// </summary>
+        public virtual void Run()
+        {
+            procFSM.Run();
+
+            Routine();
+        }
+
+        /// <summary>
+        /// 娴佺▼姣忔杩愯鐨勪緥绋�
+        /// </summary>
+        protected virtual void Routine()
+        {
+            // 澶勭悊璇锋眰
+            HandleRequests();
+        }
+
+        /// <summary>
+        /// 璁剧疆鐘舵��
+        /// </summary>
+        /// <param name="stat"></param>
+        protected internal void SetState(ProcStat stat)
+        {
+            var srcStat = GetStatDesp(curStat);
+            var dstStat = GetStatDesp(stat);
+            var tempStat = curStat;
+
+            curStat = stat;
+
+            if (null == procFSM)
+            {
+                return;
+            }
+
+            Trace.TraceInformation("{0} stat [{1}]-->[{2}]", Desp, srcStat, dstStat);
+
+            procFSM.SetStat((int)stat);
+
+            // 閫氱煡娴佺▼鐘舵�佸彉鍖�
+            if (null != StatChangeEvent)
+            {
+                StatChangeEvent(this, tempStat, stat);
+            }
+        }
+
+        /// <summary>
+        /// 璁剧疆杈撳叆澶勭悊鑰�
+        /// </summary>
+        /// <param name="handler"></param>
+        public void AddRequestHandler(object handler)
+        {
+            requestHandlers.Add(handler);
+        }
+
+        /// <summary>
+        /// 澶勭悊杈撳叆
+        /// </summary>
+        protected void HandleRequests()
+        {
+            var req = NextReq();
+            if ( null == req )
+            {
+                return;
+            }
+
+            Trace.TraceInformation("[{0}] HandleRequest {1} ", Desp, req.GetType().Name);
+
+            // 杈撳叆澶勭悊娲鹃仯
+            req.Dispatch();
+        }
+
+        /// <summary>
+        /// 鑾峰彇涓嬩釜杈撳叆
+        /// </summary>
+        /// <returns></returns>
+        protected IODataBase NextReq()
+        {
+            return NextData(requestQueue);
+        }
+
+        /// <summary>
+        /// 娣诲姞鏁版嵁
+        /// </summary>
+        /// <param name="data"></param>
+        /// <param name="dataQueue"></param>
+        protected void AddQueue(IODataBase data, Queue<IODataBase> dataQueue)
+        {
+            if ( null == data || null == dataQueue )
+            {
+                return;
+            }
+
+            lock(dataQueue)
+            {
+                dataQueue.Enqueue(data);
+            }
+        }
+        
+        /// <summary>
+        /// 鑾峰彇涓嬩釜鏁版嵁
+        /// </summary>
+        /// <param name="dataQueue"></param>
+        /// <returns></returns>
+        protected IODataBase NextData(Queue<IODataBase> dataQueue)
+        {
+            IODataBase ioData = null;
+
+            lock(dataQueue)
+            {
+                if ( dataQueue.Count > 0 )
+                {
+                    ioData = dataQueue.Dequeue();
+                }
+            }
+
+            return ioData;
+        }
+
+        /// <summary>
+        /// 鎯呯┖杈撳叆鏁版嵁
+        /// </summary>
+        protected void ClearIOData()
+        {
+            lock(requestQueue)
+            {
+                requestQueue.Clear();
+            }
+        }
+
+        /// <summary>
+        /// 鑾峰彇鐘舵�佹弿杩�
+        /// </summary>
+        /// <param name="procStat"></param>
+        /// <returns></returns>
+        private string GetStatDesp(ProcStat procStat)
+        {
+            var desp = "";
+
+            switch (procStat)
+            { 
+                case ProcStat.PSInit:
+                    desp = "PSInit";
+                    break;
+                case ProcStat.PSFnit:
+                    desp = "PSFnit";
+                    break;
+                case ProcStat.PSOpen:
+                    desp = "PSOpen";
+                    break;
+                case ProcStat.PSClose:
+                    desp = "PSClose";
+                    break;
+                case ProcStat.PSRunning:
+                    desp = "PSRunning";
+                    break;
+                case ProcStat.PSPause:
+                    desp = "PSPause";
+                    break;
+                case ProcStat.PSReset:
+                    desp = "PSReset";
+                    break;
+                case ProcStat.PSReseting:
+                    desp = "PSReseting";
+                    break;
+                default:
+                    desp = "Unknow";
+                    break;
+            }
+
+            return desp;
+        }
+
+        #endregion
+    }
+
+}
diff --git a/Bro.Comn/Procedure/ProcedureIO.cs b/Bro.Comn/Procedure/ProcedureIO.cs
new file mode 100644
index 0000000..28168d6
--- /dev/null
+++ b/Bro.Comn/Procedure/ProcedureIO.cs
@@ -0,0 +1,11 @@
+锘縩amespace Bro.Common.Procedure
+{
+    /// <summary>
+    /// 宸ュ簭鐘舵�佸彉鍖栬緭鍏�
+    /// </summary>
+    public class ProcStatChangeReq : IODataBase
+    {
+        // 鐩殑鐘舵��
+        public ProcStat TargetStat { get; set; }
+    }
+}
diff --git a/Bro.Comn/Procedure/UnitBase.cs b/Bro.Comn/Procedure/UnitBase.cs
new file mode 100644
index 0000000..9e91729
--- /dev/null
+++ b/Bro.Comn/Procedure/UnitBase.cs
@@ -0,0 +1,140 @@
+锘縩amespace Bro.Common.Procedure
+{
+    /// <summary>
+    /// 鍩虹鍗曞厓
+    /// </summary>
+    public class UnitBase
+    {
+
+        #region 鏋氫妇
+        /// <summary>
+        /// 鍗曞厓妯″潡鐘舵�佸畾涔�
+        /// </summary>
+        public enum UnitStat
+        {
+            DSUninit = 0,       // 鏈垵濮嬪寲
+            DSInit,             // 宸插垵濮嬪寲
+            DSOpen,             // 宸叉墦寮�
+            DSClose,            // 宸插叧闂�
+            DSExcept            // 寮傚父鐘舵��
+        }
+
+        #endregion
+
+        #region 甯搁噺瀹氫箟
+
+        #endregion
+
+        #region 璁惧鍩烘湰灞炴��
+
+        // 璁惧鎻忚堪
+        public string Desp { get;set; } 
+        // 璁惧鐘舵��
+        public UnitStat Stat { get;set;}
+        // 璁惧鏄惁鍒濆鍖�
+        public bool IsInit {
+            get { return UnitStat.DSInit == this.Stat; }
+        }
+        // 璁惧鏄惁鎵撳紑
+        public bool IsOpen { 
+            get { return UnitStat.DSOpen == this.Stat;}
+        }
+        // 璁惧ID(鍙敤鏉ュ敮涓�鎸囧畾鏈澶�)
+        public int  Id { get;set; }
+        // 璁惧寮傚父鎻忚堪
+        public string  ExceptionDesp { get;set;}
+        // 璁惧鎼哄甫鏁版嵁
+        public object Data { get;set; }
+
+        #endregion
+
+        /// <summary>
+        /// 璁惧鏋勯�犲嚱鏁�
+        /// 
+        /// 浣跨敤浜嗛粯璁ょ殑璁惧id
+        /// </summary>
+        public UnitBase()
+        {
+            // 榛樿鎻忚堪
+            this.Desp = this.GetType().Name;
+            // 鍒濆鐘舵��
+            this.Stat = UnitStat.DSUninit;
+            // 榛樿鍗曞厓ID
+            this.Id  = this.GetHashCode();
+        }
+
+        #region 鍩烘湰鍔ㄤ綔
+        /// <summary>
+        /// 璁惧鍒濆鍖�
+        /// </summary>
+        /// <returns></returns>
+        public virtual bool Init()
+        {
+            Stat = UnitStat.DSInit;
+
+            return true;
+        }
+
+        /// <summary>
+        /// 璁惧閿�姣�
+        /// </summary>
+        public virtual void Fnit()
+        {
+            Stat = UnitStat.DSUninit;
+        }
+
+        /// <summary>
+        /// 璁惧鎵撳紑
+        /// </summary>
+        /// <returns></returns>
+        public virtual bool Open()
+        {
+            Stat = UnitStat.DSOpen;
+
+            return true;
+        }
+
+        /// <summary>
+        /// 璁惧鍏抽棴
+        /// </summary>
+        public virtual void Close()
+        {
+            Stat = UnitStat.DSClose;
+        }
+
+        /// <summary>
+        /// 鎵撳紑鍓嶅姩浣�
+        /// </summary>
+        public virtual void OnBeforeOpen()
+        { 
+        
+        }
+
+        /// <summary>
+        /// 鎵撳紑鍚庡姩浣�
+        /// </summary>
+        public virtual void OnAfterOpen()
+        { 
+        
+        }
+
+        /// <summary>
+        /// 鍏抽棴鍓嶅姩浣�
+        /// </summary>
+        public virtual void OnBeforeClose()
+        { 
+        
+        }
+
+        /// <summary>
+        /// 鍏抽棴鍚庡姩浣�
+        /// </summary>
+        public virtual void OnAfterClose()
+        { 
+        
+        }
+
+        #endregion
+
+    }
+}
diff --git a/Bro.Comn/Properties/AssemblyInfo.cs b/Bro.Comn/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..bbf56bc
--- /dev/null
+++ b/Bro.Comn/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+锘縰sing System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("BroCComn")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("BroCComn")]
+[assembly: AssemblyCopyright("Copyright 漏 Microsoft 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("deb0c803-888e-42bb-b29c-448e9b6e09f0")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.*")]
+//[assembly: AssemblyVersion("1.0.0.0")]
+//[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Bro.Comn/Properties/Resource.Designer.cs b/Bro.Comn/Properties/Resource.Designer.cs
new file mode 100644
index 0000000..e35bda1
--- /dev/null
+++ b/Bro.Comn/Properties/Resource.Designer.cs
@@ -0,0 +1,85 @@
+锘�//------------------------------------------------------------------------------
+// <auto-generated>
+//     姝や唬鐮佺敱宸ュ叿鐢熸垚銆�
+//     杩愯鏃剁増鏈�:4.0.30319.42000
+//
+//     瀵规鏂囦欢鐨勬洿鏀瑰彲鑳戒細瀵艰嚧涓嶆纭殑琛屼负锛屽苟涓斿鏋�
+//     閲嶆柊鐢熸垚浠g爜锛岃繖浜涙洿鏀瑰皢浼氫涪澶便��
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Broc.Comn.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   涓�涓己绫诲瀷鐨勮祫婧愮被锛岀敤浜庢煡鎵炬湰鍦板寲鐨勫瓧绗︿覆绛夈��
+    /// </summary>
+    // 姝ょ被鏄敱 StronglyTypedResourceBuilder
+    // 绫婚�氳繃绫讳技浜� ResGen 鎴� Visual Studio 鐨勫伐鍏疯嚜鍔ㄧ敓鎴愮殑銆�
+    // 鑻ヨ娣诲姞鎴栫Щ闄ゆ垚鍛橈紝璇风紪杈� .ResX 鏂囦欢锛岀劧鍚庨噸鏂拌繍琛� ResGen
+    // (浠� /str 浣滀负鍛戒护閫夐」)锛屾垨閲嶆柊鐢熸垚 VS 椤圭洰銆�
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resource {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resource() {
+        }
+        
+        /// <summary>
+        ///   杩斿洖姝ょ被浣跨敤鐨勭紦瀛樼殑 ResourceManager 瀹炰緥銆�
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Broc.Comn.Properties.Resource", typeof(Resource).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   閲嶅啓褰撳墠绾跨▼鐨� CurrentUICulture 灞炴��
+        ///   閲嶅啓褰撳墠绾跨▼鐨� CurrentUICulture 灞炴�с��
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// <summary>
+        ///   鏌ユ壘绫讳技 &lt;?xml version=&quot;1.0&quot;?&gt;
+        ///&lt;configuration&gt;
+        ///    &lt;configSections&gt;
+        ///        &lt;section name=&quot;log4net&quot; type=&quot;log4net.Config.Log4NetConfigurationSectionHandler, log4net&quot; /&gt;
+        ///    &lt;/configSections&gt;
+        ///    &lt;log4net&gt;
+        ///        &lt;!--Log4net Begin by Bruce  2016.06.14--&gt;	
+        ///		&lt;appender name=&quot;RollingFileAppender&quot; type=&quot;log4net.Appender.RollingFileAppender&quot;&gt;
+        ///			&lt;file value=&quot;.\logs\&quot; /&gt;
+        ///			&lt;appendToFile value=&quot;true&quot; /&gt;
+        ///      &lt;!--log娣囨繄鏆�婢垛晜鏆�--&gt;
+        ///      &lt;maxSizeRollBackups value= &quot;30&quot;/&gt;
+        ///			&lt;rollingStyle value=&quot;Composite&quot; /&gt;
+        ///			&lt;ma [瀛楃涓茬殑鍏朵綑閮ㄥ垎琚埅鏂璢&quot;; 鐨勬湰鍦板寲瀛楃涓层��
+        /// </summary>
+        internal static string BroClog4net {
+            get {
+                return ResourceManager.GetString("BroClog4net", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/Bro.Comn/Properties/Resource.resx b/Bro.Comn/Properties/Resource.resx
new file mode 100644
index 0000000..f1e2d91
--- /dev/null
+++ b/Bro.Comn/Properties/Resource.resx
@@ -0,0 +1,124 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="BroClog4net" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Log\BroClog4net.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;gb2312</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Bro.Comn/PubSub/IPubSubCenter.cs b/Bro.Comn/PubSub/IPubSubCenter.cs
new file mode 100644
index 0000000..775a965
--- /dev/null
+++ b/Bro.Comn/PubSub/IPubSubCenter.cs
@@ -0,0 +1,63 @@
+锘縰sing System;
+
+namespace Bro.Common.PubSub
+{
+    /// <summary>
+    /// 鍙戝竷/璁㈤槄涓績
+    /// </summary>
+    public interface IPubSubCenter
+    {
+        /// <summary>
+        /// 璁㈤槄浜嬩欢
+        /// </summary>
+        /// <param name="tag"></param>
+        /// <param name="method"></param>
+        /// <returns></returns>
+        bool Subscribe(string tag, Func<ISubscriber, object, object, object> method);
+
+        /// <summary>
+        /// 璁㈤槄浜嬩欢
+        /// </summary>
+        /// <param name="tag"></param>
+        /// <param name="subscribe"></param>
+        /// <returns></returns>
+        bool Subscribe(string tag, ISubscriber subscribe);
+
+        /// <summary>
+        /// 鍙戝竷浜嬩欢
+        /// </summary>
+        /// <param name="tag"></param>
+        /// <param name="data"></param>
+        void Publish(string tag, object param1, object param2);
+
+        /// <summary>
+        /// 鑾峰彇鎵�鏈夎闃呰��
+        /// </summary>
+        /// <param name="tag"></param>
+        /// <returns></returns>
+        Subscribers GetSubscribers(string tag);
+
+        /// <summary>
+        /// 鑾峰彇鏌愪釜璁㈤槄鑰�
+        /// </summary>
+        /// <param name="tag"></param>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        ISubscriber GetSubscriber(string tag, string name);
+
+        /// <summary>
+        /// 绉婚櫎鏌愪釜璁㈤槄鑰�
+        /// </summary>
+        /// <param name="tag"></param>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        bool RemoveSubscriber(string tag, string name);
+
+        /// <summary>
+        /// 绉婚櫎鏌愮被鎵�鏈夎闃呰��
+        /// </summary>
+        /// <param name="tag"></param>
+        /// <returns></returns>
+        bool RemoveSubscribers(string tag);
+    }
+}
diff --git a/Bro.Comn/PubSub/IPublisher.cs b/Bro.Comn/PubSub/IPublisher.cs
new file mode 100644
index 0000000..8753814
--- /dev/null
+++ b/Bro.Comn/PubSub/IPublisher.cs
@@ -0,0 +1,15 @@
+锘縩amespace Bro.Common.PubSub
+{
+    /// <summary>
+    /// 鍙戝竷鑰�
+    /// </summary>
+    public interface IPublisher
+    {
+        /// <summary>
+        /// 鍙戝竷鐨勪簨浠�
+        /// </summary>
+        string PublishTag { get; set; }
+
+        object PublishData { get; set; }
+    }
+}
diff --git a/Bro.Comn/PubSub/ISubscriber.cs b/Bro.Comn/PubSub/ISubscriber.cs
new file mode 100644
index 0000000..3d83540
--- /dev/null
+++ b/Bro.Comn/PubSub/ISubscriber.cs
@@ -0,0 +1,19 @@
+锘縰sing System;
+
+namespace Bro.Common.PubSub
+{
+    /// <summary>
+    /// 璁㈤槄鑰�
+    /// </summary>
+    public interface ISubscriber
+    {
+        /// <summary>
+        /// 璁㈤槄鐨勫悕绉�
+        /// </summary>
+        string SubscriberName { get; set; }
+        /// <summary>
+        /// 鍝嶅簲鍙戝竷鐨勬柟娉�
+        /// </summary>
+        Func<ISubscriber, object, object, object> SubMethod { get; set; }
+    }
+}
diff --git a/Bro.Comn/PubSub/PubSubCenter.cs b/Bro.Comn/PubSub/PubSubCenter.cs
new file mode 100644
index 0000000..ecd782d
--- /dev/null
+++ b/Bro.Comn/PubSub/PubSubCenter.cs
@@ -0,0 +1,28 @@
+锘縩amespace Bro.Common.PubSub
+{
+    /// <summary>
+    /// E2E Core浜嬩欢涓績
+    /// </summary>
+    public class PubSubCenter : SimplePubSubCenter
+    {
+        private static PubSubCenter inst = null;
+
+        /// <summary>
+        /// Get Instance
+        /// </summary>
+        /// <returns></returns>
+        public static PubSubCenter GetInstance()
+        {
+            if (null == inst)
+            {
+                inst = new PubSubCenter();
+            }
+
+            return inst;
+        }
+
+        private PubSubCenter()
+        {
+        }
+    }
+}
diff --git a/Bro.Comn/PubSub/SimplePubSubCenter.cs b/Bro.Comn/PubSub/SimplePubSubCenter.cs
new file mode 100644
index 0000000..7db47c0
--- /dev/null
+++ b/Bro.Comn/PubSub/SimplePubSubCenter.cs
@@ -0,0 +1,391 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace Bro.Common.PubSub
+{
+    /// <summary>
+    /// 绠�鍗曞彂甯�/璁㈤槄涓績
+    /// </summary>
+    public class SimplePubSubCenter : IPubSubCenter
+    {
+        /// <summary>
+        /// 璁㈤槄涓婚鍜岃闃呰��
+        /// </summary>
+        private Dictionary<string, Subscribers> subMap = new Dictionary<string, Subscribers>();
+
+        /// <summary>
+        /// 璁㈤槄浜嬩欢
+        /// </summary>
+        /// <param name="tag"></param>
+        /// <param name="method"></param>
+        /// <returns></returns>
+        public bool Subscribe(string tag, Func<ISubscriber, object, object, object> method)
+        {
+            var sub = new SimpleSubscriber();
+
+            // 榛樿浣跨敤hash鍊艰缃悕绉帮紝闃叉閲嶅
+            sub.SubscriberName  = sub.GetHashCode().ToString();
+            sub.SubMethod       = method;
+
+            return Subscribe(tag, sub);
+        }
+
+        /// <summary>
+        /// 璁㈤槄浜嬩欢
+        /// </summary>
+        /// <param name="tag"></param>
+        /// <param name="subscribe"></param>
+        /// <returns></returns>
+        public bool Subscribe(string tag, ISubscriber subscribe)
+        {
+            if ( null == tag || null == subscribe )
+            {
+                return false;
+            }
+        
+            if ( subMap.ContainsKey(tag) )
+            {
+                var subs = subMap[tag];
+
+                return subs.Add(subscribe);
+            }
+            else
+            {
+                var subs = new Subscribers();
+                if ( !subs.Add(subscribe) )
+                {
+                    return false;
+                }
+
+                subMap.Add(tag, subs);
+
+                return true;
+            }
+        }
+
+        /// <summary>
+        /// 鍙戝竷浜嬩欢
+        /// </summary>
+        /// <param name="tag"></param>
+        /// <param name="data"></param>
+        public void Publish(string tag, object param1, object param2)
+        {
+            if ( null == tag )
+            {
+                return;
+            }
+
+            // 鑾峰彇鎵�鏈塼ag璁㈤槄鑰�
+            var subs = GetSubscribers(tag);
+            if ( null == subs )
+            {
+                return;
+            }
+
+            var enmtor = subs.GetEnumerator();
+            if ( null == enmtor )
+            {
+                return;
+            }
+            
+            // 閫氱煡鎵�鏈夎闃呰�呬簨浠�
+            while(enmtor.MoveNext())
+            {
+                var cur = enmtor.Current;
+                if ( null == cur || null == cur.SubMethod)
+                {
+                    continue;
+                }
+
+                cur.SubMethod(cur, param1, param2);
+            }
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎵�鏈夎闃呰��
+        /// </summary>
+        /// <param name="tag"></param>
+        /// <returns></returns>
+        public Subscribers GetSubscribers(string tag)
+        {
+            if ( !subMap.ContainsKey(tag) )
+            {
+                return null;
+            }
+
+            return subMap[tag];
+        }
+
+        /// <summary>
+        /// 鑾峰彇鏌愪釜璁㈤槄鑰�
+        /// </summary>
+        /// <param name="tag"></param>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public ISubscriber GetSubscriber(string tag, string name)
+        {
+            var subs = GetSubscribers(tag);
+            if ( null == subs )
+            {
+                return null;
+            }
+
+            return subs.GetSubscriber(name);
+        }
+
+        /// <summary>
+        /// 绉婚櫎鏌愪釜璁㈤槄鑰�
+        /// </summary>
+        /// <param name="tag"></param>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public bool RemoveSubscriber(string tag, string name)
+        {
+            var subs = GetSubscribers(tag);
+            if ( null == subs )
+            {
+                return false;
+            }
+
+            if ( !subs.Rmv(name) )
+            {
+                return false;
+            }
+
+            if ( subs.GetCount() == 0 )
+            {
+                subMap.Remove(tag);
+            }
+
+            return true;
+        }
+
+        /// <summary>
+        /// 绉婚櫎璁㈤槄
+        /// </summary>
+        /// <param name="tag"></param>
+        /// <param name="method"></param>
+        /// <returns></returns>
+        public bool RemoveSubscriber(string tag, Func<ISubscriber, object, object, object> method)
+        {
+            var subs = GetSubscribers(tag);
+            if ( null == subs )
+            {
+                return false;
+            }
+
+            if ( !subs.Rmv(method) )
+            {
+                return false;
+            }
+
+            if ( subs.GetCount() == 0 )
+            {
+                subMap.Remove(tag);
+            }
+
+            return true;
+        }
+
+        /// <summary>
+        /// 绉婚櫎鏌愮被鎵�鏈夎闃呰��
+        /// </summary>
+        /// <param name="tag"></param>
+        /// <returns></returns>
+        public bool RemoveSubscribers(string tag)
+        {
+            var subs = GetSubscribers(tag);
+            if ( null == subs )
+            {
+                return false;
+            }
+
+            subMap.Remove(tag);
+
+            return true;
+        }
+
+        //IEnumerable<Object> Publish(string tag, object data);
+
+        //IEnumerable<Object> Publish(string tag);
+
+        //IEnumerable<Object> Publish(IPublisher publisher);
+    }
+
+    /// <summary>
+    /// 璁㈤槄鑰呴泦鍚�
+    /// </summary>
+    public class Subscribers
+    {
+        /// <summary>
+        /// 璁㈤槄鑰呴泦鍚�
+        /// </summary>
+        private Dictionary<string, ISubscriber>     subMap = new Dictionary<string,ISubscriber>();
+
+        /// <summary>
+        /// 璁㈤槄鑰呴泦鍚�
+        /// </summary>
+        private List<ISubscriber>  subList = new List<ISubscriber>();
+
+        public Subscribers()
+        {
+        
+        }
+
+        /// <summary>
+        /// 鏂板璁㈤槄鑰�
+        /// </summary>
+        /// <param name="sub"></param>
+        /// <returns></returns>
+        public bool Add(ISubscriber sub)
+        {
+            if ( null == sub || subMap.ContainsKey(sub.SubscriberName) )
+            {
+                return false;
+            }
+
+            subMap.Add(sub.SubscriberName, sub);
+            subList.Add(sub);
+
+            return true;
+        }
+
+        /// <summary>
+        /// 绉婚櫎璁㈤槄鑰�
+        /// </summary>
+        /// <param name="sub"></param>
+        /// <returns></returns>
+        public bool Rmv(ISubscriber sub)
+        {
+            if ( null == sub || !subMap.ContainsKey(sub.SubscriberName) )
+            {
+                return false;
+            }
+
+            subMap.Remove(sub.SubscriberName);
+            subList.Remove(sub);
+
+            return true;
+        }
+
+        /// <summary>
+        /// 绉婚櫎璁㈤槄鑰�
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public bool Rmv(string name)
+        {
+            if ( !subMap.ContainsKey(name) )
+            {
+                return false;
+            }
+
+            var sub = subMap[name];
+
+            subMap.Remove(name);
+            subList.Remove(sub);
+
+            return true;
+        }
+
+        /// <summary>
+        /// 绉婚櫎璁㈤槄鑰�
+        /// </summary>
+        /// <param name="method"></param>
+        /// <returns></returns>
+        public bool Rmv(Func<ISubscriber, object, object, object> method)
+        {
+            var names   = new List<string>();
+
+            try
+            {
+                foreach(var item in subMap)
+                {
+                    if ( null == item.Value )
+                    {
+                        continue;
+                    }
+
+                    // 鑻ユ槸鐩稿悓鍑芥暟锛屽垯绉婚櫎
+                    if ( item.Value.SubMethod == method )
+                    {
+                        names.Add(item.Key);
+                    }
+                }
+
+                for(int i = 0; i < names.Count; i++)
+                {
+                    subMap.Remove(names[i]);
+                }
+
+                names.Clear();
+
+                return true;
+            }
+            catch(Exception ex)
+            {
+                Trace.TraceError("Remove subscriber fail,ex:{0}", ex);
+            }
+
+            return false;
+        }
+
+        /// <summary>
+        /// 妫�瀵熻闃呰�呮槸鍚﹀瓨鍦�
+        /// </summary>
+        /// <param name="sub"></param>
+        /// <returns></returns>
+        public bool Contains(ISubscriber sub)
+        {
+            if ( null == sub || !subMap.ContainsKey(sub.SubscriberName) )
+            {
+                return false;
+            }
+
+            return true;
+        }
+
+        /// <summary>
+        /// 鑾峰彇璁㈤槄鑰�
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public ISubscriber GetSubscriber(string name)
+        {
+            if ( !subMap.ContainsKey(name) )
+            {
+                return null;
+            }
+
+            return subMap[name];
+        }
+
+        /// <summary>
+        /// 娓呴櫎鎵�鏈夎闃呰��
+        /// </summary>
+        public void Clear()
+        {
+            subMap.Clear();
+            subList.Clear();
+        }
+
+        /// <summary>
+        /// 鑾峰彇璁㈤槄鑰呮灇涓�
+        /// </summary>
+        /// <returns></returns>
+        public IEnumerator<ISubscriber> GetEnumerator()
+        {
+            return subList.GetEnumerator();
+        }
+
+        /// <summary>
+        /// 鑾峰彇璁㈤槄鑰呮暟閲�
+        /// </summary>
+        /// <returns></returns>
+        public int GetCount()
+        {
+            return subMap.Count;
+        }
+    }
+}
diff --git a/Bro.Comn/PubSub/SimpleSubscriber.cs b/Bro.Comn/PubSub/SimpleSubscriber.cs
new file mode 100644
index 0000000..60662f2
--- /dev/null
+++ b/Bro.Comn/PubSub/SimpleSubscriber.cs
@@ -0,0 +1,19 @@
+锘縰sing System;
+
+namespace Bro.Common.PubSub
+{
+    /// <summary>
+    /// 绠�鍗曡闃呰��
+    /// </summary>
+    public class SimpleSubscriber :  ISubscriber
+    {
+        /// <summary>
+        /// 璁㈤槄鐨勫悕绉�
+        /// </summary>
+        public string SubscriberName { get; set; }
+        /// <summary>
+        /// 鍝嶅簲鍙戝竷鐨勬柟娉�
+        /// </summary>
+        public Func<ISubscriber, object, object, object> SubMethod { get; set; }
+    }
+}
diff --git a/Bro.Comn/Util/ConfigHelper.cs b/Bro.Comn/Util/ConfigHelper.cs
new file mode 100644
index 0000000..ab6a3c0
--- /dev/null
+++ b/Bro.Comn/Util/ConfigHelper.cs
@@ -0,0 +1,110 @@
+锘縰sing System;
+using System.Configuration;
+using System.Diagnostics;
+using System.IO;
+using System.Xml.Serialization;
+
+namespace Bro.Common.Util
+{
+
+    /// <summary>
+    /// 閰嶇疆鏂囦欢甯姪绫�
+    /// </summary>
+    public class ConfigHelper
+    {
+
+        private static object ioLock = new object();
+
+        /// <summary>
+        /// 杞藉叆XML閰嶇疆鏂囦欢
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="filePath"></param>
+        /// <returns></returns>
+        public static T Load<T>(string filePath)
+        {
+            try
+            {
+
+                lock (ioLock)
+                {
+                    if (!File.Exists(filePath))
+                    {
+                        return default(T);
+                    }
+
+                    var fs = new FileStream(filePath, FileMode.Open);
+                    var xs = new XmlSerializer(typeof(T));
+
+                    var config = (T)xs.Deserialize(fs);
+
+                    fs.Close();
+
+                    return config;
+                }
+            }
+            catch(Exception ex)
+            {
+                Trace.TraceError("ConfigHelper load fail, filepath:{0},ex:{1}", filePath, ex);
+            }
+
+            return default(T);
+        }
+
+        /// <summary>
+        /// 淇濆瓨XML閰嶇疆鏂囦欢
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="filePath"></param>
+        /// <param name="config"></param>
+        /// <returns></returns>
+        public static bool Save<T>(string filePath, T config)
+        {
+            try
+            {
+                lock(ioLock)
+                {
+
+                    var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None);
+                    var xs = new XmlSerializer(typeof(T));
+
+                    xs.Serialize(fs, config);
+
+                    fs.Close();
+                }
+
+                return true;
+            }
+            catch(Exception ex)
+            {
+                Trace.TraceError("ConfigHelper Save fail, filepath:{0},ex:{1}", filePath, ex);
+            }
+        
+            return false;
+        }
+
+        /// <summary>
+        /// 淇敼AppSettings涓厤缃�
+        /// </summary>
+        /// <param name="key">key鍊�</param>
+        /// <param name="value">鐩稿簲鍊�</param>
+        public static bool SetConfigValue(string key, string value)
+        {
+            try
+            {
+                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
+                if (config.AppSettings.Settings[key] != null)
+                    config.AppSettings.Settings[key].Value = value;
+                else
+                    config.AppSettings.Settings.Add(key, value);
+                config.Save(ConfigurationSaveMode.Modified);
+                ConfigurationManager.RefreshSection("appSettings");
+                return true;
+            }
+            catch
+            {
+                return false;
+            }
+        }
+    }
+}
diff --git a/Bro.Comn/Util/LoginConfig.cs b/Bro.Comn/Util/LoginConfig.cs
new file mode 100644
index 0000000..30c5b21
--- /dev/null
+++ b/Bro.Comn/Util/LoginConfig.cs
@@ -0,0 +1,39 @@
+锘縰sing System.ComponentModel;
+
+namespace Broc.Comn.Util
+{
+    public class LoginConfig
+	{
+		[Category("鐧诲綍鐢ㄦ埛璁剧疆")]
+		[Description("鐢ㄦ埛鍚�")]
+		public string LoginUserName { get; set; }
+
+		[Category("鐧诲綍鐢ㄦ埛璁剧疆")]
+		[Description("鐢ㄦ埛瀵嗙爜")]
+		public string LoginUserPassword { get; set; }
+
+		[Category("鐧诲綍鐢ㄦ埛璁剧疆")]
+		[Description("鐢ㄦ埛鐧诲綍鐘舵��")]
+		public  int LoginStatus { get; set; }
+
+		public bool CheckLogin(LoginConfig loginConfig)
+		{
+			if (loginConfig.LoginUserName == "鎿嶄綔鍛�" && loginConfig.LoginUserPassword == "1")
+			{
+				loginConfig.LoginStatus = 1;
+				return true;
+			}
+			if (loginConfig.LoginUserName == "绠$悊鍛�" && loginConfig.LoginUserPassword == "2")
+			{
+				loginConfig.LoginStatus = 2;
+				return true;
+			}
+			if (loginConfig.LoginUserName == "宸ョ▼甯�" && loginConfig.LoginUserPassword == "3")
+			{
+				loginConfig.LoginStatus = 3;
+				return true;
+			}
+			return false;
+		}
+	}
+}
diff --git a/Bro.Comn/packages.config b/Bro.Comn/packages.config
new file mode 100644
index 0000000..f651f6c
--- /dev/null
+++ b/Bro.Comn/packages.config
@@ -0,0 +1,4 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="log4net" version="2.0.8" targetFramework="net45" />
+</packages>
\ No newline at end of file
diff --git a/P066.Data.sln b/P066.Data.sln
index 195a719..560507a 100644
--- a/P066.Data.sln
+++ b/P066.Data.sln
@@ -1,20 +1,36 @@
 锘�
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.28307.1259
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30804.86
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "P066.Data", "P066.Data\P066.Data.csproj", "{8B8F7749-8823-48C6-B12A-54979E28C10C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bro.Comn", "Bro.Comn\Bro.Comn.csproj", "{42407C78-FB75-4310-8910-DF515652A012}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
+		Debug|x86 = Debug|x86
 		Release|Any CPU = Release|Any CPU
+		Release|x86 = Release|x86
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 		{8B8F7749-8823-48C6-B12A-54979E28C10C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{8B8F7749-8823-48C6-B12A-54979E28C10C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{8B8F7749-8823-48C6-B12A-54979E28C10C}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{8B8F7749-8823-48C6-B12A-54979E28C10C}.Debug|x86.Build.0 = Debug|Any CPU
 		{8B8F7749-8823-48C6-B12A-54979E28C10C}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{8B8F7749-8823-48C6-B12A-54979E28C10C}.Release|Any CPU.Build.0 = Release|Any CPU
+		{8B8F7749-8823-48C6-B12A-54979E28C10C}.Release|x86.ActiveCfg = Release|Any CPU
+		{8B8F7749-8823-48C6-B12A-54979E28C10C}.Release|x86.Build.0 = Release|Any CPU
+		{42407C78-FB75-4310-8910-DF515652A012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{42407C78-FB75-4310-8910-DF515652A012}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{42407C78-FB75-4310-8910-DF515652A012}.Debug|x86.ActiveCfg = Debug|x86
+		{42407C78-FB75-4310-8910-DF515652A012}.Debug|x86.Build.0 = Debug|x86
+		{42407C78-FB75-4310-8910-DF515652A012}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{42407C78-FB75-4310-8910-DF515652A012}.Release|Any CPU.Build.0 = Release|Any CPU
+		{42407C78-FB75-4310-8910-DF515652A012}.Release|x86.ActiveCfg = Release|x86
+		{42407C78-FB75-4310-8910-DF515652A012}.Release|x86.Build.0 = Release|x86
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/P066.Data/Form1.cs b/P066.Data/Form1.cs
index 307a429..be15bec 100644
--- a/P066.Data/Form1.cs
+++ b/P066.Data/Form1.cs
@@ -8,6 +8,8 @@
 using System.Threading.Tasks;
 using System.Windows.Forms;
 using System.IO;
+using Bro.Common;
+using Bro.Common.Util;
 
 namespace P066.Data
 {
@@ -15,10 +17,16 @@
     {
         DirectoryInfo directoryInfo1;
         DirectoryInfo directoryInfo2;
+        private P066RunParam runparam = new P066RunParam();
 
+        
         public Form1()
         {
             InitializeComponent();
+            //ConfigHelper.Save(@"D:\P066-Data\P066XML\1.xml", runparam);
+            runparam = ConfigHelper.Load<P066RunParam>(@"D:\P066-Data\P066XML\Jin_Mid.xml");
+            
+
         }
 
         private void btnLoadData1_Click(object sender, EventArgs e)
@@ -91,9 +99,7 @@
                     JudgeListSum.AddRange(judgeList);
 
                 }
-                judgeList = GetLocation(judgeList);
-                //缁欓暅澶村尯鍒嗕綅缃強瑙掑害
-                list = GetLocation(list);
+
                 string currPath = "";
                 #region//鍒ゆ柇鏄垵妫�鏂囦欢澶硅繕鏄妫�鏂囦欢澶�
                 if (fileinfos1[i].Name.Contains("鍒濇涓"))
@@ -101,30 +107,45 @@
                     ChuNum++;
                     filenameDir = "鍒濇涓鐧界偣";
                     filename = "鍒濇涓鐧界偣" + ChuNum;
+                    judgeList = GetMidLocation(judgeList);
+                    //缁欓暅澶村尯鍒嗕綅缃強瑙掑害
+                    list = GetMidLocation(list);
                 }
                else if (fileinfos1[i].Name.Contains("澶嶆涓")&& fileinfos1[i].Name.Contains("鐧界偣"))
                 {
                     FuNum=FuNum+1;
                     filenameDir = "澶嶆涓鐧界偣";
                     filename = "澶嶆涓鐧界偣" + FuNum;
+                    judgeList = GetMidLocation(judgeList);
+                    //缁欓暅澶村尯鍒嗕綅缃強瑙掑害
+                    list = GetMidLocation(list);
                 }
                 else if ( fileinfos1[i].Name.Contains("澶嶆涓") &&fileinfos1[i].Name.Contains("鍒櫧"))
                     {
                         GuaNum=GuaNum+1;
                         filenameDir = "澶嶆涓鍒櫧";
                         filename = "澶嶆涓鍒櫧" + GuaNum;
-                    }
+                    judgeList = GetMidLocation(judgeList);
+                    //缁欓暅澶村尯鍒嗕綅缃強瑙掑害
+                    list = GetMidLocation(list);
+                }
                else if (fileinfos1[i].Name.Contains("鍒濇鑳屾澘"))
                 {
                     ChuNum++;
                     filenameDir = "鍒濇鑳屾澘鐧界偣";
                     filename = "鍒濇鑳屾澘鐧界偣" + ChuNum;
+                    judgeList = GetBkLocation(judgeList);
+                    //缁欓暅澶村尯鍒嗕綅缃強瑙掑害
+                    list = GetBkLocation(list);
                 }
                 else if (fileinfos1[i].Name.Contains("澶嶆鑳屾澘") && fileinfos1[i].Name.Contains("鐧界偣"))
                 {
                     FuNum = FuNum + 1;
                     filenameDir = "澶嶆鑳屾澘鐧界偣";
                     filename = "澶嶆鑳屾澘鐧界偣" + FuNum;
+                    judgeList = GetBkLocation(judgeList);
+                    //缁欓暅澶村尯鍒嗕綅缃強瑙掑害
+                    list = GetBkLocation(list);
                 }
 
                 currPath = directoryInfo1.Parent.Parent.FullName;
@@ -543,8 +564,8 @@
             return dataList;
         }
       
-
-        private List<ResultData> GetLocation(List<ResultData> list)
+        //鑾峰彇涓瑙掑害鍜屼綅缃�
+        private List<ResultData> GetMidLocation(List<ResultData> list)
         {
             var group = list.GroupBy(a => a.TimeTip);
             foreach (var item in group)
@@ -561,11 +582,11 @@
                     listLensnumber1[k].angle = lenAngle;
 
                     var distance = GetDistance(1050, 1050, listLensnumber1[k].X, listLensnumber1[k].Y);
-                    if (distance <= 298.022)
+                    if (distance <= runparam.MidLens1R1)
                     {
                         listLensnumber1[k].location = "闀滃ご";
                     }
-                    else if (298.022 < distance && distance <= 521.171)
+                    else if (runparam.MidLens1R1 < distance && distance <= runparam.MidLens1R2)
                     {
                         listLensnumber1[k].location = "鏂滈潰";
                     }
@@ -586,11 +607,11 @@
                     }
                     listLensnumber2[k].angle = lenAngle;
                     var distance = GetDistance(1050, 1050, listLensnumber2[k].X, listLensnumber2[k].Y);
-                    if (distance <= 367.696)
+                    if (distance <= runparam.MidLens2R1)
                     {
                         listLensnumber2[k].location = "闀滃ご";
                     }
-                    else if (367.696 < distance && distance <= 653.911)
+                    else if (runparam.MidLens2R1 < distance && distance <= runparam.MidLens2R2)
                     {
                         listLensnumber2[k].location = "鏂滈潰";
                     }
@@ -610,11 +631,11 @@
                     }
                     listLensnumber3[k].angle = lenAngle;
                     var distance = GetDistance(1050, 1050, listLensnumber3[k].X, listLensnumber3[k].Y);
-                    if (distance <= 339.246)
+                    if (distance <= runparam.MidLens3R1)
                     {
                         listLensnumber3[k].location = "闀滃ご";
                     }
-                    else if (distance < 339.246 && distance <= 520.584)
+                    else if ( runparam.MidLens3R1< distance && distance <= runparam.MidLens3R2)
                     {
                         listLensnumber3[k].location = "鏂滈潰";
                     }
@@ -634,11 +655,11 @@
                     }
                     listLensnumber4[k].angle = lenAngle;
                     var distance = GetDistance(1050, 1050, listLensnumber4[k].X, listLensnumber4[k].Y);
-                    if (distance <= 104.895)
+                    if (distance <= runparam.MidLens4R1)
                     {
                         listLensnumber4[k].location = "闀滃ご";
                     }
-                    else if (104.895 < distance && distance <= 239.48)
+                    else if (runparam.MidLens4R1 < distance && distance <= runparam.MidLens4R2)
                     {
                         listLensnumber4[k].location = "鏂滈潰";
                     }
@@ -652,7 +673,101 @@
             }
             return list;
         }
+        //鑾峰彇鑳屾澘瑙掑害鍜屼綅缃�
+        private List<ResultData> GetBkLocation(List<ResultData> list)
+        {
+            var group = list.GroupBy(a => a.TimeTip);
+            foreach (var item in group)
+            {
+                //璁$畻闀滃ご1缂洪櫡浣嶇疆鍙婅搴�
+                var listLensnumber1 = list.FindAll(a => a.TimeTip == item.Key && a.Lensnumber == 1);
+                for (int k = 0; k < listLensnumber1.Count; k++)
+                {
+                    var lenAngle = GetAngle(listLensnumber1[k].X, listLensnumber1[k].Y);
+                    if (lenAngle < 0)
+                    {
+                        lenAngle = 360 + lenAngle;
+                    }
+                    listLensnumber1[k].angle = lenAngle;
 
+                    var distance = GetDistance(1050, 1050, listLensnumber1[k].X, listLensnumber1[k].Y);
+                    if (distance <= runparam.BkLens1R1)
+                    {
+                        listLensnumber1[k].location = "鍙鍖�";
+                    }
+
+                    else
+                    {
+                        listLensnumber1[k].location = "闈炲彲瑙嗗尯";
+                    }
+
+                }
+                //璁$畻闀滃ご2浣嶇疆鍙婅搴�
+                var listLensnumber2 = list.FindAll(a => a.TimeTip == item.Key && a.Lensnumber == 2);
+                for (int k = 0; k < listLensnumber2.Count; k++)
+                {
+                    var lenAngle = GetAngle(listLensnumber2[k].X, listLensnumber2[k].Y);
+                    if (lenAngle < 0)
+                    {
+                        lenAngle = 360 + lenAngle;
+                    }
+                    listLensnumber2[k].angle = lenAngle;
+                    var distance = GetDistance(1050, 1050, listLensnumber2[k].X, listLensnumber2[k].Y);
+                    if (distance <= runparam.BkLens2R1)
+                    {
+                        listLensnumber2[k].location = "鍙鍖�";
+                    }
+                    else
+                    {
+                        listLensnumber2[k].location = "闈炲彲瑙嗗尯";
+                    }
+                }
+                //璁$畻闀滃ご3浣嶇疆鍙婅搴�
+                var listLensnumber3 = list.FindAll(a => a.TimeTip == item.Key && a.Lensnumber == 3);
+                for (int k = 0; k < listLensnumber3.Count; k++)
+                {
+                    var lenAngle = GetAngle(listLensnumber3[k].X, listLensnumber3[k].Y);
+                    if (lenAngle < 0)
+                    {
+                        lenAngle = 360 + lenAngle;
+                    }
+                    listLensnumber3[k].angle = lenAngle;
+                    var distance = GetDistance(1050, 1050, listLensnumber3[k].X, listLensnumber3[k].Y);
+                    if (distance <= runparam.BkLens3R1)
+                    {
+                        listLensnumber3[k].location = "鍙鍖�";
+                    }
+
+                    else
+                    {
+                        listLensnumber3[k].location = "闈炲彲瑙嗗尯";
+                    }
+                }
+                //璁$畻闀滃ご4浣嶇疆鍙婅搴�
+                var listLensnumber4 = list.FindAll(a => a.TimeTip == item.Key && a.Lensnumber == 4);
+                for (int k = 0; k < listLensnumber4.Count; k++)
+                {
+                    var lenAngle = GetAngle(listLensnumber4[k].X, listLensnumber4[k].Y);
+                    if (lenAngle < 0)
+                    {
+                        lenAngle = 360 + lenAngle;
+                    }
+                    listLensnumber4[k].angle = lenAngle;
+                    var distance = GetDistance(1050, 1050, listLensnumber4[k].X, listLensnumber4[k].Y);
+                    if (distance <= runparam.BkLens4R1)
+                    {
+                        listLensnumber4[k].location = "鍙鍖�";
+                    }
+                    else
+                    {
+                        listLensnumber4[k].location = "闈炲彲瑙嗗尯";
+
+                    }
+                }
+
+            }
+            return list;
+        }
 
         private void WriteJR(List<ResultData> Lens,string item,int LensNumb, string file12)
         {
diff --git a/P066.Data/P066.Data.csproj b/P066.Data/P066.Data.csproj
index bb373e6..cff15a3 100644
--- a/P066.Data/P066.Data.csproj
+++ b/P066.Data/P066.Data.csproj
@@ -52,6 +52,7 @@
     <Compile Include="Form1.Designer.cs">
       <DependentUpon>Form1.cs</DependentUpon>
     </Compile>
+    <Compile Include="P066RunParam.cs" />
     <Compile Include="Program.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <EmbeddedResource Include="Form1.resx">
@@ -79,5 +80,11 @@
   <ItemGroup>
     <None Include="App.config" />
   </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Bro.Comn\Bro.Comn.csproj">
+      <Project>{42407c78-fb75-4310-8910-df515652a012}</Project>
+      <Name>Bro.Comn</Name>
+    </ProjectReference>
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
 </Project>
\ No newline at end of file
diff --git a/P066.Data/P066RunParam.cs b/P066.Data/P066RunParam.cs
new file mode 100644
index 0000000..5cb4ab1
--- /dev/null
+++ b/P066.Data/P066RunParam.cs
@@ -0,0 +1,29 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace P066.Data
+{
+    public class P066RunParam
+    {
+        public double MidLens1R1;
+        public double MidLens1R2;
+        public double MidLens2R1;
+        public double MidLens2R2;
+        public double MidLens3R1;
+        public double MidLens3R2;
+        public double MidLens4R1;
+        public double MidLens4R2;
+
+        public double BkLens1R1;
+        //public double BkLens1R2;
+        public double BkLens2R1;
+        //public double BkLens2R2;
+        public double BkLens3R1;
+        //public double BkLens3R2;
+        public double BkLens4R1;
+        //public double BkLens4R2;
+    }
+}
diff --git a/P066.Data/P066RunPaream.cs b/P066.Data/P066RunPaream.cs
new file mode 100644
index 0000000..f38d7a5
--- /dev/null
+++ b/P066.Data/P066RunPaream.cs
@@ -0,0 +1,23 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace P066.Data
+{
+    class P066RunPaream
+    {
+        public int Lens1R1;
+        public int Lens1R2;
+        public int Lens2R1;
+        public int Lens2R2;
+        public int Lens3R1;
+        public int Lens3R2;
+        public int Lens4R1;
+        public int Lens4R2;
+
+
+
+    }
+}
diff --git "a/P066XML/Jin_Mid - \345\211\257\346\234\254.xml" "b/P066XML/Jin_Mid - \345\211\257\346\234\254.xml"
new file mode 100644
index 0000000..f1015de
--- /dev/null
+++ "b/P066XML/Jin_Mid - \345\211\257\346\234\254.xml"
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<P066RunParam xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <MidLens1R1>298.022</MidLens1R1>
+  <MidLens1R2>521.171</MidLens1R2>
+  <MidLens2R1>367.696</MidLens2R1>
+  <MidLens2R2>653.911</MidLens2R2>
+  <MidLens3R1>339.246</MidLens3R1>
+  <MidLens3R2>520.584</MidLens3R2>
+  <MidLens4R1>104.895</MidLens4R1>
+  <MidLens4R2>239.48</MidLens4R2>
+  <BkLens1R1>0</BkLens1R1>
+  <BkLens2R1>0</BkLens2R1>
+  <BkLens3R1>0</BkLens3R1>
+  <BkLens4R1>0</BkLens4R1>
+</P066RunParam>
\ No newline at end of file
diff --git a/P066XML/Jin_Mid.xml b/P066XML/Jin_Mid.xml
new file mode 100644
index 0000000..90b8ce2
--- /dev/null
+++ b/P066XML/Jin_Mid.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<P066RunParam xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <MidLens1R1>298.022</MidLens1R1>
+  <MidLens1R2>521.171</MidLens1R2>
+  <MidLens2R1>367.696</MidLens2R1>
+  <MidLens2R2>653.911</MidLens2R2>
+  <MidLens3R1>339.246</MidLens3R1>
+  <MidLens3R2>520.584</MidLens3R2>
+  <MidLens4R1>104.895</MidLens4R1>
+  <MidLens4R2>239.48</MidLens4R2>
+  <BkLens1R1>573.196</BkLens1R1>
+  <BkLens2R1>714.58</BkLens2R1>
+  <BkLens3R1>766</BkLens3R1>
+  <BkLens4R1>345</BkLens4R1>
+</P066RunParam>
\ No newline at end of file

--
Gitblit v1.8.0